/* Lutrin — landing page.
 *
 * Two ideas run through this file, and everything else is plumbing.
 *
 * 1. TYPE CARRIES THE TRADE. What you write is set in mono — the eyebrows,
 *    the chores, the source panel. What the engine gives back is set in
 *    Fraunces — every heading, every verdict. The page never mixes the two
 *    voices in one sentence, so the swap is legible before a word is read.
 *
 * 2. COLOUR CARRIES THE ARGUMENT. Every colour here is a token of the
 *    product's own Slate theme, so the page cannot clash with the real slides
 *    it embeds — except one. `--fiddle`, the magenta of an alignment guide, is
 *    deliberately foreign: it marks the manual work Lutrin removes, and it
 *    appears in exactly two places, the hero artefacts and the crossed-out
 *    chores. The only loud colour on the page is the one being taken away.
 */

/* ---------------------------------------------------------------- fonts */
@font-face {
  font-family: "Fraunces";
  src: url("../fonts/Fraunces-400_700.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fraunces";
  src: url("../fonts/Fraunces-400_700-italic.woff2") format("woff2");
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}
/* Declared at its real weight, unlike before: claiming 100–700 on a single
   400 file tells the browser it already has the bold, and <strong> then comes
   out identical to its surroundings. Emphasis on this page is Fraunces, by
   design; this only keeps the fallback honest. */
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBMPlexSans-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------- tokens */
:root {
  --paper: #ffffff;
  --wash: #eef1f5; /* cool, never cream: the deck's canvas, lightened */
  --canvas: #dee2e6; /* the deck's exact canvas grey */
  --line: #ced4da; /* theme border */
  --ink: #212529; /* theme ink */
  --muted: #637381; /* theme muted — AA on white */
  --muted-strong: #525f6d; /* muted, darkened to clear AA on --wash */
  --accent: #1d4ed8; /* the theme's exact accent */
  --accent-deep: #16359a;
  --accent-bright: #5583f7; /* the same blue, lifted for dark ground */
  --night: #0b1322;
  --night-2: #111d33;
  --dust: #93a5c7;
  --line-night: rgba(148, 163, 199, 0.18);
  --fiddle: #ff2d8e; /* NOT a product colour — see the header note */

  --f-display: "Fraunces", Georgia, serif;
  --f-body: "IBM Plex Sans", -apple-system, "Segoe UI", sans-serif;
  --f-mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
  --wrap: 1180px;
  --gutter: clamp(1.25rem, 4vw, 3rem);
}

/* ----------------------------------------------------------------- base */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 1.0625rem;
  line-height: 1.66;
  overflow-x: hidden;
}
/* Images only. An `iframe { max-width: 100% }` here would look harmless and
   quietly break every embedded slide: the deck frames are deliberately WIDER
   than their container (1330 px, scaled down by main.js), and capping them at
   100% makes the deck lay itself out at container width instead — the slide
   comes back shrunk to a third of its box, with the next two slides showing
   underneath. */
img {
  max-width: 100%;
}
a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}
a:hover {
  color: var(--accent-deep);
}
code,
kbd {
  font-family: var(--f-mono);
  font-size: 0.9em;
}
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

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

/* ------------------------------------------------------- embedded slides */
/* ONE geometry, shared by the hero, the source/output pair and the gallery.
   The numbers are not adjustable decoration: at a 1330 px viewport the deck
   lays a slide out as 1280 × 720 at x = 25, which is what main.js divides by
   to scale each frame into its box and what it offsets by. 728 px of height
   is one slide and no more — at 760 the top of the NEXT slide shows through
   under the current one. */
.slidebox {
  position: relative;
  display: block;
  aspect-ratio: 1280 / 720;
  overflow: hidden;
  border-radius: 3px;
  background: var(--canvas);
}
.slidebox iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 1330px;
  height: 728px;
  border: 0;
  transform-origin: 0 0;
  pointer-events: none;
  background: var(--paper);
}

/* --------------------------------------------------------- type systems */
h1,
h2,
h3 {
  font-family: var(--f-display);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.08;
  margin: 0;
  text-wrap: balance;
}
h1 {
  font-size: clamp(2.6rem, 6.4vw, 4.35rem);
  font-variation-settings: "SOFT" 0, "WONK" 1;
}
h1 em {
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
}
h2 {
  font-size: clamp(2rem, 4.2vw, 3rem);
  margin-bottom: 0.6em;
}
h3 {
  font-size: 1.22rem;
  line-height: 1.25;
  margin-bottom: 0.45rem;
}

/* The author's voice: everything typed, labelled or counted. */
.eyebrow {
  font-family: var(--f-mono);
  font-size: 0.775rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1.1rem;
}
.eyebrow-dark {
  color: var(--dust);
}

.lead {
  font-size: 1.14rem;
  color: var(--muted-strong);
  max-width: 62ch;
  margin: 0 0 2.4rem;
}
.lead-dark {
  color: var(--dust);
}
.aside {
  font-size: 0.95rem;
  color: var(--muted-strong);
  max-width: 74ch;
  margin: 2.2rem 0 0;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}
.aside-dark {
  color: var(--dust);
  border-top-color: var(--line-night);
}

/* -------------------------------------------------------------- buttons */
.btn {
  display: inline-block;
  font-family: var(--f-mono);
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 0.78rem 1.4rem;
  border-radius: 3px;
  border: 1px solid transparent;
  text-decoration: none;
  transition: transform 0.12s ease, background-color 0.15s ease, border-color 0.15s ease;
}
.btn:active {
  transform: translateY(1px);
}
.btn-primary {
  background: var(--accent);
  color: #fff;
}
.btn-primary:hover {
  background: var(--accent-deep);
  color: #fff;
}
.btn-ghost {
  border-color: var(--line);
  color: var(--ink);
}
.btn-ghost:hover {
  border-color: var(--ink);
  color: var(--ink);
}
.btn-dark {
  border-color: var(--line-night);
  color: #fff;
}
.btn-dark:hover {
  border-color: var(--dust);
  color: #fff;
}

/* ------------------------------------------------------------------ nav */
.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0.85rem var(--gutter);
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.wordmark {
  font-family: var(--f-display);
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 1.4rem;
  font-family: var(--f-mono);
  font-size: 0.83rem;
}
.nav-links a {
  color: var(--muted-strong);
  text-decoration: none;
}
.nav-links a:hover {
  color: var(--ink);
}
.nav-gh {
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 3px;
}
@media (max-width: 860px) {
  .nav-links a:not(.nav-gh) {
    display: none;
  }
}

/* ----------------------------------------------------------------- hero */
.hero {
  padding: clamp(3rem, 7vw, 6rem) 0 clamp(3.5rem, 7vw, 6rem);
  background: radial-gradient(120% 90% at 88% 8%, rgba(29, 78, 216, 0.07), transparent 60%),
    var(--paper);
}
.hero-inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
.hero-sub {
  font-size: 1.15rem;
  color: var(--muted-strong);
  max-width: 46ch;
  margin: 1.5rem 0 2rem;
}
.hero-sub code {
  color: var(--ink);
}
.cmd {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--night);
  border-radius: 4px;
  padding: 0.7rem 0.7rem 0.7rem 1rem;
  max-width: 30rem;
}
.cmd code {
  flex: 1;
  color: #e6ecf7;
  font-size: 0.88rem;
  overflow-x: auto;
  white-space: nowrap;
}
.copy {
  flex: none;
  font-family: var(--f-mono);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dust);
  background: transparent;
  border: 1px solid var(--line-night);
  border-radius: 3px;
  padding: 0.32rem 0.6rem;
  cursor: pointer;
}
.copy:hover {
  color: #fff;
  border-color: var(--dust);
}
.copy.done {
  color: var(--accent-bright);
  border-color: var(--accent-bright);
}
.hero-meta {
  font-family: var(--f-mono);
  font-size: 0.78rem;
  color: var(--muted);
  margin: 0.85rem 0 2rem;
}
.hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* ---- the signature: a slide wearing the work you will not be doing ---- */
.stage {
  position: relative;
  margin: 0;
}
/* Clips the artefacts to the slide. Guides that carried on past the edge read
   as a rendering fault, not as a design. The shadow lives here rather than on
   the slidebox: `overflow: hidden` clips children, not the element's own. */
.stage-frame {
  position: relative;
  border-radius: 3px;
  overflow: hidden;
  box-shadow: 0 24px 60px -30px rgba(11, 19, 34, 0.5);
}
.stage .slidebox {
  border: 1px solid var(--line);
}
.stage-cap {
  font-family: var(--f-mono);
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--muted);
  margin: 0.9rem 0 0;
}

/* Hidden by default — with no JS, or with reduced motion, the slide is simply
   a slide. hero.js adds .play, and the artefacts appear only to leave. */
.fiddle {
  display: none;
  position: absolute;
  inset: 6%;
  border: 1px dashed var(--fiddle);
  pointer-events: none;
}
.stage.play .fiddle {
  display: block;
  animation: frame-out 2.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.guide {
  position: absolute;
  background: var(--fiddle);
  opacity: 0;
}
/* -7% of a box already inset by 6% reaches the slide's own edge, and the
   frame's overflow stops it exactly there. */
.guide-v {
  left: 50%;
  top: -7%;
  bottom: -7%;
  width: 1px;
}
.guide-h {
  top: 50%;
  left: -7%;
  right: -7%;
  height: 1px;
}
/* Inside the selection, the way a live readout floats over the object it
   measures — below it, the 6% margin is too thin to hold a label at hero size
   and the frame would clip it in half. */
.dims {
  position: absolute;
  right: 4px;
  bottom: 4px;
  font-family: var(--f-mono);
  font-size: 0.68rem;
  color: #fff;
  background: var(--fiddle);
  padding: 0.1rem 0.4rem;
  border-radius: 2px;
  opacity: 0;
  white-space: nowrap;
}
.handle {
  position: absolute;
  width: 9px;
  height: 9px;
  margin: -5px 0 0 -5px;
  background: #fff;
  border: 1.5px solid var(--fiddle);
  border-radius: 1px;
  opacity: 0;
}
.h-nw {
  top: 0;
  left: 0;
}
.h-n {
  top: 0;
  left: 50%;
}
.h-ne {
  top: 0;
  left: 100%;
}
.h-w {
  top: 50%;
  left: 0;
}
.h-e {
  top: 50%;
  left: 100%;
}
.h-sw {
  top: 100%;
  left: 0;
}
.h-s {
  top: 100%;
  left: 50%;
}
.h-se {
  top: 100%;
  left: 100%;
}

.stage.play .guide {
  animation: artefact-out 1.95s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.stage.play .dims {
  animation: artefact-out 2.15s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.stage.play .handle {
  animation: handle-out 2.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@keyframes artefact-out {
  0% {
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  62% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
@keyframes handle-out {
  0% {
    opacity: 0;
    transform: scale(0.5);
  }
  8% {
    opacity: 1;
    transform: scale(1);
  }
  68% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(0.3);
  }
}
@keyframes frame-out {
  0% {
    border-color: transparent;
  }
  8% {
    border-color: var(--fiddle);
  }
  66% {
    border-color: var(--fiddle);
  }
  100% {
    border-color: transparent;
  }
}

@media (max-width: 900px) {
  .hero-inner {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero-copy {
    order: 1;
  }
  .stage {
    order: 2;
  }
}

/* ----------------------------------------------------------------- cost */
.cost {
  background: var(--wash);
  border-block: 1px solid var(--line);
  padding: clamp(3.5rem, 8vw, 6.5rem) 0;
}
.chores {
  list-style: none;
  margin: 0 0 2.6rem;
  padding: 0;
  max-width: 46rem;
  display: grid;
  gap: 0.1rem;
}
.chores li {
  font-family: var(--f-mono);
  font-size: clamp(0.92rem, 2.1vw, 1.06rem);
  color: var(--muted-strong);
  padding: 0.62rem 0;
  position: relative;
  width: fit-content;
  max-width: 100%;
}
/* Struck through in the foreign magenta: the line is the product's answer to
   the item, drawn on the item itself. */
.chores li::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1.5px;
  background: var(--fiddle);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.chores.in li::after {
  transform: scaleX(1);
}
/* Narrow screens wrap a chore onto two lines, and one drawn rule then sits
   BETWEEN them, striking nothing. Below this width the strike is handed to
   text-decoration, which follows every line — the animation is what is given
   up, and it is the cheaper half. */
@media (max-width: 680px) {
  .chores li::after {
    display: none;
  }
  .chores li {
    text-decoration: line-through;
    text-decoration-color: var(--fiddle);
    text-decoration-thickness: 1.5px;
  }
}
.chores.in li:nth-child(2)::after {
  transition-delay: 0.09s;
}
.chores.in li:nth-child(3)::after {
  transition-delay: 0.18s;
}
.chores.in li:nth-child(4)::after {
  transition-delay: 0.27s;
}
.chores.in li:nth-child(5)::after {
  transition-delay: 0.36s;
}

.verdict {
  font-family: var(--f-display);
  font-size: clamp(1.2rem, 2.7vw, 1.62rem);
  line-height: 1.4;
  color: var(--ink);
  max-width: 40ch;
  margin: 0;
  text-wrap: pretty;
}

/* ----------------------------------------------------- file: source→slide */
.file {
  padding: clamp(3.5rem, 8vw, 6.5rem) 0;
}
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1.1rem;
}
.tab {
  font-family: var(--f-mono);
  font-size: 0.82rem;
  color: var(--muted-strong);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 0.42rem 0.85rem;
  cursor: pointer;
}
.tab:hover {
  color: var(--ink);
  border-color: var(--muted);
}
.tab.is-active {
  color: #fff;
  background: var(--ink);
  border-color: var(--ink);
}
.pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.14fr);
  gap: clamp(1.25rem, 3vw, 2.25rem);
  align-items: start;
}
.editor {
  background: var(--night);
  border-radius: 4px;
  overflow: hidden;
}
.editor-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--line-night);
}
.editor-bar span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line-night);
}
.editor-bar em {
  font-family: var(--f-mono);
  font-size: 0.74rem;
  font-style: normal;
  color: var(--dust);
  margin-left: 0.5rem;
}
.src {
  margin: 0;
  padding: 1.15rem 1.25rem 1.5rem;
  font-family: var(--f-mono);
  font-size: 0.83rem;
  line-height: 1.75;
  color: #d7e0ef;
  overflow-x: auto;
}
.src .k {
  color: #9fc0ff;
}
.src .d {
  color: #7f93b5;
}
.src .up {
  color: #6fd3a8;
}

.compiled .slidebox {
  border: 1px solid var(--line);
  box-shadow: 0 18px 44px -28px rgba(11, 19, 34, 0.45);
}
.pair-caption {
  font-size: 0.93rem;
  color: var(--muted-strong);
  margin: 1rem 0 0;
}
@media (max-width: 860px) {
  .pair {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --------------------------------------------------------------- slides */
.slides {
  background: var(--night);
  color: #fff;
  padding: clamp(3.5rem, 8vw, 6.5rem) 0 clamp(3rem, 6vw, 5rem);
  overflow: hidden;
}
.slides h2 {
  color: #fff;
}
.cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.9rem, 2vw, 1.6rem);
  max-width: var(--wrap);
  /* Clears the parallax, which is not decoration here but a measurement: the
     columns drift up to 56 px around their resting position (main.js caps it
     there), and at 2.5rem the topmost card rode up over the last line of the
     lead. The gap has to be bigger than the drift. */
  margin: clamp(4.5rem, 7vw, 6rem) auto 0;
  padding-inline: var(--gutter);
  align-items: start;
}
.col {
  display: grid;
  gap: clamp(0.9rem, 2vw, 1.6rem);
  will-change: transform;
}
.card {
  display: block;
  text-decoration: none;
  color: inherit;
}
.card .slidebox {
  border: 1px solid var(--line-night);
  transition: border-color 0.18s ease, transform 0.18s ease;
}
.card:hover .slidebox {
  border-color: var(--accent-bright);
  transform: translateY(-3px);
}
.card-label {
  display: block;
  font-family: var(--f-mono);
  font-size: 0.74rem;
  line-height: 1.5;
  color: var(--dust);
  margin-top: 0.6rem;
}
.card:hover .card-label {
  color: #fff;
}
.deck-ctas {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-top: clamp(2rem, 4vw, 3rem);
}
.deck-ctas .aside {
  flex-basis: 100%;
}
.slides kbd {
  border: 1px solid var(--line-night);
  border-radius: 3px;
  padding: 0.05em 0.35em;
  color: #fff;
}
@media (max-width: 900px) {
  .cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .col {
    transform: none !important;
  }
}
@media (max-width: 560px) {
  .cols {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------------------------------------------------------------- where */
.where {
  padding: clamp(3.5rem, 8vw, 6.5rem) 0;
}
/* Two widths of the same row of cards: four for the diagnostics quartet on the
   kit-editor page, three for the doors. The count is spelled in the class
   rather than left to auto-fit because a row that reflows on its own also
   reflows the eyebrow that counts it ("three doors"). */
.grid4,
.grid3 {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.5rem;
  margin-top: 2.5rem;
}
.grid3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.panel {
  padding-top: 1.1rem;
  border-top: 2px solid var(--ink);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.panel.in {
  opacity: 1;
  transform: none;
}
.panel p {
  font-size: 0.96rem;
  color: var(--muted-strong);
  margin: 0;
}
.panel:nth-child(2) {
  transition-delay: 0.06s;
}
.panel:nth-child(3) {
  transition-delay: 0.12s;
}
.panel:nth-child(4) {
  transition-delay: 0.18s;
}
@media (max-width: 880px) {
  .grid4,
  .grid3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 520px) {
  .grid4,
  .grid3 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --------------------------------------------------------------- pricing */
/* Sits between two sections that carry no background of their own: the rule is
   what keeps "three doors" and "the price" from reading as one long block. The
   tier cards reuse .grid3/.panel, and the buttons .refuse-ctas — a price list
   is not a reason to invent a third card shape. */
.pricing {
  border-top: 1px solid var(--line);
  padding: clamp(3.5rem, 8vw, 6.5rem) 0;
}
.pricing .aside {
  margin-bottom: 2.6rem;
}
/* The figure carries the tier; the unit is deliberately small and never a
   per-person rate — "$449 for ten" reads as a budget, "$45 each" reopens the
   negotiation one person at a time. */
.price {
  font-size: clamp(1.9rem, 3.2vw, 2.4rem);
  font-weight: 700;
  line-height: 1.1;
  margin: 0.6rem 0 0.8rem;
}
.price span {
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--muted-strong);
  white-space: nowrap;
}
/* One tier is the recommendation, not three equal options. It is SOLO, and
   deliberately not the most expensive one the page can plausibly push: a first
   visit that lands on a $449 button abandons the cart, and the Solo customer
   who comes back for a team in six months is worth more than that cart was. */
.panel-featured {
  border-top-color: var(--accent);
}
/* Sits ABOVE the tier name — the recommendation has to be readable before the
   price is, or it is just decoration on a card already read. */
.tier-flag {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.35rem;
}
.panel-cta {
  margin-top: 1rem;
  font-weight: 500;
}
/* The card that is a conversation still lets whoever is already decided pay by
   card — quieter than the mail link, and never instead of it. */
.cta-second {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--muted-strong);
}
.tier-more {
  margin: 2rem 0 0;
  font-size: 0.95rem;
  color: var(--muted-strong);
}

/* ----------------------------------------------------- the full price list */
/* A five-row table rather than five more cards: the reason to leave the
   landing page is to compare, and comparison is what a table is for. */
.table-scroll {
  overflow-x: auto;
  margin-top: 2.5rem;
  /* the page itself must never scroll sideways — only this box does */
  max-width: 100%;
}
.price-table {
  border-collapse: collapse;
  width: 100%;
  min-width: 40rem;
  font-size: 0.96rem;
}
.price-table caption {
  caption-side: bottom;
  text-align: left;
  padding-top: 0.9rem;
  font-size: 0.85rem;
  color: var(--muted-strong);
}
.price-table th,
.price-table td {
  text-align: left;
  padding: 0.85rem 1rem 0.85rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.price-table thead th {
  font-family: var(--f-mono);
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-strong);
  border-bottom-color: var(--ink);
}
.price-table tbody th {
  font-weight: 600;
  white-space: nowrap;
}
/* Tabular figures so the money column reads as a column and not as five
   unrelated strings — the same reason the engine gives a right-aligned table
   column its tabular numerals. */
.price-table .num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.price-table .is-recommended {
  background: var(--wash);
}
.row-flag {
  display: block;
  font-family: var(--f-mono);
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--accent);
  white-space: normal;
}
/* Visible to a screen reader, to nothing else: the buy column's header has no
   word worth showing, and an empty <th> is a hole in the table's structure. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ----------------------------------------------------------------- proof */
/* Live counters, never a stored number: a figure typed into this page is out
   of date the day after it is typed, and wrong for everyone who reads it
   after that. */
.proof {
  margin-top: 3rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
}
.proof-lead {
  font-family: var(--f-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted-strong);
  margin: 0 0 0.9rem;
}
.proof-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin: 0;
}
/* A badge that fails to load (shields.io down, a blocked third party) must
   cost the row its image and nothing else — hence a fixed height and no
   layout that depends on the width arriving. */
.proof-badges img {
  height: 22px;
  display: block;
}

/* ------------------------------------------------------------------- faq */
/* <details> and nothing else: eight answers a buyer needs BEFORE paying must
   not be behind a script that may not have loaded. */
.faq {
  margin-top: 3rem;
  border-top: 1px solid var(--line);
}
.faq-title {
  font-family: var(--f-display);
  font-size: 1.25rem;
  margin: 1.75rem 0 0.5rem;
}
.faq details {
  border-bottom: 1px solid var(--line);
}
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 0.95rem 2rem 0.95rem 0;
  position: relative;
  font-weight: 500;
}
.faq summary::-webkit-details-marker {
  display: none;
}
/* The marker is drawn rather than typed: a glyph would come from whichever
   font resolved, at whichever size, and rotate around whichever origin. */
.faq summary::after {
  content: "";
  position: absolute;
  right: 0.4rem;
  top: 1.35rem;
  width: 0.55rem;
  height: 0.55rem;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(45deg);
  transform-origin: center;
  transition: transform 0.2s ease;
}
.faq details[open] summary::after {
  transform: rotate(-135deg);
  top: 1.6rem;
}
.faq summary:hover {
  color: var(--accent);
}
.faq details p {
  margin: 0 0 1.1rem;
  padding-right: 2rem;
  max-width: 66ch;
  color: var(--muted-strong);
  font-size: 0.96rem;
}

/* ---------------------------------------------------- comparison pages */
/* One template, four pages. The order of the blocks IS the argument: what the
   other tool does better comes first, in its own framed block, before a single
   word about Lutrin. A comparison page that opens by winning is discounted on
   sight; the credibility of everything below is bought here. */
.cmp-hero {
  padding: clamp(3rem, 7vw, 5rem) 0 0;
}
.cmp-hero h1 {
  margin-bottom: 0.6rem;
}
.cmp-verdict {
  font-family: var(--f-display);
  font-size: clamp(1.05rem, 2vw, 1.28rem);
  line-height: 1.5;
  max-width: 62ch;
  color: var(--muted-strong);
}
.cmp-section {
  padding: clamp(2.5rem, 6vw, 4rem) 0 0;
}
/* The concession block. Set on the wash, with the accent rule, because it has
   to look deliberate rather than like a disclaimer someone was forced to add. */
.concede {
  background: var(--wash);
  border-left: 3px solid var(--accent);
  padding: 1.5rem 1.75rem 1.25rem;
  margin-top: 1.75rem;
}
.concede h3 {
  margin: 0 0 0.9rem;
  font-family: var(--f-display);
  font-size: 1.15rem;
}
.concede ul {
  margin: 0;
  padding-left: 1.1rem;
}
.concede li {
  margin-bottom: 0.85rem;
  max-width: 70ch;
}
.concede li:last-child {
  margin-bottom: 0;
}
.cmp-list {
  padding-left: 1.1rem;
  margin-top: 1.5rem;
}
.cmp-list li {
  margin-bottom: 0.85rem;
  max-width: 70ch;
}
/* Same shape as the price table: a comparison is a table, and inventing a
   second table style for it would only make the site look bigger. */
.cmp-table {
  border-collapse: collapse;
  width: 100%;
  min-width: 44rem;
  font-size: 0.92rem;
}
.cmp-table th,
.cmp-table td {
  text-align: left;
  padding: 0.8rem 1rem 0.8rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.cmp-table thead th {
  font-family: var(--f-mono);
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-strong);
  border-bottom-color: var(--ink);
}
.cmp-table tbody th {
  font-weight: 600;
  width: 15rem;
}
.cmp-table td:last-child {
  background: rgba(29, 78, 216, 0.04);
  padding-left: 1rem;
}
/* The try-it-yourself block: commands the reader runs, not a screenshot they
   have to believe. */
.cmp-run {
  margin-top: 1.75rem;
  background: var(--night);
  color: var(--dust);
  padding: 1.5rem 1.75rem;
  overflow-x: auto;
}
.cmp-run h3 {
  color: #fff;
  margin: 0 0 0.75rem;
  font-family: var(--f-display);
  font-size: 1.1rem;
}
.cmp-run p {
  max-width: 68ch;
  font-size: 0.92rem;
}
.cmp-run pre {
  margin: 1rem 0;
  font-family: var(--f-mono);
  font-size: 0.82rem;
  line-height: 1.7;
  color: #cfe0ff;
  white-space: pre;
}
.cmp-run code {
  color: #cfe0ff;
}
/* Every factual claim on these pages was checked against the other project's
   own current documentation, on a stated day. Undated, they rot. */
.cmp-checked {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--muted-strong);
}
.cmp-checked a {
  color: var(--muted-strong);
}
.cmp-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2rem;
  font-family: var(--f-mono);
  font-size: 0.82rem;
}
.cmp-nav a {
  border: 1px solid var(--line);
  padding: 0.4rem 0.8rem;
  text-decoration: none;
}
.cmp-nav a:hover {
  border-color: var(--accent);
}
.cmp-nav a[aria-current="page"] {
  border-color: var(--ink);
  background: var(--ink);
  color: #fff;
}

/* ----------------------------------------------------------- kit gallery */
/* Eight tiles of the SAME slide, so the eye compares brands and nothing else.
   auto-fill rather than a fixed column count: the comparison happens between
   neighbours, and a grid that kept three columns on a phone would shrink each
   slide below the size at which its type can be judged at all. */
.gallery {
  padding: clamp(3.5rem, 8vw, 6.5rem) 0 clamp(2.5rem, 5vw, 4rem);
}
.kit-hint {
  max-width: 62ch;
  margin: -1.2rem 0 2.4rem;
  font-size: 0.95rem;
  color: var(--muted-strong);
}
.kit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
  gap: clamp(1rem, 2vw, 1.7rem);
}
.kit {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 0.75rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--paper);
}
.kit-shot {
  display: block;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 3px;
}
.kit-h {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.15rem 0 0;
}
.kit-name {
  font-family: var(--f-display);
  font-size: 1.1rem;
  line-height: 1.2;
}
.kit-for {
  font-family: var(--f-mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.kit-note {
  margin: 0;
  font-size: 0.92rem;
  color: var(--muted-strong);
}
/* The command IS the card's purpose, so it runs the card's full width — past
   the hero's 30rem cap — and WRAPS rather than scrolling. Everywhere else on
   the site a command fits on one line; a URL does not, and one cut off at
   `https://lutri` reads as a broken card even though the copy button holds
   the whole thing. `margin-top: auto` keeps the commands on a common baseline
   when the notes above them run to different lengths. */
.kit .cmd {
  max-width: none;
  margin-top: auto;
  padding: 0.5rem 0.5rem 0.5rem 0.75rem;
}
.kit .cmd code {
  font-size: 0.74rem;
  white-space: normal;
  overflow-wrap: anywhere;
  overflow-x: visible;
}
.gallery-note {
  background: var(--wash);
  border-top: 1px solid var(--line);
  padding: clamp(3.5rem, 8vw, 6.5rem) 0;
}

/* --------------------------------------------------------------- refuse */
.refuse {
  background: var(--wash);
  border-top: 1px solid var(--line);
  padding: clamp(3.5rem, 8vw, 6.5rem) 0;
}
.refuse .lead:last-of-type {
  margin-bottom: 2.6rem;
}
.refuse-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* --------------------------------------------------------------- footer */
.footer {
  background: var(--night);
  color: var(--dust);
  padding: clamp(3rem, 6vw, 4.5rem) 0 2.5rem;
}
.footer .wordmark {
  color: #fff;
  display: inline-block;
  margin: 0 0 0.5rem;
}
/* Three columns since there is a person to write to: the wordmark, the link
   list, and the address. The link list keeps the widest share — it is the one
   a reader scans — and the address gets a column of its own rather than a line
   in the fine print, where nobody looking for it would find it. */
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 0.9fr);
  gap: 2rem;
}
.footer-contact p {
  margin: 0 0 0.35rem;
}
.footer-contact-h {
  font-family: var(--f-mono);
  font-size: 0.82rem;
  color: #fff;
}
.footer-contact a {
  color: #fff;
}
.footer-contact-note {
  font-size: 0.82rem;
  line-height: 1.5;
  color: #7386a8;
}
.footer-tag {
  font-family: var(--f-display);
  font-size: 1.05rem;
  font-style: italic;
  line-height: 1.5;
  margin: 0;
}
.footer-links {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem 1.5rem;
  align-content: start;
  font-family: var(--f-mono);
  font-size: 0.82rem;
}
.footer-links a {
  color: var(--dust);
  text-decoration: none;
}
.footer-links a:hover {
  color: #fff;
}
.footer-fine {
  margin-top: 2.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line-night);
  font-size: 0.78rem;
  line-height: 1.6;
  color: #7386a8;
}
.footer-fine p {
  margin: 0 0 0.4rem;
}
@media (max-width: 940px) {
  .footer-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}
@media (max-width: 700px) {
  .footer-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ------------------------------------------------------------- no script */
/* The reveals are opt-IN: main.js adds .in when an element scrolls into view.
   With scripting off that class never arrives, and a panel left at opacity 0
   is not a missing animation — it is missing content. */
@media (scripting: none) {
  .panel {
    opacity: 1;
    transform: none;
  }
  .chores li {
    text-decoration: line-through;
    text-decoration-color: var(--fiddle);
    text-decoration-thickness: 1.5px;
  }
}

/* ------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .panel {
    opacity: 1;
    transform: none;
  }
  .col {
    transform: none !important;
  }
}
