/* ==========================================================================
   Clarke — clarkesdirective.com
   v2 "Directive Arc" design system.
   One brand world, two lighting states:
   - Ivory (human, editorial) for /, /about, /work, /systems, /access
   - Dark system register shared by Directive + Transora, accent per product
   Motion is an enhancement layered by assets/motion.js; every layout below
   is complete without JavaScript.
   ========================================================================== */

/* Self-hosted type (latin subsets, variable). Direction A: Fraunces display,
   Schibsted Grotesk body, JetBrains Mono labels. No third-party font hosts. */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/fraunces-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/assets/fonts/schibsted-grotesk-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url("/assets/fonts/jetbrains-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light;
  --bg: #f5f1e8;
  --surface: #fcfaf5;
  --ink: #191713;
  --muted: #57514f;
  --hairline: #e4ddd0;
  --accent: #9a4a2e;
  --button-text: #fcfaf5;
  --dark-bg: #0a0b0d;
  --dark-ink: #e9ecea;
  --display: "Fraunces", Georgia, serif;
  --body: "Schibsted Grotesk", system-ui, sans-serif;
  --mono: "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
  --wide: 76rem;
  --prose: 42rem;
  --section: clamp(5rem, 10vw, 9.5rem);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

.register-dark,
.scene--dark {
  color-scheme: dark;
  --bg: #0a0b0d;
  --surface: #111316;
  --ink: #e9ecea;
  --muted: #8b948f;
  --hairline: #23262b;
  --accent: #86c7a2;
  --button-text: #0a0b0d;
}

.accent-fusion {
  --accent: #5b8cff;
  --button-text: #ffffff;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.65;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

body.menu-open {
  overflow: hidden;
}

::selection {
  background: var(--ink);
  color: var(--bg);
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.24em;
}

a:hover {
  color: var(--accent);
}

button,
input,
select,
textarea {
  font: inherit;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  z-index: 100;
  left: 1rem;
  top: 1rem;
  transform: translateY(-200%);
  background: var(--ink);
  color: var(--bg);
  padding: 0.65rem 0.9rem;
}

.skip-link:focus {
  transform: none;
}

.shell {
  width: min(calc(100% - 3rem), var(--wide));
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid transparent;
  background: transparent;
  transition: background-color 350ms var(--ease-out), border-color 350ms var(--ease-out), backdrop-filter 350ms var(--ease-out);
}

.site-header.is-scrolled {
  border-bottom-color: color-mix(in srgb, var(--hairline), transparent 20%);
  background: color-mix(in srgb, var(--bg), transparent 16%);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

.nav-row {
  min-height: 4.75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}

.wordmark {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 650;
  letter-spacing: -0.04em;
  text-decoration: none;
}

.desktop-nav {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  font-size: 0.88rem;
}

.desktop-nav a {
  text-decoration: none;
}

.desktop-nav a[aria-current="page"] {
  color: var(--accent);
}

.nav-cta {
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 0.55rem 1rem;
  transition: border-color 250ms var(--ease-out), background-color 250ms var(--ease-out), color 250ms var(--ease-out);
}

.nav-cta:hover {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
}

.menu-toggle {
  display: none;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: inherit;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
}

.mobile-menu {
  display: none;
}

/* --------------------------------------------------------------------------
   Type
   -------------------------------------------------------------------------- */

.kicker,
.mono-label {
  margin: 0 0 1rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  line-height: 1.4;
  text-transform: uppercase;
}

.register-dark .kicker,
.scene--dark .kicker {
  color: var(--accent);
}

h1,
h2,
h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 520;
  letter-spacing: -0.04em;
  line-height: 1.02;
  text-wrap: balance;
}

h1 {
  max-width: 12ch;
  font-size: clamp(2.9rem, 6.2vw, 5.4rem);
}

h2 {
  max-width: 18ch;
  font-size: clamp(2.1rem, 4.6vw, 3.7rem);
}

h3 {
  font-size: clamp(1.35rem, 2.5vw, 1.8rem);
}

p {
  margin: 0;
}

p + p {
  margin-top: 1.25rem;
}

.lede {
  max-width: 38rem;
  color: var(--muted);
  font-size: clamp(1.08rem, 1.8vw, 1.3rem);
  line-height: 1.6;
}

/* Split-line mask reveals: motion.js wraps H1 lines in .line > .line-inner.
   The mask has to sit below the baseline or it shears the descenders off
   letters like y and g. Padding opens the clip box, the negative margin
   takes the space back so line spacing is untouched. */
.line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}

.line-inner {
  display: block;
}

/* Scrub statement: motion.js wraps words in .w spans and scrubs opacity */
.statement {
  max-width: 24ch;
  font-family: var(--display);
  font-size: clamp(1.9rem, 4.4vw, 3.4rem);
  font-weight: 520;
  letter-spacing: -0.035em;
  line-height: 1.14;
  text-wrap: balance;
}

html.motion-on .statement .w {
  opacity: 0.16;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.button {
  position: relative;
  display: inline-flex;
  min-height: 3.1rem;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--ink);
  color: var(--button-text);
  cursor: pointer;
  font-weight: 600;
  line-height: 1;
  padding: 0.95rem 1.5rem;
  text-decoration: none;
  /* Transform is deliberately absent: motion.js drives it directly, and a CSS
     transition on the same property fights those updates into a rubbery lag. */
  transition: background-color 250ms var(--ease-out), color 250ms var(--ease-out), border-color 250ms var(--ease-out);
  will-change: transform;
}

.button::after {
  content: "→";
  transition: transform 250ms var(--ease-out);
}

.button:hover {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--button-text);
}

.button:hover::after {
  transform: translateX(4px);
}

.button:disabled {
  cursor: wait;
  opacity: 0.55;
}

.button--plain::after {
  content: none;
}

.register-dark .button,
.scene--dark .button {
  border-color: var(--accent);
  background: var(--accent);
}

.microcopy {
  color: var(--muted);
  font-size: 0.86rem;
}

.quiet-link {
  color: var(--muted);
  text-decoration: none;
}

.quiet-link:hover {
  color: var(--accent);
}

/* --------------------------------------------------------------------------
   Sections + scenes
   -------------------------------------------------------------------------- */

.section {
  padding-block: var(--section);
}

.section + .section {
  border-top: 1px solid var(--hairline);
}

.section-header {
  display: grid;
  gap: 1.4rem;
  margin-bottom: clamp(2.5rem, 6vw, 5rem);
}

.prose {
  max-width: var(--prose);
}

.prose-centered {
  margin-inline: auto;
}

/* Spacing utilities. These exist so no element needs a style attribute:
   the Content-Security-Policy has no 'unsafe-inline' for styles, and an
   inline style attribute would simply be dropped in production. */
.stack-sm { margin-top: 1rem; }
.stack-md { margin-top: 1.5rem; }
.stack-lg { margin-top: 2rem; }
.stack-xl { margin-top: 2.5rem; }

.scene--dark {
  background: var(--bg);
  color: var(--ink);
}

.scene--dark .section + .section {
  border-top-color: var(--hairline);
}

/* Gradient bands carry the light-to-dark descent without JavaScript.
   Stops follow a smoothstep curve rather than a straight ramp, so the band
   leaves the flat colour above and arrives at the flat colour below with zero
   slope. That is what removes the visible seam a linear gradient leaves behind. */
.band {
  position: relative;
  height: clamp(18rem, 46vh, 30rem);
  border: 0;
  isolation: isolate;
}

/* A single frame of fine noise, held at low opacity, breaks up the 8-bit
   stepping that any long gradient shows on wide displays. */
.band::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}

.band--to-dark {
  background: linear-gradient(
    180deg,
    #f5f1e8 0%,
    #eeebe2 10%,
    #ddd9d1 20%,
    #c2bfb9 30%,
    #a2a09b 40%,
    #807e7b 50%,
    #5d5c5a 60%,
    #3d3d3c 70%,
    #222324 80%,
    #111113 90%,
    #0a0b0d 100%
  );
}

.band--to-light {
  background: linear-gradient(
    180deg,
    #0a0b0d 0%,
    #111113 10%,
    #222324 20%,
    #3d3d3c 30%,
    #5d5c5a 40%,
    #807e7b 50%,
    #a2a09b 60%,
    #c2bfb9 70%,
    #ddd9d1 80%,
    #eeebe2 90%,
    #f5f1e8 100%
  );
}

/* Where the browser can interpolate in a perceptual space, let it: the same
   stops read even smoother through the mid-greys. */
@supports (background: linear-gradient(in oklab, red, blue)) {
  .band--to-dark {
    background: linear-gradient(
      180deg in oklab,
      #f5f1e8 0%,
      #eeebe2 10%,
      #ddd9d1 20%,
      #c2bfb9 30%,
      #a2a09b 40%,
      #807e7b 50%,
      #5d5c5a 60%,
      #3d3d3c 70%,
      #222324 80%,
      #111113 90%,
      #0a0b0d 100%
    );
  }

  .band--to-light {
    background: linear-gradient(
      180deg in oklab,
      #0a0b0d 0%,
      #111113 10%,
      #222324 20%,
      #3d3d3c 30%,
      #5d5c5a 40%,
      #807e7b 50%,
      #a2a09b 60%,
      #c2bfb9 70%,
      #ddd9d1 80%,
      #eeebe2 90%,
      #f5f1e8 100%
    );
  }
}

.direct-answer {
  margin-top: 2.5rem;
  padding-block: 1.5rem;
  border-block: 1px solid var(--hairline);
}

.direct-answer p:last-child {
  max-width: var(--prose);
  font-size: 1.02rem;
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(20rem, 0.95fr);
  align-items: center;
  gap: clamp(3rem, 7vw, 6rem);
  padding-block: clamp(3.5rem, 7vw, 6rem) clamp(2.5rem, 5vw, 4rem);
  min-height: calc(88svh - 4.75rem);
}

.hero-copy {
  display: grid;
  justify-items: start;
  gap: 1.3rem;
}

.hero-actions {
  display: grid;
  justify-items: start;
  gap: 0.7rem;
  margin-top: 0.6rem;
}

.signal-wrap {
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 5;
  max-height: 34rem;
  justify-self: end;
  width: 100%;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 70% 20%, #fcfaf5 0%, #f5f1e8 55%, #ece5d6 100%);
}

.signal-wrap canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.signal-wrap figcaption {
  position: absolute;
  left: 1rem;
  bottom: 0.9rem;
  z-index: 2;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Proof bar — sits inside the hero viewport on desktop */
.proof-bar {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) auto;
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: center;
  border-top: 1px solid var(--hairline);
  padding-block: clamp(1.4rem, 3vw, 2.2rem);
}

.proof-quote {
  margin: 0;
}

.proof-quote p {
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.7vw, 1.3rem);
  font-style: italic;
  letter-spacing: -0.01em;
  line-height: 1.45;
  max-width: 46rem;
}

.proof-quote cite {
  display: block;
  margin-top: 0.6rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-style: normal;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.proof-meta {
  display: grid;
  justify-items: start;
  gap: 0.35rem;
  padding-left: clamp(0rem, 2vw, 2rem);
  border-left: 1px solid var(--hairline);
}

.proof-rating {
  font-family: var(--display);
  font-size: clamp(1.7rem, 3vw, 2.4rem);
  font-weight: 560;
  letter-spacing: -0.03em;
  line-height: 1;
}

.proof-rating .star {
  color: var(--accent);
}

.proof-trusted {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Pipeline rail (homepage descent + system pages)
   -------------------------------------------------------------------------- */

.rail-viewport {
  overflow-x: auto;
  padding-bottom: 1.25rem;
  scrollbar-width: thin;
}

html.motion-on .rail-viewport {
  overflow-x: hidden;
}

.rail {
  display: flex;
  gap: 1rem;
  min-width: max-content;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: stage;
}

.stage {
  min-width: 13rem;
  display: grid;
  align-content: space-between;
  gap: 2.6rem;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  background: var(--surface);
  padding: 1.15rem 1.25rem;
  counter-increment: stage;
  transition: border-color 400ms var(--ease-out), background-color 400ms var(--ease-out);
}

.stage::before {
  content: counter(stage, decimal-leading-zero);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
}

.stage-name {
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.stage.is-lit {
  border-color: var(--accent);
}

.stage.is-roadmap {
  border-style: dashed;
}

.stage.is-roadmap .stage-name::after {
  content: " · roadmap";
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0.02em;
}

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  border: 1px solid var(--hairline);
  background: var(--hairline);
  border-radius: 6px;
  overflow: hidden;
}

.card-grid--pair {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.card {
  background: var(--surface);
  padding: clamp(1.5rem, 3vw, 2.4rem);
}

.card h3 + p {
  margin-top: 1rem;
  color: var(--muted);
}

/* --------------------------------------------------------------------------
   Product rows
   -------------------------------------------------------------------------- */

.editorial-rows {
  border-top: 1px solid var(--hairline);
}

.editorial-row {
  position: relative;
  display: grid;
  grid-template-columns: 8rem minmax(0, 1fr) minmax(16rem, 0.6fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
  padding-block: clamp(2.4rem, 5vw, 4.2rem);
  border-bottom: 1px solid var(--hairline);
}

.row-index {
  font-family: var(--display);
  font-size: clamp(2.4rem, 4.5vw, 3.8rem);
  font-weight: 400;
  letter-spacing: -0.04em;
  line-height: 1;
  color: color-mix(in srgb, var(--muted), transparent 45%);
}

.row-copy {
  display: grid;
  gap: 1rem;
}

.row-copy .kicker {
  margin-bottom: 0;
}

.row-copy p {
  color: var(--muted);
  max-width: 34rem;
}

.row-links {
  display: grid;
  justify-items: start;
  align-content: start;
  gap: 1rem;
  font-size: 0.9rem;
}

.row-links a:first-child {
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  padding-bottom: 0.15rem;
}

/* --------------------------------------------------------------------------
   Media slots — upgraded by site.js when generated assets exist
   -------------------------------------------------------------------------- */

.media-slot {
  position: relative;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  background:
    linear-gradient(140deg, color-mix(in srgb, var(--surface), transparent 0%) 0%, color-mix(in srgb, var(--accent), var(--bg) 88%) 100%);
}

.media-slot > img,
.media-slot > video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.media-slot .slot-label {
  position: absolute;
  left: 1rem;
  bottom: 0.9rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.media-slot.is-loaded .slot-label {
  color: color-mix(in srgb, #ffffff, transparent 25%);
  text-shadow: 0 1px 8px rgb(0 0 0 / 45%);
}

/* --------------------------------------------------------------------------
   CTA panel
   -------------------------------------------------------------------------- */

.cta-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(18rem, 0.8fr);
  gap: clamp(2.5rem, 7vw, 7rem);
  background: var(--surface);
  padding: clamp(2rem, 6vw, 5rem);
  border: 1px solid var(--hairline);
  border-radius: 8px;
}

.cta-copy {
  display: grid;
  justify-items: start;
  gap: 1.4rem;
}

/* --------------------------------------------------------------------------
   System-page components
   -------------------------------------------------------------------------- */

.page-hero {
  min-height: 58svh;
  display: grid;
  align-content: center;
  gap: 1.5rem;
  padding-block: clamp(4.5rem, 10vw, 8.5rem);
}

.page-hero .lede {
  max-width: 44rem;
}

/* Split hero — the form sits beside the argument, not a screen below it. */
.split-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(24rem, 0.95fr);
  align-items: start;
  gap: clamp(2.5rem, 6vw, 5rem);
  padding-block: clamp(3rem, 7vw, 6rem) clamp(3rem, 6vw, 5rem);
}

.split-copy {
  display: grid;
  align-content: start;
  gap: 1.4rem;
}

.split-copy .lede {
  max-width: 34rem;
}

.split-notes {
  display: grid;
  gap: 0.85rem;
  margin: 0.4rem 0 0;
  padding: 1.4rem 0 0;
  border-top: 1px solid var(--hairline);
  list-style: none;
  max-width: 32rem;
  color: var(--muted);
  font-size: 0.94rem;
}

.split-notes li {
  padding-left: 1.4rem;
  position: relative;
}

.split-notes li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 0.5rem;
  height: 1px;
  background: var(--accent);
}

.split-form {
  position: sticky;
  top: 6.5rem;
}

@media (max-width: 940px) {
  .split-hero {
    grid-template-columns: 1fr;
    gap: 2.25rem;
  }

  .split-form {
    position: static;
  }
}

.fragment-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  margin-top: 3rem;
}

.fragment-grid span {
  border: 1px solid var(--hairline);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 1rem;
}

.fragment-grid span:nth-child(2n) {
  transform: translateY(1rem) rotate(-0.4deg);
}

.fragment-grid span:nth-child(3n) {
  transform: translateY(-0.4rem) rotate(0.3deg);
}

.architecture {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: node;
}

.architecture li {
  position: relative;
  min-height: 10rem;
  display: grid;
  align-content: start;
  gap: 0.55rem;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  background: var(--surface);
  padding: 1.25rem;
  counter-increment: node;
}

.architecture li::before {
  content: counter(node, decimal-leading-zero);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
}

.architecture li::after {
  content: "";
  position: absolute;
  right: 1rem;
  top: 1rem;
  width: 0.48rem;
  height: 0.48rem;
  border-radius: 50%;
  background: var(--accent);
}

.architecture li.roadmap {
  border-style: dashed;
}

.architecture li.roadmap::after {
  border: 1px dashed var(--muted);
  background: transparent;
}

.node-name {
  font-family: var(--mono);
  font-size: 0.82rem;
  letter-spacing: 0.05em;
}

.node-detail {
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.5;
}

.build-list {
  margin: 0;
}

.build-item {
  display: grid;
  grid-template-columns: minmax(12rem, 0.4fr) minmax(0, 1fr);
  gap: 2rem;
  padding-block: 1.5rem;
  border-bottom: 1px solid var(--hairline);
}

.build-item:first-child {
  border-top: 1px solid var(--hairline);
}

.build-item dt {
  font-weight: 700;
}

.build-item dd {
  margin: 0;
  color: var(--muted);
}

.roadmap-line {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  border: 1px solid var(--hairline);
  background: var(--hairline);
  border-radius: 6px;
  overflow: hidden;
}

.roadmap-step {
  min-height: 9rem;
  display: grid;
  align-content: space-between;
  background: var(--surface);
  padding: 1.5rem;
}

.roadmap-step:nth-child(2) {
  opacity: 0.72;
}

.roadmap-step:nth-child(3) {
  opacity: 0.48;
}

.qualification-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.qualification-panel {
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: clamp(1.5rem, 3vw, 2.25rem);
}

.qualification-panel.is-for {
  border-color: color-mix(in srgb, var(--accent), var(--hairline) 45%);
}

.qualification-panel ul {
  margin: 1.25rem 0 0;
  padding-left: 1.2rem;
  color: var(--muted);
}

.qualification-panel li + li {
  margin-top: 0.85rem;
}

.proof-deferred {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
  border: 1px dashed var(--hairline);
  border-radius: 6px;
  padding: clamp(1.5rem, 4vw, 3rem);
}

.proof-deferred > div {
  display: grid;
  gap: clamp(1.1rem, 2.4vw, 1.6rem);
}

.proof-deferred .deferred-index {
  color: var(--accent);
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
}

/* Module grid (Transora build order) */
.module-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  border: 1px solid var(--hairline);
  background: var(--hairline);
  border-radius: 6px;
  overflow: hidden;
  counter-reset: module;
}

.module {
  display: grid;
  align-content: start;
  gap: 0.8rem;
  background: var(--surface);
  padding: clamp(1.5rem, 3vw, 2.4rem);
  counter-increment: module;
}

.module::before {
  content: "0" counter(module);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
}

.module h3 {
  font-family: var(--mono);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.module p {
  color: var(--muted);
  font-size: 0.95rem;
}

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.form-card {
  max-width: 48rem;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: var(--surface);
  padding: clamp(1.5rem, 5vw, 3.5rem);
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
}

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

.field.is-wide {
  grid-column: 1 / -1;
}

.field label {
  font-size: 0.86rem;
  font-weight: 650;
}

.field input,
.field select,
.field textarea,
.follow-form input {
  width: 100%;
  border: 1px solid var(--hairline);
  border-radius: 4px;
  background: var(--bg);
  color: var(--ink);
  padding: 0.78rem 0.85rem;
  transition: border-color 200ms var(--ease-out);
}

.field input:focus,
.field select:focus,
.field textarea:focus,
.follow-form input:focus {
  border-color: var(--accent);
  outline: none;
}

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

.form-actions {
  display: grid;
  justify-items: start;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.form-status {
  min-height: 1.5em;
  color: var(--muted);
  font-size: 0.85rem;
}

.form-status.is-error {
  color: #b3443a;
}

.form-status.is-success {
  color: #397657;
}

.register-dark .form-status.is-success,
.scene--dark .form-status.is-success {
  color: var(--accent);
}

.faq-list {
  max-width: 50rem;
  border-top: 1px solid var(--hairline);
}

.faq-item {
  padding-block: 1.75rem;
  border-bottom: 1px solid var(--hairline);
}

.faq-item h3 {
  font-family: var(--body);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.35;
}

.faq-item p {
  margin-top: 0.75rem;
  color: var(--muted);
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.site-footer {
  position: relative;
  overflow: hidden;
  padding-block: 4.5rem 2rem;
  border-top: 1px solid var(--hairline);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.15fr 0.7fr 1fr;
  gap: 3rem;
}

.footer-identity {
  display: grid;
  align-content: start;
  gap: 1rem;
}

.footer-identity p,
.follow-copy {
  max-width: 25rem;
  color: var(--muted);
  font-size: 0.88rem;
}

.footer-links {
  display: grid;
  align-content: start;
  justify-items: start;
  gap: 0.55rem;
  font-size: 0.9rem;
}

.follow-block {
  display: grid;
  align-content: start;
  gap: 0.8rem;
}

.follow-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem;
}

.follow-form .button {
  border-radius: 4px;
  border-color: var(--hairline);
  background: transparent;
  color: var(--ink);
}

.follow-form .button:hover {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--button-text);
}

.follow-form .form-status {
  grid-column: 1 / -1;
}

.footer-bottom {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--hairline);
  color: var(--muted);
  font-size: 0.8rem;
}

/* The floor used to be 4rem, which on a phone was larger than the line could
   ever fit: nowrap meant it could not wrap and the floor meant it could not
   shrink, so it was clipped mid-word to "Clarke's Direct". The viewport term
   now governs at every width, and both ends are set from the measured width of
   this exact string against the shell. */
.footer-watermark {
  pointer-events: none;
  user-select: none;
  margin-top: 2.5rem;
  font-family: var(--display);
  font-size: clamp(2.25rem, 11.5vw, 10.5rem);
  font-weight: 560;
  letter-spacing: -0.05em;
  line-height: 0.9;
  white-space: nowrap;
  color: transparent;
  -webkit-text-stroke: 1px color-mix(in srgb, var(--muted), transparent 55%);
}

/* --------------------------------------------------------------------------
   Motion gating — initial states only exist when motion.js confirms support
   -------------------------------------------------------------------------- */

html.motion-on [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
}

html.motion-on .proof-bar[data-reveal] {
  transform: translateY(14px);
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .shell {
    width: min(calc(100% - 2rem), var(--wide));
  }

  .desktop-nav {
    display: none;
  }

  .menu-toggle {
    display: inline-flex;
  }

  .mobile-menu {
    position: fixed;
    inset: 4.75rem 0 0;
    z-index: 38;
    display: grid;
    align-content: start;
    gap: 0.25rem;
    background: var(--bg);
    padding: 2rem 1.5rem;
  }

  .mobile-menu[hidden] {
    display: none;
  }

  .mobile-menu a {
    border-bottom: 1px solid var(--hairline);
    font-family: var(--display);
    font-size: 1.85rem;
    letter-spacing: -0.03em;
    padding: 1rem 0;
    text-decoration: none;
  }

  .mobile-menu .nav-cta {
    margin-top: 1.25rem;
    border: 1px solid var(--hairline);
    border-radius: 999px;
    font-family: var(--body);
    font-size: 1rem;
    text-align: center;
  }

  .hero {
    grid-template-columns: 1fr;
    min-height: auto;
    padding-top: 3rem;
  }

  .signal-wrap {
    aspect-ratio: 16 / 10;
    max-height: none;
    justify-self: stretch;
  }

  .proof-bar {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  .proof-meta {
    border-left: 0;
    border-top: 1px solid var(--hairline);
    padding-left: 0;
    padding-top: 1.1rem;
  }

  .card-grid,
  .architecture {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .editorial-row {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  .cta-panel {
    grid-template-columns: 1fr;
  }

  .footer-grid {
    grid-template-columns: 1fr 1fr;
  }

  .follow-block {
    grid-column: 1 / -1;
  }
}

@media (max-width: 580px) {
  h1 {
    font-size: clamp(2.7rem, 13vw, 4rem);
  }

  .section {
    padding-block: 4.5rem;
  }

  .card-grid,
  .architecture,
  .qualification-grid,
  .roadmap-line,
  .field-grid,
  .footer-grid,
  .module-grid {
    grid-template-columns: 1fr;
  }

  .architecture {
    padding-left: 1.25rem;
    border-left: 1px solid var(--hairline);
  }

  .architecture li {
    min-height: auto;
  }

  .fragment-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .build-item {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }

  .field.is-wide {
    grid-column: auto;
  }

  .footer-grid {
    gap: 2.5rem;
  }

  .follow-block {
    grid-column: auto;
  }

  .follow-form {
    grid-template-columns: 1fr;
  }

  .footer-bottom {
    display: grid;
  }
}

/* --------------------------------------------------------------------------
   v3 · Proof reel (homepage evidence grid, slots upgrade in place)
   -------------------------------------------------------------------------- */

.reel-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.reel-grid .media-slot:first-child {
  grid-column: 1 / -1;
  aspect-ratio: 21 / 9;
}

.reel-grid .media-slot {
  aspect-ratio: 4 / 3;
}


/* --------------------------------------------------------------------------
   v3 · Character swap
   -------------------------------------------------------------------------- */

.button-ghost {
  background: transparent;
  color: inherit;
  border-color: currentColor;
}

.scene--dark .button-ghost,
.register-dark .button-ghost {
  background: transparent;
  border-color: color-mix(in srgb, currentColor, transparent 55%);
  color: inherit;
}

.button-ghost:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--button-text);
}

/* A single centred action closing a section, rather than an orphan left-aligned
   button hanging off the bottom of a grid. */
.section-action {
  display: flex;
  justify-content: center;
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
}

/* Teaser strip: five portraits, staggered, so the row reads as a sequence
   rather than a product grid. */
.swap-strip {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(0.5rem, 1.2vw, 1rem);
  align-items: start;
}

.swap-tile {
  margin: 0;
  overflow: hidden;
  border-radius: 4px;
  background: color-mix(in srgb, currentColor, transparent 92%);
  aspect-ratio: 9 / 16;
}

.swap-tile:nth-child(even) {
  margin-top: clamp(1rem, 4vw, 3.25rem);
}

.swap-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 700ms var(--ease-out), filter 700ms var(--ease-out);
}

.swap-strip:hover .swap-tile img {
  filter: saturate(0.75) brightness(0.78);
}

.swap-tile:hover img {
  filter: none;
  transform: scale(1.03);
}

/* --------------------------------------------------------------------------
   v3 · Character swap · how it works
   -------------------------------------------------------------------------- */

.swap-demo {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.85fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
}

.demo-panel {
  border: 1px solid var(--hairline);
  border-radius: 16px;
  background: var(--surface);
  padding: clamp(1.1rem, 2.4vw, 1.75rem);
  display: grid;
  gap: 1.15rem;
}

.demo-head {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding-bottom: 1.05rem;
  border-bottom: 1px solid var(--hairline);
}

.demo-head p {
  font-family: var(--display);
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  font-weight: 560;
  letter-spacing: -0.03em;
}

.demo-glyph {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent), transparent 84%);
  color: var(--accent);
}

.demo-glyph svg {
  width: 1.15rem;
  height: 1.15rem;
}

.demo-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.4rem;
}

.demo-step {
  display: grid;
  grid-template-columns: 1.6rem minmax(0, 1fr);
  gap: 0.85rem;
  align-items: start;
}

.demo-index {
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
}

.demo-step.is-done .demo-index {
  border-color: color-mix(in srgb, var(--accent), transparent 45%);
  color: var(--accent);
}

.demo-index svg {
  width: 0.8rem;
  height: 0.8rem;
}

.demo-body {
  display: grid;
  gap: 0.7rem;
  min-width: 0;
}

.demo-label {
  font-size: 0.94rem;
  font-weight: 600;
}

.demo-slot {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.85rem;
  padding: 0.7rem;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: color-mix(in srgb, var(--ink), transparent 96%);
}

.demo-thumb {
  display: block;
  width: 2.7rem;
  height: 2.7rem;
  border-radius: 7px;
  overflow: hidden;
}

.demo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.demo-slot-copy {
  display: grid;
  min-width: 0;
}

.demo-slot-title {
  font-size: 0.9rem;
  font-weight: 600;
}

.demo-slot-sub,
.demo-hint {
  color: var(--muted);
  font-size: 0.76rem;
}

.demo-slot-action {
  color: var(--accent);
  font-size: 0.82rem;
}

/* Character step: two small handles, no thumbnails. The picker drives the
   screen beside it; leaving it alone lets the loop drive both. */
.demo-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.demo-option {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  padding: 0.5rem 1rem;
  transition: border-color 260ms var(--ease-out), color 260ms var(--ease-out), background-color 260ms var(--ease-out);
}

.demo-option:hover {
  border-color: color-mix(in srgb, var(--accent), transparent 40%);
  color: var(--ink);
}

.demo-option[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent), transparent 86%);
  color: var(--accent);
}

.demo-defaults {
  float: right;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.06em;
}

.demo-generate {
  display: grid;
  place-items: center;
  min-height: 3rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--button-text);
  font-weight: 600;
  font-size: 0.95rem;
}

/* The screen: a small lit display that wipes from one result to the next. */
.demo-screen {
  margin: 0;
  display: grid;
  gap: 0.85rem;
  justify-items: center;
  justify-self: center;
  width: 100%;
  /* Held near the panel's own height so the pair reads as one composition. */
  max-width: 18.5rem;
}

.demo-glass {
  position: relative;
  width: 100%;
  aspect-ratio: 720 / 1290;
  overflow: hidden;
  border-radius: 14px;
  border: 1px solid color-mix(in srgb, currentColor, transparent 86%);
  background: #0d0f12;
  box-shadow: 0 1.5rem 3.5rem rgba(0, 0, 0, 0.5);
}

.demo-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Hidden frames are clipped to nothing on the left edge; the wipe reveals
     them by opening that clip across the screen. */
  clip-path: inset(0 0 0 100%);
}

.demo-frame.is-live {
  clip-path: inset(0 0 0 0);
  z-index: 1;
}

.demo-frame.is-entering {
  z-index: 2;
  transition: clip-path var(--wipe, 900ms) var(--ease-out);
}

/* The bar that travels with the reveal, so the swap reads as a pass of light
   rather than a cross-fade. */
.demo-wipe {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 3;
  width: 2px;
  opacity: 0;
  background: linear-gradient(180deg, transparent, #ffffff 18%, #ffffff 82%, transparent);
  box-shadow: 0 0 1.5rem 0.35rem color-mix(in srgb, var(--accent), transparent 40%);
  pointer-events: none;
}

.demo-wipe.is-running {
  animation: demoWipeSweep var(--wipe, 900ms) var(--ease-out);
}

@keyframes demoWipeSweep {
  0% { left: 0; opacity: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}

.demo-screen figcaption {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .demo-frame.is-entering {
    transition-duration: 1ms;
  }

  .demo-wipe.is-running {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   v3 · Character swap · the rail
   -------------------------------------------------------------------------- */

.swap-stage {
  --card-w: clamp(10.5rem, 19vw, 16.5rem);
  position: relative;
}

.swap-rail {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-block: clamp(1.75rem, 5vw, 4rem);
  cursor: grab;
}

.swap-rail::-webkit-scrollbar {
  display: none;
}

.swap-rail:focus-visible {
  outline-offset: -4px;
}

.swap-rail.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
  scroll-behavior: auto;
}

.swap-track {
  display: flex;
  align-items: center;
  gap: clamp(0.7rem, 1.5vw, 1.35rem);
  width: max-content;
  padding-inline: max(1.5rem, calc(50% - var(--card-w) / 2));
}

.swap-card {
  position: relative;
  flex: 0 0 var(--card-w);
  width: var(--card-w);
  aspect-ratio: 9 / 16;
  margin: 0;
  border-radius: 10px;
  overflow: hidden;
  scroll-snap-align: center;
  background: color-mix(in srgb, currentColor, transparent 92%);
  /* Depth is written by script every frame, so this must not transition. */
  opacity: var(--o, 1);
  transform: perspective(1500px) rotateY(var(--ry, 0deg)) scale(var(--sc, 1));
  will-change: transform, opacity;
}

.swap-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: var(--dim, 1);
  transform: scale(var(--z, 1));
  transition: opacity 420ms var(--ease-out), transform 620ms var(--ease-out);
}

.swap-card button {
  position: absolute;
  inset: 0;
  width: 100%;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: zoom-in;
}

/* Spotlight: touching the rail settles every frame except the one under the
   pointer. Applied to the image, not the card, so it never fights the scroll
   driven transform above. */
.swap-stage:hover .swap-card img {
  --dim: 0.3;
}

.swap-stage .swap-card:hover img,
.swap-stage .swap-card:focus-within img {
  --dim: 1;
  --z: 1.06;
}

.swap-card:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.swap-nav {
  position: absolute;
  top: 50%;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  margin: 0;
  transform: translateY(-50%);
  border: 1px solid color-mix(in srgb, var(--ink), transparent 72%);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg), transparent 22%);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 250ms var(--ease-out), color 250ms var(--ease-out), opacity 250ms var(--ease-out);
}

.swap-nav svg {
  width: 1.2rem;
  height: 1.2rem;
}

.swap-nav[data-nav="prev"] {
  left: clamp(0.5rem, 2.5vw, 2rem);
}

.swap-nav[data-nav="next"] {
  right: clamp(0.5rem, 2.5vw, 2rem);
}

.swap-nav:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.swap-nav[disabled] {
  opacity: 0.2;
  pointer-events: none;
}

.swap-progress {
  width: min(calc(100% - 3rem), 18rem);
  height: 2px;
  margin: 0 auto;
  background: color-mix(in srgb, var(--ink), transparent 88%);
}

.swap-progress span {
  display: block;
  width: 0;
  height: 100%;
  background: var(--accent);
}

/* --------------------------------------------------------------------------
   v3 · Character swap · viewer
   -------------------------------------------------------------------------- */

.swap-viewer {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
  padding: clamp(4rem, 8vh, 5.5rem) clamp(4.5rem, 11vw, 8rem);
  background: color-mix(in srgb, #0a0b0d, transparent 4%);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 320ms var(--ease-out);
}

/* The product viewer carries no side arrows and holds landscape screens, so it
   can use the width the portrait viewer has to give up. */
.swap-viewer[data-deck-viewer] {
  padding-inline: clamp(1rem, 4vw, 3.5rem);
}

/* Closed state is kept out of the tab order by the `inert` attribute the
   script sets, so the fade can run both ways without a visibility flip. */
.swap-viewer[data-open="true"] {
  opacity: 1;
  pointer-events: auto;
}

/* A bounded row plus a flex frame is what keeps a tall portrait inside the
   viewport instead of running off the bottom of the screen. */
.swap-viewer-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 0;
}

.swap-viewer img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 6px;
  transform: scale(0.98);
  transition: transform 380ms var(--ease-out);
}

.swap-viewer[data-open="true"] img {
  transform: scale(1);
}

.swap-viewer-close,
.swap-viewer-step {
  position: absolute;
  display: grid;
  place-items: center;
  width: 3.4rem;
  height: 3.4rem;
  border: 1px solid rgba(245, 241, 232, 0.32);
  border-radius: 999px;
  background: rgba(10, 11, 13, 0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: #f5f1e8;
  cursor: pointer;
  transition: border-color 250ms var(--ease-out), color 250ms var(--ease-out), background-color 250ms var(--ease-out);
}

.swap-viewer-close svg,
.swap-viewer-step svg {
  width: 1.25rem;
  height: 1.25rem;
}

.swap-viewer-close {
  top: clamp(0.9rem, 3vh, 1.75rem);
  right: clamp(0.9rem, 3vw, 1.75rem);
}

.swap-viewer-step {
  top: 50%;
  transform: translateY(-50%);
}

.swap-viewer-step[data-step="prev"] {
  left: clamp(0.75rem, 3vw, 2.25rem);
}

.swap-viewer-step[data-step="next"] {
  right: clamp(0.75rem, 3vw, 2.25rem);
}

.swap-viewer-close:hover,
.swap-viewer-step:hover {
  border-color: #f5f1e8;
  background: rgba(10, 11, 13, 0.92);
  color: #ffffff;
}

@media (max-width: 900px) {
  .swap-strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .swap-strip > .swap-tile:nth-child(n + 4) {
    display: none;
  }

  .swap-demo {
    grid-template-columns: 1fr;
  }

  .demo-output {
    max-width: 22rem;
    margin-inline: auto;
  }
}

@media (max-width: 640px) {
  .swap-nav {
    width: 2.85rem;
    height: 2.85rem;
  }

  /* On a narrow screen the frame needs the width more than the arrows need
     the edges, so the controls drop below the image. */
  .swap-viewer {
    padding: 4.5rem 1rem 6rem;
  }

  .swap-viewer-step {
    top: auto;
    bottom: 1.25rem;
    transform: none;
  }

  .swap-viewer-step[data-step="prev"] {
    left: calc(50% - 4rem);
  }

  .swap-viewer-step[data-step="next"] {
    right: calc(50% - 4rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  .swap-card {
    transform: none;
    opacity: 1;
  }

  .swap-rail {
    scroll-snap-type: x proximity;
  }
}

/* --------------------------------------------------------------------------
   v3 · Product deck
   A curved carousel of real product screens. Without JavaScript it is a plain
   horizontal scroller; the script upgrades it in place.
   -------------------------------------------------------------------------- */

.deck {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
}

.deck-stage {
  position: relative;
}

.deck-slides {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.deck-slides::-webkit-scrollbar {
  display: none;
}

.deck-slide {
  position: relative;
  flex: 0 0 min(100%, 52rem);
  margin: 0;
  scroll-snap-align: center;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, currentColor, transparent 84%);
  background: #0d0f12;
}

.deck-slide img {
  width: 100%;
  height: auto;
  display: block;
}

.deck-slide button {
  position: absolute;
  inset: 0;
  width: 100%;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}

/* Enhanced: slides stack and curve away from the centre. */
.deck.is-enhanced .deck-stage {
  aspect-ratio: 2.6;
  /* The curve throws the outer screens past the shell. Clipping here keeps
     that bleed inside the section instead of widening the page. */
  overflow: hidden;
}

.deck.is-enhanced .deck-slides {
  display: block;
  position: absolute;
  inset: 0;
  overflow: visible;
  scroll-snap-type: none;
  perspective: 1800px;
  transform-style: preserve-3d;
}

.deck.is-enhanced .deck-slide {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 72%;
  aspect-ratio: 1280 / 615;
  transform:
    translate(-50%, -50%)
    translateX(var(--x, 0))
    rotateY(var(--ry, 0deg))
    scale(var(--sc, 1));
  opacity: var(--o, 1);
  z-index: var(--z, 1);
  box-shadow: 0 2rem 4rem rgba(0, 0, 0, 0.45);
  transition:
    transform 700ms var(--ease-out),
    opacity 700ms var(--ease-out),
    box-shadow 700ms var(--ease-out);
}

.deck.is-enhanced .deck-slide[data-state="far"] {
  pointer-events: none;
}

.deck.is-enhanced .deck-slide[data-state="active"] {
  box-shadow: 0 3rem 6rem rgba(0, 0, 0, 0.6);
}

.deck.is-enhanced .deck-slide[data-state="active"] button {
  cursor: zoom-in;
}

.deck-slide:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

.deck-nav {
  position: absolute;
  top: 50%;
  z-index: 6;
  display: none;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  transform: translateY(-50%);
  border: 1px solid color-mix(in srgb, var(--ink), transparent 72%);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg), transparent 22%);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 250ms var(--ease-out), color 250ms var(--ease-out), opacity 250ms var(--ease-out);
}

.deck.is-enhanced .deck-nav {
  display: grid;
}

.deck-nav svg {
  width: 1.2rem;
  height: 1.2rem;
}

.deck-nav[data-deck-nav="prev"] {
  left: clamp(0.35rem, 1.5vw, 1.1rem);
}

.deck-nav[data-deck-nav="next"] {
  right: clamp(0.35rem, 1.5vw, 1.1rem);
}

.deck-nav:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.deck-nav[disabled] {
  opacity: 0.2;
  pointer-events: none;
}

.deck-tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

.deck-tab {
  border: 1px solid color-mix(in srgb, var(--ink), transparent 80%);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.6rem 1.05rem;
  transition: border-color 250ms var(--ease-out), color 250ms var(--ease-out), background-color 250ms var(--ease-out);
}

.deck-tab:hover {
  border-color: color-mix(in srgb, var(--ink), transparent 45%);
  color: var(--ink);
}

.deck-tab[aria-selected="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent), transparent 88%);
  color: var(--accent);
}

.deck-caption {
  text-align: center;
  color: var(--muted);
  font-size: 0.92rem;
  min-height: 1.5em;
}

@media (max-width: 760px) {
  .deck.is-enhanced .deck-stage {
    aspect-ratio: 2.15;
  }

  .deck.is-enhanced .deck-slide {
    width: 86%;
  }

  .deck-nav {
    width: 2.75rem;
    height: 2.75rem;
  }

  .deck-nav[data-deck-nav="prev"] {
    left: 0.35rem;
  }

  .deck-nav[data-deck-nav="next"] {
    right: 0.35rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .deck.is-enhanced .deck-slide {
    transition-duration: 1ms;
  }
}

/* --------------------------------------------------------------------------
   v3 · Offer
   -------------------------------------------------------------------------- */

/* What the deck proves, said plainly underneath it. */
.deck-proof {
  max-width: 44rem;
  margin: clamp(1.5rem, 4vw, 2.5rem) auto 0;
  text-align: center;
  color: var(--muted);
  font-size: 0.95rem;
}

/* The terms of the offer, stated before the form rather than after it. */
.offer-terms {
  display: grid;
  gap: 0;
  margin: 0 0 clamp(1.75rem, 4vw, 2.5rem);
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--hairline);
  max-width: 46rem;
}

.offer-terms li {
  display: grid;
  grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
  gap: 0.35rem 1.5rem;
  padding-block: 1.05rem;
  border-bottom: 1px solid var(--hairline);
  color: var(--muted);
  font-size: 0.95rem;
}

.offer-terms span {
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding-top: 0.25em;
}

@media (max-width: 640px) {
  .offer-terms li {
    grid-template-columns: 1fr;
  }
}

/* Seat counter. Server-side hidden until the number helps. */
.seat-count {
  display: inline-block;
  margin-left: 0.5rem;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.seat-count[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   v3 · Not found
   -------------------------------------------------------------------------- */

.error-stage {
  position: relative;
  display: grid;
  align-items: center;
  min-height: calc(100svh - 4.75rem);
  padding-block: clamp(2.25rem, 6vh, 5rem);
  overflow: hidden;
}

/* The hero's live shader, turned down until it reads as paper texture. */
.error-field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(120% 85% at 78% 30%, #000 0%, transparent 72%);
  mask-image: radial-gradient(120% 85% at 78% 30%, #000 0%, transparent 72%);
  pointer-events: none;
}

.error-inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 1.4rem;
  justify-items: start;
}

.error-code {
  margin: 0;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.4em;
}

.error-inner h1 {
  max-width: 16ch;
}

.error-inner .lede {
  max-width: 36rem;
}

.error-routes {
  display: grid;
  width: 100%;
  max-width: 46rem;
  margin-top: 1.2rem;
  border-top: 1px solid var(--hairline);
}

.error-routes a {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 12rem) minmax(0, 1fr);
  align-items: baseline;
  gap: 0.4rem 1.25rem;
  padding-block: clamp(0.8rem, 1.9vh, 1.15rem);
  border-bottom: 1px solid var(--hairline);
  text-decoration: none;
  transition: padding-left 420ms var(--ease-out), color 250ms var(--ease-out);
}

.error-routes a:hover,
.error-routes a:focus-visible {
  padding-left: 0.6rem;
  color: var(--accent);
}

.route-index {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  transition: color 250ms var(--ease-out);
}

.error-routes a:hover .route-index {
  color: var(--accent);
}

.route-name {
  font-family: var(--display);
  font-size: clamp(1.2rem, 2.2vw, 1.55rem);
  font-weight: 560;
  letter-spacing: -0.03em;
}

.route-note {
  color: var(--muted);
  font-size: 0.9rem;
}

.error-actions {
  margin-top: 1.6rem;
}

@media (max-width: 700px) {
  .error-routes a {
    grid-template-columns: 2.25rem minmax(0, 1fr);
  }

  .route-note {
    grid-column: 2;
  }

  .error-field {
    opacity: 0.32;
  }
}

/* --------------------------------------------------------------------------
   v3 · Case studies
   -------------------------------------------------------------------------- */

.case-meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem 2rem;
  margin: 0;
  padding-block: 1.5rem;
  border-block: 1px solid var(--hairline);
}

.case-meta div {
  display: grid;
  gap: 0.4rem;
}

.case-meta dt {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.case-meta dd {
  margin: 0;
  font-size: 0.95rem;
}

.case-figure {
  margin: 0;
  display: grid;
  gap: 0.8rem;
}

.case-figure + .case-figure {
  margin-top: clamp(2rem, 5vw, 3.5rem);
}

.case-figure img {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid var(--hairline);
  border-radius: 6px;
}

.case-figure.on-dark img {
  background: var(--dark-bg);
  border-color: #23262b;
}

.case-figure figcaption {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.case-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  align-items: start;
}

.case-pair .case-figure + .case-figure {
  margin-top: 0;
}

.case-pair-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.4vw, 1rem);
  align-items: start;
}

.case-pair-3 .case-figure:nth-child(2) {
  margin-top: clamp(1.5rem, 5vw, 4rem);
}

@media (max-width: 760px) {
  .case-pair-3 {
    grid-template-columns: 1fr;
  }

  .case-pair-3 .case-figure:nth-child(2) {
    margin-top: 0;
  }
}

.case-nav {
  display: flex;
  justify-content: space-between;
  gap: 2rem;
  padding-block: clamp(2rem, 5vw, 3rem);
  border-top: 1px solid var(--hairline);
}

.case-nav a {
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  padding-bottom: 0.15rem;
}

/* --------------------------------------------------------------------------
   v3 · Early access flow — complete without JavaScript (stacked fieldsets),
   enhanced into steps when site.js adds .ea-enhanced
   -------------------------------------------------------------------------- */

.ea-panel {
  max-width: 44rem;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: var(--surface);
  padding: clamp(1.75rem, 5vw, 3rem);
}

.ea-panel fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.ea-panel fieldset + fieldset,
.ea-panel .ea-final {
  margin-top: 2rem;
}

.ea-panel legend,
.ea-final-label {
  padding: 0;
  margin-bottom: 1rem;
  font-size: 1.02rem;
  font-weight: 650;
}

.ea-progress {
  margin-bottom: 1.5rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.choice-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
}

.choice-grid label {
  position: relative;
  display: grid;
  align-content: center;
  min-height: 3.4rem;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  background: var(--bg);
  padding: 0.9rem 1.1rem;
  cursor: pointer;
  font-weight: 500;
  transition: border-color 200ms var(--ease-out), background-color 200ms var(--ease-out);
}

.choice-grid label:hover {
  border-color: var(--ink);
}

.choice-grid input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.choice-grid input:checked + span {
  color: var(--accent);
}

.choice-grid label:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent), var(--bg) 94%);
}

.choice-grid input:focus-visible + span {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
}

.ea-final {
  display: grid;
  gap: 0.9rem;
}

.ea-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
  margin-top: 1.5rem;
}

/* The reply gets its own line rather than sitting in the button row. Inline, it
   had to hold its own against two other type sizes, which never reads as
   aligned, and it changed which row it was on depending on how long the message
   happened to be. On its own line it lands in the same place every time, which
   is also how /access does it. */
.ea-actions .form-status {
  flex-basis: 100%;
  margin: 0;
}

.ea-back {
  display: none;
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  padding: 0.5rem 0;
  font-size: 0.88rem;
}

.ea-back:hover {
  color: var(--accent);
}

/* Enhanced stepping */
.ea-panel.ea-enhanced fieldset,
.ea-panel.ea-enhanced .ea-final {
  display: none;
  margin-top: 0;
}

.ea-panel.ea-enhanced fieldset.is-active {
  display: block;
}

.ea-panel.ea-enhanced .ea-final.is-active {
  display: grid;
}

.ea-panel.ea-enhanced .ea-back.is-available {
  display: inline-block;
}

/* Submit appears only on the final step once enhanced */
.ea-panel.ea-enhanced button[type="submit"] {
  display: none;
}

.ea-panel.ea-enhanced .ea-final.is-active ~ .ea-actions button[type="submit"] {
  display: inline-flex;
}

/* Honeypot — never shown, never focusable by real visitors */
.hp-field {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   v3 · Footer action (single ask per surface: a route, not a form)
   -------------------------------------------------------------------------- */

.footer-action {
  display: grid;
  align-content: start;
  justify-items: start;
  gap: 0.9rem;
}

.footer-action p {
  max-width: 25rem;
  color: var(--muted);
  font-size: 0.88rem;
}

/* --------------------------------------------------------------------------
   v3 · Utility pages
   -------------------------------------------------------------------------- */

.legal-prose {
  max-width: var(--prose);
}

.legal-prose h2 {
  font-size: 1.3rem;
  margin-top: 2.5rem;
}

.legal-prose p,
.legal-prose li {
  color: var(--muted);
}

.legal-prose ul {
  margin: 1rem 0 0;
  padding-left: 1.2rem;
}

.legal-prose li + li {
  margin-top: 0.5rem;
}

@media (max-width: 760px) {
  .reel-grid,
  .choice-grid,
  .case-pair {
    grid-template-columns: 1fr;
  }

  .beat {
    grid-template-columns: 1fr;
    gap: 0.9rem;
  }

  .case-meta {
    grid-template-columns: 1fr 1fr;
  }
}

/* --------------------------------------------------------------------------
   v3 · The prompt library (/prompts)
   Clarke's ivory register throughout, descending into the Transora dark one
   for the single conversion at the foot of every page.
   -------------------------------------------------------------------------- */

/* Shared furniture the library needed and the site did not have yet. */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
}

.breadcrumb {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  padding-top: clamp(1.5rem, 4vw, 2.5rem);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.breadcrumb a {
  text-decoration: none;
}

.breadcrumb span[aria-hidden] {
  opacity: 0.4;
}

/* The clipboard fallback needs a real, selectable node. Keeping it off-screen
   rather than display:none is what makes the selection work at all. */
.copy-scratch {
  position: fixed;
  top: 0;
  left: -9999px;
  opacity: 0;
}

body.panel-open {
  overflow: hidden;
}

.prompts-hero h1 {
  max-width: 20ch;
}

/* ------------------------------------------------------------------- terms */

.term-grid {
  display: grid;
  gap: clamp(1.75rem, 3.5vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.term p + p {
  margin-top: 0.7rem;
  color: var(--muted);
}

/* ------------------------------------------------------------------- rules */

.rule-grid {
  display: grid;
  gap: clamp(2rem, 4vw, 3.25rem);
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

.rule {
  display: grid;
  gap: 0.7rem;
  align-content: start;
  padding-top: 1.5rem;
  border-top: 1px solid var(--hairline);
}

.rule__number {
  color: var(--accent);
}

.rule__title {
  font-family: var(--body);
  font-size: 1.08rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.3;
}

.rule__body {
  color: var(--muted);
  font-size: 0.96rem;
}

/* ----------------------------------------------------------------- toolbar */

/* Hidden until the script claims it. Search and filters that cannot filter
   are worse than no search at all. */
.prompt-toolbar {
  display: none;
}

.prompt-toolbar.is-enhanced {
  position: sticky;
  top: 4.1rem;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  align-items: center;
  margin-bottom: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface), transparent 8%);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.prompt-search {
  flex: 1 1 15rem;
  min-width: 0;
}

.prompt-search input {
  width: 100%;
  padding: 0.4rem 0.2rem;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 0.95rem;
}

.prompt-search input::placeholder {
  color: var(--muted);
}

.prompt-search input:focus-visible {
  outline: 0;
}

.prompt-search input:focus-visible::placeholder {
  color: color-mix(in srgb, var(--muted), transparent 40%);
}

.prompt-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.prompt-filter {
  padding: 0.42rem 0.95rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: background-color 220ms var(--ease-out), color 220ms var(--ease-out), border-color 220ms var(--ease-out);
}

.prompt-filter:hover {
  border-color: var(--ink);
  color: var(--ink);
}

.prompt-filter.is-active {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
}

.prompt-count {
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.prompt-empty {
  padding: 3rem 0;
  color: var(--muted);
  text-align: center;
}

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

.prompt-grid {
  display: grid;
  gap: clamp(1.25rem, 2.5vw, 2rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
}

.prompt-card {
  display: flex;
  overflow: hidden;
  flex-direction: column;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--surface);
}

/* An author `display` declaration outranks the browser's own rule for the
   hidden attribute, so filtered cards would stay on screen without this.
   It has to sit after the rule above to win on source order. */
.prompt-card[hidden] {
  display: none;
}

.prompt-card__figure {
  display: block;
  overflow: hidden;
  aspect-ratio: 4 / 5;
  background: color-mix(in srgb, var(--ink), transparent 92%);
}

/* The one landscape frame in the set takes two columns rather than sitting in
   a portrait slot with its sides cropped off. */
.prompt-card.is-landscape .prompt-card__figure {
  aspect-ratio: 16 / 10;
}

@media (min-width: 48rem) {
  .prompt-card.is-landscape {
    grid-column: span 2;
  }
}

.prompt-card__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--ease-out);
}

.prompt-card:hover .prompt-card__figure img {
  transform: scale(1.03);
}

.prompt-card__body {
  display: grid;
  gap: 0.65rem;
  align-content: start;
  flex: 1;
  padding: 1.25rem 1.35rem 1.1rem;
}

.prompt-card__meta {
  display: flex;
  gap: 0.7rem;
  align-items: baseline;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.prompt-number {
  color: var(--accent);
}

.prompt-card__title {
  font-size: 1.4rem;
}

.prompt-card__title a {
  text-decoration: none;
}

.prompt-card__summary {
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.55;
}

.prompt-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.15rem 0 0;
  padding: 0;
  list-style: none;
}

.prompt-chips li {
  padding: 0.22rem 0.6rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* The disclosure is the no-JavaScript path and the panel trigger at once. */
.prompt-card__reveal {
  border-top: 1px solid var(--hairline);
}

.prompt-card__reveal summary {
  padding: 0.95rem 1.35rem;
  color: var(--ink);
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  list-style: none;
  transition: color 200ms var(--ease-out);
}

.prompt-card__reveal summary::-webkit-details-marker {
  display: none;
}

.prompt-card__reveal summary::after {
  content: " →";
  color: var(--accent);
}

.prompt-card__reveal summary:hover {
  color: var(--accent);
}

.prompt-card__detail {
  display: grid;
  gap: 1.5rem;
  padding: 0 1.35rem 1.35rem;
}

/* -------------------------------------------------- prompt body components */

.prompt-why p,
.prompt-note {
  margin-top: 0.6rem;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.6;
}

.prompt-note {
  padding: 0.85rem 1rem;
  border-left: 2px solid var(--accent);
  background: color-mix(in srgb, var(--accent), transparent 94%);
  font-size: 0.88rem;
}

.prompt-swaps {
  display: grid;
  gap: 0.55rem;
}

.prompt-swaps .mono-label {
  margin-bottom: 0.35rem;
}

.prompt-swaps .swap-row {
  display: grid;
  gap: 0.15rem;
  padding-bottom: 0.55rem;
  border-bottom: 1px solid var(--hairline);
}

.prompt-swaps .swap-row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.swap-from {
  font-family: var(--mono);
  font-size: 0.78rem;
}

.swap-to {
  color: var(--muted);
  font-size: 0.86rem;
}

.prompt-source {
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: color-mix(in srgb, var(--ink), transparent 96%);
}

.prompt-source__bar {
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--hairline);
}

.prompt-copy {
  padding: 0.42rem 0.9rem;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--ink);
  color: var(--bg);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: background-color 220ms var(--ease-out), border-color 220ms var(--ease-out);
}

.prompt-copy:hover {
  border-color: var(--accent);
  background: var(--accent);
}

.prompt-copy.is-copied {
  border-color: #3f7d55;
  background: #3f7d55;
}

.prompt-text {
  max-height: 22rem;
  margin: 0;
  overflow: auto;
  padding: 1rem 0.9rem;
  font-family: var(--mono);
  font-size: 0.76rem;
  line-height: 1.7;
  tab-size: 2;
  white-space: pre-wrap;
  word-break: break-word;
}

.prompt-card__permalink {
  font-size: 0.85rem;
}

.prompt-licence {
  color: var(--muted);
  font-size: 0.85rem;
}

/* ------------------------------------------------------------ reading panel */

.prompt-panel {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  padding: clamp(0rem, 4vh, 3rem) clamp(0rem, 4vw, 3rem);
  background: color-mix(in srgb, #0a0b0d, transparent 8%);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms var(--ease-out);
}

/* Closed state stays out of the tab order through the inert attribute the
   script sets, so the fade runs both ways without a visibility flip. */
.prompt-panel[data-open="true"] {
  opacity: 1;
  pointer-events: auto;
}

.prompt-panel__scrim {
  position: absolute;
  inset: 0;
}

.prompt-panel__sheet {
  position: relative;
  display: grid;
  overflow: hidden;
  width: min(100%, 72rem);
  max-height: 100%;
  grid-template-rows: auto minmax(0, 1fr) auto;
  margin-inline: auto;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--bg);
  transform: translateY(10px);
  transition: transform 380ms var(--ease-out);
}

.prompt-panel[data-open="true"] .prompt-panel__sheet {
  transform: translateY(0);
}

.prompt-panel__head,
.prompt-panel__foot {
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem clamp(1rem, 3vw, 1.75rem);
}

.prompt-panel__head {
  border-bottom: 1px solid var(--hairline);
}

.prompt-panel__foot {
  border-top: 1px solid var(--hairline);
}

.prompt-panel__close,
.prompt-panel__step {
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: border-color 220ms var(--ease-out), color 220ms var(--ease-out);
}

.prompt-panel__close:hover,
.prompt-panel__step:hover {
  border-color: var(--ink);
  color: var(--ink);
}

.prompt-panel__body {
  display: grid;
  overflow-y: auto;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  padding: clamp(1.25rem, 3vw, 2rem) clamp(1rem, 3vw, 1.75rem);
}

.prompt-panel__figure {
  margin: 0;
  align-self: start;
  position: sticky;
  top: 0;
}

.prompt-panel__figure img {
  width: 100%;
  height: auto;
  border-radius: 8px;
}

.prompt-panel__content {
  display: grid;
  gap: 0.85rem;
  align-content: start;
  min-width: 0;
}

.prompt-panel__content h2 {
  max-width: none;
  font-size: clamp(1.8rem, 3.4vw, 2.6rem);
}

.prompt-panel__summary {
  color: var(--muted);
}

.prompt-panel__detail .prompt-card__detail {
  padding: 0;
  gap: 1.5rem;
}

.prompt-panel__detail .prompt-text {
  max-height: none;
}

/* ------------------------------------------------------------ detail pages */

.prompt-detail-hero .prompt-chips {
  margin-top: 1.75rem;
}

.prompt-detail {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  align-items: start;
}

.prompt-detail__figure {
  position: sticky;
  top: 6rem;
  margin: 0;
}

.prompt-detail__figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
}

.prompt-detail__figure figcaption {
  margin-top: 0.8rem;
  color: var(--muted);
  font-size: 0.82rem;
  line-height: 1.55;
}

.prompt-detail__body {
  display: grid;
  gap: 2rem;
}

.prompt-detail__body .prompt-text {
  max-height: none;
}

.prompt-pager {
  display: flex;
  gap: 1.5rem;
  justify-content: space-between;
  padding-block: clamp(2.5rem, 6vw, 4rem);
  border-top: 1px solid var(--hairline);
}

.prompt-pager__link {
  display: grid;
  gap: 0.35rem;
  max-width: 45%;
  font-family: var(--display);
  font-size: clamp(1.1rem, 2vw, 1.5rem);
  letter-spacing: -0.02em;
  line-height: 1.15;
  text-decoration: none;
}

.prompt-pager__link--next {
  text-align: right;
}

@media (max-width: 62rem) {
  .prompt-detail,
  .prompt-panel__body {
    grid-template-columns: minmax(0, 1fr);
  }

  .prompt-detail__figure,
  .prompt-panel__figure {
    position: static;
  }

  .prompt-panel__figure img {
    max-height: 46vh;
    object-fit: cover;
  }
}

@media (max-width: 40rem) {
  .prompt-toolbar.is-enhanced {
    border-radius: 14px;
  }

  .prompt-pager {
    flex-direction: column;
  }

  .prompt-pager__link {
    max-width: none;
  }

  .prompt-pager__link--next {
    text-align: left;
  }
}

/* --------------------------------------------------------------------------
   v3 · The style-transfer gallery (/transora/styles)

   Fifty variations on one photograph. The page has two jobs the prompt library
   does not: hold fifty frames without turning into a contact sheet, and let one
   be compared against the source frame rather than only looked at.
   -------------------------------------------------------------------------- */

.styles-hero .lede {
  max-width: 44rem;
}

.styles-hero__growth {
  max-width: 40rem;
  margin-top: 1.25rem;
  color: var(--muted);
  font-size: 0.92rem;
}

/* ------------------------------------------------------------- source frame */

.style-source {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

@media (min-width: 60rem) {
  .style-source {
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  }
}

.style-source__figure {
  margin: 0;
}

.style-source__figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  background: var(--hairline);
}

.style-source__figure figcaption {
  margin-top: 0.85rem;
  color: var(--muted);
  font-size: 0.85rem;
}

.style-source__copy h2 {
  margin: 0.4rem 0 0;
}

.style-source__held-label {
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
}

.style-held {
  display: grid;
  gap: 0;
  margin: 0.85rem 0 0;
  padding: 0;
  border-top: 1px solid var(--hairline);
  list-style: none;
}

.style-held li {
  padding-block: 0.7rem;
  border-bottom: 1px solid var(--hairline);
  font-size: 0.95rem;
}

/* The list reads as a specification, so it gets the ticked column a spec has. */
.style-held li::before {
  margin-right: 0.7rem;
  color: var(--accent);
  content: "·";
  font-family: var(--mono);
}

/* The counted variant carries how often each thing is actually pinned across the
   set. The number is the point: nothing is held in every prompt, and a list that
   implied otherwise was describing a worse tool than this one. */
.style-held--counted li {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
}

.style-held--counted li::before {
  order: -1;
}

.style-held__what {
  flex: 1 1 auto;
}

.style-held__count {
  flex: 0 0 auto;
  color: var(--muted);
  white-space: nowrap;
}

.style-source__note,
.style-source__own {
  max-width: var(--prose);
  margin-top: clamp(1.5rem, 3.5vw, 2.25rem);
  color: var(--muted);
}

.style-source__note {
  font-size: 0.9rem;
}

/* ----------------------------------------------------------------- toolbar */

/* Hidden until styles-gallery.js marks it enhanced: a search box that cannot
   search is worse than no search box. */
.style-toolbar {
  display: none;
}

.style-toolbar.is-enhanced {
  position: sticky;
  top: 4.1rem;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  align-items: center;
  margin-bottom: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface), transparent 8%);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.style-search {
  flex: 1 1 14rem;
  min-width: 0;
}

.style-search input {
  width: 100%;
  padding: 0.4rem 0.2rem;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 0.95rem;
}

.style-search input::placeholder {
  color: var(--muted);
}

.style-search input:focus-visible {
  outline: 0;
}

.style-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* Nine chips wrap into a wall on a phone, and this bar is sticky, so the wall
   would follow you down the page. One scrolling row instead. */
@media (max-width: 46rem) {
  .style-toolbar.is-enhanced {
    border-radius: 14px;
  }

  .style-filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    width: 100%;
    padding-bottom: 0.2rem;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .style-filters::-webkit-scrollbar {
    display: none;
  }

  .style-filter {
    flex: 0 0 auto;
  }
}

.style-filter {
  padding: 0.42rem 0.9rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: background-color 220ms var(--ease-out), color 220ms var(--ease-out), border-color 220ms var(--ease-out);
}

.style-filter:hover {
  border-color: var(--ink);
  color: var(--ink);
}

.style-filter.is-active {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
}

.style-count {
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.style-empty {
  padding: 3rem 0;
  color: var(--muted);
  text-align: center;
}

/* ---------------------------------------------------------------- families */

.style-families {
  display: grid;
  gap: clamp(3rem, 7vw, 5.5rem);
}

/* An author display declaration outranks the browser's own rule for the hidden
   attribute, so a filtered-out family would stay on screen without this. It has
   to sit after the rule it is overriding to win on source order. */
.style-family[hidden],
.style-card[hidden] {
  display: none;
}

.style-family__head {
  max-width: var(--prose);
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
}

.style-family__name {
  margin: 0;
  font-size: clamp(1.35rem, 2.4vw, 1.9rem);
}

.style-family__blurb {
  margin: 0.5rem 0 0;
  color: var(--muted);
}

.style-family__tally {
  margin: 0.75rem 0 0;
}

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

.style-grid {
  display: grid;
  gap: clamp(1rem, 2vw, 1.6rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 13.5rem), 1fr));
}

.style-card {
  display: flex;
  overflow: hidden;
  flex-direction: column;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--surface);
  transition: border-color 260ms var(--ease-out), transform 260ms var(--ease-out);
}

.style-card:hover {
  border-color: color-mix(in srgb, var(--ink), transparent 55%);
  transform: translateY(-3px);
}

.style-card__figure {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 9 / 16;
  background: var(--hairline);
}

.style-card__figure img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--ease-out);
}

.style-card:hover .style-card__figure img {
  transform: scale(1.03);
}

/* The cue is the only thing telling a first-time visitor these open into a
   comparison rather than a lightbox. It stays legible over any of fifty frames
   by sitting on its own plate rather than trusting the image underneath. */
.style-card__cue {
  position: absolute;
  right: 0.55rem;
  bottom: 0.55rem;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  opacity: 0;
  background: color-mix(in srgb, var(--ink), transparent 18%);
  color: var(--bg);
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: opacity 240ms var(--ease-out);
}

.style-card:hover .style-card__cue,
.style-card:focus-within .style-card__cue {
  opacity: 1;
}

.style-card__body {
  padding: 0.9rem 1rem 1.05rem;
}

.style-card__name {
  margin: 0;
  font-family: var(--body);
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.3;
}

.style-card__name a {
  color: inherit;
  text-decoration: none;
}

.style-card__name a:hover {
  color: var(--accent);
}

.style-card__note {
  margin: 0.45rem 0 0;
  color: var(--muted);
  font-size: 0.82rem;
  line-height: 1.5;
}

/* ------------------------------------------------------------------ viewer */

.style-viewer {
  position: fixed;
  z-index: 90;
  display: grid;
  visibility: hidden;
  align-items: center;
  justify-items: center;
  opacity: 0;
  inset: 0;
  transition: opacity 300ms var(--ease-out), visibility 300ms var(--ease-out);
}

.style-viewer[data-open="true"] {
  visibility: visible;
  opacity: 1;
}

.style-viewer__scrim {
  position: absolute;
  background: color-mix(in srgb, var(--dark-bg), transparent 12%);
  cursor: pointer;
  inset: 0;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.style-viewer__sheet {
  position: relative;
  display: flex;
  overflow: hidden;
  width: fit-content;
  max-width: calc(100vw - 2rem);
  max-height: min(94dvh, 62rem);
  flex-direction: column;
  border-radius: 14px;
  background: var(--surface);
  transform: translateY(12px) scale(0.99);
  transition: transform 320ms var(--ease-out);
}

.style-viewer[data-open="true"] .style-viewer__sheet {
  transform: none;
}

.style-viewer__head,
.style-viewer__foot {
  display: flex;
  flex: 0 0 auto;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem clamp(1rem, 3vw, 1.75rem);
}

.style-viewer__head {
  border-bottom: 1px solid var(--hairline);
}

.style-viewer__foot {
  border-top: 1px solid var(--hairline);
}

.style-viewer__head .mono-label {
  margin: 0;
}

.style-viewer__close,
.style-viewer__step {
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: border-color 200ms var(--ease-out), color 200ms var(--ease-out);
}

.style-viewer__close:hover,
.style-viewer__step:hover:not(:disabled) {
  border-color: var(--ink);
  color: var(--ink);
}

.style-viewer__step:disabled {
  opacity: 0.4;
  cursor: default;
}

.style-viewer__position {
  margin: 0;
}

.style-viewer__body {
  display: grid;
  overflow-y: auto;
  gap: clamp(1.25rem, 3vw, 2rem);
  padding: clamp(1rem, 3vw, 1.75rem);
  overscroll-behavior: contain;
}

/* The frame is portrait and the sheet is height-bound, so the figure column
   takes whatever width its ratio needs and the prose takes a measured column
   beside it. Sizing the sheet to fit that rather than to a fixed width is what
   stops a short note leaving half the dialog empty. */
@media (min-width: 52rem) {
  .style-viewer__body {
    grid-template-columns: auto minmax(0, 24rem);
    align-items: start;
  }
}

.style-viewer__content h2 {
  margin: 0;
  font-size: clamp(1.5rem, 3vw, 2.1rem);
}

.style-viewer__wink {
  margin: 0.6rem 0 0;
  color: var(--accent);
  font-family: var(--display);
  font-size: 1.02rem;
  font-style: italic;
}

.style-viewer__note {
  margin: 0.9rem 0 0;
  max-width: var(--prose);
  color: var(--muted);
}

.style-viewer__held-label {
  margin: 1.6rem 0 0;
}

.style-viewer__content .style-held {
  margin-top: 0.6rem;
}

.style-viewer__content .style-held li {
  padding-block: 0.5rem;
  font-size: 0.85rem;
}

.style-viewer__held-empty {
  margin: 0.7rem 0 0;
  color: var(--muted);
  font-size: 0.88rem;
}

/* ----------------------------------------------------------------- compare */

.style-compare {
  margin: 0;
}

/* Height is the binding constraint on a portrait frame in a landscape window,
   so drive the box from height and let the ratio decide the width. Setting a
   width and capping the height instead would quietly break the ratio, and the
   whole page rests on the two frames lining up. */
.style-compare__stage {
  position: relative;
  overflow: hidden;
  width: auto;
  height: min(64dvh, 32rem);
  max-width: 100%;
  aspect-ratio: var(--frame-ratio, 941 / 1672);
  margin-inline: auto;
  border-radius: 10px;
  background: var(--dark-bg);
  cursor: ew-resize;
  /* Horizontal drag belongs to the wipe, vertical scroll to the page. */
  touch-action: pan-y;
}

@media (max-width: 52rem) {
  .style-compare__stage {
    height: auto;
    width: 100%;
  }
}

.style-compare__stage img {
  position: absolute;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  inset: 0;
  user-select: none;
  -webkit-user-drag: none;
}

/* The transfer grows from the left as the control moves right, so dragging
   towards the style name reveals more of it. */
.style-compare__top {
  clip-path: inset(0 calc(100% - var(--wipe-at, 55%)) 0 0);
}

.style-compare__seam {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--wipe-at, 55%);
  width: 2px;
  background: color-mix(in srgb, var(--surface), transparent 15%);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--dark-bg), transparent 70%);
  pointer-events: none;
  transform: translateX(-1px);
}

.style-compare__seam::after {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.1rem;
  height: 2.1rem;
  border: 2px solid color-mix(in srgb, var(--surface), transparent 15%);
  border-radius: 50%;
  background: color-mix(in srgb, var(--dark-bg), transparent 55%);
  content: "";
  transform: translate(-50%, -50%);
}

.style-compare__control {
  margin-top: 0.85rem;
}

.style-compare__control input[type="range"] {
  display: block;
  width: 100%;
  height: 1.5rem;
  margin: 0;
  background: transparent;
  cursor: ew-resize;
  -webkit-appearance: none;
  appearance: none;
}

.style-compare__control input[type="range"]::-webkit-slider-runnable-track {
  height: 2px;
  border-radius: 2px;
  background: var(--hairline);
}

.style-compare__control input[type="range"]::-moz-range-track {
  height: 2px;
  border-radius: 2px;
  background: var(--hairline);
}

.style-compare__control input[type="range"]::-webkit-slider-thumb {
  width: 1.05rem;
  height: 1.05rem;
  margin-top: -0.5rem;
  border: 0;
  border-radius: 50%;
  background: var(--ink);
  -webkit-appearance: none;
  appearance: none;
}

.style-compare__control input[type="range"]::-moz-range-thumb {
  width: 1.05rem;
  height: 1.05rem;
  border: 0;
  border-radius: 50%;
  background: var(--ink);
}

.style-compare__control input[type="range"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

.style-compare__legend {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin: 0.5rem 0 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.style-compare__legend span:last-child {
  text-align: right;
}

.style-compare__expand {
  margin-top: 0.75rem;
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: border-color 200ms var(--ease-out), color 200ms var(--ease-out);
}

.style-compare__expand:hover {
  border-color: var(--ink);
  color: var(--ink);
}

/* Full screen keeps the wipe rather than replacing it with a bare file, so the
   control and the legend come along and have to be legible on black. */
.style-compare.is-fullscreen {
  display: grid;
  align-content: center;
  justify-items: center;
  padding: clamp(1rem, 3vw, 2.5rem);
  background: var(--dark-bg);
}

/* A definite height, not a percentage. The grid rows here are sized to their
   content, so the parent height is indefinite, and a percentage against that
   cannot resolve: the stage collapsed to nothing and full screen showed a
   slider and a caption with no frame between them. vh first so the declaration
   still lands where dvh is not understood. */
.style-compare.is-fullscreen .style-compare__stage {
  width: auto;
  height: 82vh;
  height: 82dvh;
  max-width: 96vw;
  border-radius: 6px;
}

.style-compare.is-fullscreen .style-compare__control {
  width: min(38rem, 86vw);
}

.style-compare.is-fullscreen .style-compare__legend {
  color: color-mix(in srgb, var(--dark-ink), transparent 20%);
}

.style-compare.is-fullscreen input[type="range"]::-webkit-slider-runnable-track,
.style-compare.is-fullscreen input[type="range"]::-moz-range-track {
  background: color-mix(in srgb, var(--dark-ink), transparent 65%);
}

.style-compare.is-fullscreen input[type="range"]::-webkit-slider-thumb,
.style-compare.is-fullscreen input[type="range"]::-moz-range-thumb {
  background: var(--dark-ink);
}

.style-compare.is-fullscreen .style-compare__expand {
  border-color: color-mix(in srgb, var(--dark-ink), transparent 65%);
  color: color-mix(in srgb, var(--dark-ink), transparent 20%);
}

.style-compare.is-fullscreen .style-compare__expand:hover {
  border-color: var(--dark-ink);
  color: var(--dark-ink);
}

body.viewer-open {
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   Kin row — the three pages that make one argument, pointing at each other
   -------------------------------------------------------------------------- */

.kin-row {
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
  margin-top: 1.25rem;
}

@media (min-width: 48rem) {
  .kin-row {
    grid-template-columns: 1fr 1fr;
  }
}

.kin {
  display: grid;
  align-content: start;
  gap: 0.4rem;
  padding: clamp(1.25rem, 2.5vw, 1.85rem);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  color: inherit;
  text-decoration: none;
  transition: border-color 260ms var(--ease-out), transform 260ms var(--ease-out);
}

.kin:hover {
  border-color: color-mix(in srgb, var(--ink), transparent 55%);
  transform: translateY(-2px);
}

.kin__label {
  margin: 0;
  color: var(--accent);
}

.kin__title {
  font-family: var(--display);
  font-size: clamp(1.15rem, 2.2vw, 1.5rem);
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.kin__note {
  color: var(--muted);
  font-size: 0.88rem;
  line-height: 1.55;
}

.scene--dark .kin,
.register-dark .kin {
  border-color: color-mix(in srgb, var(--dark-ink), transparent 82%);
}

/* --------------------------------------------------------------------------
   Reduced motion — motion.js also declines to run its scenes
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .style-card:hover {
    transform: none;
  }

  .style-card:hover .style-card__figure img {
    transform: none;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
