/* Landing / download page. Shared tokens and components are in style.css. */

/* Language accents from LanguageDetector.swift — the dark-canvas set, and the
   darker set the app uses for contrast on the light canvas. */
:root {
  --lang-html: #dc2626;
  --lang-css: #be185d;
  --lang-js: #7a5d00;
  --lang-ts: #2563eb;
  --lang-react: #0072a3;
  --lang-glsl: #0b63ce;
  --lang-metal: #9333ea;
  --lang-swift: #b45309;
  --lang-json: #047857;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --lang-html: #ef4444;
    --lang-css: #ec4899;
    --lang-js: #eab308;
    --lang-ts: #3b82f6;
    --lang-react: #61dafb;
    --lang-glsl: #1e90ff;
    --lang-metal: #a855f7;
    --lang-swift: #f97316;
    --lang-json: #10b981;
  }
}
:root[data-theme="dark"] {
  --lang-html: #ef4444;
  --lang-css: #ec4899;
  --lang-js: #eab308;
  --lang-ts: #3b82f6;
  --lang-react: #61dafb;
  --lang-glsl: #1e90ff;
  --lang-metal: #a855f7;
  --lang-swift: #f97316;
  --lang-json: #10b981;
}

/* ───────────── Hero ───────────── */

.hero { padding: 88px 0 0; }

.hero-copy { text-align: center; }
.hero-copy .eyebrow { margin: 0 0 18px; }
.hero-copy .display { margin: 0 auto; max-width: 13ch; }
.hero-copy .lede { max-width: 600px; margin: 22px auto 34px; }

/* Button pairs (download + support): equal-width columns, each as wide as
   the wider button, centred. */
.hero-actions,
.download-actions {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 12px;
  width: fit-content;
  margin-inline: auto;
}
.hero-meta {
  margin: 8px 0 0;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text-3);
}

.hero-stage {
  position: relative;
  margin-top: 72px;
  padding-bottom: 40px;
}

/* The app window, floating on its own shadow. Tilt is driven by site.js. */
.hero-window {
  position: relative;
  border-radius: 18px;
}
.tilt { will-change: transform; border-radius: inherit; }
/* The screenshot is a macOS window capture: transparent surround, its own
   rounded corners and shadow. Scale it so the window itself spans the
   column (it is 91.6% of the capture's width) and pull the transparent
   margin back in. */
.hero-window img {
  width: 109.17%;
  max-width: none;
  height: auto;
  margin: -3.11% -4.585% -3%;
}

/* Hero entrance: the window materializes on the slower page spring. */
.js .hero-window.reveal { transform: translate3d(0, 40px, 0) scale(0.96); }
.js .hero-window.reveal.is-in {
  transition:
    opacity 600ms var(--ease-out),
    filter 600ms var(--ease-out),
    transform var(--spring-page-d) var(--spring-page);
  transition-delay: 160ms;
}


/* ───────────── Languages ───────────── */

.langs { padding: 88px 0 24px; text-align: center; }
.langs-note { margin: 18px 0 0; font-size: 15px; }

/* ───────────── Feature rows ───────────── */

.feature {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 56px;
  align-items: center;
  padding-top: 120px;
}
.feature-flip .feature-copy { order: 2; }
.feature-copy .headline { margin-bottom: 18px; }
.feature-copy .lede { margin: 0 0 22px; }

.ticks {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
  color: var(--text-2);
  font-size: 16px;
}
.ticks li {
  position: relative;
  padding-left: 28px;
}
.ticks li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.32em;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
}
.ticks li::after {
  content: "";
  position: absolute;
  left: 7px;
  top: calc(0.32em + 4px);
  width: 4px;
  height: 7px;
  border-right: 1.8px solid var(--accent);
  border-bottom: 1.8px solid var(--accent);
  transform: rotate(45deg);
}

.media-frame {
  overflow: hidden;
  padding: 0;
  border-radius: var(--r-lg);
  background: var(--code-bg);
}
/* A clip that is itself a window: the frame takes the window's own corner
   radius (16px on the 1520px capture), so no corner of the frame shows past
   the window's. Container units keep it in proportion at any width. */
.feature-media { container-type: inline-size; }
.media-window { border-radius: calc(16 / 1520 * 100cqw); }

.media-frame video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ───────────── Quick copy / capture pair ───────────── */

.pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  padding-top: 120px;
}
.pair-card {
  display: flex;
  flex-direction: column;
  padding: 28px 28px 0;
  overflow: hidden;
  border-radius: var(--r-xl);
}
.pair-card h3 { font-size: 24px; letter-spacing: -0.02em; margin-bottom: 10px; }
.pair-card p { margin: 0 0 24px; font-size: 16px; }
/* The menu bar scene: the bare desktop (wallpaper and menu bar) with the
   panel as its own layer, cut from captures taken on the same screen, so it
   sits exactly where macOS drew it and its frosted glass matches what is
   behind it. Coordinates are fractions of the 1100px square crop:
   panel 684×846 at (210, 72); scissors centred at (550.5, 33).

   The panel springs open from the scissors when the card arrives, and the
   scissors toggle it, like the real status item. The scene fades out at the
   sides and bottom into the glass card. */
.desk {
  position: relative;
  /* Sized by the desktop image itself (below), never stretched by the
     card's flex layout: Safari can give an aspect-ratio-only flex item a
     different height, which then distorted a 100%×100% background. */
  flex: none;
  margin: auto -28px 0;
  overflow: hidden;
  -webkit-mask-image:
    linear-gradient(to right, transparent 0, #000 18%, #000 82%, transparent 100%),
    linear-gradient(to bottom, #000 70%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-image:
    linear-gradient(to right, transparent 0, #000 18%, #000 82%, transparent 100%),
    linear-gradient(to bottom, #000 70%, transparent 100%);
          mask-composite: intersect;
}
.desk-bg {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
}

/* The status item's pressed capsule, as macOS draws it while its menu is open. */
.desk-highlight {
  position: absolute;
  left: calc(550.5 / 1100 * 100%);
  top: calc(33 / 1100 * 100%);
  width: calc(64 / 1100 * 100%);
  height: calc(44 / 1100 * 100%);
  translate: -50% -50%;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.24);
  opacity: 0;
  transition: opacity 120ms ease-out;
}
.desk.is-open .desk-highlight { opacity: 1; }

.desk-scissors {
  position: absolute;
  left: calc(550.5 / 1100 * 100%);
  top: calc(33 / 1100 * 100%);
  width: calc(90 / 1100 * 100%);
  height: calc(66 / 1100 * 100%);
  translate: -50% -50%;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  cursor: pointer;
}
.desk-scissors:focus-visible { outline-offset: 0; }

.desk-panel {
  position: absolute;
  left: calc(210 / 1100 * 100%);
  top: calc(72 / 1100 * 100%);
  width: calc(684 / 1100 * 100%);
  /* Grows out of the status item above it: the scissors sit at the panel's
     horizontal centre, just over its top edge. */
  transform-origin: 50% -4%;
  filter: drop-shadow(0 14px 26px rgba(20, 0, 60, 0.35));
  /* Closing: quick and plain, like DSMotion.popoverOut. */
  opacity: 0;
  transform: translate3d(0, -1.5%, 0) scale(0.92);
  transition: opacity 130ms ease-out, transform 160ms ease-out;
  pointer-events: none;
}
.desk-panel img { width: 100%; height: auto; }
.desk.is-open .desk-panel {
  /* Opening: the popover spring (response 0.22, damping 1) — critically
     damped, so it lands without bounce. CSS transitions start from the
     current value, so a click mid-flight reverses smoothly. */
  opacity: 1;
  transform: none;
  pointer-events: auto;
  transition: opacity 140ms ease-out, transform var(--spring-pop-d) var(--spring-pop);
}

/* ───────────── More ───────────── */

.more { padding-top: 120px; }
.more-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.mini {
  --c: var(--accent);
  padding: 22px;
  transition: transform var(--spring-pop-d) var(--spring-pop), box-shadow 200ms var(--ease-out);
}
.mini:hover { transform: translateY(-3px); }
.mini-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 14px;
  border-radius: 12px;
  color: var(--c);
  background: color-mix(in srgb, var(--c) 13%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 35%, transparent);
}
.mini-icon svg { width: 21px; height: 21px; }
.mini h3 { margin-bottom: 6px; }
.mini p { margin: 0; color: var(--text-3); font-size: 15px; }

/* ───────────── Privacy ───────────── */

.privacy { padding-top: 120px; }
.privacy-card {
  text-align: center;
  padding: 56px 32px;
  border-radius: var(--r-xl);
}
.privacy-card .section-label { justify-content: center; }
.privacy-card .section-label::after { display: none; }
.privacy-card .lede { max-width: 560px; margin: 16px auto 26px; }
.privacy-chips { margin-bottom: 26px; }
.privacy-link { font-weight: 600; }

/* ───────────── Download ───────────── */

.download {
  padding-top: 130px;
  text-align: center;
}
.download-icon {
  width: 128px;
  height: 128px;
  margin: 0 auto 18px;
  filter: drop-shadow(0 18px 30px rgba(10, 132, 255, 0.28));
}
.download .lede { margin: 12px 0 28px; }

.steps {
  list-style: none;
  padding: 0;
  margin: 56px auto 0;
  max-width: 980px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  text-align: left;
}
.step {
  display: flex;
  gap: 14px;
  padding: 20px;
}
.step-n {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 14px;
  color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.step h3 { font-size: 16px; margin: 3px 0 4px; }
.step p { margin: 0; font-size: 14.5px; }

.download-legal { margin: 28px 0 0; font-size: 14px; }

/* ───────────── Responsive ───────────── */

@media (max-width: 900px) {
  .feature { grid-template-columns: 1fr; gap: 32px; padding-top: 88px; }
  .feature-flip .feature-copy { order: 0; }
  .more-grid { grid-template-columns: 1fr 1fr; }
  .steps { grid-template-columns: 1fr; max-width: 480px; }
}

@media (max-width: 640px) {
  .hero { padding-top: 56px; }
  .hero-stage { margin-top: 48px; }
  .pair { grid-template-columns: 1fr; padding-top: 88px; }
  .more-grid { grid-template-columns: 1fr; }
  .privacy-card { padding: 40px 22px; }
  .hero-actions, .download-actions { grid-auto-flow: row; width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .js .hero-window.reveal { transform: none; }
  .mini { transition: none; }
  .desk-panel, .desk.is-open .desk-panel { transform: none; transition: opacity 160ms ease; }
  .mini:hover { transform: none; }
}
