/* ------------------------------------------------------------------
   Lock&Learn marketing site.
   One design system, five app worlds. The canvas is each app's dark
   "lockwall" (mirrors teaser/config.py and the store shots.html files),
   and the hero lights it like the teasers' pool rig: one lamp, near-black
   walls, the phone in the light (see the hero section below;
   note: never write a glob with star-slash in these comments, it
   terminates the comment block and corrupts the next rule). Three
   voices: content speaks serif, the interface whispers sans, meta is
   mono. The page is one stage: every section is a stretch of the same
   floor under its own pool of light, with numbered hairline heads and
   glass cards that show the widget rather than describe it. Worlds
   are themed with [data-app] so a page, a section or a card can each
   carry its own app identity.
   ------------------------------------------------------------------ */

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

:root {
  --sans: 'Inter', -apple-system, 'Helvetica Neue', sans-serif;
  --serif: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --hanzi: var(--serif);

  --ink: rgba(255,255,255,.96);
  --ink-2: rgba(255,255,255,.68);
  --ink-3: rgba(255,255,255,.42);
  --hair: rgba(255,255,255,.14);
  --hair-2: rgba(255,255,255,.08);
  --panel: rgba(255,255,255,.045);

  /* neutral (family) world — indigo night, mint accent */
  --w0: #2E3280; --w1: #1B1E4E; --w2: #0B0C22;
  --glow: 150,162,255;
  --tint: #45D6A0;

  --ease: cubic-bezier(.22, 1, .36, 1);
}

[data-app="trivia"] {
  --w0: #3A3F9E; --w1: #23265F; --w2: #0E0F2C;
  --glow: 150,162,255;
  --tint: #45D6A0;
  --hanzi: var(--serif);
}
[data-app="chinese"] {
  --w0: #6E2418; --w1: #38110A; --w2: #140705;
  --glow: 255,138,100;
  --tint: #F5926B;
  --hanzi: 'Noto Serif SC', var(--serif);
}
[data-app="japanese"] {
  --w0: #1F5474; --w1: #0F2C42; --w2: #060D16;
  --glow: 120,190,235;
  --tint: #78BEEB;
  --hanzi: 'Noto Serif JP', var(--serif);
}
[data-app="korean"] {
  --w0: #2450A8; --w1: #12295E; --w2: #060E21;
  --glow: 124,165,240;
  --tint: #7CA5F0;
  --hanzi: 'Noto Serif KR', var(--serif);
}
[data-app="arabic"] {
  --w0: #166355; --w1: #0B332C; --w2: #041511;
  --glow: 95,215,196;
  --tint: #4FD1BE;
  --hanzi: 'Noto Naskh Arabic', var(--serif);
}
/* Arabic vowel marks (harakat) stack above and below the letters; the
   headword slots need a taller line box so the marks never clip. */
[data-app="arabic"] .lockword .whanzi,
[data-app="arabic"] .float-card .fh,
[data-app="arabic"] .wcard .hanzi,
[data-app="arabic"] .app-card .showpiece .hz { line-height: 1.5; }
/* Example sentences carry dir="rtl" so the final period lands at the end of
   the sentence instead of jumping to the other side; keep them flush left so
   the card's lines still share one edge. */
[data-app="arabic"] .wcard .example .zh { text-align: left; }
[data-app="spanish"] {
  --w0: #7A5210; --w1: #3F2A08; --w2: #171003;
  --glow: 240,178,92;
  --tint: #ECA84B;
  --hanzi: var(--serif);
}

html { scroll-behavior: smooth; }
body {
  font-family: var(--sans);
  font-size: 16px;
  background: var(--w2);
  color: var(--ink);
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
::selection { background: color-mix(in srgb, var(--tint) 30%, transparent); }

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

.shell { max-width: 1200px; margin: 0 auto; padding: 0 min(5vw, 56px); }

/* film grain — the quiet thing that makes flat color feel like material */
.grain {
  position: fixed; inset: -50%; z-index: 200; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  opacity: .05;
  animation: grain 9s steps(6) infinite;
}
@keyframes grain {
  0%,100% { transform: translate(0,0) }
  20% { transform: translate(-6%,4%) }
  40% { transform: translate(4%,-7%) }
  60% { transform: translate(-3%,-4%) }
  80% { transform: translate(6%,6%) }
}

/* mono meta text */
.m {
  font-family: var(--mono);
  font-size: 11px; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-3);
}
.m.tint { color: var(--tint); }

/* ------------------------------------------------------------------ header */
.top {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  transition: background .4s ease, border-color .4s ease;
  border-bottom: 1px solid transparent;
}
.top.scrolled {
  background: color-mix(in srgb, var(--w2) 72%, transparent);
  backdrop-filter: blur(16px) saturate(1.3);
  -webkit-backdrop-filter: blur(16px) saturate(1.3);
  border-bottom-color: var(--hair-2);
}
.top-inner {
  max-width: 1200px; margin: 0 auto; padding: 0 min(5vw, 56px);
  height: 72px; display: flex; align-items: center;
}
.wordmark {
  display: flex; align-items: center; gap: 11px;
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  letter-spacing: .22em; color: var(--ink);
}
.top-nav { margin-left: auto; display: flex; align-items: center; gap: 30px; }
.top-nav a {
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3); white-space: nowrap; /* the flag never stacks over its label */
  transition: color .25s;
}
.top-nav a:hover { color: var(--ink); }
.top-nav a.here { color: var(--tint); }
.top-nav .e { letter-spacing: 0; margin-right: 7px; font-size: 12px; }

/* ------------------------------------------------------------------ prose
   Long-form pages (support) in the same voice as the rest of the site. */
.prose { max-width: 680px; margin-top: 8px; }
.prose h3 {
  font-family: var(--serif);
  font-size: 22px; font-weight: 600; letter-spacing: -.2px;
  margin-top: 44px;
  padding-top: 26px; border-top: 1px solid var(--hair-2);
}
.prose p { font-size: 15px; line-height: 1.75; color: var(--ink-2); margin-top: 12px; }
.prose a { color: var(--tint); }
.prose a:hover { text-decoration: underline; }

/* ------------------------------------------------------------------ hero
   The hero is a stage lit by one lamp: the teasers' "pool" rig
   (teaser/video/src/components/rigs.tsx, PoolRig) ported to CSS. The walls
   fall to near black, a cone of haze drops from a lamp above the phone,
   throws a pool of the app's own light on the floor beneath it and a key
   light on the phone itself. site.js measures the phone and sets --spot-x,
   --spot-key and --spot-floor on the hero so the light lands on the
   subject at every breakpoint (the percentages are the no-JS fallback).
   Every light layer lives inside .wall-layer, so the index's world
   switcher crossfades the whole rig, colour and all. Legibility is
   structural, as in the teasers: the vignette composites on top. */
.hero {
  --spot-x: 76%;     /* lamp and phone centre, from the hero's left edge */
  --spot-key: 46%;   /* where the key light sits on the phone */
  --spot-floor: 86%; /* the floor the pool lands on, just under the phone */
  position: relative; overflow: hidden;
  min-height: 100svh;
  display: flex; align-items: center;
  /* symmetric padding keeps the flex-centered content on the true middle;
     92px also clears the 72px fixed header */
  padding: 92px 0;
}
.hero-bg, .hero-bg .wall-layer { position: absolute; inset: 0; }
.hero-bg .wall-layer {
  opacity: 0; transition: opacity 1.1s ease;
  background:
    /* the pool the lamp throws on the floor under the phone */
    radial-gradient(330px 98px at var(--spot-x) var(--spot-floor),
      rgba(var(--glow),.50), rgba(var(--glow),.07) 58%, rgba(0,0,0,0) 78%),
    /* the key light on the subject itself */
    radial-gradient(340px 330px at var(--spot-x) var(--spot-key),
      rgba(var(--glow),.26), rgba(0,0,0,0) 72%),
    /* the walls, dimmed to near black so the beam has something to cut;
       the floor stays the page colour so the next section joins it */
    linear-gradient(180deg,
      color-mix(in srgb, var(--w0) 26%, #000006) 0%,
      color-mix(in srgb, var(--w1) 34%, #000006) 50%,
      var(--w2) 100%);
}
.hero-bg .wall-layer.on { opacity: 1; }
/* the beam: a soft wedge of haze from the lamp down to the floor, with a
   hot spot where it leaves the fixture (just above the hero's top edge, so
   the header's nav never sits on the brightest pixels). Blurred as one
   element so it reads as haze, not a shape; it sways and breathes very
   slowly, like the teaser key light. */
.hero-bg .wall-layer::before {
  content: ""; position: absolute; left: 0; right: 0; top: -80px; bottom: 0;
  background:
    radial-gradient(130px 30px at var(--spot-x) 56px,
      rgba(255,255,255,.24), rgba(var(--glow),.42) 38%, rgba(0,0,0,0) 72%),
    conic-gradient(from 156deg at var(--spot-x) 56px,
      rgba(0,0,0,0) 0deg, rgba(var(--glow),.07) 9deg, rgba(var(--glow),.44) 24deg,
      rgba(var(--glow),.07) 39deg, rgba(0,0,0,0) 48deg);
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 34%, rgba(0,0,0,.6) 66%, rgba(0,0,0,.16) 100%);
  mask-image: linear-gradient(180deg, #000 0, #000 34%, rgba(0,0,0,.6) 66%, rgba(0,0,0,.16) 100%);
  filter: blur(16px);
  transform-origin: var(--spot-x) 56px;
  animation: breathe 9s ease-in-out infinite;
  will-change: transform, opacity;
}
@keyframes breathe {
  0%, 100% { opacity: .9; transform: rotate(-.5deg); }
  50% { opacity: 1; transform: rotate(.5deg); }
}
/* dust in the beam: a few motes rising slowly through the light. site.js
   places them inside the cone; they are white, so the index crossfade
   never has to recolour them. */
.motes { position: absolute; inset: 0; pointer-events: none; }
.mote {
  position: absolute; left: calc(var(--spot-x) + var(--mx)); top: var(--my);
  width: var(--ms); height: var(--ms); border-radius: 50%;
  background: #fff; opacity: 0;
  animation: mote var(--md) linear infinite var(--mdl);
  will-change: transform, opacity;
}
@keyframes mote {
  0% { transform: translate3d(0, 0, 0); opacity: 0; }
  12% { opacity: var(--mo); }
  88% { opacity: var(--mo); }
  100% { transform: translate3d(var(--mdx), -160px, 0); opacity: 0; }
}
.hero-vignette {
  position: absolute; inset: 0;
  background:
    radial-gradient(130% 100% at 50% 42%, rgba(0,0,0,0) 56%, rgba(0,0,0,.40) 100%),
    linear-gradient(180deg, rgba(0,0,0,.16) 0%, rgba(0,0,0,0) 18%, rgba(0,0,0,0) 90%, var(--w2) 100%);
}
.hero-grid {
  position: relative; width: 100%;
  display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(32px, 5vw, 80px); align-items: center;
}

/* masked line reveal — headlines rise out of their own baseline.
   The mask window extends below the baseline so descenders (g, y, j)
   are not cropped by the tight line-height; the negative margin gives
   the extra window back so line spacing stays optically identical. */
.lines .l { display: block; overflow: hidden; padding-bottom: .14em; margin-bottom: -.14em; }
.lines .l > span {
  display: block;
  transform: translateY(114%);
  transition: transform 1s var(--ease);
}
.lines.in .l:nth-child(1) > span { transition-delay: .05s; }
.lines.in .l:nth-child(2) > span { transition-delay: .13s; }
.lines.in .l:nth-child(3) > span { transition-delay: .21s; }
.lines.in .l > span { transform: none; }

h1.display {
  font-family: var(--serif);
  font-size: clamp(44px, 6vw, 86px);
  line-height: 1.02; font-weight: 550; letter-spacing: -.025em;
  margin-top: 22px;
}
h1.display em { font-style: italic; font-weight: 500; color: var(--tint); }
.hero-sub {
  margin-top: 28px; max-width: 440px;
  font-size: 16.5px; line-height: 1.7; color: var(--ink-2);
}

/* world switcher — index hero */
.worlds { margin-top: 40px; display: flex; flex-wrap: wrap; gap: 18px 16px; }
.w-tab {
  position: relative; padding: 4px 0 10px;
  font-family: var(--mono); font-size: 11.5px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3);
  transition: color .3s;
}
.w-tab i { font-style: normal; margin-right: 7px; opacity: .55; }
.w-tab::after {
  content: ''; position: absolute; left: 0; bottom: 0;
  height: 1px; width: 100%; background: var(--hair-2);
}
.w-tab::before {
  content: ''; position: absolute; left: 0; bottom: 0; z-index: 1;
  height: 1px; width: 0; background: var(--tint);
  transition: width .5s var(--ease);
}
.w-tab:hover { color: var(--ink); }
.w-tab.on { color: var(--ink); }
.w-tab.on::before { width: 100%; }
/* where the copy column is narrowest, six numbered tabs wrap; drop the numbers as phones do */
@media (min-width: 561px) and (max-width: 700px), (min-width: 981px) and (max-width: 1100px) {
  .w-tab i { display: none; }
}
.world-line {
  margin-top: 24px; min-height: 64px; max-width: 460px;
  font-family: var(--serif); font-style: italic;
  font-size: 19px; line-height: 1.55; font-weight: 450;
  color: var(--ink-2);
  transition: opacity .35s ease;
}
.world-line.fade { opacity: 0; }
.world-line a {
  font-family: var(--mono); font-style: normal; font-size: 11px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--tint); white-space: nowrap; margin-left: 10px;
}
.world-line a:hover { border-bottom: 1px solid var(--tint); }

/* store action */
.store-row { margin-top: 36px; display: flex; flex-wrap: wrap; align-items: center; gap: 22px; }
.btn-store {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 15px 28px; border-radius: 999px;
  background: var(--ink); color: #0C0D16;
  font-size: 14.5px; font-weight: 600; letter-spacing: -.1px;
  box-shadow: 0 16px 44px rgba(0,0,0,.4);
  transition: transform .25s var(--ease), box-shadow .25s;
}
.btn-store:hover { transform: translateY(-2px); box-shadow: 0 22px 54px rgba(0,0,0,.5); }
.btn-store.secondary {
  background: transparent; color: var(--ink);
  border: 1px solid var(--hair); box-shadow: none;
}
.btn-store.secondary:hover {
  border-color: rgba(255,255,255,.32); background: rgba(255,255,255,.05);
  box-shadow: none;
}
.store-note { font-family: var(--mono); font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }

/* store modal (launch-date notice) */
.modal-overlay {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(6,7,12,.72); backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden; transition: opacity .25s var(--ease);
}
.modal-overlay.on { opacity: 1; visibility: visible; }
.modal-card {
  position: relative; max-width: 380px; width: 100%;
  padding: 36px 34px; border-radius: 20px;
  background: linear-gradient(180deg, #16172a, #0f1019); border: 1px solid var(--hair);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.16), 0 40px 90px rgba(0,0,0,.55);
  transform: translateY(10px) scale(.98); transition: transform .3s var(--ease);
}
.modal-overlay.on .modal-card { transform: translateY(0) scale(1); }
.modal-card h3 {
  font-family: var(--serif); font-size: 22px; font-weight: 500;
  line-height: 1.35; margin-top: 14px;
}
.modal-card p { font-size: 14.5px; line-height: 1.65; color: var(--ink-2); margin-top: 12px; }
.modal-card p a {
  color: var(--ink); text-decoration: underline;
  text-underline-offset: 3px; text-decoration-color: rgba(255,255,255,.35);
  transition: text-decoration-color .2s;
}
.modal-card p a:hover { text-decoration-color: currentColor; }
.modal-close {
  position: absolute; top: 18px; right: 18px;
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-3); font-size: 20px; line-height: 1;
  transition: color .2s, background .2s;
}
.modal-close:hover { color: var(--ink); background: rgba(255,255,255,.08); }

/* app picker (the index's store button): one glass row per app, each in
   its own world's tint, with the top nav's flag or emoji as its mark. On
   phones the card becomes a bottom sheet (see the responsive block). */
.modal-card.picker { max-width: 420px; padding: 32px 26px 24px; }
.modal-card.picker h3 { font-size: 26px; font-weight: 550; letter-spacing: -.02em; margin-top: 10px; }
.modal-card.picker > p { font-size: 14px; margin-top: 6px; }
.sheet-grip { display: none; }
.picks { display: flex; flex-direction: column; gap: 8px; margin-top: 22px; }
.pick {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 16px 12px 12px; border-radius: 16px;
  background:
    radial-gradient(90% 140% at 0% 50%, rgba(var(--glow),.16), rgba(var(--glow),0) 70%),
    linear-gradient(180deg, rgba(255,255,255,.07), rgba(255,255,255,.035));
  border: 1px solid rgba(255,255,255,.11);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.1);
  transition: border-color .25s, background-color .25s, transform .25s var(--ease);
}
.pick:hover, .pick:focus-visible {
  border-color: color-mix(in srgb, var(--tint) 55%, transparent);
  transform: translateY(-1px);
}
.pick:active { transform: scale(.985); }
.pick-e {
  flex: none; width: 42px; height: 42px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1;
  background: linear-gradient(180deg, var(--w0), var(--w1));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 4px 14px rgba(0,0,0,.3);
}
.pick-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pick-t b { font-family: var(--serif); font-size: 17px; font-weight: 600; letter-spacing: -.2px; line-height: 1.25; }
.pick-t small {
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--tint); margin-top: 3px;
}
.pick-go { flex: none; color: var(--ink-3); transition: color .25s, transform .25s var(--ease); }
.pick:hover .pick-go { color: var(--tint); transform: translateX(3px); }

/* ------------------------------------------------------------------ phone */
.phone-stage { position: relative; display: flex; justify-content: center; will-change: transform; }
.phone {
  position: relative; width: 306px; height: 626px;
  border-radius: 50px; background: #000; overflow: hidden;
  box-shadow:
    0 0 0 5px #17151F, 0 0 0 6px rgba(255,255,255,.06),
    0 60px 130px rgba(0,0,0,.6);
  text-align: center; color: #fff;
}
/* the lamp above catches the top edge of the frame */
.phone::after {
  content: ""; position: absolute; inset: 0; border-radius: 50px; pointer-events: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), inset 0 0 0 1px rgba(255,255,255,.035);
}
/* the phone's own light, thrown back off the floor beneath it */
.phone-stage::after {
  content: ""; position: absolute; left: 50%; top: 100%; z-index: -1;
  width: 306px; height: 110px; margin: 22px 0 0 -153px;
  border-radius: 50% / 60%;
  background: linear-gradient(180deg, rgba(var(--glow),.26), rgba(var(--glow),0) 80%);
  filter: blur(16px); pointer-events: none;
}
/* The wallpaper is the onboarding hook's night sky (ios/Core/
   LockScreenNightSky.swift): a seeded starfield denser toward the top, two
   tint nebulae, a twinkling third of the stars and a shooting star under
   the widget on the app's own schedule (first at 2.4s, then every 8.5s).
   The star SVGs come from sitegen/lock_sky.py; rerun it, never hand-edit. */
.phone .screen {
  position: absolute; inset: 0; overflow: hidden;
  background:
    url(lock-sky.svg) center top / cover no-repeat,
    radial-gradient(circle 200px at 18% 34%, rgba(var(--glow),.30), rgba(var(--glow),0)),
    radial-gradient(circle 250px at 84% 88%, rgba(var(--glow),.24), rgba(var(--glow),0)),
    radial-gradient(85% 50% at 50% 8%, rgba(var(--glow),.30), rgba(var(--glow),0) 70%),
    radial-gradient(70% 26% at 50% 30%, rgba(var(--glow),.18), rgba(var(--glow),0) 75%),
    linear-gradient(180deg, var(--w0) 0%, var(--w1) 50%, var(--w2) 100%);
}
.phone .screen::before {
  content: ""; position: absolute; inset: 0;
  background: url(lock-sky-tw.svg) center top / cover no-repeat;
  animation: sky-twinkle 3.6s ease-in-out infinite alternate;
}
@keyframes sky-twinkle { from { opacity: 1; } to { opacity: .35; } }
.phone .screen::after {
  content: ""; position: absolute; left: 68%; top: 50%;
  width: 96px; height: 1.5px; border-radius: 1px;
  background: linear-gradient(90deg, rgba(255,255,255,.95), rgba(255,255,255,0));
  box-shadow: -1px 0 4px rgba(255,255,255,.6);
  transform-origin: left center; opacity: 0;
  animation: sky-shoot 8.5s linear 2.4s infinite;
}
@keyframes sky-shoot {
  0%   { opacity: 0; transform: rotate(-26deg) translateX(0) scaleX(.2); }
  5%   { opacity: 1; transform: rotate(-26deg) translateX(-110px) scaleX(1); }
  10.5%{ opacity: 0; transform: rotate(-26deg) translateX(-210px) scaleX(.3); }
  100% { opacity: 0; transform: rotate(-26deg) translateX(-210px) scaleX(.3); }
}
.island {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  width: 82px; height: 25px; border-radius: 14px; background: #000;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
}
.lock-icon { padding-top: 54px; opacity: .85; }
.lock-date { margin-top: 6px; font-size: 13.5px; font-weight: 600; opacity: .92; }
.lock-clock {
  font-size: 88px; font-weight: 600; line-height: 1.02; margin-top: -2px;
  letter-spacing: -1px;
  color: rgba(255,255,255,.60);
  text-shadow:
    0 1px 1px rgba(255,255,255,.30),
    0 -1px 2px rgba(0,0,20,.38),
    0 0 18px rgba(var(--glow),.42),
    0 8px 22px rgba(0,0,15,.35);
}
.lockword {
  margin: 22px auto 0; width: 240px; text-align: left;
  color: rgba(255,255,255,.97);
  text-shadow: 0 1px 5px rgba(0,0,10,.42);
  transition: opacity .3s ease, transform .3s ease;
}
.lockword.fade { opacity: 0; transform: translateY(6px); }
.lockword .wchip {
  display: flex; align-items: center; gap: 7px;
  font-family: var(--mono);
  font-size: 8.5px; font-weight: 500; letter-spacing: .2em; opacity: .9;
}
.lockword .wchip .dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }
.lockword .wq {
  font-family: var(--serif);
  font-size: 15.5px; font-weight: 600; line-height: 1.3; margin-top: 6px;
  max-width: 210px;
}
.lockword .whanzi {
  font-family: var(--hanzi);
  font-size: 27px; font-weight: 600; line-height: 1.15; margin-top: 5px;
}
.lockword .wreading { font-size: 12px; font-weight: 500; opacity: .78; margin-top: 3px; }
.lockword .whint { font-size: 10px; font-weight: 500; opacity: .55; margin-top: 7px; }
.lock-bottom {
  position: absolute; bottom: 34px; left: 0; right: 0;
  display: flex; justify-content: space-between; padding: 0 34px;
}
.lock-circle {
  width: 34px; height: 34px; border-radius: 50%;
  background: rgba(255,255,255,.13);
  display: flex; align-items: center; justify-content: center;
}
.home-bar {
  position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%);
  width: 96px; height: 4px; border-radius: 2px; background: rgba(255,255,255,.45);
}

/* floating widget cards */
.float-card {
  position: absolute; z-index: 2;
  padding: 14px 18px; border-radius: 14px;
  background: color-mix(in srgb, var(--w2) 55%, rgba(5,5,12,.6));
  border: 1px solid var(--hair);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.14), 0 30px 70px rgba(0,0,0,.5);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  text-align: left;
  transition: opacity .35s ease;
  animation: drift 9s ease-in-out infinite;
}
@keyframes drift {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-9px); }
}
.float-card.fade { opacity: 0; }
.float-card .fh {
  font-family: var(--hanzi);
  font-size: 23px; font-weight: 600; line-height: 1.2; color: var(--ink);
}
.float-card .fq {
  font-family: var(--serif);
  font-size: 14.5px; font-weight: 600; line-height: 1.35; color: var(--ink);
  max-width: 170px;
}
.float-card .fr { font-size: 11.5px; font-weight: 500; color: var(--ink-2); margin-top: 2px; }
.float-card .fm {
  font-family: var(--mono); font-size: 9px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3); margin-top: 5px;
}
.f1 { top: 9%; left: -2%; animation-delay: -2.2s; }
.f2 { top: 45%; right: -4%; animation-delay: -4.6s; }
.f3 { bottom: 8%; left: 2%; animation-delay: -1.2s; }

/* ------------------------------------------------------------------ sections
   The page is one stage. Sections are not rooms with walls: they are
   stretches of the same floor, each under its own soft lamp (a pool of the
   app's glow that fades in below the previous section and out before the
   next), so the eye travels down one continuous space instead of across a
   stack of bands. Structure comes from the numbered hairline over each
   section head, the same rule the hero's world tabs wear. */
.sec { position: relative; padding: clamp(84px, 11vh, 130px) 0; isolation: isolate; }
/* The lamp hangs over the section's subject (the head and the first row of
   content, which sit left of centre). The pool's box is capped in height
   (Chrome will not take min() inside a gradient size), so the very tall
   word-list sections keep it near their top instead of stretching it down
   the whole table. */
.sec::before {
  content: ""; position: absolute; inset: 0; max-height: 1100px;
  z-index: -1; pointer-events: none;
  background: radial-gradient(70% 52% at 42% 30%, rgba(var(--glow),.13), rgba(var(--glow),0) 70%);
}
/* a "band" used to be a filled stripe between hairlines; now it is the same
   floor under a brighter lamp, so the page keeps its rhythm without an edge */
.sec.band::before {
  background:
    radial-gradient(70% 52% at 42% 30%, rgba(var(--glow),.18), rgba(var(--glow),0) 70%),
    radial-gradient(40% 26% at 42% 32%, rgba(var(--glow),.07), rgba(var(--glow),0) 70%);
}
.sec-head {
  position: relative; max-width: 720px;
  padding-top: 26px; border-top: 1px solid var(--hair-2);
}
.sec-head::before {
  content: ""; position: absolute; top: -1px; left: 0;
  width: 64px; height: 1px; background: var(--tint);
}
.sec-head .m { display: block; }
.sec-head h2 {
  font-family: var(--serif);
  font-size: clamp(32px, 3.8vw, 50px);
  line-height: 1.06; font-weight: 550; letter-spacing: -.02em;
  margin-top: 16px; text-wrap: balance;
}
.sec-head h2 em { font-style: italic; font-weight: 500; color: var(--tint); }
.sec-head .lede {
  margin-top: 16px; max-width: 540px;
  font-size: 15.5px; line-height: 1.7; color: var(--ink-2);
}

/* ------------------------------------------------------------------ widget cards
   The product, shown: same anatomy as the real widget and reveal. */
.cards3 {
  margin-top: 52px;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px;
}
/* Every card on the page is the same glass as the hero's floating widgets:
   a translucent pane with a rim light on its top edge, the app's glow
   falling on it from above, seated on a soft shadow. No filled boxes. */
.wcard {
  position: relative;
  border-radius: 24px; padding: 26px 28px 28px;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(var(--glow),.16), rgba(var(--glow),0) 70%),
    linear-gradient(180deg, rgba(255,255,255,.085) 0%, rgba(255,255,255,.045) 45%, rgba(255,255,255,.03) 100%), var(--w2);
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.18), inset 0 -1px 0 rgba(0,0,0,.25), 0 30px 70px rgba(0,0,0,.38);
}
.wcard .step {
  position: absolute; top: 26px; right: 26px;
}
.wcard .chip {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--mono);
  font-size: 10px; font-weight: 500; letter-spacing: .2em; text-transform: uppercase;
  color: var(--tint);
}
.wcard .chip .dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--tint);
  box-shadow: 0 0 10px 1px color-mix(in srgb, var(--tint) 60%, transparent);
}
.wcard .q {
  font-family: var(--serif);
  font-size: 22px; font-weight: 600; line-height: 1.3; margin-top: 16px;
  text-wrap: balance;
}
.wcard .hanzi {
  font-family: var(--hanzi);
  font-size: 52px; font-weight: 600; line-height: 1.08; margin-top: 16px;
  text-shadow: 0 8px 50px rgba(var(--glow),.3);
}
.wcard .reading { font-size: 14.5px; font-weight: 500; color: var(--ink-2); margin-top: 8px; }
.wcard .guess {
  font-family: var(--serif); font-style: italic;
  font-size: 24px; font-weight: 500; line-height: 1.35; margin-top: 16px;
  color: var(--ink);
}
.wcard .meaning {
  font-family: var(--serif);
  font-size: 26px; font-weight: 600; letter-spacing: -.3px; margin-top: 14px;
}
.wcard .body { font-size: 14px; line-height: 1.65; color: var(--ink-2); margin-top: 12px; }
.wcard .hint { font-size: 12.5px; color: var(--ink-3); margin-top: 16px; }
.wcard .src { display: block; margin-top: 16px; }
.wcard .example {
  margin-top: 18px; border-radius: 14px; padding: 15px 17px;
  background: rgba(255,255,255,.055);
  border: 1px solid rgba(255,255,255,.09);
}
.wcard .example .zh { font-family: var(--hanzi); font-size: 19px; font-weight: 500; line-height: 1.5; }
.wcard .example .py { font-size: 12.5px; color: var(--ink-2); margin-top: 5px; }
.wcard .example .tr { font-family: var(--serif); font-style: italic; font-size: 13.5px; color: var(--ink-3); margin-top: 3px; }
.wcard .blur-wrap {
  position: relative; margin-top: 16px; border-radius: 14px; overflow: hidden;
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.09);
  padding: 16px 18px;
}
.wcard .blurred { font-family: var(--serif); font-size: 18px; font-weight: 600; line-height: 1.35; filter: blur(9px); opacity: .8; }
.wcard .veil {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 9px;
  font-family: var(--mono); font-size: 10px; font-weight: 500; letter-spacing: .22em;
}

/* ------------------------------------------------------------------ family cards (index) */
.family {
  margin-top: 52px;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
}
.app-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column;
  border-radius: 26px; padding: 24px 20px 22px; min-height: 380px;
  background:
    radial-gradient(120% 70% at 50% 0%, rgba(var(--glow),.30), rgba(var(--glow),0) 70%),
    linear-gradient(180deg, var(--w0) 0%, var(--w1) 55%, var(--w2) 100%);
  border: 1px solid rgba(255,255,255,.13);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.22), 0 30px 70px rgba(0,0,0,.35);
  transition: transform .35s var(--ease), box-shadow .35s, border-color .35s;
}
.app-card:hover {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--tint) 45%, transparent);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.26), 0 44px 90px rgba(0,0,0,.5);
}
.app-card .tag { align-self: flex-start; }
.app-card .showpiece {
  flex: 1; display: flex; flex-direction: column; justify-content: center;
  text-align: center; padding: 28px 0 22px;
}
.app-card .showpiece .hz {
  font-family: var(--hanzi);
  font-size: 54px; font-weight: 600; line-height: 1.05;
  text-shadow: 0 6px 50px rgba(var(--glow),.35);
}
.app-card .showpiece .rd { font-size: 13.5px; color: var(--ink-2); margin-top: 10px; }
.app-card .showpiece .qz {
  font-family: var(--serif);
  font-size: 19px; font-weight: 600; line-height: 1.3; letter-spacing: -.3px;
  text-wrap: balance; padding: 0 4px;
  text-shadow: 0 6px 50px rgba(var(--glow),.35);
}
.app-card h3 { font-family: var(--serif); font-size: 19px; font-weight: 600; letter-spacing: -.3px; }
.app-card .about { font-size: 12.5px; line-height: 1.6; color: var(--ink-2); margin-top: 7px; min-height: 44px; }
.app-card .go {
  margin-top: 16px; display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--tint);
}
.app-card .go svg { transition: transform .3s var(--ease); }
.app-card:hover .go svg { transform: translateX(5px); }
.family-note { margin-top: 26px; text-align: center; }

/* tag chip — mono label in a tinted pill */
.tag {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--tint);
  padding: 8px 14px; border-radius: 999px;
  background: color-mix(in srgb, var(--tint) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--tint) 30%, transparent);
}
.tag .dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--tint);
  box-shadow: 0 0 12px 2px color-mix(in srgb, var(--tint) 60%, transparent);
}

/* ------------------------------------------------------------------ feature tiles */
.tiles {
  margin-top: 52px;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px;
}
.tile {
  border-radius: 20px; padding: 26px 24px;
  background: linear-gradient(180deg, rgba(255,255,255,.075) 0%, rgba(255,255,255,.04) 50%, rgba(255,255,255,.028) 100%), var(--w2);
  border: 1px solid rgba(255,255,255,.12);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.14), 0 18px 44px rgba(0,0,0,.28);
  transition: border-color .3s, transform .3s var(--ease), box-shadow .3s;
}
.tile:hover {
  border-color: rgba(255,255,255,.22); transform: translateY(-3px);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.2), 0 26px 56px rgba(0,0,0,.36);
}
.tile .m { display: block; }
.tile h4 { font-size: 16px; font-weight: 600; letter-spacing: -.15px; margin-top: 14px; }
.tile p { font-size: 13.5px; line-height: 1.6; color: var(--ink-2); margin-top: 8px; }

/* ------------------------------------------------------------------ packs / levels */
.packs {
  margin-top: 48px;
  display: flex; flex-wrap: wrap; gap: 10px;
}
.packs.center { justify-content: center; }
.pack {
  font-size: 14px; font-weight: 600; color: var(--ink-2);
  padding: 12px 22px; border-radius: 999px;
  background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.04));
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.14);
  transition: all .3s ease;
}
.pack:hover {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--tint) 50%, transparent);
  background: color-mix(in srgb, var(--tint) 10%, transparent);
  transform: translateY(-2px);
}
.pack.free {
  color: var(--tint);
  border-color: color-mix(in srgb, var(--tint) 45%, transparent);
  background: color-mix(in srgb, var(--tint) 10%, transparent);
}
.pack.free small {
  font-family: var(--mono); font-size: 9px; font-weight: 500;
  letter-spacing: .16em; margin-left: 8px; vertical-align: 1px;
}
.packs-note { margin-top: 22px; }
.packs-note + .packs-note { margin-top: 10px; }
.packs-note a, .family-note a { color: var(--tint); }
.packs-note a:hover, .family-note a:hover { border-bottom: 1px solid var(--tint); }

/* ------------------------------------------------------------------ faq */
.faq { margin-top: 52px; max-width: 780px; border-top: 1px solid var(--hair-2); }
.faq details { border-bottom: 1px solid var(--hair-2); }
.faq summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: baseline; justify-content: space-between; gap: 28px;
  padding: 24px 0;
  font-family: var(--serif);
  font-size: 19px; font-weight: 600; letter-spacing: -.2px; line-height: 1.35;
  transition: color .25s;
}
.faq summary:hover { color: var(--tint); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  font-family: var(--mono); font-size: 16px; font-weight: 400;
  color: var(--tint); flex: none;
  transition: transform .3s var(--ease);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq .a { padding: 0 44px 26px 0; font-size: 14.5px; line-height: 1.75; color: var(--ink-2); max-width: 660px; }
.faq .a a { color: var(--tint); }
.faq .a a:hover { text-decoration: underline; }

/* ------------------------------------------------------------------ plus panel */
.plus-panel {
  position: relative; margin-top: 52px;
  border-radius: 30px; padding: clamp(30px, 4vw, 48px);
  background:
    radial-gradient(110% 130% at 88% 0%, rgba(var(--glow),.22), rgba(var(--glow),0) 60%),
    linear-gradient(180deg, rgba(255,255,255,.08) 0%, rgba(255,255,255,.04) 50%, rgba(255,255,255,.03) 100%), var(--w2);
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.2), inset 0 -1px 0 rgba(0,0,0,.25), 0 30px 70px rgba(0,0,0,.4);
  display: grid; grid-template-columns: 1.1fr .9fr; gap: clamp(28px, 4vw, 56px);
  align-items: center;
}
/* the panel stands on the stage floor: the lamp's pool spills out under it */
.plus-panel::after {
  content: ""; position: absolute; left: 6%; right: 6%; top: 100%; z-index: -1;
  height: 160px; margin-top: -40px; pointer-events: none;
  background: radial-gradient(50% 55% at 50% 32%, rgba(var(--glow),.30), rgba(var(--glow),0) 70%);
  filter: blur(18px);
}
.plus-panel h3 {
  font-family: var(--serif);
  font-size: clamp(24px, 2.6vw, 32px); font-weight: 600; letter-spacing: -.4px;
  line-height: 1.15; margin-top: 14px; text-wrap: balance;
}
.plus-panel .lead { margin-top: 14px; font-size: 15px; line-height: 1.7; color: var(--ink-2); max-width: 460px; }
.price-cards { display: flex; flex-direction: column; gap: 12px; }
.price {
  border-radius: 18px; padding: 20px 24px;
  background: linear-gradient(180deg, rgba(255,255,255,.075), rgba(255,255,255,.04));
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.14);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.price.hot {
  border-color: color-mix(in srgb, var(--tint) 50%, transparent);
  background: color-mix(in srgb, var(--tint) 8%, transparent);
}
.price .pl { font-size: 15.5px; font-weight: 600; }
.price .ps { display: block; font-size: 12.5px; font-weight: 400; color: var(--ink-3); margin-top: 3px; }
.price .badge {
  flex: none;
  font-family: var(--mono); font-size: 9px; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--tint); padding: 6px 11px; border-radius: 999px;
  background: color-mix(in srgb, var(--tint) 14%, transparent);
}

/* ------------------------------------------------------------------ CTA */
/* The page closes on the teasers' "grid" rig (rigs.tsx, GridRig): the
   night sky that has been filling in section by section (below) reaches
   its densest here, over a neon floor in the app's own glow running to a
   lit horizon, the retrowave set. The horizon sits at 78%, below the store
   button, so the bloom rakes under the copy instead of behind it, and the
   extra bottom padding gives the floor a few rows of grid. Sky and horizon
   are gradients, the floor is one element in perspective whose lines
   scroll toward the viewer a whole cell per cycle (the grid is periodic,
   so it never pops), and the last layer fades it into the footer's wall. */
.cta {
  --horizon: 78%;
  position: relative; overflow: hidden; text-align: center; isolation: isolate;
  padding: clamp(110px, 16vh, 190px) 0 clamp(170px, 24vh, 280px);
}
/* the sky, deepening from the previous section's floor toward the middle
   and clearing at the horizon, and the horizon itself: a hot line with
   bloom above and below it */
.cta::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(0,0,0,0) calc(var(--horizon) - 1px), rgba(var(--glow),.9) calc(var(--horizon) - 1px),
      rgba(var(--glow),.9) calc(var(--horizon) + 1px), rgba(0,0,0,0) calc(var(--horizon) + 1px)) 50% 0 / 76% 100% no-repeat,
    radial-gradient(38% 3.5% at 50% var(--horizon), rgba(var(--glow),.55), rgba(var(--glow),0) 70%),
    radial-gradient(58% 13% at 50% var(--horizon), rgba(var(--glow),.75), rgba(var(--glow),0) 72%),
    linear-gradient(180deg, rgba(2,2,10,0) 0%, rgba(2,2,10,.42) 34%, rgba(2,2,10,.14) 60%, rgba(0,0,0,0) var(--horizon));
}
/* the floor itself, in perspective, scrolling toward the camera */
.cta .glowup {
  position: absolute; left: -60%; right: -60%; top: var(--horizon); bottom: -14%;
  z-index: -1; pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, rgba(var(--glow),.72) 0 3px, rgba(0,0,0,0) 3px 104px),
    repeating-linear-gradient(0deg, rgba(var(--glow),.4) 0 3px, rgba(0,0,0,0) 3px 88px);
  transform: perspective(340px) rotateX(76deg);
  transform-origin: 50% 0%;
  -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.85) 12%, #000 45%);
  mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.85) 12%, #000 45%);
  animation: gridscroll 2.6s linear infinite;
  will-change: background-position;
}
@keyframes gridscroll { to { background-position: 0 88px; } }
/* the floor runs on into the footer's dark wall instead of stopping on it */
.cta::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 22%; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,0), var(--w2));
}
/* the sky's stars stay above the horizon */
.cta .stars { bottom: 24%; }

/* ------------------------------------------------------------------ the night sky
   site.js drops a starfield into every section after the hero, denser with
   each section down the page. A field is dark until its section scrolls
   into view (.sky-on), then each star fades up on its own small delay, so
   the scroll reads as the night filling with stars; about a third of them
   keep twinkling. */
.stars { position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.star {
  position: absolute; left: var(--sx); top: var(--sy);
  width: var(--ss); height: var(--ss); border-radius: 50%;
  background: rgba(255,255,255,.95); opacity: 0;
  transition: opacity 1.4s ease var(--sd);
}
.sky-on .star { opacity: var(--so); }
.sky-on .star.tw { animation: twinkle var(--st) ease-in-out infinite; animation-delay: calc(var(--sd) + 1.4s); }
@keyframes twinkle {
  0%, 100% { opacity: var(--so); }
  50% { opacity: calc(var(--so) * .3); }
}

.cta h2 {
  position: relative;
  font-family: var(--serif);
  font-size: clamp(38px, 5.6vw, 78px);
  font-weight: 550; line-height: 1.04; letter-spacing: -.025em; text-wrap: balance;
}
.cta h2 em { font-style: italic; font-weight: 500; color: var(--tint); }
.cta .store-row { justify-content: center; position: relative; }

/* ------------------------------------------------------------------ footer */
footer { background: linear-gradient(180deg, var(--w2) 0%, color-mix(in srgb, var(--w2) 55%, #000006) 100%); }
.foot-inner {
  max-width: 1200px; margin: 0 auto; padding: 56px min(5vw, 56px) 64px;
  display: flex; flex-wrap: wrap; gap: 48px; justify-content: space-between;
}
.foot-brand p { max-width: 240px; margin-top: 14px; font-size: 13px; line-height: 1.7; color: var(--ink-3); }
.foot-cols { display: flex; flex-wrap: wrap; gap: 32px clamp(40px, 6vw, 96px); }
.foot-col .m { display: block; margin-bottom: 16px; }
.foot-col a { display: block; font-size: 13.5px; color: var(--ink-2); padding: 5px 0; transition: color .25s; }
.foot-col a:hover { color: var(--ink); }

/* ------------------------------------------------------------------ reveal */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity .9s var(--ease), transform .9s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.reveal.d1 { transition-delay: .08s; }
.reveal.d2 { transition-delay: .16s; }
.reveal.d3 { transition-delay: .24s; }
@media (prefers-reduced-motion: reduce) {
  .reveal, .lines .l > span { opacity: 1; transform: none; transition: none; }
  .float-card, .grain, .hero-bg .wall-layer::before, .cta .glowup, .mote, .star { animation: none; }
  .phone .screen::before { animation: none; opacity: .8; }
  .phone .screen::after { display: none; }
  .star { transition: none; }
}

/* ------------------------------------------------------------------ responsive */
/* Laptop displays (a 14" MacBook reads the site a touch large) render the
   whole page at 90%; desktop-class widths keep 100%. Viewport units ignore
   zoom, so the full-height hero compensates. */
@media (min-width: 981px) and (max-width: 1760px) {
  body { zoom: 0.9; }
  .hero { min-height: calc(100svh / 0.9); }
}
@media (max-width: 980px) {
  .hero { min-height: 0; padding: 140px 0 80px; }
  .motes { display: none; } /* the beam runs behind the copy here; no dust over words */
  .hero-grid { grid-template-columns: 1fr; gap: 72px; }
  .cards3 { grid-template-columns: 1fr; }
  .family { grid-template-columns: repeat(2, 1fr); }
  .tiles { grid-template-columns: repeat(2, 1fr); }
  .plus-panel { grid-template-columns: 1fr; }
  .top-nav { gap: 18px; }
}
@media (max-width: 880px) {
  .top-nav .e { display: none; } /* six apps plus Support only fit as bare labels */
}
@media (max-width: 720px) {
  .top-nav a:not(.keep) { display: none; } /* not even bare; the footer lists every app */
}
@media (max-width: 560px) {
  .top-nav { gap: 18px; }
  .top-nav a:not(.keep) { display: none; }
  .f2 { display: none; } /* would cover the phone's widget on narrow screens */
  .f1 { top: 1%; left: 0; } /* above the clock, not on it */
  .worlds { gap: 22px; }
  h1.display { font-size: 42px; }
  .tiles { grid-template-columns: 1fr; }
  .family { grid-template-columns: 1fr; }
}
/* Phones get a compact, centered hero that shows the value and the store
   button in the first screen: the phone rises first, cropped to its clock
   and widget and fading into the floor, then the headline, a short sub and
   the button. The copy column dissolves (display: contents) so each piece
   can be ordered on its own; on the index the world tabs sit right under
   the phone they switch, and the Explore line moves below the button.
   The generated word-list pages (.list-hero) keep their own phone hero
   from lists.css: there the list, not the phone, is what the visitor came for. */
@media (max-width: 560px) {
  .hero:not(.list-hero) { padding: 76px 0 44px; }
  .hero:not(.list-hero) .hero-grid { display: flex; flex-direction: column; align-items: center; gap: 0; text-align: center; }
  .hero:not(.list-hero) .hero-grid > div:first-child { display: contents; }
  .hero:not(.list-hero) .hero-grid .phone-stage {
    order: 0; width: 100%; height: 280px; overflow: hidden;
    -webkit-mask-image: linear-gradient(180deg, #000 80%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 80%, transparent 100%);
  }
  .hero:not(.list-hero) .hero-grid .phone-stage::after { display: none; }
  .hero:not(.list-hero) .hero-grid .phone { transform: scale(.76); transform-origin: 50% 0; flex: none; }
  .hero:not(.list-hero) .hero-grid .float-card { display: none; }
  .hero:not(.list-hero) .hero-grid .worlds { order: 1; }
  .hero:not(.list-hero) .hero-grid > div > .m { order: 2; margin-top: 18px; font-size: 10px; }
  .hero:not(.list-hero) .hero-grid h1.display { order: 3; font-size: 34px; margin-top: 12px; }
  .hero:not(.list-hero) .hero-grid .hero-sub { order: 4; margin-top: 12px; font-size: 14.5px; line-height: 1.5; max-width: 340px; }
  .hero:not(.list-hero) .hero-grid .store-row { order: 5; margin-top: 20px; width: 100%; flex-direction: column; gap: 12px; }
  .hero:not(.list-hero) .hero-grid .btn-store { width: 100%; max-width: 340px; justify-content: center; padding: 16px 28px; font-size: 15.5px; }
  .hero:not(.list-hero) .hero-grid .world-line { order: 6; margin-top: 26px; min-height: 0; font-size: 16px; }
  .hero:not(.list-hero) .hero-grid .world-line a { display: inline-block; margin: 6px 0 0; }
  /* index: the tabs become one compact row directly under the phone */
  .worlds { margin-top: 4px; flex-wrap: nowrap; justify-content: center; gap: 14px; }
  .w-tab { font-size: 10px; letter-spacing: .1em; padding-bottom: 8px; }
  .w-tab i { display: none; }
  /* the index's eyebrow is the least useful line on a small screen */
  #worldHero .hero-grid > div > .m { display: none; }
}
/* The rest of the page on phones, on the hero's principle: less floor
   between sections, content sooner. Card rows that stack into a tall
   tower (.cards3, the index's .family) become swipeable rails whose next
   card peeks in at the edge; numbered tiles become a compact list with
   hairlines instead of boxes; the Plus panel, FAQ and closing CTA tighten,
   and the CTA's store button goes full width like the hero's. */
@media (max-width: 560px) {
  .sec { padding: 60px 0; }
  .sec-head { padding-top: 20px; }
  .sec-head h2 { font-size: 30px; margin-top: 12px; }
  .sec-head .lede { margin-top: 12px; font-size: 15px; line-height: 1.6; }

  /* rails: bleed to the screen edges, snap card by card. Cards scrolled
     inside a rail never intersect the viewport for the reveal observer,
     so they show without it. */
  .cards3, .family {
    display: flex; gap: 12px; margin: 30px calc(-1 * min(5vw, 56px)) 0;
    padding: 2px min(5vw, 56px) 22px;
    overflow-x: auto; scroll-snap-type: x mandatory;
    scroll-padding-inline: min(5vw, 56px);
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .cards3::-webkit-scrollbar, .family::-webkit-scrollbar { display: none; }
  .cards3 > *, .family > * { flex: 0 0 84%; scroll-snap-align: start; }
  .cards3 > .reveal, .family > .reveal { opacity: 1; transform: none; }
  .wcard { padding: 22px 22px 24px; box-shadow: inset 0 1.5px 0 rgba(255,255,255,.18), inset 0 -1px 0 rgba(0,0,0,.25), 0 14px 30px rgba(0,0,0,.3); }
  .wcard .step { top: 22px; right: 22px; }
  .app-card { min-height: 0; padding: 20px 20px 20px; box-shadow: inset 0 1.5px 0 rgba(255,255,255,.22), 0 14px 30px rgba(0,0,0,.3); }
  .app-card .showpiece { padding: 22px 0 18px; }
  .app-card .showpiece .hz { font-size: 46px; }
  .app-card .about { min-height: 0; }
  .app-card .go { margin-top: 12px; }
  .family-note { margin-top: 6px; }

  /* tiles: a numbered list, number in the margin, hairline between rows */
  .tiles { margin-top: 26px; gap: 0; border-top: 1px solid var(--hair-2); }
  .tile, .tile:hover {
    display: grid; grid-template-columns: 34px 1fr; column-gap: 6px;
    padding: 18px 0; border-radius: 0;
    background: none; border: 0; border-bottom: 1px solid var(--hair-2);
    box-shadow: none; transform: none;
  }
  .tile .m { grid-row: span 2; padding-top: 3px; }
  .tile h4 { margin-top: 0; font-size: 15.5px; }
  .tile p { margin-top: 4px; font-size: 13.5px; line-height: 1.55; }

  .packs { margin-top: 28px; gap: 8px; }
  .pack { padding: 10px 18px; }

  .plus-panel { margin-top: 30px; padding: 24px 20px; border-radius: 24px; gap: 22px; }
  .plus-panel .lead { font-size: 14.5px; line-height: 1.6; }
  .price { padding: 16px 18px; }

  .faq { margin-top: 26px; }
  .faq summary { padding: 18px 0; font-size: 17px; gap: 18px; }
  .faq .a { padding: 0 0 20px; font-size: 14px; line-height: 1.65; }

  .cta { padding: 72px 0 150px; }
  .cta h2 { font-size: 36px; }
  .cta .store-row { flex-direction: column; gap: 12px; margin-top: 28px; }
  .cta .btn-store { width: 100%; max-width: 340px; justify-content: center; padding: 16px 28px; font-size: 15.5px; }

  .foot-inner { padding: 44px min(5vw, 56px) 48px; gap: 36px; }

  /* the app picker rises as a bottom sheet, rows within thumb reach */
  .modal-overlay:has(.picker) { align-items: flex-end; padding: 0; }
  .modal-card.picker {
    max-width: none; border-radius: 26px 26px 0 0; border-bottom: 0;
    padding: 12px 18px calc(18px + env(safe-area-inset-bottom));
    transform: translateY(100%);
  }
  .modal-overlay.on .modal-card.picker { transform: none; }
  .sheet-grip {
    display: block; width: 38px; height: 5px; border-radius: 3px;
    margin: 0 auto 18px; background: rgba(255,255,255,.22);
  }
  .modal-card.picker .modal-close { top: 22px; right: 14px; }
  .modal-card.picker h3 { font-size: 24px; }
  .picks { margin-top: 18px; }
  .pick { padding: 11px 14px 11px 11px; }
}
