:root {
  --bg: #eef0f6;
  --c1: #ff9ec4;
  --c2: #8fb8ff;
  --c3: #9ef0d2;
  --c4: #ffd08a;
  --blob-opacity: 0.8;
  --c5: #c7b6ff;
  --dot: rgb(20 24 40 / 0.16);

  --ink: #0c0e14;
  --ink-soft: rgb(12 14 20 / 0.62);

  --glass-tint: rgb(255 255 255 / 0.16);
  --glass-far: rgb(255 255 255 / 0.4);
  --glass-edge: rgb(255 255 255 / 0.35);
  --glass-hi: rgb(255 255 255 / 0.9);
  --glass-lo: rgb(255 255 255 / 0.3);
  --glass-glow: rgb(255 255 255 / 0.38);
  --glass-shadow: rgb(30 40 80 / 0.22);
  --rim-a: rgb(255 255 255 / 0.95);
  --rim-b: rgb(255 255 255 / 0.55);

  --hero: clamp(2rem, 5.6vw, 4.25rem);
  --sans: system-ui, -apple-system, "SF Pro Display", "Segoe UI", Roboto, "Helvetica Neue",
    "PingFang SC", "Hiragino Sans", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #07080c;
    --c1: #6b2bd9;
    --c2: #0d6e8c;
    --c3: #b0246a;
    --c4: #2346c9;
    --blob-opacity: 0.6;
    --c5: #3b2c8a;
    --dot: rgb(255 255 255 / 0.11);

    --ink: #fff;
    --ink-soft: rgb(255 255 255 / 0.66);

    --glass-tint: rgb(255 255 255 / 0.04);
    --glass-far: rgb(255 255 255 / 0.07);
    --glass-edge: rgb(255 255 255 / 0.1);
    --glass-hi: rgb(255 255 255 / 0.45);
    --glass-lo: rgb(255 255 255 / 0.08);
    --glass-glow: rgb(255 255 255 / 0.1);
    --glass-shadow: rgb(0 0 0 / 0.5);
    --rim-a: rgb(255 255 255 / 0.6);
    --rim-b: rgb(255 255 255 / 0.28);
  }
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Background: slow colour blobs plus a dot grid, so the glass has something to bend. */

.backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--bg);
}

.blob {
  position: absolute;
  width: 62vmax;
  height: 62vmax;
  border-radius: 50%;
  background: radial-gradient(circle, var(--c) 0%, transparent 66%);
  opacity: var(--blob-opacity);
  animation: drift 30s ease-in-out infinite alternate;
}

.b1 { --c: var(--c1); left: -18vmax; top: -22vmax; }
.b2 { --c: var(--c2); right: -22vmax; top: 4vh; animation-duration: 36s; animation-delay: -9s; }
.b3 { --c: var(--c3); left: 4vw; bottom: -30vmax; animation-duration: 33s; animation-delay: -17s; }
.b4 { --c: var(--c4); right: 6vw; bottom: -16vmax; width: 46vmax; height: 46vmax; animation-duration: 27s; animation-delay: -4s; }
.b5 { --c: var(--c5); left: 28vw; top: 18vh; width: 44vmax; height: 44vmax; animation-duration: 24s; animation-delay: -12s; animation-direction: alternate-reverse; }

@keyframes drift {
  0% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(7vmax, 4vmax, 0) scale(1.08); }
  100% { transform: translate3d(-4vmax, 7vmax, 0) scale(0.94); }
}

.dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--dot) 1.1px, transparent 1.6px);
  background-size: 24px 24px;
  mask-image: radial-gradient(ellipse at center, #000 30%, transparent 85%);
  -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 85%);
}

/* Liquid glass: blurred, saturated backdrop + bright rim + soft inner glow. */

.glass {
  position: relative;
  isolation: isolate;
  border-radius: 999px;
  background: var(--glass-tint);
  -webkit-backdrop-filter: blur(var(--glass-blur, 14px)) saturate(175%);
  backdrop-filter: blur(var(--glass-blur, 14px)) saturate(175%);
  box-shadow:
    inset 0 0 0 1px var(--glass-edge),
    inset 0 1px 0 0 var(--glass-hi),
    inset 0 -1px 0 0 var(--glass-lo),
    inset 0 0 1.1em -0.25em var(--glass-glow),
    0 0.4em 1.3em -0.35em var(--glass-shadow);
}

/* Specular rim, brightest at the top-left and bottom-right. */
.glass::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  padding: 1.5px;
  border-radius: inherit;
  background: linear-gradient(125deg, var(--rim-a) 0%, transparent 30%, transparent 70%, var(--rim-b) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

/* Surface gloss across the upper half. */
.glass::after {
  content: "";
  position: absolute;
  inset: 1px;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(120% 90% at 30% -10%, rgb(255 255 255 / 0.24), transparent 55%);
  pointer-events: none;
}

/* Language bubbles */

.stage {
  position: fixed;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}

.bubble {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.34em 0.85em 0.4em;
  font-size: var(--hero);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  white-space: nowrap;
  color: var(--ink);
  user-select: none;
  -webkit-user-select: none;
}

.stage .bubble {
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  transform-origin: 50% 50%;
  pointer-events: auto;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.stage .bubble.is-active {
  cursor: default;
}

/* Far-away bubbles: no live blur, just a slightly denser tint. */
.stage .bubble.is-far {
  background: var(--glass-far);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.bubble .word {
  position: relative;
  filter: blur(var(--dof, 0px));
  transition: filter 0.9s ease;
}

/* Page content sits above the bubbles but lets clicks through to them. */

.page {
  position: relative;
  z-index: 2;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 1rem;
  padding:
    max(16px, env(safe-area-inset-top))
    max(16px, env(safe-area-inset-right))
    max(16px, env(safe-area-inset-bottom))
    max(16px, env(safe-area-inset-left));
  pointer-events: none;
}

.page a,
.page .chip {
  pointer-events: auto;
}

.top {
  display: flex;
  justify-content: space-between;
  padding: clamp(0px, 2vw, 16px);
}

.chip {
  padding: 0.45em 0.95em;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

a.chip {
  color: inherit;
  text-decoration: none;
}

h1.bubble {
  margin: 0;
}

.hero {
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.slot {
  display: flex;
  justify-content: center;
  width: 100%;
}

.js .slot .bubble {
  visibility: hidden;
}

.lede {
  max-width: 30em;
  min-height: 1.5em;
  margin: 1.6rem 0 0;
  color: var(--ink-soft);
  font-size: clamp(1rem, 2.2vw, 1.15rem);
  transition: opacity 0.45s ease, transform 0.45s ease, filter 0.45s ease;
}

.lede.is-out {
  opacity: 0;
  transform: translateY(6px);
  filter: blur(4px);
}

.gh {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  margin-top: 1.9rem;
  padding: 0.72em 1.25em;
  color: var(--ink);
  font-size: 0.95rem;
  font-weight: 500;
  text-decoration: none;
  transition: transform 0.2s ease;
}

.gh:hover {
  transform: translateY(-1px) scale(1.03);
}

.gh:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.handle {
  font-family: var(--mono);
  font-size: 0.85em;
  color: var(--ink-soft);
}

.foot {
  text-align: center;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.filters {
  position: absolute;
  width: 0;
  height: 0;
}

@media (max-width: 640px) {
  .lede {
    min-height: 3em;
    padding: 0 8px;
  }
}

/* Short screens (landscape phones): tighten the centre so bubbles have room. */
@media (max-height: 520px) {
  :root {
    --hero: clamp(1.6rem, 8vh, 2.4rem);
  }

  .page {
    gap: 0.25rem;
  }

  .lede {
    margin-top: 0.75rem;
    font-size: 0.9rem;
  }

  .gh {
    margin-top: 0.9rem;
    padding: 0.5em 1em;
    font-size: 0.85rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .blob {
    animation: none;
  }

  .lede,
  .gh,
  .bubble .word {
    transition: none;
  }
}
