/* KIDA Studios — layout inspired by developer.apple.com */

:root {
  --bg: #000000;
  --bg-elevated: #000000;
  --bg-alt: #0a0a0a; /* alternate / band sections + landing */
  --surface: #1d1d1f;
  --surface-2: #2a2a2c;
  --ink: #f5f5f7;
  --ink-2: #d2d2d7;
  --muted: #a1a1a6;
  --faint: #6e6e73;
  --line: rgba(255, 255, 255, 0.12);
  --link: #2997ff;
  --link-hover: #6cb5ff;
  --btn: #f5f5f7;
  --btn-text: #000000;
  --max: 980px;
  --max-wide: 1120px;
  --nav-h: 56px;
  --section-y: 115px; /* +20% on previous 96px */
  --section-x: 22px;
  --footer-y: 22px;  /* compact band; shares --section-x horizontally */
  /* Space between the nav and the hero content — 1.15x the section rhythm. */
  --hero-top-gap: calc(var(--section-y) * 1.15);
  /* Hero bottom is its own token so desktop can gain height without
     touching the tuned nav-to-content gap above. */
  --hero-bottom-gap: var(--section-y);
  --strip-y: 30px;   /* marquee band = 2*strip-y + icon = 94px (was 72px) */
  --radius: 18px;
  --radius-lg: 28px;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
    "Helvetica Neue", Helvetica, Arial, sans-serif;
  --ease: cubic-bezier(0.25, 0.1, 0.25, 1);

  /* Type scale — shared across sections */
  --fs-hero: clamp(34px, 7.2vw, 64px);
  --fs-section: clamp(32px, 5vw, 48px);   /* section H2 */
  --fs-subhead: 21px;                     /* card / step titles */
  --fs-lead: 19px;                        /* section descriptions */
  --fs-body: 15px;                        /* body / card copy */
  --fs-caption: 13px;                     /* secondary captions */
  --fs-micro: 12px;                       /* nav, labels, footer */

  --fw-section: 600;
  --fw-subhead: 600;
  --fw-body: 400;

  --lh-section: 1.08349;
  --lh-lead: 1.4211;
  --lh-body: 1.45;
  --lh-subhead: 1.2;

  --ls-section: -0.015em;
  --ls-lead: 0.012em;
  --ls-body: -0.01em;
  --ls-subhead: -0.01em;

  --section-head-gap: 40px;               /* space under title block */
  --title-to-lead: 16px;                  /* space title → description */

  /* Buttons — shared across nav, hero, sections, tiles */
  --btn-fs: 17px;
  --btn-fw: 400;
  --btn-lh: 1.17648;
  --btn-ls: -0.022em;
  --btn-pad-y: 12px;
  --btn-pad-x: 22px;
  --btn-radius: 980px;
  --btn-gap: 4px;

  --btn-link-fs: var(--fs-body);          /* 15px — text CTAs + tile links */
  --btn-link-pad-y: 12px;
  --btn-link-pad-x: 8px;
  --btn-underline-offset: 3px;

  /* Compact primary (nav bar only) */
  --btn-nav-fs: 14px;
  --btn-nav-pad-y: 8px;
  --btn-nav-pad-x: 16px;
}

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

html {
  scroll-behavior: smooth;
  /* Anchor jumps (#platforms, #apps, #services…) were landing underneath the
     fixed nav. Offset the scroll target so headings clear it. */
  scroll-padding-top: calc(var(--nav-h) + 16px);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.47059;
  font-weight: 400;
  letter-spacing: -0.022em;
  color: var(--ink);
  background: var(--bg);
  overflow-x: hidden;
}

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

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  cursor: pointer;
  border: none;
  background: none;
  color: inherit;
}

ul {
  list-style: none;
}

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

.skip-link {
  position: absolute;
  top: -100px;
  left: 16px;
  z-index: 1000;
  padding: 10px 16px;
  background: #fff;
  color: #000;
  font-weight: 600;
  border-radius: 980px;
  font-size: 14px;
}

.skip-link:focus {
  top: 12px;
}

/* ── Buttons ── */
.btn,
.nav__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap);
  font-family: inherit;
  font-weight: var(--btn-fw);
  line-height: var(--btn-lh);
  letter-spacing: var(--btn-ls);
  border-radius: var(--btn-radius);
  white-space: nowrap;
  transition: background 0.2s var(--ease), color 0.2s, opacity 0.2s, filter 0.2s;
  text-decoration: none;
}

.btn {
  padding: var(--btn-pad-y) var(--btn-pad-x);
  font-size: var(--btn-fs);
}

.btn:focus-visible,
.nav__cta:focus-visible,
.tile__link:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 3px;
}

/* Filled primary — white pill, blue on hover */
.btn--primary,
.nav__cta {
  background: var(--btn);
  color: var(--btn-text);
}

.btn--primary:hover,
.nav__cta:hover {
  background: var(--link);
  color: #fff;
  filter: none;
}

/* Text link CTA — blue + chevron style */
.btn--link,
.tile__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap);
  background: transparent;
  color: var(--link);
  font-size: var(--btn-link-fs);
  font-weight: var(--btn-fw);
  line-height: var(--btn-lh);
  letter-spacing: var(--btn-ls);
  padding: var(--btn-link-pad-y) var(--btn-link-pad-x);
  border-radius: var(--btn-radius);
  transition: color 0.2s;
  text-decoration: none;
}

.btn--link:hover,
.tile__link:hover {
  color: var(--link-hover);
  text-decoration: underline;
  text-underline-offset: var(--btn-underline-offset);
}

.btn--link span,
.tile__link span {
  font-size: 1.15em;
  line-height: 1;
}

/* ── Nav ──
   Light bar site-wide. The alpha sits high (0.9) rather than Apple's ~0.8
   because the page still has two dark bands (`.conv`, `.cta-band`) and the
   inner pages are dark: at 0.8 the bar visibly greyed out as they passed
   under it. */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--nav-h);
  background: rgba(251, 251, 253, 0.9);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid rgba(0, 0, 0, 0.09);
}

.nav.scrolled {
  background: rgba(251, 251, 253, 0.96);
}

.nav__inner {
  width: min(var(--max-wide), calc(100% - 44px));
  margin-inline: auto;
  height: 100%;
  display: flex;
  align-items: center;
  gap: 28px;
}

/* The wordmark is a near-white monochrome PNG cut for a dark bar — invert it
   for the light one. */
.nav__logo img {
  height: 34px;
  width: auto;
  filter: invert(1);
  opacity: 0.88;
}

.nav__logo:hover img {
  opacity: 1;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 22px;
  margin-left: auto;
}

.nav__links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.72);
  letter-spacing: -0.01em;
  transition: color 0.2s;
}

.nav__links a:hover {
  color: #000;
}

.nav__ico {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  opacity: 0.85;
}

.nav__links a:hover .nav__ico {
  opacity: 1;
}

/* Nav CTA: compact pill. The shared `.btn--primary` fill is near-white for a
   dark bar, so invert it here — dark pill, white label. Needs the
   `.nav__links a.nav__cta` pair as well: the mobile CTA lives inside that list
   and `.nav__links a` (0,2,1) outranks a bare `.nav__cta` (0,1,0), which
   otherwise leaves dark text on the dark pill on phones. */
.nav__cta,
.nav__links a.nav__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: var(--btn-nav-pad-y) var(--btn-nav-pad-x);
  font-size: var(--btn-nav-fs);
  background: #1d1d1f;
  color: #fff;
}

.nav__cta:hover,
.nav__links a.nav__cta:hover {
  background: #0b5ed7;
  color: #fff;
}

.nav__cta .nav__ico {
  opacity: 1;
}

/* Higher specificity than `.nav__links a` so only one CTA shows */
a.nav__cta--mobile,
.nav__links a.nav__cta--mobile {
  display: none;
}

.nav__ham {
  display: none;
  width: 40px;
  height: 40px;
  position: relative;
  flex-shrink: 0;
}

.nav__ham span {
  position: absolute;
  left: 11px;
  right: 11px;
  height: 1px;
  background: #1d1d1f;
  transition: transform 0.25s var(--ease), top 0.25s var(--ease), opacity 0.2s;
}

.nav__ham span:nth-child(1) { top: 15px; }
.nav__ham span:nth-child(2) { top: 19.5px; }
.nav__ham span:nth-child(3) { top: 24px; }

.nav__ham.open span:nth-child(1) {
  top: 19.5px;
  transform: rotate(45deg);
}

.nav__ham.open span:nth-child(2) {
  opacity: 0;
}

.nav__ham.open span:nth-child(3) {
  top: 19.5px;
  transform: rotate(-45deg);
}

/* ── Hero ── */
.hero {
  position: relative;
  display: block;
  min-height: 0;
  /* Top clears the fixed nav, then adds --hero-top-gap of breathing room.
     That gap is tokenised separately from --section-y so phones can tighten it
     without touching the hero's bottom padding or any other section. */
  padding: calc(var(--nav-h) + var(--hero-top-gap)) var(--section-x) var(--hero-bottom-gap);
  text-align: center;
  overflow: visible;   /* the ASCII field runs on below the hero — see .hero-ascii */
  background: var(--bg);
}

/* Desktop gets a taller hero — 600px was a little short for the icon field to
   breathe. All of it goes on the bottom: the top gap is deliberately set
   (nav + 1.15x --section-y) and moving it would undo that. Phones keep the
   plain --section-y from :root. */
@media (min-width: 769px) {
  :root {
    --hero-bottom-gap: calc(var(--section-y) * 1.4);
  }
}

/* Full-section transparent background video layer (single <video>, never in-flow) */
.hero-bg {
  position: absolute !important;
  top: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: 100% !important;
  z-index: 0 !important;
  overflow: visible !important;
  pointer-events: none !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  background: transparent !important;
}

.hero-bg__video {
  position: absolute !important;
  top: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
  max-height: none !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  display: block !important;
  object-fit: cover !important;
  object-position: center center !important;
  /* Very transparent ambient plate */
  opacity: 0.22 !important;
  pointer-events: none !important;
  background: transparent !important;
  transition: opacity 0.35s var(--ease);
}

.hero-bg__video.is-fading {
  opacity: 0 !important;
}

.hero-bg__scrim {
  position: absolute !important;
  top: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  left: 0 !important;
  z-index: 1 !important;
  pointer-events: none !important;
  background:
    radial-gradient(ellipse 80% 70% at 50% 45%, transparent 0%, rgba(0, 0, 0, 0.25) 100%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.2) 0%, transparent 35%, transparent 65%, rgba(0, 0, 0, 0.3) 100%);
}

/* Only in-flow child — sizes the section; sits above the bg video */
.hero__content {
  position: relative;
  z-index: 2;
  /* Sits on the same reading rail as every `.section__head` below it, so the
     hero headline and the section headings share one left/right edge. Was a
     one-off 920px, which set it 30px in from everything else. */
  width: min(var(--max), 100%);
  margin-left: auto;
  margin-right: auto;
}

.hero__platforms {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px 4px;
  margin-bottom: 18px;
}

.hero__chip {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: rgba(255, 255, 255, 0.42);
  font-family: inherit;
  font-size: var(--fs-hero);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.03em;
  padding: 4px 10px;
  border-radius: 12px;
  cursor: pointer;
  white-space: nowrap;
  transition:
    color 0.25s var(--ease),
    background 0.25s var(--ease),
    border-color 0.25s var(--ease),
    transform 0.25s var(--ease),
    text-shadow 0.25s var(--ease);
}

.hero__chip:hover {
  color: rgba(255, 255, 255, 0.85);
  background: rgba(255, 255, 255, 0.04);
}

.hero__chip:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 3px;
}

.hero__chip.is-active {
  color: #fff;
  background: rgba(41, 151, 255, 0.1);
  border-color: rgba(41, 151, 255, 0.35);
  text-shadow: 0 0 40px rgba(41, 151, 255, 0.35);
  transform: translateY(-2px);
}

.hero__sep {
  display: inline-block;
  width: 4px;
  height: 4px;
  margin: 0 0.2em;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  flex-shrink: 0;
}

.hero__desc {
  /* Horizontal inset for the blurb. Folded into max-width because
     box-sizing:border-box is global: a bare `padding-inline` would eat into the
     420px measure on wide screens instead of insetting from the edge. This way
     the text measure stays 420px wherever the cap binds (tablet and desktop),
     and the padding only bites on phones, where the blurb previously ran the
     full width edge to edge. */
  --hero-desc-pad: 24px;
  min-height: 3em;
  max-width: calc(420px + 2 * var(--hero-desc-pad));
  padding-inline: var(--hero-desc-pad);
  margin: 0 auto 28px;
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  color: var(--link);
  opacity: 0.95;
  transition: opacity 0.2s;
}

.hero__desc.is-swap {
  opacity: 0;
}

/* Shared section rhythm */
.os-sec,
.conv,
.section,
.cta-band {
  padding: var(--section-y) var(--section-x);
  border-top: 1px solid var(--line);
}

.apps-sec {
  background: var(--bg);
}

/* OS section */
.os-sec {
  background: var(--bg-alt); /* first grey band; hero stays solid black */
  text-align: center;
  /* Thin strip now — icons only, no title block. Override the shared
     `.os-sec, .conv, .section, .cta-band` padding above. Full-bleed
     horizontally on purpose: the marquee slides edge to edge. */
  padding: var(--strip-y) 0;
  /* No `overflow: hidden` here. `.os-marquee` already clips and masks the track
     itself, so this was redundant — and it would have clipped the elevation
     shadows below, which are drawn deliberately OUTSIDE the strip's box.
     z-index lifts the strip and its shadows above `.apps-sec`, which follows in
     the DOM and would otherwise paint over the lower shadow. */
  position: relative;
  z-index: 1;
}

.os-sec__inner {
  width: min(var(--max-wide), 100%);
  margin-inline: auto;
}

.os-sec__title {
  font-size: var(--fs-section);
  font-weight: var(--fw-section);
  letter-spacing: var(--ls-section);
  line-height: var(--lh-section);
  color: #f5f5f7;
  margin: 0 0 var(--title-to-lead);
}

.os-sec__lead {
  font-size: var(--fs-lead);
  font-weight: var(--fw-body);
  line-height: var(--lh-lead);
  letter-spacing: var(--ls-lead);
  color: var(--muted);
  margin: 0 auto var(--section-head-gap);
  max-width: 640px;
}

/* OS row — always a single line */
.os-row {
  margin: 0 auto;
  width: 100%;
  max-width: 100%;
}

.os-row__list {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: stretch;
  gap: clamp(4px, 0.8vw, 10px);
  width: 100%;
}

.os-row__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(4px, 0.6vw, 8px);
  flex: 1 1 0;
  min-width: 0;
  padding: clamp(8px, 1.2vw, 12px) clamp(2px, 0.6vw, 8px) clamp(6px, 1vw, 10px);
  border-radius: 12px;
  border: 1px solid transparent;
  background: rgba(255, 255, 255, 0.03);
  color: var(--ink-2);
  transition: background 0.2s, border-color 0.2s, color 0.2s, transform 0.2s;
}

.os-row__item:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.12);
  color: #fff;
  transform: translateY(-2px);
}

.os-row__icon {
  display: grid;
  place-items: center;
  width: clamp(18px, 2.8vw, 36px);
  height: clamp(18px, 2.8vw, 36px);
  color: #f5f5f7;
  opacity: 0.9;
}

.os-row__icon svg {
  width: 100%;
  height: 100%;
}

.os-row__item:hover .os-row__icon {
  opacity: 1;
}

.os-row__name {
  font-size: clamp(8px, 1.15vw, 11px);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  text-align: center;
}

.os-row__item:hover .os-row__name {
  color: var(--ink-2);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 16px 20px;
}

.hero__seo {
  margin-top: 36px;
  max-width: 520px;
  margin-inline: auto;
  font-size: 12px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.28);
  letter-spacing: 0;
}

/* ── Conversion strip (centered, matches other sections) ── */
.conv {
  background: var(--bg-alt);
  text-align: center;
}

.conv__inner {
  width: min(var(--max-wide), 100%);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.conv__head {
  width: min(var(--max), 100%);
  margin: 0 auto var(--section-head-gap);
}

.conv__head h2 {
  font-size: var(--fs-section);
  font-weight: var(--fw-section);
  letter-spacing: var(--ls-section);
  line-height: var(--lh-section);
  color: #f5f5f7;
  margin: 0 0 var(--title-to-lead);
}

.conv__head > p {
  font-size: var(--fs-lead);
  font-weight: var(--fw-body);
  line-height: var(--lh-lead);
  letter-spacing: var(--ls-lead);
  color: var(--muted);
  max-width: 640px;
  margin: 0 auto;
}

.conv__points {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  width: 100%;
  margin: 0 0 40px;
  text-align: center;
}

.conv__points li {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 28px 20px 24px;
  background: var(--surface);
  border-radius: var(--radius-lg);
  border: 1px solid rgba(255, 255, 255, 0.06);
  transition: border-color 0.2s, background 0.2s, transform 0.2s;
}

.conv__points li:hover {
  border-color: rgba(41, 151, 255, 0.28);
  background: #252528;
  transform: translateY(-2px);
}

.conv__n {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  margin-bottom: 14px;
  border-radius: 50%;
  font-size: 14px;
  font-weight: 600;
  color: var(--link);
  background: rgba(41, 151, 255, 0.1);
  border: 1px solid rgba(41, 151, 255, 0.28);
}

.conv__points strong {
  display: block;
  font-size: var(--fs-subhead);
  font-weight: var(--fw-subhead);
  line-height: var(--lh-subhead);
  color: #f5f5f7;
  letter-spacing: var(--ls-subhead);
  margin-bottom: 8px;
}

.conv__points li > span:not(.conv__n) {
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: var(--lh-body);
  color: var(--muted);
  letter-spacing: var(--ls-body);
  max-width: 22em;
}

.conv__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px 18px;
}

/* ── Sections ── */
.section {
  background: var(--bg);
}

.apps__store-link {
  color: var(--link);
  text-decoration: none;
}

.apps__store-link:hover {
  color: var(--link-hover);
  text-decoration: underline;
  text-underline-offset: var(--btn-underline-offset);
}

/* Three equal app tiles on desktop */
.tile-grid--apps {
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 900px) {
  .tile-grid--apps {
    grid-template-columns: 1fr;
  }
}

/* App identity: large icon + title + platform chips */
.app-id {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 14px;
}

.app-id__icon {
  width: 72px;
  height: 72px;
  border-radius: 16px;
  object-fit: cover;
  flex-shrink: 0;
  background: #111;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
}

.app-id__text {
  min-width: 0;
  flex: 1;
  padding-top: 2px;
}

.app-id__text h3 {
  margin-bottom: 8px;
}

.app-platforms {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
}

.app-platforms li {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 8px 4px 6px;
  border-radius: 980px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--ink-2);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1;
}

.app-platforms li svg {
  flex-shrink: 0;
  opacity: 0.9;
}

/* Icon above every section title */
.section-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  margin: 0 auto 18px;
  border-radius: 14px;
  color: var(--link);
  background: rgba(41, 151, 255, 0.1);
  border: 1px solid rgba(41, 151, 255, 0.22);
}

.section-icon svg {
  width: 28px;
  height: 28px;
  display: block;
}

.section__head {
  width: min(var(--max), 100%);
  margin: 0 auto var(--section-head-gap);
  text-align: center;
}

.section__head h2 {
  font-size: var(--fs-section);
  font-weight: var(--fw-section);
  letter-spacing: var(--ls-section);
  line-height: var(--lh-section);
  margin: 0 0 var(--title-to-lead);
  color: #f5f5f7;
}

.section__lead {
  font-size: var(--fs-lead);
  font-weight: var(--fw-body);
  line-height: var(--lh-lead);
  letter-spacing: var(--ls-lead);
  color: var(--muted);
  max-width: 640px;
  margin: 0 auto;
}

/* ── Service tiles (Apple card style) ── */
.tile-grid {
  width: min(var(--max-wide), 100%);
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
}

.tile {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform 0.3s var(--ease), background 0.3s;
}

.tile:hover {
  background: #252528;
  transform: scale(1.01);
}

.tile__media {
  height: 180px;
  overflow: hidden;
  background: #111;
}

.tile__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}

.tile:hover .tile__media img {
  transform: scale(1.03);
}

.tile__body {
  padding: 28px 28px 32px;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.tile__icon {
  width: 44px;
  height: 44px;
  object-fit: contain;
  margin-bottom: 16px;
  border-radius: 10px;
}

.tile h3 {
  font-size: var(--fs-subhead);
  font-weight: var(--fw-subhead);
  letter-spacing: var(--ls-subhead);
  line-height: var(--lh-subhead);
  margin-bottom: 10px;
  color: #f5f5f7;
}

.tile p {
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  color: var(--muted);
  margin-bottom: 18px;
  flex: 1;
}

.tile__link {
  margin-top: auto;
  padding-left: 0;
  justify-content: flex-start;
}

.tile__links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-top: auto;
}

.tile__links .tile__link {
  margin-top: 0;
}

/* ── CTA band ── */
.cta-band {
  background: var(--bg-alt);
  text-align: center;
}

/* ── FAQ ── */
.faq-sec {
  background: var(--bg);
}

.faq {
  width: min(var(--max), 100%);
  margin: 0 auto;
  display: grid;
  gap: 10px;
  text-align: left;
}

.faq__item {
  background: var(--surface);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius);
  padding: 0;
  overflow: hidden;
}

.faq__item summary {
  list-style: none;
  cursor: pointer;
  padding: 22px 28px;
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: var(--ls-body);
  line-height: 1.4;
}

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

.faq__item summary::after {
  content: "+";
  float: right;
  color: var(--link);
  font-weight: 500;
  margin-left: 16px;
}

.faq__item[open] summary::after {
  content: "–";
}

.faq__item p {
  margin: 0;
  padding: 4px 28px 24px;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  color: var(--muted);
}

@media (max-width: 768px) {
  .faq__item summary {
    padding: 18px 20px;
  }

  .faq__item p {
    padding: 2px 20px 20px;
  }
}

.faq__item a {
  color: var(--link);
}

.faq__item a:hover {
  color: var(--link-hover);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.cta-band__inner {
  width: min(var(--max), 100%);
  margin-inline: auto;
}

.cta-band h2 {
  font-size: var(--fs-section);
  font-weight: var(--fw-section);
  letter-spacing: var(--ls-section);
  line-height: var(--lh-section);
  margin: 0 0 var(--title-to-lead);
  color: #f5f5f7;
}

.cta-band p {
  font-size: var(--fs-lead);
  font-weight: var(--fw-body);
  line-height: var(--lh-lead);
  letter-spacing: var(--ls-lead);
  color: var(--muted);
  margin: 0 auto 28px;
  max-width: 640px;
}

/* ── Footer (compact bar) ── */
.footer {
  background: var(--bg);
  color: var(--ink-2);
  /* Deliberately compact rather than the full --section-y, but symmetric and
     on the shared --section-x rail. Was an odd 20px/18px pair. */
  padding: var(--footer-y) var(--section-x);
  font-size: var(--fs-micro);
  line-height: 1.33337;
  letter-spacing: -0.01em;
  border-top: 1px solid var(--line);
}

.footer__inner {
  width: min(var(--max-wide), 100%);
  margin-inline: auto;
}

/* Three columns, brand | nav | empty, rather than a flex row. With the badge
   gone the row holds only the brand and the links, and under flex the nav would
   centre itself in the space *left over* beside the brand — visibly off-centre
   by half the wordmark's width. The empty third column restores the balance the
   badge used to provide, so the links sit centred on the page. */
.footer__row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  grid-template-areas: "brand nav .";
  align-items: center;
  gap: 12px 20px;
}

.footer__brand {
  grid-area: brand;
  justify-self: start;
  display: flex;
  align-items: center;
}

.footer__brand img {
  height: 28px;
  width: auto;
  display: block;
}

.footer__nav {
  grid-area: nav;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 14px;
  min-width: 0;
  text-align: center;
}

.footer__nav a {
  color: var(--muted);
  transition: color 0.15s;
  white-space: nowrap;
}

.footer__nav a:hover {
  color: var(--link);
}

/* The Startup India badge and its rules were removed on 2026-08-13. */

.footer__copy a{color:var(--muted);text-decoration:underline;text-underline-offset:2px}
.footer__copy a:hover{color:var(--link)}
.footer__copy {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  color: var(--faint);
  font-size: 11px;
  text-align: center;
}

/* ── Responsive ── */
@media (max-width: 900px) {
  .tile-grid {
    grid-template-columns: 1fr;
  }

  .conv__points {
    grid-template-columns: 1fr;
    max-width: none;
  }

}

@media (max-width: 768px) {
  /* Alignment matches desktop at every width: centred headings, leads, icons
     and CTAs. The rules that forced left here have been removed rather than
     flipped to `center`, so the desktop values simply apply — including the
     parts desktop deliberately keeps left (.section body copy, .tile__body,
     .faq), which stay left on purpose. Only width overrides remain below. */
  .hero__content {
    width: 100%;
    max-width: none;
    margin-left: 0;
    margin-right: 0;
  }

  /* `justify-content`/`align-items` overrides dropped so the hero chips,
     buttons and CTA rows centre as they do on desktop.

     The auto side margins on .hero__desc / .section__lead / .cta-band p are
     also left alone: their max-width caps (560-640px) never bind on a phone,
     but they do at 768px, where margin:0 would have parked the capped text
     against the left edge instead of centring it. */
  .hero__desc {
    /* padding no longer zeroed here — see the base rule's --hero-desc-pad */
    min-height: 0;
  }

  .os-sec__inner,
  .conv__inner,
  .section__head,
  .cta-band__inner,
  .tile-grid {
    margin-left: 0;
    margin-right: 0;
    width: 100%;
  }

  .conv__inner {
    align-items: stretch;
  }

  .conv__points li > span:not(.conv__n) {
    max-width: none;
  }

  .tile__body {
    text-align: left;
  }

  .nav__links {
    position: fixed;
    top: var(--nav-h);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin-left: 0;
    padding: 8px 22px 20px;
    /* Opaque, not frosted: at 0.97 over a dark page the white body text
       ghosted through the sheet as faint light streaks. */
    background: #fbfbfd;
    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
    transform: translateY(-120%);
    opacity: 0;
    pointer-events: none;
    transition: transform 0.3s var(--ease), opacity 0.3s;
  }

  .nav__links.open {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }

  .nav__links a {
    padding: 14px 0;
    font-size: 15px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  }

  .nav__cta--desktop {
    display: none;
  }

  a.nav__cta--mobile,
  .nav__links a.nav__cta--mobile {
    display: inline-flex;
    justify-content: center;
    margin-top: 14px;
    border-bottom: none !important;
    /* full-size primary on mobile menu */
    padding: var(--btn-pad-y) var(--btn-pad-x) !important;
    font-size: var(--btn-fs) !important;
  }

  .nav__ham {
    display: block;
    margin-left: auto;
  }

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

  .hero__sep {
    display: none;
  }

  .hero__platforms {
    gap: 6px 8px;
    margin-bottom: 14px;
  }

  .hero__chip {
    /* font-size intentionally omitted — it comes from --fs-hero, which the
       <=1024px override raises. A hardcoded clamp here used to cap phones at
       40px and produced a 40px -> 64px jump across the 768/769 boundary. */
    padding: 6px 12px;
  }

  .hero__desc {
    margin-bottom: 20px;
  }

  .hero__actions {
    flex-direction: column;
    gap: 10px;
  }

  /* Platforms OS row: 3 lines on mobile (~4 per row) */
  .os-row__list {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    flex-wrap: unset;
    gap: 10px 8px;
    width: 100%;
  }

  .os-row__item {
    flex: unset;
    min-width: 0;
    width: 100%;
  }

  .os-row__icon {
    width: 28px;
    height: 28px;
  }

  .os-row__name {
    font-size: 11px;
  }

  .os-row__item:hover {
    transform: none;
  }

  .tile__body {
    padding: 22px 22px 26px;
  }

  .app-id__icon {
    width: 64px;
    height: 64px;
    border-radius: 14px;
  }

  :root {
    --section-y: 92px; /* +20% on previous 77px */
    --section-x: 18px;
    --footer-y: 20px;
    /* Phones run at half the previous nav-to-content gap: 0.92 -> 0.46, so
       92px * 0.46 = 42.3px (was 84.6px). Bottom padding stays at the full
       --section-y, so only the top changes. */
    --hero-top-gap: calc(var(--section-y) * 0.46);
    --fs-subhead: 19px;
    --fs-lead: 17px;
    --fs-body: 15px;
  }
}

@media (max-width: 480px) {
  .nav__inner {
    width: min(var(--max-wide), calc(100% - 32px));
  }

  .footer__row {
    gap: 10px 12px;
  }

  .footer__brand img {
    height: 24px;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .tile:hover {
    transform: none;
  }

  .hero__chip.is-active {
    transform: none;
  }

  .hero-bg__video {
    opacity: 0.1 !important;
  }
}

/* ---- Breadcrumbs ---- */
.breadcrumb {
  margin: 0 0 18px;
}
.breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  line-height: 1.4;
  color: var(--faint);
  letter-spacing: -0.01em;
}
.breadcrumb__list li {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.breadcrumb__list li + li::before {
  content: "›";
  color: var(--faint);
  opacity: 0.7;
}
.breadcrumb a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
}
.breadcrumb a:hover {
  color: var(--link-hover);
}
.breadcrumb a:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
  border-radius: 4px;
}
.breadcrumb [aria-current="page"] {
  color: var(--ink-2);
}


/* ═══════════════════════════════════════════════════════════════════
   HERO APP ORBIT
   Our six published apps floating in the gutters either side of the
   headline. Full strength — these are our IP, not background texture —
   and each one links to its product page.

   Lives outside .hero-bg because that layer is pointer-events:none.
   Anchored to the viewport edge rather than a percentage: the headline is
   centred and max-width capped, so its inked width grows as a share of a
   narrow viewport and percentage-placed icons drift into the text.
   ═══════════════════════════════════════════════════════════════════ */

.app-orbit,
.app-orbit--a,
.app-orbit--b {
  --base-size: 84px;
  /* Scale range the placement script samples from. Max is 0.8 so the largest
     icon is 0.8x the base; the low floor gives real size variation. */
  --scale-min: 0.40;
  --scale-max: 0.80;
  position: absolute;
  inset: 0;
  z-index: 3;              /* above the scrim so the links are clickable */
  margin: 0;
  padding: 0;
  list-style: none;
  pointer-events: none;    /* only the links themselves are interactive */
  --gx: 3vw;
}

.app-orbit__item {
  position: absolute;
  top: var(--y);
}
/* Fallback placement if JS never runs — the scatter routine overrides these
   with inline left/top on load. */
.app-orbit__item[data-side="left"]:not([style*="left"])  { left:  var(--gx); }
.app-orbit__item[data-side="right"]:not([style*="left"]) { right: var(--gx); }

.app-orbit__link {
  display: block;
  pointer-events: auto;
  border-radius: 22%;
  /* slow float, staggered per icon */
  animation: app-orbit-float 6s ease-in-out infinite alternate;
  animation-delay: calc(var(--i, 0) * -1.3s);
  will-change: transform;
}

.app-orbit__link img {
  /* --base-size is read by the placement script; --scale gives each icon a
     +/-15% variation so the set doesn't look stamped out. */
  width: calc(var(--base-size) * var(--scale, 1));
  height: calc(var(--base-size) * var(--scale, 1));
  border-radius: 23%;
  object-fit: cover;
  /* a rim stops the pale icons (Lookout, Envora) bleeding into pure black */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.10);
  transition: transform 0.3s var(--ease), box-shadow 0.3s;
}

.app-orbit__link:hover img,
.app-orbit__link:focus-visible img {
  transform: scale(1.08);
  box-shadow: 0 0 0 1px rgba(41, 151, 255, 0.6);
}
.app-orbit__link:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 4px;
}

@keyframes app-orbit-float {
  from { transform: translate(0, 0)         rotate(-1.5deg); }
  to   { transform: translate(6px, -16px)   rotate(2deg);    }
}

@media (max-width: 1200px) {
  .app-orbit { --gx: 1.6vw; --base-size: 78px; }
}

/* ── Phones: no gutter exists ──
   Below 780px the headline wraps to three lines and fills the width, so
   gutter icons would sit on top of the type and swallow taps. Flow them into
   a grid beneath the hero content instead — still in the section, still
   floating, still clickable. */
/* ── Phones: three icons above the headline, three below ──
   Each group stays in flow as its own band, so the hero reserves the space
   and neither band can ever cover the type. The script scatters within each
   band independently. */
@media (max-width: 780px) {
  .app-orbit {
    position: relative;
    inset: auto;
    display: block;
    width: 100%;
    pointer-events: auto;
    --base-size: 74px;
    --scale-min: 0.62;
    /* 1.20 puts the largest phone icon at 74 * 1.2 = 89px — 1.5x the 59px it
       was at 0.80. The bands below are sized to hold that plus the 18px float
       drift the placement script insets on each edge. */
    --scale-max: 1.20;
  }
  .app-orbit--a { height: 132px; margin: 6px 0 18px; }   /* above the text */
  .app-orbit--b { height: 142px; margin: 26px 0 0; }     /* below the CTA  */

  .app-orbit__item[data-side="left"]:not([style*="left"]),
  .app-orbit__item[data-side="right"]:not([style*="left"]) {
    left: auto;
    right: auto;
  }
}

@media (max-width: 420px) {
  /* --scale-max carries over from the block above, so the smaller base keeps
     the same 1.5x uplift: 66 * 1.2 = 79px, up from 53px. */
  .app-orbit--a { height: 122px; }
  .app-orbit--b { height: 130px; }
  .app-orbit { --base-size: 66px; }
}

@media (prefers-reduced-motion: reduce) {
  .app-orbit__link { animation: none; }
  .app-orbit__link:hover img { transform: none; }
}


/* ═══════════════════════════════════════════════════════════════════
   PLATFORMS MARQUEE
   The platforms section is a thin strip of icons sliding continuously.
   main.js duplicates the track so the loop is seamless; the animation
   translates exactly -50%, which lands the copy where the original was.
   ═══════════════════════════════════════════════════════════════════ */

.os-marquee {
  position: relative;
  width: 100%;
  overflow: hidden;
  /* fade the icons out at both ends instead of hard-cutting them */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.os-marquee__track {
  display: flex;
  width: max-content;
  animation: os-marquee-scroll 34s linear infinite;
}

/* Only animate once the track has actually been duplicated, or a single
   copy would slide off and leave a gap. */
.os-marquee__track:not(.is-looping) {
  animation: none;
  width: 100%;
  justify-content: center;
}

.os-marquee:hover .os-marquee__track.is-looping {
  animation-play-state: paused;
}

.os-marquee .os-row__list {
  /* One token drives both: the side padding must be exactly half the item gap,
     or the join between two copies is wider than the rhythm inside a copy and
     the seam shows every cycle. The mobile override below only changed the gap,
     which left a 22.5px inner gap against a 28px seam. */
  --os-gap: clamp(39px, 5.6vw, 87px); /* +40% — the icons were cramped */
  display: flex;
  flex: 0 0 auto;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-start;
  gap: var(--os-gap);
  width: auto;
  margin: 0;
  padding: 0 calc(var(--os-gap) / 2);
  list-style: none;
}

.os-marquee .os-row__item {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  /* The old mobile layout set `.os-row__item { width: 100% }` for a 4-up grid.
     Without resetting it here every marquee item filled the strip and only one
     icon was visible on phones. */
  width: auto;
  height: auto;
  padding: 0;
  border: 0;
  background: none;
  min-width: 0;
  transform: none;
}
/* The phone breakpoint also turns the list into a grid — force flex back. */
.os-marquee .os-row__list {
  display: flex !important;
  grid-template-columns: none;
}

.os-marquee .os-row__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  /* The wrapper carries a fixed height from the old 4-up grid layout
     (`clamp(18px, 2.8vw, 36px)`, and 28px under 768px). That capped the strip:
     the svg overflowed the box instead of growing it, so enlarging the icon
     did nothing to the band height. Let it size to its content here. */
  width: auto;
  height: auto;
  color: var(--muted);
  opacity: 0.72;
  transition: color 0.25s, opacity 0.25s;
}

.os-marquee .os-row__icon svg {
  width: 34px;
  height: 34px;
  display: block;
}

.os-marquee .os-row__item:hover .os-row__icon {
  color: #fff;
  opacity: 1;
}

@keyframes os-marquee-scroll {
  from { transform: translate3d(0, 0, 0);     }
  to   { transform: translate3d(-50%, 0, 0);  }
}

@media (max-width: 700px) {
  :root { --strip-y: 22px; } /* band = 22+29+22 = 73px (was 56px) */
  .os-marquee .os-row__list { --os-gap: clamp(31px, 8.4vw, 56px); } /* +40% */
  .os-marquee .os-row__icon svg { width: 29px; height: 29px; }
  .os-marquee__track { animation-duration: 26s; }
}

@media (prefers-reduced-motion: reduce) {
  /* No sliding — let it scroll manually instead. */
  .os-marquee__track,
  .os-marquee__track.is-looping { animation: none; }
  .os-marquee {
    overflow-x: auto;
    -webkit-mask-image: none;
            mask-image: none;
  }
}


/* ═══════════════════════════════════════════════════════════════════
   HERO — LIGHT THEME
   The hero is light; everything below it stays dark. Scoped to .hero so
   no other section is affected, and every selector carries the .hero
   prefix so it outranks the base rules regardless of source order.

   Note on colour: the accent #2997ff only reaches ~3:1 against a light
   background, which is fine for the huge platform chips (large-text AA)
   but fails for body copy. Body-sized text uses a darkened blue instead.
   ═══════════════════════════════════════════════════════════════════ */

.hero {
  --hero-ink: #1d1d1f;
  --hero-muted: rgba(0, 0, 0, 0.56);
  --hero-faint: rgba(0, 0, 0, 0.4);
  --hero-link: #0b5ed7;          /* 5.4:1 on #fff — safe for body text */
  background: #fff;
  color: var(--hero-ink);
}

/* ── Hero surface: ASCII warp tunnel ──
   A fine monospace grid in polar coordinates. Rings travel outward from a
   vanishing point at the centre and glyphs orient along the radius, so the
   field reads as a tunnel at speed. Deliberately too small to read as text —
   it is texture and structure, not a message.

   Strictly black on white.

   The cursor carves a hole in it: glyphs within a radius of the pointer are
   dropped, with an eased edge and an eased entry/exit, so moving the mouse
   feels like parting the field rather than toggling a mask.

   No CSS mask on this layer. The clear zone is computed in JS from the real
   bounding boxes of the hero text, so it tracks the actual layout at every
   breakpoint. Two earlier versions used a hand-tuned CSS ellipse and both
   leaked glyphs behind body copy once the aspect changed — a phone hero is
   375x864 and an ellipse tuned for landscape simply does not fit it.
   ───────────────────────────────────────────────────────────────────────── */

/* Neutral vignette only; no hue anywhere in this layer. */
.hero .hero-bg__scrim {
  background-image:
    radial-gradient(126% 102% at 50% 46%, transparent 54%, rgba(0, 0, 0, 0.05) 100%);
  background-repeat: no-repeat;
}

.hero-ascii {
  position: absolute;
  /* top/left only, NOT inset:0. The canvas is deliberately taller than the hero
     (main.js sets bleedBottom), and pinning all four edges would stretch it back
     to the host's height and undo that. */
  top: 0;
  left: 0;
  z-index: 2;
  pointer-events: none;
  display: block;
}

/* The same torus on the two conversion bands. Added to their existing wash and
   lattice background rather than replacing it: the canvas sits above the
   section's own background layers and below the content, so nothing that was
   there is lost.

   `__inner` gets a stacking position so the copy stays above the canvas — the
   sections already had `position: relative` for their lit top hairline. */
.sec-ascii {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  display: block;
}

.conv > .conv__inner,
.cta-band > .cta-band__inner {
  position: relative;
  z-index: 1;
}

.hero .hero-bg__scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='0.055'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 180px 180px;
}

@media (prefers-reduced-motion: reduce) {
  /* nothing animates here, but keep the hook alongside the other hero motion */
}

/* ── platform chips ── */
/* 0.48 alpha lands ~3.4:1 on #f5f5f7. Anything lighter fails large-text AA —
   0.30 measured 2.09:1 — while still reading clearly as "not selected"
   against the near-black active chip. */
.hero .hero__chip {
  color: rgba(0, 0, 0, 0.48);
}
.hero .hero__chip:hover {
  color: rgba(0, 0, 0, 0.78);
  background: rgba(0, 0, 0, 0.04);
}
.hero .hero__chip.is-active {
  color: var(--hero-ink);
  background: rgba(41, 151, 255, 0.14);
  border-color: rgba(41, 151, 255, 0.45);
  text-shadow: none;
}
.hero .hero__sep { background: rgba(0, 0, 0, 0.22); }

/* ── copy ── */
.hero .hero__desc { color: var(--hero-link); }
.hero .hero__seo  { color: var(--hero-faint); }

/* ── buttons ── */
/* The primary button was white-on-black; inverted it would vanish. */
.hero .btn--primary {
  background: var(--hero-ink);
  color: #fff;
}
.hero .btn--primary:hover {
  background: var(--hero-link);
  color: #fff;
}
.hero .btn--ghost {
  background: rgba(0, 0, 0, 0.05);
  color: var(--hero-ink);
  border-color: rgba(0, 0, 0, 0.14);
}
.hero .btn--ghost:hover { background: rgba(0, 0, 0, 0.1); }
.hero .btn--link { color: var(--hero-link); }
.hero .btn--link:hover { color: #0847a5; }

/* ── app icons ── */
/* No drop shadow — the icons sit flat on the light field. The 1px rim stays:
   it was a white hairline for the black background and is dark here, without
   it the pale icons (Lookout, Envora) bleed into the page. */
/* White drop shadow. On a near-white field this reads as a halo rather than a
   shadow, and it does real work: it punches the ASCII glyphs away from each
   icon so the artwork sits clearly on top of the field instead of tangling with
   it. Layer order matters — box-shadow paints the first layer on top, so the
   dark hairline hugs the icon (still needed, or pale artwork like Lookout and
   Envora bleeds into the halo), then the white ring, then the soft spread. */
.hero .app-orbit__link img {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.12),
    0 0 0 4px rgba(255, 255, 255, 0.94),
    0 3px 26px 11px rgba(255, 255, 255, 0.74);
}
.hero .app-orbit__link:hover img,
.hero .app-orbit__link:focus-visible img {
  box-shadow:
    0 0 0 1px rgba(41, 151, 255, 0.6),
    0 0 0 4px rgba(255, 255, 255, 0.96),
    0 5px 32px 13px rgba(255, 255, 255, 0.82);
}


/* ═══════════════════════════════════════════════════════════════════
   LIGHT ZONE — nav over hero, and the platforms marquee
   ═══════════════════════════════════════════════════════════════════ */

/* The nav keeps its fill everywhere, including over the hero — there is no
   transparent state. (`is-over-light` and the JS that toggled it are gone.) */

/* ── Platforms marquee ──
   White, continuous with the hero above it. It no longer runs into the apps
   grid below, which is now a black field, so the boundary there is carried by
   the colour change itself rather than by a hairline. */
.os-sec {
  background: #fff;
  border-top: 0;
  border-bottom: 0;
}

/* ── Platforms strip: elevation ──
   A box-shadow cannot vary in strength along its own length, so the falloff
   toward the screen edges is done with two masked layers instead. Each is a
   vertical shadow ramp spanning the full width, masked horizontally so it peaks
   at the centre of the viewport and is gone by the left and right edges — the
   strip reads as lifted off the page in the middle and flush at the sides.

   Drawn OUTSIDE the strip's box (bottom:100% / top:100%) rather than inset, so
   it reads as raised rather than recessed. */
.os-sec::before,
.os-sec::after,
.cta-band::before,
.cta-band::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 30px;
  pointer-events: none;
  /* Peak at 50%, nothing at either edge. Intermediate stops keep the ramp
     smooth — a plain transparent→black→transparent reads as a hard lens. */
  -webkit-mask-image: linear-gradient(90deg,
    rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.38) 20%,
    rgba(0, 0, 0, 1) 50%,
    rgba(0, 0, 0, 0.38) 80%, rgba(0, 0, 0, 0) 100%);
  mask-image: linear-gradient(90deg,
    rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.38) 20%,
    rgba(0, 0, 0, 1) 50%,
    rgba(0, 0, 0, 0.38) 80%, rgba(0, 0, 0, 0) 100%);
}

/* Above the strip, falling onto the white hero — this is the one that carries
   the effect, since the section below is black and swallows a dark shadow. */
/* On `.cta-band` both sides land on light sections — grey above, white below —
   so unlike the marquee, where the lower shadow falls on black and is swallowed,
   here both halves of the effect are actually visible.
   No z-index needed: `.services-sec` and `.faq-sec` are both statically
   positioned, so these positioned pseudo-elements already paint over them. */
.os-sec::before,
.cta-band::before {
  bottom: 100%;
  background: linear-gradient(to top,
    rgba(0, 0, 0, 0.22) 0%, rgba(0, 0, 0, 0.10) 38%, rgba(0, 0, 0, 0) 100%);
}

.os-sec::after,
.cta-band::after {
  top: 100%;
  background: linear-gradient(to bottom,
    rgba(0, 0, 0, 0.22) 0%, rgba(0, 0, 0, 0.10) 38%, rgba(0, 0, 0, 0) 100%);
}

/* ── Platforms strip: floating overlay ──
   The strip is taken OUT OF FLOW so the hero and the apps grid meet directly,
   and the tilted band floats over that seam.

   This replaces a running battle with the in-flow version: while the strip
   occupied vertical space, a rotated full-bleed band left uncovered wedges at
   two opposite corners, which needed asymmetric bleed to hide, which in turn
   dragged the elevation shadow off the visual edge and made the section read as
   taller. Out of flow there is no layout box to leave wedges in — the band is
   simply a rotated bar floating over the boundary — so the bleed, the width
   override and the shadow offset all go away with it.

   `top: 0` IS the seam: `.os-sec` is `main`'s first child, so once it leaves the
   flow, main's top edge is exactly the hero/apps boundary. translateY(-50%)
   centres the band on that line. The inline insets run it past both viewport
   edges so the rotation still reaches the corners. */
.os-sec {
  position: absolute;
  top: 0;
  left: -4%;
  right: -4%;
  z-index: 3;
  transform: translateY(-50%) rotate(-1.6deg);
}

/* Positioning context for the strip, plus the clip that contains its extra
   width. `clip`, not `hidden`: with `hidden` the other axis computes to `auto`,
   which would turn `main` into a scroll container and cut the band and its
   shadows off vertically. `overflow-x: clip` leaves `overflow-y: visible`. */
main {
  position: relative;
  overflow-x: clip;
}

/* Mobile keeps hairlines top and bottom. On desktop the hero, strip and apps
   grid read as one continuous field, but on a phone the strip sits directly
   between two tall stacked blocks and needs the rules to register as its own
   band. 768px is the site's mobile breakpoint (where the hamburger appears). */
@media (max-width: 768px) {
  .os-sec {
    border-top: 1px solid rgba(0, 0, 0, 0.09);
    border-bottom: 1px solid rgba(0, 0, 0, 0.09);
  }
}

.os-marquee .os-row__icon {
  color: rgba(0, 0, 0, 0.58);
  opacity: 1;
}
.os-marquee .os-row__item:hover .os-row__icon {
  color: #000;
  opacity: 1;
}

/* The edge fade masks the strip against its own background, so it needs the
   light tone rather than the black it was cut against before. */
.os-marquee {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

/* ═════════════════════════════════════════════════════════════
   Light sections
   The page now reads light from the hero down to the footer, with
   `.conv` (#start) and `.cta-band` left dark as accent bands at the
   two conversion moments. Every override is scoped to a light
   section so the dark bands keep the base theme untouched.

   Field tones: hero #f5f5f7 · marquee #efeff1 · sections #f5f5f7
   with white cards, footer #efeff1.
   ═════════════════════════════════════════════════════════════ */
.apps-sec,
.services-sec,
.faq-sec,
.footer {
  --lt-ink: #1d1d1f;
  --lt-muted: rgba(0, 0, 0, 0.56);
  /* .56 is the lightest that clears 4.5:1 on the #efeff1 footer field,
     which the 11px copyright line needs. */
  --lt-faint: rgba(0, 0, 0, 0.56);
  --lt-link: #0b5ed7;
  --lt-link-hover: #0847a5;
  --lt-line: rgba(0, 0, 0, 0.09);
}

/* Grey is now only the services band. The hero, the marquee and the FAQ are
   white and the apps grid is black, so alternating the three light sections as
   one shared tone no longer applies. */
.services-sec {
  background: #f5f5f7;
  border-top: 1px solid var(--lt-line);
}

.faq-sec {
  background: #fff;
  border-top: 1px solid var(--lt-line);
}

/* Base declaration only — overridden to black at the end of this file, where
   the apps field is themed. Kept so the section still has a light fallback if
   that block is ever removed. */
.apps-sec {
  background: #f5f5f7;
}

/* No rule between the marquee and the apps grid: both are #f5f5f7 now, so this
   hairline was the visible seam the strip's own borders were hiding. */
.apps-sec {
  border-top: 0;
}

/* ── Section heads ── */
.apps-sec .section-icon,
.services-sec .section-icon,
.faq-sec .section-icon {
  color: var(--lt-link);
  background: rgba(11, 94, 215, 0.08);
  border-color: rgba(11, 94, 215, 0.2);
}

.apps-sec .section__head h2,
.services-sec .section__head h2,
.faq-sec .section__head h2 {
  color: var(--lt-ink);
}

.apps-sec .section__lead,
.services-sec .section__lead,
.faq-sec .section__lead {
  color: var(--lt-muted);
}

.apps-sec .apps__store-link {
  color: var(--lt-link);
}

.apps-sec .apps__store-link:hover {
  color: var(--lt-link-hover);
}

/* ── Tiles ──
   The dark theme leans on a raised surface colour for separation. On a
   light field there is nowhere lighter to go, so a hairline plus a soft
   shadow carries it instead. */
.apps-sec .tile,
.services-sec .tile {
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.07);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  transition: transform 0.3s var(--ease), box-shadow 0.3s, border-color 0.3s;
}

.apps-sec .tile:hover,
.services-sec .tile:hover {
  background: #fff;
  border-color: rgba(0, 0, 0, 0.11);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.09);
}

.apps-sec .tile h3,
.services-sec .tile h3 {
  color: var(--lt-ink);
}

.apps-sec .tile p,
.services-sec .tile p {
  color: var(--lt-muted);
}

.apps-sec .tile__link,
.services-sec .tile__link {
  color: var(--lt-link);
}

.apps-sec .tile__link:hover,
.services-sec .tile__link:hover {
  color: var(--lt-link-hover);
}

.apps-sec .tile__link:focus-visible,
.services-sec .tile__link:focus-visible,
.faq-sec a:focus-visible {
  outline-color: var(--lt-link);
}

/* Platform chips — white-on-white washes out entirely here. */
.apps-sec .app-platforms li {
  background: rgba(0, 0, 0, 0.045);
  border-color: rgba(0, 0, 0, 0.1);
  color: rgba(0, 0, 0, 0.6);
}

/* App icons sit on white now; the heavy drop shadow reads as grime. */
.apps-sec .app-id__icon {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.14);
}

/* Tile media placeholder background, in case any tile has no image yet. */
.apps-sec .tile__media,
.services-sec .tile__media {
  background: #e8e8ed;
}

/* ── FAQ ── */
.faq-sec .faq__item {
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}

.faq-sec .faq__item summary,
.faq-sec .faq__item h3 {
  color: var(--lt-ink);
}

.faq-sec .faq__item summary::after {
  color: var(--lt-link);
}

.faq-sec .faq__item p {
  color: var(--lt-muted);
}

.faq-sec .faq__item a {
  color: var(--lt-link);
}

.faq-sec .faq__item a:hover {
  color: var(--lt-link-hover);
}

/* ── Footer ──
   Black. The --lt-* tokens are redefined here rather than unpicking `.footer`
   from the shared light block above: every footer rule reads its colour from a
   token, so six declarations flip the whole band. */
.footer {
  --lt-ink: #f5f5f7;
  --lt-muted: rgba(255, 255, 255, 0.66);
  --lt-faint: rgba(255, 255, 255, 0.6);
  --lt-link: #6cb5ff;
  --lt-link-hover: #9ccdff;
  --lt-line: rgba(255, 255, 255, 0.1);
  background: #000;
  color: var(--lt-muted);
  border-top: 1px solid var(--lt-line);
}

/* The wordmark PNG is already white, cut for dark backgrounds. The light footer
   had to invert it; on black the invert has to come off or it renders as a
   black wordmark on black. */
.footer .footer__brand img {
  filter: none;
  opacity: 0.9;
}

/* Brighter than --lt-muted so the nav still outranks the copyright line. */
.footer__nav a {
  color: rgba(255, 255, 255, 0.8);
}

.footer__nav a:hover {
  color: var(--lt-link);
}

.footer__copy {
  border-top: 1px solid var(--lt-line);
  color: var(--lt-faint);
}

.footer__copy a {
  color: var(--lt-muted);
}

.footer__copy a:hover {
  color: var(--lt-link);
}

.footer a:focus-visible {
  outline: 2px solid var(--lt-link);
  outline-offset: 3px;
}

/* The service glyphs are light-grey PNGs cut for a dark background — median
   luma 192, which is ~1.8:1 on a white card and effectively invisible.
   Invert to dark and pull the alpha back so they land near #8c8c8c: present
   but still decorative, matching the weight they had on black. */
.services-sec .tile__icon {
  filter: invert(1) opacity(0.6);
}

/* ─────────────────────────────────────────────────────────────
   Footer — tablet and phone layout
   The footer is one flex row at every width, which squeezes the
   link list into a ragged two-line wrap between the brand and the
   Startup India badge. Break it into rows instead.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  /* Tablet down: brand centred on its own row, links centred beneath. The old
     three-column arrangement existed to hold the brand and the badge at
     opposite edges; with the badge gone there is nothing to balance against. */
  .footer__row {
    grid-template-columns: 1fr;
    grid-template-areas:
      "brand"
      "nav";
    justify-items: center;
    row-gap: 18px;
    column-gap: 0;
  }

  .footer__brand { justify-self: center; }

  .footer__nav {
    justify-content: center;
    gap: 2px 20px;
  }

  /* Touch territory starts here, not at 600px — the bare links are ~16px
     tall, under the 24px minimum target size. */
  .footer__nav a {
    padding: 5px 2px;
  }
}

@media (max-width: 600px) {
  /* Phone: one centred column — brand, links, badge — then the legal line. */
  .footer {
    padding-top: 28px;
    padding-bottom: 24px;
  }

  /* Tighter column gap so the five links still hold one row on a 375px
     phone; the tap padding is inherited from the 900px block above. */
  .footer__nav {
    gap: 2px 12px;
  }

  .footer__copy {
    margin-top: 20px;
    padding-top: 16px;
    line-height: 1.5;
  }

  /* Break the legal links onto their own line rather than letting the
     copyright sentence and the two links wrap as one ragged block. The
     separator is aria-hidden, so collapsing it costs nothing. */
  .footer__copy > span:first-of-type {
    display: block;
    height: 6px;
    font-size: 0;
    line-height: 0;
  }
}

@media (max-width: 340px) {
  /* Was 360px, which fired ~24px early: measured, the five links plus their
     four 12px gaps need 292px, and a 360px viewport leaves 324px — so a
     perfectly good single row was being broken into three. 340px leaves 304px,
     still a fit; below that they genuinely wrap 4+1 with "Contact" orphaned,
     and a two-column grid wraps predictably (2/2/1) with columns aligned. */
  .footer__nav {
    display: grid;
    grid-template-columns: repeat(2, auto);
    justify-content: center;
    column-gap: 18px;
  }
}

/* ─────────────────────────────────────────────────────────────
   Hero icons — contact shadow + parallax
   The icons previously floated with no relationship to the surface.
   The shadow sits on the <li>, which does not run the float
   keyframes, so it stays grounded while the icon rises off it —
   and shrinks and fades in counterpoint, which is what sells the
   suspension. The <li> also carries the parallax translate, so
   shadow and icon travel together in depth.
   ───────────────────────────────────────────────────────────── */
.app-orbit__item {
  /* Set by the placement script from each icon's --scale; the fallback keeps
     the shadow sane if the script has not run yet. */
  --depth: 1;
  will-change: transform;
}

.app-orbit__item::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -10%;
  width: 84%;
  aspect-ratio: 2.6 / 1;
  border-radius: 50%;
  /* Softer and wider than a box-shadow can be, and independent of the icon's
     own transform. The mid stop keeps the falloff gradual instead of ramping
     straight to transparent, which read as a hard smudge. */
  background: radial-gradient(closest-side,
    rgba(0, 0, 0, 0.2),
    rgba(0, 0, 0, 0.07) 58%,
    rgba(0, 0, 0, 0) 100%);
  /* Blur proportional to the icon, not a fixed 4px: the icons range from ~34px
     to ~74px across breakpoints, and one radius cannot serve both. */
  filter: blur(calc(var(--base-size, 84px) * var(--scale, 1) * 0.07));
  z-index: -1;
  pointer-events: none;
  transform: translateX(-50%);
  animation: app-orbit-ground 6s ease-in-out infinite alternate;
  /* Same --i the float uses, so shadow and icon stay in phase. */
  animation-delay: calc(var(--i, 0) * -1.3s);
}

/* As the icon lifts 16px the contact patch tightens and lightens. */
@keyframes app-orbit-ground {
  from { transform: translateX(-50%) scale(1);    opacity: 0.6; }
  to   { transform: translateX(-50%) scale(0.78); opacity: 0.3; }
}

/* No hover override on the shadow: a running animation outranks a normal
   declaration, so any hover transform would either be ignored or snap when
   the animation was cancelled. The icon's own 1.08 scale carries the hover. */

@media (prefers-reduced-motion: reduce) {
  .app-orbit__item::after {
    animation: none;
    transform: translateX(-50%);
    opacity: 0.45;
  }
}

/* ═════════════════════════════════════════════════════════════
   Conversion bands — composed light, not photography
   Stock imagery (a node constellation, a matrix world map) read as
   generic no matter how it was darkened. This is the treatment premium
   product sites actually use: near-black, a soft off-axis colour wash
   for depth, and a fine grid for structure — all CSS.

   Three practical wins over a photo: it stays razor-sharp at any DPR
   (nothing is being upscaled), it costs zero bytes, and its lightest
   possible pixel is knowable — so text contrast cannot be ambushed by
   a stray highlight the way it was at 4.19:1 on the photos.

   Layer order (topmost first): grid, grid, wash, wash, floor vignette.
   ═════════════════════════════════════════════════════════════ */
.conv,
.cta-band {
  /* Solid black. The ASCII field is the whole treatment now, so the composed
     background it used to sit on (72px lattice, two colour washes, a floor
     vignette) was competing with it rather than supporting it. Black also
     gives the glyphs their maximum contrast range, and unlike the washes it
     has one knowable luminance — text contrast here cannot be ambushed.
     `background`, not `background-color`: the shorthand clears the
     background-image list these two selectors used to carry. */
  background: #000;
  position: relative;
}

/* No lit top hairline. It existed to lift a #08080b band away from a page that
   was also darkish; against a #f5f5f7 section directly above, a pure-black edge
   is already the hardest boundary on the page, and a 14% white line sitting on
   it just reads as a seam artifact. */

/* Text on the bare photo needs the lighter accent.
   #2997ff measures 4.19:1 against the brightest pixel in these two images —
   under AA. #6cb5ff clears it at 5.77:1 even in that worst case, and reads
   better on photography anyway. Only affects elements with no fill of their
   own: the primary pills already sit on an opaque near-white background. */
.conv .btn--link,
.cta-band .btn--link {
  color: var(--link-hover);
}

.conv .btn--link:hover,
.cta-band .btn--link:hover {
  color: #fff;
}

/* Step badges are 10%-alpha blue, so the photo shows through — lift the
   numerals and firm up the chip so 1/2/3 stay readable. */
.conv .conv__n {
  color: var(--link-hover);
  background: rgba(41, 151, 255, 0.16);
  border: 1px solid rgba(108, 181, 255, 0.28);
}


/* Mobile and tablet order the platform chips AI XR Mobile PC Embedded Web;
   desktop keeps the DOM order (…Web Embedded). Done with flex `order` so the
   markup, reading order and JSON-LD stay untouched. The 4th separator moves
   with Web, otherwise two dots collide between PC and Embedded and Web ends
   up with none. */
@media (max-width: 1024px) {
  .hero__platforms > .hero__chip[data-platform="web"],
  .hero__platforms > .hero__sep:nth-of-type(4) {
    order: 1;
  }
}

/* Bigger hero headline on mobile and tablet, as one continuous ramp from
   phone to tablet, capped at the 64px desktop size so nothing here can outgrow
   desktop. Floor and slope carry a further +15% for phones (36px -> 41.4px,
   10.6vw -> 12.2vw): every width up to ~525px scales by exactly that, while
   tablets from ~604px up were already sitting on the 64px cap and so are
   unaffected. */
@media (max-width: 1024px) {
  :root {
    --fs-hero: clamp(41.4px, 12.2vw, 64px);
  }
}

/* Phones stack the headline into more rows, so it ends higher up the hero
   (~51% vs ~54%). Move the vanishing point with it, otherwise the glow and the
   top of the plane sit behind the last row of type. */
@media (max-width: 768px) {
  .hero .hero-bg__scrim {
    --horizon: 52%;
  }
}


/* ═════════════════════════════════════════════════════════════
   APPS SECTION — black field with ASCII data rain
   A token flip, not a rewrite. `.apps-sec` shares roughly fifteen selectors
   with `.services-sec` and `.faq-sec`, and every one of them reads its colour
   from a --lt-* custom property. Redefining those six properties on this one
   section therefore re-themes all of them at once, and unpicking `.apps-sec`
   from each shared selector list — which would have been the obvious move — is
   avoided entirely. Only the few rules that hardcode a light value rather than
   reading a token need the explicit overrides below.
   ═════════════════════════════════════════════════════════════ */
.apps-sec {
  --lt-ink: #f5f5f7;
  --lt-muted: rgba(255, 255, 255, 0.68);
  --lt-faint: rgba(255, 255, 255, 0.6);
  /* The light field used #0b5ed7 for 4.5:1 on near-white. On black that reads
     almost navy, so this is the light-on-dark counterpart the conversion bands
     already use. */
  --lt-link: #6cb5ff;
  --lt-link-hover: #9ccdff;
  --lt-line: rgba(255, 255, 255, 0.1);
  background: #000;
  position: relative;
  overflow: hidden;
  border-top: 0;
}

.apps-sec .section-icon {
  color: var(--lt-link);
  background: rgba(108, 181, 255, 0.1);
  border-color: rgba(108, 181, 255, 0.22);
}

/* Glass, with the alpha chosen by contrast arithmetic rather than by eye.
   These tiles used to be opaque, and the ASCII mount relies on that: it does
   NOT add the tiles to its clear zone, precisely because glyphs behind an opaque
   card are hidden outright and can carry no contrast risk. Letting the rain show
   through reverses that, so the text now sits on whatever the field happens to
   be doing underneath it.

   0.62 is the worst-case-safe value. Composited against the brightest glyph the
   field can produce — #2997ff at full alpha, the rain's top tier — and taking no
   credit at all for the blur (which in reality averages that peak far down), the
   heading holds 9.13:1 and body copy 5.56:1. Both clear AA with margin, so the
   guarantee does not depend on where a streak happens to fall. Over plain black
   it is 18.04:1 and 9.16:1.

   The inset top highlight is what actually sells glass: a lit edge where the
   panel catches light, which a flat translucent fill alone never reads as. */
.apps-sec .tile {
  background: rgba(18, 18, 22, 0.62);
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  /* Data blue, same #2997ff as the ASCII field behind it, so the edge reads as
     part of the same system rather than as a stray accent. Carried at a high
     alpha on purpose: a 1px line against near-black needs it to register as
     blue at all — at 0.3 it composites to roughly rgb(12,45,77) and just looks
     like a slightly-off dark grey. */
  border: 1px solid rgba(41, 151, 255, 0.58);
  /* The lit top edge is tinted to match. It stays a highlight rather than
     becoming a glow — it is what makes the panel read as a material catching
     light instead of a flat translucent fill. */
  box-shadow:
    inset 0 1px 0 rgba(41, 151, 255, 0.22),
    0 8px 30px rgba(0, 0, 0, 0.4);
}

.apps-sec .tile:hover {
  background: rgba(24, 24, 29, 0.7);
  border-color: rgba(41, 151, 255, 0.95);
  /* Hover adds an outer ring rather than a bigger blur, so the tile gains
     definition without appearing to move. */
  box-shadow:
    inset 0 1px 0 rgba(41, 151, 255, 0.32),
    0 0 0 1px rgba(41, 151, 255, 0.22),
    0 14px 40px rgba(0, 0, 0, 0.5);
}

/* Without backdrop-filter there is no blur to soften the field, so the rain
   would read as sharp glyphs sliding under the copy. Contrast still holds at
   0.62 (the arithmetic above takes no blur credit), but it looks like a bug
   rather than a material, so these browsers get the opaque card instead. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .apps-sec .tile {
    background: #131316;
  }
  .apps-sec .tile:hover {
    background: #17171b;
  }
}

.apps-sec .app-platforms li {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.13);
  color: rgba(255, 255, 255, 0.66);
}

/* The light theme dialled this down because a heavy shadow reads as grime on
   white. Against black it has to come back or the icons look pasted on. */
.apps-sec .app-id__icon {
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.55);
}

.apps-sec .tile__media {
  background: #1c1c20;
}

/* Content above the canvas. */
.apps-sec > .section__head,
.apps-sec > .tile-grid {
  position: relative;
  z-index: 1;
}
