/* EB Garamond (SIL OFL 1.1, see fonts/OFL-EBGaramond.txt), subset to Latin, weights 400-800. */
@font-face {
  font-family: "EB Garamond";
  src: url("/static/fonts/EBGaramond-latin.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;

  --root-color-bg: rgb(15, 10, 10);
  --page-max-width: 72rem;
  --radius-sm: 0.75rem;
  --radius-md: 1rem;
  --radius-lg: 1.5rem;
  --radius-pill: 9999px;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --font-body:
    "Helvetica Neue", Helvetica, "Segoe UI", Arial, system-ui, sans-serif;
  --font-display:
    "EB Garamond", Garamond, "Hoefler Text", Baskerville, Georgia, serif;
  --font-mono:
    ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas,
    "Liberation Mono", "Courier New", monospace;
  --color-bg: color-mix(in srgb, var(--root-color-bg) 4%, white);
  --color-bg-accent: color-mix(in srgb, var(--root-color-bg) 12%, white);
  --color-surface: color-mix(in srgb, var(--root-color-bg) 6%, white 94%);
  --color-surface-strong: color-mix(in srgb, var(--root-color-bg) 2%, white);
  --color-surface-muted: color-mix(in srgb, var(--root-color-bg) 8%, white);
  --color-border: color-mix(in srgb, var(--root-color-bg) 18%, white);
  --color-border-strong: color-mix(in srgb, var(--root-color-bg) 26%, white);
  --color-thumbnail-placeholder-base: color-mix(
    in srgb,
    var(--root-color-bg) 12%,
    white 88%
  );
  --color-thumbnail-placeholder-glint: color-mix(
    in srgb,
    var(--root-color-bg) 3%,
    white 97%
  );
  --thumbnail-placeholder-glint-opacity: 0.8;
  --color-text: color-mix(in srgb, var(--root-color-bg) 18%, black);
  --color-text-muted: color-mix(in srgb, var(--root-color-bg) 60%, white 40%);
  /* Running copy: a step softer than headings, well above muted text. */
  --color-text-body: color-mix(in srgb, var(--color-text) 84%, var(--color-bg));
  --color-accent: color-mix(in srgb, var(--root-color-bg) 60%, #939393 40%);
  --color-accent-strong: color-mix(
    in srgb,
    var(--root-color-bg) 72%,
    #2b2b2b 28%
  );
  --color-accent-contrast: color-mix(in srgb, var(--root-color-bg) 4%, white);
  --color-focus-ring: color-mix(in srgb, var(--root-color-bg) 28%, transparent);
  --color-selection: color-mix(in srgb, var(--root-color-bg) 18%, transparent);
  --shadow-sm: 0 1px 2px color-mix(in srgb, var(--root-color-bg) 12%, black 8%);
  --shadow-md: 0 12px 30px
    color-mix(in srgb, var(--root-color-bg) 10%, black 5%);
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --color-bg: color-mix(in srgb, var(--root-color-bg) 10%, #0d0d0f 90%);
    --color-bg-accent: color-mix(
      in srgb,
      var(--root-color-bg) 16%,
      #131315 84%
    );
    --color-surface: color-mix(in srgb, var(--root-color-bg) 14%, #171719 86%);
    --color-surface-strong: color-mix(
      in srgb,
      var(--root-color-bg) 18%,
      #1b1b1d 82%
    );
    --color-surface-muted: color-mix(
      in srgb,
      var(--root-color-bg) 20%,
      #212123 80%
    );
    --color-border: color-mix(in srgb, var(--root-color-bg) 24%, #323235 76%);
    --color-border-strong: color-mix(
      in srgb,
      var(--root-color-bg) 30%,
      #434347 70%
    );
    --color-thumbnail-placeholder-base: color-mix(
      in srgb,
      var(--root-color-bg) 18%,
      #212123 82%
    );
    --color-thumbnail-placeholder-glint: color-mix(
      in srgb,
      var(--root-color-bg) 22%,
      #b0b0b0 78%
    );
    --thumbnail-placeholder-glint-opacity: 0.38;
    --color-text: color-mix(in srgb, var(--root-color-bg) 12%, #f2f2f2 88%);
    --color-text-muted: color-mix(
      in srgb,
      var(--root-color-bg) 18%,
      #d6d6d6 82%
    );
    /* Dark muted text is already close to full, so soften copy less. */
    --color-text-body: color-mix(
      in srgb,
      var(--color-text) 90%,
      var(--color-bg)
    );
    --color-accent: color-mix(in srgb, var(--root-color-bg) 20%, #eeeeee 80%);
    --color-accent-strong: color-mix(
      in srgb,
      var(--root-color-bg) 50%,
      #e2e2e2 50%
    );
    --color-accent-contrast: color-mix(
      in srgb,
      var(--root-color-bg) 14%,
      #1a1a1a 86%
    );
    --color-focus-ring: color-mix(
      in srgb,
      var(--root-color-bg) 36%,
      transparent
    );
    --color-selection: color-mix(
      in srgb,
      var(--root-color-bg) 28%,
      transparent
    );
    --shadow-sm: 0 1px 2px
      color-mix(in srgb, var(--root-color-bg) 8%, black 92%);
    --shadow-md: 0 18px 48px
      color-mix(in srgb, var(--root-color-bg) 12%, black 88%);
  }
}

html {
  background:
    radial-gradient(circle at top, var(--color-bg-accent), transparent 40%),
    var(--color-bg);
}

/* Follow the text size people choose on iPhone and iPad (Settings >
   Display & Brightness > Text Size, or Accessibility > Larger Text).
   Safari only applies it to pages that use Apple's body text style. Sizes
   on this site are in rem, so everything scales from this. */
@supports (font: -apple-system-body) {
  html {
    font: -apple-system-body;
  }
}

body {
  min-height: 100vh;
  margin: 0;
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  /* At very large text sizes, long words wrap instead of running off. */
  overflow-wrap: break-word;
}

a {
  color: var(--color-accent);
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.18em;
}

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

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 3px;
}

/* Disclosures: a chevron that points at the content, turning down when
   it's open, in place of the browser's triangle. It's a mask, so it takes
   the text colour. */
summary {
  display: flex;
  align-items: center;
  cursor: pointer;
  list-style: none;
}

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

summary::before {
  content: "";
  flex: none;
  width: 0.7em;
  height: 0.7em;
  margin-inline-end: 0.4em;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 2.75 11.25 8 6 13.25' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 2.75 11.25 8 6 13.25' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 0.15s ease;
}

details[open] > summary::before {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  summary::before {
    transition: none;
  }
}

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

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0 0 var(--space-4) 0;
  color: var(--color-text);
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.1;
}

h1 {
  font-size: clamp(2.4rem, 5vw, 4.5rem);
}

h2 {
  font-size: clamp(1.5rem, 2.8vw, 2.25rem);
}

h3 {
  font-size: clamp(1.2rem, 2vw, 1.5rem);
}

/* A dictionary-style entry: the word, then how it sounds between
   slashes. */
.pronunciation {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--space-4);
}

.pronunciation-word {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-text);
}

.pronunciation-sound {
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-style: italic;
  color: var(--color-text-muted);
}

/* The start of a second part of a long page, such as How it works on the
   about page: an h2 set like a title, with a rule above it. */
h2.page-part {
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-border);
  font-size: clamp(2rem, 4vw, 3.25rem);
}

hr {
  margin-top: var(--space-4);
  margin-bottom: var(--space-5);
  border: 0;
  border-top: 1px solid var(--color-border);
}

p,
ul,
ol,
dl,
pre,
blockquote {
  margin: 0;
}

ul,
ol {
  /* padding-left: 1.25rem; */
}

/* Body-copy bullets: the marker sits ~0.4rem from its text, and the whole
   item is indented ~1.2rem, so lists read as part of the paragraph flow. */
li:not(.nav-list li) {
  padding-left: 0.35rem;
  margin-left: 1.15rem;
  list-style: disc;
}

/* Zero specificity, so .muted and component colors still win. Bold text
   and links keep full contrast for hierarchy. */
:where(.page-content) :where(p, li, dd) {
  color: var(--color-text-body);
}

:where(.page-content) :where(p, li, dd) :where(strong, b) {
  color: var(--color-text);
}

li:not(.nav-list li)::marker {
  color: var(--color-text-muted);
}

li + li {
  margin-top: var(--space-2);
}

pre,
code,
kbd,
samp {
  font-family: var(--font-mono);
  font-size: 0.95em;
}

pre {
  overflow-x: auto;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-muted);
  box-shadow: var(--shadow-sm);
}

section {
  margin-bottom: var(--space-8);
}

small {
  color: var(--color-text-muted);
}

.app-shell {
  display: grid;
  grid-template-rows: auto 1fr auto auto;
}

.shell {
  width: min(calc(100% - min(2rem, 10vw)), var(--page-max-width));
  margin-inline: auto;
}

.page-main {
  padding-block: var(--space-7);
}

.page-content {
  --stack-space: var(--space-6);
}

.page-content > * {
  width: min(100%, 60rem);
  margin-inline: auto;
}

.page-content-centered {
  text-align: center;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  border-bottom: 1px solid var(--color-border);
  background: color-mix(in srgb, var(--color-surface-strong) 82%, transparent);
  backdrop-filter: blur(18px);
}

.site-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: min(calc(100% - min(2rem, 10vw)), var(--page-max-width));
  margin-inline: auto;
  padding-block: var(--space-4);
}

.brand {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  padding: 0.5rem 0.85rem 0;
}

.brand-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: inherit;
  text-decoration: none;
}

.brand-logo {
  display: block;
  height: clamp(2.6rem, 2rem + 1.5vw, 3.2rem);
  width: auto;
}

/* Desktop: the wordmark's lettering sits in the lower part of the SVG (the
   lily rises above it), so centring the image leaves the letters below the
   nav text. The shift has a part that scales with the logo's own height
   (the % term) and a fixed part from the nav text metrics (the rem term);
   together they centre the lettering on the middle of the nav links' text
   across desktop widths. */
@media (min-width: 721px) {
  .site-nav .brand {
    padding-top: 0;
  }

  .brand-logo {
    transform: translateY(calc(-20.7% + 0.306rem));
  }
}

.nav-list {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  margin-left: auto;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-list li {
  margin: 0;
}

.nav-list a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.5rem 0.85rem;
  color: var(--color-text);
  text-decoration: none;
}

.nav-list a:hover,
.nav-list a:focus-visible {
  color: var(--color-text);
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.18em;
}

/* The account link: a stamp with how many stamps you have. Its name for
   screen readers is set in stamps.js.

   The stamp is centred on the digits' cap height, not the line box: the
   count's box is trimmed to the cap height and the alphabetic baseline
   (text-box), so centring the two boxes centres the ink. The padding is
   set from the ink too: the stamp's ink fills its box, while the digits
   carry a little side bearing, so the number's side gets slightly less. */
.account-badge {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--color-text-muted);
  text-decoration: none;
}

.account-badge:hover {
  color: var(--color-text);
}

.account-badge[hidden] {
  display: none;
}

.account-badge-stamps {
  --badge-pad-y: 0.42em;
  display: inline-flex;
  align-items: center;
  gap: 0.2em;
  padding: var(--badge-pad-y) 0.53em var(--badge-pad-y) 0.65em;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* With no number, just the stamp in a true circle: as wide as the badge
   is tall (the stamp's height, the padding above and below, and the
   border), never an almost-circle. */
.account-badge-stamps:has(.account-badge-count[hidden]) {
  width: calc(1.05em + 2 * var(--badge-pad-y) + 2px);
  height: calc(1.05em + 2 * var(--badge-pad-y) + 2px);
  padding: 0;
  justify-content: center;
}

.account-badge-count {
  text-box: trim-both cap alphabetic;
}

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

.stamp-icon {
  /* About 1.45 times the digits' cap height: the stamp reads as an object
     beside the number, not a letter in it. */
  height: 1.05em;
  width: calc(1.05em * 18.5 / 26.5);
  flex: none;
  /* Room for the dots' edges: nothing at the border gets cut off. */
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* The perforated edge is a line of dots: holes the eye joins into a
   stamp. */
.stamp-edge {
  stroke-width: 1.9;
  stroke-dasharray: 0 1;
}

/* While stamps are on their way, the perforations march round. */
.account-badge[data-refilling] .stamp-edge {
  animation: stamp-march 1s linear infinite;
}

@keyframes stamp-march {
  to {
    stroke-dashoffset: -1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .account-badge[data-refilling] .stamp-edge {
    animation: none;
    opacity: 0.5;
  }
}

.site-header-search {
  padding: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.site-footer {
  padding-block: var(--space-7);
  border-top: 1px solid var(--color-border);
}

.footer-inner {
  color: var(--color-text-muted);
  text-align: center;
}

.footer-inner > p {
  font-family: var(--font-display);
  font-size: 1.0625rem;
}

.footer-inner > * + * {
  margin-top: var(--space-3);
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-5);
  margin: 0;
  padding: 0;
}

.footer-inner .footer-links li {
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-inner .footer-links li + li {
  margin-top: 0;
}

.footer-links a {
  color: var(--color-text-muted);
}

.footer-links a:hover {
  color: var(--color-text);
}

.stack-sm {
  --stack-space: var(--space-2);
}

.stack-md {
  --stack-space: var(--space-4);
}

.stack-lg {
  --stack-space: var(--space-5);
}

.stack-xl {
  --stack-space: var(--space-6);
}

.stack-sm > * + *,
.stack-md > * + *,
.stack-lg > * + *,
.stack-xl > * + *,
.page-content > * + * {
  margin-block-start: var(--stack-space, var(--space-4));
}

.surface {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.card {
  padding: clamp(min(1.25rem, 6vw), 2vw, 2rem);
}

/* Close under the header; more room below, before the rest of the page. */
.hero {
  padding-block: clamp(0.5rem, 2vh, 2rem) clamp(4rem, 10vh, 8rem);
}

/* The line under a home page headline. */
.hero-sub {
  margin-block-start: calc(-1 * var(--space-3));
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 1.9rem);
  line-height: 1.25;
  color: var(--color-text-body);
  text-wrap: balance;
}

.eyebrow {
  color: var(--color-text-muted);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.lead {
  max-width: 34rem;
  margin-inline: auto;
  font-size: clamp(1.1rem, 1.6vw, 1.35rem);
  color: var(--color-text);
}

.muted {
  color: var(--color-text-muted);
}

/* The search box: the words on top, wrapping onto as many lines as they
   need, and a row of controls underneath with the search button at the
   end, so nothing is ever hidden behind the button. */
.form-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  overflow: hidden;
  border: 1px solid var(--color-border-strong);
  border-radius: 1.75rem;
  background: var(--color-surface-muted);
  box-shadow:
    0 0 0 1px rgba(15, 10, 10, 0.08),
    0 10px 30px rgba(0, 0, 0, 0.18);
}

/* A band of brushed-metal highlight that travels along the search bar's
   outline. The gradient is painted on a 1.5px ring (padding + mask) and
   slid across by animating background-position. */
.form-row::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  padding: 1.5px;
  border-radius: inherit;
  background: linear-gradient(
      100deg,
      transparent 0%,
      transparent 38%,
      var(--shimmer-green) 43%,
      var(--shimmer-silver) 47.5%,
      var(--shimmer-gold) 50%,
      var(--shimmer-silver) 52.5%,
      var(--shimmer-peach) 57%,
      transparent 62%,
      transparent 100%
    )
    0 0 / 300% 100% no-repeat;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box exclude,
    linear-gradient(#000 0 0);
  pointer-events: none;
  animation: search-shimmer 7s ease-in-out infinite;
}

/* The glisten: silver either side of a gold highlight, led in by a
   tinge of the lily's green and trailed by its peach. Kept a little
   softer than full strength, so it stays close to the muted border. */
.form-row {
  --shimmer-green: rgba(169, 199, 138, 0.38);
  --shimmer-silver: rgba(206, 208, 212, 0.72);
  --shimmer-gold: rgba(228, 204, 146, 0.86);
  --shimmer-peach: rgba(242, 163, 122, 0.38);
}

@keyframes search-shimmer {
  0% {
    background-position: 100% 0;
  }
  60%,
  100% {
    background-position: 0% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .form-row::after {
    animation: none;
    opacity: 0;
  }
}

.form-row:focus-within {
  border-color: var(--color-accent);
  box-shadow:
    0 0 0 1px rgba(15, 10, 10, 0.18),
    0 0 0 6px rgba(15, 10, 10, 0.08),
    0 14px 34px rgba(0, 0, 0, 0.22);
}

/* Once app.js has drawn the outline (see smoothEdge), the drawing is the
   box: its fill, edge, shadow, focus ring and shine. */
.form-row.has-smooth-edge {
  overflow: visible;
  border-color: transparent;
  background: transparent;
  box-shadow: none;
}

.form-row.has-smooth-edge::after {
  content: none;
}

.form-row.has-smooth-edge > :not(.composer-edge) {
  position: relative;
  z-index: 1;
}

.composer-edge {
  position: absolute;
  top: -1px;
  left: -1px;
  z-index: 0;
  overflow: visible;
  pointer-events: none;
}

.composer-edge-fill {
  fill: var(--color-surface-muted);
  filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.18));
}

.composer-edge-line {
  fill: none;
  stroke: var(--color-border-strong);
  stroke-width: 1.5;
  transition: stroke 140ms ease;
}

.composer-edge-shine {
  fill: none;
  stroke-width: 1.5;
}

.composer-edge-glow {
  fill: none;
  stroke: transparent;
  stroke-width: 12;
  transition: stroke 140ms ease;
}

.form-row:focus-within .composer-edge-line {
  stroke: var(--color-accent);
}

.form-row:focus-within .composer-edge-glow {
  stroke: rgba(15, 10, 10, 0.08);
}

.form-row:focus-within .composer-edge-fill {
  filter: drop-shadow(0 14px 17px rgba(0, 0, 0, 0.22));
}

@media (prefers-reduced-motion: reduce) {
  .composer-edge-shine {
    display: none;
  }
}

.input,
input,
select,
textarea {
  width: 100%;
  min-height: 3.5rem;
  padding: 0.8rem 1rem;
  border: 0;
  border-radius: var(--radius-pill) 0 0 var(--radius-pill);
  background: transparent;
  color: var(--color-text);
  box-shadow: none;
}

.composer {
  text-align: start;
}

.composer-input {
  display: block;
  /* At least one line, so the box can't collapse whatever the script does. */
  min-height: calc(1.5em + 1.25rem);
  max-height: 12lh;
  padding: 1rem min(1.25rem, 6vw) 0.25rem;
  border-radius: 0;
  font: inherit;
  line-height: 1.5;
  resize: none;
  overflow-y: auto;
  overflow-wrap: break-word;
}

/* Clear: a small x at the top right of the box; the words stop short of it. */
.composer-input {
  padding-inline-end: calc(min(1.25rem, 6vw) + 2rem);
}

.composer-clear {
  position: absolute;
  top: 0.65rem;
  right: 0.65rem;
  z-index: 2;
  width: 2rem;
  height: 2rem;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--color-text-muted);
}

/* Beats the outline's layering rule, which makes the box's children
   position: relative. */
.form-row.has-smooth-edge > .composer-clear {
  position: absolute;
}

.composer-clear:hover {
  background: var(--color-surface-strong);
  color: var(--color-text);
  transform: none;
}

.composer-clear[hidden] {
  display: none;
}

.composer-clear svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
}

.composer-input:focus {
  outline: none;
}

.composer-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.25rem 0.6rem 0.6rem;
}

.composer-option,
.composer-send {
  min-height: 0;
  margin: 0;
  border-radius: var(--radius-pill);
  font-family: inherit;
}

.composer-option {
  max-width: 100%;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--color-border-strong);
  background: transparent;
  color: var(--color-text-muted);
  font-size: 0.9rem;
  font-weight: 600;
}

.composer-option:hover {
  background: var(--color-surface-strong);
  border-color: var(--color-border-strong);
  color: var(--color-text);
}

/* Search options: a sliders icon, with a dot when searches use a stamp. */
.composer-options-toggle {
  position: relative;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
}

.composer-options-toggle svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.composer-options-toggle[aria-expanded="true"] {
  background: var(--color-surface-strong);
  color: var(--color-text);
}

.composer-options-dot {
  position: absolute;
  top: 0.3rem;
  right: 0.3rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--color-accent);
}

.composer-options-dot[hidden] {
  display: none;
}

.composer-options {
  display: grid;
  gap: var(--space-3);
  margin: 0.5rem min(0.75rem, 3vw) 0.25rem;
  padding: 0.85rem min(1rem, 4vw);
  border-radius: 1.1rem;
  background: var(--color-surface-strong);
  font-size: 0.95rem;
  line-height: 1.45;
}

.composer-options[hidden],
.composer-stamp-note[hidden] {
  display: none;
}

.composer-stamp-note {
  margin: 0;
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

.composer-check {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
}

.composer-check input {
  width: 1.25rem;
  min-height: 1.25rem;
  height: 1.25rem;
  margin-top: 0.1rem;
  padding: 0;
  flex: none;
  -webkit-appearance: checkbox;
  appearance: auto;
  accent-color: var(--color-accent);
}

.composer-check span {
  color: var(--color-text-muted);
}

.composer-check strong {
  display: block;
  color: var(--color-text);
  font-weight: 600;
}

.composer-send {
  width: 2.5rem;
  height: 2.5rem;
  margin-inline-start: auto;
  padding: 0;
}

/* Empty box: the arrow is dimmed and marked unavailable, but still takes
   a tap, so an empty submit can say no (the shake below) as well as the
   field's own message. */
.composer-send[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

.composer-bar {
  position: relative;
}

.composer-hint {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0.2rem;
  z-index: 3;
  max-width: min(16rem, 80vw);
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface-strong);
  color: var(--color-text);
  font-size: 0.875rem;
  line-height: 1.35;
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.18);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-0.2rem);
  /* Fades out gently; app.js decides when it shows (a mouse over the
     arrow, keyboard focus, or a couple of seconds after an empty submit),
     so a tap on a phone doesn't leave it stuck. */
  transition: opacity 0.35s ease, transform 0.35s ease, visibility 0s linear 0.35s;
  pointer-events: none;
}

.composer-hint[data-shown] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.12s ease, transform 0.12s ease, visibility 0s;
}

.form-row.composer-nope {
  animation: composer-nope 0.38s ease-in-out;
}

@keyframes composer-nope {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(2px); }
}

@media (prefers-reduced-motion: reduce) {
  .form-row.composer-nope {
    animation: none;
  }

  .composer-hint {
    transition: none;
  }
}

.composer-send svg {
  width: 1.3rem;
  height: 1.3rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.input::placeholder,
input::placeholder,
textarea::placeholder {
  color: var(--color-text-muted);
}

.button,
button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 1;
  margin-left: 0.25rem;
  min-height: 3.5rem;
  padding: 0.8rem 1.4rem;
  border: 1px solid var(--color-border-strong);
  border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  text-decoration: none;
  transition:
    background-color 140ms ease,
    border-color 140ms ease,
    color 140ms ease,
    transform 140ms ease;
}

.button:hover,
button:hover {
  transform: translateY(-1px);
}

.button-primary,
button {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-contrast);
  box-shadow: none;
}

.button-primary:hover,
button:hover {
  background: var(--color-accent-strong);
  border-color: var(--color-accent-strong);
}

.search-form {
  width: 100%;
  max-width: 60rem;
  margin-inline: auto;
}

.search-form [data-search-status] {
  min-height: 1.5em;
  margin-top: var(--space-5);
}

/* Collapse the status line when it has nothing to say (e.g. on the results
   page); app.js fills it with messages when needed. */
.search-form [data-search-status]:empty {
  min-height: 0;
  margin-top: 0;
}

/* "protected relay" in the search tagline: a hairline-underlined link to
   its explanation, ending in a small "?" coin. The coin is inline-flex, so
   the underline doesn't run through it; the invisible ::after widens the
   link's tap target without changing the layout. */
.relay-link,
#pay-to-skip a,
.search-notice a {
  position: relative;
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
}

.relay-link::after {
  content: "";
  position: absolute;
  inset: -0.5rem -0.25rem;
}

.relay-link:hover,
.relay-link:focus-visible,
#pay-to-skip a:hover,
#pay-to-skip a:focus-visible,
.search-notice a:hover,
.search-notice a:focus-visible {
  color: var(--color-text);
  text-decoration-color: currentColor;
}

.help-coin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15em;
  height: 1.15em;
  margin-left: 0.25em;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: 0.8em;
  font-weight: 600;
  line-height: 1;
  vertical-align: 0.2em;
}

.relay-link:hover .help-coin,
.relay-link:focus-visible .help-coin {
  border-color: currentColor;
}

/* Sections linked to directly (e.g. /how-it-works#protected-relay) land
   below the sticky header rather than underneath it. */
.anchor-target {
  scroll-margin-top: 17rem;
}

/* The pay-to-skip line continues the explainer under the search bar, so it
   shares its colour and (on phones) its size. */
#pay-to-skip {
  color: var(--color-text-muted);
}

.hero-search {
  margin-top: var(--space-6);
}

.meta-grid {
  display: grid;
  gap: var(--space-3);
}

.meta-grid dt {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  font-weight: 600;
}

.meta-grid dd {
  margin: var(--space-1) 0 0;
}

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

/* Source medallion: a small coin with the source's serif initial. */
.source-mark {
  --mark-size: 1.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-width: var(--mark-size);
  height: var(--mark-size);
  padding-inline: calc(var(--mark-size) * 0.19);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background: var(--color-surface-strong);
  color: var(--color-text);
  font-family: var(--font-display);
  font-size: calc(var(--mark-size) * 0.53);
  font-weight: 600;
  line-height: 1;
  box-shadow: inset 0 0 0 2px var(--color-surface-muted);
}

/* Several sources overlap like a small stack of coins; a ring in the page
   colour keeps each edge legible, and the stack fans out on hover. */
.source-marks {
  display: inline-flex;
  /* Never squeezed by a long address next to it: the marks would spill
     over it. The address gives way instead (it ellipsizes). */
  flex: none;
  align-items: center;
}

.source-marks .source-mark {
  position: relative;
  box-shadow:
    inset 0 0 0 2px var(--color-surface-muted),
    0 0 0 2px var(--color-bg);
  transition: margin-left 160ms ease;
}

.source-marks .source-mark + .source-mark {
  margin-left: calc(var(--mark-size) * -0.25);
}

.source-marks:hover .source-mark + .source-mark {
  margin-left: calc(var(--mark-size) * -0.06);
}

@media (prefers-reduced-motion: reduce) {
  .source-marks .source-mark {
    transition: none;
  }
}

/* ---- Results page ---------------------------------------------------- */

/* Less air between the header and the first result. */
.page-main:has(.results-page) {
  padding-top: var(--space-5);
}

/* Most of the results page starts hidden (notes, answers, related
   searches), so space each part from the visible part before it only: the
   first thing shown sits right under the header. */
.results-page > * {
  margin-block-start: 0;
}

.results-page > :not([hidden]) ~ * {
  margin-block-start: var(--stack-space, var(--space-4));
}

.results-summary {
  margin-block: 0;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

/* Shown beside the count while preview images come through the relay. */
.results-progress {
  margin-left: 0.75em;
}

@media (prefers-reduced-motion: no-preference) {
  .results-progress {
    animation: results-progress-pulse 1.6s ease-in-out infinite;
  }
}

/* While a search runs: the lily, breathing, over one line at a time. */
.results-waiting {
  display: grid;
  justify-items: center;
  gap: var(--space-4);
  padding-block: var(--space-7);
  text-align: center;
}

.results-waiting[hidden] {
  display: none;
}

.results-waiting-mark {
  width: 2.75rem;
  height: auto;
}

.results-waiting-line {
  max-width: 24rem;
  min-height: 3em;
  margin: 0;
  color: var(--color-text-muted);
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1.5;
}

@media (prefers-reduced-motion: no-preference) {
  .results-waiting-mark {
    animation: results-waiting-breathe 3.2s ease-in-out infinite;
  }

  .results-waiting-line.is-showing {
    animation: results-waiting-in 600ms ease-out;
  }
}

@keyframes results-waiting-breathe {
  50% {
    opacity: 0.55;
    transform: scale(0.94);
  }
}

@keyframes results-waiting-in {
  from {
    opacity: 0;
    transform: translateY(0.25rem);
  }
}

@keyframes results-progress-pulse {
  50% {
    opacity: 0.45;
  }
}

/* Each result: title, then source line, then description, separated from
   the next by a hairline and generous space. Selectors outrank the generic
   li:not(.nav-list li) indent rule. */
.result-list > .result-list-item {
  margin: 0;
  padding: var(--space-6) 0;
  border-top: 1px solid var(--color-border);
  list-style: none;
}

/* A result folded in after the page first showed (app.js foldResults). */
.result-list > .result-list-item.result-arrived {
  animation: result-arrive 400ms ease-out;
}

@keyframes result-arrive {
  from {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .result-list > .result-list-item.result-arrived {
    animation: none;
  }
}

/* While results from the other sources are on their way. */
.results-more {
  padding-block: var(--space-4);
  border-top: 1px solid var(--color-border);
  text-align: center;
}

.result-list > .result-list-item:first-child {
  padding-top: var(--space-3);
  border-top: 0;
}

.result-item {
  padding: 0;
}

.result-title {
  margin: 0;
  font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
  line-height: 1.25;
  letter-spacing: 0;
}

/* A hairline underline: 1px and faint at rest, solid on hover/focus. The
   default scales with font size, which looked heavy at title size. */
.result-title a {
  color: var(--color-text);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);
  transition: text-decoration-color 120ms ease;
}

.result-title a:hover,
.result-title a:focus-visible {
  color: var(--color-text);
  text-decoration-color: currentColor;
}

.result-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  margin-top: var(--space-2);
  color: var(--color-text-muted);
  font-size: 0.8125rem;
}

.result-meta .source-mark {
  --mark-size: 1.35rem;
}

.result-url {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.result-snippet {
  margin-top: var(--space-3);
  color: color-mix(in srgb, var(--color-text) 82%, var(--color-bg));
  font-size: 0.9375rem;
  line-height: 1.6;
}

.result-item-body .result-thumbnail,
.result-item-body .result-thumbnail-placeholder {
  margin-top: var(--space-4);
}

/* Wider screens: preview image sits to the right of the text instead of
   adding a tall block under every result. */
@media (min-width: 640px) {
  .result-item-body:has(> .result-thumbnail, > .result-thumbnail-placeholder) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 8.5rem;
    column-gap: var(--space-5);
    align-items: start;
  }

  .result-item-body > * {
    grid-column: 1;
  }

  .result-item-body > .result-thumbnail,
  .result-item-body > .result-thumbnail-placeholder {
    grid-column: 2;
    grid-row: 1 / span 3;
    width: 8.5rem;
    min-width: 0;
    margin-top: 0.2rem;
  }
}

/* Instant answers above the results: the answer itself is the headline. */
.answer-list {
  display: grid;
  gap: var(--space-4);
}

/* Answers, then the search notice, then the count. Only applies when
   those are showing, so a plain results page keeps its spacing. */
.answer-list:not([hidden]) ~ .search-notice:not([hidden]),
.answer-list:not([hidden]) ~ .search-notice[hidden] + .results-summary {
  margin-top: var(--space-5);
}

.search-notice {
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

.search-notice:not([hidden]) + .results-summary {
  margin-top: var(--space-2);
}

.answer-card {
  box-shadow: none;
}

.answer-card > * + * {
  margin-top: var(--space-2);
}

.answer-label {
  margin: 0;
  color: var(--color-text-muted);
  font-size: 0.9375rem;
  overflow-wrap: anywhere;
}

.answer-text {
  margin: 0;
  color: var(--color-text);
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.4rem + 1.5vw, 2.4rem);
  font-weight: 600;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.answer-source {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 0;
  color: var(--color-text-muted);
  font-size: 0.8125rem;
}

.answer-source .source-mark {
  --mark-size: 1.4rem;
  width: var(--mark-size);
  padding-inline: 0;
  letter-spacing: -0.03em;
}

.answer-source a {
  color: inherit;
}

/* Long answers and hashes: still the headline, but they fit. */
.answer-text.is-long {
  font-size: 1.35rem;
  line-height: 1.3;
}

.answer-text.is-code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.95rem;
  font-weight: 500;
  line-height: 1.5;
  word-break: break-all;
}

/* Weather: temperature as the headline, condition beside it, then a short
   forecast. */
.weather-condition {
  margin-left: var(--space-3);
  color: var(--color-text-muted);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 500;
}

.weather-details {
  margin-bottom: 0;
  color: var(--color-text-body);
  font-size: 0.875rem;
}

.weather-card > * + *,
.infobox-card > * + * {
  margin-top: var(--space-3);
}

.weather-card > .answer-text {
  margin-top: var(--space-2);
}

.weather-days {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin-bottom: 0;
  padding: var(--space-3) 0 0;
  border-top: 1px solid var(--color-border);
}

.weather-days > .weather-day {
  display: grid;
  gap: 0.1rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
}

.weather-day-name {
  font-weight: 600;
}

.weather-day-condition {
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.weather-day-range {
  color: var(--color-text-body);
}

/* ---- Weather skies ------------------------------------------------------
   A quiet backdrop matching the conditions. Two layers (back, front) per
   sky; everything is decorative, sits behind the content, and holds still
   for Reduce Motion. Night cards switch to dark tokens so text stays
   readable over a night sky in either theme. */
.weather-card {
  position: relative;
  isolation: isolate;
  --sky-ink: color-mix(in srgb, var(--color-text) 22%, transparent);
}

/* The sky clips itself, not the card, so an answer menu can hang below. */
.weather-card > .weather-sky {
  position: absolute;
  inset: 0;
  z-index: -1;
  margin: 0;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}

.sky-layer {
  position: absolute;
  inset: 0;
}

.weather-card[data-daytime="night"] {
  color-scheme: dark;
  --color-surface: #141826;
  --color-text: #eef0f6;
  --color-text-body: #d5d9e4;
  --color-text-muted: #a3a9ba;
  --color-border: rgb(255 255 255 / 0.12);
  --color-border-strong: rgb(255 255 255 / 0.22);
  --color-surface-strong: #1e2335;
  --color-surface-muted: #181c2b;
  --color-bg: #141826;
  background: #141826;
  color: var(--color-text);
}

/* Clear day: a warm sun glow in the corner, breathing slowly. */
.weather-card[data-sky="clear"][data-daytime="day"] .weather-sky {
  background: linear-gradient(165deg, rgb(120 170 230 / 0.16), transparent 60%);
}

.weather-card[data-sky="clear"][data-daytime="day"] .sky-back,
.weather-card[data-sky="partly"][data-daytime="day"] .sky-back {
  inset: -30% -30% auto auto;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(255 196 92 / 0.55), rgb(255 196 92 / 0.12) 45%, transparent 70%);
  animation: sky-sun 9s ease-in-out infinite;
}

/* Clear and partly cloudy nights: stars that twinkle out of step. */
.weather-card[data-daytime="night"] .weather-sky {
  background: radial-gradient(ellipse at 80% -10%, rgb(110 130 200 / 0.28), transparent 60%);
}

.weather-card[data-sky="clear"][data-daytime="night"] .sky-back,
.weather-card[data-sky="partly"][data-daytime="night"] .sky-back {
  /* Crisp pinpricks, thinning toward the bottom: unlike snow, they're tiny,
     hard-edged and don't fall. */
  background-image:
    radial-gradient(circle at 12% 18%, #fff 0 0.9px, transparent 1.3px),
    radial-gradient(circle at 28% 52%, #fff 0 0.6px, transparent 1px),
    radial-gradient(circle at 47% 12%, #fff 0 1px, transparent 1.4px),
    radial-gradient(circle at 58% 34%, #fff 0 0.6px, transparent 1px),
    radial-gradient(circle at 78% 30%, #fff 0 0.8px, transparent 1.2px),
    radial-gradient(circle at 92% 8%, #fff 0 0.6px, transparent 1px),
    radial-gradient(circle at 6% 66%, #fff 0 0.6px, transparent 1px),
    radial-gradient(circle at 38% 30%, #fff 0 0.5px, transparent 0.9px),
    radial-gradient(circle at 86% 58%, #fff 0 0.7px, transparent 1.1px),
    radial-gradient(circle at 66% 6%, #fff 0 0.5px, transparent 0.9px),
    radial-gradient(circle at 20% 38%, #fff 0 0.5px, transparent 0.9px),
    radial-gradient(circle at 52% 70%, #fff 0 0.5px, transparent 0.9px),
    radial-gradient(circle at 3% 24%, #fff 0 0.6px, transparent 1px),
    radial-gradient(circle at 72% 46%, #fff 0 0.5px, transparent 0.9px);
  mask-image: linear-gradient(180deg, #000 30%, transparent 95%);
  -webkit-mask-image: linear-gradient(180deg, #000 30%, transparent 95%);
  opacity: 0.9;
  animation: sky-twinkle 5s ease-in-out infinite;
}

/* A few four-point sparkles that pulse, the clearest "these are stars". */
.weather-card[data-sky="clear"][data-daytime="night"] .sky-front::before,
.weather-card[data-sky="clear"][data-daytime="night"] .sky-front::after,
.weather-card[data-sky="partly"][data-daytime="night"] .sky-back::after {
  content: "\2726";
  position: absolute;
  color: #fff;
  font-size: 9px;
  line-height: 1;
  text-shadow: 0 0 6px rgb(200 215 255 / 0.9);
  animation: sky-sparkle 3.8s ease-in-out infinite;
}

.weather-card[data-sky="clear"][data-daytime="night"] .sky-front::before {
  top: 14%;
  left: 62%;
}

.weather-card[data-sky="clear"][data-daytime="night"] .sky-front::after {
  top: 44%;
  left: 90%;
  font-size: 7px;
  animation-delay: -1.9s;
}

.weather-card[data-sky="partly"][data-daytime="night"] .sky-back::after {
  top: 10%;
  left: 54%;
}

/* Tonight's moon, in its real phase, top right of night skies. */
.weather-card .sky-moon {
  position: absolute;
  top: var(--space-4);
  right: var(--space-5);
  --moon-size: 1.9rem;
  box-shadow: 0 0 18px 4px rgb(235 235 210 / 0.18);
}

/* Clouds: soft blurred banks drifting across. */
.weather-card[data-sky="partly"] .sky-front,
.weather-card[data-sky="cloudy"] .sky-back,
.weather-card[data-sky="cloudy"] .sky-front {
  inset: -10% -40%;
  background:
    radial-gradient(ellipse 22% 14% at 30% 22%, var(--sky-cloud), transparent 70%),
    radial-gradient(ellipse 18% 12% at 42% 26%, var(--sky-cloud), transparent 70%),
    radial-gradient(ellipse 26% 16% at 72% 70%, var(--sky-cloud), transparent 70%),
    radial-gradient(ellipse 16% 10% at 84% 66%, var(--sky-cloud), transparent 70%);
  filter: blur(6px);
  animation: sky-drift 38s linear infinite alternate;
}

.weather-card {
  --sky-cloud: color-mix(in srgb, var(--color-text) 10%, transparent);
}

.weather-card[data-sky="cloudy"] .weather-sky {
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-text) 7%, transparent), transparent 70%);
}

.weather-card[data-sky="cloudy"] .sky-front {
  transform: scale(-1, 1);
  animation-duration: 52s;
  animation-direction: alternate-reverse;
}

/* Fog: long pale bands sliding past each other. */
.weather-card[data-sky="fog"] .sky-back,
.weather-card[data-sky="fog"] .sky-front {
  inset: 0 -50%;
  background: repeating-linear-gradient(
    180deg,
    transparent 0 18%,
    color-mix(in srgb, var(--color-text) 8%, transparent) 24% 30%,
    transparent 36% 44%
  );
  filter: blur(8px);
  animation: sky-drift 30s ease-in-out infinite alternate;
}

.weather-card[data-sky="fog"] .sky-front {
  top: 12%;
  animation-duration: 44s;
  animation-direction: alternate-reverse;
}

/* Rain and storms: thin slanted streaks falling, two speeds for depth. */
.weather-card[data-sky="rain"] .weather-sky,
.weather-card[data-sky="storm"] .weather-sky {
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-text) 8%, transparent), transparent 75%);
}

.weather-card[data-sky="rain"] .sky-back,
.weather-card[data-sky="rain"] .sky-front,
.weather-card[data-sky="storm"] .sky-back {
  /* Drops, not a grid: five drop patterns whose tile widths don't line up
     (59, 97, 131, 173, 211 px), so the field never visibly repeats. Tile
     heights all divide 240px, so falling 240px loops seamlessly. */
  --drop: radial-gradient(1px 10px at 50% 50%, var(--sky-rain) 55%, transparent 100%);
  top: -240px;
  background-image: var(--drop), var(--drop), var(--drop), var(--drop), var(--drop);
  background-size: 97px 240px, 131px 120px, 173px 80px, 59px 240px, 211px 60px;
  background-position: 13px 30px, 71px 90px, 40px 10px, 22px 170px, 150px 45px;
  transform: skewX(-12deg);
  opacity: 0.6;
  animation: sky-rain-fall 1.05s linear infinite;
}

.weather-card {
  --sky-rain: color-mix(in srgb, var(--color-text) 34%, transparent);
}

.weather-card[data-sky="rain"] .sky-front {
  background-size: 113px 240px, 151px 80px, 67px 120px, 193px 60px, 89px 48px;
  background-position: 50px 200px, 12px 20px, 33px 64px, 120px 5px, 70px 30px;
  opacity: 0.32;
  animation-duration: 0.78s;
}

/* Storms add a soft, infrequent flash: twice, quickly, every eight seconds. */
.weather-card[data-sky="storm"] .sky-front {
  background: rgb(255 255 255 / 0.5);
  opacity: 0;
  animation: sky-flash 8s linear infinite;
}

.weather-card[data-daytime="night"][data-sky="storm"] .sky-front {
  background: rgb(190 205 255 / 0.25);
}

/* Snow: two layers of flakes falling at different speeds. */
.weather-card[data-sky="snow"] .weather-sky {
  background: linear-gradient(180deg, rgb(200 220 245 / 0.18), transparent 70%);
}

.weather-card[data-sky="snow"] .sky-back,
.weather-card[data-sky="snow"] .sky-front {
  --flake: color-mix(in srgb, var(--color-text) 30%, transparent);
  /* Soft, rounder and larger than stars, and always falling. */
  background-image:
    radial-gradient(circle at 10% 20%, var(--flake) 0 2px, transparent 3.5px),
    radial-gradient(circle at 35% 60%, var(--flake) 0 2.5px, transparent 4px),
    radial-gradient(circle at 60% 30%, var(--flake) 0 1.8px, transparent 3px),
    radial-gradient(circle at 85% 75%, var(--flake) 0 3px, transparent 4.5px),
    radial-gradient(circle at 50% 90%, var(--flake) 0 2px, transparent 3.5px);
  background-size: 190px 190px;
  filter: blur(0.4px);
  animation: sky-snow 9s linear infinite;
}

.weather-card[data-daytime="night"][data-sky="snow"] .sky-back,
.weather-card[data-daytime="night"][data-sky="snow"] .sky-front {
  --flake: rgb(255 255 255 / 0.42);
}

.weather-card[data-sky="snow"] .sky-front {
  background-size: 130px 130px;
  opacity: 0.55;
  animation-name: sky-snow-near;
  animation-duration: 14s;
}

@keyframes sky-sun {
  50% {
    transform: scale(1.08);
    opacity: 0.85;
  }
}

@keyframes sky-sparkle {
  0%, 100% {
    opacity: 0.9;
    transform: scale(1);
  }
  50% {
    opacity: 0.35;
    transform: scale(0.6) rotate(20deg);
  }
}

@keyframes sky-twinkle {
  50% {
    opacity: 0.35;
  }
}

@keyframes sky-drift {
  from {
    translate: -8% 0;
  }
  to {
    translate: 8% 0;
  }
}

@keyframes sky-rain-fall {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 240px;
  }
}

@keyframes sky-snow {
  to {
    background-position: 30px 190px;
  }
}

@keyframes sky-snow-near {
  to {
    background-position: -20px 130px;
  }
}

@keyframes sky-flash {
  0%, 90%, 92.5%, 95%, 100% {
    opacity: 0;
  }
  91% {
    opacity: 0.55;
  }
  94% {
    opacity: 0.35;
  }
}

@media (prefers-reduced-motion: reduce) {
  .weather-sky .sky-layer {
    animation: none !important;
  }
}

/* ---- Moon disc --------------------------------------------------------
   A pale disc with one overlay: a dark shadow for crescents, or a lit disc
   on a dark base for gibbous moons, shifted by app.js to the phase. */
.moon-disc {
  --moon-size: 2.75rem;
  --moon-light: #f1eedf;
  --moon-dark: color-mix(in srgb, #2a2f40 85%, var(--moon-light));
  position: relative;
  display: inline-block;
  flex: 0 0 auto;
  width: var(--moon-size);
  height: var(--moon-size);
  overflow: hidden;
  border-radius: 50%;
  background: var(--moon-light);
}

.moon-disc.is-gibbous {
  background: var(--moon-dark);
}

.moon-disc > span {
  position: absolute;
  inset: 0;
  border-radius: 50%;
}

.moon-disc > .moon-shadow {
  background: var(--moon-dark);
}

.moon-disc > .moon-light {
  background: var(--moon-light);
}

/* Answers with a moon: the moon sits top right, beside the headline. */
.answer-card.has-moon {
  position: relative;
  padding-right: calc(clamp(1.25rem, 2vw, 2rem) + 3.5rem);
}

.answer-card > .answer-moon {
  position: absolute;
  top: clamp(1.25rem, 2vw, 2rem);
  right: clamp(1.25rem, 2vw, 2rem);
  margin: 0;
}

/* From the southern hemisphere, lit on the other side. */
.moon-disc.is-south {
  transform: scaleX(-1);
}

/* ---- Answer menus -------------------------------------------------------
   The ⋮ button sits in the card's top right corner; its menu drops down
   from it, over whatever is below. */
.answer-card.has-menu {
  position: relative;
  --menu-inset: clamp(0.35rem, 1vw, 0.75rem);
  /* A comfortable tap, without crowding the card at the largest text. */
  --menu-button: max(44px, 1.75rem);
}

.answer-card.has-menu > :first-child {
  padding-right: calc(var(--menu-button) - 0.5rem);
}

.answer-card > .answer-menu-button {
  position: absolute;
  top: var(--menu-inset);
  right: var(--menu-inset);
  z-index: 2;
  width: var(--menu-button);
  height: var(--menu-button);
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--color-text-muted);
}

.answer-card > .answer-menu-button:hover,
.answer-card > .answer-menu-button[aria-expanded="true"] {
  transform: none;
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
  color: var(--color-text);
}

.answer-menu-button svg {
  width: 9%;
  height: 36%;
  fill: currentColor;
}

/* A moon beside the headline moves down, out of the button's way. */
.answer-card.has-menu > .answer-moon {
  top: calc(var(--menu-inset) + var(--menu-button));
}

.weather-card.has-menu .sky-moon {
  right: calc(var(--menu-inset) + var(--menu-button) + 0.5rem);
}

.answer-card.is-menu-open {
  z-index: 5;
}

.answer-card > .answer-menu {
  position: absolute;
  top: calc(var(--menu-inset) + var(--menu-button) + 0.25rem);
  right: var(--menu-inset);
  z-index: 3;
  display: grid;
  gap: var(--space-3);
  width: max-content;
  max-width: min(22rem, calc(100% - 2 * var(--menu-inset)));
  margin: 0;
  padding: var(--space-3) var(--space-4) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-strong);
  box-shadow: var(--shadow-md);
  hyphens: auto;
}

.weather-card[data-daytime="night"] .answer-menu {
  background: color-mix(in srgb, var(--color-surface) 92%, white);
}

.answer-card > .answer-menu[hidden] {
  display: none;
}

.answer-menu-group {
  display: grid;
  gap: var(--space-1);
}

.answer-menu-label {
  margin: 0;
  color: var(--color-text-muted);
  font-size: 0.75rem;
}

.answer-choices,
.answer-menu-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.answer-menu .answer-choice,
.answer-menu .answer-action {
  z-index: auto;
  min-height: 2.25rem;
  margin: 0;
  padding: 0.25rem 0.75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
}

.answer-menu .answer-choice:hover,
.answer-menu .answer-action:hover {
  transform: none;
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
  border-color: var(--color-border-strong);
}

.answer-menu .answer-choice[aria-pressed="true"] {
  background: var(--color-text);
  border-color: var(--color-text);
  color: var(--color-surface);
}

.answer-detail {
  margin-bottom: 0;
  color: var(--color-text-body);
  font-size: 0.875rem;
}

/* Knowledge panel: image floats right of the summary on any width. */
.infobox-card::after {
  content: "";
  display: block;
  clear: both;
}

.infobox-image {
  float: right;
  width: min(6.5rem, 30%);
  height: auto;
  margin: 0 0 var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  object-fit: cover;
}

.infobox-title {
  margin-bottom: 0;
  font-size: 1.4rem;
}

.infobox-content {
  margin-bottom: 0;
  color: var(--color-text-body);
  font-size: 0.9375rem;
  line-height: 1.6;
}

.infobox-facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-1) var(--space-4);
  clear: both;
  margin-bottom: 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  font-size: 0.875rem;
}

.infobox-facts dt {
  color: var(--color-text-muted);
}

.infobox-facts dd {
  margin: 0;
  color: var(--color-text-body);
  overflow-wrap: anywhere;
}

.infobox-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-bottom: 0;
  font-size: 0.875rem;
}

.infobox-links a,
.answer-source a,
.related-search a {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
}

/* Related searches, at the top of the results, folded. */
.related-searches > summary {
  color: var(--color-text-muted);
  font-size: 0.9375rem;
}

.related-searches-count {
  margin-inline-start: 0.25em;
  font-variant-numeric: tabular-nums;
}

.related-searches[open] > summary {
  margin-bottom: var(--space-3);
}

.related-searches[open] {
  padding-bottom: var(--space-3);
}

.related-search-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin: 0;
  padding: 0;
}

.related-search-list > .related-search {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
}

/* Status page. Selectors outrank the generic li:not(.nav-list li) indent.
   The list is a three-column grid (coin, name, badge) that every row shares
   through subgrid, so all badges in a list are as wide as the widest one and
   their labels line up in one column. */
.status-list {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) max-content;
  column-gap: var(--space-3);
  margin-bottom: 0;
  padding: 0;
}

/* Equal space above and below every separator. */
.status-list > .status-item {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  margin: 0;
  padding: var(--space-3) 0;
  list-style: none;
  border-top: 1px solid var(--color-border);
}

.status-list > .status-item:first-child {
  border-top: 0;
  padding-top: 0;
}

.status-list > .status-item:last-child {
  padding-bottom: 0;
}

/* Fixed-width medallions so two-letter marks (Wd) don't push names out of
   line. */
.status-item .source-mark {
  width: var(--mark-size);
  padding-inline: 0;
  letter-spacing: -0.03em;
}

.status-text {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-width: 0;
}

.status-name {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.status-detail {
  line-height: 1.35;
}

/* Same-size pills (they fill the shared badge column), text centred
   optically. */
.status-state {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  justify-self: stretch;
  min-width: 4.25rem;
  height: 1.75rem;
  /* letter-spacing adds space after the last letter, so the same amount is
     added on the left to keep the label centred. */
  padding: 0 0.6rem 0 calc(0.6rem + 0.02em);
  border: 1px solid var(--color-text);
  border-radius: var(--radius-pill);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* Where supported, trim the label's box to exactly cap height and baseline,
   so the label is centred on its capitals in whatever font is in use. */
@supports (text-box: trim-both cap alphabetic) {
  .status-state {
    text-box: trim-both cap alphabetic;
  }
}

.status-state.is-up {
  background: var(--color-text);
  color: var(--color-bg);
}

.status-state.is-down {
  background: transparent;
  color: var(--color-text);
  border-style: dashed;
}

/* Disabled and in-development sources: listed, but quieter than live ones. */
.status-state.is-off {
  background: transparent;
  border-color: var(--color-border-strong);
  color: var(--color-text-muted);
}

.status-item.is-inactive .status-name {
  color: var(--color-text-muted);
}

.status-item.is-inactive .source-mark {
  opacity: 0.6;
}

/* Sized from the mark, not as a percentage of it: the mark's width comes
   from its content, and Safari resolves a percentage of that to the
   image's own (large) size. */
.source-mark img {
  flex: none;
  width: calc(var(--mark-size) * 0.72);
  height: calc(var(--mark-size) * 0.72);
  object-fit: contain;
}

/* The results notice card (e.g. "Development fallback") sits flat on the page. */
#results-context {
  box-shadow: none;
  margin-bottom: var(--space-5);
  font-size: 0.875rem;
}

/* Garamond runs small next to the sans body; 1.15em matches it optically. */
#results-context h3 {
  margin-bottom: var(--space-1);
  font-size: 1.15em;
}

.result-list {
  display: grid;
  margin: 0;
  padding: 0;
}

.result-item-body {
  min-width: 0;
}

.result-item-layout {
  display: grid;
  gap: var(--space-4);
  align-items: start;
}

.result-thumbnail {
  display: block;
  width: min(100%, 10rem);
  min-width: 7rem;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-muted);
  box-shadow: var(--shadow-sm);
}

/* Images that arrive after the results ease in rather than pop. */
.result-thumbnail {
  animation: result-thumbnail-in 240ms ease-out;
}

@keyframes result-thumbnail-in {
  from {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .result-thumbnail {
    animation: none;
  }
}

.result-thumbnail-placeholder {
  position: relative;
  overflow: hidden;
  width: min(100%, 10rem);
  min-width: 7rem;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-thumbnail-placeholder-base);
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}

.result-thumbnail-placeholder::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -28%;
  width: 28%;
  opacity: var(--thumbnail-placeholder-glint-opacity);
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--color-thumbnail-placeholder-glint) 50%,
    transparent 100%
  );
  animation: result-thumbnail-shimmer 1.6s ease-in-out infinite alternate;
}

.result-thumbnail-placeholder-label {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  color: var(--color-text-muted);
  font-size: 0.7rem;
  line-height: 1.25;
  text-align: center;
  text-wrap: balance;
  text-shadow: 0 1px 0 color-mix(in srgb, var(--color-bg) 70%, transparent);
}

@keyframes result-thumbnail-shimmer {
  0% {
    transform: translateX(0);
  }

  100% {
    transform: translateX(456%);
  }
}

/* Utility classes */

/* Text sizes */

.text-2xs {
  font-size: 0.65rem;
}

.text-xs {
  font-size: 0.75rem;
}

.text-sm {
  font-size: 0.875rem;
}

.text-md {
  font-size: 1rem;
}

.text-lg {
  font-size: 1.125rem;
}

.text-xl {
  font-size: 1.25rem;
}

.text-2xl {
  font-size: 1.5rem;
}

/* Text align */

.text-left {
  text-align: left;
}

.text-center {
  text-align: center;
}

.text-right {
  text-align: right;
}

/* Margins */

.m-0 {
  margin: 0;
}

.m-2xs {
  margin: 0.25rem;
}

.m-xs {
  margin: 0.5rem;
}

.m-sm {
  margin: 0.75rem;
}

.m-md {
  margin: 1rem;
}

.m-lg {
  margin: 1.5rem;
}

.m-xl {
  margin: 2rem;
}

.m-2xl {
  margin: 3rem;
}

.mt-0 {
  margin-top: 0;
}

.mt-2xs {
  margin-top: 0.25rem;
}

.mt-xs {
  margin-top: 0.5rem;
}

.mt-sm {
  margin-top: 0.75rem;
}

.mt-md {
  margin-top: 1rem;
}

.mt-lg {
  margin-top: 1.5rem;
}

.mt-xl {
  margin-top: 2rem;
}

.mt-2xl {
  margin-top: 3rem;
}

.mb-0 {
  margin-bottom: 0;
}

.mb-2xs {
  margin-bottom: 0.25rem;
}

.mb-xs {
  margin-bottom: 0.5rem;
}

.mb-sm {
  margin-bottom: 0.75rem;
}

.mb-md {
  margin-bottom: 1rem;
}

.mb-lg {
  margin-bottom: 1.5rem;
}

.mb-xl {
  margin-bottom: 2rem;
}

.mb-2xl {
  margin-bottom: 3rem;
}

.ml-0 {
  margin-left: 0;
}

.ml-2xs {
  margin-left: 0.25rem;
}

.ml-xs {
  margin-left: 0.5rem;
}

.ml-sm {
  margin-left: 0.75rem;
}

.ml-md {
  margin-left: 1rem;
}

.ml-lg {
  margin-left: 1.5rem;
}

.ml-xl {
  margin-left: 2rem;
}

.ml-2xl {
  margin-left: 3rem;
}

.mr-0 {
  margin-right: 0;
}

.mr-2xs {
  margin-right: 0.25rem;
}

.mr-xs {
  margin-right: 0.5rem;
}

.mr-sm {
  margin-right: 0.75rem;
}

.mr-md {
  margin-right: 1rem;
}

.mr-lg {
  margin-right: 1.5rem;
}

.mr-xl {
  margin-right: 2rem;
}

.mr-2xl {
  margin-right: 3rem;
}

/* Padding */

.p-0 {
  padding: 0;
}

.p-2xs {
  padding: 0.25rem;
}

.p-xs {
  padding: 0.5rem;
}

.p-sm {
  padding: 0.75rem;
}

.p-md {
  padding: 1rem;
}

.p-lg {
  padding: 1.5rem;
}

.p-xl {
  padding: 2rem;
}

.p-2xl {
  padding: 3rem;
}

.pt-0 {
  padding-top: 0;
}

.pt-2xs {
  padding-top: 0.25rem;
}

.pt-xs {
  padding-top: 0.5rem;
}

.pt-sm {
  padding-top: 0.75rem;
}

.pt-md {
  padding-top: 1rem;
}

.pt-lg {
  padding-top: 1.5rem;
}

.pt-xl {
  padding-top: 2rem;
}

.pt-2xl {
  padding-top: 3rem;
}

.pb-0 {
  padding-bottom: 0;
}

.pb-2xs {
  padding-bottom: 0.25rem;
}

.pb-xs {
  padding-bottom: 0.5rem;
}

.pb-sm {
  padding-bottom: 0.75rem;
}

.pb-md {
  padding-bottom: 1rem;
}

.pb-lg {
  padding-bottom: 1.5rem;
}

.pb-xl {
  padding-bottom: 2rem;
}

.pb-2xl {
  padding-bottom: 3rem;
}

.pl-0 {
  padding-left: 0;
}

.pl-2xs {
  padding-left: 0.25rem;
}

.pl-xs {
  padding-left: 0.5rem;
}

.pl-sm {
  padding-left: 0.75rem;
}

.pl-md {
  padding-left: 1rem;
}

.pl-lg {
  padding-left: 1.5rem;
}

.pl-xl {
  padding-left: 2rem;
}

.pl-2xl {
  padding-left: 3rem;
}

.pr-0 {
  padding-right: 0;
}

.pr-2xs {
  padding-right: 0.25rem;
}

.pr-xs {
  padding-right: 0.5rem;
}

.pr-sm {
  padding-right: 0.75rem;
}

.pr-md {
  padding-right: 1rem;
}

.pr-lg {
  padding-right: 1.5rem;
}

.pr-xl {
  padding-right: 2rem;
}

.pr-2xl {
  padding-right: 3rem;
}

@media (min-width: 640px) {
  .meta-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .result-item-layout {
    grid-template-columns: minmax(0, 10rem) minmax(0, 1fr);
  }
}

@media (max-width: 720px) {
  .page-main {
    padding-block: var(--space-6);
  }

  .site-nav {
    flex-direction: column;
    align-items: center;
    gap: 0;
    padding-top: 0;
    padding-bottom: 0;
  }

  .site-nav .brand {
    padding-bottom: 0;
  }

  .site-nav .nav-list li a {
    padding-top: 0;
  }

  /* Smaller explainer lines under the search bar on phones. */
  .search-form [data-search-status],
  .search-tagline,
  #pay-to-skip {
    font-size: 0.875rem;
    line-height: 1.5;
  }

  /* Keep all four nav links on one line at phone widths. */
  .site-nav .nav-list {
    gap: 0;
    justify-content: center;
  }

  .site-nav .nav-list a {
    padding-inline: 0.6rem;
  }



  .site-header-search {
    border-top: 0;
    padding-top: 0;
  }
}

@media (prefers-color-scheme: dark) {
  .site-header {
    background: color-mix(
      in srgb,
      var(--color-surface-strong) 80%,
      transparent
    );
  }
}

/* Account page */

.account {
  --color-danger: #a3322a;
  max-width: 40rem;
  margin-inline: auto;
}

@media (prefers-color-scheme: dark) {
  .account {
    --color-danger: #e0796f;
  }
}

.account section {
  margin-bottom: 0;
}

.account h3 {
  font-size: 1.1rem;
}

.account-loading {
  color: var(--color-text-muted);
}

.account-button {
  margin-left: 0;
  min-height: 3rem;
  padding: 0.6rem 1.3rem;
  border-radius: var(--radius-pill);
  font-size: 1.05rem;
}

.account-button:disabled {
  opacity: 0.7;
  cursor: progress;
  transform: none;
}

.account-button-quiet,
.account-button-quiet:hover {
  background: transparent;
  border-color: var(--color-border-strong);
  color: var(--color-text);
}

.account-button-quiet:hover {
  border-color: var(--color-accent);
}

.account-button-danger,
.account-button-danger:hover {
  background: var(--color-danger);
  border-color: var(--color-danger);
  color: white;
}

.account-button-small {
  white-space: nowrap;
  min-height: 2.25rem;
  padding: 0.3rem 0.9rem;
  font-size: 0.95rem;
}

.account-or {
  color: var(--color-text-muted);
  text-align: center;
}

.account [data-passkey-only] > .account-button,
.account form > .account-button {
  width: 100%;
}

.account-field {
  display: grid;
  gap: 0.35rem;
  margin-inline: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.account-field > span,
.account-field > legend {
  padding: 0;
  font-weight: 600;
}

/* A field's label sits close to its own box and well clear of the box
   above it, so each label reads as belonging to what's below. */
* + .account-field {
  margin-block-start: var(--space-5);
}

/* A label with one word to stress: plain, with only that word bold. */
.account-field > span.account-field-plain {
  font-weight: 400;
}

.account-field-plain strong {
  font-weight: 700;
}

.account-field em {
  color: var(--color-text-muted);
  font-style: normal;
  font-weight: 400;
}

.account-field small,
.account-list small {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

.account-input {
  min-height: 3rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-strong);
  font-size: 1rem;
}

textarea.account-input {
  min-height: 6rem;
  resize: vertical;
}

.account-input:focus-visible {
  border-color: var(--color-accent);
}

.account-check {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
}

.account-check input {
  width: 1.25rem;
  min-height: 1.25rem;
  height: 1.25rem;
  margin-top: 0.2rem;
  padding: 0;
  flex: none;
  -webkit-appearance: checkbox;
  appearance: auto;
  accent-color: var(--color-accent);
}

.account-message {
  color: var(--color-text);
  font-weight: 600;
}

.account-message.is-error {
  color: var(--color-danger);
}

.account-phrase {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem 1rem;
  margin: 0;
  padding: 1rem 1rem 1rem 2.5rem;
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface-strong);
  font-family: var(--font-mono);
  font-size: 1.05rem;
  user-select: all;
}

.account .account-phrase li {
  margin: 0;
  padding-left: 0.25rem;
  list-style: decimal;
}

.account-phrase li::marker {
  color: var(--color-text-muted);
  font-size: 0.85em;
}

@media (min-width: 30rem) {
  .account-phrase {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.account-facts {
  display: grid;
  gap: 0.5rem;
  margin: 0;
}

.account-facts > div {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 1rem;
}

.account-facts dt {
  color: var(--color-text-muted);
}

.account-facts dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.account-stamps {
  font-size: 1.25rem;
}

.account-list {
  display: grid;
  gap: 0.75rem;
  margin-inline: 0;
  margin-bottom: 0;
  padding: 0;
  list-style: none;
}

.account .account-list li {
  margin: 0;
  padding-left: 0;
  list-style: none;
}

.account-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--color-border);
}

.account-resend {
  margin-top: 0.5rem;
}

.account-resend .account-button {
  justify-self: start;
}

.account-list-buttons {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.5rem;
}

.account-list-text {
  display: grid;
  gap: 0.1rem;
}

.account-list-empty {
  color: var(--color-text-muted);
}

.account-details summary {
  color: var(--color-accent);
  cursor: pointer;
}

.account-details[open] summary {
  margin-bottom: var(--space-4);
}

.account-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* Stamps */

.results-stamp {
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

.link-button {
  display: inline;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 0.15em;
  cursor: pointer;
}

.link-button:hover {
  background: none;
  color: var(--color-text);
  transform: none;
}

.account-code {
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.pricing-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.pricing-table th,
.pricing-table td {
  padding: 0.7rem 0.5rem;
  border-bottom: 1px solid var(--color-border);
  text-align: left;
  vertical-align: baseline;
}

.pricing-table thead th {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  font-weight: 600;
}

.pricing-table tbody th {
  font-family: var(--font-display);
  font-size: 1.2rem;
}

.pricing-bonus {
  display: inline-block;
  margin-left: 0.4rem;
  color: var(--color-text-muted);
  font-size: 0.85rem;
  white-space: nowrap;
}

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

.buy-packs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 9rem), 1fr));
  gap: 0.75rem;
}

.buy-pack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  border-radius: var(--radius-md);
  text-align: left;
}

.buy-pack strong {
  font-family: var(--font-display);
  font-size: 1.2rem;
}

.buy-pack span {
  font-size: 0.9rem;
}

.purchase-code {
  font-size: 1.1rem;
  overflow-wrap: anywhere;
  user-select: all;
}

/* Admin */

.admin-note {
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

.admin-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
}

.admin-table th,
.admin-table td {
  padding: 0.45rem 0.6rem 0.45rem 0;
  border-bottom: 1px solid var(--color-border);
  text-align: left;
  vertical-align: top;
}

.admin-table thead th {
  color: var(--color-text-muted);
  font-weight: 600;
  white-space: nowrap;
}

[data-table="search-days"] td:first-child,
[data-table="recent"] td:first-child,
[data-table="account-days"] td:first-child {
  white-space: nowrap;
}

.admin-table .admin-number {
  text-align: right;
  white-space: nowrap;
}

.admin-table .admin-empty {
  color: var(--color-text-muted);
}

/* Dialogs: errors after a submission, and confirmations */

.spes-dialog {
  width: min(26rem, calc(100vw - 2rem));
  max-height: calc(100dvh - 2rem);
  margin: auto;
  padding: 0;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: var(--color-surface-strong);
  color: var(--color-text);
  box-shadow: var(--shadow-md);
}

.spes-dialog::backdrop {
  background: rgb(0 0 0 / 0.45);
}

.spes-dialog-body {
  display: grid;
  gap: var(--space-5);
  padding: var(--space-5);
}

.spes-dialog-message {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.5;
}

.spes-dialog-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-3);
}

.spes-dialog .spes-dialog-button {
  min-height: 2.75rem;
  margin-left: 0;
  padding: 0.5rem 1.3rem;
  border-radius: var(--radius-pill);
  font-size: 1rem;
}

.spes-dialog .spes-dialog-button-quiet,
.spes-dialog .spes-dialog-button-quiet:hover {
  background: transparent;
  border-color: var(--color-border-strong);
  color: var(--color-text);
}

.spes-dialog .spes-dialog-button-danger,
.spes-dialog .spes-dialog-button-danger:hover {
  background: #a3322a;
  border-color: #a3322a;
  color: white;
}

/* When the header would take up too much of the screen (large text, or a
   phone on its side), it scrolls away with the page instead of staying
   pinned. site.js sets the class. */
.header-scrolls .site-header {
  position: static;
}

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---- Holding page -------------------------------------------------------
   What visitors without a preview link see while the site is closed. */
.welcome h1 {
  max-width: 18ch;
  margin-inline: auto;
}

.welcome-points {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-4);
  padding: 0;
  list-style: none;
}

/* Beat the body-copy bullet style (li:not(.nav-list li)). */
.welcome-points > li.card {
  margin: 0;
  padding-left: clamp(min(1.25rem, 6vw), 2vw, 2rem);
  list-style: none;
}

.welcome-points h2 {
  font-size: 1.25rem;
}

.welcome-statement {
  margin-block: var(--space-8);
  font-family: var(--font-display);
  font-size: clamp(2rem, 7vw, 3.5rem);
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
  text-wrap: balance;
}

.welcome-request {
  max-width: 34rem;
}

.welcome-request form > .account-button {
  width: 100%;
}

.welcome-request textarea.account-input {
  min-height: 6rem;
  padding-block: 0.6rem;
  resize: vertical;
}

/* ---- Error pages ---------------------------------------------------------
   Page not found and the like, from the web service (errors.go). */
.error-page {
  padding-block: var(--space-7);
  text-align: center;
}

.error-page .error-mark {
  width: 2.75rem;
  height: auto;
  margin-inline: auto;
}

.error-page .lead {
  max-width: 28rem;
}

/* ---- Feedback ------------------------------------------------------------
   The bubble, bottom right, for people with access (feedback.js). Its size,
   gutters and padding are capped in pixels so very large text doesn't turn
   it into a wall over the page; the text inside still grows. */
.feedback {
  --feedback-size: clamp(48px, 3rem, 60px);
  --feedback-gap: max(16px, env(safe-area-inset-bottom));
  --feedback-pad: clamp(16px, 1.5rem, 24px);
  position: fixed;
  right: max(16px, env(safe-area-inset-right));
  bottom: var(--feedback-gap);
  z-index: 20;
}

.feedback[hidden] {
  display: none;
}

.feedback .feedback-toggle {
  width: var(--feedback-size);
  height: var(--feedback-size);
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 1px solid var(--color-border-strong);
  border-radius: 50%;
  background: var(--color-surface-strong);
  color: var(--color-text);
  box-shadow: var(--shadow-md);
}

.feedback .feedback-toggle:hover,
.feedback .feedback-toggle[aria-expanded="true"] {
  background: var(--color-surface-strong);
  border-color: var(--color-accent);
  color: var(--color-text);
}

.feedback-toggle svg {
  width: 62%;
  height: 62%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linejoin: round;
}

.feedback-toggle circle {
  fill: currentColor;
  stroke: none;
}

.feedback-panel {
  position: absolute;
  right: 0;
  bottom: calc(var(--feedback-size) + 12px);
  display: grid;
  gap: var(--space-4);
  width: min(24rem, calc(100vw - 32px));
  max-height: calc(100dvh - var(--feedback-size) - var(--feedback-gap) - 28px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--feedback-pad);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--feedback-pad);
  background: var(--color-surface-strong);
  color: var(--color-text);
  box-shadow: var(--shadow-md);
}

.feedback-panel[hidden] {
  display: none;
}

.feedback-panel p {
  margin: 0;
  color: var(--color-text-body);
  line-height: 1.5;
}

/* With very large text the title takes the whole line and the close
   button drops below it, rather than the word breaking in two. */
.feedback-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
}

.feedback-title {
  margin: 0;
  font-size: 1.35rem;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
}

.feedback .feedback-close {
  flex: none;
  width: clamp(36px, 2.25rem, 64px);
  height: clamp(36px, 2.25rem, 64px);
  min-height: 0;
  margin: 0 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--color-text-muted);
}

.feedback .feedback-close:hover {
  background: var(--color-surface-muted);
  color: var(--color-text);
  transform: none;
}

.feedback-close svg {
  width: 45%;
  height: 45%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}

.feedback-form {
  display: grid;
  gap: var(--space-4);
}

.feedback-form * + .account-field {
  margin-block-start: 0;
}

.feedback-form .account-button {
  width: 100%;
}

@media print {
  .feedback {
    display: none;
  }
}

/* ---- Marketing page (/lp/) ----------------------------------------------
   Its images are placeholders in /static/lp/. */
.lp {
  display: grid;
  gap: clamp(3rem, 8vw, 6rem);
  max-width: var(--page-max-width);
  margin-inline: auto;
  padding-block: clamp(2rem, 6vw, 4rem);
}

.lp img {
  display: block;
  max-width: 100%;
  height: auto;
}

.lp-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
  align-items: center;
}

.lp-hero h1 {
  max-width: 16ch;
  text-wrap: balance;
}

.lp-lead {
  max-width: 36rem;
  font-size: clamp(1.1rem, 1.8vw, 1.35rem);
  line-height: 1.5;
  color: var(--color-text-body);
}

.lp-hero-art {
  width: min(100%, 30rem);
  justify-self: center;
}

.lp-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
}

.lp .lp-button {
  display: inline-flex;
  color: var(--color-accent-contrast);
}

.lp-section h2 {
  text-wrap: balance;
}

.lp-points {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Beat the body-copy bullet style (li:not(.nav-list li)). */
.lp-points > li.card {
  margin: 0;
  padding: clamp(min(1.25rem, 6vw), 2vw, 2rem);
  list-style: none;
}

.lp-points h3,
.lp-steps h3 {
  margin: 0;
}

.lp-points p,
.lp-steps p {
  margin: 0;
}

.lp-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: lp-step;
}

.lp-steps > li.stack-sm {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-increment: lp-step;
}

.lp-steps > li img {
  width: min(100%, 10rem);
}

.lp-steps h3::before {
  content: counter(lp-step) ". ";
  color: var(--color-text-muted);
}

.lp-compare {
  width: 100%;
  border-collapse: collapse;
}

.lp-compare th,
.lp-compare td {
  padding: var(--space-3) clamp(var(--space-2), 2vw, var(--space-4));
  border-bottom: 1px solid var(--color-border);
  text-align: start;
  vertical-align: top;
}

.lp-compare thead th {
  font-family: var(--font-display);
  font-size: 1.1rem;
}

.lp-compare tbody th {
  font-weight: 600;
}

.lp-compare td:last-child {
  font-weight: 600;
}

.lp-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
  align-items: center;
}

.lp-split > img {
  width: min(100%, 16rem);
  justify-self: center;
}

.lp-split-photo > img {
  width: 100%;
  border-radius: var(--radius-lg);
}

.lp-closing {
  text-align: center;
}

.lp-closing .lp-actions {
  justify-content: center;
}

@media (min-width: 48rem) {
  .lp-hero {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  }

  .lp-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  }

  .lp-split-photo {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  }
}
