/* ==========================================================================
   sections.css - page-specific sections, top to bottom
   hero > sponsors > contributors > compatibility > statement poster > skills > release
   > projects > support > footer
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hero
   Measured composition: a tall LIGHT stone-textured hero carrying dark type,
   with a draggable field of drifting image tiles in 3D perspective behind it.
   The copy sits on the plain upper zone so the tiles can never sit under the
   headline and eat its contrast; the field is its own full-bleed band below.
   The hero ground was measured at an average RGB of 213,206,198.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  padding-block: clamp(2.5rem, 5vw, 4rem) 0;
  background-color: var(--stone);
  overflow: hidden;
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--hero-glow);
  pointer-events: none;
}

.hero > .container {
  position: relative;
  z-index: var(--z-copy);
}

/* Hero main: 3D stage layout - grid 1fr + 1.1fr at desktop,
   copy left centred on mobile, left-aligned at desktop. */
.hero__main {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 4vw, 3rem);
  align-items: start;
}

.hero__copy {
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

@media (min-width: 992px) {
  .hero__main {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: clamp(2rem, 4vw, 3rem);
    align-items: stretch;
    min-height: min(82vh, 560px);
  }

  .hero__copy {
    max-width: 36rem;
    margin-inline: 0;
    text-align: left;
    justify-content: center;
  }

  .hero__copy .hero__title {
    margin-inline: 0;
  }

  .hero__copy .hero__body {
    margin-inline: 0;
  }

  .hero__actions {
    justify-content: flex-start;
  }
}

.hero__chip {
  border-color: var(--accent-line);
  background-color: var(--violet-wash);
  color: var(--text);
}

/* The measured status dot pulses on a 1.5s ping. */
.hero__dot {
  position: relative;
  display: inline-block;
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background-color: var(--accent);
}

.hero__dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background-color: inherit;
  animation: hero-ping 1.5s cubic-bezier(0, 0, 0.2, 1) infinite;
}

@keyframes hero-ping {
  0% {
    transform: scale(1);
    opacity: 0.7;
  }

  75%,
  100% {
    transform: scale(2.6);
    opacity: 0;
  }
}

/* The install panel is centred under the copy at the panel's own width. */
.hero__install {
  max-width: 46rem;
  margin: var(--space-8) auto 0;
}

/* --- tile field ---------------------------------------------------------
   Desktop is a 3D perspective carousel
   (perspective 3400px, 7 figures at 62% width, rounded 18px, depth -1000..+273)
   Mobile: hidden - replaced by horizontal marquee. */

.hero__stage {
  position: relative;
  height: clamp(17rem, 30vw, 26rem);
  margin-top: clamp(1.5rem, 4vw, 2rem);
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
}

.hero__stage.is-dragging {
  cursor: grabbing;
}

.hero__field {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}

/* Mobile base - simple centred stack, will be hidden at lg anyway */
.hero__tile {
  position: absolute;
  left: calc(50% + var(--tx, 0%));
  top: calc(50% + var(--ty, 0%));
  width: var(--tw, 14rem);
  margin: 0;
  aspect-ratio: 1200 / 780;
  border-radius: 18px;
  overflow: hidden;
  background-color: var(--bg-deep);
  box-shadow: 0 22px 44px -26px rgb(10 10 10 / 45%);
  transform: translate(-50%, -50%) rotate(var(--tr, 0deg));
}

.hero__tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}

.hero__tile:nth-child(1) { --tx: -40%; --ty: -14%; --tr: -7deg; --tw: 15rem; }
.hero__tile:nth-child(2) { --tx: -20%; --ty: 26%; --tr: 4deg; --tw: 12rem; }
.hero__tile:nth-child(3) { --tx: 18%; --ty: -24%; --tr: 6deg; --tw: 14rem; }
.hero__tile:nth-child(4) { --tx: 38%; --ty: 18%; --tr: -5deg; --tw: 16rem; }
.hero__tile:nth-child(5) { --tx: 0%; --ty: 4%; --tr: -2deg; --tw: 18rem; }
.hero__tile:nth-child(6) { --tx: -58%; --ty: 22%; --tr: 9deg; --tw: 11rem; }
.hero__tile:nth-child(7) { --tx: 58%; --ty: -8%; --tr: -9deg; --tw: 13rem; }

/* Desktop 3D carousel - shifted right so it doesn't sit under left text */
@media (min-width: 992px) {
  .hero__stage {
    position: relative;
    width: 100%;
    max-width: 680px;
    height: 580px;
    max-height: 82vh;
    margin-top: 0;
    margin-left: auto;
    margin-right: -8px;
    transform: translateX(18px);
    perspective: 3400px;
    overflow: visible;
    background: transparent;
    border: none;
    box-shadow: none;
    align-self: center;
    justify-self: end;
  }

  .hero__field {
    inset: 0;
    transform: rotateX(3deg) rotateY(-4deg);
    transform-style: preserve-3d;
  }

  /* 7 figures exactly like live: 64% width, centred, 3D depth handled by JS */
  .hero__tile {
    width: 64%;
    left: 50%;
    top: 50%;
    --tw: 64%;
    border-radius: 18px;
    box-shadow: 0 14px 30px -12px rgba(10,10,10,0.28);
    will-change: transform, opacity;
    transform: translate3d(-50%, -50%, 0) rotateX(0) rotateY(0) scale(1);
  }

  /* Remove old scatter at desktop - JS owns positions */
  .hero__tile:nth-child(1),
  .hero__tile:nth-child(2),
  .hero__tile:nth-child(3),
  .hero__tile:nth-child(4),
  .hero__tile:nth-child(5),
  .hero__tile:nth-child(6),
  .hero__tile:nth-child(7) {
    --tx: 0%; --ty: 0%; --tr: 0deg;
  }
}

/* Once JavaScript owns the positions it drives the inline transform directly;
   left/top stay at the 50%/50% centre anchor set above, since the JS offsets
   (translate(-50%, -50%) plus x/y) are computed relative to that centre. */
.hero__field.is-live .hero__tile {
  /* Promoted only while the loop is actually running. */
  will-change: transform;
}

/* --- mobile fallback ----------------------------------------------------
   Below the desktop layout the field is replaced by the measured 32s linear
   horizontal image marquee, which costs no JavaScript at all. */

.hero__flow {
  display: none;
}

@media (max-width: 991.98px) {
  .hero__stage {
    display: none;
  }

  .hero__flow {
    display: block;
    margin-top: clamp(2rem, 6vw, 3rem);
    overflow: hidden;
  }

  .hero__flow-track {
    display: flex;
    width: max-content;
    animation: hero-flow 32s linear infinite;
  }

  /* Two identical groups. The trailing padding makes the -50% shift land on a
     seam, so the loop has no visible jump. */
  .hero__flow-group {
    display: flex;
    flex: none;
    gap: var(--space-4);
    padding-right: var(--space-4);
  }

  .hero__flow figure {
    flex: none;
    width: 13rem;
    margin: 0;
    aspect-ratio: 16 / 11;
    border-radius: var(--radius-tile);
    overflow: hidden;
    background-color: var(--bg-deep);
  }

  .hero__flow img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

@keyframes hero-flow {
  from {
    transform: translate3d(0, 0, 0);
  }

  to {
    transform: translate3d(-50%, 0, 0);
  }
}

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

  .hero__stage {
    cursor: default;
  }

  .hero__flow-track {
    animation: none;
  }
}

.hero__title {
  max-width: 24ch;
  margin: var(--space-6) auto 0;
  font-size: var(--fs-display-1);
  font-weight: 600;
  letter-spacing: var(--tracking-display);
  line-height: var(--lh-display);
}

/* Measured: 18px / 500 / accent. The live value is the raw accent, which is only
   2.4:1 on the stone ground - it fails AA for text this size. --accent-text is the
   solved equivalent at 4.8:1. See FINAL_AUDIT.md section 6. */
.hero__lede {
  margin-top: var(--space-5);
  color: var(--accent-text);
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.4;
}

.hero__body {
  max-width: var(--measure-muted);
  margin: var(--space-4) auto 0;
  color: var(--muted);
  text-wrap: pretty;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-8);
}

/* --------------------------------------------------------------------------
   Sponsors - a ledger of three tiers, each opened by one top hairline.
   No logos are reproduced; see FINAL_AUDIT.md section 6.
   -------------------------------------------------------------------------- */

.tier {
  height: 100%;
  padding-top: var(--space-5);
  border-top: 1px solid var(--line);
}

.tier__label {
  color: var(--faint);
}

/* The gold tier carries the one measured second tone in the palette. */
.tier--gold .tier__label {
  color: var(--gold);
}

.tier__list {
  display: grid;
  gap: var(--space-5);
  margin-top: var(--space-6);
}

/* Explicit grid items: min-width keeps long sponsor names from forcing the
   track wider than its column. */
.sponsor,
.rule {
  min-width: 0;
}

.sponsor__name {
  color: var(--text);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.tier--gold .sponsor__name {
  font-size: 1.25rem;
  letter-spacing: -0.02em;
}

.sponsor__desc {
  margin-top: 0.125rem;
  max-width: 34ch;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.55;
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   Contributor wall
   -------------------------------------------------------------------------- */

.contributors__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-5);
}

.contributors__title {
  max-width: 28ch;
  font-size: clamp(1.25rem, 2.2vw, 1.75rem);
  letter-spacing: var(--tracking-heading);
  line-height: 1.2;
}

.contributors__count {
  color: var(--accent-text);
  font-family: var(--font-mono);
  font-weight: 500;
}

.avatar-wall {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-8);
}

.avatar {
  position: relative;
  display: block;
  width: 2.75rem;
  height: 2.75rem;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background-color: var(--surface-2);
  transition: border-color var(--dur) ease, transform var(--dur) var(--ease);
}

.avatar:hover {
  border-color: var(--accent-line);
  transform: translateY(-2px);
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Error state: GitHub avatar could not be loaded, fall back to an initial. */
.avatar__fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--faint);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {
  .avatar,
  .avatar:hover {
    transition: none;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Compatibility
   -------------------------------------------------------------------------- */

.compat-stage {
  position: relative;
  min-height: clamp(34rem, 74vw, 48rem);
  padding-block: clamp(5rem, 10vw, 8rem) clamp(3rem, 7vw, 5rem);
  border-top: 1px solid var(--line);
  overflow: hidden;
}

/* Original in-house backdrop: a routing schematic. A core chip sits in the
   copy column's clear bottom-left zone and two quiet bus rails carry packets
   through the outer margins — the floating cards are the surfaces. Paper base
   lives in CSS; the artwork is inline SVG in the markup (no image asset) and
   packets ride the rails via SMIL, so no JS is involved. */
.compat-stage__bg {
  position: absolute;
  inset: 0;
  background: linear-gradient(150deg, #faf9f7 0%, #f1efec 52%, #eae7e2 100%);
}

.compat-stage__schematic {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
}

/* Bottom fade keeps the hand-off to the statement band seamless. */
.compat-stage__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgb(245 244 242 / 0%) 0%,
    rgb(245 244 242 / 0%) 55%,
    rgb(245 244 242 / 55%) 82%,
    var(--bg) 100%
  );
}

.schematic__label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  fill: rgb(31 26 22 / 42%);
}

.schematic__pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: compat-core-pulse 3s var(--ease) infinite;
}

@keyframes compat-core-pulse {
  0%,
  100% {
    transform: scale(0.7);
    opacity: 0.9;
  }

  70% {
    transform: scale(2.1);
    opacity: 0;
  }
}

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

  .schematic__pulse {
    animation: none;
  }
}

/* On small screens the copy is centered and the artwork would only fight it —
   the stage keeps a quiet paper wash instead. */
@media (max-width: 991.98px) {
  .compat-stage__schematic {
    display: none;
  }
}

.compat-stage > .container {
  position: relative;
  z-index: var(--z-copy);
}

.compat-stage__hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}

.compat-stage__copy {
  max-width: 31rem;
}

.compat__title {
  font-size: clamp(2.25rem, 5vw, 4.75rem);
  letter-spacing: var(--tracking-heading);
  line-height: 0.98;
}

.compat__body {
  margin-top: var(--space-4);
  max-width: 35rem;
  color: var(--muted);
  text-wrap: pretty;
}

.compat__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-7);
}

.compat-stage__cards {
  position: relative;
  min-height: clamp(18rem, 38vw, 31rem);
}

.compat-stage__card {
  position: absolute;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
  filter: drop-shadow(0 22px 28px rgb(20 20 20 / 18%));
  transition: filter var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
  will-change: transform;
}

.compat-stage__card:hover {
  filter: drop-shadow(0 36px 46px rgb(15 15 15 / 28%));
  transform: translateY(-8px) scale(1.03);
}

.compat-stage__card img {
  display: block;
  width: 100%;
  height: auto;
}

.compat-stage__card--terminal {
  z-index: 2;
  top: 4%;
  left: 4%;
  width: min(42%, 20rem);
  rotate: -2deg;
}

.compat-stage__card--system {
  z-index: 3;
  top: 0;
  right: 13%;
  width: min(34%, 15.5rem);
  rotate: 1deg;
}

.compat-stage__card--skill {
  z-index: 4;
  left: 20%;
  bottom: 12%;
  width: min(24%, 10.75rem);
  rotate: -1deg;
}

.compat-stage__card--mark {
  z-index: 5;
  left: 43%;
  bottom: 17%;
  width: min(27%, 12.5rem);
  rotate: 2deg;
}

.compat-stage__card--code {
  z-index: 4;
  right: 2%;
  bottom: 7%;
  width: min(30%, 14rem);
  rotate: -1deg;
}

.compat-stage__agents {
  margin-top: clamp(2rem, 5vw, 4rem);
  text-align: center;
}

.agent-strip {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.agent-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: clamp(5.5rem, 9vw, 7rem);
  min-height: 5.75rem;
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background-color: rgb(255 255 255 / 82%);
  box-shadow: 0 12px 28px -22px rgb(10 10 10 / 40%);
  backdrop-filter: blur(12px) saturate(135%);
  -webkit-backdrop-filter: blur(12px) saturate(135%);
  transition: border-color var(--dur) ease, background-color var(--dur) ease,
    transform var(--dur) var(--ease);
}

.agent-tile:hover {
  border-color: var(--line-strong);
  background-color: var(--surface);
  transform: translateY(-3px);
}

.agent-tile img {
  width: 1.75rem;
  height: 1.75rem;
  object-fit: contain;
}

.agent-tile span {
  color: var(--muted);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

@media (min-width: 992px) {
  .compat-stage__hero {
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  }

  .compat-stage__copy {
    padding-left: clamp(1rem, 6vw, 6rem);
  }
}

@media (max-width: 991.98px) {
  .compat-stage {
    min-height: auto;
    padding-block: clamp(4rem, 12vw, 6rem);
  }

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

  .compat__actions {
    justify-content: center;
  }

  .compat-stage__cards {
    min-height: 25rem;
    max-width: 40rem;
    margin-inline: auto;
  }

  .compat-stage__card--terminal {
    left: 2%;
    width: 42%;
  }

  .compat-stage__card--system {
    right: 4%;
    width: 37%;
  }
}

@media (max-width: 575.98px) {
  .compat-stage__cards {
    min-height: 18rem;
  }

  .compat-stage__copy {
    max-width: 21rem;
  }

  .compat__title {
    font-size: clamp(2.35rem, 11vw, 3rem);
  }

  .compat__body {
    max-width: 19rem;
    margin-inline: auto;
    font-size: var(--fs-small);
  }

  .compat-stage__card--terminal {
    left: -3%;
    top: 6%;
    width: 54%;
  }

  .compat-stage__card--system {
    right: -2%;
    top: 4%;
    width: 48%;
  }

  .compat-stage__card--skill {
    left: 7%;
    bottom: 14%;
    width: 34%;
  }

  .compat-stage__card--mark {
    left: 36%;
    bottom: 15%;
    width: 36%;
  }

  .compat-stage__card--code {
    right: 0;
    bottom: 11%;
    width: 38%;
  }

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

  .agent-tile {
    width: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .compat-stage__card,
  .compat-stage__card:hover,
  .agent-tile,
  .agent-tile:hover {
    transition: none;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Statement poster
   The page's single kinetic moment. The visible sentence is decorative because
   the same phrase is exposed by the section's hidden heading.
   -------------------------------------------------------------------------- */

.band-poster {
  position: relative;
  padding-block: clamp(4rem, 9vw, 7rem);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background-color: var(--bg);
  overflow: hidden;
}

.band-poster__glow {
  position: absolute;
  width: clamp(16rem, 34vw, 28rem);
  aspect-ratio: 1;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(56px);
}

.band-poster__glow--left {
  left: min(-12vw, -5rem);
  bottom: 22%;
  background-color: rgb(255 107 0 / 5%);
}

.band-poster__glow--right {
  right: min(-12vw, -5rem);
  top: 20%;
  background-color: rgb(114 106 98 / 14%);
}

/* A faint data bus running the width of the band behind the sentence —
   the same schematic language as the compat stage above, so the two
   sections read as one system. Packets reuse .schematic__packets, which
   the reduced-motion rules already hide. */
.band-poster__bus {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.band-poster__copy {
  position: relative;
  z-index: var(--z-copy);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.375rem, 1vw, 0.75rem);
  text-align: center;
}

/* Screen-reader heading carries the whole sentence. Bootstrap pins
   visually-hidden text to one nowrap line, and as an absolutely-positioned
   descendant it inflates the section's scrollable overflow on narrow
   screens — so it may wrap here. It has no visual rendering to disturb. */
.band-poster > .visually-hidden {
  white-space: normal !important;
}

.band-poster__line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(0.75rem, 2.5vw, 1.5rem);
}

.band-poster__line--baseline {
  align-items: baseline;
}

.band-poster__line--end {
  gap: clamp(0.5rem, 1.5vw, 1rem);
}

.band-poster__word {
  display: inline-block;
  color: var(--text);
  font-size: clamp(3rem, 8vw, 8rem);
  font-weight: 600;
  letter-spacing: -0.055em;
  line-height: 0.92;
}

.band-poster__word--accent {
  color: var(--accent);
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.05;
  padding-bottom: 0.05em;
}

.band-poster__word--ink {
  color: var(--text);
}

.band-poster__word--ship {
  color: var(--accent);
}

.band-poster__pill {
  position: relative;
  display: inline-block;
  flex: none;
  overflow: hidden;
  border: 1px solid rgb(10 10 10 / 10%);
  border-radius: var(--radius-pill);
  background-color: var(--surface-2);
  box-shadow: 0 10px 30px -12px rgb(0 0 0 / 28%);
  transform-origin: center;
}

.band-poster__pill--land {
  width: clamp(6rem, 14vw, 11.125rem);
  height: clamp(2.375rem, 5.5vw, 4.75rem);
  rotate: -8deg;
}

.band-poster__pill--code {
  width: clamp(6.875rem, 15vw, 12.5rem);
  height: clamp(2.5rem, 5.8vw, 5rem);
  rotate: 6deg;
}

.band-poster__pill svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* Commit node: an orange station dot with a ring, from the schematic
   language above. Replaces the template's star spark. */
.band-poster__node {
  position: relative;
  display: inline-block;
  flex: none;
  width: clamp(1.5rem, 3.2vw, 2.5rem);
  aspect-ratio: 1;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
}

.band-poster__node::after {
  content: "";
  position: absolute;
  inset: 30%;
  border-radius: 50%;
  background-color: var(--accent);
}

/* Deploy packet: a dot leaving a fading trail — the pipeline shipping.
   Replaces the template's flame blob. */
.band-poster__packet {
  position: relative;
  display: inline-block;
  flex: none;
  width: clamp(2.5rem, 5.5vw, 4.5rem);
  height: clamp(0.75rem, 1.6vw, 1.25rem);
}

.band-poster__packet::before {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: 38%;
  aspect-ratio: 1;
  transform: translateY(-50%);
  border-radius: 50%;
  background-color: var(--accent);
}

.band-poster__packet::after {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 58%;
  height: 3px;
  transform: translateY(-50%);
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--accent));
}

html.js .band-poster__copy {
  opacity: 1;
  transform: none;
}

html.js .band-poster__copy .band-poster__word--rise {
  opacity: 0;
  filter: blur(12px);
  transform: translate3d(0, 70px, 0);
}

html.js .band-poster__copy .band-poster__word--slide {
  opacity: 0;
  filter: blur(8px);
  transform: translate3d(-28px, 0, 0);
}

html.js .band-poster__copy .band-poster__word--wide {
  opacity: 0;
  filter: blur(8px);
  transform: translate3d(-80px, 0, 0);
}

html.js .band-poster__copy .band-poster__pill--land {
  opacity: 0;
  transform: scale(0.45) rotate(-14deg);
}

html.js .band-poster__copy .band-poster__pill--code {
  opacity: 0;
  transform: scale(0.5) rotate(14deg);
}

html.js .band-poster__copy .band-poster__node,
html.js .band-poster__copy .band-poster__packet {
  opacity: 0;
  transform: scale(0.2);
}

html.js .band-poster__copy.is-revealed .band-poster__word,
html.js .band-poster__copy.is-revealed .band-poster__pill,
html.js .band-poster__copy.is-revealed .band-poster__node,
html.js .band-poster__copy.is-revealed .band-poster__packet {
  opacity: 1;
  filter: none;
  transform: none;
  transition: opacity 760ms var(--ease), filter 760ms var(--ease),
    transform 900ms var(--ease);
}

html.js .band-poster__copy.is-revealed .band-poster__pill--land {
  transition-delay: 80ms;
}

html.js .band-poster__copy.is-revealed .band-poster__word--accent {
  transition-delay: 140ms;
}

html.js .band-poster__copy.is-revealed .band-poster__line:nth-child(2) .band-poster__word--rise {
  transition-delay: 220ms;
}

html.js .band-poster__copy.is-revealed .band-poster__node {
  transition-delay: 310ms;
}

html.js .band-poster__copy.is-revealed .band-poster__word--ink {
  transition-delay: 360ms;
}

html.js .band-poster__copy.is-revealed .band-poster__pill--code {
  transition-delay: 430ms;
}

html.js .band-poster__copy.is-revealed .band-poster__word--ship {
  transition-delay: 540ms;
}

html.js .band-poster__copy.is-revealed .band-poster__packet {
  transition-delay: 620ms;
}

@media (prefers-reduced-motion: no-preference) {
  .band-poster__copy.is-revealed .band-poster__pill {
    animation: band-poster-float 5.8s var(--ease) infinite;
  }

  .band-poster__copy.is-revealed .band-poster__pill--code {
    animation-delay: -2.4s;
  }

  .band-poster__copy.is-revealed .band-poster__node {
    animation: band-poster-node-ping 3.2s var(--ease) infinite 1s;
  }

  .band-poster__copy.is-revealed .band-poster__packet {
    animation: band-poster-packet-run 2.8s var(--ease) infinite 1.1s;
  }
}

@keyframes band-poster-float {
  0%,
  100% {
    translate: 0 0;
  }

  50% {
    translate: 0 -8px;
  }
}

@keyframes band-poster-node-ping {
  0%,
  100% {
    scale: 1;
    opacity: 1;
  }

  50% {
    scale: 1.15;
    opacity: 0.7;
  }
}

@keyframes band-poster-packet-run {
  0%,
  100% {
    translate: 0 0;
  }

  50% {
    translate: 10px 0;
  }
}

@media (max-width: 575.98px) {
  .band-poster {
    padding-block: clamp(3.25rem, 16vw, 5rem);
  }

  .band-poster__line {
    max-width: 100%;
    gap: 0.5rem;
  }

  .band-poster__word {
    font-size: clamp(2.5rem, 12.5vw, 3.35rem);
    letter-spacing: -0.05em;
  }

  .band-poster__pill--land {
    width: clamp(4.5rem, 20vw, 5.5rem);
    height: clamp(1.9rem, 8vw, 2.4rem);
  }

  .band-poster__pill--code {
    width: clamp(5rem, 22vw, 6rem);
    height: clamp(2rem, 8.5vw, 2.55rem);
  }

  .band-poster__node {
    width: clamp(1.1rem, 5vw, 1.5rem);
  }

  .band-poster__packet {
    width: clamp(1.9rem, 9vw, 2.6rem);
    height: clamp(0.6rem, 3vw, 0.9rem);
  }

  .band-poster__bus {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html.js .band-poster__copy .band-poster__word,
  html.js .band-poster__copy .band-poster__pill,
  html.js .band-poster__copy .band-poster__node,
  html.js .band-poster__copy .band-poster__packet {
    opacity: 1;
    filter: none;
    transform: none;
    transition: none;
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   Skills catalogue
   -------------------------------------------------------------------------- */

.skills__grid {
  margin-top: var(--space-8);
}

/* --------------------------------------------------------------------------
   Release / v2
   Rules are grouped in a two-column grid and separated by space, not by a
   hairline under every row.
   -------------------------------------------------------------------------- */

.rules {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-7) var(--space-8);
  margin-top: var(--space-9);
}

.rule__id {
  color: var(--accent-text);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-label);
}

.rule__title {
  margin-top: var(--space-3);
  font-size: var(--fs-h3);
  letter-spacing: -0.02em;
}

.rule__desc {
  margin-top: var(--space-2);
  max-width: var(--measure-card);
  color: var(--muted);
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  text-wrap: pretty;
}

.release__note {
  margin-top: var(--space-9);
}

.release__note-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

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

/* --------------------------------------------------------------------------
   Showcase
   -------------------------------------------------------------------------- */

.projects__grid {
  margin-top: var(--space-8);
}

.projects__invite {
  margin-top: var(--space-7);
  color: var(--muted);
  font-size: var(--fs-body-sm);
}

/* --------------------------------------------------------------------------
   Support
   Closing ledger: statement left, single action right. No centred CTA stack.
   -------------------------------------------------------------------------- */

.support__panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: clamp(1.5rem, 3vw, 2.5rem);
  border: 1px solid var(--line);
  /* The measured 24px radius belongs to the large panels. */
  border-radius: var(--radius-lg);
  background-color: var(--surface);
}

.support__media {
  overflow: hidden;
  width: 100%;
  max-width: 12rem;
  border-radius: var(--radius);
  background-color: var(--surface-2);
}

.support__media img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.support__copy {
  flex: 1 1 auto;
}

.support__title {
  /* Measured at 60px: one of the quieter display steps, not the 96px one. */
  font-size: var(--fs-display-3);
  letter-spacing: var(--tracking-heading);
  line-height: var(--lh-heading);
}

.support__body {
  margin-top: var(--space-4);
  max-width: var(--measure-muted);
  color: var(--muted);
  text-wrap: pretty;
}

.support__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

@media (min-width: 992px) {
  .support__panel {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-9);
  }

  .support__actions {
    flex: none;
  }
}

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

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

.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}

.footer__blurb {
  margin-top: var(--space-4);
  max-width: 34ch;
  color: var(--muted);
  font-size: var(--fs-body-sm);
  text-wrap: pretty;
}

.footer__heading {
  color: var(--faint);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 400;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.footer__list {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.footer__list a,
.footer__list span {
  color: var(--muted);
  font-size: var(--fs-body-sm);
}

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

.footer__install .code-block {
  margin-top: var(--space-4);
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-10);
  padding-top: var(--space-5);
  border-top: 1px solid var(--line);
  color: var(--faint);
  font-size: 0.8125rem;
}

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

@media (min-width: 992px) {
  .footer__grid {
    grid-template-columns: 1.5fr 1fr 1fr 1.7fr;
    gap: var(--space-8);
  }
}
