/*
 * Ryde marketing site.
 *
 * Colour, spacing and radii mirror `mobile/src/constants/theme.ts` -- same
 * palette, same 4pt scale. They are duplicated rather than imported because
 * this site has no build step and shares no runtime with the app; when a colour
 * changes there, change it here.
 *
 * Type is the one system that deliberately diverges. Inter, tightened: large
 * sizes get negative tracking and weight 600 rather than 700, because at 44px a
 * bold weight reads as loud rather than as confident. Numbers are tabular
 * everywhere they can change.
 */

:root {
  /* Ink -- the neutral chrome. Higher number, darker. */
  --ink-1000: #000000;
  --ink-975: #08080a;
  --ink-950: #0e0e11;
  --ink-900: #141418;
  --ink-870: #1a1a1f;
  --ink-850: #212127;
  --ink-800: #2b2b32;
  --ink-780: #35353d;
  --ink-700: #45454d;
  --ink-500: #6f6f78;
  --ink-400: #8c8c93;
  --ink-300: #c6c6cb;
  --ink-50: #f4f4f6;

  /* Status. Only these carry hue, and only where it means something. */
  --blue-400: #4a94f0;
  --blue-300: #82b6f7;
  --blue-900: #132c4a;

  --green-400: #2fbf88;
  --green-300: #7be3b8;
  --green-900: #0e2a20;

  --amber-400: #e9a23b;
  --amber-300: #f6c87a;
  --amber-900: #2e2110;

  --red-400: #f2645f;
  --red-300: #ff9b97;
  --red-900: #301618;

  /* Semantic aliases, matching the app's dark theme. */
  --background: var(--ink-1000);
  --wash: var(--ink-975);
  --surface: var(--ink-900);
  --surface-raised: var(--ink-870);
  --surface-subtle: var(--ink-850);
  --border: var(--ink-800);
  --border-strong: var(--ink-780);
  --hairline: rgba(255, 255, 255, 0.07);
  --text: var(--ink-50);
  --text-secondary: var(--ink-300);
  --text-muted: var(--ink-400);
  --text-faint: var(--ink-500);
  --text-inverse: #06070a;
  --accent: var(--blue-400);
  --accent-pressed: var(--blue-300);
  --accent-surface: var(--blue-900);

  /* 4pt scale. */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 12px;
  --space-lg: 16px;
  --space-xl: 24px;
  --space-2xl: 32px;
  --space-3xl: 48px;
  --space-4xl: 72px;
  --space-5xl: 112px;
  --space-6xl: 152px;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
  --radius-pill: 999px;

  --font-sans:
    Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif,
    'Apple Color Emoji', 'Segoe UI Emoji';
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;

  --width-content: 1140px;
  --width-prose: 660px;

  --ease: cubic-bezier(0.22, 0.7, 0.28, 1);
}

/* The product is dark unconditionally and so is this page. Declaring the
   scheme stops the browser painting white behind it during load. */
:root {
  color-scheme: dark;
}

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

html {
  scroll-behavior: smooth;
  /* The header floats over content; anchored sections need to clear it. */
  scroll-padding-top: 84px;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--background);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.55;
  font-feature-settings: 'cv11', 'ss01';
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a {
  color: var(--accent);
  text-decoration: none;
}

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

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

h1,
h2,
h3,
p,
ul,
ol,
figure,
blockquote {
  margin: 0;
}

ul {
  list-style: none;
  padding: 0;
}

/* ---- Type -------------------------------------------------------------- */

.section-title {
  font-size: clamp(29px, 3.5vw, 45px);
  line-height: 1.1;
  font-weight: 600;
  letter-spacing: -0.028em;
  color: var(--text);
  text-wrap: balance;
}

.section-lede {
  margin-top: var(--space-lg);
  font-size: clamp(16px, 1.35vw, 19px);
  line-height: 1.55;
  font-weight: 400;
  color: var(--text-muted);
  max-width: 46ch;
  text-wrap: pretty;
}

/*
 * The small uppercase label. Used only inside components to name a column or a
 * readout -- never as a section banner, because a page that announces "THE
 * PROBLEM" above every block reads as a deck, not a product.
 */
.micro {
  font-size: 11px;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Names a control for a screen reader without drawing anything. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- Layout ------------------------------------------------------------ */

.wrap {
  width: 100%;
  max-width: var(--width-content);
  margin-inline: auto;
  padding-inline: var(--space-xl);
}

section {
  padding-block: clamp(80px, 8.5vw, 124px);
}

/*
 * Sections are separated by a hairline that stops short of the viewport edge,
 * rather than a full-bleed 1px border. The old page drew a hard rule across
 * every boundary, which chopped a continuous argument into nine boxes.
 */
section + section > .wrap {
  position: relative;
}

section + section > .wrap::before {
  content: '';
  position: absolute;
  top: calc(clamp(80px, 8.5vw, 124px) * -0.5);
  left: var(--space-xl);
  right: var(--space-xl);
  height: 1px;
  background: var(--hairline);
}

.section-head {
  max-width: var(--width-prose);
  margin-bottom: var(--space-4xl);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: var(--space-lg);
  background: var(--surface);
  color: var(--text);
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius-md);
  z-index: 100;
}

.skip-link:focus {
  left: var(--space-lg);
}

/* ---- Reveals ----------------------------------------------------------- */

/*
 * Resting state is the FINAL state. main.js adds `.js-reveal` to <html> only
 * when motion is welcome and an observer is running, so a reader with reduced
 * motion, or with JS broken, gets the finished page rather than a blank one.
 */
.js-reveal .reveal {
  opacity: 0;
  translate: 0 18px;
  transition: opacity 620ms var(--ease), translate 620ms var(--ease);
}

.js-reveal .reveal.is-visible {
  opacity: 1;
  translate: none;
}

/* ---- Buttons ----------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  min-height: 46px;
  padding: 0 var(--space-xl);
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-size: 15px;
  font-weight: 550;
  letter-spacing: -0.005em;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 140ms var(--ease), color 140ms var(--ease),
    border-color 140ms var(--ease), translate 140ms var(--ease);
}

.btn-primary {
  background: var(--accent);
  color: var(--text-inverse);
}

.btn-primary:hover {
  background: var(--accent-pressed);
  color: var(--text-inverse);
}

.btn-sm {
  min-height: 36px;
  padding-inline: var(--space-lg);
  font-size: 14px;
}

.btn-block {
  width: 100%;
}

/* ---- Header ------------------------------------------------------------ */

/*
 * Transparent over the photograph, and only acquires a ground once the hero is
 * behind you. The old header was an opaque black bar sitting on top of a
 * photograph, which read as two separate pages stacked.
 */
.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 240ms var(--ease), border-color 240ms var(--ease),
    backdrop-filter 240ms var(--ease);
}

.site-header.is-stuck {
  background: rgba(6, 6, 8, 0.72);
  backdrop-filter: saturate(150%) blur(14px);
  border-bottom-color: var(--hairline);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: var(--space-2xl);
  min-height: 60px;
}

.wordmark img {
  height: 19px;
  width: auto;
}

.nav-desktop {
  display: flex;
  align-items: center;
  gap: var(--space-xl);
}

.nav-desktop a,
.nav-signin {
  position: relative;
  font-size: 14px;
  font-weight: 450;
  letter-spacing: -0.003em;
  color: var(--text-muted);
  transition: color 140ms var(--ease);
}

.nav-desktop a:hover,
.nav-signin:hover {
  color: var(--text);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  margin-left: auto;
}

/* ---- Mobile menu ------------------------------------------------------- */

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.03);
  cursor: pointer;
}

.nav-toggle-box {
  display: block;
  position: relative;
  width: 16px;
  height: 10px;
}

.nav-toggle-bar {
  position: absolute;
  left: 0;
  width: 16px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--text);
  transition: translate 200ms var(--ease), rotate 200ms var(--ease);
}

.nav-toggle-bar:nth-child(1) {
  top: 0;
}

.nav-toggle-bar:nth-child(2) {
  top: 8.5px;
}

.site-header.is-menu-open .nav-toggle-bar:nth-child(1) {
  translate: 0 4.25px;
  rotate: 45deg;
}

.site-header.is-menu-open .nav-toggle-bar:nth-child(2) {
  translate: 0 -4.25px;
  rotate: -45deg;
}

/*
 * Closed with visibility:hidden rather than display:none so it can transition
 * and still leave the accessibility tree when shut.
 */
.nav-mobile {
  display: none;
  overflow: hidden;
  border-top: 1px solid var(--hairline);
  background: rgba(6, 6, 8, 0.94);
  backdrop-filter: saturate(150%) blur(14px);
  visibility: hidden;
  opacity: 0;
  translate: 0 -8px;
  transition: opacity 200ms var(--ease), translate 200ms var(--ease),
    visibility 0s linear 200ms;
}

.site-header.is-menu-open .nav-mobile {
  visibility: visible;
  opacity: 1;
  translate: none;
  transition-delay: 0s;
}

.nav-mobile nav {
  display: flex;
  flex-direction: column;
  padding: var(--space-sm) var(--space-xl) var(--space-xl);
}

.nav-mobile a {
  padding-block: var(--space-lg);
  font-size: 17px;
  font-weight: 450;
  color: var(--text);
  border-bottom: 1px solid var(--hairline);
}

.nav-mobile a:last-child {
  border-bottom: none;
}

@media (max-width: 860px) {
  .nav-desktop,
  .nav-signin {
    display: none;
  }

  .nav-toggle {
    display: inline-flex;
  }

  .nav-mobile {
    display: block;
  }

  .header-actions {
    gap: var(--space-md);
  }
}

@media (max-width: 380px) {
  .header-inner {
    gap: var(--space-lg);
  }

  .btn-sm {
    padding-inline: var(--space-md);
  }
}

/* ---- Hero ------------------------------------------------------------- */

/*
 * The photograph is the hero and the centre of it belongs to Ryde. The empty
 * lane down the middle of the lot is the only place on the frame where type
 * sits at full contrast without a slab of colour laid over the cars, so the
 * wordmark goes there and nothing else does.
 *
 * The sides belong to the vehicles. Four diagnostics are anchored to actual
 * cars in the image; each marker sits in empty asphalt and reaches its car
 * with a line, so the thing being described is never covered by the thing
 * describing it.
 */
.hero {
  --hero-h: min(86vh, 840px);
  --photo-aspect: 1.7768;

  position: relative;
  isolation: isolate;
  border-top: none;
  padding-block: 0;
  min-height: var(--hero-h);
  display: grid;
  align-items: center;
  overflow: hidden;
}

.hero-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  container-type: size;
}

/*
 * The photograph's own box, sized to cover the hero.
 *
 * This exists so the markers can be positioned in the image's coordinate
 * space. With `object-fit: cover` on a bare <img>, the rendered picture is
 * cropped by an amount that depends on the viewport, and a marker placed at
 * "34% across" would drift off its car as the window resized. Sizing this box
 * to the cover dimensions instead means a percentage inside it is always the
 * same point on the photograph, at every viewport.
 */
.hero-frame {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  width: 100%;
  height: 100%;
}

@supports (width: 1cqw) {
  .hero-frame {
    width: max(100cqw, calc(100cqh * var(--photo-aspect)));
    height: max(100cqh, calc(100cqw / var(--photo-aspect)));
  }
}

.hero-frame picture,
.hero-frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/*
 * Two scrims. The radial deepens the lane so the wordmark sits on something
 * close to black -- the lighting already started this and it only finishes it.
 * The linear gives the sticky header a ground and fades the bottom edge into
 * the page background, so the section boundary is a change of subject rather
 * than a visible seam.
 */
.hero-scrim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      46% 54% at 50% 48%,
      rgba(0, 0, 0, 0.86) 0%,
      rgba(0, 0, 0, 0.52) 48%,
      rgba(0, 0, 0, 0) 76%
    ),
    linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.74) 0%,
      rgba(0, 0, 0, 0.16) 24%,
      rgba(0, 0, 0, 0.48) 70%,
      var(--background) 100%
    );
}

/* ---- Centre: the brand ------------------------------------------------- */

.hero-inner {
  position: relative;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding-block: var(--space-5xl);
  /* The markers live outside this column and must stay reachable through it. */
  pointer-events: none;
}

.hero-inner a {
  pointer-events: auto;
}

.hero-lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hero-wordmark {
  width: clamp(190px, 26vw, 360px);
  height: auto;
}

.hero-tagline {
  margin-top: var(--space-lg);
  font-size: clamp(17px, 2.1vw, 25px);
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--text-secondary);
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.7);
}

.hero-actions {
  margin-top: var(--space-2xl);
}

.btn-lg {
  min-height: 54px;
  padding-inline: var(--space-2xl);
  font-size: 17px;
}

/* ---- Sides: the diagnostics -------------------------------------------- */

.hero-markers {
  position: absolute;
  inset: 0;
  z-index: 2;
}

/*
 * Each marker owns a full-frame SVG so that hovering it can style its own line
 * and its own vehicle without reaching across the DOM. The SVGs take no
 * pointer events, so four of them stacked cost nothing in hit testing.
 */
.marker {
  position: absolute;
  inset: 0;
  pointer-events: none;

  /* Overridden per marker below. */
  --x: 50%;
  --y: 50%;
  --i: 0;
  --tone: var(--accent);
}

.marker.is-critical {
  --tone: var(--red-400);
}

.marker.is-attention {
  --tone: var(--amber-400);
}

.marker.is-offline {
  --tone: var(--ink-300);
}

.marker-line {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.marker-line .line {
  fill: none;
  stroke: var(--tone);
  stroke-width: 1.25;
  opacity: 0.42;
  transition: opacity 180ms ease, stroke-width 180ms ease;
}

.marker-line .target {
  fill: none;
  stroke: var(--tone);
  stroke-width: 1.5;
  opacity: 0;
  transition: opacity 200ms ease;
}

.marker-anchor {
  position: absolute;
  left: var(--x);
  top: var(--y);
  translate: -50% -50%;
  pointer-events: auto;
}

/* At rest a marker is a dot in a ring, and nothing else. */
.marker-dot {
  display: block;
  position: relative;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  cursor: pointer;
}

.marker-dot::before,
.marker-dot::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  border-radius: var(--radius-pill);
}

/* The dot. */
.marker-dot::before {
  width: 9px;
  height: 9px;
  background: var(--tone);
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.55), 0 0 14px 2px var(--tone);
  transition: width 180ms ease, height 180ms ease;
}

/* The ring. */
.marker-dot::after {
  width: 26px;
  height: 26px;
  border: 1px solid var(--tone);
  opacity: 0.35;
  transition: opacity 180ms ease, scale 220ms ease;
}

.marker:hover .marker-dot::before,
.marker:focus-within .marker-dot::before {
  width: 11px;
  height: 11px;
}

.marker:hover .marker-dot::after,
.marker:focus-within .marker-dot::after {
  opacity: 0.85;
  scale: 1.12;
}

.marker:hover .line,
.marker:focus-within .line {
  opacity: 1;
  stroke-width: 1.75;
}

.marker:hover .target,
.marker:focus-within .target {
  opacity: 0.85;
}

/* ---- The diagnostic card ----------------------------------------------- */

.marker-card {
  position: absolute;
  width: max-content;
  max-width: 232px;
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong);
  border-left: 2px solid var(--tone);
  background: rgba(16, 16, 19, 0.92);
  backdrop-filter: blur(10px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.6);
  text-align: left;

  opacity: 0;
  visibility: hidden;
  transition: opacity 180ms ease, translate 180ms ease, visibility 0s linear 180ms;
}

/*
 * Cards open away from the centre so they never cross the wordmark, and off the
 * axis of their own connector so they never cover the line or the car it
 * reaches. A card sitting on the vehicle it is describing would make the
 * highlight on that vehicle pointless, which is what the first version did.
 */
.marker--left .marker-card {
  right: 100%;
  translate: 10px 0;
}

.marker--right .marker-card {
  left: 100%;
  translate: -10px 0;
}

.marker--below .marker-card {
  top: 100%;
}

.marker--above .marker-card {
  bottom: 100%;
}

.marker:hover .marker-card,
.marker:focus-within .marker-card {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
  transition-delay: 0s;
}

.marker-card-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--tone);
}

.marker-card-value {
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: 19px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.marker-card-note {
  margin-top: var(--space-xs);
  font-size: 12px;
  line-height: 17px;
  color: var(--text-muted);
}

/* ---- Where each marker sits, and which car it reaches ------------------ */

/*
 * Percentages are positions on the photograph, matched to the line endpoints
 * in the markup. They were read off a grid laid over the image rather than
 * guessed -- moving one means moving its <line> to match.
 */
.marker--battery {
  --x: 34%;
  --y: 27%;
  --i: 0;
}

.marker--code {
  --x: 66%;
  --y: 36%;
  --i: 1;
}

.marker--seen {
  --x: 33%;
  --y: 66%;
  --i: 2;
}

.marker--fuel {
  --x: 66.5%;
  --y: 60%;
  --i: 3;
}

/* ---- The load ---------------------------------------------------------- */

/*
 * Order: photograph, wordmark, call to action, then the lines reaching out to
 * the cars with their markers landing behind them. Roughly 1.9s end to end.
 *
 * Every element's resting style is its FINAL state, and the entry animations
 * exist only inside the no-preference block, with `fill-mode: both` holding
 * the opening frame during the delay. A reader who asked for no motion
 * therefore gets the finished hero rather than a blank one -- there is no way
 * for this to fail closed.
 */
@media (prefers-reduced-motion: no-preference) {
  .hero-frame picture {
    animation: hero-fade 700ms ease-out both;
  }

  .hero-lockup {
    animation: hero-rise 700ms cubic-bezier(0.2, 0.7, 0.3, 1) 220ms both;
  }

  .hero-actions {
    animation: hero-rise 600ms cubic-bezier(0.2, 0.7, 0.3, 1) 560ms both;
  }

  .marker-line .line {
    animation: hero-draw 520ms ease-out calc(880ms + var(--i) * 150ms) both;
  }

  .marker-anchor {
    animation: hero-pop 380ms cubic-bezier(0.2, 0.8, 0.3, 1.2)
      calc(1240ms + var(--i) * 150ms) both;
  }
}

@keyframes hero-fade {
  from {
    opacity: 0;
  }
}

@keyframes hero-rise {
  from {
    opacity: 0;
    translate: 0 14px;
  }
}

@keyframes hero-draw {
  from {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
  }
  to {
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
  }
}

@keyframes hero-pop {
  from {
    opacity: 0;
    scale: 0.4;
  }
}

/*
 * Phones get a different hero, not a squeezed one.
 *
 * `object-fit: cover` on a portrait viewport crops a 1.78:1 photograph to its
 * centre -- which here is the empty lane, so the lot disappears and the hero
 * becomes a black rectangle. Below this width the photograph is a 1.3:1 crop
 * banded across the top, uncropped vertically, with the brand over it and the
 * call to action beneath on the page background.
 *
 * The markers do not survive the move, and are not meant to. They are anchored
 * to coordinates in the full frame, the mobile crop is a different image, a
 * 300px band has no room for a diagnostic card, and a touch screen has no
 * hover to reveal one with. Half a version of the interaction would be worse
 * than none.
 */
@media (max-width: 720px) {
  .hero {
    --band: calc(100vw / 1.3);

    display: block;
    min-height: 0;
    padding-bottom: var(--space-3xl);
  }

  .hero-media {
    height: var(--band);
    bottom: auto;
  }

  .hero-frame {
    width: 100%;
    height: 100%;
  }

  .hero-markers {
    display: none;
  }

  .hero-scrim {
    background: linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.62) 0%,
      rgba(0, 0, 0, 0.24) 36%,
      rgba(0, 0, 0, 0.8) 84%,
      var(--background) 100%
    );
  }

  .hero-lockup {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: var(--band);
    justify-content: center;
    z-index: 3;
    padding-inline: var(--space-xl);
  }

  .hero-inner {
    padding-top: calc(var(--band) + var(--space-xl));
    padding-bottom: 0;
  }
}


/* ======================================================================
   1. Ryde sees what your systems don't
   ====================================================================== */

.check {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(190px, 0.6fr) minmax(0, 1fr);
  gap: var(--space-3xl);
  /* Start, not centre: "Your systems say" and "Ryde observes" have to sit on
     the same line or the section stops reading as a comparison. */
  align-items: start;
}

.check-vehicle {
  align-self: center;
}

/* ---- The claim --------------------------------------------------------- */

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

/*
 * Deliberately the palest thing in the section. It is a large confident
 * statement rendered in the colour of something nobody has checked -- the
 * hierarchy is the argument.
 */
.claim-state {
  margin-top: var(--space-lg);
  font-size: clamp(30px, 3.4vw, 44px);
  line-height: 1.06;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--ink-500);
}

.claim-meta {
  margin-top: var(--space-lg);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-faint);
}

/* ---- The car ----------------------------------------------------------- */

.check-vehicle {
  display: flex;
  justify-content: center;
}

.car {
  width: 100%;
  max-width: 210px;
  height: auto;
}

.car-body {
  fill: #141419;
  stroke: #4e4e58;
  stroke-width: 1.5;
}

.car-glass,
.car-roof {
  fill: none;
  stroke: var(--ink-800);
  stroke-width: 1.25;
}

.car-wheel {
  fill: var(--ink-900);
  stroke: var(--ink-800);
  stroke-width: 1;
}

.pt {
  fill: var(--ink-800);
  stroke: none;
  transition: fill 320ms var(--ease), r 320ms var(--ease);
}

/* Lit by main.js as each signal resolves, and again on hover of its row. */
.pt.is-live[data-pt='battery'],
.pt.is-live[data-pt='engine'],
.pt.is-live[data-pt='fuel'] {
  fill: var(--red-400);
}

.pt.is-live[data-pt='location'] {
  fill: var(--amber-400);
}

.pt.is-live[data-pt='recon'] {
  fill: var(--green-400);
}

.pt.is-focus {
  r: 9;
}

/* ---- The observation --------------------------------------------------- */

.signals {
  margin-top: var(--space-lg);
  border-top: 1px solid var(--hairline);
}

.signal {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-md);
  padding-block: var(--space-md);
  border-bottom: 1px solid var(--hairline);
  cursor: default;
}

.signal-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--ink-780);
  transition: background-color 320ms var(--ease), box-shadow 320ms var(--ease);
}

.signal.is-resolved .signal-dot {
  background: var(--tone);
  box-shadow: 0 0 10px 0 var(--tone);
}

.signal {
  --tone: var(--ink-400);
}

.signal.is-critical {
  --tone: var(--red-400);
}

.signal.is-attention {
  --tone: var(--amber-400);
}

.signal.is-healthy {
  --tone: var(--green-400);
}

.signal-label {
  font-size: 15px;
  font-weight: 450;
  color: var(--text-secondary);
}

.signal-value {
  font-size: 15px;
  font-weight: 550;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: color 320ms var(--ease);
}

.signal.is-resolved .signal-value {
  color: var(--tone);
}

.signal:hover .signal-label {
  color: var(--text);
}

.verdict-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-lg);
  margin-top: var(--space-xl);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--border);
}

.verdict-state {
  font-size: clamp(20px, 2vw, 26px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--red-300);
}

.check-foot {
  margin-top: var(--space-lg);
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-faint);
  max-width: 40ch;
}

@media (max-width: 1000px) {
  .check {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-2xl) var(--space-3xl);
    align-items: start;
  }

  .check-vehicle {
    grid-row: 1 / 3;
    grid-column: 1;
    align-self: center;
  }

  .check-claim {
    grid-column: 2;
    text-align: left;
  }

  .check-observed {
    grid-column: 2;
  }
}

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

  .check-vehicle,
  .check-claim,
  .check-observed {
    grid-column: 1;
    grid-row: auto;
  }

  .check-claim {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-lg);
    flex-wrap: wrap;
  }

  .claim-state {
    margin-top: 0;
    font-size: 26px;
  }

  .claim-state br {
    display: none;
  }

  .claim-meta {
    margin-top: 0;
  }

  .car {
    max-width: 120px;
  }
}

/* ======================================================================
   2. The operating system
   ====================================================================== */

.os {
  display: grid;
  grid-template-columns: minmax(280px, 0.78fr) minmax(0, 1fr);
  gap: var(--space-4xl);
  align-items: start;
}

.os-nav {
  display: flex;
  flex-direction: column;
}

/*
 * Capability rows, not cards. The active one is marked by a rule on its inner
 * edge and a lift in text colour -- no boxes, no shadows, no six-up grid.
 */
.os-item {
  position: relative;
  display: block;
  width: 100%;
  padding: var(--space-lg) 0 var(--space-lg) var(--space-xl);
  border: 0;
  border-top: 1px solid var(--hairline);
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  color: inherit;
}

.os-item:last-child {
  border-bottom: 1px solid var(--hairline);
}

.os-item::before {
  content: '';
  position: absolute;
  left: 0;
  top: var(--space-lg);
  bottom: var(--space-lg);
  width: 2px;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0;
  scale: 1 0.3;
  transition: opacity 240ms var(--ease), scale 240ms var(--ease);
}

.os-item.is-active::before {
  opacity: 1;
  scale: 1 1;
}

.os-item-name {
  display: block;
  font-size: 17px;
  font-weight: 550;
  letter-spacing: -0.012em;
  color: var(--text-muted);
  transition: color 200ms var(--ease);
}

.os-item.is-active .os-item-name {
  color: var(--text);
}

.os-item:hover .os-item-name {
  color: var(--text);
}

.os-item-desc {
  display: block;
  margin-top: var(--space-xs);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-muted);
  max-width: 42ch;
}

/* ---- The lot ----------------------------------------------------------- */

.os-stage {
  padding: var(--space-xl);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(255, 255, 255, 0.028), transparent 60%),
    var(--surface);
}

.os-stage-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-lg);
  padding-bottom: var(--space-lg);
  border-bottom: 1px solid var(--hairline);
}

.os-stage-mode {
  font-size: 13px;
  font-weight: 550;
  color: var(--text-secondary);
}

/*
 * Twenty-four vehicles, read six ways. The same tiles restyle per mode rather
 * than six illustrations swapping out, because the claim being made is that
 * this is one system looking at one lot.
 */
.lot {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 8px;
  margin-block: var(--space-xl);
}

.tile {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-sm);
  background: #23232a;
  border: 1px solid #2f2f37;
  overflow: hidden;
  transition: background-color 420ms var(--ease), border-color 420ms var(--ease),
    opacity 420ms var(--ease), translate 520ms var(--ease);
}

/* The roof line, so a tile reads as a car from above rather than as a swatch. */
.tile::before {
  content: '';
  position: absolute;
  inset: 26% 22%;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.09);
  transition: background-color 420ms var(--ease);
}

/* A status pip, shown only in the modes where a tile is being called out. */
.tile::after {
  content: '';
  position: absolute;
  top: 5px;
  right: 5px;
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--pip, transparent);
  opacity: 0;
  scale: 0.4;
  transition: opacity 380ms var(--ease), scale 380ms var(--ease);
}

.tile.is-flagged::after {
  opacity: 1;
  scale: 1;
}

/* Dimmed, not erased. "4 of 24" only lands if the other 20 are still there. */
.tile.is-dim {
  opacity: 0.58;
}

.tile.is-tone {
  background: color-mix(in srgb, var(--pip) 9%, #23232a);
  border-color: color-mix(in srgb, var(--pip) 62%, transparent);
}

.tile.is-tone::before {
  background: color-mix(in srgb, var(--pip) 34%, rgba(255, 255, 255, 0.09));
}

/* A recon progress bar along the bottom edge. */
.tile .bar {
  position: absolute;
  left: 4px;
  right: 4px;
  bottom: 4px;
  height: 2px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.09);
  opacity: 0;
  transition: opacity 380ms var(--ease);
}

.tile .bar::after {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--progress, 0%);
  border-radius: 2px;
  background: var(--accent);
  transition: width 620ms var(--ease);
}

.lot[data-mode='recon'] .tile .bar {
  opacity: 1;
}

/* Out-of-place vehicles nudge off the grid in location mode. */
.lot[data-mode='location'] .tile.is-misplaced {
  translate: 0 7px;
  border-style: dashed;
}

.os-readout {
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-muted);
  min-height: 2.6em;
}

@media (max-width: 980px) {
  .os {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2xl);
  }

  /* Stage first on narrow screens: the picture is the point, the list is the
     control for it. */
  .os-stage {
    order: -1;
  }

  .lot {
    grid-template-columns: repeat(8, 1fr);
  }
}

@media (max-width: 640px) {
  /*
   * The capability list becomes a scrollable rail of names. Descriptions are
   * not dropped -- they move into the stage readout, so nothing is hidden.
   */
  .os-nav {
    flex-direction: row;
    gap: var(--space-sm);
    overflow-x: auto;
    scroll-snap-type: x proximity;
    padding-bottom: var(--space-sm);
    margin-inline: calc(var(--space-xl) * -1);
    padding-inline: var(--space-xl);
    -webkit-overflow-scrolling: touch;
  }

  .os-nav::-webkit-scrollbar {
    display: none;
  }

  .os-item {
    flex: 0 0 auto;
    width: auto;
    scroll-snap-align: start;
    padding: var(--space-sm) var(--space-lg);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--surface);
  }

  .os-item:last-child {
    border-bottom: 1px solid var(--border);
  }

  .os-item::before {
    display: none;
  }

  .os-item.is-active {
    background: var(--accent-surface);
    border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  }

  .os-item.is-active .os-item-name {
    color: var(--blue-300);
  }

  .os-item-name {
    font-size: 14px;
    white-space: nowrap;
  }

  .os-item-desc {
    display: none;
  }

  .os-stage {
    padding: var(--space-lg);
  }

  .lot {
    grid-template-columns: repeat(6, 1fr);
    gap: 6px;
  }
}

/* ======================================================================
   3. How Ryde knows
   ====================================================================== */

.flow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 118px minmax(0, 0.92fr) 118px minmax(0, 1fr);
  /* No gap around the wire columns: a connector that stops 16px short of the
     thing it connects to reads as a broken diagram rather than a quiet one. */
  gap: 0;
  align-items: center;
}

.flow-col-label {
  margin-bottom: var(--space-lg);
}

.flow-list li {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-wrap: wrap;
  padding-block: var(--space-md);
  border-top: 1px solid var(--hairline);
}

.flow-list li:last-child {
  border-bottom: 1px solid var(--hairline);
}

.flow-name {
  font-size: 15px;
  font-weight: 450;
  color: var(--text-secondary);
}

.flow-col-out {
  text-align: right;
}

.flow-col-out .flow-list li {
  justify-content: flex-end;
}

.flow-col-out .flow-name {
  color: var(--text);
  font-weight: 500;
}

.chip {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  background: var(--surface-subtle);
  border: 1px solid var(--border);
}

.chip-ok {
  color: var(--green-300);
  background: var(--green-900);
  border-color: color-mix(in srgb, var(--green-400) 30%, transparent);
}

/*
 * Aligned to the BOTTOM of its column, not the middle. Both list columns end
 * flush with the column box, so bottom alignment lands the fan's endpoints on
 * the rows; centring it floats the whole fan a row-height too high.
 */
.wires {
  width: 100%;
  height: 240px;
  align-self: end;
  overflow: visible;
}

.wire {
  fill: none;
  stroke: #4d4d59;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* Drawn on reveal; resting state is fully drawn, so no-JS and reduced-motion
   both show the finished diagram. */
.js-reveal .flow.is-visible .wire {
  animation: wire-draw 900ms var(--ease) both;
}

.js-reveal .flow.is-visible .wires-in .wire:nth-child(1) { animation-delay: 120ms; }
.js-reveal .flow.is-visible .wires-in .wire:nth-child(2) { animation-delay: 200ms; }
.js-reveal .flow.is-visible .wires-in .wire:nth-child(3) { animation-delay: 280ms; }
.js-reveal .flow.is-visible .wires-in .wire:nth-child(4) { animation-delay: 360ms; }
.js-reveal .flow.is-visible .wires-in .wire:nth-child(5) { animation-delay: 440ms; }
.js-reveal .flow.is-visible .wires-out .wire:nth-child(1) { animation-delay: 700ms; }
.js-reveal .flow.is-visible .wires-out .wire:nth-child(2) { animation-delay: 780ms; }
.js-reveal .flow.is-visible .wires-out .wire:nth-child(3) { animation-delay: 860ms; }
.js-reveal .flow.is-visible .wires-out .wire:nth-child(4) { animation-delay: 940ms; }
.js-reveal .flow.is-visible .wires-out .wire:nth-child(5) { animation-delay: 1020ms; }

@keyframes wire-draw {
  from {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
  }
  to {
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
  }
}

.flow-core {
  padding: var(--space-xl);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xl);
  background:
    radial-gradient(100% 100% at 50% 0%, rgba(74, 148, 240, 0.09), transparent 70%),
    var(--surface);
  text-align: center;
}

.flow-core-mark {
  display: block;
  width: 8px;
  height: 8px;
  margin: 0 auto var(--space-lg);
  border-radius: var(--radius-pill);
  background: var(--accent);
  box-shadow: 0 0 0 5px rgba(74, 148, 240, 0.13), 0 0 20px 2px rgba(74, 148, 240, 0.5);
}

.flow-core-name {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text);
}

.flow-core-note {
  margin-top: var(--space-sm);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-faint);
}

.guarantees {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-lg) var(--space-2xl);
  margin-top: var(--space-4xl);
  padding-top: var(--space-xl);
  border-top: 1px solid var(--hairline);
}

.guarantees li {
  position: relative;
  padding-left: var(--space-lg);
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-muted);
}

.guarantees li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 9px;
  width: 4px;
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--green-400);
}

@media (max-width: 940px) {
  /* Vertical flow. The wires are a horizontal idea; below this width they are
     replaced by the stacking order itself. */
  .flow {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-xl);
  }

  .wires {
    display: none;
  }

  .flow-col-out {
    text-align: left;
  }

  .flow-col-out .flow-list li {
    justify-content: flex-start;
  }

  .flow-core {
    order: 0;
  }
}

/* ======================================================================
   4. ROI / cost matrix
   ====================================================================== */

.matrix {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--space-4xl);
  align-items: start;
}

.matrix-controls {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

.ctrl-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-lg);
}

.ctrl-name {
  font-size: 15px;
  font-weight: 450;
  color: var(--text-secondary);
}

.ctrl-value {
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
}

.ctrl-note {
  margin-top: var(--space-sm);
  font-size: 12px;
  color: var(--text-faint);
}

/* ---- Sliders ------------------------------------------------------------
 * Native range inputs, fully restyled. The filled portion is a gradient driven
 * by --fill, which main.js writes through the CSSOM (permitted under our CSP;
 * only style attributes in markup are blocked).
 */
.slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  margin-top: var(--space-md);
  height: 22px;
  background: none;
  cursor: pointer;
}

.slider::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--accent) 0%,
    var(--accent) var(--fill, 30%),
    var(--ink-800) var(--fill, 30%),
    var(--ink-800) 100%
  );
}

.slider::-moz-range-track {
  height: 3px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--accent) 0%,
    var(--accent) var(--fill, 30%),
    var(--ink-800) var(--fill, 30%),
    var(--ink-800) 100%
  );
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  margin-top: -6.5px;
  border-radius: var(--radius-pill);
  background: var(--text);
  border: none;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.65);
  transition: scale 140ms var(--ease), box-shadow 140ms var(--ease);
}

.slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: var(--radius-pill);
  background: var(--text);
  border: none;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.65);
}

.slider:hover::-webkit-slider-thumb,
.slider:focus-visible::-webkit-slider-thumb {
  scale: 1.14;
  box-shadow: 0 0 0 6px rgba(74, 148, 240, 0.16);
}

.slider:focus-visible {
  outline: none;
}

/* ---- Result ------------------------------------------------------------ */

.matrix-result {
  padding: var(--space-2xl);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(255, 255, 255, 0.03), transparent 62%),
    var(--surface);
}

.result-figure {
  margin-top: var(--space-sm);
  font-size: clamp(38px, 5vw, 58px);
  line-height: 1;
  font-weight: 600;
  letter-spacing: -0.035em;
  color: var(--green-300);
  font-variant-numeric: tabular-nums;
}

.result-unit {
  margin-top: var(--space-sm);
  font-size: 14px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.result-unit span {
  color: var(--text-secondary);
  font-weight: 500;
}

/* ---- The curve --------------------------------------------------------- */

.curve {
  margin-top: var(--space-2xl);
  padding-top: var(--space-xl);
  border-top: 1px solid var(--hairline);
}

.curve-bars {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 84px;
  margin-top: var(--space-md);
}

.cbar {
  flex: 1;
  height: var(--h, 10%);
  min-height: 3px;
  border-radius: 3px 3px 0 0;
  background: var(--ink-800);
  transition: height 420ms var(--ease), background-color 220ms var(--ease);
}

.cbar.is-current {
  background: var(--green-400);
}

.cbar.is-under {
  background: color-mix(in srgb, var(--green-400) 34%, var(--ink-800));
}

.curve-axis {
  display: flex;
  justify-content: space-between;
  margin-top: var(--space-sm);
  font-size: 11px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.result-math {
  margin-top: var(--space-xl);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--hairline);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-faint);
}

@media (max-width: 900px) {
  .matrix {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2xl);
  }
}

/* ======================================================================
   5. Pilot
   ====================================================================== */

/*
 * The last section changes ground, which is the transition. A hairline on top
 * of that is a second announcement of the same thing.
 */
.pilot {
  background: var(--wash);
}

#pilot > .wrap::before {
  display: none;
}

.pilot-wrap {
  max-width: 720px;
  text-align: center;
}

.pilot-intro .section-lede {
  margin-inline: auto;
}

#pilot-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  margin-top: var(--space-3xl);
  text-align: left;
}

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-lg);
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-field label {
  font-size: 12px;
  font-weight: 550;
  letter-spacing: 0.01em;
  color: var(--text-muted);
}

input[type='text'],
input[type='email'],
select {
  min-height: 46px;
  padding: 0 var(--space-md);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong);
  background: var(--surface-raised);
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  width: 100%;
  transition: border-color 140ms var(--ease), background-color 140ms var(--ease);
}

input::placeholder {
  color: var(--text-faint);
}

input:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface-raised);
}

#pilot-form .btn {
  margin-top: var(--space-sm);
  min-height: 50px;
}

.form-status {
  font-size: 13px;
  line-height: 1.5;
  min-height: 1.5em;
  color: var(--text-muted);
}

.form-status.is-error {
  color: var(--red-300);
}

.form-status.is-ok {
  color: var(--green-300);
}

.pilot-terms {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm) var(--space-xl);
  margin-top: var(--space-2xl);
}

.pilot-terms li {
  position: relative;
  padding-left: var(--space-md);
  font-size: 13px;
  color: var(--text-faint);
}

.pilot-terms li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  width: 3px;
  height: 3px;
  border-radius: var(--radius-pill);
  background: var(--ink-700);
}

/* ======================================================================
   Footer
   ====================================================================== */

.site-footer {
  padding-block: var(--space-2xl);
  border-top: 1px solid var(--hairline);
}

.footer-inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-xl);
}

.footer-mark {
  opacity: 0.7;
}

.footer-copy {
  font-size: 13px;
  color: var(--text-faint);
}

.footer-links {
  display: flex;
  gap: var(--space-xl);
  margin-left: auto;
}

.footer-links a {
  font-size: 13px;
  color: var(--text-muted);
}

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

@media (max-width: 560px) {
  .footer-links {
    margin-left: 0;
    width: 100%;
    justify-content: space-between;
  }
}

/* ---- Late additions ---------------------------------------------------- */

/*
 * The verdict is a conclusion, so it arrives after the evidence it is drawn
 * from. main.js holds it in a pending colour until the last signal resolves.
 */
.verdict-state {
  transition: color 420ms var(--ease);
}

.verdict-state.is-pending {
  color: var(--ink-700);
}

/* The car draws itself in as the section arrives, then the points light. */
.js-reveal .check .car-body,
.js-reveal .check .car-glass,
.js-reveal .check .car-roof,
.js-reveal .check .car-wheel {
  opacity: 0;
  transition: opacity 700ms var(--ease) 120ms;
}

.js-reveal .check.is-visible .car-body,
.js-reveal .check.is-visible .car-glass,
.js-reveal .check.is-visible .car-roof,
.js-reveal .check.is-visible .car-wheel {
  opacity: 1;
}

/* The mirrors are what make a top-down rounded shape read as a car. */
.car-mirror {
  fill: var(--ink-900);
  stroke: var(--ink-780);
  stroke-width: 1;
}

/*
 * The capability description, relocated. On wide screens it lives beside its
 * capability in the list; on a phone the list is a rail of names, so the
 * description moves here rather than being hidden.
 */
.os-desc {
  display: none;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-secondary);
  margin-bottom: var(--space-sm);
}

@media (max-width: 640px) {
  .os-desc {
    display: block;
  }
}
