/* likwest.com — landing-page design system (apex hub + per-app landing pages).
   Light canvas with large flat organic shapes (the "scene": drifting bands,
   cropped rings, morphing blobs), scroll reveals. Legal/support pages keep
   using shared/style.css; this file is for the marketing pages only.
   Per-page accent: override --brand / --brand-2 in a page <style>. */

/* Self-hosted Inter (latin, variable 400–800) so the type looks identical and
   crisp on every browser/OS — the system stack renders SF Pro on Apple but
   Segoe UI on Windows. Absolute path so it also loads on the app subdomains. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/fonts/inter-latin.woff2") format("woff2");
}
/* Geist — the wordmark face: cool, technical, engineered (Vercel's type).
   Inter stays the body/UI text face. */
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/geist-latin.woff2") format("woff2");
}

:root {
  --bg: #f2f3f6;
  --bg-elev: #ffffff;
  --bg-card: #ffffff;
  --text: #14161f;
  --dim: #4e5464;
  --faint: #868da0;
  --line: rgba(18, 24, 48, 0.13);
  --line-soft: rgba(18, 24, 48, 0.075);

  --brand: #3564f2;          /* deep blue — likwest default (light bg) */
  --brand-2: #6f95ff;        /* lighter blue */
  --gold: #c8860a;           /* dark gold — readable on the light canvas */

  --radius: 20px;
  --radius-lg: 28px;
  --wrap: 1120px;
  --nav-h: 64px;

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

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 16px);
  color-scheme: light;
}

/* ------------------------------------------------------------- dark mode
   Light is the default. /shared/theme.js stamps data-theme="dark" on <html>
   before first paint (stored choice, else system preference); the navbar
   moon toggle (site.js) flips + persists it. Accents go back to their
   brighter values — the darkened light-canvas tints would drown on dark.
   Per-app accent pages override their dark --brand in their own <style>. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0c0d12;
  --bg-elev: #14161e;
  --bg-card: rgba(255, 255, 255, 0.035);
  --text: #f2f3f8;
  --dim: #a4a9ba;
  --faint: #707588;
  --line: rgba(255, 255, 255, 0.11);
  --line-soft: rgba(255, 255, 255, 0.065);
  --brand: #6f95ff;
  --brand-2: #9db8ff;
  --gold: #e8b23a;
}
[data-theme="dark"] nav.top {
  background: color-mix(in srgb, #0c0d12 70%, transparent);
}
[data-theme="dark"] body::after { opacity: 0.05; mix-blend-mode: normal; }
[data-theme="dark"] .btn.ghost { background: rgba(255, 255, 255, 0.04); }
[data-theme="dark"] a.store-badge { border-color: rgba(255, 255, 255, 0.3); }
[data-theme="dark"] a.store-badge:hover {
  border-color: rgba(255, 255, 255, 0.55);
  box-shadow: 0 12px 36px -10px rgba(0, 0, 0, 0.9);
}
[data-theme="dark"] .shot-nav { background: rgba(20, 22, 32, 0.6); }
[data-theme="dark"] .shot-nav:hover { background: rgba(30, 33, 46, 0.75); }
[data-theme="dark"] .float-chip {
  background: rgba(20, 22, 32, 0.6);
  box-shadow: 0 14px 34px -12px rgba(0, 0, 0, 0.7);
}
[data-theme="dark"] .card,
[data-theme="dark"] .app-card { background: var(--bg-card); box-shadow: none; }
[data-theme="dark"] .card:hover { background: rgba(255, 255, 255, 0.055); }
[data-theme="dark"] .app-card .platforms span { background: rgba(255, 255, 255, 0.03); }
[data-theme="dark"] .chip { background: rgba(255, 255, 255, 0.04); }
[data-theme="dark"] .prose .contact { background: rgba(255, 255, 255, 0.04); }
[data-theme="dark"] .phone {
  box-shadow:
    0 40px 90px -30px rgba(0, 0, 0, 0.85),
    0 0 0 1px rgba(255, 255, 255, 0.08),
    inset 0 0 0 1px rgba(0, 0, 0, 0.9);
}
/* scene: same shapes, night tones — a touch lighter than the canvas */
[data-theme="dark"] .scene .blob { background: linear-gradient(150deg, #181b26, #10121a); }
[data-theme="dark"] .scene .b2 { background: linear-gradient(200deg, #161923, #10121a); }
[data-theme="dark"] .scene .b3 { background: linear-gradient(120deg, #151823, #111319); }
[data-theme="dark"] .scene .ring { border-color: #181b27; }
[data-theme="dark"] .scene .flow stop:first-child { stop-color: #161927; }
[data-theme="dark"] .scene .flow stop:last-child { stop-color: #10121a; }
[data-theme="dark"] .gridlines {
  background-image: radial-gradient(rgba(160, 180, 255, 0.11) 1.1px, transparent 1.6px);
}
/* liquid glass, night version: faint white fill, dimmer rim */
[data-theme="dark"] .feature .copy::before {
  background:
    radial-gradient(120% 90% at 16% 0%, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0) 44%) padding-box,
    linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03) 55%, rgba(255, 255, 255, 0.06)) padding-box,
    linear-gradient(135deg, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.06) 45%, rgba(255, 255, 255, 0.28)) border-box;
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.25),
    0 22px 55px -28px rgba(0, 0, 0, 0.7);
}
[data-theme="dark"] .feature:has(.row-link):hover .copy::before {
  filter: brightness(1.2);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.35),
    0 30px 70px -30px rgba(0, 0, 0, 0.8);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.65 "Inter", -apple-system, BlinkMacSystemFont, "SF Pro Text",
        "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

/* Geist is used ONLY for the "lìkwest" company wordmark (hero + nav) and its
   tagline. Everything else — including app-page headlines like "Duet with
   yourself" — stays on Inter. */
.brand-name, .brand-word, .brand-sub {
  font-family: "Geist", "Inter", sans-serif;
}
/* One-accent wordmark: all white, only the ì carries the brand blue.
   Used in the hero lockup and the nav. */
.brand-name, .brand-word { color: var(--text); font-weight: 600; }
.brand-name .acc, .brand-word .acc { color: var(--brand); }

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 24px;
}

::selection { background: color-mix(in srgb, var(--brand) 40%, transparent); }

/* ----------------------------------------------------------------- scene
   Large FLAT organic shapes with defined edges — sweeping SVG bands,
   cropped rings, slowly morphing blobs — in blue-grey tones across the
   WHOLE page. Each page injects <div class="scene"> right after <body>:

     <div class="scene" aria-hidden="true">
       <span class="blob b1"></span>
       <svg class="flow f1" …>   (band; inline so gradients/paths stay per-page)
       <span class="ring r1"></span>
       …
     </div>

   Motion is glacial (30–60s loops) and CSS-only. */

body { position: relative; }

.scene {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  animation: scene-fade 1.2s ease-out both;
}
.scene .blob,
.scene .ring,
.scene .flow { position: absolute; }

/* morphing blobs */
.scene .blob {
  background: linear-gradient(150deg, #f7f8fb, #e6e9f1);
  animation: blob-morph 30s ease-in-out infinite alternate,
             scene-drift 64s ease-in-out infinite alternate;
}
.scene .b1 {
  width: 58vw; height: 50vw;
  right: -14vw; top: -10vw;
  border-radius: 58% 42% 55% 45% / 52% 48% 60% 40%;
}
.scene .b2 {
  width: 46vw; height: 40vw;
  right: -14vw; top: 64%;
  border-radius: 47% 53% 58% 42% / 55% 46% 54% 45%;
  background: linear-gradient(200deg, #f4f6fa, #e5e8f1);
  animation-delay: -14s, -20s;
}
.scene .b3 {
  width: 44vw; height: 36vw;
  left: -16vw; top: 80%;
  border-radius: 55% 45% 44% 56% / 48% 58% 42% 52%;
  background: linear-gradient(120deg, #e9ecf3, #f2f4f8);
  animation-delay: -7s, -32s;
}

/* flat rings, cropped by the page edge */
.scene .ring {
  border-radius: 50%;
  border-style: solid;
  border-color: #e4e7ef;
  animation: ring-breathe 28s ease-in-out infinite alternate;
}
.scene .r1 {
  width: 46vw; height: 46vw;
  border-width: 7.5vw;
  left: -18vw; top: 24%;
}

/* sweeping bands (inline SVGs, full width) */
.scene .flow { left: 0; width: 100%; height: auto; }
.scene .f1 {
  top: 3vw;
  animation: flow-sway 46s ease-in-out infinite alternate;
}
.scene .f2 {
  top: 56%;
  animation: flow-sway-flip 54s ease-in-out infinite alternate;
}

@keyframes blob-morph {
  0%   { border-radius: 58% 42% 55% 45% / 52% 48% 60% 40%; }
  50%  { border-radius: 45% 55% 48% 52% / 60% 44% 52% 48%; }
  100% { border-radius: 52% 48% 60% 40% / 46% 58% 44% 56%; }
}
@keyframes ring-breathe {
  from { transform: scale(1) rotate(0deg); }
  to   { transform: scale(1.05) rotate(8deg); }
}
@keyframes scene-drift {
  from { transform: translate3d(0, 0, 0) scale(1.03); }
  to   { transform: translate3d(-3vw, 4vw, 0) scale(0.97); }
}
@keyframes flow-sway {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-2.5vw, 1vw, 0); }
}
@keyframes flow-sway-flip {
  from { transform: scaleX(-1) translate3d(0, 0, 0); }
  to   { transform: scaleX(-1) translate3d(-2.5vw, 1vw, 0); }
}
@keyframes scene-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* faint blueprint dots behind the hero, fading downwards */
.gridlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image: radial-gradient(rgba(35, 55, 120, 0.10) 1.1px, transparent 1.6px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 0%, #000 30%, transparent 75%);
          mask-image: radial-gradient(120% 90% at 50% 0%, #000 30%, transparent 75%);
}

/* film-grain so gradients don't band — a whisper of it on light */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 60;
  opacity: 0.025;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------------ nav */

nav.top {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--nav-h);
  backdrop-filter: blur(18px) saturate(1.6);
  -webkit-backdrop-filter: blur(18px) saturate(1.6);
  background: color-mix(in srgb, #ffffff 72%, transparent);
  border-bottom: 1px solid var(--line-soft);
}
nav.top .wrap {
  position: relative;      /* anchors the centred .nav-context */
  height: 100%;
  display: flex;
  align-items: center;
  gap: 28px;
}

/* centred context label — JS fills it from the current section's
   data-nav-title (apex: "My Apps") and toggles .on while one is active */
.nav-context {
  position: absolute;
  left: 50%;
  transform: translate(-50%, 4px);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--dim);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.nav-context.on { opacity: 1; transform: translate(-50%, 0); }
@media (max-width: 720px) { .nav-context { display: none; } }

/* scrollspy: the nav link of the section being read takes the page accent */
nav.top .links a.is-current { color: var(--brand); }

/* dark-mode toggle (JS-built): moon in light mode, sun in dark mode */
button.theme-toggle {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--dim);
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease),
              transform 0.2s var(--ease);
}
button.theme-toggle:hover {
  color: var(--text);
  border-color: color-mix(in srgb, var(--brand) 45%, var(--line));
  transform: translateY(-1px);
}
button.theme-toggle svg { display: block; }
button.theme-toggle .sun { display: none; }
[data-theme="dark"] button.theme-toggle .moon { display: none; }
[data-theme="dark"] button.theme-toggle .sun { display: block; }

/* app pages: the sail mark ahead of the app logo — breadcrumb back to the
   likwest apex (absolute URL: app pages live on their own subdomains).
   Styled as a black rounded tile so it matches the 30px app icon next to
   it (and the apex's ~30px bare sail — no size jump between pages). */
a.parent-mark {
  position: relative;
  display: block;
  flex: none;
  margin-right: -4px;      /* tighten the .wrap gap to breadcrumb spacing */
  transition: transform 0.2s var(--ease), filter 0.2s var(--ease);
}
a.parent-mark:hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
}
a.parent-mark::after {
  content: "/";
  position: absolute;
  right: -16px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--faint);
  font-size: 15px;
}
.logo {
  display: flex;
  align-items: center;
  gap: 11px;
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.02em;
}
.logo img, .logo svg { width: 30px; height: 30px; border-radius: 8px; }
/* the tile-less lìkwest mark: taller than the glyphs so the slim boat has
   the same visual presence as the 30px square app icons next to their names */
.logo img.likwest-mark { height: 1.4em; width: auto; border-radius: 0; }
/* THE likwest nav tile — one shared class for every navbar appearance of the
   sail (apex logo lockup + app pages' breadcrumb). 30px liquid glass: white
   frosted fill, bright rim, soft shadow; the white mainsail gets a hair of
   drop-shadow so it reads on the light glass. Markup:
   <span class="likwest-tile"><img src="/assets/likwest-mark.svg" …></span> */
.likwest-tile {
  width: 30px;
  height: 30px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.65), rgba(255, 255, 255, 0.3));
  border: 1px solid rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 4px 12px -6px rgba(24, 32, 64, 0.3);
}
.likwest-tile img {
  width: auto;
  height: 22px;
  border-radius: 0;
  display: block;
  filter: drop-shadow(0 1px 1.5px rgba(24, 32, 64, 0.3));
}
[data-theme="dark"] .likwest-tile {
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.06));
  border-color: rgba(255, 255, 255, 0.3);
}
.logo .app-ico {
  border-radius: 8px;
  box-shadow: 0 4px 12px -6px rgba(24, 32, 64, 0.3);   /* same lift as .likwest-tile */
}

nav.top .links {
  display: flex;
  gap: 26px;
  margin-left: auto;
  align-items: center;
  font-size: 14.5px;
  color: var(--dim);
}
nav.top .links a:hover { color: var(--text); }
nav.top .links a.cta {
  color: #fff;
  background: var(--brand);
  padding: 7px 16px;
  border-radius: 999px;
  font-weight: 600;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
nav.top .links a.cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 24px -6px color-mix(in srgb, var(--brand) 55%, transparent);
}
/* Phone navbar: logo + dark-mode toggle + language switch, nothing else.
   The section anchors go, and so does the Download CTA — nothing is lost, the
   App Store badge sits in the hero directly below and again at the foot of
   every page. The language switch survives via its own override further down;
   on a phone it is the only route to the other language.

   Dropping the CTA alone does NOT stop the app wordmark from wrapping — that
   was measured, not assumed. At 375px the budget is: 327px content (375 − 2×24
   padding) − 30px parent mark − ~86px toggle+switch − 2×28px .wrap gap = 139px
   for a logo that wants 169px (30 icon + 11 gap + 128 label). So the gaps come
   down here too, and nowrap makes the one-line guarantee explicit rather than a
   coincidence of arithmetic.

   The "/" between the lìkwest mark and the app icon has to go with them: it is
   an absolutely positioned ::after at `right: -16px`, i.e. it lives *inside*
   the 28px .wrap gap. Shrink that gap and the slash slides under the app icon
   instead of disappearing politely. Two adjacent icons 16px apart read fine
   without it, and the mark keeps its aria-label, so nothing is lost but ink. */
@media (max-width: 640px) {
  nav.top .links a { display: none; }
  nav.top .wrap { gap: 16px; }
  nav.top .links { gap: 10px; }
  nav.top .logo { white-space: nowrap; }
  nav.top .parent-mark::after { content: none; }
}

/* ----------------------------------------------------------------- type */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
}
.eyebrow::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
}

h1.display {
  margin: 18px 0 0;
  font-size: clamp(42px, 7.4vw, 88px);
  line-height: 1.02;
  letter-spacing: -0.045em;
  font-weight: 800;
}
/* a smaller second line under a big first line — kept to one line */
h1.display .line-2 {
  display: inline-block;
  margin-top: 0.12em;
  font-size: clamp(28px, 4.7vw, 56px);
  letter-spacing: -0.03em;
  white-space: nowrap;
}

/* apex brand hero: the wordmark alone, type-first — the sail mark stays in
   the nav. All white in Geist, one blue accent on the ì; no frame, no box.
   The soft hero-glow aurora behind it is the only stage light. */
.brand-hero {
  width: fit-content;
  margin-bottom: 34px;
}
.brand-name {
  font-size: clamp(54px, 6.2vw, 82px);
  letter-spacing: -0.03em;
  line-height: 0.98;
  white-space: nowrap;
}
.brand-sub {
  margin-top: -0.08em;
  font-size: clamp(15px, 1.78vw, 21px);
  color: var(--dim);
  white-space: nowrap;
  /* tracked out so the tagline spans the same width as "lìkwest" above */
  letter-spacing: 0.235em;
  text-indent: 0.235em;   /* balance the trailing letter-spacing → centred track */
}
@media (max-width: 880px) {
  /* mobile: centre the whole logo lockup (lede stays left) */
  .brand-hero { margin-left: auto; margin-right: auto; }
}
.grad {
  background: linear-gradient(100deg, var(--brand) 0%, var(--brand-2) 55%, var(--brand) 110%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}
.grad-gold {
  background: linear-gradient(100deg, #e0a52f, var(--gold) 45%, #9a6607);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}

.lede {
  margin: 22px 0 0;
  max-width: 560px;
  font-size: clamp(17px, 2vw, 20px);
  line-height: 1.6;
  color: var(--dim);
}
.lede strong { color: var(--text); font-weight: 600; }

h2.title {
  margin: 14px 0 0;
  font-size: clamp(30px, 4.4vw, 48px);
  line-height: 1.08;
  letter-spacing: -0.035em;
  font-weight: 750;
}
.sub {
  margin: 16px 0 0;
  color: var(--dim);
  font-size: 17px;
  max-width: 520px;
}
h2.title .pro {
  display: inline-block;
  vertical-align: middle;
  margin-left: 14px;
  padding: 4px 12px;
  border: 1px solid color-mix(in srgb, var(--gold) 55%, transparent);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold);
  transform: translateY(-4px);
}

/* "Beta" badge — for apps not yet on the App Store (e.g. IPTV Pano). Tinted in
   the app's own accent (the card's --card-accent, else the page --brand) so it
   reads as part of the brand. Sits inline next to a title or in an eyebrow. */
.beta {
  --beta-c: var(--card-accent, var(--brand));
  display: inline-block;
  vertical-align: middle;
  margin-left: 10px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--beta-c);
  background: color-mix(in srgb, var(--beta-c) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--beta-c) 50%, transparent);
  transform: translateY(-1px);
}

.sub strong { color: var(--text); font-weight: 600; }

/* icon chip ahead of a feature/mode title (app pages) — a rounded tile
   tinted in the page brand, holding a small stroke icon */
h2.title.with-ico {
  display: flex;
  align-items: center;
  gap: 14px;
}
h2.title .t-ico {
  flex: none;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  /* deliberately neutral, not the accent: a coloured tile per feature title
     reads as a row of badges competing with the headline. Grey keeps the
     structure and lets the accent stay on links, buttons and the .grad text. */
  color: var(--dim);
  background: color-mix(in srgb, var(--text) 5%, transparent);
  border: 1px solid var(--line);
}
h2.title .t-ico svg { display: block; width: 22px; height: 22px; }
@media (max-width: 880px) {
  h2.title .t-ico { width: 36px; height: 36px; border-radius: 10px; }
  h2.title .t-ico svg { width: 19px; height: 19px; }
}

/* -------------------------------------------------------------- buttons */

.actions {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 34px;
  flex-wrap: wrap;
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 13px 24px;
  border-radius: 999px;
  font-size: 15.5px;
  font-weight: 600;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease),
              background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.btn.primary {
  background: var(--brand);
  color: #fff;
}
.btn.primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 32px -8px color-mix(in srgb, var(--brand) 55%, transparent);
}
.btn.ghost {
  border: 1px solid var(--line);
  color: var(--text);
  background: #fff;
}
.btn.ghost:hover {
  border-color: color-mix(in srgb, var(--brand) 60%, var(--line));
  transform: translateY(-2px);
}
.aside-note { font-size: 13.5px; color: var(--faint); }

/* App Store badge (official look, HTML+CSS) */
a.store-badge {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 11px 22px 11px 18px;
  background: #000;
  border: 1px solid rgba(0, 0, 0, 0.85);
  border-radius: 14px;
  line-height: 1.15;
  transition: transform 0.2s var(--ease), border-color 0.2s var(--ease),
              box-shadow 0.2s var(--ease);
}
a.store-badge:hover {
  transform: translateY(-2px);
  border-color: #000;
  box-shadow: 0 12px 30px -12px rgba(10, 14, 30, 0.45);
}
a.store-badge svg { width: 26px; height: 30px; flex: none; }
a.store-badge .small { display: block; font-size: 11px; color: #d8d8de; }
a.store-badge .big  { display: block; font-size: 19px; font-weight: 600; letter-spacing: -0.01em; color: #fff; }

/* ----------------------------------------------------------------- hero */

header.hero {
  position: relative;
  overflow: hidden;
  padding: clamp(44px, 6vh, 76px) 0 clamp(32px, 4.5vh, 56px);
}
header.hero .wrap {
  position: relative;
  z-index: 1;
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(36px, 5vw, 72px);
  align-items: start;            /* top-align so the tall phone doesn't push the copy down */
}
/* nudge the copy column down a touch so it isn't glued to the nav */
.hero-grid > div:first-child { padding-top: clamp(12px, 5vh, 56px); }
@media (max-width: 880px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-grid > div:first-child { padding-top: 0; }
  /* On mobile the hero phone sits BELOW the copy, so there's nothing to align
     to — let the brand lockup start high, close under the (sticky) nav, and
     trim the bottom so the first section follows without a big void. */
  header.hero { padding-top: clamp(10px, 2vh, 24px); padding-bottom: clamp(16px, 3vh, 36px); }
  /* Musaic: drop the hero phone on mobile — the "Mosaic Layers" section right
     below shows the same shot, so it's just extra scroll before the content.
     Videcho opts out with .keep-mobile: its hero video is the only visual, so
     it must stay on phones. */
  .hero-visual:not(.keep-mobile) { display: none; }
  .hero-visual.keep-mobile { margin-top: 6px; }
  .hero-visual.keep-mobile .phone { width: min(280px, 72vw); }
  /* Musaic: keep the note beside the App Store badge, not on its own line. */
  .actions-inline { flex-wrap: nowrap; align-items: center; gap: 14px; }
  .actions-inline .store-badge { flex: 0 0 auto; }   /* keep badge at natural size, don't squash it */
  .actions-inline .aside-note { flex: 1 1 auto; min-width: 0; margin: 0; font-size: 12px; line-height: 1.35; }
  /* Keep the apex's two hero buttons side by side (equal halves) instead of
     stacking — saves the wasted vertical space. Scoped so app-page heroes
     (store badge + note) keep wrapping. */
  .actions-duo { flex-wrap: nowrap; gap: 12px; }
  .actions-duo .btn {
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
    padding: 13px 12px;
    font-size: 14px;
    white-space: nowrap;
  }
  .actions-duo .btn .btn-ico { width: 18px; height: 18px; }
}

/* ---------------------------------------------------------- phone frame */

.phone {
  position: relative;
  width: min(320px, 78vw);
  margin: 0 auto;
  border-radius: 54px;
  padding: 12px;
  background: linear-gradient(160deg, #3a3a46, #17171d 40%, #101016);
  box-shadow:
    0 34px 80px -30px rgba(24, 32, 64, 0.45),
    0 0 0 1px rgba(255, 255, 255, 0.4),
    inset 0 0 0 1px rgba(0, 0, 0, 0.85);
}
.phone::before {
  /* Dynamic-Island pill */
  content: "";
  position: absolute;
  top: 24px; left: 50%;
  width: 88px; height: 26px;
  transform: translateX(-50%);
  background: #000;
  border-radius: 999px;
  z-index: 2;
}
.phone::after {
  /* accent glow behind the device */
  content: "";
  position: absolute;
  inset: -12%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(closest-side,
      color-mix(in srgb, var(--brand) 20%, transparent), transparent 72%);
  filter: blur(30px);
}
.phone img,
.phone video {
  display: block;
  border-radius: 42px;
  width: 100%;
  height: auto;   /* the width/height attrs otherwise stretch the media */
}
.phone video { object-fit: cover; }

/* crossfading screenshot slideshow inside a phone frame */
.phone .shots {
  position: relative;
  width: 100%;
  aspect-ratio: 840 / 1827;
  border-radius: 42px;
  overflow: hidden;
}
.phone .shots .shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 42px;
  opacity: 0;
  transition: opacity 0.9s var(--ease);
}
.phone .shots .shot.is-on { opacity: 1; }
/* no-JS: show only the first shot */
html:not(.js) .phone .shots .shot:not(.is-on) { display: none; }
@media (prefers-reduced-motion: reduce) {
  .phone .shots .shot { transition: none; }
}

/* app icon inside a button (e.g. the hero "Musaic Studio" ghost button) */
.btn .btn-ico {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  margin-right: -1px;
}

/* slideshow prev/next controls under the hero phone (JS-only) */
.shot-controls {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin-top: 24px;
}
html:not(.js) .shot-controls { display: none; }
.shot-nav {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--text);
  background: rgba(255, 255, 255, 0.78);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  cursor: pointer;
  transition: transform 0.2s var(--ease), border-color 0.2s var(--ease),
              background 0.2s var(--ease);
}
.shot-nav:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--brand) 55%, var(--line));
  background: #fff;
}
.shot-nav:active { transform: translateY(0); }
.shot-nav svg { display: block; }

.shot-dots {
  display: flex;
  align-items: center;
  gap: 9px;
}
.shot-dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--faint);
  opacity: 0.55;
  cursor: pointer;
  transition: width 0.28s var(--ease), background 0.28s var(--ease),
              opacity 0.28s var(--ease);
}
.shot-dot:hover { opacity: 0.85; }
.shot-dot.is-on {
  width: 22px;
  background: var(--brand);
  opacity: 1;
}
.phone.tilt { transform: rotate(2.4deg); }
.phone.tilt-l { transform: rotate(-2.4deg); }

/* ------------------------------------------------------------- tv frame */
/* 16:9 sibling of .phone, for apps whose screenshots are TV-shaped.
   Same slideshow markup (.shots / .shot / .shot-controls) - site.js finds
   the controls via the .visual / .hero-media wrapper, so no JS changes. */

.tv {
  position: relative;
  width: min(620px, 100%);
  margin: 0 auto;
  border-radius: 20px;
  padding: 10px;
  background: linear-gradient(160deg, #3a3a46, #17171d 40%, #101016);
  box-shadow:
    0 34px 80px -30px rgba(24, 32, 64, 0.45),
    0 0 0 1px rgba(255, 255, 255, 0.4),
    inset 0 0 0 1px rgba(0, 0, 0, 0.85);
}
.tv::before {
  /* stand */
  content: "";
  position: absolute;
  left: 50%; bottom: -9px;
  width: 24%; height: 9px;
  transform: translateX(-50%);
  border-radius: 0 0 7px 7px;
  background: linear-gradient(180deg, #23232b, #14141a);
}
.tv::after {
  /* accent glow behind the device */
  content: "";
  position: absolute;
  inset: -14%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(closest-side,
      color-mix(in srgb, var(--brand) 20%, transparent), transparent 72%);
  filter: blur(30px);
}
.tv img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 11px;
}
.tv .shots {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 11px;
  overflow: hidden;
}
.tv .shots .shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 11px;
  opacity: 0;
  transition: opacity 0.9s var(--ease);
}
.tv .shots .shot.is-on { opacity: 1; }
html:not(.js) .tv .shots .shot:not(.is-on) { display: none; }
@media (prefers-reduced-motion: reduce) {
  .tv .shots .shot { transition: none; }
}
.tv.tilt { transform: rotate(1.4deg); }
.tv.tilt-l { transform: rotate(-1.4deg); }

/* a TV is wider than a phone, so a hero-sized one takes more of the column.
   Deliberately not the full width: at 940px the hero screenshot dominated
   everything above it. */
.tv-wide { width: min(705px, 100%); }

/* ------------------------------------------- crossfade between two devices */
/* Same feature shown on a TV and on a phone. The slides here are the FRAMES,
   not the images - a 16:9 shot and a 9:19.5 shot can't share one box.
   Both frames are taken out of flow and stacked, and site.js sets the
   container height to whichever is showing. Sizing the box to the TALLEST
   frame instead would park the switch a phone-height below a TV shot; here the
   box (and the switch under it) follows the active device. */
.device-shots {
  position: relative;
  transition: height 0.45s var(--ease);
}
.device-shots > .shot {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity 0.55s var(--ease);
  pointer-events: none;
}
.device-shots > .shot.is-on { opacity: 1; }
/* no JS = no height sync and nothing to switch: show the first frame in flow */
html:not(.js) .device-shots > .shot { position: static; transform: none; }
html:not(.js) .device-shots > .shot:not(.is-on) { display: none; }
@media (prefers-reduced-motion: reduce) {
  .device-shots,
  .device-shots > .shot { transition: none; }
}
/* inside a feature column the phone stays a bit narrower, so the two frames
   read as roughly the same object rather than the phone dwarfing the TV */
.device-shots > .phone { width: min(268px, 68vw); }
/* pin the ratios so a frame has its final height before the (lazy) image
   loads - otherwise the first height measurement can land on the bezel only */
.device-shots > .tv img { aspect-ratio: 16 / 9; }
.device-shots > .phone img { aspect-ratio: 840 / 1826; }

/* the TV / phone switch under a .device-shots crossfade (JS-only, like
   .shot-controls - without JS there is nothing to switch between) */
.device-switch {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 20px;
  padding: 5px;
  width: fit-content;
  margin-inline: auto;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg-elev) 70%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
html:not(.js) .device-switch { display: none; }
.dev-btn {
  width: 40px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--faint);
  cursor: pointer;
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
.dev-btn:hover { color: var(--dim); }
.dev-btn.is-on {
  color: #fff;
  background: var(--brand);
}
.dev-btn svg { display: block; }

/* floating glass chips around the hero phone */
.float-chip {
  position: absolute;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 15px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  background: rgba(255, 255, 255, 0.75);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 14px 34px -14px rgba(20, 30, 60, 0.25);
  white-space: nowrap;
}
.float-chip b { font-weight: 700; color: var(--gold); }
@media (max-width: 880px) { .float-chip { display: none; } }

/* ------------------------------------------------------------- sections */

section.block {
  position: relative;
  padding: clamp(52px, 7.5vh, 92px) 0;
}
section.block.hairline { border-top: 1px solid var(--line-soft); }

.section-head { max-width: 680px; }
.section-head.center { margin: 0 auto; text-align: center; }
.section-head.center .sub { margin-left: auto; margin-right: auto; }

/* feature rows: copy ↔ phone, alternating */
.feature {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: center;
  padding: clamp(34px, 5.5vh, 68px) 0;
}
.feature .visual { order: 2; }
.feature.flip .visual { order: -1; }  /* beat the copy's implicit order:0 */
@media (max-width: 880px) {
  /* Tighter section rhythm on mobile — the desktop padding leaves a huge gap,
     most visible on pages whose hero phone is hidden (Musaic). Placed after the
     base section.block rule so it actually wins (media queries add no specificity). */
  section.block { padding: clamp(24px, 3.5vh, 40px) 0; }
  .feature { grid-template-columns: 1fr; padding: 20px 0; gap: 18px; }
  /* Screenshot slots directly under the title, above the feature copy.
     display:contents promotes the copy's children into the feature grid so the
     visual (a sibling of .copy) can be ordered between the title and the rest. */
  .feature .copy { display: contents; }
  .feature .copy > h2.title { order: 0; margin-top: 0; }
  .feature .visual, .feature.flip .visual { order: 1; }
  .feature .copy > :not(h2.title) { order: 2; }
  /* gap now owns the vertical rhythm — drop the stacked top margins */
  .feature .copy > .sub,
  .feature .copy > .ticks,
  .feature .copy > .chips { margin-top: 0; }
  /* a touch smaller than the desktop phone, still centered */
  .feature .visual .phone { width: min(238px, 62vw); }
}
.feature .copy .eyebrow { margin-bottom: 2px; }

/* Feature rows sit on a permanent liquid-glass panel behind the copy column —
   mostly-clear glass with a refractive rim over the scene shapes. On rows that
   are one click target (apex: they carry a stretched .row-link) hovering lifts
   the panel. Desktop only — on mobile .copy is display:contents. */
@media (min-width: 881px) {
  .feature .copy { position: relative; }
  .feature .copy::before {
    content: "";
    position: absolute;
    inset: -42px -46px;
    z-index: -1;
    border-radius: 34px;
    /* liquid glass: a mostly-clear fill (the scene shimmers through the
       saturated blur), a specular highlight top-left, and a refractive rim —
       a gradient painted into the border box so the edge catches light
       unevenly instead of being one flat hairline */
    border: 1.5px solid transparent;
    background:
      radial-gradient(120% 90% at 16% 0%, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0) 44%) padding-box,
      linear-gradient(135deg, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.14) 55%, rgba(255, 255, 255, 0.32)) padding-box,
      linear-gradient(135deg, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.18) 45%, rgba(255, 255, 255, 0.85)) border-box;
    backdrop-filter: blur(14px) saturate(1.8);
    -webkit-backdrop-filter: blur(14px) saturate(1.8);
    box-shadow:
      inset 0 1px 1px rgba(255, 255, 255, 0.9),
      0 22px 55px -28px rgba(24, 32, 64, 0.3);
    transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease),
                filter 0.3s var(--ease);
    pointer-events: none;
  }
  .feature:has(.row-link):hover .copy::before {
    transform: translateY(-3px);
    filter: brightness(1.045);
    box-shadow:
      inset 0 1px 1px #fff,
      0 30px 70px -30px rgba(24, 32, 64, 0.4);
  }
}

.feature ul.ticks {
  list-style: none;
  padding: 0;
  margin: 22px 0 0;
  display: grid;
  gap: 12px;
  color: var(--dim);
  font-size: 15.5px;
}
.feature ul.ticks li {
  position: relative;
  padding-left: 21px;
}
.feature ul.ticks li::before {
  content: "";
  position: absolute;
  left: 1px;
  top: 0.5em;
  width: 7px; height: 7px;
  border-radius: 2px;
  transform: rotate(45deg);
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
}
.feature ul.ticks b { color: var(--text); font-weight: 600; }

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin-top: 22px;
}
.chip {
  padding: 7px 13px;
  font-size: 13px;
  font-weight: 500;
  color: var(--dim);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-card);
}

/* ---------------------------------------------------------------- cards */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  margin-top: 44px;
}
.card {
  position: relative;
  padding: 26px 26px 28px;
  border-radius: var(--radius);
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: transform 0.25s var(--ease), border-color 0.25s var(--ease),
              background 0.25s var(--ease);
}
.card:hover {
  transform: translateY(-4px);
  border-color: var(--line);
  background: #fff;
}
.card .num {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--brand);
}
.card h3 { margin: 10px 0 8px; font-size: 19px; letter-spacing: -0.015em; }
.card p { margin: 0; color: var(--dim); font-size: 15px; }

/* apex: app showcase cards — the whole card is clickable via a stretched
   .more link; interactive children (store badge) sit above the overlay. */
.app-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 30px;
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: transform 0.25s var(--ease), border-color 0.25s var(--ease),
              box-shadow 0.25s var(--ease);
}
.app-card:hover {
  transform: translateY(-5px);
  border-color: color-mix(in srgb, var(--card-accent, var(--brand)) 45%, var(--line));
  box-shadow: 0 30px 80px -30px color-mix(in srgb, var(--card-accent, var(--brand)) 30%, transparent);
}
.app-card .head {
  display: flex;
  align-items: center;
  gap: 16px;
}
.app-card .head img {
  width: 62px; height: 62px;
  border-radius: 15px;
  border: 1px solid var(--line);
}
.app-card .head h3 {
  margin: 0;
  font-size: 22px;
  letter-spacing: -0.02em;
}
.app-card .head .kind {
  margin-top: 3px;
  font-size: 13px;
  color: var(--card-accent, var(--brand));
  font-weight: 600;
}
.app-card p.blurb {
  margin: 16px 0 0;
  color: var(--dim);
  font-size: 15.5px;
  flex-grow: 1;
}
.app-card .platforms {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 16px;
}
.app-card .platforms span {
  font-size: 12px;
  font-weight: 600;
  color: var(--dim);
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-soft);
  background: rgba(18, 24, 48, 0.035);
}
.app-card .foot {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 22px;
  flex-wrap: wrap;
}
.app-card .foot .more {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--card-accent, var(--brand));
}
.app-card .foot .more::after {
  /* stretch the link over the whole card */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-lg);
}
.app-card:has(.more:hover) {
  transform: translateY(-5px);
  border-color: color-mix(in srgb, var(--card-accent, var(--brand)) 45%, var(--line));
}
.app-card .foot .more:hover { text-decoration: underline; }
.app-card a.store-badge {
  position: relative;
  z-index: 1;                 /* stays clickable above the stretched link */
  padding: 8px 16px 8px 13px;
  border-radius: 11px;
}
.app-card a.store-badge svg { width: 20px; height: 24px; }
.app-card a.store-badge .small { font-size: 9.5px; }
.app-card a.store-badge .big { font-size: 15px; }

.apps-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  margin-top: 44px;
}
@media (max-width: 820px) { .apps-grid { grid-template-columns: 1fr; } }

/* app groups on the apex — a colour-accented label per category */
.app-group { margin-top: 46px; }
.app-group .apps-grid { margin-top: 18px; }
.apps-grid.single { grid-template-columns: 1fr; }
.group-head {
  display: flex;
  align-items: center;
  gap: 13px;
  margin: 0;
  padding-left: 2px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--group-accent, var(--brand));
}
.group-head::before {
  content: "";
  flex: none;
  width: 22px;
  height: 3px;
  border-radius: 2px;
  background: currentColor;
}

/* -------------------------------------------------------------- pricing */

.plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
  margin-top: 44px;
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
}
.plan {
  padding: 30px;
  border-radius: var(--radius-lg);
  background: var(--bg-elev);
  border: 1px solid var(--line-soft);
}
.plan.pro {
  background:
    linear-gradient(var(--bg-elev), var(--bg-elev)) padding-box,
    linear-gradient(140deg, var(--brand), var(--brand-2) 50%, var(--gold)) border-box;
  border: 1px solid transparent;
}
.plan h3 { margin: 0; font-size: 20px; letter-spacing: -0.02em; }
.plan .price { margin: 12px 0 2px; font-size: 34px; font-weight: 750; letter-spacing: -0.03em; }
.plan .price span { font-size: 15px; font-weight: 500; color: var(--dim); }
.plan .alt { font-size: 13.5px; color: var(--faint); }
.plan ul {
  list-style: none;
  padding: 0;
  margin: 20px 0 0;
  display: grid;
  gap: 10px;
  color: var(--dim);
  font-size: 15px;
}
.plan ul li { padding-left: 26px; position: relative; }
.plan ul li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--brand);
  font-weight: 700;
}
.plan.pro ul li::before { color: var(--gold); }

/* --------------------------------------------------------------- footer */

footer.site {
  border-top: 1px solid var(--line-soft);
  padding: 44px 0 56px;
  color: var(--faint);
  font-size: 14px;
}
footer.site .wrap {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}
footer.site .logo { font-size: 16px; color: var(--dim); }
footer.site .logo img { width: 24px; height: 24px; }
footer.site nav {
  margin-left: auto;
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
}
footer.site a:hover { color: var(--text); }

/* ------------------------------------------------- legal / prose pages */

main.prose {
  position: relative;
  z-index: 1;
  max-width: 780px;
  margin: 0 auto;
  padding: clamp(40px, 7vh, 72px) 24px 96px;
}
.prose h1 {
  margin: 0 0 6px;
  font-size: clamp(32px, 5vw, 44px);
  letter-spacing: -0.03em;
  font-weight: 750;
}
.prose .updated {
  margin: 0 0 30px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--faint);
  font-size: 14px;
}
.prose h2 {
  margin: 36px 0 10px;
  font-size: 20px;
  letter-spacing: -0.015em;
}
.prose p, .prose li { color: var(--dim); font-size: 15.5px; }
.prose li { margin: 6px 0; }
.prose strong { color: var(--text); }
.prose a { color: var(--brand); }
.prose a:hover { text-decoration: underline; }
.prose .muted { color: var(--faint); }
.prose .contact {
  display: inline-block;
  padding: 9px 16px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--bg-card);
  color: var(--text);
  font-size: 15px;
}
.prose .card {
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 22px 24px;
  margin: 18px 0;
}

/* -------------------------------------------------------------- reveals */

html.js .reveal {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity 0.8s var(--ease) var(--d, 0ms),
    transform 0.8s var(--ease) var(--d, 0ms);
  will-change: opacity, transform;
}
html.js .reveal.in {
  opacity: 1;
  transform: none;
}

/* Phones fly in from below: feature visuals and the hero device get a longer
   travel + duration than plain copy reveals. :where() keeps specificity level
   with html.js .reveal, so the reduced-motion override below still wins. */
html.js :where(.feature .visual, .hero-media, .hero-visual).reveal {
  transform: translateY(96px);
  transition-duration: 1.05s;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .scene,
  .scene .blob,
  .scene .ring,
  .scene .flow { animation: none; }
  html.js .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ------------------------------------------------------- language switch */

/* EN ⇄ DE in the navbar. Outlined pill, deliberately NOT the filled .cta
   treatment — a language switch must not compete with the download button.
   `order: 1` parks it at the far right of the bar: site.js appends the
   dark-mode toggle to .links at runtime, so it is always the last DOM child
   and markup order alone cannot win. Everything else defaults to order 0. */
nav.top .links a.lang {
  order: 1;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 11px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
}
nav.top .links a.lang:hover { border-color: var(--brand); color: var(--brand); }
/* The 640px rule above hides every non-.cta nav link; the language switch is the
   one exception worth keeping — on a phone it is the only route to the other
   language, and the footer link is a whole page away. */
@media (max-width: 640px) {
  nav.top .links a.lang { display: inline-block; }
}

/* ------------------------------------------------------------------ faq */

/* Question-shaped copy, collapsed. <details> is deliberate: the answers stay
   in the DOM and in the accessibility tree whether open or shut, so crawlers
   and LLMs read every one of them while the page keeps its short silhouette.
   Never swap this for JS-mounted panels — that hides the text we came for.
   Pair each block with FAQPage JSON-LD in the page head. */
.faq {
  display: grid;
  gap: 12px;
  margin-top: 40px;
}
.faq details {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--bg-card);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.faq details:hover { border-color: var(--line); }
.faq details[open] { border-color: var(--line); }
.faq summary {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 20px 24px;
  cursor: pointer;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  list-style: none;
}
/* both spellings — WebKit still wants the pseudo-element */
.faq summary::-webkit-details-marker { display: none; }
.faq summary::marker { content: ''; }
.faq summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--radius);
}
/* chevron, drawn from borders so it needs no asset */
.faq summary::after {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  margin: 6px 0 0 auto;
  border-right: 2px solid var(--faint);
  border-bottom: 2px solid var(--faint);
  transform: rotate(45deg);
  transition: transform 0.25s var(--ease), border-color 0.25s var(--ease);
}
.faq details[open] summary::after {
  transform: rotate(-135deg);
  border-color: var(--brand);
}
.faq .answer {
  padding: 0 24px 22px;
  margin: 0;
  max-width: 62ch;
  color: var(--dim);
  font-size: 15.5px;
  line-height: 1.62;
}
.faq .answer + .answer { padding-top: 12px; }
.faq .answer a { color: var(--brand); }
@media (max-width: 640px) {
  .faq summary { padding: 17px 18px; font-size: 16px; gap: 12px; }
  .faq .answer { padding: 0 18px 19px; }
}

/* --------------------------------------------------------- support matrix */

/* A real <table> rather than a chip cloud: agents and search engines extract
   rows and headers reliably, a bag of <span>s not at all. Scrolls inside its
   own box so a narrow viewport never scrolls the page sideways. */
.matrix-scroll {
  margin-top: 34px;
  overflow-x: auto;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--bg-card);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
table.matrix {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
  text-align: left;
}
table.matrix caption {
  padding: 18px 22px 0;
  text-align: left;
  font-size: 13px;
  color: var(--faint);
}
table.matrix th,
table.matrix td {
  padding: 13px 22px;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
  white-space: nowrap;
}
table.matrix thead th {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
}
table.matrix tbody th {
  font-weight: 600;
  color: var(--text);
}
table.matrix td { color: var(--dim); }
table.matrix tbody tr:last-child th,
table.matrix tbody tr:last-child td { border-bottom: 0; }
@media (max-width: 640px) {
  table.matrix th,
  table.matrix td { padding: 11px 15px; }
  table.matrix caption { padding: 15px 15px 0; }
}
