/* =========================================================================
   Additive layer, loaded after styles.css.

   This file exists because styles.css was not readable from the environment
   these rules were written in. Everything here therefore uses class names that
   appear nowhere in styles.css, so nothing collides and nothing is overridden
   by accident. It should be folded into styles.css once that file can be
   edited again; until then it is a clean, self-contained layer rather than a
   pile of !important.

   Depends only on the custom properties styles.css defines on :root:
   --ink --paper --muted --line --green --page --pad --ease
   ========================================================================= */

/* -------------------------------------------------------------------------
   The hero signal rail.

   Replaces three cards that said "OPEN SOURCE / Inspect it. Change it." in
   three identical boxes. Three boxes in a row is the shape every open-source
   landing page uses, and the shape carried no meaning here.

   This is one strip with three readouts on it: an index, the claim, and the
   state that backs the claim up. It behaves like an instrument — a light
   follows the pointer along it, and a slow sweep crosses it when nobody is
   touching it — so it reads as live without anything moving all the time.
   ------------------------------------------------------------------------- */

.sigrail {
  position: relative;
  isolation: isolate;
  width: min(100%, 780px);
  margin: 0 0 auto;
  border-top: 1px solid rgba(255, 255, 255, .16);
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  /* Pointer position, in px from the rail's left edge. Set by app.js. */
  --sig-x: -200px;
}

/* The light that tracks the pointer. Sits under the text, over the rail. */
.sigrail-glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s var(--ease);
  background: radial-gradient(
    170px 120px at var(--sig-x) 50%,
    rgba(121, 255, 54, .13),
    rgba(121, 255, 54, .04) 45%,
    transparent 72%
  );
}
.sigrail[data-live='true'] .sigrail-glow { opacity: 1; }

/* The idle sweep: a hairline crossing the rail, not a shimmer over everything.
   It stops the moment the rail is being used, because then it is redundant. */
.sigrail-sweep {
  position: absolute;
  z-index: 0;
  top: -1px;
  left: 0;
  height: 1px;
  width: 34%;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--green), transparent);
  opacity: .55;
  animation: sigSweep 7.5s var(--ease) infinite;
}
.sigrail[data-live='true'] .sigrail-sweep { animation-play-state: paused; opacity: 0; }
@keyframes sigSweep {
  0%, 12% { transform: translateX(-100%); opacity: 0; }
  22% { opacity: .55; }
  62% { opacity: .55; }
  76%, 100% { transform: translateX(294%); opacity: 0; }
}

.sigrail-list {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}
.sigrail-item + .sigrail-item { border-left: 1px solid rgba(255, 255, 255, .09); }

/* A plain wrapper, deliberately not a heading. These are disclosure controls,
   and as <h2> they sat above the page's own <h1> in the document outline.
   aria-expanded and aria-controls already carry the semantics. */
.sigrail-h { margin: 0; font: inherit; font-weight: inherit; }

.sigrail-trigger {
  display: grid;
  gap: 9px;
  width: 100%;
  padding: 16px 18px 15px;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background .35s var(--ease);
}
.sigrail-trigger:hover { background: rgba(255, 255, 255, .028); }

.sigrail-idx {
  font-size: 9px;
  letter-spacing: .3em;
  color: rgba(242, 242, 236, .3);
  transition: color .35s var(--ease);
}
.sigrail-trigger:hover .sigrail-idx,
.sigrail-trigger[aria-expanded='true'] .sigrail-idx { color: var(--green); }

.sigrail-name {
  font-size: clamp(13px, 1.15vw, 17px);
  font-weight: 500;
  letter-spacing: -.015em;
  text-transform: uppercase;
  line-height: 1.05;
  color: var(--paper);
}
/* The asterisk is a promise that something is qualified, so it is visible
   enough to notice and the panel below answers it. */
.sigrail-name em {
  font-style: normal;
  color: var(--green);
  padding-left: 2px;
}

.sigrail-state {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 9.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .42);
}
.sigrail-state i {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(242, 242, 236, .3);
  transition: background .35s var(--ease), box-shadow .35s var(--ease);
}
.sigrail-trigger:hover .sigrail-state i,
.sigrail-trigger[aria-expanded='true'] .sigrail-state i {
  background: var(--green);
  box-shadow: 0 0 9px rgba(121, 255, 54, .75);
}

/*
 * The detail panel.
 *
 * The open height is written by app.js as an inline pixel value measured from
 * the content, rather than being chosen here.
 *
 * The CSS-only alternatives both have real costs. grid-template-rows 0fr -> 1fr
 * needs the container's height to stay indefinite, which is fragile inside a
 * grid item. A max-height cap animates the cap, so the easing describes a
 * distance the panel never travels and short content snaps open early.
 * Measuring gives an honest curve for any length of sentence, and works in
 * every browser rather than only recent ones.
 */
.sigrail-detail {
  overflow: hidden;
  height: 0;
  opacity: 0;
  transition: height .48s var(--ease), opacity .3s var(--ease);
}
/*
 * Opened from the list item, not from the button's next sibling.
 *
 * The trigger sits inside a wrapper, so the panel is that wrapper's sibling
 * rather than the button's, and an adjacent selector off the button silently
 * never matches. app.js sets data-open on the item, which does not care how
 * the markup is nested.
 */
.sigrail-item[data-open='true'] .sigrail-detail {
  opacity: 1;
  transition: height .48s var(--ease), opacity .34s var(--ease) .08s;
}

.sigrail-detail p {
  margin: 0;
  padding: 0 18px 4px;
  max-width: 34ch;
  font-size: 12.5px;
  line-height: 1.55;
  color: rgba(242, 242, 236, .58);
}
.sigrail-detail p em { font-style: normal; color: var(--green); }

.sigrail-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 9px 18px 16px;
  font-size: 9.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .55);
  transition: color .3s var(--ease);
}
.sigrail-link:hover { color: var(--paper); }
.sigrail-link i { font-style: normal; transition: transform .3s var(--ease); }
.sigrail-link:hover i { transform: translateX(4px); }

/* Tablet: still one rail, but the three readouts need more room each. */
@media (max-width: 1040px) {
  .sigrail { width: 100%; }
  .sigrail-trigger { padding: 14px 14px 13px; }
  .sigrail-detail p,
  .sigrail-link { padding-inline: 14px; margin-inline: 14px; }
  .sigrail-detail p { padding-inline: 14px; margin-inline: 0; }
}

/*
 * Phone: the rail becomes a stack.
 *
 * Three columns at 390px would give each claim about 110px, which breaks
 * "No paid X API" across three lines and makes the readout unreadable. Stacked,
 * each claim gets the full width and the dividers become horizontal — the same
 * instrument, turned ninety degrees.
 */
@media (max-width: 720px) {
  .sigrail-list { grid-template-columns: 1fr; }
  .sigrail-item + .sigrail-item {
    border-left: 0;
    border-top: 1px solid rgba(255, 255, 255, .09);
  }
  .sigrail-trigger {
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 0 12px;
    padding: 13px 4px;
  }
  .sigrail-idx { grid-column: 1; }
  .sigrail-name { grid-column: 2; font-size: 14px; }
  .sigrail-state { grid-column: 3; justify-self: end; }
  .sigrail-detail p { padding: 0 4px 4px; max-width: none; }
  .sigrail-link { margin: 8px 4px 14px; }
  /* The sweep is a desktop-idle flourish; on a phone it competes with reading. */
  .sigrail-sweep { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sigrail-sweep { animation: none; opacity: 0; }
  .sigrail-glow { transition: none; }
  .sigrail-detail { transition: none; }
  .sigrail-link i { transition: none; }
}


/* -------------------------------------------------------------------------
   Verification.

   The section removes itself when nothing is configured, so these rules only
   ever apply to a deployment that actually has something to show.
   ------------------------------------------------------------------------- */

.verify {
  position: relative;
  background: var(--ink);
  color: var(--paper);
  padding: clamp(80px, 11vh, 150px) var(--pad) clamp(80px, 10vh, 140px);
  overflow: clip;
}
.verify[hidden] { display: none; }

.verify-grid {
  max-width: var(--page);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(32px, 5vw, 90px);
  align-items: start;
}
.verify-lede p {
  margin: 26px 0 0;
  max-width: 40ch;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.65;
  color: var(--muted);
}

.verify-panels { display: grid; gap: 16px; }

.vcard {
  position: relative;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 16px;
  background: linear-gradient(150deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .018));
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  box-shadow: inset 0 1px rgba(255, 255, 255, .1);
  padding: clamp(18px, 2vw, 26px);
  transition: border-color .4s var(--ease);
}
.vcard[hidden] { display: none; }
.vcard:hover { border-color: rgba(255, 255, 255, .24); }

.vcard-head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 18px;
}
.vcard-idx { font-size: 9px; letter-spacing: .3em; color: rgba(242, 242, 236, .32); }
.vcard-head h3 {
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.vcard-tag {
  margin-left: auto;
  font-size: 9.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .38);
  text-align: right;
}

/* The checksum. Selectable, copyable, and wraps rather than scrolling. */
.vhash {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 16px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 11px;
  background: rgba(0, 0, 0, .3);
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.vhash:hover { border-color: rgba(121, 255, 54, .4); background: rgba(0, 0, 0, .45); }
.vhash-label {
  font-size: 8.5px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .35);
}
.vhash code {
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(10px, .82vw, 12px);
  line-height: 1.5;
  color: rgba(242, 242, 236, .78);
  overflow-wrap: anywhere;
  user-select: all;
}
.vhash-copy {
  font-size: 8.5px;
  letter-spacing: .2em;
  color: rgba(242, 242, 236, .4);
  transition: color .25s var(--ease);
}
.vhash:hover .vhash-copy { color: var(--green); }
.vhash.copied { border-color: rgba(121, 255, 54, .55); }
.vhash.copied .vhash-copy { color: var(--green); }

.vsteps { display: grid; gap: 8px; margin-top: 14px; }
.vstep {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr);
  gap: 12px;
  align-items: baseline;
  padding: 9px 12px;
  border-radius: 9px;
  background: rgba(255, 255, 255, .022);
}
.vstep span {
  font-size: 8.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .34);
}
.vstep code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  line-height: 1.5;
  color: rgba(242, 242, 236, .66);
  overflow-wrap: anywhere;
}

.vnote {
  margin: 14px 0 0;
  font-size: 11.5px;
  line-height: 1.55;
  color: rgba(242, 242, 236, .38);
}

/* The scan verdict, with a ring that draws itself once when it scrolls in. */
.vscan { display: flex; align-items: center; gap: 20px; }
.vscan-ring { position: relative; flex: none; width: 62px; height: 62px; }
.vscan-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.vscan-ring circle {
  fill: none;
  stroke: rgba(255, 255, 255, .09);
  stroke-width: 2;
}
.vscan-ring .arc {
  stroke: var(--green);
  stroke-linecap: round;
  stroke-dasharray: 214;
  stroke-dashoffset: 214;
}
.verify.in-view .vscan-ring .arc {
  animation: vScanDraw 1.5s var(--ease) .3s forwards;
}
@keyframes vScanDraw { to { stroke-dashoffset: 0; } }
.vscan-ring i {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-style: normal;
  color: var(--green);
  opacity: 0;
}
.vscan-ring i::before { content: '\2713'; font-size: 20px; }
.verify.in-view .vscan-ring i { animation: vScanTick .5s var(--ease) 1.4s forwards; }
@keyframes vScanTick { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }

.vscan-body { min-width: 0; }
.vscan-verdict {
  margin: 0;
  font-size: clamp(17px, 1.7vw, 24px);
  font-weight: 500;
  letter-spacing: -.025em;
  line-height: 1.15;
}
.vscan-vendor {
  margin: 7px 0 0;
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .45);
}
.vscan-subject {
  margin: 5px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  color: rgba(242, 242, 236, .35);
  overflow-wrap: anywhere;
}

.vreport {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  padding: 11px 18px;
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 999px;
  font-size: 10px;
  letter-spacing: .2em;
  text-transform: uppercase;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.vreport:hover { border-color: rgba(121, 255, 54, .5); background: rgba(121, 255, 54, .07); }
.vreport i { font-style: normal; transition: transform .3s var(--ease); }
.vreport:hover i { transform: translate(3px, -3px); }

@media (max-width: 900px) {
  .verify-grid { grid-template-columns: 1fr; gap: 34px; }
  .vhash { grid-template-columns: 1fr; gap: 8px; }
  .vhash-copy { justify-self: start; }
  .vstep { grid-template-columns: 1fr; gap: 4px; }
  .vscan { flex-direction: column; align-items: flex-start; gap: 14px; }
}


/* -------------------------------------------------------------------------
   The footer.

   The last thing on the page, so it gets to be a composition rather than a
   row of small links: an oversized wordmark whose letters light under the
   pointer, three columns of destinations, and a status readout that says what
   this build actually is.
   ------------------------------------------------------------------------- */

.foot {
  position: relative;
  background: var(--ink);
  color: var(--paper);
  padding: clamp(60px, 8vh, 110px) var(--pad) clamp(26px, 3vh, 40px);
  overflow: clip;
}
.foot::before {
  content: '';
  position: absolute;
  inset-inline: var(--pad);
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .18) 20%, rgba(255, 255, 255, .18) 80%, transparent);
}

.foot-top {
  max-width: var(--page);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(40px, 6vw, 110px);
  align-items: start;
}

.foot-word {
  display: flex;
  line-height: .82;
  font-size: clamp(64px, 13vw, 190px);
  font-weight: 700;
  letter-spacing: -.07em;
}
/* Each letter is its own element so the pointer can pick one out. Dimmed at
   rest; the one nearest the cursor comes up to full and lifts a little. */
.foot-word span {
  display: block;
  color: rgba(242, 242, 236, .28);
  transition: color .4s var(--ease), transform .4s var(--ease);
  will-change: transform;
}
.foot-word span.lit { color: var(--paper); transform: translateY(-.035em); }
.foot-word span.near { color: rgba(242, 242, 236, .62); }

.foot-line {
  margin: 22px 0 0;
  max-width: 34ch;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.6;
  color: var(--muted);
}

.foot-nav {
  display: grid;
  grid-auto-flow: column;
  gap: clamp(28px, 4vw, 70px);
  align-items: start;
}
.foot-col h2 {
  margin: 0 0 16px;
  font-size: 9px;
  font-weight: 400;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .32);
}
.foot-col[hidden] { display: none; }
.foot-col ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }

/*
 * The link hover is a wipe, not a colour change.
 *
 * A hairline grows from the left as the label steps aside for it, so the
 * gesture reads as the link being selected rather than merely highlighted.
 */
.foot-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding-left: 0;
  font-size: 13.5px;
  color: rgba(242, 242, 236, .62);
  transition: color .3s var(--ease), padding-left .3s var(--ease);
}
.foot-link::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 0;
  height: 1px;
  background: var(--green);
  transition: width .3s var(--ease);
}
.foot-link:hover,
.foot-link:focus-visible { color: var(--paper); padding-left: 20px; }
.foot-link:hover::before,
.foot-link:focus-visible::before { width: 13px; }
.foot-link i { font-style: normal; font-size: 10px; opacity: .5; }
.foot-link[aria-disabled='true'] { color: rgba(242, 242, 236, .34); }

.foot-status {
  max-width: var(--page);
  margin: clamp(44px, 6vh, 80px) auto 0;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, .08);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 34px;
}
.foot-stat {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 9.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .38);
}
.foot-stat[hidden] { display: none; }
.foot-stat i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(242, 242, 236, .25);
}
.foot-stat i.ok { background: var(--green); box-shadow: 0 0 8px rgba(121, 255, 54, .6); }
.foot-stat em { font-style: normal; color: rgba(242, 242, 236, .72); }

.foot-bottom {
  max-width: var(--page);
  margin: 22px auto 0;
  display: flex;
  flex-wrap: wrap;
  gap: 14px 30px;
  align-items: center;
  justify-content: space-between;
}
.foot-bottom p {
  margin: 0;
  max-width: 62ch;
  font-size: 11px;
  line-height: 1.6;
  color: rgba(242, 242, 236, .3);
}
.foot-top-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 999px;
  background: none;
  color: rgba(242, 242, 236, .6);
  font: inherit;
  font-size: 9.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.foot-top-link:hover { border-color: rgba(255, 255, 255, .34); color: var(--paper); }
.foot-top-link i { transition: transform .3s var(--ease); }
.foot-top-link:hover i { transform: translateY(-3px); }

@media (max-width: 900px) {
  .foot-top { grid-template-columns: 1fr; gap: 44px; }
  .foot-nav { grid-auto-flow: row; gap: 30px; }
  .foot-word { font-size: clamp(72px, 26vw, 150px); }
}
@media (max-width: 560px) {
  .foot-bottom { flex-direction: column; align-items: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .verify.in-view .vscan-ring .arc { animation: none; stroke-dashoffset: 0; }
  .verify.in-view .vscan-ring i { animation: none; opacity: 1; }
  .foot-word span,
  .foot-link,
  .foot-link::before,
  .foot-top-link i,
  .vreport i { transition: none; }
}

/*
 * Touch targets.
 *
 * The footer links are 17px tall, which is right for a mouse and far too small
 * for a thumb. Rather than making them bigger everywhere and loosening a
 * composition that works, they grow only where the pointer is coarse.
 */
@media (pointer: coarse) {
  .foot-col ul { gap: 2px; }
  .foot-link { min-height: 44px; padding-block: 12px; }
  .foot-link:hover,
  .foot-link:focus-visible { padding-left: 20px; }
  .foot-top-link { min-height: 46px; }
  .vreport { min-height: 46px; }
  .vhash { min-height: 52px; }
  .sigrail-trigger { min-height: 52px; }
  /* 12px tall was a mouse target that made it into a touch layout. */
  .sigrail-link { min-height: 44px; margin-block: 2px 10px; }

  /*
   * Controls that live in styles.css.
   *
   * Raised here rather than there so every touch-size decision on this site is
   * in one block instead of scattered through the base sheet. The download pill
   * is the page's primary action and was 39px; the rest are navigation.
   */
  .pill { min-height: 46px; }
  /* styles.css narrows these to 39px at two breakpoints with a two-class
     selector, so this has to match that specificity to win. It is the page's
     primary action; 39px is a mouse target. */
  .hero-actions .pill { min-height: 46px; }
  .preview-cta a { min-height: 46px; }
  .menu-toggle { width: 46px; height: 46px; }
  .nav-wordmark,
  .site-footer .wordmark { min-height: 44px; display: inline-flex; align-items: center; }
  .nav-link,
  .mobile-nav-link { min-height: 44px; display: inline-flex; align-items: center; }
  .preview-guide-step { min-height: 46px; }
  .install-line { min-height: 48px; }
  /* The whole line copies, but the COPY affordance inside it is separately
     focusable and was 13px tall. */
  .install-line button { min-height: 44px; padding-inline: 12px; }
  .setup-step { min-height: 56px; }
}

/*
 * Ultrawide.
 *
 * styles.css widened the old three-card block to 940px past 1700px so the hero
 * did not read as a narrow column in a wide frame. The rail replaced that block
 * and inherited none of it, so it takes the same treatment: wider, and with the
 * readouts given more room rather than more gap.
 */
@media (min-width: 1700px) {
  .sigrail { width: min(100%, 940px); }
  .sigrail-trigger { padding: 19px 22px 18px; }
  .sigrail-name { font-size: 18px; }
}

/*
 * The smallest labels.
 *
 * 10px uppercase with wide tracking is the site's technical-label register and
 * reads fine on a monitor. On a phone held at arm's length it does not, so the
 * few that carry real information — not decoration — come up a step.
 */
@media (max-width: 720px) {
  .vscan-vendor { font-size: 11px; }
  .vstep code { font-size: 11.5px; }
  .vhash code { font-size: 11px; }
  .foot-bottom p { font-size: 11.5px; }
}


/* -------------------------------------------------------------------------
   What you need.

   Not a checklist and not four cards. Three numbered entries down one rule,
   each with the reason it is needed, the catch that actually trips people up,
   and a real download link — with the visitor's own platform chosen for them.

   The catch line is the point of the section. "Docker Desktop" installed but
   not running, Node 20 when 22 is the floor, and Chromium standing in for
   Chrome are the three ways a first install fails, so each one is said out
   loud next to the thing it applies to.
   ------------------------------------------------------------------------- */

.need {
  position: relative;
  background: var(--ink);
  color: var(--paper);
  padding: clamp(80px, 11vh, 150px) var(--pad) clamp(80px, 10vh, 140px);
  overflow: clip;
}

.need-head {
  max-width: var(--page);
  margin: 0 auto clamp(44px, 6vh, 80px);
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: clamp(28px, 5vw, 90px);
  align-items: end;
}
.need-intro p {
  margin: 0;
  max-width: 46ch;
  font-size: clamp(14px, 1.1vw, 17px);
  line-height: 1.65;
  color: var(--muted);
}

/* The platform switch. Small, because it preselects itself correctly. */
.need-os {
  display: flex !important;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin-top: 22px !important;
}
.need-os-label {
  font-size: 9px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .3);
}
.need-os-chips { display: inline-flex; gap: 6px; }
.need-os-chip {
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, .13);
  border-radius: 999px;
  background: none;
  color: rgba(242, 242, 236, .5);
  font: inherit;
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .3s var(--ease), color .3s var(--ease), background .3s var(--ease);
}
.need-os-chip:hover { color: var(--paper); border-color: rgba(255, 255, 255, .3); }
.need-os-chip[aria-pressed='true'] {
  color: var(--ink);
  background: var(--paper);
  border-color: var(--paper);
}

.need-list {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0;
  list-style: none;
  counter-reset: none;
  border-top: 1px solid rgba(255, 255, 255, .12);
}

.need-item {
  display: grid;
  grid-template-columns: clamp(56px, 7vw, 120px) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 48px);
  padding: clamp(26px, 3.4vw, 46px) 0;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
  transition: background .45s var(--ease);
}
.need-item:hover { background: rgba(255, 255, 255, .016); }

.need-idx {
  font-size: clamp(11px, .95vw, 13px);
  letter-spacing: .28em;
  color: rgba(242, 242, 236, .28);
  padding-top: .5em;
}
.need-item:hover .need-idx { color: var(--green); }

.need-body { min-width: 0; }
.need-body h3 {
  margin: 0;
  font-size: clamp(24px, 3.2vw, 46px);
  font-weight: 500;
  letter-spacing: -.04em;
  line-height: 1.02;
  text-transform: uppercase;
}
.need-why {
  margin: 14px 0 0;
  max-width: 48ch;
  font-size: clamp(13px, 1vw, 16px);
  line-height: 1.6;
  color: var(--muted);
}

/*
 * The catch. Set apart with a green rule because it is the sentence that
 * prevents the support message, not a footnote to the sentence above it.
 */
.need-catch {
  margin: 14px 0 0;
  padding-left: 14px;
  border-left: 2px solid rgba(121, 255, 54, .45);
  max-width: 52ch;
  font-size: clamp(12.5px, .92vw, 14.5px);
  line-height: 1.6;
  color: rgba(242, 242, 236, .72);
}
.need-catch em { font-style: normal; color: var(--green); }

.need-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  margin-top: 22px;
}

/* The primary get. One per prerequisite, and it is the platform-correct one. */
.need-get {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 13px 22px;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: transform .3s var(--ease), background .3s var(--ease);
}
.need-get:hover { transform: translateY(-2px); background: #fff; }
.need-get i { font-style: normal; transition: transform .3s var(--ease); }
.need-get:hover i { transform: translateY(3px); }

.need-alt {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .5);
  transition: color .3s var(--ease);
}
.need-alt:hover { color: var(--paper); }
.need-alt i { font-style: normal; font-size: 9px; transition: transform .3s var(--ease); }
.need-alt:hover i { transform: translate(2px, -2px); }

/* The one-line Ubuntu install, shown only when Ubuntu is selected. */
.need-cmd { margin-top: 18px; }
.need-cmd[hidden] { display: none; }
.need-cmd > span {
  display: block;
  margin-bottom: 8px;
  font-size: 9px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(242, 242, 236, .3);
}
.need-copy {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  max-width: 100%;
  padding: 12px 16px;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 10px;
  background: rgba(0, 0, 0, .35);
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.need-copy:hover { border-color: rgba(121, 255, 54, .4); background: rgba(0, 0, 0, .5); }
.need-copy code {
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  color: rgba(242, 242, 236, .8);
  overflow-wrap: anywhere;
  text-align: left;
}
.need-copy i {
  flex: none;
  font-style: normal;
  font-size: 8.5px;
  letter-spacing: .2em;
  color: rgba(242, 242, 236, .4);
  transition: color .25s var(--ease);
}
.need-copy:hover i { color: var(--green); }
.need-copy.copied i { color: var(--green); }

.need-fine {
  margin: 16px 0 0;
  font-size: 12px;
  color: rgba(242, 242, 236, .38);
}
.need-fine code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  color: rgba(242, 242, 236, .62);
}

/* The two things that are not downloads. */
.need-foot {
  max-width: var(--page);
  margin: clamp(34px, 4.5vh, 60px) auto 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 3vw, 48px);
}
.need-foot p {
  margin: 0;
  font-size: clamp(13px, 1vw, 15.5px);
  line-height: 1.65;
  color: var(--muted);
}
.need-foot strong { color: var(--paper); font-weight: 500; }
.need-foot span { display: block; margin-top: 6px; color: rgba(242, 242, 236, .38); font-size: .92em; }

@media (max-width: 900px) {
  .need-head { grid-template-columns: 1fr; align-items: start; gap: 26px; }
  .need-foot { grid-template-columns: 1fr; gap: 20px; }
}

@media (max-width: 720px) {
  /* The index moves above the heading rather than taking a column of its own,
     which at 390px was 56px of nothing beside three lines of wrapped title. */
  .need-item { grid-template-columns: 1fr; gap: 8px; }
  .need-idx { padding-top: 0; }
  .need-actions { gap: 10px 14px; }
  .need-get { width: 100%; justify-content: space-between; }
  .need-copy { width: 100%; }
}

@media (pointer: coarse) {
  .need-os-chip { min-height: 44px; }
  .need-get { min-height: 48px; }
  .need-alt { min-height: 44px; }
  .need-copy { min-height: 48px; }
}

@media (prefers-reduced-motion: reduce) {
  .need-item,
  .need-get,
  .need-get i,
  .need-alt,
  .need-alt i,
  .need-os-chip { transition: none; }
  .need-get:hover { transform: none; }
}

/* --------------------------------------------------------------------------
   Mobile hero composition — keep the character centered behind the message.
   The desktop composition deliberately pushes her to the right; phones/tablets
   instead use the character as a centered atmospheric layer so no part of the
   focal artwork is lost off the right edge.
   -------------------------------------------------------------------------- */
@media (max-width: 1040px) {
  .hero {
    overflow: hidden;
  }

  .hero-character-wrap {
    left: 50%;
    right: auto;
    bottom: -1.5svh;
    translate: -50% 0;
    width: 100vw;
    height: min(72svh, 760px);
    justify-content: center;
    opacity: .50;
  }

  .hero-character {
    max-width: 100vw;
    object-position: bottom center;
    filter: drop-shadow(0 0 34px rgba(77,255,25,.07));
  }

  .character-orbit,
  .character-halo {
    left: 50%;
    right: auto;
    translate: -50% 0;
  }

  .hero-title,
  .hero-overline,
  .hero-description {
    position: relative;
    z-index: 1;
    text-shadow: 0 2px 18px rgba(0,0,0,.72);
  }

  .hero-bottom {
    max-width: min(88%, 620px);
  }
}

@media (max-width: 560px) {
  html,
  body {
    max-width: 100%;
    overflow-x: hidden;
  }

  .hero-character-wrap {
    width: 100vw;
    height: 74svh;
    bottom: -2svh;
    opacity: .42;
  }

  .hero-character {
    max-width: 100vw;
  }

  .hero-bottom {
    max-width: 100%;
  }

  .hero-actions {
    width: 100%;
  }
}
