/* KEYBO — the website.
 *
 * White and lime by default, dark and lime on the toggle. Colours are the
 * app's (ios/AIKeyboard/App/Brand.swift); Premium stays lime, gold is only
 * KEYBO's crown. Headings are Poppins, body text the system font.
 *
 * Built to stay smooth: no backdrop blur, no filters, no endless animations
 * except KEYBO's own loop on large screens, which pauses off screen.
 */

@font-face { font-family: "Poppins"; font-weight: 600; font-style: normal; font-display: swap;
  src: url("../fonts/Poppins-SemiBold.ttf") format("truetype"); }
@font-face { font-family: "Poppins"; font-weight: 700; font-style: normal; font-display: swap;
  src: url("../fonts/Poppins-Bold.ttf") format("truetype"); }

:root {
  --lime-50: #EFFCBD;
  --lime-100: #DEF777;
  --lime: #C8E84B;
  --lime-600: #B6DB33;
  --ink: #141708;
  --btn: linear-gradient(90deg, #DEF777, #C8E84B 55%, #B6DB33);

  --bg: #FFFFFF;
  --bg-alt: #F7F9EF;
  --card: #FFFFFF;
  --card-2: #F3F6EA;
  --text: #141708;
  --muted: #5C6152;
  --line: #E6EADB;
  --accent: #4F6B00;
  --icon-bg: #EFFCBD;
  --icon-fg: #3E5500;
  --hl-bg: #DEF777;
  --hl-fg: inherit;
  --store-bg: #141708;
  --store-fg: #FFFFFF;
  --shadow: 0 1px 2px rgba(20, 23, 8, .04), 0 8px 24px rgba(20, 23, 8, .06);

  --font-display: "Poppins", ui-sans-serif, system-ui, sans-serif;
  --font-body: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --wrap: 1140px;
  --gutter: 24px;
  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #0A0A0A;
  --bg-alt: #0F100E;
  --card: #151614;
  --card-2: #1D1F1A;
  --text: #F4F6EE;
  --muted: #A4A898;
  --line: rgba(255, 255, 255, .09);
  --accent: #C8E84B;
  --icon-bg: rgba(200, 232, 75, .14);
  --icon-fg: #C8E84B;
  --hl-bg: transparent;
  --hl-fg: #C8E84B;
  --store-bg: #FFFFFF;
  --store-fg: #141708;
  --shadow: 0 1px 2px rgba(0, 0, 0, .3);
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; scroll-padding-top: 76px; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font-family: var(--font-body); font-size: 17px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;               /* nothing may push the page sideways; clip keeps sticky working */
}
img, video, svg { display: block; max-width: 100%; }
img, video { height: auto; }
a { color: inherit; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--lime-600); outline-offset: 3px; border-radius: 10px; }

h1, h2, h3 { font-family: var(--font-display); margin: 0; letter-spacing: -0.025em; line-height: 1.12; }
h1 { font-size: clamp(40px, 5.6vw, 68px); font-weight: 700; letter-spacing: -0.035em; line-height: 1.05; }
h2 { font-size: clamp(30px, 3.8vw, 46px); font-weight: 700; }
h3 { font-size: 19px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.3; }
p { margin: 0; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.hl { background: linear-gradient(transparent 58%, var(--hl-bg) 58%, var(--hl-bg) 92%, transparent 92%); color: var(--hl-fg); padding: 0 .06em; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.icon { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; flex: none; }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 22px; border-radius: 999px; border: 0; cursor: pointer;
  font-family: var(--font-display); font-weight: 600; font-size: 15.5px;
  text-decoration: none; white-space: nowrap; transition: transform .15s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: scale(.98); }
.btn-lime { background: var(--btn); color: var(--ink); box-shadow: 0 4px 14px rgba(182, 219, 51, .35); }
.btn-line { background: var(--card); color: var(--text); box-shadow: inset 0 0 0 1.5px var(--line); }
.btn-ink { background: var(--ink); color: #fff; }
:root[data-theme="dark"] .btn-ink { background: #fff; color: var(--ink); }

/* App Store / Google Play: the stores' own marks, store-badge shaped. */
.stores { display: flex; flex-wrap: wrap; gap: 12px; }
.store {
  display: inline-flex; align-items: center; gap: 10px;
  height: 56px; padding: 0 20px 0 16px; border-radius: 14px;
  background: var(--store-bg); color: var(--store-fg); text-decoration: none;
  transition: transform .15s ease;
}
.store:hover { transform: translateY(-1px); }
.store svg { width: 26px; height: 26px; flex: none; }
.store span { display: flex; flex-direction: column; line-height: 1.1; }
.store small { font-size: 11px; font-weight: 500; letter-spacing: .01em; opacity: .85; }
.store b { font-family: var(--font-display); font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }

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

.site-header { position: sticky; top: 0; z-index: 50; background: transparent; border-bottom: 1px solid transparent; transition: background-color .2s ease, border-color .2s ease; }
.site-header.scrolled, .site-header.open { background: var(--bg); border-bottom-color: var(--line); }
/* At the top the header sits on the lime, like the app's home: ink on lime. */
.site-header:not(.scrolled):not(.open) .wordmark { color: var(--ink); }
.site-header:not(.scrolled):not(.open) .nav-links a { color: rgba(20, 23, 8, .7); }
.site-header:not(.scrolled):not(.open) .nav-links a:hover { color: var(--ink); background: rgba(20, 23, 8, .07); }
.site-header:not(.scrolled):not(.open) .theme-btn, .site-header:not(.scrolled):not(.open) .menu-btn { background: rgba(20, 23, 8, .08); color: var(--ink); }
.site-header:not(.scrolled):not(.open) .btn-lime { background: var(--ink); color: #CCFA00; box-shadow: none; }
.nav { display: flex; align-items: center; height: 68px; gap: 14px; }
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; margin-right: auto; }
.brand img { width: 34px; height: 34px; border-radius: 9px; }
.wordmark { font-family: var(--font-display); font-weight: 600; font-size: 17px; letter-spacing: .32em; margin-right: -.32em; }
.nav-links { display: flex; gap: 2px; list-style: none; margin: 0; padding: 0; }
.nav-links a { display: block; padding: 8px 13px; border-radius: 999px; font-size: 15px; font-weight: 500; color: var(--muted); text-decoration: none; }
.nav-links a:hover { color: var(--text); background: var(--card-2); }
.nav .btn { min-height: 42px; padding: 0 16px 0 18px; font-size: 14.5px; }
.theme-btn, .menu-btn {
  width: 42px; height: 42px; border-radius: 50%; border: 0; cursor: pointer; flex: none;
  display: inline-grid; place-items: center; background: var(--card-2); color: var(--text);
}
.theme-btn:hover, .menu-btn:hover { box-shadow: inset 0 0 0 1.5px var(--lime-600); }
.theme-btn .icon { width: 20px; height: 20px; }
.theme-btn .sun { display: none; }
:root[data-theme="dark"] .theme-btn .moon { display: none; }
:root[data-theme="dark"] .theme-btn .sun { display: block; }
.menu-btn { display: none; }

@media (max-width: 920px) {
  .nav-links { display: none; }
  .nav .dl-btn { padding: 0 14px; }
  .menu-btn { display: inline-grid; }
  .site-header.open .nav-links {
    display: flex; flex-direction: column; position: absolute; top: 68px; left: 0; right: 0;
    padding: 4px var(--gutter) 16px; background: var(--bg); border-bottom: 1px solid var(--line);
  }
  .site-header.open .nav-links a { padding: 14px 2px; font-size: 17px; color: var(--text); border-radius: 0; border-bottom: 1px solid var(--line); }
}

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

/* The top of the page is the app's home header: the icon's lime gradient,
   ink type, KEYBO on the right, and the page rising over it on a rounded
   sheet. It stays lime in the dark theme too, as it does in the app. */
.hero {
  position: relative; overflow: hidden; color: var(--ink);
  margin-top: -69px; padding: 125px 0 124px;
  background: linear-gradient(135deg, #EFFCBD 0%, #DEF777 34%, #C8E84B 68%, #B6DB33 100%);
}
.sheet { position: relative; margin-top: -36px; border-radius: 36px 36px 0 0; background: var(--bg); }
.hero-grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: 32px; }
.pill {
  display: inline-flex; align-items: center; gap: 9px; padding: 8px 15px 8px 13px; border-radius: 999px;
  background: var(--ink); color: #fff; font-size: 14px; font-weight: 600;
}
.pill i { width: 8px; height: 8px; border-radius: 50%; background: #CCFA00; }
.hero h1 { margin: 22px 0 20px; }
.hero .lede { font-size: clamp(18px, 1.5vw, 20px); color: rgba(20, 23, 8, .74); max-width: 32em; margin-bottom: 32px; }
.hero .store { background: var(--ink); color: #fff; }
.hero-ticks { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 26px; font-size: 14.5px; font-weight: 500; color: rgba(20, 23, 8, .78); }
.hero-ticks span { display: inline-flex; align-items: center; gap: 7px; }
.hero-ticks .icon { width: 17px; height: 17px; color: var(--ink); stroke-width: 2.4; }
/* The hero art: KEYBO, big, holding up a phone and showing its screen,
   where the real keyboard plays (Reply, Tone, Fix and Rewrite, Translate,
   cross-fading). Layers on one 2000x1200 canvas: KEYBO and the phone, the
   video in the screen hole, then the bit of his hand over the screen. The
   hole is x 1121.54, y 181.95, w 434.07, h 943.39 (hold2-screen.json). On
   wide screens the scene sits beside the text, about as tall as it (the
   canvas's empty margins are trimmed with negative margins); on tablets it
   sits under the text; on phones it's the phone alone with the small hello
   KEYBO in front. */
.hero-art { position: relative; width: 140%; max-width: none; margin: -12% 0 -7% -7%; pointer-events: none; }
/* narrower laptops: a little smaller and further left, so the phone and its
   label stay clear of the window's edge */
@media (min-width: 901px) and (max-width: 1240px) { .hero-art { width: 132%; margin: -11% 0 -6% -10%; } }
.hold { position: relative; aspect-ratio: 2000 / 1200; }
.hold-back img, .hold-front img, .hold-loop { position: absolute; inset: 0; width: 100%; height: 100%; }
.hold-back img, .hold-loop { z-index: 1; }
.hp-screen { position: absolute; z-index: 2; left: 56.077%; top: 15.163%; width: 21.704%; height: 78.616%; border-radius: 13% / 5.982%; overflow: hidden; background: #F2F2F7 url(../videos/reply.jpg?v=2) center / cover; }
.hold-front img { z-index: 3; }
.hp-v { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .5s ease; }
.hp-v.on { opacity: 1; }
.hp-chip { position: absolute; z-index: 4; left: 66.93%; top: 96%; transform: translateX(-50%); display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-radius: 999px; background: var(--ink); color: #fff; font-family: var(--font-display); font-weight: 600; font-size: 14px; white-space: nowrap; box-shadow: 0 14px 30px -10px rgba(20, 23, 8, .5); }
.hp-chip b { font-weight: 600; min-width: 7.2em; }
.hp-dots { display: inline-flex; gap: 5px; }
.hp-dots i { width: 6px; height: 6px; border-radius: 3px; background: rgba(255, 255, 255, .3); transition: width .3s ease, background-color .3s ease; }
.hp-dots i.on { width: 16px; background: #CCFA00; }
.hero-keybo { display: none; }
@media (min-width: 701px) and (max-width: 900px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); justify-items: center; gap: 0; text-align: center; }
  .hero .lede { margin-left: auto; margin-right: auto; }
  .hero .stores, .hero-ticks { justify-content: center; }
  /* the canvas's content (KEYBO to the phone) spans 3%-79% of it; centre that */
  .hero-art { --aw: min(940px, calc((100vw - 32px) / .78)); width: var(--aw); margin: calc(var(--aw) * -.07) 0 calc(var(--aw) * .02) calc(50% - var(--aw) * .41); justify-self: start; }
}
@media (max-width: 900px) {
  .hero { padding: 88px 0 72px; }
  .hp-chip { font-size: 13.5px; padding: 8px 13px; gap: 9px; }
}
@media (max-width: 700px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .hero-art { width: 100%; max-width: 360px; margin: 44px auto 0; padding-bottom: 20px; }
  .hold { aspect-ratio: auto; }
  .hold-back, .hold-front { display: none; }
  .hp-screen { position: relative; left: auto; top: auto; width: 222px; height: auto; aspect-ratio: 600 / 1304; margin: 10px 10px 10px auto; border-radius: 30px; box-shadow: 0 0 0 10px #141708, 0 0 0 11.5px rgba(255, 255, 255, .25), 0 44px 80px -20px rgba(20, 23, 8, .45); }
  .hp-chip { left: 0; top: 5%; transform: none; }
  .hero-keybo { display: block; position: absolute; z-index: 3; left: -7%; bottom: -8px; width: 50%; aspect-ratio: 1; }
  .hero-keybo img, .hero-keybo video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
}


/* ---------- Sections ---------- */

.section { padding: 104px 0; }
.section.alt { background: var(--bg-alt); }
.head { max-width: 720px; margin: 0 auto 52px; text-align: center; }
.kicker { display: block; margin-bottom: 14px; font-family: var(--font-display); font-weight: 600; font-size: 13.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
.head p { margin-top: 16px; font-size: 18.5px; color: var(--muted); }
@media (max-width: 760px) { .section { padding: 72px 0; } .head { margin-bottom: 36px; } }

.card { background: var(--card); border-radius: 22px; box-shadow: inset 0 0 0 1px var(--line), var(--shadow); }

/* AI features, one at a time.
   Large screens: the section holds still; one scroll (or a tab) moves one
   feature. The left side is one big panel per feature, a large lime number,
   name, title, line and points, and the panels swap: the old one lifts away,
   the new one rises in. Its video fades in on the right. Phones: a list. */
.features { position: relative; background: var(--bg); padding-top: 96px; }
.features-head { padding-bottom: 8px; }
.features-head { margin-bottom: 0; }
/* The held view is as tall as its content (site.js measures it into
   --pinh) and sticks centred in the space under the header (--pintop), so
   it follows straight on from the heading with no empty band. */
.tour { position: relative; height: calc(var(--pinh, 620px) + var(--steps) * 45vh); }
.tour-pin {
  position: sticky; top: var(--pintop, 68px);
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: 64px; align-items: center;
  padding-top: 16px; padding-bottom: 16px;
}
.tour-panels { display: grid; }
.tour-panel {
  grid-area: 1 / 1; align-self: center;
  opacity: 0; visibility: hidden; transform: translateY(90px); filter: blur(14px);
  transition: opacity .3s ease, transform .45s cubic-bezier(.4, 0, .6, 1), filter .35s ease, visibility 0s linear .45s;
}
.tour-panel.past { transform: translateY(-90px); }
.tour-panel.on {
  opacity: 1; visibility: visible; transform: none; filter: blur(0);
  transition: opacity .5s ease .1s, transform .75s cubic-bezier(.16, 1, .3, 1) .1s, filter .55s ease .1s, visibility 0s;
}
.tour-progress { display: flex; align-items: center; gap: 16px; margin-bottom: 40px; }
.tour-count { font-family: var(--font-display); font-weight: 600; font-size: 14px; letter-spacing: .06em; color: var(--muted); min-width: 56px; }
.tour-count b { color: var(--text); font-weight: 700; }
.tour-bars { display: flex; gap: 6px; }
.tour-tab { width: 34px; height: 5px; padding: 0; border: 0; border-radius: 3px; cursor: pointer; background: var(--line); transition: background-color .3s ease, width .3s ease; }
.tour-tab::after { content: ""; display: block; height: 22px; margin-top: -9px; }
.tour-tab:hover { background: var(--lime-100); }
.tour-tab.on { width: 56px; background: var(--lime-600); }
.tour-name { display: block; font-family: var(--font-display); font-weight: 600; font-size: 14px; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
.tour-panel h3 { font-size: clamp(38px, 4vw, 56px); font-weight: 700; letter-spacing: -0.035em; line-height: 1.04; margin: 14px 0 18px; max-width: 12em; }
.tour-panel > p { font-size: 20px; color: var(--muted); max-width: 24em; }
.tour-stage { position: relative; height: min(580px, calc(100vh - 160px)); }
.tour-visual {
  position: absolute; inset: 0; display: grid; place-items: center;
  opacity: 0; transform: translateY(140px) scale(.94); filter: blur(16px);
  transition: opacity .3s ease, transform .45s cubic-bezier(.4, 0, .6, 1), filter .35s ease;
  pointer-events: none;
}
.tour-visual.past { transform: translateY(-140px) scale(.94); }
.tour-visual.on {
  opacity: 1; transform: none; filter: blur(0); pointer-events: auto;
  transition: opacity .5s ease .05s, transform .8s cubic-bezier(.16, 1, .3, 1) .05s, filter .55s ease .05s;
}
.tour-visual .demo { max-width: 440px; }

@media (max-width: 960px), (max-height: 600px) {
  .features { padding: 72px 0; }
  .tour { height: auto; }
  .tour-pin { position: static; height: auto; display: flex; flex-direction: column; align-items: stretch; gap: 0; }
  .tour-side, .tour-panels, .tour-stage { display: contents; }
  .tour-progress { display: none; }
  .tour-panel, .tour-panel.on, .tour-panel.past { order: var(--o); opacity: 1; visibility: visible; transform: none; filter: none; margin-top: 52px; }
  .tour-visual, .tour-visual.on, .tour-visual.past { order: var(--o); position: static; opacity: 1; transform: none; filter: none; margin-top: 22px; pointer-events: auto; }
  .tour-panel h3 { font-size: 30px; margin: 10px 0 10px; }
  .tour-panel > p { font-size: 17px; }
}

/* The real keyboard, recorded in Messages. The clips are full phone
   screens; the action is all in the lower half, so they are shown from
   there down: message box, AI buttons, keyboard. */
.clip { width: 100%; max-width: 360px; margin: 0 auto; aspect-ratio: 600 / 760; overflow: hidden; border-radius: 28px; background: #E4E6EA 50% 100% / cover no-repeat; box-shadow: 0 0 0 8px var(--card-2), 0 0 0 9px var(--line), 0 18px 40px rgba(20, 23, 8, .12); }
.clip video { width: 100%; height: 100%; object-fit: cover; object-position: 50% 100%; }
.tour-stage .clip { width: min(100%, 458px, calc(min(580px, 100vh - 160px) * 600 / 760)); height: auto; }
@media (max-width: 960px), (max-height: 600px) { .tour-stage .clip, .clip { width: 100%; height: auto; max-width: 320px; border-radius: 24px; } }
.tag { display: inline-block; padding: 2px 9px; border-radius: 999px; background: var(--lime); color: var(--ink); font-family: var(--font-body); font-size: 11.5px; font-weight: 700; letter-spacing: .02em; vertical-align: 1px; }

/* Tick lists */
.ticks { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 13px; }
.ticks li { position: relative; padding-left: 34px; font-size: 16px; }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: 2px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--icon-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233E5500' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 12.5 4 4L18 8'/%3E%3C/svg%3E") center / 14px no-repeat;
}
:root[data-theme="dark"] .ticks li::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23C8E84B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 12.5 4 4L18 8'/%3E%3C/svg%3E"); }
.ticks b { font-weight: 650; }

/* Demo card */
.demo { padding: 22px; border-radius: 24px; width: 100%; background: var(--bg-alt); box-shadow: inset 0 0 0 1px var(--line); }
.demo .chip, .demo .reply { background: var(--card); }
.demo .field, .demo .out-line, .demo .strip { background: var(--card); box-shadow: inset 0 0 0 1px var(--line); }
.demo .bubble.in { background: var(--card); box-shadow: inset 0 0 0 1px var(--line); }
.voice { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-radius: 18px; background: var(--lime); color: var(--ink); }
.voice .play { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: var(--ink); color: #CCFA00; font-size: 12px; }
.voice .bars { flex: 1; display: flex; align-items: center; gap: 3px; height: 28px; }
.voice .bars i { flex: 1; border-radius: 2px; background: rgba(20, 23, 8, .55); height: 40%; }
.voice .bars i:nth-child(3n) { height: 85%; } .voice .bars i:nth-child(4n+1) { height: 60%; } .voice .bars i:nth-child(5n) { height: 100%; }
.voice .dur { font-size: 13px; font-weight: 700; }
.order { display: grid; gap: 6px; }
.order div { display: flex; align-items: center; gap: 12px; padding: 11px 14px; border-radius: 14px; background: var(--card); box-shadow: inset 0 0 0 1px var(--line); font-weight: 600; font-size: 15px; }
.order div:first-child { box-shadow: inset 0 0 0 2px var(--lime-600); }
.order .grip { color: var(--muted); letter-spacing: -2px; font-size: 13px; }
.demo-top { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; font-size: 13.5px; color: var(--muted); }
.demo-top .av { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: var(--card-2); font-weight: 700; font-size: 14px; color: var(--text); }
.demo-top b { display: block; color: var(--text); font-size: 14.5px; line-height: 1.2; }
.bubble { max-width: 84%; padding: 11px 15px; border-radius: 18px; font-size: 15.5px; line-height: 1.45; }
.bubble.in { background: var(--card-2); border-bottom-left-radius: 6px; }
.bubble.out { margin-left: auto; background: var(--lime); color: var(--ink); border-bottom-right-radius: 6px; }
.thread { display: flex; flex-direction: column; gap: 8px; min-height: 52px; }
.strip { display: flex; gap: 6px; margin: 16px 0 12px; padding: 6px; border-radius: 16px; background: var(--card-2); overflow-x: auto; scrollbar-width: none; }
.strip::-webkit-scrollbar { display: none; }
.chip {
  flex: none; padding: 8px 13px; border-radius: 999px; border: 0; cursor: pointer;
  background: var(--card); color: var(--text); font-size: 14px; font-weight: 600; white-space: nowrap;
  box-shadow: inset 0 0 0 1px var(--line);
}
.chip.on, .demo .chip.on { background: var(--btn); color: var(--ink); box-shadow: none; }
.chip .tag { margin-left: 4px; }
.chip.static { cursor: default; }
.replies { display: grid; gap: 8px; }
.reply { text-align: left; width: 100%; padding: 12px 14px; border-radius: 14px; border: 0; cursor: pointer; background: var(--card-2); font-size: 15px; line-height: 1.45; }
.reply:hover, .reply.picked { box-shadow: inset 0 0 0 2px var(--lime-600); }
.reply small { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--accent); }
.field { min-height: 84px; padding: 14px 16px; border-radius: 16px; background: var(--card-2); font-size: 16px; line-height: 1.5; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.note { margin-top: 14px; font-size: 13px; color: var(--muted); }
.out-line { min-height: 58px; display: flex; align-items: center; padding: 12px 16px; border-radius: 16px; background: var(--card-2); font-family: var(--font-display); font-weight: 600; font-size: 20px; }
.label { margin: 18px 0 8px; font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }

/* How it works: three steps on one line, then the setup panel. */
.how-steps { list-style: none; margin: 0 auto; padding: 0; max-width: 1000px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 40px; position: relative; }
.how-steps::before { content: ""; position: absolute; top: 31px; left: 16%; right: 16%; height: 2px; background: linear-gradient(90deg, var(--line), var(--lime-600), var(--line)); }
.how-steps li { position: relative; text-align: center; }
.how-n {
  position: relative; display: grid; place-items: center; width: 64px; height: 64px; margin: 0 auto 22px; border-radius: 50%;
  background: var(--btn); color: var(--ink); font-family: var(--font-display); font-weight: 700; font-size: 26px;
  box-shadow: 0 0 0 8px var(--bg-alt), 0 8px 22px rgba(182, 219, 51, .4);
}
.how-steps h3 { font-size: 22px; margin-bottom: 8px; }
.how-steps p { font-size: 16px; color: var(--muted); max-width: 22em; margin: 0 auto; }
@media (max-width: 820px) {
  .how-steps { grid-template-columns: minmax(0, 1fr); gap: 28px; max-width: 440px; }
  .how-steps::before { top: 0; bottom: 0; left: 31px; right: auto; width: 2px; height: auto; background: linear-gradient(180deg, var(--line), var(--lime-600), var(--line)); }
  .how-steps li { display: grid; grid-template-columns: 64px minmax(0, 1fr); column-gap: 18px; text-align: left; }
  .how-n { grid-row: span 2; margin: 0; }
  .how-steps h3 { align-self: end; margin: 0 0 4px; }
  .how-steps p { margin: 0; }
}

.setup { margin-top: 80px; padding: 36px; display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 40px; align-items: start; }
.setup-intro h3 { font-size: 26px; margin-bottom: 8px; }
.setup-intro p { color: var(--muted); font-size: 16px; margin-bottom: 22px; }
.tabs { display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px; background: var(--card-2); }
.tabs button { border: 0; cursor: pointer; padding: 9px 16px; border-radius: 999px; background: transparent; font-weight: 600; font-size: 14px; color: var(--muted); }
.tabs button[aria-selected="true"] { background: var(--btn); color: var(--ink); }
.setup-steps [role="tabpanel"] { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.setup-steps [role="tabpanel"][hidden] { display: none; }
.setup-step { padding: 22px; border-radius: 18px; background: var(--bg-alt); box-shadow: inset 0 0 0 1px var(--line); }
.step-tag { display: inline-block; padding: 3px 10px; border-radius: 999px; background: var(--ink); color: #CCFA00; font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
:root[data-theme="dark"] .step-tag { background: var(--lime); color: var(--ink); }
.setup-step h4 { margin: 12px 0 12px; font-family: var(--font-display); font-weight: 600; font-size: 19px; }
.setup-step ol { margin: 0; padding: 0; list-style: none; counter-reset: k; display: grid; gap: 10px; }
.setup-step li { counter-increment: k; position: relative; padding-left: 30px; font-size: 15px; color: var(--muted); }
.setup-step li::before { content: counter(k); position: absolute; left: 0; top: 1px; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; background: var(--icon-bg); color: var(--icon-fg); font-size: 11.5px; font-weight: 700; }
.setup-step li b { color: var(--text); font-weight: 600; }
.setup .hint { grid-column: 1 / -1; margin: 2px 0 0; padding: 12px 16px; border-radius: 14px; background: var(--icon-bg); color: var(--icon-fg); font-size: 14.5px; font-weight: 500; }
@media (max-width: 900px) { .setup { grid-template-columns: minmax(0, 1fr); padding: 26px 22px; gap: 24px; margin-top: 56px; } }
@media (max-width: 620px) { .setup-steps [role="tabpanel"] { grid-template-columns: minmax(0, 1fr); } }

/* Privacy: the main promise, on the app's lime, in both themes. */
#privacy { padding-top: 64px; }
.privacy-panel {
  display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 56px; align-items: center;
  padding: 64px; border-radius: 36px; color: var(--ink);
  background: linear-gradient(135deg, #EFFCBD 0%, #DEF777 34%, #C8E84B 68%, #B6DB33 100%);
}
.shield { position: relative; width: 100%; max-width: 280px; aspect-ratio: 1; justify-self: center; display: grid; place-items: center; }
.shield::before { content: ""; position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(closest-side, rgba(255, 255, 255, .65), rgba(255, 255, 255, 0)); }
.shield svg { position: relative; width: 74%; height: auto; }
.privacy-panel .kicker { color: rgba(20, 23, 8, .66); }
.privacy-panel h2 { margin-bottom: 14px; font-size: clamp(34px, 4.4vw, 54px); }
.privacy-panel .intro { font-size: 18.5px; color: rgba(20, 23, 8, .74); max-width: 34em; }
.promises { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 30px; }
.promise { padding: 20px; border-radius: 20px; background: rgba(255, 255, 255, .55); }
.promise .icon { color: var(--ink); margin-bottom: 10px; width: 24px; height: 24px; }
.promise h3 { font-size: 17px; margin-bottom: 4px; }
.promise p { font-size: 15px; color: rgba(20, 23, 8, .72); }
.privacy-panel .more { margin-top: 22px; font-size: 15px; color: rgba(20, 23, 8, .74); }
.privacy-panel .more a { color: var(--ink); font-weight: 700; }
@media (max-width: 960px) { .privacy-panel { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 36px 24px; border-radius: 28px; } .shield { max-width: 190px; } #privacy { padding-top: 44px; } }
@media (max-width: 560px) { .promises { grid-template-columns: minmax(0, 1fr); } }

/* The side rail: which section you are in, and a way to jump (like 2mv.ai).
   Labels on the left where there is room; dots on the right otherwise. */
.rail { position: fixed; z-index: 40; top: 50%; left: 28px; transform: translateY(-50%); display: none; flex-direction: column; gap: 2px; opacity: 0; pointer-events: none; transition: opacity .25s ease; }
.rail.show { opacity: 1; pointer-events: auto; }
.rail a { position: relative; display: flex; align-items: center; gap: 12px; padding: 7px 0; color: var(--muted); text-decoration: none; font-size: 14.5px; font-weight: 500; transition: color .2s ease; }
.rail a i { width: 3px; height: 16px; border-radius: 3px; background: var(--line); transition: height .2s ease, background-color .2s ease; }
.rail a:hover { color: var(--text); }
.rail a.on { color: var(--text); font-family: var(--font-display); font-weight: 600; font-size: 17px; }
.rail a.on i { height: 26px; background: var(--lime-600); }
.rail a small { font-family: var(--font-body); font-size: 12px; font-weight: 600; color: var(--muted); }
@media (min-width: 1400px) { .rail { display: flex; } }
@media (min-width: 960px) and (max-width: 1399px) {
  .rail { display: flex; left: auto; right: 14px; align-items: flex-end; }
  .rail a { padding: 8px 6px; }
  .rail a i { width: 8px; height: 8px; border-radius: 50%; }
  .rail a.on i { width: 10px; height: 10px; }
  .rail a span { position: absolute; right: 26px; padding: 4px 10px; border-radius: 999px; white-space: nowrap; background: var(--card); box-shadow: inset 0 0 0 1px var(--line), var(--shadow); font-size: 13px; opacity: 0; transition: opacity .2s ease; pointer-events: none; }
  .rail a.on span, .rail a:hover span { opacity: 1; }
  .rail a.on { font-size: 14.5px; }
  .rail a small { display: none; }
}

/* Pricing */
.plans { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; max-width: 920px; margin: 0 auto; }
.plan { padding: 34px; display: flex; flex-direction: column; position: relative; }
.plan .name { font-family: var(--font-display); font-weight: 600; font-size: 20px; }
.plan .price { font-family: var(--font-display); font-weight: 700; font-size: 46px; letter-spacing: -0.04em; line-height: 1; margin: 18px 0 6px; }
.plan .price small { font-size: 16px; font-weight: 500; letter-spacing: 0; color: var(--muted); }
.plan .sub { font-size: 15px; color: var(--muted); }
.plan .ticks { margin: 26px 0 30px; }
.plan .btn { margin-top: auto; }
.plan.pro { box-shadow: inset 0 0 0 2px var(--lime-600), 0 12px 40px rgba(182, 219, 51, .2); }
.plan.pro img { position: absolute; top: -40px; right: 18px; width: 120px; pointer-events: none; }
.fine { max-width: 720px; margin: 26px auto 0; text-align: center; font-size: 13px; color: var(--muted); }
@media (max-width: 820px) { .plans { grid-template-columns: minmax(0, 1fr); } .plan { padding: 28px; } .plan.pro img { width: 100px; top: -30px; } }

/* FAQ */
.faq { max-width: 820px; margin: 0 auto; display: grid; gap: 10px; }
.faq details { padding: 0 24px; border-radius: 18px; }
.faq summary { list-style: none; cursor: pointer; padding: 20px 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; font-family: var(--font-display); font-weight: 600; font-size: 17px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; flex: none; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; background: var(--card-2); font-size: 20px; font-weight: 500; line-height: 1; }
.faq details[open] summary::after { content: "–"; background: var(--lime); color: var(--ink); }
.faq .answer { padding-bottom: 22px; color: var(--muted); font-size: 16px; }
.faq .answer p + p { margin-top: 10px; }
.faq .answer b { color: var(--text); font-weight: 600; }
.faq .answer a { color: var(--accent); font-weight: 600; }

/* Final call */
.cta { padding: 0 0 104px; }
.cta-box { border-radius: 30px; padding: 64px 32px; text-align: center; background: linear-gradient(135deg, #EFFCBD, #DEF777 45%, #C8E84B); color: var(--ink); }
.cta-box h2 { margin-bottom: 14px; }
.cta-box p { font-size: 18px; color: rgba(20, 23, 8, .72); margin-bottom: 30px; }
.cta-box .stores { justify-content: center; }
.cta-box .store { background: var(--ink); color: #fff; }
.cta-box @media (max-width: 760px) { .cta { padding-bottom: 72px; } .cta-box { padding: 48px 22px; border-radius: 24px; } }

/* Footer */
.site-footer { border-top: 1px solid var(--line); padding: 48px 0 36px; font-size: 15px; }
.foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 32px; }
.foot .about { max-width: 22em; margin-top: 12px; color: var(--muted); }
.foot-links { display: flex; flex-wrap: wrap; gap: 48px; }
.foot-links h4 { margin: 0 0 12px; font-size: 13px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.foot-links ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.foot-links a { text-decoration: none; }
.foot-links a:hover { color: var(--accent); }
.copyright { margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 13.5px; color: var(--muted); }

/* Gentle entrance, once. */
.js .reveal { opacity: 0; transform: translateY(14px); transition: opacity .5s ease, transform .5s ease; }
.js .reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  .js .reveal { opacity: 1; transform: none; }
  html { scroll-behavior: auto; }
}
.rail.aside { opacity: 0; pointer-events: none; }

/* Header Download: choose a store. */
.dl { position: relative; }
.dl-btn .chev { width: 16px; height: 16px; stroke-width: 2.4; transition: transform .2s ease; }
.dl-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }
.dl-menu {
  position: absolute; right: 0; top: calc(100% + 10px); width: 250px; padding: 8px; border-radius: 18px; z-index: 60;
  background: var(--card); box-shadow: inset 0 0 0 1px var(--line), 0 18px 50px rgba(20, 23, 8, .16);
}
.dl-menu[hidden] { display: none; }
.dl-item { display: flex; align-items: center; gap: 12px; padding: 11px 12px; border-radius: 12px; text-decoration: none; color: var(--text); }
.dl-item:hover { background: var(--card-2); }
.dl-item svg { width: 26px; height: 26px; flex: none; color: var(--text); }
.dl-item span { display: flex; flex-direction: column; line-height: 1.25; }
.dl-item b { font-size: 15px; font-weight: 650; }
.dl-item small { font-size: 12.5px; color: var(--muted); }

/* "Not out yet" note under a store button. */
.soon-pop {
  position: fixed; z-index: 80; padding: 18px 18px 16px; border-radius: 18px; color: var(--text);
  background: var(--card); box-shadow: inset 0 0 0 1px var(--line), 0 20px 60px rgba(20, 23, 8, .2);
}
.soon-pop[hidden] { display: none; }
.soon-pop b { display: block; font-family: var(--font-display); font-weight: 600; font-size: 16.5px; margin-right: 24px; }
.soon-pop p { margin: 6px 0 14px; font-size: 14.5px; color: var(--muted); }
.soon-pop .btn { min-height: 42px; font-size: 14px; width: 100%; }
.soon-pop .soon-alt { display: block; margin-top: 10px; text-align: center; font-size: 13.5px; font-weight: 600; color: var(--accent); }
.soon-x { position: absolute; top: 10px; right: 10px; width: 28px; height: 28px; border-radius: 50%; border: 0; cursor: pointer; background: var(--card-2); font-size: 18px; line-height: 1; }

/* Privacy: one message's journey. A person types it on their phone (a
   popup shows what they typed); it seals into code and travels to KEYBO
   at its laptop; KEYBO fixes it and sends it back sealed; the popup opens
   on the fixed message. site.js steps data-s 0-6. The person and KEYBO
   are the Animation session's Cycles renders. */
.journey {
  grid-column: 1 / -1; display: grid; grid-template-columns: 290px minmax(0, 1fr) 280px; align-items: end; gap: 12px;
  margin-top: 10px; padding: 26px 28px 22px; border-radius: 26px; background: rgba(255, 255, 255, .5);
}
.actor { position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.cap { font-size: 12.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: rgba(20, 23, 8, .62); text-align: center; line-height: 1.35; }
.cap small { font-weight: 600; text-transform: none; letter-spacing: 0; font-size: 12px; }
.actor-art { position: relative; width: 100%; display: grid; place-items: end center; }
/* The person and KEYBO, rendered through one camera: same size, same top,
   and they stand on one floor (soles at 624 of 720, so 13.3% hangs below). */
.clipstack { --cs: 280px; position: relative; width: var(--cs); aspect-ratio: 1; margin-bottom: calc(var(--cs) * -0.133); }
.clipstack video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; transition: opacity .14s ease; }
.clipstack .once { opacity: 0; }
.clipstack.oneshot .once { opacity: 1; }
.clipstack.oneshot .loop { opacity: 0; }

/* the popup over the person's phone */
.pop {
  position: relative; width: 100%; padding: 12px 14px 14px; border-radius: 18px; background: #fff; color: var(--ink);
  box-shadow: 0 14px 34px rgba(20, 23, 8, .16); min-height: 112px;
}
.pop::after { content: ""; position: absolute; left: 50%; bottom: -8px; width: 16px; height: 16px; margin-left: -8px; background: #fff; transform: rotate(45deg); border-radius: 3px; }
.pop-top { display: flex; align-items: center; gap: 7px; margin-bottom: 8px; font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: rgba(20, 23, 8, .5); }
.pop-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--lime-600); }
.j-bubble {
  position: relative; min-height: 3.1em; padding: 9px 12px; border-radius: 14px 14px 4px 14px; background: var(--lime); color: var(--ink);
  font-size: 14px; line-height: 1.4; overflow: hidden; overflow-wrap: anywhere; transition: background-color .3s ease, color .3s ease;
}
.j-caret { display: inline-block; width: 2px; height: 1em; margin-left: 1px; vertical-align: -2px; background: var(--ink); animation: blink 1s steps(1) infinite; }
.journey:not([data-s="0"]) .j-caret { display: none; }
.journey.sealed .j-bubble { background: var(--ink); color: #CCFA00; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12.5px; letter-spacing: .02em; }
.journey[data-s="5"] .j-bubble, .journey[data-s="6"] .j-bubble { background: #EFFCBD; }
.j-fixed { position: absolute; right: 12px; bottom: -11px; padding: 3px 9px; border-radius: 999px; background: var(--ink); color: #CCFA00; font-size: 11px; font-weight: 700; opacity: 0; transform: translateY(4px) scale(.9); transition: opacity .3s ease, transform .4s cubic-bezier(.16, 1, .3, 1); }
.journey[data-s="5"] .j-fixed, .journey[data-s="6"] .j-fixed { opacity: 1; transform: none; }

/* KEYBO's side */
.pop-ai { min-height: 0; padding: 10px 14px; text-align: center; font-size: 13.5px; font-weight: 700; }
.ai-status { display: inline-flex; align-items: center; gap: 6px; }
.journey[data-s="3"] .ai-status::after { content: ""; width: 18px; height: 6px; background: radial-gradient(circle, var(--ink) 2px, transparent 2.5px) 0 50% / 6px 6px repeat-x; animation: dots 1s steps(4) infinite; }
@keyframes dots { from { width: 0; } to { width: 24px; } }

.lane { position: relative; height: 150px; align-self: center; }
/* The encrypted tube: a dark tube from the person's phone into KEYBO's
   laptop (site.js draws it from where they stand), with code always
   streaming through it, to KEYBO along the top and back along the bottom.
   The stream carrying the message lights up; a lime lock sits midway, and
   the message itself rides the tube. */
.journey { position: relative; }
.journey .actor { z-index: 1; }
.tube { position: absolute; z-index: 0; left: 0; top: 0; overflow: visible; pointer-events: none; }
.tube-glow { fill: none; stroke: rgba(204, 250, 0, .38); stroke-width: 36; stroke-linecap: round; }
.tube-body { fill: none; stroke: #141708; stroke-width: 28; stroke-linecap: round; }
.tube-code { font: 600 9.5px ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: .08em; fill: rgba(204, 250, 0, .42); transition: fill .4s ease; }
.tube-code.back { fill: rgba(204, 250, 0, .28); }
.journey[data-s="1"] .tube-code.to, .journey[data-s="2"] .tube-code.to, .journey[data-s="4"] .tube-code.back { fill: #CCFA00; }
.pipe-lock { position: absolute; z-index: 2; left: 50%; top: 50%; width: 40px; height: 40px; transform: translate(-50%, -50%); display: grid; place-items: center; border-radius: 50%; background: #CCFA00; color: var(--ink); box-shadow: 0 0 0 5px #141708, 0 8px 18px rgba(20, 23, 8, .3); }
.pipe-lock .icon { width: 18px; height: 18px; stroke-width: 2.4; }
.journey.run .pipe-lock { animation: lockpulse 2.4s ease-in-out infinite; }
@keyframes lockpulse { 50% { box-shadow: 0 0 0 5px #141708, 0 0 0 11px rgba(204, 250, 0, .28), 0 8px 18px rgba(20, 23, 8, .3); } }
.packet {
  position: absolute; z-index: 3; top: 0; left: 0; display: inline-flex; align-items: center; gap: 7px; padding: 8px 12px; border-radius: 999px;
  background: var(--ink); color: #CCFA00; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12px; font-weight: 700; white-space: nowrap;
  box-shadow: 0 0 0 2px rgba(204, 250, 0, .5), 0 8px 20px rgba(20, 23, 8, .25);
  offset-rotate: 0deg; offset-anchor: 50% 50%; offset-distance: 6%;
  transform: scale(.6); opacity: 0;
  transition: offset-distance 1.3s cubic-bezier(.65, 0, .35, 1), transform .35s ease, opacity .3s ease;
}
.packet .icon { width: 14px; height: 14px; stroke-width: 2.4; }
.journey[data-s="2"] .packet { offset-distance: 86%; opacity: 1; transform: scale(1); }
.journey[data-s="3"] .packet { offset-distance: 86%; opacity: 0; transition: opacity .2s ease; }
.journey[data-s="4"] .packet { offset-distance: 10%; opacity: 1; transform: scale(1); transition: offset-distance 1.3s cubic-bezier(.65, 0, .35, 1) .1s, opacity .3s ease, transform .35s ease; }
.tube-cap { position: absolute; z-index: 2; transform: translate(-50%, -100%); white-space: nowrap; }

@media (max-width: 860px) {
  .journey { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding: 18px 14px; gap: 14px 10px; }
  /* person top left, KEYBO bottom right, the tube curving between them */
  .journey .you { grid-column: 1; grid-row: 1; }
  .journey .ai { grid-column: 2; grid-row: 2; margin-top: -36px; }
  .journey .lane { display: none; }
  .clipstack { --cs: 150px; }
  .pop { padding: 10px 11px 12px; min-height: 100px; }
  .pop.pop-ai { min-height: 0; padding: 9px 11px; }
  .j-bubble { font-size: 12.5px; }
  .packet { padding: 6px 9px; font-size: 10.5px; }
  .tube-glow { stroke-width: 28; }
  .tube-body { stroke-width: 22; }
  .tube-code { font-size: 7.5px; }
  .pipe-lock { width: 32px; height: 32px; }
  .pipe-lock .icon { width: 15px; height: 15px; }
  .packet .pcode { display: none; }
  .tube-cap { display: none; }
}

/* Reviews people post on the site, once approved in /admin/: a grid of
   cards, newest first, then the form. */
.reviews { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 18px; margin: 4px 0 48px; }
.reviews[hidden] { display: none; }
.rcard { display: flex; flex-direction: column; gap: 14px; padding: 22px; border-radius: 20px; background: var(--card); box-shadow: inset 0 0 0 1px var(--line), 0 10px 28px rgba(20, 23, 8, .06); }
.rcard.mine { box-shadow: inset 0 0 0 2px var(--lime-600), 0 10px 28px rgba(20, 23, 8, .06); }
.rtop { display: flex; align-items: center; gap: 12px; }
.rtop > span:nth-child(2) { min-width: 0; flex: 1; }
.rtop b { display: block; font-family: var(--font-display); font-weight: 600; font-size: 15.5px; color: var(--text); overflow-wrap: anywhere; }
.rtop small { display: block; margin-top: 1px; font-size: 13px; color: var(--muted); }
.rav { width: 42px; height: 42px; flex: none; display: grid; place-items: center; border-radius: 50%; background: var(--btn); color: var(--ink); font-family: var(--font-display); font-weight: 700; font-size: 16px; }
.rstars { flex: none; color: var(--accent); font-size: 14px; letter-spacing: 1px; }
.rcard p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--text); overflow-wrap: anywhere; }
.rnote { font-size: 12.5px; color: var(--muted); }
.reviews-more { grid-column: 1 / -1; justify-self: center; }
.review-head { margin-top: 8px; }

.review { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 48px; align-items: center; padding: 44px; border-radius: 30px; }
.review-copy h3 { font-size: clamp(28px, 3vw, 38px); font-weight: 700; letter-spacing: -0.03em; margin-bottom: 12px; }
.review-copy p { font-size: 17px; color: var(--muted); }
.review-copy p a { color: var(--text); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.review-box { padding: 26px 24px; border-radius: 22px; background: var(--bg-alt); box-shadow: inset 0 0 0 1px var(--line); }
.stars { display: flex; gap: 4px; justify-content: center; }
.stars button { width: 48px; height: 48px; padding: 6px; border: 0; border-radius: 14px; background: none; cursor: pointer; color: var(--line); transition: transform .15s ease, color .15s ease; }
.stars button svg { width: 100%; height: 100%; fill: currentColor; stroke: none; }
.stars button:hover { transform: scale(1.08); }
.stars button.on, .stars button.hover { color: var(--lime-600); }
:root[data-theme="dark"] .stars button { color: #2B2D27; }
:root[data-theme="dark"] .stars button.on, :root[data-theme="dark"] .stars button.hover { color: var(--lime); }
.review-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 18px; }
.review-fields label { display: grid; gap: 6px; font-size: 13px; font-weight: 600; color: var(--muted); }
.review-fields .wide { grid-column: 1 / -1; }
.review-fields input, .review-fields textarea {
  width: 100%; padding: 12px 14px; border-radius: 12px; border: 0; font: inherit; font-size: 15.5px; color: var(--text);
  background: var(--card); box-shadow: inset 0 0 0 1.5px var(--line); resize: vertical;
}
.review-fields input:focus, .review-fields textarea:focus { outline: none; box-shadow: inset 0 0 0 2px var(--lime-600); }
.review-fields .hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.review-msg { margin: 14px 0 0; font-size: 14.5px; color: var(--muted); min-height: 1.5em; text-align: center; }
.review-msg.ok { color: var(--accent); font-weight: 600; }
.review-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 14px; }
.review-actions [hidden] { display: none; }
.review-actions .icon { width: 18px; height: 18px; }
@media (max-width: 860px) { .review { grid-template-columns: minmax(0, 1fr); padding: 26px 20px; gap: 22px; } .review-fields { grid-template-columns: minmax(0, 1fr); } .stars button { width: 44px; height: 44px; } }

/* Small phones: the logo alone, so the theme switch, Download and menu fit. */
@media (max-width: 480px) {
  .nav { gap: 8px; }
  .site-header .brand .wordmark { display: none; }
  .nav .dl-btn { min-height: 40px; padding: 0 12px 0 14px; font-size: 14px; }
  .theme-btn, .menu-btn { width: 40px; height: 40px; }
  .dl-menu { right: -48px; }
}

/* KEYBO walking above the footer, from the Animation session's sprite
   strips (assets/keybo/walker/, 320 px cells at 24 fps, shown at 160 px so
   they are sharp on retina). site.js moves .walker along the floor with a
   transform and sets one state class; each state shows one strip. Standing
   still, KEYBO is the eyeless front with its eye layer on top, and the eyes
   follow the cursor. Feet sit at y 277 of 320, so the box hangs below the
   floor line by that margin. */
.walkway { padding: 8px 0 0; overflow: hidden; }
.walk-wrap { position: relative; }
.walk-hint { text-align: center; font-size: 14px; font-weight: 600; color: var(--muted); margin-bottom: 4px; }
.walk-floor { position: relative; height: 190px; border-bottom: 2px dashed color-mix(in srgb, var(--lime-600) 60%, transparent); }
.walker { --s: 160px; position: absolute; left: 0; bottom: calc(var(--s) * -43 / 320); width: var(--s); height: var(--s); cursor: pointer; transform: translateX(var(--x, 40px)); will-change: transform; -webkit-tap-highlight-color: transparent; outline: none; }
.walker:focus-visible .walker-body { outline: 3px solid var(--lime-600); outline-offset: -10px; border-radius: 30px; }
.walker-body, .w-front, .w-strip { position: absolute; inset: 0; }
.w-front img { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; user-select: none; }
/* Looking: the Blender look grid, 17 columns of yaw (-80..+80 in 10 deg)
   by 5 rows of pitch (+20 up .. -20 down), 320 px cells. site.js eases the
   aim like a spring and picks the cell (--lx, --ly). The legs stay planted;
   the body turns about the hips like a head on a neck. */
.w-look { position: absolute; inset: 0; display: none; background: url("../keybo/walker/look-grid.webp?v=keybo2") no-repeat; background-size: 1700% 500%; background-position: var(--lx, 50%) var(--ly, 50%); }
.walker.look .w-look { display: block; }
.walker.look .w-front { display: none; }
.w-eyes { transform: translate(var(--ex, 0px), var(--ey, 0px)); transition: transform .12s ease-out; }
.w-strip { display: none; background-repeat: no-repeat; background-size: calc(var(--n) * 100%) 100%; }
.walker-shadow { position: absolute; left: 26%; right: 26%; bottom: calc(var(--s) * 43 / 320 - 5px); height: 10px; border-radius: 50%; background: radial-gradient(closest-side, rgba(20, 23, 8, .22), transparent); }
.walker-say {
  position: absolute; left: 50%; bottom: 92%; padding: 6px 12px; border-radius: 14px; white-space: nowrap; z-index: 2;
  background: var(--ink); color: #CCFA00; font-size: 13px; font-weight: 700; transform: translate(-50%, 6px) scale(.9); opacity: 0;
  transition: opacity .2s ease, transform .25s cubic-bezier(.16, 1, .3, 1); pointer-events: none;
}
.walker-say.show { opacity: 1; transform: translate(-50%, 0) scale(1); }
:root[data-theme="dark"] .walker-say { background: var(--lime); color: var(--ink); }

/* one strip per state */
.walker.walk-r .w-front, .walker.walk-l .w-front, .walker.wobble .w-front, .walker.fall .w-front,
.walker.down .w-front, .walker.getup .w-front, .walker.dizzy .w-front,
.walker.turn-r .w-front, .walker.turn-l .w-front, .walker.unturn-r .w-front, .walker.unturn-l .w-front { display: none; }
.walker.walk-r .w-strip, .walker.walk-l .w-strip, .walker.wobble .w-strip, .walker.fall .w-strip,
.walker.down .w-strip, .walker.getup .w-strip, .walker.dizzy .w-strip,
.walker.turn-r .w-strip, .walker.turn-l .w-strip, .walker.unturn-r .w-strip, .walker.unturn-l .w-strip { display: block; }
.walker.walk-r .w-strip { --n: 16; background-image: url("../keybo/walker/walk-strip.png?v=keybo2"); animation: sprite .667s steps(16, jump-none) infinite; }
.walker.walk-l .w-strip { --n: 16; background-image: url("../keybo/walker/walk-left-strip.png?v=keybo2"); animation: sprite .667s steps(16, jump-none) infinite; }
.walker.wobble .w-strip { --n: 10; background-image: url("../keybo/walker/wobble-strip.png?v=keybo2"); animation: sprite .417s steps(10, jump-none) forwards; }
.walker.fall .w-strip { --n: 14; background-image: url("../keybo/walker/fall-strip.png?v=keybo2"); animation: sprite .583s steps(14, jump-none) forwards; }
.walker.down .w-strip { --n: 14; background-image: url("../keybo/walker/fall-strip.png?v=keybo2"); background-position-x: 100%; }
.walker.getup .w-strip { --n: 14; background-image: url("../keybo/walker/getup-strip.png?v=keybo2"); animation: sprite .583s steps(14, jump-none) forwards; }
.walker.dizzy .w-strip { --n: 20; background-image: url("../keybo/walker/dizzy-strip.png?v=keybo2"); animation: sprite .833s steps(20, jump-none) forwards; }
/* turning to face us when it stops, and back again to walk on (8 frames) */
.walker.turn-r .w-strip, .walker.unturn-r .w-strip { --n: 8; background-image: url("../keybo/walker/turn-from-right-strip.png?v=keybo2"); animation: sprite .333s steps(8, jump-none) forwards; }
.walker.turn-l .w-strip, .walker.unturn-l .w-strip { --n: 8; background-image: url("../keybo/walker/turn-from-left-strip.png?v=keybo2"); animation: sprite .333s steps(8, jump-none) forwards; }
.walker.unturn-r .w-strip, .walker.unturn-l .w-strip { animation-direction: reverse; }
/* steps(n, jump-none) lands on n positions, 0% to 100%: exactly one per frame,
   since background-position k/(n-1) of an n-cell strip is cell k. */
@keyframes sprite { from { background-position-x: 0%; } to { background-position-x: 100%; } }

.walker-dust { position: absolute; left: 50%; bottom: calc(var(--s) * 43 / 320); width: 0; height: 0; }
.walker-dust i { position: absolute; width: 16px; height: 16px; border-radius: 50%; background: color-mix(in srgb, var(--muted) 35%, transparent); opacity: 0; }
.walker.landed .walker-dust i { animation: dust .6s ease-out; }
.walker-dust i:nth-child(1) { --dx: -60px; } .walker-dust i:nth-child(2) { --dx: 0px; --dy: -24px; } .walker-dust i:nth-child(3) { --dx: 60px; }
@keyframes dust { from { opacity: .9; transform: translate(-8px, -4px) scale(.6); } to { opacity: 0; transform: translate(calc(var(--dx) - 8px), calc(var(--dy, -10px))) scale(1.6); } }
@media (max-width: 700px) { .walk-floor { height: 160px; } .walker { --s: 128px; } }

/* Real-time 3D KEYBO (keybo3d.js): a transparent layer over the whole
   window that takes no clicks (the script hit-tests KEYBO itself), so he
   can walk the full width, be carried anywhere and fall back to his floor,
   the walkway's dashed line. Below the header, above the page. */
.kb3d { position: fixed; inset: 0; width: 100vw; height: 100vh; display: block; pointer-events: none; z-index: 45; }
.kb3d-say { position: fixed; z-index: 46; left: 0; top: 0; bottom: auto; transform: translate(-50%, calc(-100% + 6px)) scale(.9); }
.kb3d-say.show { transform: translate(-50%, -100%) scale(1); }
.kb3d-dust { position: fixed; z-index: 44; width: 18px; height: 18px; margin-left: -9px; border-radius: 50%; background: color-mix(in srgb, var(--muted) 30%, transparent); pointer-events: none; animation: kbdust .7s ease-out forwards; }
@keyframes kbdust { from { opacity: .85; transform: translate(0, 0) scale(calc(var(--s) * .5)); } to { opacity: 0; transform: translate(var(--dx), -26px) scale(calc(var(--s) * 1.8)); } }

/* Works in every app: two rows of app icons sliding slowly, opposite
   ways, fading at both ends. Transforms only; paused on hover and while
   off screen. */
.apps { padding: 96px 0 24px; background: var(--bg); }
.apps .head { margin-bottom: 40px; }
.apps-rows { display: grid; gap: 14px; max-width: var(--wrap); margin: 0 auto; -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); }
.apps-row { overflow: hidden; }
.apps-track { display: flex; width: max-content; margin: 0; padding: 6px 0 4px; list-style: none; animation: apps-slide var(--t, 60s) linear infinite; will-change: transform; }
.apps-row.rev .apps-track { animation-direction: reverse; }
.apps-rows:hover .apps-track, .apps-rows.off .apps-track { animation-play-state: paused; }
@keyframes apps-slide { to { transform: translateX(-50%); } }
.app { flex: none; width: 112px; margin-right: 12px; display: grid; justify-items: center; gap: 10px; }
.app i { width: 68px; height: 68px; border-radius: 19px; display: grid; place-items: center; background: var(--c); color: var(--g, #fff); box-shadow: 0 10px 22px rgba(20, 23, 8, .12), inset 0 0 0 1px rgba(0, 0, 0, .05); }
.app.ig i { background: radial-gradient(circle at 30% 107%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285aeb 90%); color: #fff; }
.app svg { width: 34px; height: 34px; fill: currentColor; }
.app span { font-size: 13px; font-weight: 500; color: var(--muted); white-space: nowrap; }
.apps-note { margin-top: 26px; text-align: center; font-size: 13px; color: var(--muted); }
:root[data-theme="dark"] .app i { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14); }
@media (max-width: 700px) { .apps { padding-top: 72px; } .app { width: 86px; margin-right: 8px; } .app i { width: 56px; height: 56px; border-radius: 16px; } .app svg { width: 28px; height: 28px; } .app span { font-size: 12px; } }
@media (prefers-reduced-motion: reduce) { .apps-row { overflow-x: auto; } .apps-track { animation: none; } }
