/* Kaname site: Liquid Glass over an illustrated coastal path that scrolls behind the page.
   Frosted smoky glass carries every text surface (deep blur that takes on the scenery's colour,
   white text); secondary buttons are clear glass lenses; Apple Intelligence is an iridescent
   bubble. The one call to action, Join the waitlist, is a glossy golden capsule so it never reads
   like anything else on the page. */

:root {
  color-scheme: dark;
  --ink: #ffffff;
  --ink-2: #f0f8f7;
  --aqua: #9ff0e4;
  --navy: #0e2a33;
  --radius: 34px;
  --content: 1080px;
  --font: system-ui, -apple-system, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --rounded: ui-rounded, "SF Pro Rounded", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Background illustration and its intrinsic proportions (2048 × 2048). */
  --bg-image: url("/images/bg/coastal-path-2048.webp");
  --bg-ratio: 1;
  /* Horizontal point of the image kept in view when it is wider than the screen: the cliff path. */
  --bg-focus-x: 0.55;
  /* On tall screens the image is drawn this many viewport-heights tall, so it has room to scroll. */
  --bg-overscan: 1.45;

  /* Frosted smoky glass. Brightness 0.56 with a 0.32 teal tint keeps white text at 4.9:1 and
     --ink-2 at 4.6:1 over the brightest blurred region of the illustration (see README). */
  --smoke: rgb(6 34 40 / 0.32);
  --smoke-filter: blur(30px) saturate(150%) brightness(0.56);
  --sheen: linear-gradient(150deg, rgb(255 255 255 / 0.1), rgb(255 255 255 / 0.03) 28%, rgb(255 255 255 / 0) 55%);
  --smoke-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.14),
    inset 1.5px 2px 1px -1px rgb(255 255 255 / 0.55),
    inset -1.5px -2px 2px -1px rgb(255 255 255 / 0.22),
    0 16px 40px rgb(0 30 36 / 0.18);
  --rim: linear-gradient(140deg, rgb(255 255 255 / 0.85), rgb(255 255 255 / 0.2) 26%, rgb(255 255 255 / 0.04) 55%, rgb(255 255 255 / 0.5));

  /* Clear lens: almost no tint, light concentrated in the top-left crescent. */
  --lens: radial-gradient(90% 60% at 28% 8%, rgb(255 255 255 / 0.3), rgb(255 255 255 / 0) 60%), rgb(255 255 255 / 0.04);
  --lens-filter: blur(1.5px) saturate(120%) brightness(1.03);
  --lens-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.32),
    inset 2px 3px 2px -1px rgb(255 255 255 / 0.9),
    inset -2px -3px 3px -1px rgb(255 255 255 / 0.5),
    inset 0 -12px 18px -10px rgb(0 30 40 / 0.35),
    0 8px 22px rgb(0 30 40 / 0.2);

  /* Call to action: sunlit gold with dark text (about 10:1), glossy like the glass around it. */
  --cta: linear-gradient(180deg, #ffe27d, #ffc233 55%, #f2a31b);
  --cta-ink: #2b1d02;
  --cta-shadow:
    inset 0 1px 0 rgb(255 255 255 / 0.85),
    inset 0 -2px 5px rgb(150 80 0 / 0.25),
    0 0 0 1px rgb(255 236 170 / 0.65),
    0 8px 20px rgb(220 140 20 / 0.35),
    0 0 30px rgb(255 205 90 / 0.35);

  /* Scene illustrations (index.html uses these through the sc-* classes). */
  --scene-device: #123a45;
  --scene-screen: #0b2b34;
  --scene-panel: #1f5563;
  --scene-accent: #17707e;
  --scene-glow: #9fe0d5;
  --scene-ink: rgb(14 42 51 / 0.38);
  --scene-badge: #3faa6c;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  background: #8fc3dd;
  color: var(--ink);
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

/* Background illustration. Without scroll-driven animations (or with reduced motion) it simply
   covers the screen. The parallax block below replaces this. bubble.js reads this layer's
   computed left, top, size, translate and background size/position to line up the scenery inside
   the WebGL bubble; it understands `cover` and `100% 100%`, so keep to those. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--bg-image) 55% 40% / cover no-repeat;
}

/* Parallax from the image's own size: the layer is drawn at the image's proportions, as tall as
   max(screen width ÷ ratio, overscan × screen height), and slides up by (its height − the screen
   height) over the whole page scroll. It moves slower than the page, starts at the sky and ends
   exactly at the image's bottom edge, with nothing stretched or repeated. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    body::before {
      --bg-h: max(100vw / var(--bg-ratio), 100vh * var(--bg-overscan));
      --bg-w: calc(var(--bg-h) * var(--bg-ratio));
      inset: 0 auto auto;
      left: clamp(calc(100vw - var(--bg-w)), calc(50vw - var(--bg-w) * var(--bg-focus-x)), 0px);
      width: var(--bg-w);
      height: var(--bg-h);
      background-position: 0 0;
      background-size: 100% 100%;
      animation-name: bg-parallax;
      animation-duration: auto;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: scroll(root block);
    }
  }
}

@keyframes bg-parallax {
  from {
    translate: 0 0;
  }

  to {
    translate: 0 calc(100vh - var(--bg-h));
  }
}

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

/* Holds the bubble's refraction filter; takes no space. */
.svg-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

a {
  color: var(--ink);
  text-decoration-color: rgb(159 240 228 / 0.7);
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-color: var(--ink);
}

:focus-visible {
  outline: 2px solid var(--aqua);
  outline-offset: 3px;
  border-radius: 14px;
}

h1,
h2,
h3 {
  font-family: var(--rounded);
  font-weight: 600;
  line-height: 1.12;
  margin: 0 0 0.5em;
}

h1 {
  font-size: clamp(2.3rem, 4.8vw, 3.6rem);
  letter-spacing: -0.025em;
}

h2 {
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  letter-spacing: -0.015em;
}

h3 {
  font-size: 1.15rem;
}

p {
  margin: 0 0 1em;
}

.skip-link {
  position: absolute;
  left: 1rem;
  top: -4rem;
  padding: 0.6rem 1.1rem;
  border-radius: 999px;
  background: var(--ink);
  color: var(--navy);
  font-weight: 600;
  z-index: 10;
}

.skip-link:focus {
  top: 1rem;
}

.wrap {
  width: min(100% - 2.5rem, var(--content));
  margin-inline: auto;
}

/* Frosted smoky glass: every surface that carries text. */

.panel,
.site-footer .wrap,
.prose {
  position: relative;
  background: var(--sheen), var(--smoke);
  box-shadow: var(--smoke-shadow);
  -webkit-backdrop-filter: var(--smoke-filter);
  backdrop-filter: var(--smoke-filter);
}

.panel {
  border-radius: var(--radius);
}

/* Specular rim: bright at the top-left, fading, catching light again at the bottom-right. */
.panel::after,
.site-footer .wrap::after,
.prose::after,
.scene-disc::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.25px;
  background: var(--rim);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

/* Clear lenses: the secondary buttons. */

.button.secondary {
  box-shadow: var(--lens-shadow);
  -webkit-backdrop-filter: var(--lens-filter);
  backdrop-filter: var(--lens-filter);
}

/* Header: the 要 mark and a bold wordmark straight on the sky, plain links, one golden action. */

.site-header {
  padding-block: 1.25rem;
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.brand {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 0.7rem;
  color: var(--navy);
  text-decoration: none;
}

.brand img {
  width: 46px;
  height: 46px;
  border-radius: 12px;
  box-shadow: 0 6px 18px rgb(8 60 70 / 0.3), 0 0 0 1px rgb(255 255 255 / 0.55);
}

/* Wordmark with its subtext, "Your money, Private", stacked beside the mark. */
.brand-text {
  display: grid;
  line-height: 1.05;
}

.brand-name {
  font-family: var(--rounded);
  font-size: 1.8rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  text-shadow: 0 1px 0 rgb(255 255 255 / 0.6), 0 0 18px rgb(255 255 255 / 0.75);
}

.brand-sub {
  margin-top: 0.15rem;
  font-family: var(--rounded);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-shadow: 0 1px 0 rgb(255 255 255 / 0.6), 0 0 12px rgb(255 255 255 / 0.75);
}

.site-nav ul {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav a:not(.nav-cta) {
  display: inline-block;
  padding: 0.45rem 0.8rem;
  border-radius: 999px;
  color: var(--navy);
  font-size: 0.975rem;
  font-weight: 600;
  text-decoration: none;
  text-shadow: 0 0 14px rgb(255 255 255 / 0.9);
}

.site-nav a:not(.nav-cta):hover,
.site-nav a[aria-current="page"] {
  background: rgb(255 255 255 / 0.55);
  text-decoration: underline;
}

.site-footer {
  margin-top: 4rem;
  padding-bottom: 2rem;
  color: var(--ink-2);
  font-size: 0.875rem;
}

.site-footer .wrap {
  display: grid;
  gap: 0.6rem;
  padding: 1.4rem 1.75rem;
  border-radius: 28px;
}

.site-footer ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-footer p {
  margin: 0;
}

/* Buttons: the golden call to action, and clear lens capsules for everything else. */

.button,
.nav-cta {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 999px;
  font-family: var(--font);
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.2s ease, filter 0.2s ease;
}

.button {
  min-height: 52px;
  padding: 0.8rem 1.7rem;
  font-size: 1.05rem;
  font-weight: 600;
}

.nav-cta {
  padding: 0.6rem 1.15rem;
  font-size: 0.95rem;
  white-space: nowrap;
}

.button:not(.secondary),
.nav-cta {
  background: var(--cta);
  box-shadow: var(--cta-shadow);
  color: var(--cta-ink);
  font-weight: 700;
  text-shadow: 0 1px 0 rgb(255 255 255 / 0.45);
}

/* Gloss across the top half of every capsule. */
.button::before,
.nav-cta::before {
  content: "";
  position: absolute;
  inset: 1px 1px 50%;
  z-index: -1;
  border-radius: 999px 999px 40% 40%;
  background: linear-gradient(180deg, rgb(255 255 255 / 0.4), rgb(255 255 255 / 0));
  pointer-events: none;
}

.button.secondary {
  background: radial-gradient(90% 60% at 28% 8%, rgb(255 255 255 / 0.22), rgb(255 255 255 / 0) 60%), rgb(6 34 40 / 0.22);
  color: var(--ink);
  text-shadow: 0 1px 2px rgb(0 30 40 / 0.35);
}

.button.secondary::before {
  background: linear-gradient(180deg, rgb(255 255 255 / 0.22), rgb(255 255 255 / 0));
}

.button:hover,
.nav-cta:hover {
  filter: brightness(1.06);
  transform: translateY(-1px);
}

.button:not(.secondary):hover,
.nav-cta:hover {
  color: var(--cta-ink);
}

.button.secondary:hover {
  color: var(--ink);
}

section {
  padding-block: 3.5rem;
}

.section-intro {
  max-width: 42rem;
  color: var(--ink-2);
}

/* Section titles float on their own small glass card. */
.section-head {
  display: inline-block;
  max-width: 100%;
  padding: 1.1rem 1.6rem;
  border-radius: 28px;
}

.section-head h2 {
  margin: 0;
}

.section-head .section-intro {
  margin: 0.35rem 0 0;
}

/* Hero: balanced on a portrait phone first; two columns on wide screens. */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 3rem;
  align-items: center;
  min-height: min(calc(100svh - 6.5rem), 46rem);
  padding-block: 1rem 3rem;
}

.hero-copy {
  padding: clamp(1.6rem, 4vw, 2.75rem);
}

/* On load, the first card's text rises into focus: headline, then lede, then buttons. */
.hero-copy > * {
  animation: hero-enter 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.hero-copy > :nth-child(2) {
  animation-delay: 0.18s;
}

.hero-copy > :nth-child(3) {
  animation-delay: 0.36s;
}

@keyframes hero-enter {
  from {
    opacity: 0;
    filter: blur(8px);
    transform: translateY(18px);
  }

  to {
    opacity: 1;
    filter: blur(0);
    transform: none;
  }
}

/* Phones only: the hero phone slides up from the bottom of the screen as the page opens. */
@keyframes phone-rise {
  from {
    opacity: 0;
    translate: 0 55vh;
  }

  to {
    opacity: 1;
    translate: none;
  }
}

.hero h1 {
  max-width: 14ch;
}

.lede {
  max-width: 34rem;
  color: var(--ink-2);
  font-size: 1.15rem;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.75rem;
}

/* Hero phone: the home screen from the Release app design (design/release-app), built at the
   design's 390 × 844 points and scaled with `zoom`, so every size from here to the day flow is in
   app points. The app's own scenery sits frosted behind its glass, as the design ships by
   default. The app's tokens (--ink-3, its darker --lens and so on) apply inside .screen only. */
.phone-figure {
  --phone-zoom: 0.7;
  justify-self: center;
  margin: 1rem 0;
}

@media (max-height: 820px) {
  .phone-figure {
    --phone-zoom: 0.62;
  }
}

@media (max-height: 700px) {
  .phone-figure {
    --phone-zoom: 0.54;
  }
}

.bezel {
  zoom: var(--phone-zoom);
  padding: 11px;
  border-radius: 66px;
  background: linear-gradient(145deg, #4a5a60, #121a1d 38%, #2c393d 70%, #56666c);
  box-shadow:
    0 0 0 1px rgb(255 255 255 / 0.22),
    inset 0 0 0 1px rgb(255 255 255 / 0.15),
    0 30px 60px rgb(0 20 26 / 0.45);
}

.screen {
  --ink-3: rgb(240 248 247 / 0.78);
  --hairline: rgb(255 255 255 / 0.14);
  --amber: #ffd27a;
  --tint-aqua: rgb(38 150 138 / 0.3);
  --lens: radial-gradient(90% 60% at 28% 8%, rgb(255 255 255 / 0.22), rgb(255 255 255 / 0) 60%), rgb(6 34 40 / 0.24);
  --lens-filter: blur(2px) saturate(130%) brightness(0.92);
  --margin: 16px;
  position: relative;
  isolation: isolate;
  width: 390px;
  height: 844px;
  overflow: hidden;
  border-radius: 55px;
  background: var(--navy);
  color: var(--ink);
  font: 400 17px/22px var(--font);
}

/* The app's background: the page's coastal path, frosted. */
.screen-scenery {
  position: absolute;
  inset: -40px;
  z-index: -1;
  background: var(--bg-image) 55% 40% / cover no-repeat;
  filter: blur(26px) saturate(125%) brightness(0.74);
}

/* Darkest at the top (status bar, toolbar, title), then the bottom, so white text straight on the
   scenery stays legible. */
.screen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(3 26 33 / 0.6), rgb(3 26 33 / 0.42) 30%, rgb(3 26 33 / 0.3) 62%, rgb(3 26 33 / 0.5));
  pointer-events: none;
}

.screen svg:not([width]) {
  flex: none;
  width: 20px;
  height: 20px;
}

.statusbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 8;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 54px;
  padding: 4px 30px 0 52px;
  font: 600 17px/1 var(--font);
  pointer-events: none;
}

/* Dynamic Island */
.statusbar::after {
  content: "";
  position: absolute;
  top: 11px;
  left: 50%;
  width: 124px;
  height: 36px;
  border-radius: 20px;
  background: #000;
  translate: -50% 0;
}

.statusbar .icons {
  display: flex;
  align-items: center;
  gap: 6px;
}

.home-indicator {
  position: absolute;
  bottom: 8px;
  left: 50%;
  z-index: 9;
  width: 134px;
  height: 5px;
  border-radius: 3px;
  background: rgb(255 255 255 / 0.85);
  translate: -50% 0;
}

.screen-top {
  position: absolute;
  top: 54px;
  left: 0;
  right: 0;
  z-index: 6;
  padding: 2px var(--margin) 0;
}

/* Scroll edge: content passing under the status bar and toolbar blurs out. */
.screen-edge {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  height: 116px;
  pointer-events: none;
  background: linear-gradient(rgb(3 26 33 / 0.35), rgb(3 26 33 / 0));
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  -webkit-mask: linear-gradient(#000 50%, transparent);
  mask: linear-gradient(#000 50%, transparent);
}

/* The ledger scrolls inside the phone. It is focusable so it can be scrolled from the keyboard. */
.screen-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  padding: 108px var(--margin) 48px;
  scrollbar-width: none;
}

.screen-scroll::-webkit-scrollbar {
  display: none;
}

.screen-scroll:focus-visible {
  outline-offset: -4px;
  border-radius: 55px;
}

.k-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

/* The 要 mark and a bold wordmark, as in the page header, where the app shows its status capsule. */
.k-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font: 800 24px/1 var(--rounded);
  letter-spacing: -0.02em;
  text-shadow: 0 1px 10px rgb(0 20 26 / 0.45);
}

.k-brand img {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  box-shadow: 0 6px 16px rgb(0 30 40 / 0.35), 0 0 0 1px rgb(255 255 255 / 0.5);
}

.k-glass {
  position: relative;
  border-radius: 28px;
  background: var(--sheen), var(--smoke);
  box-shadow: var(--smoke-shadow);
  -webkit-backdrop-filter: var(--smoke-filter);
  backdrop-filter: var(--smoke-filter);
}

/* Frosted glass holding work that waits on you. */
.k-glass.k-tint-aqua {
  background: var(--sheen), linear-gradient(var(--tint-aqua), var(--tint-aqua)), var(--smoke);
}

.k-glass::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.25px;
  background: var(--rim);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

.k-lens {
  position: relative;
  background: var(--lens);
  box-shadow: var(--lens-shadow);
  color: var(--ink);
  -webkit-backdrop-filter: var(--lens-filter);
  backdrop-filter: var(--lens-filter);
}

.k-btn {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  border-radius: 999px;
}

.k-btn svg {
  width: 20px;
  height: 20px;
}

/* Gloss across the top half, as on the page's capsules. */
.k-btn.k-lens::before {
  content: "";
  position: absolute;
  inset: 1px 1px 50%;
  z-index: -1;
  border-radius: 999px 999px 40% 40%;
  background: linear-gradient(180deg, rgb(255 255 255 / 0.2), rgb(255 255 255 / 0));
  pointer-events: none;
}

.k-btn--icon {
  width: 44px;
}

.k-large-title {
  margin: 0;
  font: 700 34px/41px var(--rounded);
  letter-spacing: 0.005em;
  text-shadow: 0 1px 12px rgb(0 20 26 / 0.45);
}

.k-headline {
  margin: 0;
  font: 600 17px/22px var(--font);
}

.k-page-title {
  display: grid;
  gap: 2px;
  margin: 10px 4px 20px;
}

.k-page-title p:not(.k-large-title) {
  margin: 0;
  color: var(--ink-2);
  font: 400 15px/20px var(--font);
  text-shadow: 0 1px 10px rgb(0 20 26 / 0.45);
}

/* Month groups, straight on the scenery. */
.k-section-title {
  margin: 24px 6px 8px;
  font: 600 15px/20px var(--font);
  text-shadow: 0 1px 10px rgb(0 20 26 / 0.5);
}

.k-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 16px 16px 6px;
}

.k-count {
  min-width: 26px;
  height: 26px;
  padding: 0 8px;
  border-radius: 999px;
  background: var(--aqua);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.6);
  color: var(--navy);
  font: 700 14px/26px var(--rounded);
  text-align: center;
}

.k-list {
  margin: 0;
  padding: 4px 0;
  list-style: none;
}

.k-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 64px;
  padding: 10px 16px;
}

/* Hairlines start after the glyph. */
.k-row + .k-row::before {
  content: "";
  position: absolute;
  top: 0;
  left: 68px;
  right: 0;
  height: 1px;
  background: var(--hairline);
}

.k-row-text {
  display: grid;
  flex: 1;
  gap: 2px;
  min-width: 0;
}

.k-row-text strong {
  overflow: hidden;
  font: 600 17px/22px var(--font);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.k-row-text span {
  color: var(--ink-3);
  font: 400 15px/20px var(--font);
}

.k-row > svg.k-chevron {
  width: 16px;
  height: 16px;
  color: var(--ink-3);
}

.k-amount {
  flex: none;
  font: 600 17px/22px var(--rounded);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.k-amount--in {
  color: var(--aqua);
}

/* Direction and review glyphs: flat tinted discs, never nested glass. */
.k-glyph {
  display: grid;
  flex: none;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgb(255 255 255 / 0.13);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.16);
}

.k-glyph svg {
  width: 18px;
  height: 18px;
}

.k-glyph--in,
.k-glyph--review {
  background: rgb(159 240 228 / 0.17);
  box-shadow: inset 0 0 0 1px rgb(159 240 228 / 0.32);
  color: var(--aqua);
}

.k-glyph--caution {
  background: rgb(255 210 122 / 0.17);
  box-shadow: inset 0 0 0 1px rgb(255 210 122 / 0.34);
  color: var(--amber);
}

/* How it fits. With motion allowed, the four cards become a linear carousel (see the
   no-preference block near the end): card 1 starts centred with nothing to its left, the track
   steps forward one card at a time until card 4 is centred with nothing to its right, then slides
   back to card 1 and repeats. At most three cards show at once (flow-fade). A card lands in the
   centre exactly as its scene starts. With reduced motion they stay a plain grid of still scenes.
   Each card owns a quarter of the cycle; every scene keyframe acts inside its first 25% and rests
   after it, and --delay moves a scene into its card's quarter. --i is the card's place on the
   track. Hover pauses it all. */

.flow {
  --cycle: 10s;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
  text-align: center;
}

.flow li {
  --i: 0;
  --delay: 0s;
  position: relative;
  padding: 1.75rem 1.5rem;
}

.flow li:nth-child(2) {
  --i: 1;
  --delay: calc(var(--cycle) * 0.25);
}

.flow li:nth-child(3) {
  --i: 2;
  --delay: calc(var(--cycle) * 0.5);
}

.flow li:nth-child(4) {
  --i: 3;
  --delay: calc(var(--cycle) * 0.75);
}

/* Hover pauses it all; so does .is-waiting, which flow.js sets until the row scrolls into view. */
.flow:hover li,
.flow:hover .scene *,
.flow.is-waiting li,
.flow.is-waiting .scene * {
  animation-play-state: paused;
}

.flow p {
  margin: 0;
  color: var(--ink-2);
}

/* Each scene sits in a bright lens disc, a lit window in the dark glass. */
.scene-disc {
  position: relative;
  display: grid;
  place-items: center;
  width: min(100%, 15rem);
  aspect-ratio: 1;
  margin: 0 auto 1.4rem;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 22%, #ffffff, rgb(255 255 255 / 0) 55%),
    radial-gradient(circle, rgb(236 248 246 / 0.96), rgb(196 230 225 / 0.92));
  box-shadow:
    inset 2px 3px 2px -1px #ffffff,
    inset 0 -14px 26px rgb(23 112 126 / 0.22),
    0 14px 30px rgb(0 30 36 / 0.3);
}

.scene {
  display: block;
  width: 84%;
  height: auto;
  overflow: visible;
}

.scene * {
  transform-box: fill-box;
  transform-origin: center;
}

.scene text {
  fill: var(--navy);
  font: 600 8.5px var(--font);
  text-anchor: middle;
}

.sc-device {
  fill: var(--scene-device);
}

.sc-screen {
  fill: var(--scene-screen);
}

.sc-panel {
  fill: var(--scene-panel);
}

.sc-accent {
  fill: var(--scene-accent);
}

.sc-glow {
  fill: var(--scene-glow);
}

.sc-badge {
  fill: var(--scene-badge);
}

.sc-accent-line {
  stroke: var(--scene-accent);
}

.sc-glow-line {
  stroke: var(--scene-glow);
}

.sc-ink {
  stroke: var(--scene-ink);
}

.sc-stop-accent {
  stop-color: var(--scene-accent);
}

.sc-stop-glow {
  stop-color: var(--scene-glow);
}

.sc-stop-white {
  stop-color: #ffffff;
}

/* Base styles are the still frame shown when motion is reduced. */

/* 1. A card taps the terminal, contactless waves pulse, the amount turns into a tick. */
.s1-card {
  transform: rotate(-8deg);
  animation: s1-card var(--cycle) ease-in-out var(--delay) infinite backwards;
}

.s1-wave {
  opacity: 0.7;
  animation: s1-wave var(--cycle) ease-out var(--delay) infinite backwards;
}

.s1-wave:nth-child(2) {
  animation-delay: calc(var(--delay) + 0.12s);
}

.s1-wave:nth-child(3) {
  animation-delay: calc(var(--delay) + 0.24s);
}

.scene .s1-amount {
  opacity: 0;
  fill: #ffffff;
  font-size: 10px;
  animation: s1-amount var(--cycle) linear var(--delay) infinite backwards;
}

.s1-check {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  animation: s1-check var(--cycle) ease-out var(--delay) infinite backwards;
}

@keyframes s1-card {
  0%,
  4% {
    transform: translate(0, 0) rotate(-8deg);
  }

  7.5%,
  10.5% {
    transform: translate(48px, -4px) rotate(0deg);
  }

  14.5%,
  100% {
    transform: translate(0, 0) rotate(-8deg);
  }
}

@keyframes s1-wave {
  0%,
  7.5% {
    opacity: 0;
    transform: scale(0.8);
  }

  9% {
    opacity: 1;
    transform: scale(1);
  }

  11.5%,
  100% {
    opacity: 0;
    transform: scale(1.15);
  }
}

@keyframes s1-amount {
  0%,
  9.25% {
    opacity: 1;
  }

  10%,
  23% {
    opacity: 0;
  }

  25%,
  100% {
    opacity: 1;
  }
}

@keyframes s1-check {
  0%,
  9.75% {
    opacity: 1;
    stroke-dashoffset: 1;
  }

  12%,
  22.5% {
    opacity: 1;
    stroke-dashoffset: 0;
  }

  24%,
  100% {
    opacity: 0;
    stroke-dashoffset: 0;
  }
}

/* 2. The phone buzzes, the bank alert drops in, a badge pops. */
.s2-phone {
  animation: s2-phone var(--cycle) linear var(--delay) infinite backwards;
}

.s2-buzz {
  opacity: 0.5;
  animation: s2-buzz var(--cycle) linear var(--delay) infinite backwards;
}

.s2-banner {
  animation: s2-banner var(--cycle) ease-out var(--delay) infinite backwards;
}

.s2-badge {
  animation: s2-badge var(--cycle) ease-out var(--delay) infinite backwards;
}

@keyframes s2-phone {
  0%,
  4% {
    transform: rotate(0deg);
  }

  4.75% {
    transform: rotate(-4deg);
  }

  5.5% {
    transform: rotate(4deg);
  }

  6.25% {
    transform: rotate(-3deg);
  }

  7% {
    transform: rotate(2deg);
  }

  7.75%,
  100% {
    transform: rotate(0deg);
  }
}

@keyframes s2-buzz {
  0%,
  4% {
    opacity: 0;
  }

  4.75%,
  7% {
    opacity: 1;
  }

  8.5%,
  100% {
    opacity: 0;
  }
}

@keyframes s2-banner {
  0%,
  5% {
    opacity: 1;
    transform: translateY(-44px);
  }

  7% {
    transform: translateY(3px);
  }

  8%,
  22% {
    opacity: 1;
    transform: translateY(0);
  }

  23.5% {
    opacity: 0;
    transform: translateY(0);
  }

  24%,
  100% {
    opacity: 0;
    transform: translateY(-44px);
  }
}

@keyframes s2-badge {
  0%,
  8% {
    transform: scale(0);
  }

  9.5% {
    transform: scale(1.3);
  }

  10.5%,
  22% {
    transform: scale(1);
  }

  23.5%,
  100% {
    transform: scale(0);
  }
}

/* 3. The message rides the automation path from Messages to Kaname while the gear turns. */
.s3-path {
  animation: dash-flow 0.9s linear infinite;
}

.s3-gear {
  animation: spin 5s linear infinite;
}

.s3-from {
  animation: s3-from var(--cycle) ease-out var(--delay) infinite backwards;
}

.s3-to {
  animation: s3-to var(--cycle) ease-out var(--delay) infinite backwards;
}

.s3-packet {
  transform: translate(42px, 0);
  animation: s3-packet var(--cycle) linear var(--delay) infinite backwards;
}

@keyframes dash-flow {
  to {
    stroke-dashoffset: -8;
  }
}

@keyframes s3-from {
  0%,
  4% {
    transform: scale(1);
  }

  5.5% {
    transform: scale(1.1);
  }

  7%,
  100% {
    transform: scale(1);
  }
}

/* Kaname stays slightly raised after the message arrives, until the card steps back. */
@keyframes s3-to {
  0%,
  12.8% {
    transform: scale(1);
  }

  14.5% {
    transform: scale(1.16);
  }

  16%,
  22% {
    transform: scale(1.06);
  }

  24%,
  100% {
    transform: scale(1);
  }
}

/* Points on the path's Bézier curve at t = 0, .2, .4, .6, .8, 1, relative to its start. */
@keyframes s3-packet {
  0%,
  5.5% {
    opacity: 0;
    transform: translate(0, 0);
  }

  6% {
    opacity: 1;
    transform: translate(0, 0);
  }

  7.4% {
    transform: translate(16.2px, -11.5px);
  }

  8.8% {
    transform: translate(33.3px, -5.8px);
  }

  10.2% {
    transform: translate(50.7px, 5.8px);
  }

  11.6% {
    transform: translate(67.8px, 11.5px);
  }

  13% {
    opacity: 1;
    transform: translate(84px, 0);
  }

  13.6%,
  100% {
    opacity: 0;
    transform: translate(84px, 0);
  }
}

/* 4. A light beam scans the message and the fields fly out one by one. */
.s4-scan {
  opacity: 0;
  animation: s4-scan var(--cycle) ease-in-out var(--delay) infinite backwards;
}

.s4-ring {
  animation: spin 3s linear infinite;
}

.s4-spark {
  animation: s4-spark var(--cycle) ease-out var(--delay) infinite backwards;
}

.s4-chip rect {
  fill: rgb(255 255 255 / 0.9);
  stroke: rgb(23 112 126 / 0.45);
}

.s4-chip {
  animation: s4-chip var(--cycle) ease-out var(--delay) infinite backwards;
}

.s4-chip:nth-child(2) {
  animation-delay: calc(var(--delay) + 0.25s);
}

.s4-chip:nth-child(3) {
  animation-delay: calc(var(--delay) + 0.5s);
}

.s4-chip:nth-child(4) {
  animation-delay: calc(var(--delay) + 0.75s);
}

@keyframes s4-scan {
  0%,
  3.5% {
    opacity: 0;
    transform: translateY(0);
  }

  4% {
    opacity: 1;
    transform: translateY(0);
  }

  9.5% {
    opacity: 1;
    transform: translateY(80px);
  }

  10%,
  100% {
    opacity: 0;
    transform: translateY(80px);
  }
}

@keyframes s4-spark {
  0%,
  9% {
    transform: scale(1);
  }

  10.5% {
    transform: scale(1.7);
  }

  12%,
  100% {
    transform: scale(1);
  }
}

@keyframes s4-chip {
  0%,
  10% {
    opacity: 0;
    transform: translateX(-28px);
  }

  12%,
  22.5% {
    opacity: 1;
    transform: translateX(0);
  }

  24%,
  100% {
    opacity: 0;
    transform: translateX(0);
  }
}

/* The track, shared by every card: hold, then a 6% move to the next card, three times; the last
   6% slides from card 4 all the way back to card 1. Each card is offset by its own --i, so all
   four move together as one row. */
@keyframes flow-track {
  0%,
  19%,
  100% {
    translate: calc(var(--i) * var(--step)) 0;
  }

  25%,
  44% {
    translate: calc((var(--i) - 1) * var(--step)) 0;
  }

  50%,
  69% {
    translate: calc((var(--i) - 2) * var(--step)) 0;
  }

  75%,
  94% {
    translate: calc((var(--i) - 3) * var(--step)) 0;
  }
}

/* At most three cards show at any moment: the centred one and its neighbours. With the centre at
   c (in cards), a card at distance |--i - c| is opaque at rest up to 1 and fully transparent by
   1.5, so a fourth card is never seen, even mid-slide. Stops sit where the eased track crosses
   half-cards: the midpoint of each forward slide (ease-in-out is symmetric), and 95.7%, 97% and
   98.3% of the rewind, where ease-in-out reaches 1/6, 1/2 and 5/6 of its three-card slide. Runs
   linear, alongside flow-track. */
@keyframes flow-fade {
  0%,
  19%,
  100% {
    opacity: clamp(0, 2 - var(--i), 1);
  }

  22%,
  98.3% {
    opacity: clamp(0, 1.5 - max(var(--i) - 0.5, 0.5 - var(--i)), 1);
  }

  25%,
  44% {
    opacity: clamp(0, 2 - max(var(--i) - 1, 1 - var(--i)), 1);
  }

  47%,
  97% {
    opacity: clamp(0, 1.5 - max(var(--i) - 1.5, 1.5 - var(--i)), 1);
  }

  50%,
  69% {
    opacity: clamp(0, 2 - max(var(--i) - 2, 2 - var(--i)), 1);
  }

  72%,
  95.7% {
    opacity: clamp(0, 1.5 - max(var(--i) - 2.5, 2.5 - var(--i)), 1);
  }

  75%,
  94% {
    opacity: clamp(0, var(--i) - 1, 1);
  }
}

/* Each card's own quarter: full size while centred, smaller and dimmer while beside it. Neighbours
   dim with filters, not opacity, so nothing behind them shows through. */
@keyframes flow-focus {
  0%,
  19%,
  100% {
    scale: 1;
    filter: brightness(1) saturate(1);
  }

  25%,
  94% {
    scale: 0.86;
    filter: brightness(0.72) saturate(0.85);
  }
}

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

/* Apple Intelligence: one glass card, with a small glass bubble resting in its top corner. */

.ai-copy {
  display: flow-root;
  padding: clamp(2rem, 4vw, 3rem);
}

.ai-copy h2 {
  max-width: 30rem;
}

.ai-copy .section-intro {
  margin: 0;
}

/* Apple Intelligence orb. bubble.js draws a WebGL glass blob on the canvas (see that file) and
   marks the orb .is-gl; without JavaScript or WebGL the CSS bubble below shows instead. The
   canvas leaves room around the blob for it to deform. It floats in the card's top-right corner
   and the heading wraps around it. */
.orb {
  position: relative;
  display: grid;
  float: right;
  place-items: center;
  width: 150px;
  aspect-ratio: 1;
  margin: -1.5rem -1.5rem 0.5rem 1rem;
  shape-outside: circle(38%);
}

.orb-gl {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.orb.is-gl .orb-gl {
  display: block;
}

.orb.is-gl .bubble {
  display: none;
}

/* Fallback: iridescent glass bubble in CSS, after the same reference: clear glass (see-through,
   bright rim, specular edges, refraction in Chromium) carrying the reference's reflections,
   drawn in the inline SVG: a lavender ribbon from the crown into a pool at the lower left, a pink
   patch at the crown, a red patch with a green band low on the right, each with blue and red
   fringes, and a white glint on the lower-left rim. Around them, soap-film colour swirls near
   the edge, extra patches cycle through the spectrum and a streak of light glides across the
   glass. It moves as liquid: outline, drift and tilt run on separate, unsynchronised loops, and
   the reflections swirl, drift and change colour on their own. Rim and highlights inherit the
   morphing outline, so they always hug it. */
.bubble {
  position: relative;
  isolation: isolate;
  width: 75%;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 56% 44% 52% 48% / 46% 54% 50% 50%;
  background:
    radial-gradient(circle at 30% 24%, rgb(255 255 255 / 0.18), rgb(255 255 255 / 0) 45%),
    radial-gradient(closest-side, rgb(10 16 56 / 0) 62%, rgb(10 16 56 / 0.38)),
    rgb(12 18 48 / 0.22);
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.28),
    inset 0 -14px 24px -12px rgb(10 20 60 / 0.35),
    0 0 36px rgb(130 150 255 / 0.25),
    0 20px 44px rgb(0 20 40 / 0.22);
  -webkit-backdrop-filter: blur(1px) saturate(135%) brightness(0.9);
  backdrop-filter: blur(1px) saturate(135%) brightness(0.9);
  animation:
    bubble-morph 9s ease-in-out infinite,
    bubble-float 7s ease-in-out infinite alternate,
    bubble-tilt 13s ease-in-out infinite alternate;
}

/* Real refraction where the browser can run an SVG filter on the backdrop. Only Chromium renders
   it. WebKit reports url() in backdrop-filter as supported (checked with WebKit 26.6) but does not
   render SVG backdrop filters, nor does Firefox (w3c/svgwg#1142), so both are excluded by features
   only they recognise and keep the clear glass above. */
@supports (backdrop-filter: url(#lens-round)) and (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
  .bubble {
    backdrop-filter: url(#lens-round) saturate(135%) brightness(0.9);
  }
}

.bubble span {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}

/* Reflections. Shapes are drawn in a 100 × 100 box and blurred by the SVG's own filter. */
.bubble-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.bubble-art g {
  transform-box: view-box;
  transform-origin: 50% 50%;
}

.bb-core {
  fill: rgb(224 222 255 / 0.74);
}

.bb-blue {
  fill: rgb(60 110 255 / 0.55);
}

.bb-red {
  fill: rgb(255 60 100 / 0.55);
}

.bb-pink {
  fill: rgb(255 110 140 / 0.62);
  animation: bubble-colour-pink 10s ease-in-out infinite;
}

.bb-green {
  fill: rgb(110 240 150 / 0.55);
  animation: bubble-colour-green 8s ease-in-out infinite;
}

/* Patches that cycle through the spectrum, each on its own clock. */
.bb-shift-a {
  fill: rgb(70 225 255 / 0.55);
  animation: bubble-colour-a 9s ease-in-out infinite;
}

.bb-shift-b {
  fill: rgb(255 200 80 / 0.55);
  animation: bubble-colour-b 11s ease-in-out infinite;
}

.bb-shift-c {
  fill: rgb(170 110 255 / 0.55);
  animation: bubble-colour-c 7s ease-in-out infinite;
}

.bb-smudge {
  fill: rgb(160 40 80 / 0.35);
}

.bubble-glint {
  fill: rgb(240 248 255 / 0.95);
}

.bubble-sheen {
  animation: bubble-swirl 13s ease-in-out infinite alternate;
}

.bubble-ribbon {
  animation: bubble-sway 7s ease-in-out infinite alternate;
}

.bubble-patch-top {
  animation: bubble-drift 9s ease-in-out infinite alternate;
}

.bubble-patch-low {
  animation: bubble-drift 11s ease-in-out -4s infinite alternate-reverse;
}

.bubble-patch-colour {
  animation: bubble-drift 13s ease-in-out -6s infinite alternate;
}

/* Soap-film colour: bands of cyan, gold, magenta, green, violet and orange swirling round the
   glass, strongest towards the edge, while the whole film drifts through the spectrum. */
.bubble-film {
  inset: -10%;
  border-radius: 50%;
  background: conic-gradient(
    rgb(80 220 255 / 0.45),
    rgb(255 210 90 / 0.38) 60deg,
    rgb(255 90 200 / 0.42) 120deg,
    rgb(120 255 170 / 0.38) 180deg,
    rgb(150 110 255 / 0.45) 240deg,
    rgb(255 140 90 / 0.38) 300deg,
    rgb(80 220 255 / 0.45)
  );
  -webkit-mask: radial-gradient(closest-side, transparent 55%, #000 78%, #000 90%, transparent 100%);
  mask: radial-gradient(closest-side, transparent 55%, #000 78%, #000 90%, transparent 100%);
  animation:
    spin 16s linear infinite,
    bubble-film-hue 12s linear infinite;
}

/* A reflection of light gliding across the glass every few seconds: a white streak with cyan
   and pink edges, like light catching a curved surface as it turns. */
.bubble-sweep {
  background: linear-gradient(
    115deg,
    transparent 40%,
    rgb(120 220 255 / 0.3) 46%,
    rgb(255 255 255 / 0.6) 50%,
    rgb(255 150 220 / 0.3) 54%,
    transparent 60%
  ) 100% 0 / 250% 100% no-repeat;
  animation: bubble-sweep 8s ease-in-out infinite;
}

/* Thin prismatic rim: blue on the left, teal and pink over the top, violet below, cycling. */
.bubble-rim {
  box-shadow:
    inset 3px 1px 3px -1px rgb(80 160 255 / 0.95),
    inset -3px 0 4px -1px rgb(255 90 150 / 0.9),
    inset 0 3px 4px -2px rgb(110 255 210 / 0.75),
    inset 0 -3px 5px -2px rgb(150 110 255 / 0.85),
    inset 0 0 14px rgb(140 160 255 / 0.3);
  mix-blend-mode: screen;
  animation: bubble-hue 10s linear infinite;
}

/* Specular edges: the bright white-blue crescent low on the left, softer light high on the right
   and along the top-left, as on the earlier glass lens. */
.bubble-gloss {
  box-shadow:
    inset 9px -12px 10px -9px rgb(255 255 255 / 0.95),
    inset 2px -4px 3px -2px rgb(235 245 255 / 0.9),
    inset -4px 6px 7px -5px rgb(255 255 255 / 0.65),
    inset 2px 3px 2px -1px rgb(255 255 255 / 0.55);
}

@keyframes bubble-morph {
  0%,
  100% {
    border-radius: 56% 44% 52% 48% / 46% 54% 50% 50%;
  }

  20% {
    border-radius: 62% 38% 46% 54% / 52% 44% 56% 48%;
  }

  40% {
    border-radius: 48% 52% 58% 42% / 44% 58% 42% 56%;
  }

  /* A flattened lower-left edge, as in the reference. */
  60% {
    border-radius: 54% 46% 40% 60% / 58% 42% 52% 48%;
  }

  80% {
    border-radius: 60% 40% 54% 46% / 48% 50% 58% 42%;
  }
}

@keyframes bubble-float {
  from {
    translate: -4px 6px;
  }

  to {
    translate: 5px -9px;
  }
}

@keyframes bubble-tilt {
  from {
    rotate: -6deg;
    scale: 0.98;
  }

  to {
    rotate: 7deg;
    scale: 1.03;
  }
}

@keyframes bubble-swirl {
  from {
    rotate: -8deg;
    scale: 0.97;
  }

  to {
    rotate: 10deg;
    scale: 1.05;
  }
}

@keyframes bubble-sway {
  from {
    rotate: 4deg;
    translate: -2px 1px;
  }

  to {
    rotate: -6deg;
    translate: 3px -2px;
  }
}

@keyframes bubble-drift {
  from {
    translate: -2px 2px;
    scale: 0.94;
  }

  to {
    translate: 3px -3px;
    scale: 1.06;
  }
}

@keyframes bubble-hue {
  to {
    filter: hue-rotate(1turn);
  }
}

@keyframes bubble-film-hue {
  from {
    filter: blur(6px) hue-rotate(0turn);
  }

  to {
    filter: blur(6px) hue-rotate(1turn);
  }
}

/* Waits off to the left, then crosses in about 3 seconds. */
@keyframes bubble-sweep {
  0%,
  55% {
    background-position: 100% 0;
  }

  95%,
  100% {
    background-position: 0% 0;
  }
}

@keyframes bubble-colour-pink {
  0%,
  100% {
    fill: rgb(255 110 140 / 0.62);
  }

  33% {
    fill: rgb(255 150 90 / 0.6);
  }

  66% {
    fill: rgb(220 90 255 / 0.6);
  }
}

@keyframes bubble-colour-green {
  0%,
  100% {
    fill: rgb(110 240 150 / 0.55);
  }

  50% {
    fill: rgb(80 220 255 / 0.55);
  }
}

@keyframes bubble-colour-a {
  0%,
  100% {
    fill: rgb(70 225 255 / 0.55);
  }

  33% {
    fill: rgb(160 110 255 / 0.55);
  }

  66% {
    fill: rgb(90 255 170 / 0.5);
  }
}

@keyframes bubble-colour-b {
  0%,
  100% {
    fill: rgb(255 200 80 / 0.55);
  }

  33% {
    fill: rgb(255 120 80 / 0.55);
  }

  66% {
    fill: rgb(255 90 190 / 0.55);
  }
}

@keyframes bubble-colour-c {
  0%,
  100% {
    fill: rgb(170 110 255 / 0.55);
  }

  33% {
    fill: rgb(90 255 190 / 0.5);
  }

  66% {
    fill: rgb(70 180 255 / 0.55);
  }
}

/* Facts are plain text with check marks: nothing here is clickable, so nothing looks it. */
.ai-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.6rem;
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
}

.ai-facts li {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--ink);
  font-size: 0.975rem;
  font-weight: 600;
}

.ai-facts li::before {
  content: "";
  width: 0.4rem;
  height: 0.75rem;
  margin: -0.25rem 0.1rem 0;
  border: solid var(--aqua);
  border-width: 0 2.5px 2.5px 0;
  rotate: 45deg;
}

/* What you'll need, inside the Apple Intelligence card */

.ai-need {
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgb(255 255 255 / 0.18);
}

.ai-need h3 {
  margin-bottom: 0.6rem;
  font-size: 1rem;
}

.ai-need p {
  display: flex;
  gap: 0.85rem;
  align-items: center;
  max-width: 40rem;
  margin: 0;
  color: var(--ink-2);
}

.ai-need strong {
  color: var(--ink);
  font-weight: 600;
}

.ai-need svg {
  flex: none;
  width: 24px;
  height: 24px;
  color: var(--aqua);
}

/* What Kaname is like */

.features {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.1rem;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
}

.features li {
  padding: 1.9rem;
}

.features p {
  margin: 0;
  color: var(--ink-2);
}

/* Plain line icons: decorative, never shaped like a control. */
.feature-icon {
  display: block;
  width: 30px;
  height: 30px;
  margin-bottom: 1rem;
  color: var(--aqua);
}

.feature-icon svg {
  width: 30px;
  height: 30px;
}

/* Waitlist */

#join {
  scroll-margin-top: 1rem;
}

.join {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 3rem;
  align-items: start;
  padding: clamp(1.75rem, 4vw, 3.25rem);
}

.join form {
  display: grid;
  gap: 1.1rem;
}

.field label {
  display: block;
  margin-bottom: 0.45rem;
  font-size: 0.95rem;
  font-weight: 600;
}

/* A recessed field, not a capsule, so it reads as a place to type. */
.field input[type="email"] {
  width: 100%;
  min-height: 52px;
  padding: 0.75rem 1rem;
  border: 0;
  border-radius: 14px;
  background: rgb(0 20 26 / 0.3);
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.35),
    inset 0 2px 6px rgb(0 0 0 / 0.25);
  color: var(--ink);
  font: inherit;
}

.field input[type="email"]:focus {
  box-shadow:
    inset 0 0 0 2px var(--aqua),
    inset 0 2px 6px rgb(0 0 0 / 0.25);
  outline: none;
}

.field input[type="email"]::placeholder {
  color: rgb(230 243 241 / 0.75);
}

.consent {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  align-items: start;
  color: var(--ink-2);
  font-size: 0.95rem;
}

.consent input {
  width: 20px;
  height: 20px;
  margin: 0.2rem 0 0;
  accent-color: var(--aqua);
}

.form-note {
  margin: 0;
  color: var(--ink-2);
  font-size: 0.875rem;
}

/* Hidden from people, visible to naive bots; never focusable. */
.trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Long-form pages */

.prose {
  max-width: 46rem;
  margin: 1.5rem 0 1rem;
  padding: clamp(1.6rem, 4vw, 2.75rem);
  border-radius: var(--radius);
}

.prose h2 {
  margin-top: 2.25rem;
  font-size: 1.5rem;
}

.prose li {
  margin-bottom: 0.6rem;
  color: var(--ink-2);
}

.prose p {
  color: var(--ink-2);
}

.prose strong {
  color: var(--ink);
  font-weight: 600;
}

.prose .updated {
  color: var(--ink-2);
  font-size: 0.95rem;
}

.message {
  max-width: 36rem;
  margin: 3rem auto 0;
  padding: clamp(1.75rem, 5vw, 3rem);
  text-align: center;
}

.message p {
  color: var(--ink-2);
}

@media (max-width: 960px) {
  .flow {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .features {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 860px) {
  .hero,
  .join {
    grid-template-columns: minmax(0, 1fr);
  }

  .hero {
    gap: 1.5rem;
    min-height: 0;
  }

  .hero h1 {
    max-width: none;
  }

  /* Phones and tablets: the phone first, then the headline card. */
  .phone-figure {
    --phone-zoom: 0.6;
    order: -1;
    margin: 0.5rem 0 0;
  }
}

@media (max-width: 860px) and (max-height: 640px) {
  .phone-figure {
    --phone-zoom: 0.5;
  }
}

@media (max-width: 700px) {
  .orb {
    width: 104px;
    margin: -1.25rem -1.25rem 0.25rem 0.5rem;
  }
}

@media (max-width: 560px) {
  .brand {
    gap: 0.5rem;
  }

  .brand img {
    width: 38px;
    height: 38px;
    border-radius: 10px;
  }

  .brand-name {
    font-size: 1.45rem;
  }

  .brand-sub {
    font-size: 0.72rem;
  }

  .site-nav ul {
    gap: 0.15rem;
  }

  .site-nav a:not(.nav-cta) {
    padding: 0.4rem 0.55rem;
    font-size: 0.9rem;
  }

  .nav-cta {
    padding: 0.5rem 0.85rem;
    font-size: 0.875rem;
  }

  section {
    padding-block: 2.5rem;
  }

  .lede {
    font-size: 1.08rem;
  }

  .flow,
  .features {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Phones: the header keeps the brand, its subtext and the call to action; Privacy stays in the
   footer of every page and behind the hero's "How your data is handled". With the subtext the
   three do not fit beside it below about 425 px, so it leaves a little earlier than that. */
@media (max-width: 440px) {
  .site-nav li:has(> a:not(.nav-cta)) {
    display: none;
  }
}

@media (max-width: 370px) {
  .brand-name {
    font-size: 1.3rem;
  }

  .brand-sub {
    font-size: 0.66rem;
  }
}

/* 320 px screens: the subtext cannot sit beside the call to action at a readable size, so the
   wordmark stands alone (the title and structured data still carry it). */
@media (max-width: 350px) {
  .brand-sub {
    display: none;
  }
}

/* Carousel: all four cards share one grid cell, so the row is as tall as the tallest card and
   every card matches it; each is then offset along the row by its --i. The row runs past the
   content column and is clipped only at the screen's edges (on main, which clips without becoming
   a scroll container), so neighbours slide in from off-screen instead of being cut mid-card.
   Placed after the width queries so it overrides their grid columns. */
@media (prefers-reduced-motion: no-preference) {
  main {
    overflow-x: clip;
  }

  .flow {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    padding-block: 0.5rem 1.5rem;
  }

  .flow li {
    --step: calc(100% + 1.5rem);
    grid-area: 1 / 1;
    width: min(100%, 26rem);
    translate: calc(var(--i) * var(--step)) 0;
    animation:
      flow-track var(--cycle) ease-in-out infinite,
      flow-fade var(--cycle) linear infinite,
      flow-focus var(--cycle) ease-in-out calc(var(--delay) - var(--cycle)) infinite;
  }
}

@media (max-width: 860px) and (prefers-reduced-motion: no-preference) {
  .phone-figure {
    animation: phone-rise 1s cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }
}

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

  .button,
  .nav-cta {
    transition: none;
  }

  .flow li,
  .flow .scene *,
  .hero-copy > *,
  .bubble,
  .bubble * {
    animation: none;
  }
}

/* Without transparency, glass becomes solid sea-teal panels. */
@media (prefers-reduced-transparency: reduce) {
  .panel,
  .site-footer .wrap,
  .prose,
  .button.secondary {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: #163f46;
  }

  .bubble {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgb(22 34 80 / 0.85);
  }

  .k-glass,
  .k-lens {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: #16414b;
  }
}
