/**
 * AnyChat — landing page.
 *
 * Light mode only, by design: the product's light palettes are the ones taken
 * from each provider's own composer, and a page that inverted would fight the
 * device sitting in the middle of it.
 *
 * Token naming is deliberately disjoint from the extension's. `styles/device.css`
 * is generated from src/lib/themes.css and registers --bg, --surface, --border,
 * --accent, --text, --muted, --radius and --glow as inheriting custom
 * properties, which means their *initial* values land on :root and inherit into
 * this whole document. Nothing here may use those names. Site tokens are
 * --paper / --ink / --edge, and the one value that crosses the boundary is
 * --live: the current provider's accent, republished onto :root by
 * scripts/device.js.
 *
 * See site/DESIGN.md for why the page is shaped the way it is.
 */

/* --live is registered so the aurora, the rail and the rules can tween between
   provider accents instead of snapping. It is the only token this page shares
   with the device, and it travels one way: device -> page.

   The initial value is ChatGPT's light accent, because ChatGPT is where the hero
   starts. It has to match: scripts/device.js only overwrites this on the first
   morph, a frame or two after paint, so any other value would open the page in
   one colour and change to another before the reader had done anything. It
   being near-black is the cost of leading with ChatGPT — the page opens neutral
   and warms up three seconds later, when Gemini arrives. */
@property --live {
  syntax: '<color>';
  inherits: true;
  initial-value: #0d0d0d;
}

:root {
  color-scheme: light;

  --paper: #fbfbf9;
  --paper-2: #ffffff;
  --paper-3: #f4f4f1;
  --paper-4: #eeeeea;

  --ink: #14161a;
  --ink-2: #4b5261;
  --ink-3: #686f7d;
  --ink-4: #b4bac6;

  --edge: #e6e6e1;
  --edge-2: #f0f0ec;

  --live-soft: color-mix(in srgb, var(--live) 10%, transparent);
  --live-line: color-mix(in srgb, var(--live) 34%, transparent);

  --sans:
    'Inter var', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI Variable Text',
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --serif: ui-serif, Georgia, 'Times New Roman', serif;
  --mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  --r-xl: 26px;
  --r-lg: 18px;
  --r-md: 12px;
  --r-sm: 8px;

  /* Tinted blue-grey rather than neutral black, for the same reason the
     extension's light theme is: a neutral blur over warm paper reads as dirt. */
  --lift-1: 0 1px 2px rgb(20 24 34 / 5%);
  --lift-2:
    0 1px 2px rgb(20 24 34 / 4%),
    0 10px 26px -10px rgb(20 24 34 / 12%);
  --lift-3:
    0 2px 6px rgb(20 24 34 / 5%),
    0 30px 70px -22px rgb(20 24 34 / 20%);

  --maxw: 1240px;
  --gut: clamp(20px, 4.2vw, 44px);
  --ease: cubic-bezier(0.22, 0.8, 0.24, 1);
}

/* ---------------------------------------------------------------- resets --- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Every in-page anchor lands under the sticky nav otherwise. */
  scroll-padding-top: 118px;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: 'cv05' 1, 'ss03' 1;
  overflow-x: hidden;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  color: var(--ink);
  font-weight: 640;
  letter-spacing: -0.035em;
  line-height: 1.06;
  text-wrap: balance;
}

p {
  margin: 0;
}

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

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  border: 0;
  background: none;
  cursor: pointer;
}

:focus-visible {
  outline: 2px solid var(--live);
  outline-offset: 3px;
  border-radius: 4px;
}

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

/* A skip link that is invisible even when focused is not a skip link. */
a.sr-only:focus-visible {
  position: fixed;
  z-index: 100;
  top: 12px;
  left: 12px;
  width: auto;
  height: auto;
  clip-path: none;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 560;
}

/* ------------------------------------------------------------- primitives --- */

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.wrap--narrow {
  max-width: 860px;
}

section {
  position: relative;
  padding-block: clamp(76px, 9.5vw, 148px);
}

.band {
  background: var(--paper-3);
  border-block: 1px solid var(--edge);
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 20px;
  color: var(--ink-3);
  font-size: 0.75rem;
  font-weight: 620;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.eyebrow::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--live);
  transition: background 420ms var(--ease);
}

h2.section-title {
  font-size: clamp(1.95rem, 4.1vw, 3.05rem);
}

.lede {
  margin-top: 20px;
  max-width: 58ch;
  color: var(--ink-2);
  font-size: clamp(1.03rem, 1.35vw, 1.2rem);
  line-height: 1.6;
  letter-spacing: -0.011em;
  text-wrap: pretty;
}

.head {
  max-width: 720px;
  margin-bottom: clamp(40px, 4.4vw, 64px);
}

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

.head--center .lede {
  margin-inline: auto;
}

.head--center .eyebrow {
  justify-content: center;
}

.rule {
  height: 1px;
  border: 0;
  margin: 0;
  background: var(--edge);
}

/* Small caps-ish label, used above the footer link columns. */
.label {
  color: var(--ink-3);
  font-size: 0.7rem;
  font-weight: 650;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.mono {
  font-family: var(--mono);
  font-size: 0.82em;
  letter-spacing: -0.01em;
}

kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.9em;
  padding: 2px 6px;
  border: 1px solid var(--edge);
  border-bottom-width: 2px;
  border-radius: 6px;
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: 0.78em;
  font-weight: 600;
  line-height: 1.5;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 13px 22px;
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 580;
  letter-spacing: -0.012em;
  white-space: nowrap;
  transition:
    transform 200ms var(--ease),
    box-shadow 240ms var(--ease),
    background 200ms var(--ease),
    border-color 200ms var(--ease),
    color 200ms var(--ease);
}

.btn svg {
  flex: none;
}

/* Ink, not the provider accent. The structural colour on this page never
   moves — only the ambient colour follows the device. See DESIGN.md. */
.btn--primary {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: #fff;
  box-shadow:
    0 1px 2px rgb(20 24 34 / 20%),
    0 12px 28px -12px rgb(20 24 34 / 45%);
}

/* The magnetic glow: a soft radial that follows the pointer. --mx/--my are set
   by scripts/site.js on pointermove and default to the centre. */
.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    120px 120px at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--live) 62%, white 38%) 0%,
    transparent 68%
  );
  opacity: 0;
  transition: opacity 260ms var(--ease);
  pointer-events: none;
}

.btn--primary:hover {
  transform: translateY(-1px);
  box-shadow:
    0 1px 2px rgb(20 24 34 / 22%),
    0 18px 38px -14px rgb(20 24 34 / 50%);
}

.btn--primary:hover::after {
  opacity: 0.32;
}

.btn--primary > * {
  position: relative;
  z-index: 1;
}

.btn--ghost {
  border: 1px solid var(--edge);
  background: var(--paper-2);
  color: var(--ink);
  box-shadow: var(--lift-1);
}

.btn--ghost:hover {
  border-color: var(--ink-4);
  transform: translateY(-1px);
  box-shadow: var(--lift-2);
}

.btn--sm {
  padding: 9px 16px;
  font-size: 0.875rem;
}

.btn--quiet {
  color: var(--ink-2);
  padding: 9px 4px;
}

.btn--quiet:hover {
  color: var(--ink);
}

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

.nav {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--paper) 78%, transparent);
  backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 240ms var(--ease), background 240ms var(--ease);
}

.nav[data-stuck] {
  border-bottom-color: var(--edge);
  background: color-mix(in srgb, var(--paper) 90%, transparent);
}

.nav__rail {
  position: absolute;
  inset: 0 auto auto 0;
  height: 2px;
  width: 100%;
  transform: scaleX(var(--progress, 0));
  transform-origin: 0 50%;
  background: var(--live);
  transition: background 420ms var(--ease);
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 18px;
  height: 96px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 1.03rem;
  font-weight: 640;
  letter-spacing: -0.028em;
}

.brand svg {
  width: 22px;
  height: 22px;
  color: var(--ink);
}

/* Twice the size in the nav, and only there: the footer's copy of .brand is a
   sign-off, not a masthead. The nav grows to hold it. */
.nav .brand {
  gap: 14px;
  font-size: 2.06rem;
  letter-spacing: -0.034em;
}

.nav .brand svg {
  width: 44px;
  height: 44px;
}

.nav__links {
  display: flex;
  gap: 4px;
  margin-inline: auto;
}

.nav__links a {
  padding: 8px 13px;
  border-radius: 999px;
  color: var(--ink-2);
  font-size: 0.9rem;
  font-weight: 520;
  letter-spacing: -0.011em;
  transition: color 180ms, background 180ms;
}

.nav__links a:hover {
  color: var(--ink);
  background: var(--paper-4);
}

.nav__cta {
  display: flex;
  align-items: center;
  gap: 6px;
}

@media (max-width: 900px) {
  .nav__links {
    display: none;
  }

  .nav__inner {
    justify-content: space-between;
  }
}

/* ---------------------------------------------------------------- aurora --- */

/* Three very soft blobs in the live accent, behind the hero. They are what
   makes the whole page feel like it is being tinted by the device. */
.aurora {
  position: absolute;
  inset: -20% -10% auto;
  height: 900px;
  z-index: 0;
  pointer-events: none;
  filter: blur(0.5px);
  opacity: 0.9;
}

.aurora i {
  position: absolute;
  border-radius: 50%;
  background: var(--live);
  filter: blur(90px);
  transition: background 620ms var(--ease);
  will-change: transform;
}

.aurora i:nth-child(1) {
  inset: 6% 52% auto auto;
  width: 46vw;
  height: 46vw;
  opacity: 0.11;
  animation: drift-a 26s ease-in-out infinite alternate;
}

.aurora i:nth-child(2) {
  inset: 22% auto auto 46%;
  width: 38vw;
  height: 38vw;
  opacity: 0.09;
  animation: drift-b 32s ease-in-out infinite alternate;
}

.aurora i:nth-child(3) {
  inset: 0 auto auto 14%;
  width: 26vw;
  height: 26vw;
  opacity: 0.07;
  animation: drift-c 22s ease-in-out infinite alternate;
}

@keyframes drift-a {
  to {
    transform: translate3d(5%, 5%, 0) scale(1.12);
  }
}

@keyframes drift-b {
  to {
    transform: translate3d(-7%, 4%, 0) scale(1.08);
  }
}

@keyframes drift-c {
  to {
    transform: translate3d(6%, -5%, 0) scale(1.16);
  }
}

/* A fine grain over the whole page. Cheap, and it stops the large flat areas
   of paper from banding on wide gradients. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

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

.hero {
  position: relative;
  z-index: 2;
  padding-top: clamp(48px, 6vw, 84px);
  padding-bottom: clamp(56px, 7vw, 104px);
  overflow: hidden;
}

.hero__grid {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
  gap: clamp(36px, 4.4vw, 64px);
  align-items: center;
}

@media (max-width: 1040px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 48px;
  }
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 14px 6px 10px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  color: var(--ink-2);
  font-size: 0.815rem;
  font-weight: 540;
  letter-spacing: -0.008em;
}

.chip__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--live);
  box-shadow: 0 0 0 3px var(--live-soft);
  transition: background 420ms var(--ease), box-shadow 420ms var(--ease);
}

.hero h1 {
  margin-top: 22px;
  font-size: clamp(2.15rem, 3.9vw, 3rem);
  letter-spacing: -0.036em;
  line-height: 1.05;
}

/* The provider name in the headline. Two stacked children so one can leave
   while the other arrives; the wrapper's inline-size is set from a measurement
   in scripts/device.js so the line reflows smoothly instead of jumping. */
.swap {
  position: relative;
  display: inline-block;
  vertical-align: baseline;
  color: var(--live);
  white-space: nowrap;
  transition: inline-size 420ms var(--ease), color 420ms var(--ease);

  /* clip-path, not overflow: hidden.
   *
   * Both clip the word that is leaving, but `overflow` on an inline-block moves
   * its baseline to the bottom margin edge — so the name sat visibly higher
   * than the words either side of it. clip-path is paint-only and leaves the
   * baseline alone. The 18% vertical slack is there so descenders in
   * "Perplexity" and "Copilot" are not shaved. */
  clip-path: inset(-18% -2px);
}

.swap__now,
.swap__was {
  display: inline-block;
  white-space: nowrap;
}

.swap__was {
  position: absolute;
  inset: 0 auto auto 0;
}

.swap[data-turning] .swap__now {
  animation: swap-in 420ms var(--ease) both;
}

.swap[data-turning] .swap__was {
  animation: swap-out 340ms var(--ease) both;
}

@keyframes swap-in {
  from {
    transform: translateY(0.42em);
    opacity: 0;
  }
}

@keyframes swap-out {
  to {
    transform: translateY(-0.42em);
    opacity: 0;
  }
}

/* Between the headline and the explanation: the live line. It is where the
   provider name morphs, so the sentence that changes is short and sits on its
   own — a name swapping in the middle of a paragraph would reflow three lines
   of body copy every few seconds. */
.hero__deck {
  margin-top: 20px;
  color: var(--ink);
  font-size: clamp(1.2rem, 1.9vw, 1.6rem);
  font-weight: 560;
  letter-spacing: -0.028em;
  line-height: 1.28;
}

.hero__sub {
  margin-top: 16px;
  max-width: 52ch;
  color: var(--ink-2);
  font-size: clamp(1.04rem, 1.4vw, 1.2rem);
  line-height: 1.6;
  letter-spacing: -0.012em;
  text-wrap: pretty;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 34px;
}

.hero__note {
  margin-top: 18px;
  color: var(--ink-3);
  font-size: 0.82rem;
  letter-spacing: -0.005em;
}

.facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  margin-top: 34px;
  padding-top: 24px;
  border-top: 1px solid var(--edge);
  list-style: none;
  padding-left: 0;
}

/* Not fine print. These three are the answer to "what is the catch", which a
   free extension that talks to nine paid services has to answer before
   anything else on the page matters. Still one plain row, just at a size that
   gets read rather than scanned past: ink instead of grey, and a tick large
   enough to carry the live accent. */
.facts li {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--ink);
  font-size: 0.97rem;
  font-weight: 570;
  letter-spacing: -0.018em;
}

.facts svg {
  width: 17px;
  height: 17px;
  color: var(--live);
  transition: color 420ms var(--ease);
}

/* ----------------------------------------------------- the browser frame --- */

.browser {
  position: relative;
  border: 1px solid var(--edge);
  border-radius: var(--r-xl);
  background: var(--paper-2);
  box-shadow: var(--lift-3);
  overflow: hidden;
}

.browser__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--edge-2);
  background: linear-gradient(var(--paper-2), var(--paper-3));
}

.browser__dots {
  display: flex;
  gap: 6px;
}

.browser__dots i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--paper-4);
  box-shadow: inset 0 0 0 1px rgb(20 24 34 / 6%);
}

.browser__url {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  height: 26px;
  padding: 0 12px;
  border-radius: 999px;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--edge);
  color: var(--ink-3);
  font-size: 0.74rem;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.browser__url svg {
  width: 11px;
  height: 11px;
  flex: none;
}

.browser__ext {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-4);
}

.browser__ext svg {
  width: 15px;
  height: 15px;
}

/* The toolbar button the panel hangs off. Pulses once per morph cycle so the
   eye is told where the thing lives. */
.browser__pin {
  position: relative;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 7px;
  background: var(--paper-4);
  color: var(--ink);
}

.browser__pin svg {
  width: 15px;
  height: 15px;
}

.browser__pin::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 10px;
  border: 2px solid var(--live);
  opacity: 0;
}

.browser__pin[data-ping]::after {
  animation: ping 900ms var(--ease);
}

@keyframes ping {
  0% {
    opacity: 0.65;
    transform: scale(0.86);
  }
  100% {
    opacity: 0;
    transform: scale(1.25);
  }
}

.browser__view {
  position: relative;
}

/* ----------------------------------------------- the faux page behind it --- */

.page {
  position: relative;
  padding: 26px 30px 30px;
  min-height: 356px;
  font-family: var(--serif);
}

.page__kicker {
  color: #c2410c;
  font-family: var(--sans);
  font-size: 0.63rem;
  font-weight: 660;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.page__title {
  margin-top: 9px;
  font-family: var(--sans);
  font-size: clamp(1.15rem, 1.9vw, 1.6rem);
  letter-spacing: -0.032em;
  color: #0b1220;
}

.page__by {
  margin-top: 7px;
  color: var(--ink-3);
  font-family: var(--sans);
  font-size: 0.72rem;
}

.page p.page__body {
  margin-top: 14px;
  color: #333b47;
  font-size: 0.845rem;
  line-height: 1.72;
  max-width: 46ch;
}

.page__figure {
  margin-top: 16px;
  height: 84px;
  max-width: 74%;
  border-radius: 10px;
  background: linear-gradient(118deg, #eef2f7, #e3e9f1 58%, #eaeef4);
}

.page__lines {
  margin-top: 18px;
  display: grid;
  gap: 9px;
  max-width: 62%;
}

.page__lines i {
  height: 7px;
  border-radius: 4px;
  background: var(--paper-4);
}

.page__lines i:nth-child(2) {
  width: 92%;
}

.page__lines i:nth-child(3) {
  width: 74%;
}

/* The device floats over the lower-right of the page, where the real one does. */
.stage {
  position: relative;
}

.stage__device {
  position: absolute;
  right: 16px;
  bottom: 16px;
  width: min(340px, 82%);
  z-index: 3;
}

@media (max-width: 560px) {
  /* The device stops floating and stacks under the article here, so the page
     no longer has to reserve room for it — min-height would just be a band of
     empty paper between the two. */
  .page {
    min-height: 0;
    padding: 20px 20px 4px;
  }

  .page__figure,
  .page__lines {
    display: none;
  }

  .stage__device {
    position: static;
    width: auto;
    margin: 18px 14px 16px;
  }
}

/* ------------------------------------------------------------- the device --- */

/* Everything below reproduces src/popup.css's composer shell for the panel that
   src/overlay/ renders. The palette comes from styles/device.css, which *is*
   src/lib/themes.css, so the only thing duplicated here is the geometry. */

.ac-device {
  position: relative;
  /* The extension's morph is 200ms and snaps inside a Shadow Root, because
     @property cannot be registered there. Here it is registered, so the tokens
     genuinely interpolate — and a little slower, because on a landing page the
     morph is the message rather than a side effect of a click. */
  --morph: 420ms;

  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font);
  overflow: hidden;
  box-shadow: var(--lift-3);
  transition:
    --bg var(--morph) ease,
    --surface var(--morph) ease,
    --border var(--morph) ease,
    --accent var(--morph) ease,
    --on-accent var(--morph) ease,
    --text var(--morph) ease,
    --muted var(--morph) ease,
    --radius var(--morph) ease,
    --glow var(--morph) ease;
}

/* Gemini's radial glow behind the composer, from popup.css. */
.ac-device__glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(
    120% 90% at 50% 0%,
    color-mix(in srgb, var(--accent) 22%, transparent) 0%,
    transparent 62%
  );
  opacity: var(--glow);
}

.ac-device > *:not(.ac-device__glow) {
  position: relative;
  z-index: 1;
}

.ac-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--sans);
}

.ac-head__brand {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.9rem;
  font-weight: 660;
  letter-spacing: -0.026em;
}

.ac-head__brand svg {
  width: 17px;
  height: 17px;
}

.ac-head__actions {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-left: auto;
  color: var(--muted);
  font-size: 0.72rem;
}

.ac-head__actions svg {
  width: 13px;
  height: 13px;
}

.ac-field {
  position: relative;
  min-height: 74px;
  font-size: 0.925rem;
  line-height: 1.5;
  letter-spacing: -0.008em;
}

.ac-msg {
  transition: transform 380ms var(--ease), opacity 380ms var(--ease);
}

.ac-msg[data-sending] {
  transform: translateY(-16px);
  opacity: 0;
}

.ac-caret {
  display: inline-block;
  width: 1.5px;
  height: 1.05em;
  margin-left: 1px;
  vertical-align: -0.16em;
  background: var(--accent);
  animation: blink 1.1s steps(1) infinite;
}

.ac-caret[hidden] {
  display: none;
}

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

/* A token pill, from src/popup.css. One rule serves both kinds: a template
   falls back to the provider accent (so it re-tints on every morph), and a tab
   sets --pill from its own favicon colour and keeps it. */
.ac-token {
  display: inline;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--pill-soft, color-mix(in srgb, var(--accent) 22%, transparent));
  box-shadow: inset 0 0 0 1px var(--pill-edge, color-mix(in srgb, var(--accent) 45%, transparent));
  color: var(--pill, var(--accent));
  font-weight: 600;
  white-space: nowrap;
}

/* On a pale ground the favicon-derived tint is too weak to read as text —
   color.js aims it at a dark panel. Darkened here, hue kept, exactly as the
   product does it. */
.ac-device[data-theme='light'] .ac-token {
  color: color-mix(in srgb, var(--pill, var(--accent)) 74%, #000);
}

/* A pill is picked, not typed, so it arrives whole. */
.ac-token[data-land] {
  animation: token-land 320ms var(--ease) both;
}

@keyframes token-land {
  from {
    opacity: 0;
    letter-spacing: -0.04em;
  }
}

.ac-placeholder {
  position: absolute;
  inset: 0;
  color: var(--muted);
  pointer-events: none;
  transition: opacity 200ms ease;
}

.ac-placeholder[data-off] {
  opacity: 0;
}

.ac-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--sans);
}

.ac-pick {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--muted);
}

.ac-pick .mark-slot {
  display: grid;
  place-items: center;
  transition: transform 380ms var(--ease), opacity 200ms ease;
}

.ac-pick[data-turning] .mark-slot {
  transform: scale(0.82);
  opacity: 0;
}

.ac-pick svg.chev {
  width: 11px;
  height: 11px;
}

.ac-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 9px;
  border-radius: 999px;
  background: color-mix(in srgb, currentColor 7%, transparent);
  color: var(--muted);
  font-size: 0.755rem;
  font-weight: 520;
  white-space: nowrap;
}

.ac-pill svg {
  width: 11px;
  height: 11px;
}

.ac-send {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  margin-left: auto;
  border-radius: 50%;
  background: var(--send-bg, var(--accent));
  color: var(--on-send, var(--on-accent));
  transition: transform 260ms var(--ease);
}

.ac-send svg {
  width: 15px;
  height: 15px;
}

.ac-send::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0;
}

.ac-send[data-fire] {
  animation: fire 460ms var(--ease);
}

.ac-send[data-fire]::after {
  animation: fire-ring 620ms var(--ease);
}

@keyframes fire {
  40% {
    transform: scale(0.9);
  }
  70% {
    transform: scale(1.07);
  }
}

@keyframes fire-ring {
  0% {
    opacity: 0.7;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(2.1);
  }
}

/* Brand colours for the marks, exactly as src/popup.css does it: a provider's
   logomark is its own colour in every list, whichever theme is showing. */
.mark-slot {
  display: inline-grid;
  place-items: center;
}

.mark-slot[data-mark='chatgpt'] { color: var(--mark-chatgpt); }
.mark-slot[data-mark='claude'] { color: var(--mark-claude); }
.mark-slot[data-mark='deepseek'] { color: var(--mark-deepseek); }
.mark-slot[data-mark='gemini'] { color: var(--mark-gemini); }
.mark-slot[data-mark='grok'] { color: var(--mark-grok); }
.mark-slot[data-mark='perplexity'] { color: var(--mark-perplexity); }
.mark-slot[data-mark='copilot'] { color: var(--mark-copilot); }
.mark-slot[data-mark='m365copilot'] { color: var(--mark-m365copilot); }
.mark-slot[data-mark='metaai'] { color: var(--mark-metaai); }

/* `.marks-scope` itself is declared in the generated styles/device.css, lifted
   straight out of themes.css so the nine brand colours have one home. */

/* ------------------------------------------------------------ provider rail --- */

.rail {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  justify-content: center;
  margin-top: 26px;
}

.rail__btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px 6px 9px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--paper-2);
  color: var(--ink-2);
  font-size: 0.765rem;
  font-weight: 540;
  letter-spacing: -0.011em;
  overflow: hidden;
  transition:
    border-color 220ms var(--ease),
    color 220ms var(--ease),
    transform 220ms var(--ease),
    box-shadow 220ms var(--ease);
}

.rail__btn:hover {
  transform: translateY(-1px);
  border-color: var(--ink-4);
  box-shadow: var(--lift-1);
}

.rail__btn[aria-pressed='true'] {
  border-color: var(--live-line);
  background: var(--paper-2);
  color: var(--ink);
  box-shadow: var(--lift-2);
}

/* The dwell timer, driven by the Web Animations API so it can be cancelled
   the instant somebody takes over. */
.rail__btn i {
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--live);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.rail__btn .mark-slot {
  width: 14px;
  height: 14px;
}

/* --------------------------------------------------------- the try device --- */

/* The second composer: bigger than the hero's, and waiting to be driven.
 *
 * --live-soft and --live-line are redeclared here on purpose. A custom property
 * that contains var() is substituted where it is *declared*, so the copies on
 * :root resolve against the hero's accent and would not follow this device.
 * Declaring them again on .try makes them resolve against this container's own
 * --live, which scripts/device.js publishes here rather than onto :root. */
.try {
  --live-soft: color-mix(in srgb, var(--live) 10%, transparent);
  --live-line: color-mix(in srgb, var(--live) 34%, transparent);

  display: grid;
  justify-items: center;
  gap: clamp(22px, 2.6vw, 32px);
}

.try__stage {
  width: 100%;
  max-width: 660px;
  padding: clamp(24px, 3vw, 42px);
  border: 1px solid var(--edge);
  border-radius: var(--r-xl);
  background:
    radial-gradient(120% 100% at 50% 0%, var(--live-soft), transparent 64%),
    var(--paper-2);
  box-shadow: var(--lift-2);
  transition: background 620ms var(--ease);
}

/* This rail is the control, not a caption, so it is a size up from the hero's. */
/* Capped so the nine wrap 5 and 4 rather than 6 and 3. */
.try .rail {
  margin-top: 0;
  max-width: 610px;
}

.try .rail__btn {
  padding: 8px 14px 8px 11px;
  font-size: 0.845rem;
}

.try .rail__btn .mark-slot {
  width: 16px;
  height: 16px;
}

/* --------------------------------------------------------------- how it works --- */

/* The sequence, happening. scripts/howto.js drives it; everything here is a
   resting state and a transition into it, keyed off one attribute per beat, so
   the timeline in the JS stays the only place the order lives. */
.how {
  display: grid;
  grid-template-columns: minmax(0, 1.14fr) minmax(0, 0.86fr);
  gap: clamp(32px, 4.5vw, 64px);
  align-items: center;
}

@media (max-width: 940px) {
  .how {
    grid-template-columns: minmax(0, 1fr);
    gap: 34px;
  }
}

/* `auto` is a real value to transition from here, which is what lets the panel
   grow by the height of the conversation without that height being written down
   anywhere. Set on the stage rather than the panel because the collapse happens
   on a descendant. */
.how__stage {
  position: relative;
  interpolate-size: allow-keywords;
}

.how__stage .page {
  min-height: 308px;
}

/* Below 560px the hero's device stops floating and stacks under the article, so
   the article stops reserving room for it. This one still floats — a panel
   arriving over the page is the whole sequence, and stacking it would say the
   opposite — so the page keeps its height and its lines here, and the panel
   takes the width it needs to stay legible. */
@media (max-width: 560px) {
  .how__stage .page {
    padding: 22px 22px 12px;
  }

  .how__stage .page__lines {
    display: grid;
  }

  .how__panel {
    width: min(304px, 84%);
  }
}

/* The keycaps sit over the page until the panel arrives, and they sit where it
   is about to land so that the eye is already there when it does. */
.how__keys {
  position: absolute;
  z-index: 4;
  top: 24%;
  right: 24%;
  display: flex;
  gap: 7px;
  transition:
    opacity 220ms var(--ease),
    transform 260ms var(--ease);
}

.how__keys kbd {
  min-width: 2.1em;
  padding: 7px 10px;
  font-size: 0.86rem;
  transition: transform 140ms var(--ease), box-shadow 140ms var(--ease);
}

.how__keys[data-press] kbd {
  transform: translateY(2px);
  box-shadow: none;
}

.how__keys[data-gone] {
  opacity: 0;
  transform: scale(0.92);
}

/* The panel. Anchored top-right and growing downward, which is where the real
   one sits and which way the real one grows. */
.how__panel {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 3;
  width: min(304px, 62%);
  transform-origin: 100% 0;
  transform: scale(0.95) translateY(-8px);
  opacity: 0;
  /* Replaces the registered-property morph inherited from .ac-device. Nothing
     to lose: this panel is fixed to one provider and never changes palette. */
  transition:
    transform 440ms var(--ease),
    opacity 280ms var(--ease);
}

.how__panel[data-in] {
  transform: none;
  opacity: 1;
}

/* Composing and conversing are the same panel: on send the composer collapses
   to nothing and the conversation takes the room it leaves. Two halves of one
   movement, so they share a duration. */
.how__composer,
.how__chat {
  overflow: hidden;
  transition:
    height 480ms var(--ease),
    opacity 260ms var(--ease);
}

.how__composer {
  height: auto;
}

.how__chat {
  height: 0;
  opacity: 0;
}

.how__panel[data-view='chat'] .how__composer {
  height: 0;
  opacity: 0;
}

.how__panel[data-view='chat'] .how__chat {
  height: auto;
  opacity: 1;
}

/* The head goes with it. Both of these are the real panel's behaviour: a way
   back out, and the provider's name once the panel is theirs. */
.how__back,
.how__title {
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  white-space: nowrap;
  transition:
    max-width 320ms var(--ease),
    opacity 200ms var(--ease);
}

.how__back {
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
}

.how__title {
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
}

.how__panel[data-view='chat'] .how__back {
  max-width: 20px;
  opacity: 1;
}

.how__panel[data-view='chat'] .how__title {
  max-width: 8em;
  opacity: 1;
  padding-left: 8px;
}

/* Three words and three icons is more than a 300px head can hold. */
.how__panel[data-view='chat'] .ac-head__actions > span {
  max-width: 0;
  opacity: 0;
  overflow: hidden;
}

.how__panel .ac-head__actions > span {
  max-width: 6em;
  transition:
    max-width 320ms var(--ease),
    opacity 200ms var(--ease);
}

/* The conversation itself, on the provider's own ground rather than the
   panel's, because in the real thing this area is their page. */
.how__chat > * {
  margin: 0 12px;
}

.how__ask {
  --pill-soft: transparent;
  --pill-edge: transparent;

  margin-top: 6px;
  /* fit-content, not a percentage: the bubble should be exactly as wide as the
     sentence, pinned right, the way a sent message is. And one line, because
     wrapping makes the sentence and the reference it carries read as two
     separate things when the point is that they arrived together. */
  width: fit-content;
  max-width: 100%;
  margin-left: auto;
  padding: 7px 11px;
  border-radius: 13px 13px 4px 13px;
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--text);
  font-size: 11.5px;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
}

.how__reply {
  display: grid;
  grid-template-columns: 15px minmax(0, 1fr);
  align-items: start;
  gap: 10px;
  padding: 15px 0 14px;
}

/* The answer, arriving a line at a time. Bars rather than sentences: this is a
   picture of a reply, and putting invented prose in it would only ask to be
   read. */
.how__lines {
  display: grid;
  gap: 7px;
  align-content: start;
}

.how__lines i {
  height: 7px;
  border-radius: 4px;
  background: color-mix(in srgb, var(--text) 13%, transparent);
  transform-origin: 0 50%;
  transform: scaleX(0);
}

.how__panel[data-view='chat'] .how__lines i {
  animation: reply-line 380ms var(--ease) forwards;
}

.how__lines i:nth-child(1) { animation-delay: 300ms; }
.how__lines i:nth-child(2) { animation-delay: 480ms; width: 94%; }
.how__lines i:nth-child(3) { animation-delay: 660ms; }
.how__lines i:nth-child(4) { animation-delay: 840ms; width: 58%; }

@keyframes reply-line {
  to {
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .how__keys,
  .how__panel,
  .how__composer,
  .how__chat,
  .how__back,
  .how__title {
    transition: none;
  }

  .how__panel[data-view='chat'] .how__lines i {
    animation: none;
    transform: none;
  }
}

/* The three labels, lighting up with the beat they belong to. */
.steps {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps li {
  counter-increment: step;
  position: relative;
  padding: clamp(16px, 1.8vw, 22px) 0 clamp(16px, 1.8vw, 22px) 46px;
  border-left: 2px solid var(--edge);
  color: var(--ink-3);
  font-size: 0.93rem;
  line-height: 1.55;
  transition: color 320ms var(--ease), border-color 320ms var(--ease);
}

.steps li::before {
  content: counter(step);
  position: absolute;
  top: clamp(16px, 1.8vw, 22px);
  left: -13px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--paper-3);
  box-shadow: inset 0 0 0 1.5px var(--edge);
  color: var(--ink-3);
  font-size: 0.7rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  transition:
    background 320ms var(--ease),
    box-shadow 320ms var(--ease),
    color 320ms var(--ease);
}

.steps b {
  display: block;
  margin-bottom: 4px;
  color: var(--ink-2);
  font-size: 1.01rem;
  font-weight: 580;
  letter-spacing: -0.024em;
  transition: color 320ms var(--ease);
}

.steps li[data-active] {
  border-left-color: var(--live);
  color: var(--ink-2);
}

.steps li[data-active]::before {
  background: var(--ink);
  box-shadow: none;
  color: #fff;
}

.steps li[data-active] b {
  color: var(--ink);
}

@media (max-width: 940px) {
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-flow: column;
    gap: 18px;
  }
}

@media (max-width: 700px) {
  .steps {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-flow: row;
    gap: 0;
  }
}

/* ------------------------------------------------------------- showcase --- */

/* Prompts and tabs each get a section of this shape: copy and worked examples
   on one side, two real screenshots stacked on the other. The two screenshots
   are the loop — one shows setting the thing up, one shows using it — and a
   single image of either half never made the feature land. */
.showcase {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.88fr);
  gap: clamp(32px, 4.5vw, 72px);
  align-items: center;
}

/* The tabs section mirrors the prompts one, so the two do not read as the same
   slide twice. */
.showcase--flip .showcase__copy {
  order: 2;
}

.showcase--flip .plate,
.showcase--flip .showcase__art figcaption {
  margin-left: 0;
  margin-right: auto;
}

@media (max-width: 940px) {
  .showcase {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px;
  }

  .showcase--flip .showcase__copy {
    order: 0;
  }

  .plate,
  .showcase__art figcaption {
    margin-inline: 0;
  }
}

.showcase__copy .lede + .lede {
  margin-top: 14px;
}

.showcase__art {
  display: grid;
  gap: clamp(14px, 1.8vw, 22px);
}

.showcase__art figure {
  margin: 0;
}

/* Capped, because these are 2x captures of a small panel: the picker shot is
   800px of real pixels, so displaying it 700 CSS px wide asks for 1400 on a
   retina screen and gets 800. At 460 it is inside its own resolution. */
.plate {
  display: flex;
  justify-content: center;
  max-width: 520px;
  margin-left: auto;
  padding: clamp(14px, 1.8vw, 24px);
  border: 1px solid var(--edge);
  border-radius: var(--r-xl);
  background:
    radial-gradient(120% 100% at 50% 0%, var(--live-soft), transparent 62%),
    var(--paper-2);
  box-shadow: var(--lift-2);
}

.plate img {
  width: 100%;
  height: auto;
  border-radius: var(--r-md);
  box-shadow: var(--lift-1);
}

.showcase__art figcaption {
  margin-top: 10px;
  max-width: 520px;
  margin-left: auto;
  padding-left: 4px;
  color: var(--ink-3);
  font-size: 0.85rem;
}

/* The worked examples. A name, what it does, and where it applies. */
.examples {
  margin: clamp(26px, 3vw, 36px) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--edge);
}

.examples li {
  padding: 15px 0;
  border-bottom: 1px solid var(--edge);
  color: var(--ink-2);
  font-size: 0.92rem;
  line-height: 1.55;
}

.examples b {
  display: block;
  margin-bottom: 3px;
  color: var(--ink);
  font-size: 0.97rem;
  font-weight: 580;
  letter-spacing: -0.018em;
}

.examples b .mono {
  font-size: 0.95em;
}

/* Where a prompt is pinned. Quiet, because it is the qualifier and not the
   headline, but tinted so it reads as a property of the thing above it. */
.scope {
  display: inline-flex;
  align-items: center;
  margin-top: 8px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--live-soft);
  box-shadow: inset 0 0 0 1px var(--live-line);
  color: color-mix(in srgb, var(--live) 72%, var(--ink));
  font-size: 0.76rem;
  font-weight: 540;
  transition: background 420ms var(--ease), box-shadow 420ms var(--ease),
    color 420ms var(--ease);
}

/* -------------------------------------------------------------- surfaces --- */

.tabs {
  display: inline-flex;
  position: relative;
  gap: 2px;
  padding: 4px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--paper-2);
  box-shadow: var(--lift-1);
}

.tabs__ind {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 0;
  border-radius: 999px;
  background: var(--ink);
  transition: transform 340ms var(--ease), width 340ms var(--ease);
  will-change: transform, width;
}

.tabs button {
  position: relative;
  z-index: 1;
  padding: 8px 16px;
  border-radius: 999px;
  color: var(--ink-2);
  font-size: 0.865rem;
  font-weight: 540;
  letter-spacing: -0.013em;
  white-space: nowrap;
  transition: color 240ms var(--ease);
}

.tabs button[aria-selected='true'] {
  color: #fff;
}

.surface {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 60px);
  align-items: center;
  margin-top: clamp(32px, 4vw, 52px);
}

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

.surface__panel {
  display: none;
}

.surface__panel[data-current] {
  display: contents;
}

.surface__copy > h3 {
  font-size: clamp(1.35rem, 2.2vw, 1.85rem);
  letter-spacing: -0.03em;
}

.surface__copy > p {
  margin-top: 14px;
  color: var(--ink-2);
  font-size: 0.965rem;
  line-height: 1.62;
}

.surface__meta {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--edge);
  display: grid;
  gap: 10px;
}

.surface__meta div {
  display: flex;
  gap: 12px;
  font-size: 0.855rem;
}

.surface__meta dt {
  flex: none;
  width: 92px;
  color: var(--ink-3);
}

.surface__meta dd {
  margin: 0;
  color: var(--ink-2);
}

.surface__art {
  padding: clamp(20px, 3vw, 40px);
  border: 1px solid var(--edge);
  border-radius: var(--r-xl);
  background:
    radial-gradient(120% 100% at 50% 0%, var(--live-soft), transparent 62%),
    var(--paper-2);
  box-shadow: var(--lift-2);
}

/* ------------------------------------------------- the surface diagrams ---
 *
 * Drawn in HTML rather than SVG, and not for novelty. lib/surface-art.js draws
 * these as 64x44 line icons, which is right at the size the options page uses
 * them and wrong at 500px — an 0.85px stroke becomes a seven-pixel slab and a
 * toolbar dot becomes a plate. These are the same four ideas at the size this
 * page needs, in the same frame language as the hero, so the section reads as
 * a continuation of it.
 *
 * Every variant is one shape moved: `.diag__spot` is where a conversation
 * lands. Fixed aspect ratio, so switching tabs never jumps the layout.
 */
.diag {
  position: relative;
  aspect-ratio: 16 / 10;
  border: 1px solid var(--edge);
  border-radius: 14px;
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  container-type: inline-size;
}

.diag__chrome {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border-bottom: 1px solid var(--edge-2);
  background: var(--paper-3);
}

.diag__dots {
  display: flex;
  gap: 3px;
}

.diag__dots i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--paper-4);
}

.diag__url {
  flex: 1;
  height: 9px;
  border-radius: 999px;
  background: var(--paper-2);
  box-shadow: inset 0 0 0 1px var(--edge);
}

.diag__pin {
  flex: none;
  width: 11px;
  height: 11px;
  border-radius: 3px;
  background: var(--live);
  opacity: 0.85;
}

/* The new tab's strip. Only that variant has one. */
.diag__tabs {
  flex: none;
  display: flex;
  gap: 3px;
  padding: 5px 9px 0;
  background: var(--paper-3);
}

.diag__tabs i {
  height: 11px;
  flex: 1;
  max-width: 62px;
  border-radius: 4px 4px 0 0;
  background: var(--paper-4);
}

.diag__tabs i.on {
  background: var(--live);
  opacity: 0.85;
}

.diag__view {
  position: relative;
  flex: 1;
  padding: 12px;
}

/* The page underneath — five rules standing in for whatever you were reading. */
.diag__page {
  display: grid;
  gap: 7px;
  width: 58%;
}

.diag__page i {
  height: 6px;
  border-radius: 3px;
  background: var(--paper-4);
}

.diag__page i:first-child {
  height: 10px;
  width: 76%;
  background: var(--edge);
}

.diag__page i:nth-child(3) {
  width: 88%;
}

.diag__page i:nth-child(5) {
  width: 64%;
}

/* Where a send lands. Every variant only moves this. */
.diag__spot {
  position: absolute;
  border-radius: 8px;
  background: var(--live);
  opacity: 0.9;
  transition: background 420ms var(--ease);
}

/* A hairline across the top of the spot, standing in for its own header. */
.diag__spot span {
  position: absolute;
  inset: 22% 12% auto 12%;
  height: 1px;
  background: var(--paper-2);
  opacity: 0.55;
}

.diag--overlay .diag__spot {
  inset: auto 12px 12px auto;
  width: 46%;
  height: 62%;
}

.diag--tab .diag__page {
  display: none;
}

/* A new tab has no page behind it: it has the box, and the last six things you
   asked. Both, or the frame reads as empty. */
.diag--tab .diag__spot {
  inset: 26% 16% auto 16%;
  height: 14%;
  border-radius: 999px;
}

.diag--tab .diag__spot span {
  display: none;
}

.diag__cards {
  display: none;
}

.diag--tab .diag__cards {
  position: absolute;
  inset: 48% 16% 10% 16%;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  gap: 5px;
}

.diag--tab .diag__cards i {
  border-radius: 4px;
  background: var(--paper-3);
  box-shadow: inset 0 0 0 1px var(--edge);
}

.surface__art[data-in] .diag--tab .diag__cards i {
  animation: art-land 520ms var(--ease) both;
}

.diag--tab .diag__cards i:nth-child(2) { animation-delay: 60ms; }
.diag--tab .diag__cards i:nth-child(3) { animation-delay: 120ms; }
.diag--tab .diag__cards i:nth-child(4) { animation-delay: 180ms; }
.diag--tab .diag__cards i:nth-child(5) { animation-delay: 240ms; }
.diag--tab .diag__cards i:nth-child(6) { animation-delay: 300ms; }

.diag--panel .diag__spot {
  inset: 0 0 0 auto;
  width: 34%;
  border-radius: 0;
}

.diag--panel .diag__page {
  width: 52%;
}

/* The parent recedes, so the new window reads as separate rather than nested. */
.diag--window .diag__chrome,
.diag--window .diag__page {
  opacity: 0.4;
}

.diag--window .diag__spot {
  inset: 18% 8% 14% 34%;
  border-radius: 10px;
  box-shadow: var(--lift-3);
}

/* Drawn on entry: the region lands rather than appearing. */
.surface__art[data-in] .diag__spot,
.surface__art[data-in] .diag__tabs i.on,
.surface__art[data-in] .diag__pin {
  animation: art-land 520ms var(--ease) both;
}

/* ------------------------------------------------------------- new tab --- */

.newtab {
  display: grid;
  gap: clamp(28px, 4vw, 48px);
}

.newtab__frame img {
  width: 100%;
  height: auto;
}

/* --------------------------------------------------------------- bento --- */

.bento {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 1.7vw, 22px);
}

@media (max-width: 940px) {
  .bento {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 620px) {
  .bento {
    grid-template-columns: minmax(0, 1fr);
  }
}

.cell {
  display: flex;
  flex-direction: column;
  padding: 20px;
  border: 1px solid var(--edge);
  border-radius: var(--r-lg);
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  transition: box-shadow 320ms var(--ease), transform 320ms var(--ease);
}

.cell:hover {
  transform: translateY(-2px);
  box-shadow: var(--lift-2);
}

/* Four cards in a three-column grid: three across, then one across the whole
   row. Spanning two would leave a hole where a fifth card is not. */
.cell--full {
  grid-column: 1 / -1;
}

.cell--full .cell__art {
  height: 132px;
}

.cell__art {
  position: relative;
  height: 158px;
  margin-bottom: 18px;
  border: 1px solid var(--edge-2);
  border-radius: var(--r-md);
  background: var(--paper-3);
  overflow: hidden;
}

.cell h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 1.01rem;
  letter-spacing: -0.024em;
}

.cell h3 .cell p {
  margin-top: 8px;
  color: var(--ink-2);
  font-size: 0.89rem;
  line-height: 1.6;
}

/* The little mock UIs inside the bento cards. Shared bits first. */
.mock {
  position: absolute;
  inset: 0;
  padding: 14px;
  font-size: 0.76rem;
  color: var(--ink-2);
}

/* Attach page: paragraph lines collapse into four markdown lines. */
.mock--attach .mock__lines {
  display: grid;
  gap: 6px;
}

.mock--attach .mock__lines i {
  height: 6px;
  border-radius: 3px;
  background: var(--paper-4);
  transition: width 480ms var(--ease), background 480ms var(--ease);
}

.mock--attach[data-run] .mock__lines i:nth-child(odd) {
  width: 46%;
  background: var(--live);
  opacity: 0.55;
}

.mock--attach[data-run] .mock__lines i:nth-child(even) {
  width: 78%;
}

/* Region shot: a dashed crop rect draws itself over a dimmed page. */
.mock--shot svg {
  width: 100%;
  height: 100%;
}

.mock--shot .crop {
  fill: none;
  stroke: var(--live);
  stroke-width: 1.4;
  stroke-dasharray: 5 4;
  stroke-dashoffset: 220;
}

.mock--shot[data-run] .crop {
  animation: draw 900ms var(--ease) 180ms forwards;
}

@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

.mock--shot .scrim {
  fill: #14161a;
  opacity: 0;
  transition: opacity 500ms var(--ease);
}

.mock--shot[data-run] .scrim {
  opacity: 0.28;
}

/* Selection actions: a highlight sweeps a sentence, then the bubble lands. */
.mock--select .sentence {
  font-family: var(--serif);
  font-size: 0.79rem;
  line-height: 1.62;
  color: #333b47;
  background: linear-gradient(var(--live-soft), var(--live-soft)) no-repeat;
  background-size: 0% 100%;
  transition: background-size 700ms var(--ease);
  box-decoration-break: clone;
}

.mock--select[data-run] .sentence {
  background-size: 100% 100%;
}

.mock--select .bubble {
  display: inline-flex;
  gap: 5px;
  margin-top: 10px;
  padding: 5px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--paper-2);
  box-shadow: var(--lift-2);
  transform: scale(0.9) translateY(4px);
  opacity: 0;
  transition: transform 380ms var(--ease), opacity 380ms var(--ease);
}

.mock--select[data-run] .bubble {
  transform: none;
  opacity: 1;
  transition-delay: 620ms;
}

.bubble span {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--paper-3);
  font-size: 0.7rem;
  font-weight: 540;
}

/* Three small tiles for the odds and ends: a shortcut, the recent cards, the
   two schemes. Each one is a picture and a label rather than a label alone,
   which is what the old version of this card was. */
.mock--tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px 8px;
  border-radius: 10px;
  background: var(--paper-2);
  box-shadow: inset 0 0 0 1px var(--edge-2);
  text-align: center;
}

.tile__art {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 34px;
}

.tile__label {
  color: var(--ink-2);
  font-size: 0.7rem;
  line-height: 1.35;
  letter-spacing: -0.006em;
}

/* Six little cards, for the six chats the new tab remembers. */
.tile__art i {
  width: 9px;
  height: 12px;
  border-radius: 2px;
  background: var(--live);
  opacity: 0.28;
}

.mock--tiles[data-run] .tile__art i {
  animation: tile-cards 2.6s var(--ease) infinite;
}

.tile__art i:nth-child(2) { animation-delay: 0.1s; }
.tile__art i:nth-child(3) { animation-delay: 0.2s; }
.tile__art i:nth-child(4) { animation-delay: 0.3s; }
.tile__art i:nth-child(5) { animation-delay: 0.4s; }
.tile__art i:nth-child(6) { animation-delay: 0.5s; }

@keyframes tile-cards {
  0%, 60%, 100% { opacity: 0.28; }
  20% { opacity: 0.85; }
}

/* A sun and a moon, because "light and dark" is two shapes. */
.tile__art em {
  width: 14px;
  height: 14px;
  border-radius: 50%;
}

.sun {
  background: var(--live);
  opacity: 0.85;
}

.moon {
  background: var(--ink);
  box-shadow: inset 4px 0 0 var(--paper-2);
}

/* The tiles are a third the width, so their keycaps are smaller. */
.tile__art.keys kbd {
  transition: transform 120ms var(--ease), box-shadow 120ms var(--ease);
  min-width: 2em;
  padding: 5px 7px;
  font-size: 0.78rem;
}

.mock--tiles[data-run] .keys kbd:last-child {
  animation: press 1.5s var(--ease) infinite;
}

@keyframes press {
  0%,
  70%,
  100% {
    transform: none;
  }
  8%,
  20% {
    transform: translateY(2px);
    box-shadow: none;
  }
}

/* --------------------------------------------------------------- privacy --- */

.privacy {
  text-align: center;
}

.route {
  max-width: 720px;
  margin: clamp(36px, 4.5vw, 56px) auto 0;
}

.route svg {
  width: 100%;
  height: auto;
}

.route .node {
  fill: var(--paper-2);
  stroke: var(--edge);
  stroke-width: 1;
}

.route .node-label {
  fill: var(--ink);
  font: 600 8.5px var(--sans);
  letter-spacing: -0.02em;
}

.route .node-sub {
  fill: var(--ink-3);
  font: 500 6.5px var(--sans);
}

.route .wire {
  fill: none;
  stroke: var(--live);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
}

.route[data-in] .wire {
  animation: draw 900ms var(--ease) 200ms forwards;
}

.route .ghost {
  fill: none;
  stroke: var(--ink-4);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

/* The riser only exists to point at the empty box, so it is the faintest thing
   in the drawing. */
.route .riser {
  fill: none;
  stroke: var(--ink-4);
  stroke-width: 1;
  stroke-dasharray: 2 3;
  opacity: 0.7;
}

.route__note {
  margin-top: 22px;
  color: var(--ink-3);
  font-size: 0.875rem;
}

.route .ghost-label {
  fill: var(--ink-3);
  font: 500 7.5px var(--sans);
}

.route .strike {
  stroke: #cd2b31;
  stroke-width: 1.3;
  stroke-linecap: round;
  opacity: 0.75;
  stroke-dasharray: 90;
  stroke-dashoffset: 90;
}

.route[data-in] .strike {
  animation: draw 520ms var(--ease) 1000ms forwards;
}

.route .arrow {
  fill: var(--live);
}

.zeros {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 20px);
  margin-top: clamp(36px, 4vw, 52px);
}

@media (max-width: 700px) {
  .zeros {
    grid-template-columns: minmax(0, 1fr);
  }
}

.zero {
  padding: 22px 18px;
  border: 1px solid var(--edge);
  border-radius: var(--r-lg);
  background: var(--paper-2);
  box-shadow: var(--lift-1);
}

.zero b {
  display: block;
  font-size: clamp(2rem, 3.4vw, 2.7rem);
  font-weight: 640;
  letter-spacing: -0.05em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.zero span {
  display: block;
  margin-top: 8px;
  color: var(--ink-2);
  font-size: 0.875rem;
}

/* ------------------------------------------------------------- new tab --- */

/* Two real captures of the same box, one per mode, stacked. Crossfading them is
   the whole trick: they differ only in the lit pill and the focus ring, so the
   wordmark and the cards underneath do not appear to move at all. */
.newtab__modes {
  position: relative;
}

.newtab__modes img {
  display: block;
  width: 100%;
  height: auto;
}

.newtab__mode {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 260ms var(--ease);
}

.newtab__modes[data-mode='search'] .newtab__mode {
  opacity: 1;
}

/* The Tab key, going down.
 *
 * Sitting on top of the one in the screenshot, which is why the numbers are
 * percentages of the shot rather than pixels: they came from measuring
 * `.mode-hint kbd` in the running extension, so they cannot drift from what the
 * capture actually contains. tools/site-shots.mjs prints them; rerun
 * `npm run site:shots` if the new tab's layout ever changes.
 *
 * A tint and a ring rather than an opaque cap with its own "Tab" in it: the
 * label is already there in the pixels underneath, and matching its font at a
 * size that changes with the frame width is a fight with nothing to win.
 */
.newtab__key {
  position: absolute;
  left: 56.418%;
  top: 36.489%;
  width: 2.207%;
  height: 2.813%;
  border-radius: 6px;
  background: color-mix(in srgb, var(--live) 16%, transparent);
  box-shadow:
    inset 0 0 0 1.5px var(--live),
    0 0 0 4px color-mix(in srgb, var(--live) 12%, transparent);
  opacity: 0;
  transform: scale(1);
  transition:
    opacity 130ms var(--ease),
    transform 130ms var(--ease);
}

.newtab__modes[data-press] .newtab__key {
  opacity: 1;
  transform: scale(0.88);
}

@media (prefers-reduced-motion: reduce) {
  .newtab__mode,
  .newtab__key {
    transition: none;
  }
}

/* ------------------------------------------------------------- install --- */

.install {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 26px);
  counter-reset: install;
}

@media (max-width: 760px) {
  .install {
    grid-template-columns: minmax(0, 1fr);
  }
}

.install > li {
  counter-increment: install;
  list-style: none;
  padding: 24px;
  border: 1px solid var(--edge);
  border-radius: var(--r-lg);
  background: var(--paper-2);
  box-shadow: var(--lift-1);
}

.install > li::before {
  content: counter(install);
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  margin-bottom: 14px;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  font-size: 0.73rem;
  font-weight: 650;
}

.install h3 {
  font-size: 1.02rem;
  letter-spacing: -0.024em;
}

.install p {
  margin-top: 8px;
  color: var(--ink-2);
  font-size: 0.9rem;
}

.install code {
  padding: 2px 7px;
  border: 1px solid var(--edge);
  border-radius: 6px;
  background: var(--paper);
  font-family: var(--mono);
  font-size: 0.8rem;
}

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

.faq {
  max-width: 820px;
  margin-inline: auto;
  border-top: 1px solid var(--edge);
}

.faq details {
  border-bottom: 1px solid var(--edge);
}

.faq summary {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 20px 4px;
  cursor: pointer;
  font-size: 1.02rem;
  font-weight: 560;
  letter-spacing: -0.02em;
  list-style: none;
}

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

.faq summary::after {
  content: '';
  flex: none;
  width: 11px;
  height: 11px;
  margin-left: auto;
  margin-top: 7px;
  border-right: 1.6px solid var(--ink-2);
  border-bottom: 1.6px solid var(--ink-2);
  transform: rotate(45deg);
  transition: transform 260ms var(--ease);
}

.faq details[open] summary::after {
  transform: rotate(-135deg);
}

.faq details p {
  padding: 0 40px 22px 4px;
  color: var(--ink-2);
  font-size: 0.93rem;
  line-height: 1.68;
}

/* -------------------------------------------------------------- last CTA --- */

.last {
  position: relative;
  overflow: hidden;
  text-align: center;
}

.last h2 {
  font-size: clamp(2.1rem, 5vw, 3.4rem);
  letter-spacing: -0.042em;
}

.last .hero__cta {
  justify-content: center;
}

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

.footer {
  border-top: 1px solid var(--edge);
  padding-block: 52px 40px;
  background: var(--paper-3);
}

.footer__top {
  display: flex;
  flex-wrap: wrap;
  gap: 32px 56px;
  justify-content: space-between;
}

.footer__cols {
  display: flex;
  flex-wrap: wrap;
  gap: 32px 56px;
}

.footer__col {
  display: grid;
  gap: 9px;
  align-content: start;
}

.footer__col a {
  color: var(--ink-2);
  font-size: 0.885rem;
  transition: color 180ms;
}

.footer__col a:hover {
  color: var(--ink);
}

.footer__fine {
  margin-top: 44px;
  padding-top: 24px;
  border-top: 1px solid var(--edge);
  color: var(--ink-3);
  font-size: 0.775rem;
  line-height: 1.7;
  max-width: 80ch;
}

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

/* Set by scripts/site.js only when IntersectionObserver is available, so a
   browser without it — or with JS off — gets the page fully visible rather than
   a blank sheet. */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 620ms var(--ease),
    transform 620ms var(--ease);
  transition-delay: var(--stagger, 0ms);
}

[data-reveal][data-in] {
  opacity: 1;
  transform: none;
}

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

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

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }

  .aurora i {
    animation: none;
  }

  [data-reveal] {
    opacity: 1;
    transform: none;
  }

  .ac-caret {
    animation: none;
  }
}
