:root {
  /* Tina brand tokens (from tina.io) */
  --orange: #ec4815;
  --orange-600: #d13f13;
  --orange-100: #ffede4;
  --orange-50: #fff8f3;
  --blue: #0084ff;
  --blue-900: #1d2c6c;
  --ink: #00255b;
  --heading: #14141a;
  --seafoam-100: #e9fbf4;
  --seafoam-300: #b4efd9;
  --seafoam-600: #72c39b;
  --seafoam-700: #529c7b;
  --seafoam-800: #39745c;

  --bg: #f8fafc;
  --surface: #ffffff;
  --border: #e2e8f0;
  --border-strong: #cbd5e1;
  --text: #0f172a;
  --text-2: #64748b;

  --radius: 16px;
  --shadow: 0 1px 3px rgb(20 70 150 / 0.07), 0 2px 6px -1px rgb(20 70 150 / 0.07);
  --shadow-panel: 6px 4px 16px rgba(0, 132, 255, 0.07),
    10px 8px 32px rgba(0, 132, 255, 0.07), 18px 16px 64px rgba(0, 132, 255, 0.1);
  --font-head: 'IBM Plex Sans', system-ui, sans-serif;
  --font-body: 'Inter', system-ui, sans-serif;
}

* {
  box-sizing: border-box;
  margin: 0;
}

body {
  font-family: var(--font-body);
  color: var(--text);
  background: var(--bg);
  /* Base bumped from the browser default 16px: the report is dense, reference-
     style reading, and at 16px it tested as too small. Everything else is in
     rem, so this scales the whole page. */
  font-size: 1.0625rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Branded background glow, echoing the seafoam/blue of the main site. */
body::before {
  content: '';
  position: fixed;
  inset: 0 0 auto 0;
  height: 70vh;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(70% 55% at 50% -8%, rgba(147, 233, 190, 0.28), transparent 62%),
    radial-gradient(55% 45% at 88% 2%, rgba(0, 132, 255, 0.12), transparent 60%),
    radial-gradient(45% 40% at 10% 6%, rgba(236, 72, 21, 0.06), transparent 60%);
}

.wrap {
  max-width: 56rem;
  margin: 0 auto;
  padding: 0 1.5rem;
  width: 100%;
}

.page {
  flex: 1 0 auto;
  /* The llama flies past the hero's right edge, which at some widths is also
     the viewport's. clip rather than hidden: hidden would make this a scroll
     container and break the sticky header. */
  overflow-x: clip;
}

/* Header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(248, 250, 252, 0.8);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  max-width: 90rem;
  margin: 0 auto;
  padding: 0.75rem 2rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.brand img {
  display: block;
}

.header-nav {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.header-nav > a:not(.btn) {
  font-weight: 500;
  color: var(--blue-900);
  text-decoration: none;
  font-size: 0.95rem;
}

.header-nav > a:not(.btn):hover {
  color: var(--orange-600);
}

.header-nav .btn {
  padding: 0.35rem 1.1rem;
  font-size: 0.9rem;
}

@media (max-width: 520px) {
  .header-nav a:not(.btn) {
    display: none;
  }
}

a {
  color: var(--orange-600);
}

h1,
h2,
h3 {
  font-family: var(--font-head);
  color: var(--heading);
  line-height: 1.15;
  font-weight: 600;
}

/* Hero: copy on the left, the short on the right, both centred against the
   phone, which is the tallest thing in the row. Wider than .wrap on purpose —
   the report below stays at reading width, the hero does not. */
.hero {
  width: min(100% - 3rem, 71rem);
  margin-inline: auto;
  /* The extra top padding is headroom for the llama, which flies about 65px
     above the frame — without it the card sits closer to the header than to
     the report below. */
  padding: 5.75rem 0 1rem;
  display: grid;
  grid-template-columns: 1.32fr 1fr;
  column-gap: 4rem;
  align-items: center;
}

.hero-copy {
  min-width: 0;
  /* The error row under the form always reserves its height (see .error), so
     add that height back on top to keep the copy centred against the frame. */
  margin-top: 2.5rem;
}

.hero .error {
  margin-inline: 0;
}

/* tina.io's hero badge: white pill, light blue hairline, YouTube mark inline */
.yt-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 1.3rem 0.3rem 0.8rem;
  border: 1px solid #b3d9ff;
  border-radius: 999px;
  background: var(--surface);
  color: var(--blue);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.875rem;
  text-decoration: none;
  box-shadow: var(--shadow);
}

.yt-badge:hover {
  border-color: var(--blue);
}

.yt-badge svg {
  display: block;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--seafoam-100);
  color: var(--seafoam-800);
  font-size: 0.875rem;
  font-weight: 600;
  padding: 0.4rem 1rem;
  border-radius: 999px;
}

.hero h1 {
  font-size: clamp(2.1875rem, 5vw, 3.75rem);
  line-height: 1.09;
  margin: 1.5rem 0 0;
}

.hero h1 .hl {
  color: var(--orange);
}

.hero p.lead {
  max-width: 42rem;
  margin: 1.5rem auto 0;
  color: var(--text-2);
  font-size: 1.125rem;
}

/* Form */
.analyze-form {
  display: flex;
  gap: 0.75rem;
  max-width: 34rem;
  margin: 2.5rem 0 0;
}

/* Hero controls sit a little shorter than the report's inputs and buttons */
.analyze-form input[type='text'],
.analyze-form .btn {
  padding-block: 0.7rem;
}

.input-wrap {
  position: relative;
  flex: 1;
}

.input-wrap svg {
  position: absolute;
  left: 1rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-2);
}

input[type='text'],
input[type='email'],
input[type='tel'] {
  width: 100%;
  font: inherit;
  font-size: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.input-wrap input {
  padding-left: 3rem;
}

input:focus {
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgb(236 72 21 / 0.18);
}

.btn {
  font: inherit;
  font-weight: 600;
  font-family: var(--font-head);
  color: #fff;
  background: linear-gradient(to bottom right, #ff724b, var(--orange-600));
  border: none;
  border-radius: 999px;
  padding: 0.85rem 1.75rem;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  white-space: nowrap;
  transition: transform 0.12s ease-out, box-shadow 0.12s ease-out, opacity 0.12s;
}

.btn:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow);
}

.btn:active {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.microcopy {
  margin-top: 1rem;
  font-size: 0.875rem;
  color: var(--text-2);
}

/* Error rows are always present and always reserve their height, so revealing
   one never shifts the form. Left aligned even inside centred blocks, because
   an error belongs with the field it refers to. */
.error {
  margin-top: 1rem;
  min-height: 1.5rem;
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  text-align: left;
  /* Same width and centring as .analyze-form, so the message starts flush with
     the left edge of the input it refers to rather than the section. */
  max-width: 34rem;
  margin-inline: auto;
  color: #b42318;
  font-size: 0.95rem;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.error.is-shown {
  opacity: 1;
}

.error .err-x {
  flex-shrink: 0;
  font-size: 0.9rem;
  line-height: 1.6;
}

.hidden {
  display: none !important;
}

/* Results */
.results {
  padding: 6rem 0 0;
  display: flex;
  flex-direction: column;
  gap: clamp(6rem, 15vh, 13rem);
}

.report {
  display: flex;
  flex-direction: column;
  gap: clamp(5rem, 11vh, 10rem);
}

.report-cats {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* Scroll-triggered reveal */
.reveal-enabled .reveal {
  opacity: 0;
  transform: translateY(30px);
  transition:
    opacity 0.6s ease,
    transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.reveal-enabled .reveal.reveal-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .reveal-enabled .reveal {
    transform: none;
    transition: opacity 0.3s ease;
  }
}

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

/* Version C: editorial / typographic ---------------------------------------- */
.editorial {
  align-self: center;
  display: flex;
  align-items: center;
  gap: clamp(2rem, 6vw, 4.5rem);
  margin: 1rem 0 0.5rem;
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.6s ease,
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.editorial.in {
  opacity: 1;
  transform: none;
}
.ed-main {
  display: grid;
  /* The column lands wider than the skeleton: the llama arrives and the
     hostname line fills in. JS parks that growth in a negative margin and
     releases it here, so the centred row glides out instead of snapping.
     See sizeFigure. */
  transition: margin-right 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  justify-items: start;
  gap: 0.4rem;
  padding-right: clamp(2rem, 6vw, 4.5rem);
  border-right: 1px solid var(--border);
}
.ed-figure {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  font-family: var(--font-head);
  color: var(--heading);
  line-height: 0.9;
}
.ed-num {
  font-weight: 700;
  /* 22vw rather than 12vw so the size is continuous across the 680px
     breakpoint; at 12vw it dropped from 160px to 92px crossing it. */
  font-size: clamp(5.5rem, 22vw, 9rem);
  font-variant-numeric: tabular-nums;
  /* The skeleton reserves the widest score there is, so the column is settled
     before the result lands. JS then narrows it to the digits actually needed,
     so a two-digit score sits against the llama rather than across a digit of
     dead space, and sizeFigure eases the difference. */
  min-width: 3ch;
}
.ed-bar {
  width: 100%;
  height: 4px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}
.ed-bar-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: var(--heading);
}
.editorial.loading .ed-bar-fill {
  width: 30%;
  animation: ed-indeterminate 1.1s ease-in-out infinite;
}
.editorial.loaded .ed-bar-fill {
  width: var(--w);
  transition:
    width 0.9s cubic-bezier(0.22, 1, 0.36, 1),
    background 0.9s ease;
}
@keyframes ed-indeterminate {
  0% {
    transform: translateX(-110%);
  }
  100% {
    transform: translateX(400%);
  }
}
/* Host on its own line, check count beneath it, with the llama as a byline
   mark to the left. Beside the score it read as an exponent; here it has a
   baseline to sit on. */
/* Flex row with an explicit image height, not a grid row-span with
   align-self: stretch. Stretching an <img> with height:auto is laid out
   differently by WebKit, where the image collapsed and painted over the text. */
.ed-scored {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.8rem;
  font-size: 0.9rem;
  color: var(--text-2);
}

.ed-llama {
  flex-shrink: 0;
  height: 2.65rem;
  width: auto;
}

.ed-scored-text {
  display: grid;
  gap: 0.1rem;
  min-width: 0;
}

.ed-scored .ed-host {
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere;
}

.ed-stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.85rem;
  /* Wide enough that the longest category label still fits on one line at the
     larger base font size */
  min-width: min(29rem, 48vw);
}
.ed-stats li {
  display: grid;
  grid-template-columns: 1fr 6rem auto;
  align-items: center;
  gap: 0.9rem;
  opacity: 0;
  transform: translateX(12px);
  transition:
    opacity 0.5s ease,
    transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.editorial.loaded .ed-stats li {
  opacity: 1;
  transform: none;
}
.es-cat {
  color: var(--text-2);
  font-size: 0.98rem;
}
.es-track {
  height: 3px;
  border-radius: 999px;
  background: var(--border);
}
.es-fill {
  display: block;
  height: 100%;
  width: var(--w);
  border-radius: inherit;
  background: var(--border-strong);
}
.es-num {
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 680px) {
  .editorial {
    flex-direction: column;
    gap: 1.75rem;
  }
  .ed-main {
    justify-items: center;
    padding-right: 0;
    border-right: 0;
  }
  .ed-stats {
    min-width: min(24rem, 88vw);
  }
  /* Stacked layout gives the score the full width, so scale it to the viewport
     instead of sitting on the desktop clamp's 5.5rem floor. */
  .ed-num {
    font-size: min(30vw, 10rem);
  }
}

/* Version C section-score colours are computed per-score in JS (smooth hue
   ramp red -> yellow -> green); the es-fill transition eases the reveal. */
.es-fill {
  transition: background 0.5s ease;
}

/* Report header: plain label + Copy-as-Markdown button on the right */
.report-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 1.5rem;
  flex-wrap: wrap;
  margin: 0.5rem 0 1.5rem;
}
.report-head h2 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--heading);
}
/* Let the heading block shrink so the copy buttons stay on the same row as the
   heading instead of wrapping underneath it */
.report-head-text {
  flex: 1 1 14rem;
  min-width: 0;
}

.report-head-text p {
  color: var(--text-2);
  font-size: 0.9rem;
  margin-top: 0.2rem;
}
.btn-ghost {
  color: var(--orange-600);
  background: transparent;
  border: 1px solid var(--border-strong);
  padding: 0.6rem 1.1rem;
  font-size: 0.9rem;
}
.btn-ghost:hover {
  background: var(--orange-50);
  border-color: var(--orange);
}

.report-head-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* Blocker banner: shown above the top fixes when the page cannot be reached or
   indexed at all, so the capped score explains itself. */
.blockers {
  border: 1px solid #fecaca;
  border-left: 4px solid #dc2626;
  background: #fef2f2;
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
}

.blockers h3 {
  font-family: var(--font-head);
  font-size: 1.125rem;
  color: #991b1b;
}

.blockers p {
  color: var(--text-2);
  font-size: 0.875rem;
  margin-top: 0.3rem;
}

.blockers ul {
  margin: 0.75rem 0 0;
  padding-left: 1.1rem;
  color: #7f1d1d;
  font-size: 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

/* "Copy prompt for your coding agent" inside a check's fix panel */
.btn-prompt {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.85rem;
  padding: 0.45rem 0.8rem;
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  /* Pill, matching every other button */
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.btn-prompt:hover {
  color: var(--orange-600);
  border-color: var(--border-strong);
}

.btn-prompt svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* Label sits in its own span so the "Copied ✓" swap replaces like with like.
   The button's width is pinned in JS for the duration of the swap. */
.btn-label {
  white-space: nowrap;
}

/* Top fixes -> full report / gate: keep a clear gap between the two sections */
.post-tease {
  display: flex;
  flex-direction: column;
  gap: clamp(3rem, 7vh, 5rem);
}

.fixes h3 {
  font-size: 1.375rem;
  color: var(--heading);
}

.fix-list {
  list-style: none;
  padding: 0;
  margin: 0.75rem 0 0;
  display: flex;
  flex-direction: column;
}

.fix-item {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--border);
}

.fix-item:last-child {
  border-bottom: none;
}

.fix-num {
  flex-shrink: 0;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--border-strong);
  color: var(--text-2);
  font-size: 0.8rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}

.fix-item .lbl {
  display: block;
  font-weight: 600;
}

.fix-item .why {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.85rem;
  color: var(--text-2);
}

.fix-item .read-more {
  margin-top: 0.4rem;
}

/* Lead gate */
.gate {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-panel);
}

.gate .peek {
  position: absolute;
  inset: 0;
  padding: 6rem 1.5rem 0;
  opacity: 0.4;
  filter: blur(3px);
  pointer-events: none;
  user-select: none;
}

.gate .peek span {
  display: block;
  height: 1rem;
  border-radius: 4px;
  background: var(--border-strong);
  margin-bottom: 0.75rem;
}

.gate .inner {
  position: relative;
  text-align: center;
  /* Less bottom padding than top: the error row below the button already
     reserves its own space, so an even 3rem left a dead gap. */
  padding: 3rem 1.5rem 1.25rem;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.5), #fff);
}

.gate .lock {
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--orange-100);
  color: var(--orange-600);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Lock sits beside the heading, not stacked above it */
.gate-title {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  text-align: left;
  /* Hostnames can be long and unbreakable, so let them wrap rather than
     overflow the card and shove the lock off-screen */
  overflow-wrap: anywhere;
  min-width: 0;
  margin-inline: auto;
  font-family: var(--font-head);
  font-weight: 600;
  line-height: 1.05;
  color: var(--heading);
  /* Same ramp as the "Talk to a Tina Expert" banner heading, so the two
     section headings read as the same level. */
  font-size: clamp(1.75rem, 3.6vw, 2.5rem);
}

/* A long hostname cannot sit at full heading size without filling the card and
   breaking mid-word, so step the whole heading down. Short hosts keep the
   larger size, which is the common case. */
.gate-title.is-long {
  font-size: clamp(1.3rem, 2.4vw, 1.7rem);
  max-width: 26rem;
}

/* Break before the host rather than mid-label, so it reads
   "See full report for" / "long-host.example.com" */
.gate-title.is-long .gate-host {
  display: block;
}

/* Break the host at its punctuation rather than anywhere in the string */
.gate-host {
  overflow-wrap: break-word;
  word-break: break-word;
}

.gate p {
  max-width: 34rem;
  margin: 0.9rem auto 0;
  color: var(--text-2);
  font-size: 1.05rem;
}

.gate form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 30rem;
  margin: 1.5rem auto 0;
}

/* Turnstile renders a fixed 300px iframe; centre it and let the row collapse
   to nothing until the widget actually mounts. */
.turnstile {
  display: flex;
  justify-content: center;
}

.turnstile:empty {
  display: none;
}

/* Categories */
.category {
  overflow: hidden;
}

.cat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--border);
  background: rgba(248, 250, 252, 0.6);
  flex-wrap: wrap;
}

.cat-head h3 {
  font-size: 1.125rem;
}

.cat-head p {
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: var(--text-2);
  max-width: 40rem;
}

.cat-score {
  font-family: var(--font-head);
  font-size: 1.5rem;
  color: var(--blue-900);
}

.cat-score small {
  font-size: 0.875rem;
  color: var(--text-2);
  font-family: var(--font-body);
}

.checks {
  padding: 0 1.5rem;
}

.check {
  border-bottom: 1px solid var(--border);
}

.check:last-child {
  border-bottom: none;
}

.check-btn {
  width: 100%;
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  text-align: left;
  background: none;
  border: none;
  padding: 1rem 0;
  cursor: pointer;
  font: inherit;
}

.check-icon {
  flex-shrink: 0;
  margin-top: 2px;
}

.check-main {
  flex: 1;
}

.check-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-weight: 500;
  color: var(--text);
}

.check-detail {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: var(--text-2);
}

.chevron {
  color: var(--text-2);
  transition: transform 0.2s;
}

.check.open .chevron {
  transform: rotate(180deg);
}

.check-body {
  display: none;
  padding: 0 0 1rem 1.75rem;
}

.check.open .check-body {
  display: block;
}

.check-body .box {
  background: var(--bg);
  border-radius: 10px;
  padding: 1rem;
  font-size: 0.875rem;
}

.check-body .box p + p {
  margin-top: 0.5rem;
  color: var(--text-2);
}

.badge-ev {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  text-decoration: none;
  margin-top: 0.75rem;
}

.ev-official {
  background: #dceeff;
  color: #144696;
}

.ev-study {
  background: var(--seafoam-100);
  color: var(--seafoam-800);
}

.ev-opinion {
  background: #f1f5f9;
  color: var(--text-2);
}

.ev-experimental {
  background: var(--orange-50);
  color: var(--orange-600);
}

.badge-ev .src {
  font-weight: 400;
  opacity: 0.75;
}

.ev-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-top: 0.75rem;
}

.ev-row .badge-ev {
  margin-top: 0;
}

.read-more {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--orange-600);
  text-decoration: none;
}

.read-more:hover {
  text-decoration: underline;
}

/* In the references list the row sits above the prose, not inline with it. */
.refs .ev-row {
  margin-top: 0;
  margin-bottom: 0.35rem;
}

/* Icons via status color */
.i-pass {
  color: var(--seafoam-600);
}
.i-warn {
  color: #f59e0b;
}
.i-fail {
  color: var(--orange-600);
}
.i-info {
  color: var(--blue);
}

/* Next steps + references */
.next h3 {
  font-size: 1.375rem;
}

.tool-grid {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  margin-top: 1rem;
}

.tool {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 1.25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.tool:hover {
  border-color: var(--orange);
  box-shadow: var(--shadow);
}

.tool .name {
  display: block;
  font-weight: 600;
}

.tool .note {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: var(--text-2);
}

.refs {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0 1.5rem;
}

.refs summary {
  cursor: pointer;
  padding: 1rem 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--heading);
}

.refs ul {
  list-style: none;
  padding: 0;
  margin: 0.25rem 0 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.refs p {
  margin-top: 0.5rem;
  font-size: 0.875rem;
  color: var(--text-2);
}

footer.site {
  flex-shrink: 0;
  margin-top: 4rem;
  border-top: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.6);
}

.footer-inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 2rem 1.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  text-align: center;
}

.footer-brand img {
  display: block;
  opacity: 0.9;
}

.footer-tag {
  color: var(--text-2);
  font-size: 0.9rem;
}

.footer-links {
  display: flex;
  gap: 1.5rem;
  margin-top: 0.25rem;
}

.footer-links a {
  color: var(--blue-900);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 500;
}

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

.footer-copy {
  color: var(--text-2);
  font-size: 0.8rem;
  margin-top: 0.5rem;
}

@media (max-width: 640px) {
  .analyze-form,
  .gate form {
    flex-direction: column;
  }
  .summary {
    justify-content: center;
    text-align: center;
  }
}

/* "Made for your AI" feature section */
.agent-feature {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
  align-items: center;
  background: #0e0e12;
  border-radius: var(--radius);
  padding: 2.5rem;
}

/* Metal behind the right side, faded to the black background toward the left. */
.agent-metal {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, transparent 40%, #000 88%);
  mask-image: linear-gradient(to right, transparent 0%, transparent 40%, #000 88%);
}

.agent-feature > :not(.agent-metal) {
  position: relative;
  z-index: 1;
}

.agent-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--seafoam-300);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.agent-feature h2 {
  color: #fff;
  font-size: clamp(1.5rem, 3vw, 2rem);
  margin-top: 0.75rem;
  line-height: 1.15;
}

.agent-feature p {
  color: rgba(255, 255, 255, 0.66);
  margin-top: 0.85rem;
  font-size: 1rem;
  max-width: 32rem;
}

.agent-feature .btn {
  margin-top: 1.5rem;
}

.agent-code {
  background: rgba(23, 23, 28, 0.8);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}

.agent-code-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 0.85rem;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.agent-code-bar i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #d13f13;
}

.agent-code-bar i:nth-child(2) {
  background: #f59e0b;
}

.agent-code-bar i:nth-child(3) {
  background: #72c39b;
}

.agent-code-bar em {
  margin-left: 0.5rem;
  font-style: normal;
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.5);
  font-family: var(--font-body);
}

.agent-code pre {
  margin: 0;
  max-height: 20rem;
  overflow: auto;
  padding: 1rem 1.15rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78rem;
  line-height: 1.55;
  color: #d4d9e3;
  white-space: pre-wrap;
  word-break: break-word;
}

/* "Read it yourself" divider */
.read-yourself {
  text-align: center;
  padding-top: 1rem;
}

.read-yourself h3 {
  font-size: 1.375rem;
}

.read-yourself p {
  margin-top: 0.35rem;
  color: var(--text-2);
  font-size: 0.95rem;
}

@media (max-width: 720px) {
  .agent-feature {
    grid-template-columns: 1fr;
    padding: 1.75rem;
  }
  /* Stacked: text on top, code below — fade the metal bottom-up so the text
     keeps its contrast against the dark background. */
  .agent-metal {
    -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 55%);
    mask-image: linear-gradient(to top, #000 0%, transparent 55%);
  }
}

/* Liquid-metal border frame */
.metal-frame {
  position: relative;
  display: inline-flex;
  vertical-align: top;
  padding: var(--mt, 2px);
  border-radius: calc(var(--mr, 12px) + var(--mt, 2px));
  isolation: isolate;
}

.metal-frame.block {
  display: block;
}

.metal-frame > canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  z-index: 0;
  pointer-events: none;
}

.metal-frame > :not(canvas) {
  position: relative;
  z-index: 1;
}

.metal-frame.block > :not(canvas) {
  width: 100%;
}

/* Static fallback ring when WebGL2 is unavailable */
.metal-fallback {
  background: linear-gradient(135deg, #e8e8ee, #9a9aa4 40%, #f4f4f8 55%, #7d7d88 70%, #dcdce4);
}

/* Fill mode: metal is the element's whole background (buttons) */
.metal-frame.fill {
  padding: 0;
  overflow: hidden;
  border-radius: var(--mr);
}

.metal-frame.fill > canvas {
  border-radius: var(--mr);
}

.metal-frame.fill > .btn {
  background: transparent;
  color: #fff;
  text-shadow:
    0 0 14px rgba(0, 0, 0, 0.6),
    0 1px 6px rgba(0, 0, 0, 0.7),
    0 0 3px rgba(0, 0, 0, 0.6);
}

.metal-frame.fill > .btn svg {
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.7));
}

.metal-frame.fill > .btn:hover {
  color: #fff;
  transform: none;
}

/* Metal fill buttons: keep the lift/press hover the plain buttons had */
.metal-frame.fill {
  transition: transform 0.15s ease, filter 0.15s ease;
}

.metal-frame.fill:hover {
  transform: translateY(-1px);
  filter: brightness(1.08);
}

.metal-frame.fill:active {
  transform: translateY(1px);
}

/* Keep coated buttons from overflowing their flex row */
.analyze-form .metal-frame,
.gate form .metal-frame {
  flex-shrink: 0;
}

.gate form input {
  flex: 1;
  min-width: 0;
}

/* Contact banner with a metal-filled llama */
/* Bottom callout — matches tina.io's "Talk to a Tina Expert" card:
   text left, outline llama right, soft white card, orange rounded-rect button. */
.cta-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2.5rem;
  margin: clamp(4.5rem, 9vh, 7.5rem) 0 4rem;
  background: linear-gradient(135deg, #ffffff, #f3f8ff);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 10px 40px rgba(20, 70, 150, 0.08);
  padding: clamp(2.25rem, 5vw, 3.5rem);
  overflow: hidden;
}

.cta-text {
  max-width: 34rem;
}

.cta-text h2 {
  font-family: var(--font-head);
  font-weight: 600;
  /* Kept in step with .gate-title so the two section headings match */
  font-size: clamp(1.75rem, 3.6vw, 2.5rem);
  line-height: 1.05;
  color: var(--heading);
}

.cta-text p {
  margin-top: 0.9rem;
  color: var(--text-2);
  font-size: 1.125rem;
  max-width: 30rem;
}

/* Pill everywhere, matching .btn. Shape is inherited; this class only equalises
   size, so the gate's submit button and "Schedule Call" look identical. */
.cta-btn {
  padding: 0.7rem 1.5rem;
  font-size: 1rem;
}

.cta-text .cta-btn {
  margin-top: 1.75rem;
}

/* Auto width and centred, matching Schedule Call rather than stretching to the
   full width of the form */
.gate form .cta-btn {
  align-self: center;
  margin-top: 0.5rem;
}

/* The gate's error sits close under the button; it still reserves its row. */
.gate .error {
  margin-top: 0.6rem;
}

.cta-llama-outline {
  flex-shrink: 0;
  width: clamp(120px, 17vw, 165px);
  height: auto;
  align-self: center;
}

@media (max-width: 560px) {
  /* Long hostnames need a smaller heading to stay inside the card */
  .gate-title {
    font-size: 1.4rem;
    gap: 0.65rem;
  }
  .gate .lock {
    width: 2.25rem;
    height: 2.25rem;
  }
  .gate .inner {
    padding: 2.25rem 1.25rem;
  }
}

@media (max-width: 640px) {
  .cta-banner {
    flex-direction: column-reverse;
    text-align: center;
    gap: 1.5rem;
    padding: 2rem;
  }
  .cta-text p,
  .cta-btn {
    margin-inline: auto;
  }
  .cta-llama-outline {
    width: 120px;
  }
}

.next .refs {
  margin-top: 1.75rem;
}

/* Scroll hint: appears if the user lingers at the top after a result loads */
.scroll-hint {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 3.5rem 1rem 1.35rem;
  color: var(--text-2);
  font-size: 0.85rem;
  font-weight: 500;
  background: linear-gradient(to top, var(--bg) 22%, rgba(248, 250, 252, 0) 100%);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  pointer-events: none;
}

.scroll-hint.show {
  opacity: 1;
  transform: none;
}

.scroll-hint svg {
  animation: scroll-bob 1.4s ease-in-out infinite;
}

@keyframes scroll-bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(5px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-hint svg {
    animation: none;
  }
}

/* The short, framed like a phone and tilted off-square. The frame, the caption
   and the llama are siblings so only the frame carries the rotation — a tilted
   caption reads as a mistake rather than a flourish. */
.hero-video {
  position: relative;
  width: min(310px, 58vw);
  margin-inline: auto;
}

/* Seafoam wash behind the phone, echoing the page glow */
.hero-video::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: -32%;
  top: 32%;
  width: 66%;
  height: 41%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(150, 235, 235, 0.65), rgba(150, 235, 235, 0));
}

.short {
  display: block;
  position: relative;
  width: 100%;
  aspect-ratio: 9 / 16;
  padding: 0;
  border: 4px solid var(--orange);
  border-radius: 28px;
  background: #0e0e12;
  overflow: hidden;
  cursor: pointer;
  transform: rotate(2deg);
  box-shadow: 0 18px 44px rgba(0, 60, 120, 0.14);
}

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

/* The player letterboxes itself inside its box, so oversize it and let the
   frame clip the bars off */
.short iframe {
  position: absolute;
  top: -2%;
  left: -2%;
  width: 104%;
  height: 104%;
  border: 0;
}

/* YouTube's play button in Tina orange, on the same gradient as .btn */
.short-play {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 88px;
  height: 62px;
  border-radius: 14px;
  display: grid;
  place-items: center;
  background: linear-gradient(to bottom right, #ff724b, var(--orange-600));
  transition: transform 0.15s ease-out;
}

.short:hover .short-play {
  transform: scale(1.06);
}

.short-caption {
  position: absolute;
  left: 50%;
  /* Clear of the player's own controls once the video is running */
  bottom: -24px;
  /* The frame is rotated, so its bottom edge centres ~10px left of the box.
     The caption takes the frame's full tilt so it reads as part of the card.
     Chrome rounds each glyph's baseline to a whole pixel row, so the letters
     step slightly along the tilt. Measured across will-change, perspective(1px)
     + backface-visibility, filter, opacity, text-stroke and SVG <text>: every
     one snaps by the same 0.27px RMS at 1x, so none of them is worth carrying.
     Only unrotated text or baked outlines avoid it. */
  transform: translateX(calc(-50% - 10px)) rotate(2deg);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.4rem 1.1rem;
  line-height: 0;
  box-shadow: 0 4px 14px rgba(0, 60, 120, 0.12);
}

/* Baked at 4x, so it stays sharp on hidpi and downscales cleanly */
.short-caption img {
  display: block;
  width: 231.09px;
  height: auto;
}

/* Percentages keep the llama pinned to the frame's top-right corner as the
   frame scales down */
.hero-llama {
  position: absolute;
  width: 50%;
  height: auto;
  right: -27%;
  top: -11.8%;
  pointer-events: none;
}

/* Stacked hero: copy centred above the short */
@media (max-width: 880px) {
  .hero {
    grid-template-columns: 1fr;
    /* The invisible error row under the form supplies part of the gap; the
       rest is headroom for the llama, which flies above the frame */
    row-gap: 2.25rem;
    padding-top: 2rem;
    text-align: center;
  }

  .hero-copy {
    margin-top: 0;
  }

  .yt-badge {
    font-size: 0.8125rem;
    padding-block: 0.25rem;
  }

  .hero h1 {
    margin-top: 1rem;
    /* Breaks the title over three lines, as in the mockup — a full-width line
       of 35px type reads as a wall on a phone */
    max-width: 12ch;
    margin-inline: auto;
  }

  .analyze-form {
    flex-direction: column;
    margin-top: 1.5rem;
    margin-inline: auto;
  }

  .short-caption img {
    width: 198px;
  }


  .hero .error {
    margin-inline: auto;
  }
}

/* Fix-subcard link row: docs on the left, SSW rule on the right */
.link-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.6rem 1.25rem;
  flex-wrap: wrap;
  margin-top: 0.85rem;
}

.lr-left {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.ssw-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--orange-600);
  text-decoration: none;
  white-space: nowrap;
}

.ssw-link:hover {
  text-decoration: underline;
}

/* --- Easter egg: analysing tina.io ------------------------------------------
   Two offset llama layers make a proper tessellation rather than a plain grid.
   Both fade in after the score lands, and honour reduced-motion. */
.llama-mode body::after,
html.llama-mode body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* llama-tile.svg pads the llama inside its tile. The first attempt tiled the
     bare mark, which fills its box edge to edge, so the half-offset second layer
     landed on top of the first and merged into an abstract blob rather than a
     tessellation. */
  background-image: url('/geo/llama-tile.svg'), url('/geo/llama-tile.svg');
  background-size: 104px 78px, 104px 78px;
  background-position: 0 0, 52px 39px;
  opacity: 0;
  animation: llama-fade 1.6s ease 0.35s forwards;
}

@keyframes llama-fade {
  to { opacity: 0.028; }
}

/* The llama turns up beside every score and dances to it. Four bands, from
   the full routine at 90+ down to a droop under 40. Three layers so the
   animations never fight over transform: wrapper owns the entrance, img owns
   the routine, ::after is the contact shadow. */
.dancer {
  position: relative;
  /* Stands on the digits' baseline, not the flex line's bottom edge. The line
     box runs 11px past the baseline, and flex-end put the llama's feet down
     there, reading as though it were sunk below the number. The img is
     display:block, so this wrapper's baseline is its own bottom edge. */
  align-self: baseline;
  display: block;
  transform-origin: 50% 100%;
  animation: dancer-rise 0.6s cubic-bezier(0.2, 1.6, 0.4, 1) 0.75s both;
  margin-left: 0.7rem;
}

/* Masked rather than an <img> so the mark takes the score's colour, and
   rather than inlining the paths so llama.svg stays the one source for the
   shape. aspect-ratio pins the width off the viewBox, so the row is sized
   before the mask file lands. */
.dancer-mark {
  display: block;
  height: clamp(3.8rem, 14vw, 6rem);
  aspect-ratio: 141.81 / 196.6;
  background: currentColor;
  -webkit-mask: url('/geo/llama.svg') center / contain no-repeat;
  mask: url('/geo/llama.svg') center / contain no-repeat;
  /* Feet stay planted, so squash and tilt pivot from the ground. */
  transform-origin: 50% 100%;
  animation-delay: 1.35s;
  animation-iteration-count: infinite;
}

/* Shrinks and fades on the airborne beats, which is what reads as a hop
   rather than a wobble. */
.dancer::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -0.32rem;
  width: 68%;
  height: 0.42rem;
  border-radius: 50%;
  background: rgb(15 23 42 / 0.16);
  animation-delay: 1.35s;
  animation-iteration-count: infinite;
}

@keyframes dancer-rise {
  from { transform: translateY(120%) scale(0.65); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* --- 90+ : the full routine ------------------------------------------------
   Easing is per-segment rather than on the animation: ease-out up, ease-in
   down. A single ease-in-out across the whole loop floats instead of bounces. */
.dancer.is-hype .dancer-mark { animation-name: dancer-hype; animation-duration: 2.6s; }
.dancer.is-hype::after { animation-name: dancer-shadow-hype; animation-duration: 2.6s; }

@keyframes dancer-hype {
  0% { transform: perspective(520px) translate(0, 0) rotate(0deg) rotateY(0deg) scale(1, 1);
       animation-timing-function: ease-out; }
  6% { transform: perspective(520px) translate(-2%, -32%) rotate(-12deg) rotateY(0deg) scale(0.94, 1.07);
       animation-timing-function: ease-in; }
  13% { transform: perspective(520px) translate(-4%, 0) rotate(-5deg) rotateY(0deg) scale(1.08, 0.92);
        animation-timing-function: ease-out; }
  19% { transform: perspective(520px) translate(0, -32%) rotate(12deg) rotateY(0deg) scale(0.94, 1.07);
        animation-timing-function: ease-in; }
  26% { transform: perspective(520px) translate(4%, 0) rotate(5deg) rotateY(0deg) scale(1.08, 0.92);
        animation-timing-function: ease-out; }
  32% { transform: perspective(520px) translate(2%, -32%) rotate(-12deg) rotateY(0deg) scale(0.94, 1.07);
        animation-timing-function: ease-in; }
  39% { transform: perspective(520px) translate(-4%, 0) rotate(-5deg) rotateY(0deg) scale(1.08, 0.92);
        animation-timing-function: ease-out; }
  45% { transform: perspective(520px) translate(0, -32%) rotate(12deg) rotateY(0deg) scale(0.94, 1.07);
        animation-timing-function: ease-in; }
  52% { transform: perspective(520px) translate(4%, 0) rotate(5deg) rotateY(0deg) scale(1.08, 0.92);
        animation-timing-function: ease-in; }
  /* Crouch, then a full turn on the spot. */
  60% { transform: perspective(520px) translate(2%, 2%) rotate(0deg) rotateY(0deg) scale(1.14, 0.86);
        animation-timing-function: ease-out; }
  74% { transform: perspective(520px) translate(0, -42%) rotate(0deg) rotateY(180deg) scale(0.94, 1.06);
        animation-timing-function: ease-in; }
  86% { transform: perspective(520px) translate(0, 0) rotate(0deg) rotateY(360deg) scale(1.12, 0.88);
        animation-timing-function: ease-out; }
  93% { transform: perspective(520px) translate(0, -10%) rotate(0deg) rotateY(360deg) scale(0.98, 1.02);
        animation-timing-function: ease-in; }
  100% { transform: perspective(520px) translate(0, 0) rotate(0deg) rotateY(360deg) scale(1, 1); }
}

@keyframes dancer-shadow-hype {
  0%, 13%, 26%, 39%, 52%, 86%, 100% { transform: translateX(-50%) scale(1); opacity: 1; }
  60% { transform: translateX(-50%) scale(1.12); opacity: 1; }
  6%, 19%, 32%, 45%, 93% { transform: translateX(-50%) scale(0.6); opacity: 0.42; }
  74% { transform: translateX(-50%) scale(0.42); opacity: 0.28; }
}

/* --- 70-89 : a happy bounce, no spin -------------------------------------- */
.dancer.is-happy .dancer-mark { animation-name: dancer-happy; animation-duration: 1.45s; }
.dancer.is-happy::after { animation-name: dancer-shadow-2beat; animation-duration: 1.45s; }

@keyframes dancer-happy {
  0%, 100% { transform: translate(0, 0) rotate(-7deg) scale(1.05, 0.95);
             animation-timing-function: ease-out; }
  25% { transform: translate(-2%, -24%) rotate(0deg) scale(0.97, 1.03);
        animation-timing-function: ease-in; }
  50% { transform: translate(0, 0) rotate(7deg) scale(1.05, 0.95);
        animation-timing-function: ease-out; }
  75% { transform: translate(2%, -24%) rotate(0deg) scale(0.97, 1.03);
        animation-timing-function: ease-in; }
}

/* --- 40-69 : a modest sway with small hops -------------------------------- */
.dancer.is-ok .dancer-mark { animation-name: dancer-ok; animation-duration: 2.1s; }
.dancer.is-ok::after { animation-name: dancer-shadow-2beat; animation-duration: 2.1s; }

@keyframes dancer-ok {
  0%, 100% { transform: translate(0, 0) rotate(-4deg) scale(1.02, 0.98);
             animation-timing-function: ease-out; }
  25% { transform: translate(0, -9%) rotate(0deg) scale(0.99, 1.01);
        animation-timing-function: ease-in; }
  50% { transform: translate(0, 0) rotate(4deg) scale(1.02, 0.98);
        animation-timing-function: ease-out; }
  75% { transform: translate(0, -9%) rotate(0deg) scale(0.99, 1.01);
        animation-timing-function: ease-in; }
}

@keyframes dancer-shadow-2beat {
  0%, 50%, 100% { transform: translateX(-50%) scale(1); opacity: 1; }
  25%, 75% { transform: translateX(-50%) scale(0.72); opacity: 0.55; }
}

/* --- under 40 : a droop --------------------------------------------------- */
/* Head-down lean and a sag, breathing slowly. Nothing leaves the ground, so
   the shadow just sits there at full size. */
.dancer.is-droop .dancer-mark { animation-name: dancer-droop; animation-duration: 3.8s;
                       animation-timing-function: ease-in-out; }
.dancer.is-droop::after { animation: none; }

@keyframes dancer-droop {
  0%, 100% { transform: translate(0, 2%) rotate(3deg) scale(1.02, 0.94); }
  50%      { transform: translate(0, 3%) rotate(6deg) scale(1.03, 0.92); }
}

@media (prefers-reduced-motion: reduce) {
  .llama-mode body::after { animation: none; opacity: 0.028; }
  .dancer { animation: dancer-fade-in 0.4s ease-out 0.75s both; }
  /* JS skips the absorb entirely here, so there is nothing to ease. */
  .ed-main { transition: none; }
  /* One gentle rock for every band. No hop, no spin, no travel, no scaling:
     what the spec calls large-scale movement all goes, and what is left keeps
     the llama from being a static sticker. */
  .dancer-mark,
  .dancer.is-hype .dancer-mark,
  .dancer.is-happy .dancer-mark,
  .dancer.is-ok .dancer-mark,
  .dancer.is-droop .dancer-mark {
    animation: dancer-sway 3.4s ease-in-out 1.15s infinite;
  }
  /* The band is still legible without motion: the droop keeps its lean, held
     on the wrapper so it does not fight the sway on the mark. */
  .dancer.is-droop { transform: rotate(5deg); }
  /* The shadow only exists to sell the hop. Nothing leaves the ground here,
     so a shadow parked under a rocking llama just reads as a smudge. */
  .dancer::after { display: none; }
}

@keyframes dancer-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes dancer-sway {
  0%, 100% { transform: rotate(-2.5deg); }
  50%      { transform: rotate(2.5deg); }
}
