@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800;900&family=Lora:wght@400;500;600;700&display=swap');

:root {
  /* ---- light, the default. Colours sampled from ChaloJi's own art. ---- */
  --bg: #FBF6FF;
  --bg-deep: #F4E9FF;
  --surface: #ffffff;
  --surface-2: #FAF5FF;
  --surface-3: #F3EAFC;
  --bubble-user: #F3EAFC;
  --line: rgba(26, 16, 48, 0.09);
  --line-soft: rgba(26, 16, 48, 0.05);
  --text: #1A1030;
  --dim: #7D6E95;
  --faint: #A99BC0;
  --green: #15B877;
  --gold: #B8860B;
  --red: #E5484D;
  --yellow: #E8A21E;
  /* the primary button is the brand gradient in light, so it needs its own ink */
  --btn: #A848FC;
  --btn-ink: #ffffff;

  /* ---- brand, the same in both themes ---- */
  --violet: #A848FC;
  --magenta: #E43CFC;
  --brand: linear-gradient(135deg, #A848FC 0%, #E43CFC 100%);
  --gold-1: #FFF2C8;
  --gold-2: #FFDF91;
  --gold-3: #FFCB5E;
  --gold-ink: #5E4408;

  --serif: 'Lora', Georgia, 'Times New Roman', serif;
  --sans: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --sky: url('../images/sky.svg');
  --shell: 480px;

  /* elevation — one ramp, so every raised surface agrees on where the light is */
  --e1: 0 1px 2px rgba(80, 40, 140, 0.07);
  --e2: 0 4px 14px -4px rgba(80, 40, 140, 0.14);
  --e3: 0 12px 34px -10px rgba(80, 40, 140, 0.18);
  --e4: 0 22px 60px -18px rgba(80, 40, 140, 0.22);

  /* motion */
  --spring: cubic-bezier(0.34, 1.4, 0.56, 1);
  --out: cubic-bezier(0.22, 1, 0.36, 1);
  --inout: cubic-bezier(0.65, 0, 0.35, 1);
  --t-page: 380ms;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
}

/* ---- dark, the palette this app shipped with, unchanged ---- */
[data-theme="dark"] {
  --bg: #0a0e14;
  --bg-deep: #070b11;
  --surface: #151a22;
  --surface-2: #1c222c;
  --surface-3: #242b36;
  --bubble-user: #272d38;
  --line: rgba(255, 255, 255, 0.11);
  --line-soft: rgba(255, 255, 255, 0.07);
  --text: #ffffff;
  --dim: #99a3b1;
  --faint: #6a7483;
  --green: #22c55e;
  --gold: #c7ab6d;
  --red: #ef6b6b;
  --yellow: #f5cf4a;
  --btn: #f6f7f8;
  --btn-ink: #11151c;

  --e1: 0 1px 2px rgba(0, 0, 0, 0.28);
  --e2: 0 4px 14px -4px rgba(0, 0, 0, 0.45);
  --e3: 0 12px 34px -10px rgba(0, 0, 0, 0.55);
  --e4: 0 22px 60px -18px rgba(0, 0, 0, 0.65);
}

/* The front door keeps its night sky whichever theme is on: it is the brand,
   and the theme is for the app behind it. */
#page-splash, #page-welcome {
  --bg: #0a0e14;
  --bg-deep: #070b11;
  --surface: #151a22;
  --surface-2: #1c222c;
  --line: rgba(255, 255, 255, 0.11);
  --line-soft: rgba(255, 255, 255, 0.07);
  --text: #ffffff;
  --dim: #99a3b1;
  --faint: #6a7483;
  --btn: #f6f7f8;
  --btn-ink: #11151c;
  color: #fff;
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body { height: 100%; overflow: hidden; overscroll-behavior: none; }

body {
  background: var(--bg-deep);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  display: flex;
  justify-content: center;
  user-select: none;
  -webkit-user-select: none;
}
.msg, .review-text, input, textarea { user-select: text; -webkit-user-select: text; }

button, input, textarea { font-family: inherit; color: inherit; border: none; background: none; outline: none; }
button { cursor: pointer; }
a { color: inherit; }

/* ============ APP SHELL ============ */
#app {
  position: relative;
  width: 100%;
  max-width: var(--shell);
  height: 100dvh;
  background: var(--bg);
  overflow: hidden;
  box-shadow: 0 0 60px rgba(0, 0, 0, 0.6);
}

.page {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  will-change: transform, opacity;
}
.page.active { display: flex; }

/* native-style push / pop transitions */
.page.in-push  { animation: pushIn  var(--t-page) var(--out) both; }
.page.out-push { animation: pushOut var(--t-page) var(--out) both; display: flex; z-index: 1; }
.page.in-pop   { animation: popIn   var(--t-page) var(--out) both; }
.page.out-pop  { animation: popOut  var(--t-page) var(--out) both; display: flex; z-index: 3; }
.page.in-fade  { animation: fadeUp  440ms var(--out) both; }
.page.out-fade { animation: fadeAway 300ms ease both; display: flex; z-index: 1; }

@keyframes pushIn  { from { transform: translate3d(100%,0,0) } to { transform: none } }
@keyframes pushOut { from { transform: none; opacity: 1 } to { transform: translate3d(-26%,0,0); opacity: .55 } }
@keyframes popIn   { from { transform: translate3d(-26%,0,0); opacity: .55 } to { transform: none; opacity: 1 } }
@keyframes popOut  { from { transform: none } to { transform: translate3d(100%,0,0) } }
@keyframes fadeUp   { from { opacity: 0; transform: translate3d(0,14px,0) scale(.985) } to { opacity: 1; transform: none } }
@keyframes fadeAway { from { opacity: 1 } to { opacity: 0 } }

/* scrim that rides along with a push */
.page-shade {
  position: absolute; inset: 0; z-index: 2;
  background: #000; opacity: 0; pointer-events: none;
}

.icon { width: 22px; height: 22px; stroke: currentColor; stroke-width: 1.7; fill: none; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.icon-sm { width: 18px; height: 18px; }
.icon-lg { width: 26px; height: 26px; }

/* ============ 1. SPLASH ============ */
#page-splash {
  background: var(--bg-deep);
  align-items: center;
  justify-content: center;
}
.splash-mark {
  font-family: var(--serif);
  font-size: clamp(34px, 11vw, 48px);
  font-weight: 500;
  letter-spacing: -0.02em;
  opacity: 0;
  animation: splashIn 1s var(--out) forwards, splashGlow 2.6s ease-in-out 1s infinite;
}
.splash-tag {
  margin-top: 10px;
  font-size: 17px;
  color: var(--dim);
  opacity: 0;
  animation: splashIn 0.9s var(--out) 0.4s forwards;
}
@keyframes splashIn {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(.96); filter: blur(6px); }
  to { opacity: 1; transform: none; filter: none; }
}
@keyframes splashGlow {
  0%, 100% { text-shadow: 0 0 0 rgba(255,255,255,0); }
  50% { text-shadow: 0 0 26px rgba(190, 214, 255, 0.35); }
}

/* ============ 2. WELCOME ============ */
#page-welcome { background: #0a1326 var(--sky) center/cover no-repeat; }
#page-welcome::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(4, 9, 19, 0.5) 0%, transparent 22%, transparent 68%, rgba(4, 9, 19, 0.5) 100%);
  pointer-events: none;
}

.social-btn {
  width: 54px; height: 54px;
  border-radius: 16px;
  display: grid; place-items: center;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  border: 2.5px solid #fff;
}
.social-btn.x { background: #000; }
.social-btn.x svg { width: 24px; height: 24px; fill: #fff; }
.social-btn.ig { background: linear-gradient(45deg, #f9ce34, #ee2a7b 45%, #6228d7); }
.social-btn.ig svg { width: 27px; height: 27px; stroke: #fff; stroke-width: 2; fill: none; }

@keyframes cardIn {
  from { opacity: 0; transform: translate3d(0, 26px, 0) scale(.86) rotate(var(--rot, 0deg)); }
  to { opacity: 1; }
}
@keyframes drift {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -11px; }
}
/* Crop tighter than the page background and grade it, so each card reads as its
   own photograph rather than showing the same sky straight through. Too tight
   and the crop lands on empty sky and goes flat, so this stays wide enough to
   keep stars and cloud edges in frame. */
/* a touch of variation so five cards do not look like five copies */

/* A print catches the light across one corner. This is what stops the card
   reading as a hole cut through to the background. */

/* twinkle + shooting star overlay */
.sky-fx { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.sky-fx::before {
  content: '';
  position: absolute; inset: 0;
  background-image:
    radial-gradient(1.6px 1.6px at 14% 12%, #fff, transparent),
    radial-gradient(1.4px 1.4px at 68% 8%,  #fff, transparent),
    radial-gradient(1.8px 1.8px at 34% 26%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 88% 22%, #fff, transparent),
    radial-gradient(1.7px 1.7px at 52% 40%, #fff, transparent),
    radial-gradient(1.4px 1.4px at 8% 44%,  #fff, transparent),
    radial-gradient(1.5px 1.5px at 78% 52%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 26% 58%, #fff, transparent);
  animation: twinkle 3.6s ease-in-out infinite alternate;
}
.sky-fx::after {
  content: '';
  position: absolute;
  top: 14%; left: -14%;
  width: 150px; height: 1.6px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.9), transparent);
  opacity: 0;
  animation: shoot 11s ease-in 3s infinite;
}
@keyframes twinkle { from { opacity: .3 } to { opacity: .95 } }
@keyframes shoot {
  0%      { opacity: 0; translate: 0 0; rotate: 16deg; }
  3%      { opacity: 1; }
  11%     { opacity: 0; translate: 128vw 36vh; rotate: 16deg; }
  100%    { opacity: 0; translate: 128vw 36vh; }
}


/* The wordmark is white and the polaroids are white, so wherever a card drifts
   behind the text the text disappears into it. This pool of shade sits between
   them and is invisible against the night sky. */
.welcome-center::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 170%;
  height: 58%;
  margin-left: -85%;
  background: radial-gradient(58% 64% at 50% 74%, rgba(4, 9, 19, 0.8), rgba(4, 9, 19, 0) 72%);
  pointer-events: none;
}
@keyframes riseIn {
  from { opacity: 0; transform: translate3d(0, 16px, 0); filter: blur(4px); }
  to { opacity: 1; transform: none; filter: none; }
}

.welcome-cta {
  position: relative;
  z-index: 4;
  margin: 0 auto 14px;
  background: var(--btn);
  color: var(--btn-ink);
  border-radius: 999px;
  padding: 17px 38px;
  font-size: 18px;
  font-weight: 500;
  display: flex; align-items: center; gap: 11px;
  box-shadow: var(--e4), 0 1px 0 rgba(255, 255, 255, 0.5) inset;
  transition: transform 180ms var(--spring), box-shadow 180ms ease;
  animation: ctaIn 760ms var(--spring) 780ms both;
}
.welcome-cta::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.45);
  animation: ctaPulse 3s ease-out 2s infinite;
}
.welcome-cta:active { transform: scale(0.95); box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45); }

/* landing footer — business, pricing and policy links for the public page */
.home-foot {
  position: relative;
  z-index: 4;
  text-align: center;
  padding: 0 16px calc(14px + var(--safe-b));
  animation: ctaIn 760ms var(--spring) 900ms both;
}
.home-foot-plan {
  font-size: 12px;
  color: rgba(255,255,255,0.72);
  text-shadow: 0 1px 8px rgba(0,0,0,0.6);
  margin-bottom: 9px;
  line-height: 1.6;
}
.home-foot-plan b { color: #fff; font-weight: 650; }
.home-foot-plan .hf-dot { opacity: .45; margin: 0 5px; }
.home-foot-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 5px 15px;
  margin-bottom: 9px;
}
.home-foot-links a {
  font-size: 12.5px;
  color: rgba(255,255,255,0.62);
  text-decoration: none;
  text-shadow: 0 1px 8px rgba(0,0,0,0.6);
  padding: 2px 0;
}
.home-foot-links a:active { color: #fff; }
.home-foot-brand {
  font-size: 11.5px;
  color: rgba(255,255,255,0.42);
  text-shadow: 0 1px 8px rgba(0,0,0,0.6);
  letter-spacing: .2px;
}
.home-foot-brand b { color: rgba(255,255,255,0.72); font-weight: 600; }

@media (max-height: 700px) {
  .welcome-cta { padding: 14px 32px; font-size: 16px; }
  .home-foot-plan { font-size: 11px; }
}
/* tap-to-play welcome recording — deliberately quieter than .welcome-cta:
   glass instead of solid white, and a slower, softer ring */
.welcome-note {
  position: relative;
  z-index: 4;
  margin: 0 auto 16px;
  display: flex; align-items: center; gap: 10px;
  padding: 11px 20px 11px 12px;
  border-radius: 999px;
  border: 1px solid rgba(232,183,48,.45);
  background: rgba(255,255,255,0.10);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: rgba(255,255,255,0.92);
  font-size: 14px;
  font-weight: 500;
  text-shadow: 0 1px 8px rgba(0,0,0,0.5);
  animation: ctaIn 760ms var(--spring) 860ms both;
  transition: transform 180ms var(--spring), background 200ms ease;
}
.welcome-note:active { transform: scale(0.96); background: rgba(255,255,255,0.16); }
.welcome-note::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  box-shadow: 0 0 0 0 rgba(232,183,48,.4);
  animation: notePulse 4s ease-out 2.6s infinite;
}
.welcome-note.playing::after { animation: none; }
.wn-play {
  width: 28px; height: 28px; flex-shrink: 0; border-radius: 50%;
  background: #e8b730; color: var(--btn-ink);
  display: grid; place-items: center;
}
.wn-play svg { width: 14px; height: 14px; grid-area: 1 / 1; }
.wn-ic-pause { opacity: 0; }
.welcome-note.playing .wn-ic-play { opacity: 0; }
.welcome-note.playing .wn-ic-pause { opacity: 1; }
.wn-time { font-size: 12px; opacity: .6; font-variant-numeric: tabular-nums; }
@keyframes notePulse {
  0%   { box-shadow: 0 0 0 0 rgba(232,183,48,.35); }
  70%  { box-shadow: 0 0 0 14px rgba(232,183,48,0); }
  100% { box-shadow: 0 0 0 0 rgba(232,183,48,0); }
}
@media (prefers-reduced-motion: reduce) { .welcome-note::after { animation: none; } }
@media (max-height: 700px) { .welcome-note { padding: 9px 16px 9px 10px; font-size: 13px; } }

.welcome-cta .hand { display: inline-block; font-size: 21px; animation: wave 2.6s ease-in-out 2s infinite; transform-origin: 70% 80%; }
@keyframes ctaIn { from { opacity: 0; transform: translate3d(0, 22px, 0) scale(.9); } to { opacity: 1; transform: none; } }
@keyframes ctaPulse {
  0%   { box-shadow: 0 0 0 0 rgba(255,255,255,.35); }
  70%  { box-shadow: 0 0 0 18px rgba(255,255,255,0); }
  100% { box-shadow: 0 0 0 0 rgba(255,255,255,0); }
}
@keyframes wave {
  0%, 60%, 100% { transform: rotate(0deg); }
  10%, 30%, 50% { transform: rotate(14deg); }
  20%, 40%      { transform: rotate(-8deg); }
}

/* ============ 3. LOGIN ============ */
#page-login { background: var(--bg-deep); padding: 0 20px; }

.login-top { padding-top: 52px; text-align: center; }
.tilt-card {
  width: 112px; height: 112px;
  margin: 0 auto;
  border-radius: 22px;
  overflow: hidden;
  transform: rotate(-5deg);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.6);
  animation: cardIn 760ms var(--spring) 60ms both, drift 9s ease-in-out 9s infinite;
}
.tilt-card img { width: 100%; height: 100%; object-fit: cover; }

.login-title {
  font-family: var(--serif);
  font-size: clamp(30px, 9.5vw, 40px);
  font-weight: 500;
  color: #d6dbe2;
  margin-top: 22px;
  letter-spacing: -0.01em;
  animation: riseIn 640ms var(--out) 180ms both;
}
.login-sub { font-size: 17px; color: var(--faint); margin-top: 2px; animation: riseIn 640ms var(--out) 260ms both; }
.waved { margin-top: 22px; font-size: 16px; color: var(--dim); display: flex; align-items: center; justify-content: center; gap: 10px; animation: riseIn 640ms var(--out) 350ms both; }
.waved b { font-size: 19px; font-weight: 400; display: inline-block; animation: wave 2.6s ease-in-out 1.2s infinite; transform-origin: 70% 80%; }
.login-bottom > * { animation: riseIn 620ms var(--out) both; }
.login-bottom > *:nth-child(1) { animation-delay: 700ms; }
.login-bottom > *:nth-child(2) { animation-delay: 790ms; }
.login-bottom > *:nth-child(3) { animation-delay: 870ms; }

/* This box absorbs whatever height is left between the title block and the
   buttons. Pinned to the top it left a tall empty band; centred, the greeting
   holds the middle of the screen and the page reads as one column. */
.greet-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* a column flex parent stretches its children, which blew the bubble out to
     the full width; it is meant to hug its text */
  align-items: flex-start;
  padding: 0 0 6%;
}
.greet-bubble {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.02));
  border: 1px solid var(--line);
  border-radius: 17px 17px 17px 6px;
  box-shadow: var(--e2);
  padding: 15px 19px;
  font-size: 17px;
  color: #d7dde5;
  display: inline-block;
  opacity: 0;
  animation: bubbleIn 0.5s ease 0.5s forwards;
}
@keyframes bubbleIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

.login-bottom { flex: none; padding-bottom: 26px; }
.btn-google {
  width: 100%;
  background: var(--btn);
  color: #1a1f27;
  border-radius: 999px;
  padding: 18px;
  font-size: 18px;
  font-weight: 500;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  transition: transform 0.15s;
}
.btn-google { box-shadow: var(--e3); }
.btn-google:active { transform: scale(0.98); box-shadow: var(--e1); }
.btn-google:disabled { opacity: 0.5; pointer-events: none; }
.g-mark { width: 22px; height: 22px; }

/* At --dim on this background it read as a greyed-out button rather than the
   second way in. */
.link-phone { display: block; width: 100%; text-align: center; margin-top: 22px; font-size: 17px; font-weight: 500; color: #c6ceda; }
.link-phone:active { color: #fff; }
.legal { margin-top: 26px; text-align: center; font-size: 11.5px; color: var(--faint); line-height: 1.6; opacity: 0.7; }
.legal a { text-decoration: underline; }

/* ============ BOTTOM SHEET ============ */
.sheet-scrim {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 60;
  opacity: 0; visibility: hidden;
  transition: opacity 0.25s;
  display: flex; align-items: flex-end;
}
.sheet-scrim.show { opacity: 1; visibility: visible; }
.sheet {
  width: 100%;
  background: #0d1219;
  border: 1px solid var(--line);
  border-radius: 26px;
  margin: 10px;
  padding: 24px 22px 26px;
  transform: translateY(16px);
  transition: transform 0.28s cubic-bezier(.2,.9,.3,1);
}
.sheet-scrim.show .sheet { transform: none; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 26px; }
.sheet-head > .icon { width: 28px; height: 28px; stroke-width: 1.6; }
.btn-x { width: 46px; height: 46px; border-radius: 50%; background: var(--surface-2); display: grid; place-items: center; }
.sheet-title { font-family: var(--serif); font-size: 27px; font-weight: 500; margin-bottom: 20px; }

.phone-field { display: flex; align-items: center; background: var(--surface); border-radius: 999px; padding: 0 20px; height: 58px; }
.cc { font-size: 17px; color: #e4e8ee; padding-right: 14px; border-right: 1px solid var(--line); }
.phone-field input { flex: 1; padding-left: 14px; font-size: 17px; }
.phone-field input::placeholder { color: var(--faint); }
.field-hint { text-align: center; font-size: 14.5px; color: var(--dim); margin: 16px 0 20px; }

.btn-white {
  width: 100%;
  background: var(--btn);
  color: #1a1f27;
  border-radius: 999px;
  padding: 17px;
  font-size: 18px;
  font-weight: 500;
  transition: transform 0.15s;
}
.btn-white:active { transform: scale(0.98); }
.btn-white:disabled { opacity: 0.5; pointer-events: none; }

.otp-row { display: flex; gap: 8px; justify-content: center; margin-bottom: 20px; }
.otp-box { width: 44px; height: 54px; background: var(--surface); border-radius: 12px; text-align: center; font-size: 22px; font-weight: 500; }

/* ============ 4. CHAT ============ */
/* The admin's wallpaper sits on its own layer so the slider can fade it
   without touching anything else. No image set and the class is absent, so
   this costs nothing. */
#page-chat.has-bg::before {
  content: '';
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background-image: var(--chat-bg-image);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: var(--chat-bg-opacity, 0.3);
  z-index: 0;
  pointer-events: none;
}
/* The conversation has to sit above that layer. The header and composer carry
   their own stacking already. */
#page-chat .msgs { position: relative; z-index: 1; }
#page-chat .composer { position: relative; z-index: 2; }

/* A messaging app has a wallpaper, not a flat fill. This one is just a few
   very low-contrast dots and a warm pool of light near the top, so it reads
   as a surface without ever competing with the text on top of it. */
#page-chat {
  background:
    radial-gradient(90% 44% at 50% 0%, rgba(74, 94, 134, 0.26), rgba(10, 14, 20, 0) 62%),
    radial-gradient(1.5px 1.5px at 18% 22%, rgba(255, 255, 255, 0.05), transparent),
    radial-gradient(1.5px 1.5px at 72% 38%, rgba(255, 255, 255, 0.045), transparent),
    radial-gradient(1.5px 1.5px at 42% 66%, rgba(255, 255, 255, 0.05), transparent),
    radial-gradient(1.5px 1.5px at 86% 78%, rgba(255, 255, 255, 0.04), transparent),
    var(--bg);
  background-size: auto, 190px 190px, 230px 230px, 170px 170px, 210px 210px, auto;
}

.chat-head {
  position: relative;
  flex: none;
  padding: calc(10px + var(--safe-t)) 12px 10px;
  display: flex; align-items: center; gap: 11px;
  z-index: 5;
  animation: headIn 620ms var(--out) both;
}
@keyframes headIn { from { opacity: 0; transform: translate3d(0, -18px, 0); } to { opacity: 1; transform: none; } }
/* The sky photo used to bleed 96px down behind the header and fade out over
   the first messages, which made the top of every conversation busy. A
   messaging header is flat: one surface, one hairline. */
.chat-head::before {
  content: '';
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background: rgba(14, 19, 27, 0.92);
  z-index: -2;
}
.chat-head::after {
  content: '';
  position: absolute;
  top: auto; right: 0; bottom: 0; left: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.08);
  z-index: -1;
}

/* Round, in a gradient ring — the shape people already read as "a person you
   message", rather than a rounded-square app tile. */
.head-av {
  position: relative;
  width: 44px; height: 44px;
  flex: none;
  border-radius: 50%;
  border: 0;
  padding: 2px;
  background: linear-gradient(135deg, #f5a623, #e8457f 42%, #b83ad6 78%, #6a4bff);
  animation: none;
  transition: transform 200ms var(--spring);
}
.head-av:active { transform: scale(0.93); }
.head-av img {
  width: 100%; height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  border: 2px solid #0e131b;
}
@keyframes avatarGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(199, 171, 109, 0); }
  50%      { box-shadow: 0 0 18px 1px rgba(199, 171, 109, 0.3); }
}
.dot {
  position: absolute;
  right: -1px; bottom: -1px;
  width: 13px; height: 13px;
  border-radius: 50%;
  background: var(--green);
  border: 2.5px solid #0e131b;
}
.dot::after {
  content: '';
  position: absolute; inset: -2px;
  border-radius: 50%;
  animation: livePulse 2.4s ease-out infinite;
}
.dot.off { background: #5d6673; }
.dot.off::after { animation: none; }
@keyframes livePulse {
  0%   { box-shadow: 0 0 0 0 rgba(34, 197, 94, .6); }
  70%  { box-shadow: 0 0 0 9px rgba(34, 197, 94, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); }
}

.head-meta { flex: 1; min-width: 0; }
/* Sans, not the display serif: this is a contact name in a message list. */
.head-name {
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.head-sub { display: flex; align-items: center; gap: 6px; margin-top: 1px; }
.premium-badge { display: inline-flex; align-items: center; gap: 3px; color: #e8b730; font-size: 11px; font-weight: 600; letter-spacing: 0.3px; }
.premium-badge svg { flex-shrink: 0; }
.head-status {
  font-size: 12.5px;
  color: #93d8a8;
  display: inline-flex; align-items: center; gap: 5px;
}
.head-status::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--green);
}
.head-status.off { color: var(--faint); }
.head-status.off::before { background: #5d6673; }

/* No filled circles. On a flat header the icons carry themselves, and three
   of them in a row stop looking like three buttons competing for the tap. */
.head-btn {
  width: 38px; height: 38px;
  flex: none;
  border-radius: 50%;
  background: none;
  border: 0;
  display: grid; place-items: center;
  color: #dfe5ee;
}
.head-btn:active { background: rgba(255, 255, 255, 0.1); }
.head-btn .icon { width: 23px; height: 23px; stroke-width: 1.7; }

/* It used to hang over the first messages as a big white pill. As a quiet
   chip directly under the header it stops fighting the conversation. */
.hangout-pill {
  position: relative;
  top: auto; left: auto;
  transform: none;
  flex: none;
  z-index: 6;
  margin: 8px auto 2px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #e7ecf3;
  border-radius: 999px;
  padding: 7px 15px;
  font-size: 13px;
  white-space: nowrap;
  max-width: calc(100% - 32px);
  display: flex; align-items: center; gap: 7px;
  box-shadow: none;
}
.hangout-pill:active { background: rgba(255, 255, 255, 0.14); }
.hangout-pill .icon-sm { width: 15px; height: 15px; }
.hangout-pill span { overflow: hidden; text-overflow: ellipsis; }

.menu-scrim { position: absolute; inset: 0; z-index: 40; opacity: 0; visibility: hidden; transition: opacity 0.18s; }
.menu-scrim.show { opacity: 1; visibility: visible; }
.menu-card {
  position: absolute;
  top: 80px; right: 14px;
  width: 234px;
  background: #0f141c;
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: 10px 0;
  box-shadow: 0 20px 44px rgba(0, 0, 0, 0.6);
  transform-origin: top right;
  transform: scale(0.9);
  opacity: 0;
  transition: 0.18s;
}
.menu-scrim.show .menu-card { transform: none; opacity: 1; }
.menu-item {
  width: 100%;
  display: flex; align-items: center; gap: 18px;
  padding: 15px 22px;
  font-size: 16.5px;
  color: #e3e8ee;
  text-align: left;
}
.menu-item:active { background: rgba(255, 255, 255, 0.05); }
.menu-item.danger { color: var(--red); }

.menu-links {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  padding: 14px 22px 16px;
  margin-top: 6px;
  border-top: 1px solid var(--line);
}
.menu-links a { font-size: 13px; color: var(--faint); }

.msgs {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px 8px;
}
/* Grouping: a run from one side stays tight, and a change of speaker opens a
   real gap. The gap does the work that avatars and tails do elsewhere. */
.msgs > .msg-ai + .msg-user,
.msgs > .msg-user + .msg-ai { margin-top: 8px; }
.msgs > .sys-note + .msg { margin-top: 2px; }
/* the last bubble needs clearance for its own meta row above the composer */
.msgs > .msg:last-child { margin-bottom: 20px; }
/* justify-content: flex-end used to sit here. It pins the list to the bottom,
   but once the list is taller than the box the overflow goes off the TOP, and
   that direction is not scrollable � the oldest messages become unreachable.
   An auto top margin on the first row pins it the same way and still scrolls. */
.msgs > *:first-child { margin-top: auto; }
.msgs::-webkit-scrollbar { width: 0; }

/* Centred chip, the way a date divider sits in a thread. */
.sys-note {
  flex-shrink: 0;
  align-self: center;
  font-size: 11.5px;
  color: #9aa5b4;
  display: flex; align-items: center; gap: 7px;
  margin: 6px 0 10px;
  padding: 5px 13px;
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 999px;
}
.sys-note b { font-size: 14px; font-weight: 400; }

.msg {
  max-width: 78%;
  /* .msgs is a flex column, so every bubble is a flex item and shrinks along
     the main axis once the list overflows. A text bubble only loses a little;
     the image bubble gets crushed to a few pixels. Nothing here should shrink. */
  flex-shrink: 0;
  font-size: 17px;
  line-height: 1.4;
  word-wrap: break-word;
  animation: msgIn 440ms var(--spring) both;
}
@keyframes msgIn {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(.94); }
  to   { opacity: 1; transform: none; }
}
.msg-ai {
  align-self: flex-start;
  border: 1px solid rgba(255, 255, 255, 0.075);
  border-radius: 20px 20px 20px 7px;
  padding: 10px 15px;
  color: #f0f3f7;
  transform-origin: left bottom;
  background: #252e3c;
  box-shadow: var(--e1);
}
/* Your side carries the brand colour, the way the accent bubble does in every
   messenger people already use. It is the fastest way to tell the two sides
   apart without reading a word. Pulled back from the full-saturation version:
   long messages sat on it badly. */
.msg-user {
  align-self: flex-end;
  background: linear-gradient(120deg, #b03a79, #7d3bb8 60%, #5244cf);
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-radius: 20px 20px 7px 20px;
  padding: 10px 15px;
  color: #fff;
  position: relative;
  transform-origin: right bottom;
  box-shadow: 0 8px 20px -10px rgba(125, 59, 184, 0.7);
}
/* The clock line hangs under the bubble on its own row. Inside the text it
   read as part of the sentence; underneath it reads as what it is — a receipt
   for the message above it. */
.msg { position: relative; }
.msg-meta {
  position: absolute;
  bottom: -16px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  line-height: 1;
  white-space: nowrap;
  user-select: none;
  color: #7d8796;
}
.msg-ai .msg-meta { left: 8px; }
.msg-user .msg-meta { right: 8px; }
/* the row underneath needs room, or the next bubble sits on top of it */
.msgs > .msg { margin-bottom: 17px; }

/* Thin strokes and round caps: a chunky tick reads as a bullet point, not a
   receipt. Width tracks the 17x11 viewBox so the pair is never squashed. */
.ticks {
  position: static;
  width: 17px; height: 11px;
  flex: none;
  stroke: #9aa5b4; stroke-width: 1.85; fill: none;
  stroke-linecap: round; stroke-linejoin: round;
  transition: stroke 240ms ease;
}
/* Sent: the single centred mark. Delivered: it gives way to the overlapping
   pair and the whole thing turns blue. Swapping whole paths keeps each state
   correctly centred instead of one mark drifting sideways. */
.ticks .t0 { opacity: 1; transition: opacity 180ms ease; animation: tickDraw 420ms var(--out) both; stroke-dasharray: 24; }
.ticks .t1,
.ticks .t2 { opacity: 0; }

.ticks.delivered { stroke: #53bdf5; }
.ticks.delivered .t0 { opacity: 0; }
.ticks.delivered .t1,
.ticks.delivered .t2 { opacity: 1; animation: tickDraw 360ms var(--out) both; stroke-dasharray: 24; }
.ticks.delivered .t2 { animation-delay: 60ms; }

/* On your own bubble the meta sits on the accent gradient, so the sent state
   needs to be light enough to read against it. */
.msg-user .ticks { stroke: rgba(255, 255, 255, 0.72); }
.msg-user .ticks.delivered { stroke: #7fd4ff; }
@keyframes tickDraw {
  from { stroke-dashoffset: 22; opacity: 0; }
  to   { stroke-dashoffset: 0; opacity: 1; }
}

/* A bubble with three bouncing dots, like the thing it is imitating. The
   swirl goes; the shimmering label stays, because "waking up..." is hers. */
.typing {
  flex-shrink: 0;
  align-self: flex-start;
  display: none;
  align-items: center;
  gap: 10px;
  margin: 8px 0 20px;
  padding: 12px 16px;
  background: #252e3c;
  border: 1px solid rgba(255, 255, 255, 0.075);
  border-radius: 20px 20px 20px 7px;
}
.typing.show { display: flex; animation: msgIn 360ms var(--out) both; }
.typing-swirl { display: none; }
/* one element, three dots: the other two are box-shadows of the first */
.typing::before {
  content: '';
  width: 7px; height: 7px;
  /* The other two dots are box-shadows, so they paint outside this element's
     7px of layout width. Without room reserved for them the label sat on top
     of them. 24px reaches the last dot, and the flex gap adds the breathing
     room after it. */
  margin-right: 26px;
  border-radius: 50%;
  background: #aab4c2;
  box-shadow: 12px 0 0 #aab4c2, 24px 0 0 #aab4c2;
  animation: typeBounce 1.25s ease-in-out infinite;
}
@keyframes typeBounce {
  0%, 60%, 100% { opacity: .35; transform: translateY(0); }
  30%           { opacity: 1;   transform: translateY(-3px); }
}
@keyframes swirl { to { stroke-dashoffset: -32; } }
.typing-text {
  font-size: 13.5px;
  background: linear-gradient(90deg, #6d7684 18%, #ffffff 50%, #6d7684 82%) 0 0 / 220% 100%;
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  animation: shimmer 2.1s linear infinite;
}
@keyframes shimmer { to { background-position: -220% 0; } }

.composer {
  flex: none;
  padding: 9px 12px calc(12px + var(--safe-b));
  display: flex; align-items: center; gap: 10px;
  background: rgba(10, 14, 20, 0.92);
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  animation: ctaIn 620ms var(--spring) 180ms both;
}
.composer-bar {
  flex: 1;
  display: flex; align-items: center; gap: 9px;
  background: #1a2029;
  border-radius: 999px;
  padding: 6px 7px 6px 6px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  transition: border-color 220ms ease, background-color 220ms ease;
}
.composer-bar { box-shadow: var(--e1); }
.composer-bar:focus-within { border-color: rgba(255, 255, 255, 0.18); background: #19202a; box-shadow: var(--e2); }
.round-btn { width: 42px; height: 42px; flex: none; border-radius: 50%; background: var(--surface-3); display: grid; place-items: center; }
.round-btn:active { background: #303845; }
/* the one button that sends gets the same colour as your bubbles */
.mic-send {
  background: linear-gradient(118deg, #c2387f, #8d3bc4 60%, #5b47e0);
  color: #fff;
  box-shadow: 0 6px 16px -6px rgba(141, 59, 196, 0.75);
}
.mic-send:active { background: linear-gradient(118deg, #a92f6f, #7a31ab 60%, #4c3bc4); }

/* voice note bubble */
/* A text bubble is readable on the faint .msg-ai gradient because of its text;
   a voice note has none, so it needs a surface of its own to read as a bubble. */
.msg-voice {
  display: flex; align-items: center; gap: 11px;
  min-width: 200px; max-width: 290px; padding: 11px 14px;
  background: rgba(255,255,255,0.07);
}
.vn-play {
  width: 36px; height: 36px; flex-shrink: 0; border: 0; border-radius: 50%;
  background: rgba(255,255,255,0.22); color: #fff; cursor: pointer;
  display: grid; place-items: center; transition: background 180ms ease, transform 180ms ease;
}
.vn-play:active { transform: scale(0.93); }
.vn-play svg { width: 17px; height: 17px; grid-area: 1 / 1; }
.vn-ic-pause { opacity: 0; }
.msg-voice.playing .vn-ic-play { opacity: 0; }
.msg-voice.playing .vn-ic-pause { opacity: 1; }
.vn-body { flex: 1; min-width: 0; }
.vn-bar { height: 4px; border-radius: 3px; background: rgba(255,255,255,0.16); overflow: hidden; }
.vn-fill { height: 100%; width: 0%; border-radius: 3px; background: currentColor; opacity: .85; transition: width 120ms linear; }
.vn-time { font-size: 11px; opacity: .65; margin-top: 5px; font-variant-numeric: tabular-nums; }

/* stays lit until it has been listened to */
.msg-voice.unplayed { box-shadow: 0 0 0 2px rgba(232,183,48,.75); animation: vnGlow 1.8s ease-in-out infinite; }
.msg-voice.unplayed .vn-play { background: #e8b730; color: var(--btn-ink); }
@keyframes vnGlow {
  0%, 100% { box-shadow: 0 0 0 2px rgba(232,183,48,.75), 0 0 0 0 rgba(232,183,48,.45); }
  50% { box-shadow: 0 0 0 2px rgba(232,183,48,.75), 0 0 0 9px rgba(232,183,48,0); }
}
@media (prefers-reduced-motion: reduce) { .msg-voice.unplayed { animation: none; } }

/* mic morphs into send when there's text */
.mic-send { position: relative; transition: background-color 240ms ease, transform 240ms var(--spring); }
.mic-send .ic-mic, .mic-send .ic-send {
  grid-area: 1 / 1;
  transition: opacity 220ms ease, transform 300ms var(--spring);
}
.mic-send .ic-send { opacity: 0; transform: rotate(-35deg) scale(.6); }
.mic-send.is-send { background: var(--btn); transform: scale(1.04); }
.mic-send.is-send .ic-mic { opacity: 0; transform: scale(.6); }
.mic-send.is-send .ic-send { opacity: 1; transform: none; stroke: #11151c; }
/* pulses while the mic is actually picking up speech */
.mic-send.listening { background: #e8b730; animation: micPulse 1.4s ease-in-out infinite; }
.mic-send.listening .ic-mic { stroke: #11151c; opacity: 1; transform: none; }
@keyframes micPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(232, 183, 48, 0.55); }
  50% { box-shadow: 0 0 0 10px rgba(232, 183, 48, 0); }
}
.composer-bar textarea { flex: 1; resize: none; font-size: 17px; max-height: 96px; padding: 11px 0; line-height: 1.35; }
.composer-bar textarea::placeholder { color: var(--faint); }

/* ============ MODALS ============ */
.modal-scrim {
  position: absolute; inset: 0; z-index: 70;
  background: rgba(3, 6, 11, 0.62);
  backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  opacity: 0; visibility: hidden;
  transition: opacity 0.22s;
}
.modal-scrim.show { opacity: 1; visibility: visible; }
.modal-card {
  width: 100%;
  background: #10161f;
  border: 1px solid var(--line-soft);
  border-radius: 24px;
  padding: 30px 24px 26px;
  text-align: center;
  transform: scale(0.94);
  transition: transform 0.24s cubic-bezier(.2,.9,.3,1);
}
.modal-scrim.show .modal-card { transform: none; }

.lock-circle { width: 72px; height: 72px; margin: 0 auto 20px; border-radius: 50%; background: var(--surface-2); display: grid; place-items: center; }
.lock-circle .icon { width: 30px; height: 30px; }
.modal-title { font-size: 23px; font-weight: 500; }
.modal-title.serif { font-family: var(--serif); font-size: 28px; font-weight: 600; }
.modal-sub { font-size: 16.5px; color: var(--dim); margin-top: 8px; line-height: 1.45; }
.modal-btns { display: flex; gap: 14px; margin-top: 26px; }
.btn-ghost { flex: 1; background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; padding: 15px; font-size: 17px; }
.btn-pill-white { flex: 1; background: var(--btn); color: #1a1f27; border-radius: 999px; padding: 15px; font-size: 17px; font-weight: 500; }

.stars-row { display: flex; justify-content: center; gap: 14px; margin: 26px 0 22px; }
.star-btn .icon { width: 42px; height: 42px; stroke: #9aa3b0; stroke-width: 1.5; }
.star-btn.on .icon { stroke: var(--yellow); fill: var(--yellow); }
.modal-divider { height: 1px; background: var(--line-soft); margin: 0 -24px; }
.modal-foot-btn { width: 100%; padding: 18px 0 2px; font-size: 17px; font-weight: 700; }

.field-label { text-align: left; font-size: 16px; color: #d6dbe2; margin-bottom: 10px; }
.modal-textarea { width: 100%; background: var(--surface-2); border-radius: 15px; padding: 15px; font-size: 16px; min-height: 118px; resize: none; }
.modal-textarea::placeholder { color: var(--faint); }
.btn-stack { display: flex; flex-direction: column; gap: 13px; margin-top: 22px; }
.btn-dark { background: #161c25; border: 1px solid var(--line); border-radius: 999px; padding: 16px; font-size: 17px; color: var(--dim); display: flex; align-items: center; justify-content: center; gap: 10px; }
.btn-grey { background: #333b47; border-radius: 999px; padding: 16px; font-size: 17px; font-weight: 500; }

/* ============ 5. HANGOUT ============ */
#page-hangout { background: #0a1326 var(--sky) center/cover no-repeat; }
.hangout-top { position: relative; z-index: 3; padding: 16px 16px 0; display: flex; justify-content: flex-end; }
.gear-btn {
  width: 48px; height: 48px;
  border-radius: 50%;
  background: rgba(32, 39, 50, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.13);
  display: grid; place-items: center;
  backdrop-filter: blur(6px);
}
.hangout-body { position: relative; z-index: 2; flex: 1; }
.hangout-label {
  position: absolute;
  top: 46%; left: 60%;
  transform: translate(-50%, -50%);
  text-align: center;
  font-family: var(--serif);
  font-size: 25px;
  line-height: 1.2;
  color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.6);
}
.hangout-label .icon { width: 26px; height: 26px; margin: 0 auto 10px; display: block; stroke-width: 1.6; }

.act-card {
  position: absolute;
  width: 184px;
  background: #0c1118;
  border-radius: 26px;
  padding: 58px 18px 18px;
  box-shadow: 0 14px 38px rgba(0, 0, 0, 0.55);
}
.act-card h3 { font-family: var(--serif); font-size: 25px; font-weight: 500; line-height: 1.15; margin-bottom: 16px; }
.act-emblem {
  position: absolute;
  top: -22px; left: 46px;
  width: 74px; height: 74px;
  border-radius: 18px;
  display: grid; place-items: center;
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.5);
}
.act-emblem.yt { background: linear-gradient(160deg, #ff4b45, #cc0000); }
.act-emblem.yt svg { width: 34px; height: 34px; fill: #fff; }
.act-emblem.ttt { background: #15181d; border: 1px solid #2a2f38; }
.act-emblem.ttt svg { width: 42px; height: 42px; stroke: #fff; stroke-width: 2; fill: none; }
.act-btn { background: #1a212b; border-radius: 999px; padding: 11px 18px; font-size: 15.5px; color: #c3cad3; display: flex; align-items: center; gap: 9px; }
.act-card { animation: cardIn 740ms var(--spring) both, drift var(--dur, 10s) ease-in-out var(--dur, 10s) infinite; }
.a1 { left: -12px; top: 9%;  transform: rotate(-9deg); --dur: 10s;   animation-delay: 80ms, 0.5s; }
.a2 { left: -10px; top: 49%; transform: rotate(-7deg); --dur: 12s;   animation-delay: 200ms, 1.4s; }
.a3 { right: -58px; top: 17%; transform: rotate(8deg); --dur: 11s;   animation-delay: 140ms, 0.9s; }
.hangout-label { animation: riseIn 700ms var(--out) 320ms both; }
.hangout-label .icon { animation: nudge 3.4s ease-in-out 1.5s infinite; }
@keyframes nudge { 0%, 100% { translate: 0 0 } 50% { translate: 0 -5px } }
.hangout-dock { animation: ctaIn 620ms var(--spring) 260ms both; }

.hangout-dock {
  position: relative; z-index: 4;
  margin: 0 14px 18px;
  background: rgba(14, 19, 27, 0.82);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 9px 10px 9px 9px;
  display: flex; align-items: center; gap: 12px;
  backdrop-filter: blur(14px);
}
.dock-av { width: 46px; height: 46px; border-radius: 13px; object-fit: cover; flex: none; }
.dock-text { flex: 1; font-size: 16.5px; color: #dde3ea; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dock-chat { background: var(--btn); color: var(--btn-ink); border-radius: 999px; padding: 12px 20px; font-size: 16.5px; font-weight: 500; display: flex; align-items: center; gap: 9px; }

/* ============ 6. SUBSCRIBE ============ */
#page-subscribe { background: var(--bg-deep); }
.sub-hero { position: relative; flex: none; height: 120px; background: #0d1a33 var(--sky) center top/cover no-repeat; }
.sub-hero::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 40%, var(--bg-deep) 100%); }
.sub-close {
  position: absolute;
  top: 14px; left: 14px; z-index: 3;
  width: 46px; height: 46px;
  border-radius: 50%;
  background: rgba(25, 31, 40, 0.75);
  display: grid; place-items: center;
  backdrop-filter: blur(6px);
}
.sub-av {
  position: absolute;
  z-index: 3;
  left: 50%; bottom: -14px;
  transform: translateX(-50%) rotate(3deg);
  width: 104px; height: 122px;
  border-radius: 19px;
  background: #fff;
  padding: 5px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
}
.sub-av img { width: 100%; height: 100%; object-fit: cover; border-radius: 14px; display: block; }

.sub-body { flex: 1; overflow-y: auto; padding: 30px 18px 0; }
.sub-body::-webkit-scrollbar { width: 0; }
.rating-row { display: flex; align-items: center; justify-content: center; gap: 10px; }
.laurel { width: 58px; height: 74px; fill: #fff; flex: none; }
.laurel.r { transform: scaleX(-1); }
.rating-score { font-family: var(--serif); font-size: 31px; font-weight: 600; }
.rating-count { font-size: 17px; color: var(--dim); margin-top: -2px; }

.sec-serif { font-family: var(--serif); font-size: 23px; font-weight: 600; text-align: center; margin: 22px 0 12px; }

.review-card { border: 1px solid var(--line); border-radius: 20px; padding: 18px; }
.review-text { font-size: 17px; line-height: 1.42; color: #e7ebf0; }
.review-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 16px; gap: 12px; }
.review-who { display: flex; align-items: center; gap: 12px; font-size: 16.5px; color: #cdd4dc; }
.who-av { width: 38px; height: 38px; border-radius: 50%; background: var(--surface-2); display: grid; place-items: center; flex: none; }
.who-av .icon { width: 19px; height: 19px; stroke: #93a0b0; }
.review-stars { background: var(--surface); border: 1px solid var(--line-soft); border-radius: 12px; padding: 8px 14px; display: flex; gap: 3px; font-size: 15px; color: var(--yellow); letter-spacing: 1px; }

.plan-wrap { position: relative; margin-top: 26px; }
.plan-tag {
  position: absolute;
  top: -16px; right: -4px;
  z-index: 3;
  background: var(--yellow);
  color: #1c1708;
  font-size: 17px;
  font-weight: 700;
  padding: 9px 18px;
  border-radius: 13px;
  border: 1.5px dashed #6d5a12;
  transform: rotate(-7deg);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}
.plan-card { border: 1.5px dashed rgba(255, 255, 255, 0.22); border-radius: 22px; padding: 22px 20px 16px; }
.plan-price { font-family: var(--serif); font-size: 33px; font-weight: 600; letter-spacing: -0.01em; }
.plan-then { font-size: 13px; color: var(--faint); margin-top: 6px; font-weight: 400; opacity: 0.75; }
.plan-list { margin-top: 20px; display: flex; flex-direction: column; gap: 16px; }
.plan-item { display: flex; align-items: center; gap: 14px; font-size: 17px; color: #e7ebf0; }
.plan-item .icon { width: 23px; height: 23px; stroke: #cfd6de; }
.restore { display: block; width: 100%; text-align: center; margin-top: 18px; font-size: 16px; color: var(--faint); }

.sub-foot { flex: none; padding: 16px 18px 14px; }
.sub-note { text-align: center; font-size: 13.5px; color: var(--faint); margin-top: 12px; }

/* ============ 7. SETTINGS ============ */
#page-settings { background: var(--bg-deep); }
.set-head { flex: none; padding: 14px 16px; display: flex; align-items: center; gap: 14px; }
.back-btn { width: 46px; height: 46px; border-radius: 50%; background: var(--surface-2); display: grid; place-items: center; flex: none; }
.set-title { flex: 1; text-align: center; font-family: var(--serif); font-size: 27px; font-weight: 600; margin-right: 46px; }

.set-body { flex: 1; overflow-y: auto; padding: 0 16px 30px; }
.set-body::-webkit-scrollbar { width: 0; }
.set-banner { height: 128px; border-radius: 20px; background: #0d1a33 var(--sky) center top/cover no-repeat; display: grid; place-items: center; }
.set-banner img { width: 76px; height: 76px; border-radius: 18px; object-fit: cover; border: 2.5px solid var(--gold); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5); }

.name-field { margin-top: 20px; display: flex; align-items: center; background: var(--surface); border: 1px solid var(--line-soft); border-radius: 999px; padding: 7px 7px 7px 22px; height: 62px; box-shadow: var(--e2); }
.name-field span { flex: 1; font-size: 18px; }
.pencil-btn { width: 48px; height: 48px; border-radius: 50%; background: var(--surface-3); display: grid; place-items: center; flex: none; }
.field-cap { text-align: center; font-size: 15px; color: var(--faint); margin-top: 11px; }

.set-group { margin-top: 24px; background: var(--surface); border: 1px solid var(--line-soft); border-radius: 20px; overflow: hidden; box-shadow: var(--e2); }
.set-row { width: 100%; display: flex; align-items: center; gap: 16px; padding: 18px 20px; font-size: 17.5px; text-align: left; }
.set-row + .set-row { border-top: 1px solid rgba(255, 255, 255, 0.055); }
.set-row span { flex: 1; }
.set-row .icon { stroke: #cfd6de; }
/* The quiet word on the right of a row — "anytime" next to cancel autopay.
   It is reassurance, so it reads calm rather than like a warning. */
.set-row-hint {
  flex: none;
  font-style: normal;
  font-size: 13px;
  color: var(--faint);
  letter-spacing: 0.01em;
}

.toggle { width: 54px; height: 31px; border-radius: 999px; background: #39414d; position: relative; transition: background 0.2s; flex: none; }
.toggle.on { background: var(--green); }
.toggle::after { content: ''; position: absolute; top: 3px; left: 3px; width: 25px; height: 25px; border-radius: 50%; background: #fff; transition: transform 0.2s; }
.toggle.on::after { transform: translateX(23px); }

/* A card used to come to rest half-cut through a word, which reads as broken
   rather than as "there is more to the right". Snapping lands each card on the
   gutter and leaves a deliberate sliver of the next one showing. */
.privacy-scroll {
  display: flex; gap: 13px;
  margin: 16px -16px 0;
  padding: 0 16px 6px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 16px;
  -webkit-overflow-scrolling: touch;
  /* At rest the next card is cut off mid-word, which reads as a broken layout
     rather than as more content. Fading that edge turns the cut into a hint. */
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 78%, rgba(0, 0, 0, 0) 97%);
  mask-image: linear-gradient(90deg, #000 0, #000 78%, rgba(0, 0, 0, 0) 97%);
}
.privacy-scroll::-webkit-scrollbar { height: 0; }
.privacy-card {
  flex: none;
  width: 236px;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: 18px;
  padding: 20px 18px;
  scroll-snap-align: start;
  box-shadow: var(--e2);
}
.privacy-card .emo { font-size: 30px; }
.privacy-card p { margin-top: 36px; font-size: 16.5px; color: #dbe1e8; line-height: 1.4; }

.danger-list { margin-top: 36px; display: flex; flex-direction: column; gap: 24px; }
.danger-list button { text-align: left; font-size: 17.5px; color: #5c6572; }
.danger-list button.red { color: #7a4a4a; }

/* ============ TOAST ============ */
.toast {
  position: fixed;
  bottom: 96px; left: 50%;
  transform: translate(-50%, 14px);
  background: #1d242e;
  border: 1px solid var(--line);
  padding: 12px 20px;
  border-radius: 16px;
  font-size: 14.5px;
  line-height: 1.45;
  z-index: 200;
  opacity: 0; visibility: hidden;
  transition: 0.22s;
  width: max-content;
  max-width: min(86%, 360px);
  text-align: center;
  overflow-wrap: anywhere;
}
.toast.show { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.toast.error { border-color: rgba(239, 107, 107, 0.5); }
.toast.success { border-color: rgba(34, 197, 94, 0.5); }

@media (min-width: 520px) {
  /* On a wide screen the shell is a column in the middle of a dark field. A
     little ambient light behind it and a hairline on the edge stop it reading
     as a rectangle cut out of the page. Phones never see any of this. */
  body {
    align-items: center;
    background:
      radial-gradient(60% 50% at 50% 42%, rgba(42, 62, 102, 0.3), rgba(5, 8, 13, 0) 70%),
      #05080d;
  }
  #app {
    height: min(900px, 100dvh);
    border-radius: 26px;
    border: 1px solid rgba(255, 255, 255, 0.07);
    box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(0, 0, 0, 0.5);
  }
}

/* ============ MICRO-INTERACTIONS ============ */
.head-btn, .round-btn, .btn-x, .back-btn, .pencil-btn, .gear-btn, .social-btn, .star-btn, .act-btn, .dock-chat {
  transition: transform 180ms var(--spring), background-color 160ms ease, border-color 160ms ease;
}
.head-btn:active, .round-btn:active, .btn-x:active, .back-btn:active,
.pencil-btn:active, .gear-btn:active, .social-btn:active, .act-btn:active, .dock-chat:active { transform: scale(0.88); }
.star-btn:active { transform: scale(1.22); }

.btn-google, .btn-white, .btn-pill-white, .btn-ghost, .btn-dark, .btn-grey, .modal-foot-btn, .link-phone, .restore {
  transition: transform 180ms var(--spring), opacity 160ms ease, background-color 160ms ease;
}
.btn-ghost:active, .btn-dark:active, .btn-grey:active, .btn-pill-white:active { transform: scale(0.96); }
.modal-foot-btn:active, .link-phone:active, .restore:active { opacity: 0.55; }

.menu-item, .set-row, .plan-item { transition: background-color 150ms ease, transform 150ms var(--spring); }
.set-row:active { background: rgba(255, 255, 255, 0.045); }
.menu-item:active { transform: scale(0.975); }

/* ripple */
.ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
  transform: scale(0);
  opacity: 0.7;
  pointer-events: none;
  animation: rippleOut 560ms var(--out) forwards;
}
.ripple-dark { background: rgba(0, 0, 0, 0.16); }
@keyframes rippleOut { to { transform: scale(2.6); opacity: 0; } }

/* staggered list reveals */
.stagger > * { animation: riseIn 520ms var(--out) both; }
.stagger > *:nth-child(1) { animation-delay: 40ms; }
.stagger > *:nth-child(2) { animation-delay: 95ms; }
.stagger > *:nth-child(3) { animation-delay: 150ms; }
.stagger > *:nth-child(4) { animation-delay: 205ms; }
.stagger > *:nth-child(5) { animation-delay: 260ms; }
.stagger > *:nth-child(6) { animation-delay: 315ms; }

/* menu items cascade when the dropdown opens */
.menu-scrim.show .menu-item { animation: menuItemIn 320ms var(--out) both; }
.menu-scrim.show .menu-item:nth-child(1) { animation-delay: 30ms; }
.menu-scrim.show .menu-item:nth-child(2) { animation-delay: 65ms; }
.menu-scrim.show .menu-item:nth-child(3) { animation-delay: 100ms; }
.menu-scrim.show .menu-item:nth-child(4) { animation-delay: 135ms; }
.menu-scrim.show .menu-item:nth-child(5) { animation-delay: 170ms; }
@keyframes menuItemIn { from { opacity: 0; transform: translate3d(10px, 0, 0); } to { opacity: 1; transform: none; } }

/* modal card springs in */
.modal-card { transform: scale(0.9) translate3d(0, 16px, 0); transition: transform 380ms var(--spring), opacity 240ms ease; }
.modal-scrim.show .modal-card { transform: none; }
.lock-circle { animation: lockPop 620ms var(--spring) 90ms both; }
@keyframes lockPop { from { opacity: 0; transform: scale(.4) rotate(-18deg); } to { opacity: 1; transform: none; } }

/* sheet springs up */
.sheet { transform: translate3d(0, 110%, 0); transition: transform 420ms var(--spring); }
.sheet-scrim.show .sheet { transform: none; }

/* plan tag wiggles to draw the eye */
.plan-wrap { margin-bottom: 26px; }

/* The unlock button stays parked at the bottom and the price card hides behind
   it, sliding into view only when the page is scrolled. Lifting the footer out
   of the flex flow is what lets the content pass underneath it. */
#page-subscribe .sub-foot {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background: var(--bg-deep);
  box-shadow: 0 -20px 24px -10px var(--bg-deep);
}
/* Room for the price to clear the button once scrolled all the way down. */
#subBuyFlow { padding-bottom: 142px; }

.plan-tag { animation: tagIn 700ms var(--spring) 260ms both, tagNudge 4.5s ease-in-out 2s infinite; }
@keyframes tagIn { from { opacity: 0; transform: rotate(-30deg) scale(.5); } to { opacity: 1; transform: rotate(-7deg) scale(1); } }
@keyframes tagNudge {
  0%, 92%, 100% { rotate: 0deg; }
  95%  { rotate: 5deg; }
  97%  { rotate: -4deg; }
}

/* subscribe hero + CTA */
.sub-av { animation: cardIn 760ms var(--spring) 120ms both; }
.sub-foot .btn-white { animation: ctaIn 680ms var(--spring) 400ms both; }
.rating-row { animation: riseIn 620ms var(--out) 200ms both; }
.laurel { animation: laurelIn 760ms var(--spring) 300ms both; }
@keyframes laurelIn { from { opacity: 0; scale: .5; } to { opacity: 1; scale: 1; } }

/* toggle knob squash */
.toggle::after { transition: transform 260ms var(--spring), width 160ms ease; }
.toggle:active::after { width: 31px; }

/* scrollers get momentum + no bounce-through */
.msgs, .sub-body, .set-body, .privacy-scroll {
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
}
.privacy-scroll { scroll-snap-type: x mandatory; }
.privacy-card { scroll-snap-align: start; transition: transform 200ms var(--spring); }
.privacy-card:active { transform: scale(0.97); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============ VOICE CALL OVERLAY ============ */
.call-overlay {
  position: absolute;
  inset: 0;
  z-index: 100;
  background: linear-gradient(180deg, #0c1220 0%, #0a0e18 40%, #111827 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s, visibility 0.3s;
}
.call-overlay.show { opacity: 1; visibility: visible; }

.call-bg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  overflow: hidden;
}
.call-ripple {
  position: absolute;
  width: 220px; height: 220px;
  border-radius: 50%;
  border: 1.5px solid rgba(99, 146, 255, 0.12);
  animation: callPulse 3s ease-out infinite;
}
.call-ripple.r2 { animation-delay: 1s; }
.call-ripple.r3 { animation-delay: 2s; }
@keyframes callPulse {
  0%   { transform: scale(0.8); opacity: 0.7; }
  100% { transform: scale(2.8); opacity: 0; }
}

.call-top {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: max(60px, calc(var(--safe-t) + 48px));
}
.call-av-wrap { position: relative; margin-bottom: 18px; }
.call-av {
  width: 110px; height: 110px;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid rgba(255,255,255,0.15);
  box-shadow: 0 8px 40px rgba(99, 146, 255, 0.2);
}
.call-av img { width: 100%; height: 100%; object-fit: cover; }
.call-dot {
  position: absolute;
  bottom: 4px; right: 4px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--green);
  border: 2.5px solid #0c1220;
}
.call-name {
  font-family: var(--serif);
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.01em;
}
.call-status {
  font-size: 14px;
  color: var(--dim);
  margin-top: 4px;
}
.call-overlay.show .call-status.listening { color: var(--green); }
.call-timer {
  font-size: 15px;
  color: var(--faint);
  margin-top: 8px;
  font-variant-numeric: tabular-nums;
}

.call-mid {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 24px;
  gap: 20px;
  width: 100%;
}
.call-wave {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 40px;
  opacity: 0;
  transition: opacity 0.3s;
}
.call-wave.active { opacity: 1; }
.call-wave span {
  width: 4px;
  border-radius: 3px;
  background: linear-gradient(180deg, #6392ff, #a78bfa);
  height: 8px;
  animation: waveBar 0.8s ease-in-out infinite alternate;
}
.call-wave span:nth-child(1)  { animation-delay: 0s;    }
.call-wave span:nth-child(2)  { animation-delay: 0.1s;  }
.call-wave span:nth-child(3)  { animation-delay: 0.2s;  }
.call-wave span:nth-child(4)  { animation-delay: 0.3s;  }
.call-wave span:nth-child(5)  { animation-delay: 0.4s;  }
.call-wave span:nth-child(6)  { animation-delay: 0.35s; }
.call-wave span:nth-child(7)  { animation-delay: 0.25s; }
.call-wave span:nth-child(8)  { animation-delay: 0.15s; }
.call-wave span:nth-child(9)  { animation-delay: 0.05s; }
.call-wave span:nth-child(10) { animation-delay: 0.45s; }
@keyframes waveBar {
  0%   { height: 6px;  }
  100% { height: 32px; }
}

.call-transcript {
  font-size: 16px;
  color: var(--dim);
  text-align: center;
  max-width: 100%;
  max-height: 80px;
  overflow-y: auto;
  line-height: 1.5;
  padding: 0 8px;
  opacity: 0;
  transition: opacity 0.3s;
}
.call-transcript.show { opacity: 1; }

.call-controls {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 36px;
  padding: 24px 0 max(40px, calc(var(--safe-b) + 24px));
}
.call-ctrl {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.call-ctrl span {
  font-size: 12px;
  color: var(--dim);
  letter-spacing: 0.02em;
}
.ctrl-circle {
  width: 60px; height: 60px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.1);
  display: grid;
  place-items: center;
  transition: background 0.2s, transform 0.15s;
}
.ctrl-circle:active { transform: scale(0.92); }
.ctrl-circle .icon { width: 24px; height: 24px; }
.ctrl-circle.end {
  width: 68px; height: 68px;
  background: #ef4444;
  border-color: transparent;
  box-shadow: 0 4px 24px rgba(239, 68, 68, 0.4);
}
.ctrl-circle.end .icon { stroke: #fff; }
.call-ctrl.active .ctrl-circle {
  background: #fff;
}
.call-ctrl.active .ctrl-circle .icon { stroke: #111; }
.call-ctrl.active span { color: #fff; }

/* The call screen deliberately shows no transcript: printing the caller's own
   words back made it read like a demo instead of a conversation. */
#callTranscript { display: none !important; }

/* ============ PROFILE PHOTO + STORIES ============ */

/* tap her photo in chat -> the whole picture, nothing cropped */
.photo-view {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(4, 6, 10, 0.97);
  display: none; place-items: center;
  padding: 24px;
  animation: pvIn 200ms ease both;
}
.photo-view.show { display: grid; }
/* Percentages do not resolve against an auto-sized grid track, so the picture
   is bounded by the viewport itself. */
.photo-view img {
  max-width: calc(100vw - 48px);
  max-height: calc(100vh - 48px);
  object-fit: contain;
  border-radius: 14px;
}
.pv-close {
  position: absolute; top: calc(14px + var(--safe-t, 0px)); right: 16px;
  width: 42px; height: 42px; border-radius: 50%;
  background: rgba(255,255,255,0.14); color: #fff; font-size: 26px; line-height: 1;
  border: 0; display: grid; place-items: center;
}
@keyframes pvIn { from { opacity: 0 } to { opacity: 1 } }

/* a ring on her avatar only while unseen stories exist */
.head-av.has-story { border-color: #e8b730; box-shadow: 0 0 0 2px rgba(232,183,48,.35); }
.head-name.has-story { cursor: pointer; }

.story-view {
  position: fixed; inset: 0; z-index: 310;
  background: #000;
  display: none;
  animation: pvIn 180ms ease both;
}
.story-view.show { display: block; }

/* contain, not cover: the whole image is meant to be visible */
.sv-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  background: #000;
}

.sv-bars {
  position: absolute; top: calc(10px + var(--safe-t, 0px)); left: 10px; right: 10px;
  z-index: 3; display: flex; gap: 4px;
}
.sv-bar { flex: 1; height: 2.5px; border-radius: 2px; background: rgba(255,255,255,0.32); overflow: hidden; }
.sv-bar > i { display: block; height: 100%; width: 0; background: #fff; border-radius: 2px; }
.sv-bar.done > i { width: 100%; }
.sv-bar.active > i { animation: svFill linear forwards; }
@keyframes svFill { from { width: 0 } to { width: 100% } }

.sv-top {
  position: absolute; top: calc(24px + var(--safe-t, 0px)); left: 12px; right: 12px;
  z-index: 3; display: flex; align-items: center; gap: 10px;
}
.sv-av { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; border: 1.5px solid rgba(255,255,255,.7); }
.sv-name { flex: 1; color: #fff; font-size: 15px; font-weight: 600; text-shadow: 0 1px 6px rgba(0,0,0,.6); }
.sv-close {
  width: 38px; height: 38px; border: 0; background: transparent;
  color: #fff; font-size: 30px; line-height: 1; display: grid; place-items: center;
}

.sv-caption {
  position: absolute; left: 0; right: 0;
  bottom: calc(26px + var(--safe-b, 0px));
  z-index: 3; padding: 0 22px;
  color: #fff; font-size: 16px; line-height: 1.4; text-align: center;
  text-shadow: 0 2px 10px rgba(0,0,0,.75);
}
.sv-caption:empty { display: none; }

/* invisible halves: left goes back, right goes forward */
.sv-tap { position: absolute; top: 0; bottom: 0; width: 34%; z-index: 2; border: 0; background: transparent; }
.sv-prev { left: 0; }
.sv-next { right: 0; width: 66%; }

/* ============ EXCLUSIVE IMAGE (paid unlock) ============ */
/* A definite width is required here: the bubble is a flex item that shrinks to
   its content, while the image asks for 100% of the bubble. Without one, each
   waits on the other and both collapse to zero. */
.msg-excl { padding: 6px; width: 250px; max-width: 76%; cursor: pointer; overflow: hidden; }
/* A plain pixel height, not aspect-ratio: a good share of this audience is on
   Chrome 58-78, where aspect-ratio does nothing and the box collapses to zero.
   The height is set here and the image simply fills it. */
.ex-shot { position: relative; height: 340px; border-radius: 14px; overflow: hidden; }
.ex-img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 14px; }

/* The teaser file is already blurred on the server — this only darkens it so
   the lock and the price stay readable on top. */
.ex-lock {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: linear-gradient(180deg, rgba(8,10,14,.25), rgba(8,10,14,.6));
}
.ex-lock-ic {
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(255,255,255,.16);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  display: grid; place-items: center;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
}
.ex-lock-ic svg { width: 22px; height: 22px; stroke: #fff; }
.ex-pay {
  background: #e8b730; color: var(--btn-ink);
  font-size: 13px; font-weight: 700;
  padding: 7px 14px; border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0,0,0,.45);
  white-space: nowrap;
}
.msg-excl:active .ex-lock-ic { transform: scale(.92); }

/* once paid for, the lock comes off and it reads as a normal photo. The teaser
   is cropped to a fixed shape so every bubble looks the same; the real photo is
   not — they paid for it, so they see all of it. */
.msg-excl.unlocked .ex-lock { display: none; }
.msg-excl.unlocked { cursor: zoom-in; }
.msg-excl.unlocked .ex-shot { height: auto; }
.msg-excl.unlocked .ex-img { height: auto; object-fit: contain; }

/* ============ PREMIUM CTA CARD ============ */
.msg-cta { max-width: 300px; padding: 16px 18px; }
.cta-title { font-size: 16px; font-weight: 700; color: #fff; margin-bottom: 6px; line-height: 1.3; }
.cta-text { font-size: 14.5px; color: #cdd4dc; line-height: 1.45; margin-bottom: 14px; }
.cta-btn {
  display: block; text-align: center; text-decoration: none;
  background: linear-gradient(135deg, #FF1493, #a855f7);
  color: #fff; font-size: 15px; font-weight: 700;
  padding: 12px 18px; border-radius: 999px;
  box-shadow: 0 6px 18px rgba(255, 20, 147, .35);
  transition: transform 180ms var(--spring), box-shadow 180ms ease;
  position: relative; overflow: hidden;
}
.cta-btn:active { transform: scale(.96); box-shadow: 0 3px 10px rgba(255, 20, 147, .3); }
/* a slow sheen so the button reads as the thing to tap */
.cta-btn::after {
  content: ''; position: absolute; top: 0; bottom: 0; width: 45%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.28), transparent);
  transform: translateX(-160%);
  animation: ctaSheen 3.4s ease-in-out 1.2s infinite;
}
@keyframes ctaSheen { 0% { transform: translateX(-160%); } 55%, 100% { transform: translateX(320%); } }
@media (prefers-reduced-motion: reduce) { .cta-btn::after { animation: none; } }

/* ============ HANGOUT ACTIVITIES ============ */
/* The overlay and the three games inside it. Built by hangout.js, which only
   loads when a premium user opens one — so none of this is ever seen by a
   free visitor, and the markup does not sit in index.html either. */
.hg-overlay {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  z-index: 90;
  background: var(--bg-deep);
  display: none;
  flex-direction: column;
  max-width: var(--shell);
  margin: 0 auto;
}
.hg-overlay.show { display: flex; animation: fadeUp 300ms var(--out) both; }
body.hg-open { overflow: hidden; }

.hg-head {
  flex: none;
  display: flex; align-items: center; gap: 10px;
  padding: calc(10px + var(--safe-t)) 12px 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(14, 19, 27, 0.92);
}
.hg-back {
  width: 38px; height: 38px;
  flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  color: #dfe5ee;
}
.hg-back svg { width: 22px; height: 22px; }
.hg-back:active { background: rgba(255, 255, 255, 0.1); }
.hg-title { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }

.hg-body {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 14px 14px calc(18px + var(--safe-b));
}
.hg-body::-webkit-scrollbar { width: 0; }

.hg-game { flex: none; }

/* who is playing whom */
.ttt-who {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  font-size: 14px; color: var(--dim);
  margin-bottom: 14px;
}
.ttt-who b { font-size: 17px; color: #fff; font-weight: 600; }
.ttt-vs { font-size: 12px; opacity: .6; }
.ttt-her b { color: #e07ab8; }

/* ---- tic tac toe ---- */
.ttt-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 9px;
  max-width: 330px;
  margin: 0 auto;
}
.ttt-cell {
  /* A plain height, not aspect-ratio: a real share of this audience is on
     Chrome 58-78, where aspect-ratio does nothing and the grid collapses. */
  height: 100px;
  border-radius: 18px;
  background: #1b2230;
  border: 1px solid rgba(255, 255, 255, 0.07);
  font-size: 42px;
  font-weight: 600;
  line-height: 1;
  color: #fff;
  transition: transform 160ms var(--spring), background-color 160ms ease;
}
.ttt-cell:active:not(:disabled) { transform: scale(0.95); }
.ttt-cell:disabled { cursor: default; }
.ttt-cell.filled { animation: msgIn 300ms var(--spring) both; }
.ttt-cell.x { color: #7fd4ff; }
.ttt-cell.o { color: #ff8ec4; }
.ttt-cell.win { background: #2b3a4d; border-color: rgba(127, 212, 255, 0.5); }

/* ---- chess ---- */
/* The board is kept square by a padding-ratio wrapper and the grid is laid
   absolutely inside it. aspect-ratio would be the obvious tool and does
   nothing on the Chrome 58-78 share of this audience, and a padding box on
   the squares themselves would leave the glyphs stranded at the top edge
   with no height to centre in. */
.chess-wrap {
  position: relative;
  width: 100%;
  max-width: 360px;
  height: 0;
  padding-bottom: 100%;
  margin: 0 auto;
}
.chess-grid {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  grid-template-rows: repeat(8, minmax(0, 1fr));
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.chess-sq {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* scales with the board instead of a fixed size, so it fits a small phone */
  font-size: 5.6vw;
  line-height: 1;
  border-radius: 0;
  padding: 0;
  transition: background-color 140ms ease;
}
/* The two square colours are kept far enough apart that a dark piece still
   reads on the dark square, and each side carries a rim in the opposite
   tone so neither set disappears into the board. */
.chess-sq.light { background: #6b7891; }
.chess-sq.dark { background: #36425a; }
.chess-sq.white {
  color: #ffffff;
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.9), 0 1px 2px rgba(0, 0, 0, 0.65);
}
.chess-sq.black {
  color: #0b0e14;
  text-shadow: 0 0 2px rgba(255, 255, 255, 0.55), 0 1px 1px rgba(255, 255, 255, 0.3);
}
.chess-sq.sel { background: #6b7ea0; }
.chess-sq.target::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 26%; height: 26%;
  margin: -13% 0 0 -13%;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
}
.chess-sq.capture::after {
  content: '';
  position: absolute;
  top: 6%; right: 6%; bottom: 6%; left: 6%;
  border-radius: 50%;
  border: 3px solid rgba(255, 140, 170, 0.75);
}
.chess-sq.check { background: #8c3b4b; }

/* the board stops growing once the shell does, so cap the glyph too */
@media (min-width: 420px) {
  .chess-sq { font-size: 25px; }
}

/* ---- youtube ---- */
.yt-frame {
  position: relative;
  width: 100%;
  max-width: 330px;
  margin: 0 auto;
  /* 9:16, the shorts shape, as a padding ratio rather than aspect-ratio */
  height: 0;
  padding-bottom: 177.8%;
  border-radius: 18px;
  overflow: hidden;
  background: #000;
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.yt-frame iframe {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  border: 0;
}
.yt-nav {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  margin-top: 14px;
}
.yt-count { font-size: 13px; color: var(--dim); min-width: 56px; text-align: center; }
.yt-btn {
  padding: 11px 20px;
  border-radius: 999px;
  font-size: 15px;
  background: var(--surface-2);
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: #e7ecf3;
  transition: transform 160ms var(--spring);
}
.yt-btn:active:not(:disabled) { transform: scale(0.96); }
.yt-btn:disabled { opacity: 0.4; pointer-events: none; }
.yt-btn.primary {
  background: linear-gradient(120deg, #b03a79, #7d3bb8 60%, #5244cf);
  border-color: rgba(255, 255, 255, 0.14);
  color: #fff;
}

/* nothing queued */
.hg-empty { text-align: center; padding: 48px 20px; }
.hg-empty-title { font-family: var(--serif); font-size: 23px; margin-bottom: 8px; }
.hg-empty-sub { font-size: 15.5px; color: var(--dim); line-height: 1.5; }

/* ---- shared status row ---- */
.hg-status {
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.hg-status-text { font-size: 15.5px; color: #cfd6e0; }
.hg-restart {
  flex: none;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 14.5px;
  background: var(--surface-2);
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: #e7ecf3;
  transition: transform 160ms var(--spring);
}
.hg-restart:active { transform: scale(0.96); }

/* ============ HOME ============ */
/* She is the hero, but the night scene is the brand and it stays. The first
   attempt at this replaced the sky with a flat dark page and the result was a
   generic template — the atmosphere is the point, she just needed to be
   standing in it instead of buried under five empty cards. */

#page-welcome[data-home="new"] {
  background:
    /* darkens downward so the type at the bottom always has something to sit on */
    linear-gradient(180deg,
      rgba(6, 10, 20, 0.28) 0%,
      rgba(6, 10, 20, 0.55) 34%,
      rgba(6, 10, 20, 0.86) 62%,
      rgba(5, 8, 15, 0.97) 82%,
      #05080f 100%),
    #0a1326 var(--sky) center top / cover no-repeat;
  overflow-y: auto;
  justify-content: flex-start;
}
#page-welcome[data-home="new"]::after { display: none; }
#page-welcome::-webkit-scrollbar { width: 0; }

#page-welcome[data-home="new"] .sky-fx::before { opacity: .5; }

/* ---- brand bar ---- */
.home-bar {
  position: relative;
  z-index: 4;
  flex: none;
  display: flex; align-items: center; gap: 9px;
  padding: calc(12px + var(--safe-t)) 18px 0;
}
.home-bar-mark {
  width: 28px; height: 28px;
  border-radius: 8px;
  display: block;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.home-bar-name {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.6);
}
.home-bar-age {
  margin-left: auto;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.72);
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(0, 0, 0, 0.25);
}

/* ---- her ---- */
.home-hero {
  position: relative;
  z-index: 3;
  /* She is the only part of this page that flexes. Everything else has a
     fixed height, so she takes what is left over and the page always ends
     exactly at the bottom of the screen instead of scrolling. The cap stops
     her becoming a pillar on a tall screen; the floor keeps her a portrait
     rather than a letterbox on a short one. */
  flex: 1 1 auto;
  min-height: 118px;
  max-height: 352px;
  width: 70%;
  max-width: 278px;
  margin: 14px auto 0;
  border-radius: 150px 150px 26px 26px;   /* arched top, like a portrait niche */
  overflow: hidden;
  background: #121824;
  /* a warm rim and a long shadow, so she is lit by the scene rather than
     pasted on top of it */
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.14),
    0 0 0 6px rgba(255, 255, 255, 0.045),
    0 26px 70px -18px rgba(0, 0, 0, 0.95),
    0 0 90px -20px rgba(120, 160, 255, 0.45);
  animation: heroIn 820ms var(--out) both;
}
@keyframes heroIn {
  from { opacity: 0; transform: translate3d(0, 18px, 0) scale(.96); }
  to   { opacity: 1; transform: none; }
}
.home-hero-photo {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background-size: cover;
  background-position: center top;
}
.home-hero-fade {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background: linear-gradient(180deg, rgba(8, 12, 22, 0.3) 0%, rgba(8, 12, 22, 0) 30%, rgba(8, 12, 22, 0) 68%, rgba(8, 12, 22, 0.55) 100%);
}
.home-hero-live {
  position: absolute;
  left: 50%; bottom: 12px;
  transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 13px 6px 11px;
  border-radius: 999px;
  font-size: 12px; font-weight: 500;
  white-space: nowrap;
  color: #eaf3ee;
  background: rgba(8, 14, 10, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.home-hero-live i {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--green);
  animation: livePulse 2.4s ease-out infinite;
}

/* ---- name, line, proof ---- */
.home-main {
  position: relative;
  z-index: 4;
  flex: none;
  padding: 0 22px;
  text-align: center;
  margin-top: 16px;
}
.home-name {
  font-family: var(--serif);
  font-size: clamp(34px, 11vw, 46px);
  font-weight: 500;
  line-height: 1.04;
  margin: 0;
  letter-spacing: -0.005em;
  text-shadow: 0 2px 26px rgba(0, 0, 0, 0.85);
  animation: riseIn 700ms var(--out) 160ms both;
}
.home-tag {
  margin: 8px auto 0;
  max-width: 290px;
  font-size: 15px;
  line-height: 1.45;
  color: rgba(226, 233, 243, 0.82);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.7);
  animation: riseIn 700ms var(--out) 240ms both;
}

.home-proof {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 15px;
  padding: 7px 15px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.11);
  font-size: 13px;
  color: rgba(226, 233, 243, 0.85);
  animation: riseIn 700ms var(--out) 320ms both;
}
.home-proof b { color: #fff; font-weight: 600; font-size: 14.5px; }
.home-stars svg { width: 15px; height: 15px; fill: var(--yellow); display: block; }
.home-proof-sub { opacity: .72; }

#page-welcome[data-home="new"] .welcome-cta {
  margin: 18px auto 0;
  width: 100%;
  max-width: 320px;
  justify-content: center;
  font-weight: 600;
}
.home-offer {
  margin-top: 10px;
  font-size: 13.5px;
  color: rgba(214, 223, 235, 0.65);
  animation: riseIn 700ms var(--out) 880ms both;
}
#page-welcome[data-home="new"] .welcome-note { margin: 14px auto 0; }

/* ---- footer ---- */
/* margin-top:auto pins it to the bottom on a tall screen and simply follows
   the content on a short one, so there is never a pool of dead black. */
#page-welcome[data-home="new"] .home-foot {
  position: relative;
  z-index: 4;
  flex: none;
  /* only bites once the hero has hit its cap and there is space to spare */
  margin-top: auto;
  padding-top: 18px;
}
.home-foot-social {
  display: flex; justify-content: center; gap: 12px;
  margin-bottom: 16px;
}
#page-welcome[data-home="new"] .social-btn {
  width: 40px; height: 40px;
  border-radius: 12px;
  border-width: 2px;
}
#page-welcome[data-home="new"] .social-btn.x svg { width: 18px; height: 18px; }
#page-welcome[data-home="new"] .social-btn.ig svg { width: 20px; height: 20px; }

/* The fixed parts give ground before the hero is squeezed flat, so a short
   phone loses a few pixels of padding rather than losing the button or the
   footer links off the bottom. */
@media (max-height: 740px) {
  .home-hero { width: 64%; margin-top: 10px; max-height: 300px; }
  .home-main { margin-top: 12px; }
  .home-tag { font-size: 14px; margin-top: 6px; }
  .home-proof { margin-top: 10px; padding: 6px 13px; }
  #page-welcome[data-home="new"] .welcome-cta { margin-top: 13px; padding: 15px 34px; font-size: 17px; }
  .home-offer { margin-top: 8px; font-size: 13px; }
  #page-welcome[data-home="new"] .home-foot { padding-top: 12px; }
  .home-foot-social { margin-bottom: 10px; }
  #page-welcome[data-home="new"] .social-btn { width: 36px; height: 36px; }
}

@media (max-height: 660px) {
  .home-bar { padding-top: calc(8px + var(--safe-t)); }
  .home-hero { width: 54%; margin-top: 8px; max-height: 238px; border-radius: 110px 110px 20px 20px; }
  .home-hero-live { bottom: 8px; padding: 4px 11px 4px 9px; font-size: 11px; }
  .home-main { margin-top: 10px; }
  .home-name { font-size: 32px; }
  .home-tag { font-size: 13px; line-height: 1.35; margin-top: 5px; }
  .home-proof { margin-top: 8px; font-size: 12px; padding: 5px 11px; }
  #page-welcome[data-home="new"] .welcome-cta { margin-top: 11px; padding: 13px 30px; font-size: 16px; }
  .home-offer { margin-top: 6px; font-size: 12px; }
  #page-welcome[data-home="new"] .home-foot { padding-top: 10px; }
  .home-foot-social { margin-bottom: 8px; }
  #page-welcome[data-home="new"] .social-btn { width: 32px; height: 32px; }
  #page-welcome[data-home="new"] .social-btn.x svg { width: 15px; height: 15px; }
  #page-welcome[data-home="new"] .social-btn.ig svg { width: 17px; height: 17px; }
  .home-foot-links { gap: 4px 12px; margin-bottom: 6px; }
  .home-foot-links a { font-size: 12px; }
  .home-foot-brand { font-size: 11px; }
}


/* ============ HOME — classic ============ */
/* The original landing, kept so admin can switch back to it from Settings.
   These selectors only match once app.js has swapped the classic markup in,
   so in new mode they cost nothing but their bytes. */
#page-welcome[data-home="classic"] {
  background: #0a1326 var(--sky) center/cover no-repeat;
  overflow-y: hidden;
  justify-content: normal;
}
#page-welcome[data-home="classic"]::after {
  content: '';
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  background: linear-gradient(180deg, rgba(4, 9, 19, 0.5) 0%, transparent 22%, transparent 68%, rgba(4, 9, 19, 0.5) 100%);
  pointer-events: none;
}
#page-welcome[data-home="classic"] .welcome-cta { margin: 0 auto 14px; width: auto; max-width: none; }
#page-welcome[data-home="classic"] .welcome-note { margin: 0 auto 10px; }
#page-welcome[data-home="classic"] .home-foot { margin-top: 0; padding-top: 0; }
#page-welcome[data-home="classic"] .social-btn { width: 54px; height: 54px; border-radius: 16px; border-width: 2.5px; }
#page-welcome[data-home="classic"] .social-btn.x svg { width: 24px; height: 24px; }
#page-welcome[data-home="classic"] .social-btn.ig svg { width: 27px; height: 27px; }

.follow-row {
  position: relative;
  z-index: 3;
  padding: 18px 20px 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.follow-label { font-family: var(--serif); font-size: 20px; color: rgba(255, 255, 255, 0.82); }
.follow-arrow { width: 62px; height: 26px; stroke: rgba(255, 255, 255, 0.6); stroke-width: 1.4; fill: none; }
.social-row { position: relative; z-index: 3; margin-top: 4px; display: flex; justify-content: center; gap: 14px; }
.polaroids { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; }
.polaroid {
  position: absolute;
  background: #fff;
  padding: 6px;
  border-radius: 18px;
  box-shadow: var(--e3), 0 2px 4px rgba(0, 0, 0, 0.3);
  animation: cardIn 900ms var(--spring) both, drift var(--dur, 9s) ease-in-out var(--dur, 9s) infinite;
}
.polaroid .ph {
  width: 100%; height: 100%;
  border-radius: 13px;
  background-size: cover;
  background-position: center;
  position: relative;
  /* a print has a little depth of its own: a dark lip at the edge and light
     falling off towards the bottom */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.07),
              inset 0 -22px 34px -20px rgba(0, 0, 0, 0.55);
}
.polaroid .sky-ph {
  background-image: var(--sky);
  background-size: 400% auto;
  filter: saturate(1.35) contrast(1.22) brightness(1.08);
}
.p2 .sky-ph { filter: saturate(1.2) contrast(1.26) brightness(1.0) hue-rotate(-8deg); }
.p4 .sky-ph { filter: saturate(1.45) contrast(1.18) brightness(1.14) hue-rotate(6deg); }
.p5 .sky-ph { filter: saturate(1.25) contrast(1.28) brightness(0.96); }
/* A print catches the light across one corner. This is what stops the card
   reading as a hole cut through to the background. */
.polaroid .ph::after {
  content: '';
  position: absolute;
  /* explicit sides rather than `inset`, which this share of old Android Chrome
     does not understand */
  top: 0; right: 0; bottom: 0; left: 0;
  border-radius: inherit;
  background: linear-gradient(126deg, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0.05) 26%, rgba(255, 255, 255, 0) 46%);
  pointer-events: none;
}
.p1 { width: 144px; height: 152px; left: -34px; top: 19%; transform: rotate(-9deg); --dur: 9s;    animation-delay: 160ms, 0.4s; }
.p2 { width: 138px; height: 154px; right: -32px; top: 13%; transform: rotate(8deg);  --dur: 10.5s; animation-delay: 60ms, 1.1s; }
.p3 { width: 116px; height: 118px; left: 50%; margin-left: -58px; top: 40%; transform: rotate(-4deg); --dur: 8s; animation-delay: 300ms, 0.7s; }
.p4 { width: 132px; height: 150px; right: -36px; top: 66%; transform: rotate(-7deg); --dur: 11.5s; animation-delay: 240ms, 1.6s; }
.p5 { width: 120px; height: 130px; left: -36px; top: 59%; transform: rotate(6deg);  --dur: 9.8s;  animation-delay: 380ms, 0.2s; }
.voice-chip {
  position: absolute;
  left: 6px; bottom: 6px;
  background: #fff;
  border-radius: 20px;
  padding: 7px 12px;
  display: flex; align-items: center; gap: 8px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
}
.wave { display: flex; align-items: center; gap: 1.8px; height: 17px; }
.wave i { width: 2.2px; border-radius: 2px; background: #9aa3b2; display: block; }
.voice-time { font-size: 12px; font-weight: 700; color: #1a1f27; }
.welcome-center {
  position: relative;
  z-index: 3;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding-bottom: 11%;
}
.welcome-name, .welcome-tag { position: relative; }
.welcome-name {
  font-family: var(--serif);
  font-size: clamp(30px, 9.5vw, 40px);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.1;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.5);
  animation: riseIn 800ms var(--out) 520ms both;
}
.welcome-tag {
  margin-top: 5px;
  font-size: 17px;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 2px 14px rgba(0, 0, 0, 0.6);
  animation: riseIn 800ms var(--out) 640ms both;
}
  .welcome-center { padding-bottom: 6%; }

/* ============ COINS ============ */
/* The balance is the only entitlement on this site, so it is always on screen
   in the chat header rather than hidden behind a settings page. */
.coin-pill {
  flex: none;
  display: inline-flex; align-items: center; gap: 5px;
  height: 32px;
  padding: 0 11px 0 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #f1d98a;
  font-size: 13.5px; font-weight: 600;
  transition: transform 160ms var(--spring), background-color 160ms ease;
}
.coin-pill:active { transform: scale(0.94); }
.coin-pill.low {
  color: #ffc9a8;
  background: rgba(255, 138, 99, 0.16);
  border-color: rgba(255, 138, 99, 0.4);
}
.coin-ic { width: 17px; height: 17px; stroke: currentColor; stroke-width: 1.7; fill: none; }
.coin-ic.sm { width: 15px; height: 15px; }

/* ---- coins page ---- */
.coin-balance {
  display: flex; align-items: center; gap: 14px;
  padding: 18px 20px;
  border-radius: 20px;
  background: linear-gradient(120deg, rgba(224, 55, 155, 0.16), rgba(91, 71, 224, 0.16));
  border: 1px solid rgba(255, 255, 255, 0.1);
  margin-bottom: 14px;
}
.coin-balance .coin-ic { width: 34px; height: 34px; color: #f1d98a; stroke-width: 1.5; }
.coin-balance-num { font-family: var(--serif); font-size: 34px; line-height: 1; }
.coin-balance-lbl { font-size: 13px; color: var(--dim); margin-top: 3px; }

.coin-free {
  font-size: 13.5px; color: var(--dim);
  text-align: center;
  margin-bottom: 26px;
  line-height: 1.5;
}

.coin-rates {
  display: flex; flex-direction: column;
  border: 1px solid var(--line-soft);
  border-radius: 18px;
  overflow: hidden;
  margin-bottom: 8px;
}
.coin-rate {
  display: flex; align-items: center; gap: 13px;
  padding: 14px 17px;
  font-size: 15.5px;
  background: var(--surface);
}
.coin-rate + .coin-rate { border-top: 1px solid rgba(255, 255, 255, 0.055); }
.coin-rate .icon { width: 20px; height: 20px; stroke: #cfd6de; flex: none; }
.coin-rate span { flex: 1; }
.coin-rate b { color: #f1d98a; font-weight: 600; }

/* Two across on a phone; a pack is a glance, not a page. */
.coin-packs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 11px;
  margin-bottom: 10px;
}
.coin-pack {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 18px 10px 14px;
  border-radius: 18px;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  color: inherit;
  transition: transform 160ms var(--spring), border-color 160ms ease;
}
.coin-pack:active { transform: scale(0.97); }
.coin-pack.has-badge { border-color: rgba(224, 55, 155, 0.45); }
.coin-pack-badge {
  position: absolute;
  top: -9px; left: 50%; transform: translateX(-50%);
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  background: linear-gradient(120deg, #b03a79, #7d3bb8);
  color: #fff;
}
.coin-pack-coins {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 21px; font-weight: 600;
  color: #f1d98a;
}
.coin-pack-bonus { font-size: 12px; color: var(--faint); }
.coin-pack-price {
  margin-top: 7px;
  font-size: 16px; font-weight: 600;
  color: #fff;
}
.coin-empty { text-align: center; color: var(--dim); font-size: 15px; padding: 24px 0; }

/* The coin pill made a seventh item in the chat header and squeezed her name
   down to a few pixels. Everything here buys that name back its width. */
#page-chat .chat-head { gap: 6px; padding-left: 10px; padding-right: 10px; }
#page-chat .head-btn { width: 34px; height: 34px; }
#page-chat .head-btn .icon { width: 21px; height: 21px; }
#page-chat .head-av { width: 40px; height: 40px; }
#page-chat .head-meta { flex: 1 1 auto; min-width: 70px; }
#page-chat .head-name { font-size: 16px; }
#page-chat .coin-pill { height: 29px; padding: 0 9px 0 7px; font-size: 13px; gap: 4px; }
#page-chat .coin-pill .coin-ic { width: 14px; height: 14px; }

/* ============ UPI CHECKOUT ============ */
/* The amount is the mechanism, not a detail: the bank credit for those exact
   paise is what identifies the buyer. So it is the loudest thing on the card
   and the line under it says why it has to be exact. */
.pay-card { text-align: center; }

.pay-amt-wrap { margin-bottom: 10px; }
.pay-amt {
  font-family: var(--serif);
  font-size: 42px;
  line-height: 1;
  letter-spacing: -0.01em;
}
.pay-for { font-size: 14px; color: #f1d98a; margin-top: 5px; }
.pay-exact {
  font-size: 13px;
  line-height: 1.5;
  color: var(--dim);
  margin: 0 0 18px;
}
.pay-exact b { color: #fff; }

.pay-apps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 16px;
}
.pay-app {
  padding: 12px 6px;
  border-radius: 14px;
  font-size: 14px; font-weight: 500;
  background: var(--surface-2);
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: #e7ecf3;
  transition: transform 160ms var(--spring);
}
.pay-app:active { transform: scale(0.96); }
.pay-app.wide {
  grid-column: 1 / -1;
  background: linear-gradient(120deg, #b03a79, #7d3bb8 60%, #5244cf);
  border-color: rgba(255, 255, 255, 0.14);
  color: #fff;
}

.pay-qr {
  width: 180px;
  margin: 0 auto 12px;
  padding: 10px;
  border-radius: 16px;
  background: #fff;
  line-height: 0;
}
.pay-qr svg { width: 100%; height: auto; display: block; }

.pay-upi { font-size: 13.5px; color: var(--dim); }
.pay-upi b { color: #e7ecf3; }
.pay-timer { font-size: 12.5px; color: var(--faint); margin-top: 8px; }
.pay-link {
  display: block; width: 100%;
  margin-top: 14px;
  font-size: 14.5px;
  color: #c6ceda;
  text-decoration: underline;
}

.pay-or {
  font-size: 12.5px; color: var(--faint);
  margin: 12px 0 10px;
  text-transform: uppercase; letter-spacing: 0.1em;
}
.pay-input {
  width: 100%;
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: 17px;
  letter-spacing: 0.08em;
  text-align: center;
  color: #fff;
}
.pay-input:focus { border-color: rgba(224, 55, 155, 0.55); }

@media (max-height: 720px) {
  .pay-amt { font-size: 34px; }
  .pay-qr { width: 140px; }
}


/* ============ coin sheet + gifts ============ */
/* Bottom sheets, because the thing being asked for is a purchase and a
   purchase should not cost you your place in the conversation. */
.sheet-bottom { align-items: flex-end; }
.coin-sheet {
  width: 100%;
  max-width: var(--shell);
  border-radius: 26px 26px 0 0;
  padding: 10px 18px calc(18px + var(--safe-b));
  text-align: left;
  animation: sheetUp 320ms var(--out) both;
}
@keyframes sheetUp { from { transform: translate3d(0, 100%, 0) } to { transform: none } }
.cs-grab { width: 40px; height: 4px; border-radius: 4px; background: rgba(255,255,255,.22); margin: 0 auto 16px; }
.cs-head { display: flex; align-items: center; gap: 13px; margin-bottom: 16px; }
.cs-ic {
  width: 46px; height: 46px; border-radius: 15px; flex: none;
  display: grid; place-items: center;
  background: linear-gradient(135deg, #FFD873, #F0A521);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.5);
}
.cs-ic.gift { background: linear-gradient(135deg, #FF93D2, #E43CFC); }
.cs-ic .icon { width: 24px; height: 24px; stroke: #fff; fill: none; }
.cs-head-t b { display: block; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.cs-head-t span { display: block; font-size: 13.5px; color: var(--dim); margin-top: 2px; }

.cs-packs { display: flex; flex-direction: column; gap: 9px; }
.cs-pack {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: var(--surface); border-radius: 18px; padding: 12px 13px;
  border: 1.5px solid transparent;
}
.cs-pack.best { border-color: var(--btn); }
.cs-pack-coins { display: flex; align-items: center; gap: 7px; font-size: 19px; font-weight: 650; }
.cs-pack-mid { flex: 1; min-width: 0; text-align: left; }
.cs-pack-bonus { display: block; font-size: 11.5px; color: var(--green); font-weight: 600; margin-top: 2px; }
.cs-pack-price {
  flex: none; min-width: 74px; text-align: center; border-radius: 999px;
  padding: 10px 14px; font-size: 15px; font-weight: 600;
  background: var(--btn); color: var(--btn-ink);
}
.cs-later {
  display: block; width: 100%; margin-top: 14px; padding: 12px;
  font-size: 14.5px; color: var(--dim); font-weight: 500;
}

.gift-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.gift-item {
  background: var(--surface); border-radius: 18px; padding: 13px 6px 11px;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  border: 1.5px solid transparent;
}
.gift-item.cant { opacity: .45; }
.gift-art { font-size: 30px; line-height: 1.1; }
.gift-name { font-size: 12px; font-weight: 550; }
.gift-cost { display: flex; align-items: center; gap: 4px; font-size: 12.5px; font-weight: 650; color: var(--yellow); }
.gift-cost .coin-ic { width: 13px; height: 13px; }

/* the day's coins, offered once on the way in */
.daily-pop {
  position: fixed; left: 50%; bottom: calc(22px + var(--safe-b)); transform: translateX(-50%);
  z-index: 60; display: flex; align-items: center; gap: 11px;
  background: linear-gradient(135deg, #FFD873, #F0A521);
  color: #4A3503; padding: 11px 13px 11px 11px; border-radius: 999px;
  box-shadow: 0 10px 26px rgba(214,150,20,.45);
  animation: dailyIn 460ms var(--spring) both;
  max-width: calc(100% - 32px);
}
@keyframes dailyIn { from { opacity: 0; transform: translate(-50%, 18px) scale(.94) } to { opacity: 1; transform: translateX(-50%) } }
.daily-pop b { font-size: 14px; font-weight: 700; }
.daily-pop small { display: block; font-size: 11.5px; opacity: .8; font-weight: 600; }
.daily-claim {
  background: #fff; color: #8A5A08; border-radius: 999px; padding: 8px 15px;
  font-size: 13px; font-weight: 700; flex: none;
}


/* ============ gift animations ============ */
/* The stage covers everything and takes taps, so the pyrotechnics cannot be
   interacted through and a tap anywhere ends them early. */
:root { --gfx-spring: cubic-bezier(.2,1.5,.4,1); --gfx-out: cubic-bezier(.22,1,.36,1); }

.gfx-stage {
  position: fixed; inset: 0; z-index: 2000;
  overflow: hidden; pointer-events: auto;
  background: radial-gradient(circle at 50% 45%, rgba(8,4,18,.80), rgba(4,2,10,.95));
  animation: gfxIn 260ms ease both;
  -webkit-tap-highlight-color: transparent;
}
@keyframes gfxIn  { from { opacity: 0 } to { opacity: 1 } }
@keyframes gfxOut { to { opacity: 0 } }

.gfx-p {
  position: absolute; will-change: transform, opacity;
  line-height: 1; pointer-events: none; user-select: none;
}
@keyframes gfxBurst {
  0%   { transform: translate3d(-50%,-50%,0) scale(.3) rotate(0); opacity: 0 }
  18%  { opacity: 1 }
  100% { transform: translate3d(calc(-50% + var(--dx)), calc(-50% + var(--dy)), 0) scale(1) rotate(var(--rot));
         opacity: 0 }
}
@keyframes gfxRain {
  0%   { transform: translate3d(0,0,0) rotate(0); opacity: 0 }
  12%  { opacity: 1 }
  100% { transform: translate3d(var(--drift), 112vh, 0) rotate(var(--rot)); opacity: 0 }
}

.gfx-hero {
  position: absolute; left: 50%; top: 46%;
  font-size: clamp(76px, 25vw, 132px); line-height: 1;
  pointer-events: none; user-select: none;
  filter: drop-shadow(0 10px 26px rgba(0,0,0,.55));
}
@keyframes gfxPop {
  0%   { transform: translate(-50%,-50%) scale(.1) rotate(-28deg); opacity: 0 }
  60%  { opacity: 1 }
  100% { transform: translate(-50%,-50%) scale(1) rotate(0); opacity: 1 }
}
@keyframes gfxFloat {
  0%,100% { transform: translate(-50%,-50%) scale(1) }
  50%     { transform: translate(-50%,-54%) scale(1.04) }
}
@keyframes gfxWobble {
  0%,100% { transform: translate(-50%,-50%) rotate(0) }
  25%     { transform: translate(-50%,-50%) rotate(-7deg) }
  75%     { transform: translate(-50%,-50%) rotate(7deg) }
}
@keyframes gfxDrop {
  0%   { transform: translate(-50%,-320%) scale(.7); opacity: 0 }
  45%  { transform: translate(-50%,-42%) scale(1.12); opacity: 1 }
  62%  { transform: translate(-50%,-62%) scale(.95) }
  80%  { transform: translate(-50%,-46%) scale(1.05) }
  100% { transform: translate(-50%,-50%) scale(1) }
}
@keyframes gfxRise {
  0%   { transform: translate(-50%, 210%) scale(.7) rotate(-14deg); opacity: 0 }
  100% { transform: translate(-50%,-50%) scale(1) rotate(0); opacity: 1 }
}
@keyframes gfxSpinIn {
  0%   { transform: translate(-50%,-50%) scale(.05) rotateY(0); opacity: 0 }
  55%  { opacity: 1 }
  100% { transform: translate(-50%,-50%) scale(1) rotateY(1080deg); opacity: 1 }
}
@keyframes gfxCrownDrop {
  0%   { transform: translate(-50%,-300%) scale(.5) rotate(-18deg); opacity: 0 }
  55%  { transform: translate(-50%,-44%) scale(1.14) rotate(5deg); opacity: 1 }
  78%  { transform: translate(-50%,-54%) scale(.97) rotate(-2deg) }
  100% { transform: translate(-50%,-50%) scale(1) rotate(0) }
}

.gfx-flash { position: absolute; inset: 0; pointer-events: none; }
@keyframes gfxFlash { 0% { opacity: 0 } 22% { opacity: 1 } 100% { opacity: 0 } }

.gfx-ring {
  position: absolute; left: 50%; top: 46%;
  width: 90px; height: 90px; margin: -45px 0 0 -45px;
  border-radius: 50%; border: 3px solid #fff; pointer-events: none;
}
@keyframes gfxRing {
  0%   { transform: scale(.2); opacity: .95; border-width: 5px }
  100% { transform: scale(5.4); opacity: 0; border-width: 1px }
}

.gfx-rocket {
  position: absolute; left: 50%; bottom: 0;
  font-size: clamp(42px, 13vw, 66px); line-height: 1; pointer-events: none;
  filter: drop-shadow(0 0 16px rgba(255,180,80,.9));
}
@keyframes gfxRocket {
  0%   { transform: translate(-50%, 40px) rotate(-18deg) scale(.8); opacity: 0 }
  14%  { opacity: 1 }
  88%  { opacity: 1 }
  100% { transform: translate(-50%, -58vh) rotate(-18deg) scale(1.1); opacity: 0 }
}

/* the shaft of light the crown comes down in */
.gfx-beam {
  position: absolute; left: 50%; top: 0; width: 46vw; max-width: 260px;
  height: 62vh; margin-left: -23vw; pointer-events: none;
  background: linear-gradient(180deg, rgba(255,214,120,.5) 0%, rgba(255,190,90,.14) 55%, rgba(255,190,90,0) 100%);
  clip-path: polygon(38% 0, 62% 0, 100% 100%, 0 100%);
}
@media (min-width: 580px) { .gfx-beam { margin-left: -130px } }
@keyframes gfxBeam { 0% { opacity: 0 } 25% { opacity: 1 } 100% { opacity: 0 } }

.gfx-rays {
  position: absolute; left: 50%; top: 46%; width: 150vmax; height: 150vmax;
  margin: -75vmax 0 0 -75vmax; pointer-events: none; opacity: .5;
  background: repeating-conic-gradient(from 0deg,
    rgba(255,255,255,.22) 0deg 7deg, rgba(255,255,255,0) 7deg 20deg);
  -webkit-mask-image: radial-gradient(circle, #000 12%, transparent 55%);
  mask-image: radial-gradient(circle, #000 12%, transparent 55%);
}
@keyframes gfxRays { to { transform: rotate(360deg) } }

.gfx-label {
  position: absolute; left: 50%; top: 68%; transform: translateX(-50%);
  font-size: 19px; font-weight: 650; letter-spacing: .01em; color: #fff;
  text-shadow: 0 2px 14px rgba(0,0,0,.7); white-space: nowrap; pointer-events: none;
}
@keyframes gfxLabel {
  0%   { opacity: 0; transform: translate(-50%, 14px) }
  25%  { opacity: 1; transform: translateX(-50%) }
  78%  { opacity: 1 }
  100% { opacity: 0 }
}


/* ============================================================
   LIGHT THEME — the ChaloJi look for the app screens
   ============================================================
   Written as overrides under html:not([data-theme="dark"]) rather than by
   editing the rules above, so the dark theme stays byte for byte what it
   always was. Everything here is a colour or a shadow; no layout moves
   between themes, which is what keeps the two from drifting apart.

   The splash and welcome pages are deliberately untouched: they keep the
   night sky in both themes because that screen is the brand. */

html:not([data-theme="dark"]) {

  /* ---------------- chat ---------------- */
  /* The starfield belongs to the night sky. In light it becomes the soft
     lilac wash the reference app uses behind its conversations. */
  #page-chat {
    background:
      radial-gradient(120% 52% at 12% 0%, #F7ECFF 0%, rgba(247, 236, 255, 0) 60%),
      radial-gradient(90% 38% at 100% 6%, #FFE9F8 0%, rgba(255, 233, 248, 0) 55%),
      linear-gradient(180deg, #FBF6FF 0%, #F7F0FE 100%);
  }
  .chat-head::before { background: rgba(255, 255, 255, 0.94); }
  .chat-head::after  { background: rgba(26, 16, 48, 0.08); }
  .hangout-pill {
    background: #ffffff;
    color: var(--ink, #1A1030);
    box-shadow: 0 2px 10px rgba(120, 60, 200, 0.12);
  }

  /* Her side: white, the way every messenger does the other person. */
  .msg-ai {
    background: #ffffff;
    color: #2A1F3D;
    border-color: rgba(26, 16, 48, 0.05);
    box-shadow: 0 3px 14px rgba(120, 60, 200, 0.10);
  }
  /* Your side keeps the brand, just the cleaner two-stop version. */
  .msg-user {
    background: var(--brand);
    border-color: rgba(255, 255, 255, 0.18);
    box-shadow: 0 6px 18px rgba(195, 70, 250, 0.32);
  }
  /* The clock line hangs BELOW the bubble, so on your side it sits on the page
     background, not on the gradient. White there is invisible. */
  .msg-ai .msg-meta, .msg-user .msg-meta { color: #A99BC0; }
  .msg-user .ticks { stroke: #C3B2D8; }
  .msg-user .ticks.delivered { stroke: var(--violet); }

  .composer {
    background: rgba(251, 246, 255, 0.94);
    border-top-color: rgba(26, 16, 48, 0.07);
  }
  .composer-bar {
    background: #ffffff;
    border-color: rgba(26, 16, 48, 0.07);
    box-shadow: 0 4px 16px rgba(120, 60, 200, 0.13);
  }
  .composer-bar:focus-within {
    background: #ffffff;
    border-color: rgba(168, 72, 252, 0.4);
    box-shadow: 0 6px 20px rgba(168, 72, 252, 0.2);
  }
  .round-btn { background: #ffffff; box-shadow: 0 3px 10px rgba(120, 60, 200, 0.14); }
  .round-btn:active { background: #F3EAFC; }
  /* the gift button earns its colour; it is the one that spends money */
  .gift-btn { background: var(--brand); color: #fff; }
  .gift-btn .icon { stroke: #fff; }
  .mic-send { background: var(--brand); }
  .mic-send .icon { stroke: #fff; }

  /* ---------------- the brand button ---------------- */
  /* --btn is a flat colour in dark and the gradient here, so anything that
     paints with it needs the gradient too. */
  .btn-pill-white, .btn-dark, .welcome-cta, .cs-pack-price, .pack-buy {
    background: var(--brand);
    color: #fff;
  }

  /* ---------------- coins ---------------- */
  .coin-balance {
    background: linear-gradient(135deg, var(--gold-1) 0%, var(--gold-2) 54%, var(--gold-3) 100%);
    color: var(--gold-ink);
    box-shadow: 0 10px 26px rgba(214, 150, 20, 0.3), inset 0 1.5px 0 rgba(255, 255, 255, 0.9);
    border: 0;
  }
  .coin-balance-num { color: #4A3503; }
  .coin-balance-lbl { color: #7A5A0E; }
  .coin-rate { background: #ffffff; }
  .coin-pack, .cs-pack, .gift-item {
    background: #ffffff;
    box-shadow: 0 4px 16px rgba(120, 60, 200, 0.10);
  }
  .coin-pack.has-badge, .cs-pack.best { border-color: var(--violet); }

  /* ---------------- sheets and modals ---------------- */
  .modal-scrim { background: rgba(26, 16, 48, 0.46); }
  .modal-card { background: #ffffff; box-shadow: 0 -14px 50px rgba(80, 40, 140, 0.26); }
  .cs-grab { background: #E8DCF6; }
  .cs-ic .icon { stroke: #fff; }

  /* ---------------- settings ---------------- */
  .set-row { background: #ffffff; }
  /* the icon ramp was tuned for a dark surface; on white it disappears */
  .set-row .icon { stroke: var(--dim); }
  .set-row:active { background: #FAF5FF; }
  .toggle { background: #E0D4F2; }
  .toggle.on { background: var(--violet); }
}

/* Light mode on a phone: the status bar area should read as part of the app,
   not as a dark strip left over from the other theme. */
html:not([data-theme="dark"]) body { background: var(--bg-deep); }


/* ============ coins, the ported design ============ */
/* Art sizes are fixed in px rather than em: these are drawings, and they
   should be the same size whatever the surrounding type does. */
#page-coins { overflow-y: auto; }
#page-coins::-webkit-scrollbar { width: 0; }

.cn-top { display: flex; align-items: center; gap: 6px; padding: calc(10px + var(--safe-t)) 12px 14px; flex: none; }
.cn-back { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; color: var(--text); }
.cn-back .icon { width: 21px; height: 21px; }
.cn-title { font-family: var(--sans); font-size: 21px; font-weight: 700; letter-spacing: -.02em; }
.cn-body { padding: 0 0 30px; }

.cn-balance {
  position: relative; margin: 0 18px; border-radius: 26px; padding: 20px 22px 18px; overflow: hidden;
  background: linear-gradient(135deg, var(--gold-1) 0%, var(--gold-2) 54%, var(--gold-3) 100%);
  box-shadow: 0 12px 28px rgba(214, 150, 20, .32), inset 0 1.5px 0 rgba(255, 255, 255, .9);
}
/* behind the copy, low enough that nothing ever collides with it */
.cn-bal-art { position: absolute; right: -22px; top: 50%; transform: translateY(-50%);
  width: 132px; height: 132px; opacity: .42; pointer-events: none; }
.cn-bal-lbl { font-size: 10.5px; font-weight: 800; color: #B8860B; letter-spacing: .14em; }
.cn-bal-num { display: flex; align-items: center; gap: 11px; margin-top: 5px; }
.cn-bal-num svg { width: 38px; height: 38px; flex: none; }
.cn-bal-num b { font-size: 48px; font-weight: 900; color: #4A3503; line-height: .95;
  letter-spacing: -.035em; font-variant-numeric: tabular-nums; }
.cn-bal-sub { font-size: 11.5px; color: #7A5A0E; margin-top: 8px; font-weight: 600; }

.cn-sec { font-size: 11px; font-weight: 800; color: var(--dim); letter-spacing: .13em; margin: 26px 20px 11px; }

.cn-rates { margin: 0 18px; background: var(--surface); border-radius: 22px; overflow: hidden; box-shadow: var(--e2); }
.cn-rate { display: flex; align-items: center; gap: 13px; padding: 14px 17px; border-bottom: 1px solid var(--line-soft); }
.cn-rate:last-child { border-bottom: 0; }
.cn-rico { width: 40px; height: 40px; border-radius: 14px; display: grid; place-items: center; flex: none;
  color: #fff; box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, .5), 0 5px 12px rgba(80, 40, 140, .2); }
.cn-rico .icon { width: 19px; height: 19px; fill: #fff; stroke: none; }
.cn-rico.violet { background: linear-gradient(135deg, #C488FF, #A848FC); }
.cn-rico.green  { background: linear-gradient(135deg, #6FE0AE, #15B877); }
.cn-rico.pink   { background: linear-gradient(135deg, #FF9BC0, #F0255F); }
.cn-rname { font-size: 14.5px; font-weight: 600; flex: 1; letter-spacing: -.01em; }
.cn-rcost { display: flex; align-items: center; gap: 6px; font-size: 16px; font-weight: 800;
  color: var(--gold); font-variant-numeric: tabular-nums; }
.cn-rcost svg { width: 19px; height: 19px; }

/* A list, not a grid: the grid clipped the bonus line and squeezed the art. */
.cn-packs { display: flex; flex-direction: column; gap: 11px; margin: 0 18px; }
.cn-pack {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left; position: relative;
  background: var(--surface); border-radius: 22px; padding: 13px 14px 13px 12px;
  border: 2px solid transparent; box-shadow: var(--e2);
  transition: transform .14s var(--spring);
}
.cn-pack:active { transform: scale(.975); }
.cn-pack.featured { border-color: var(--violet); box-shadow: 0 10px 26px rgba(168, 72, 252, .26); }
.cn-pack-art { width: 62px; height: 62px; flex: none; display: grid; place-items: center; }
.cn-pack-art svg { width: 62px; height: 62px; filter: drop-shadow(0 4px 7px rgba(140, 80, 20, .26)); }
.cn-pack-mid { flex: 1; min-width: 0; }
.cn-pack-num { display: flex; align-items: baseline; gap: 6px; font-size: 25px; font-weight: 900;
  letter-spacing: -.035em; line-height: 1; font-variant-numeric: tabular-nums; }
.cn-pack-num small { font-size: 10.5px; font-weight: 800; color: var(--dim); letter-spacing: .13em; }
.cn-bonus { display: inline-block; margin-top: 6px; font-size: 11px; font-weight: 800; color: var(--green);
  background: rgba(21, 184, 119, .13); padding: 3px 9px; border-radius: 999px; }
.cn-price { flex: none; min-width: 84px; text-align: center; border-radius: 999px; padding: 11px 14px;
  font-size: 15.5px; font-weight: 800; color: #fff; background: var(--brand); letter-spacing: -.01em;
  box-shadow: 0 5px 14px rgba(195, 70, 250, .36); }
.cn-tag { position: absolute; top: -9px; left: 16px; background: var(--brand); color: #fff; font-size: 9px;
  font-weight: 900; letter-spacing: .11em; padding: 4px 10px; border-radius: 999px;
  box-shadow: 0 4px 10px rgba(195, 70, 250, .45); }
.cn-pack.featured .cn-tag { background: linear-gradient(135deg, #FF9D3C, #F04A1E);
  box-shadow: 0 4px 10px rgba(240, 74, 30, .45); }


/* ============ pay sheet, the ported gateway ============ */
/* A gateway states who is being paid before it states anything else, so the
   merchant row comes first and the amount second. */
.pay-card { padding: 0 !important; overflow: hidden; }
.pg-merchant { display: flex; align-items: center; gap: 11px; padding: 18px 22px 15px;
  border-bottom: 1px solid var(--line-soft); }
.pg-logo { width: 38px; height: 38px; border-radius: 12px; overflow: hidden; flex: none;
  background: var(--brand); padding: 2px; }
.pg-logo img { width: 100%; height: 100%; border-radius: 10px; object-fit: cover; display: block; }
.pg-who { flex: 1; min-width: 0; text-align: left; }
.pg-who b { display: block; font-size: 14.5px; font-weight: 700; line-height: 1.2; }
.pg-who span { display: block; font-size: 11.5px; color: var(--dim); font-weight: 500; margin-top: 1px; }
.pg-secure { display: flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 700;
  color: var(--green); background: rgba(21, 184, 119, .12); padding: 5px 10px; border-radius: 999px; flex: none; }
.pg-secure .icon { width: 11px; height: 11px; fill: currentColor; stroke: none; }

.pg-body { padding: 20px 22px calc(22px + var(--safe-b)); }
.pg-amt { text-align: center; font-size: 46px; font-weight: 900; line-height: 1;
  letter-spacing: -.045em; font-variant-numeric: tabular-nums; }
.pg-amt-lbl { text-align: center; font-size: 13px; color: var(--dim); font-weight: 600; margin-top: 8px; }

.pg-exact { margin: 16px 0 20px; display: flex; gap: 9px; align-items: flex-start;
  background: rgba(232, 162, 30, .1); border: 1px solid rgba(232, 162, 30, .32);
  border-radius: 14px; padding: 11px 13px; }
.pg-exact .icon { width: 15px; height: 15px; flex: none; margin-top: 1px; fill: var(--gold); stroke: none; }
.pg-exact span { font-size: 12px; line-height: 1.5; font-weight: 500; color: var(--text); opacity: .85; text-align: left; }
.pg-exact b { font-weight: 800; opacity: 1; }

.pg-lbl { font-size: 10.5px; font-weight: 800; color: var(--dim); letter-spacing: .13em; margin-bottom: 11px; text-align: left; }
.pg-apps { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
.pg-app { background: var(--surface); border: 1.5px solid var(--line); border-radius: 18px;
  padding: 14px 6px 11px; display: flex; flex-direction: column; align-items: center; gap: 8px;
  box-shadow: var(--e1); transition: transform .14s var(--spring); }
.pg-app:active { transform: scale(.96); }
.pg-mark { width: 48px; height: 48px; border-radius: 16px; display: grid; place-items: center;
  background: #fff; box-shadow: 0 3px 10px rgba(80, 40, 140, .14); }
.pg-name { font-size: 12px; font-weight: 700; }
.pg-any { margin-top: 10px; width: 100%; border: 1.5px solid var(--line); background: var(--surface);
  border-radius: 18px; padding: 14px; font-size: 14px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; gap: 9px; box-shadow: var(--e1); }
.pg-any .icon { width: 18px; height: 18px; fill: currentColor; stroke: none; }
.pg-upi { margin-top: 14px; background: var(--surface-2); border-radius: 14px; padding: 12px 15px; text-align: left; }
.pg-upi span { font-size: 11.5px; color: var(--dim); font-weight: 600; }
.pg-upi b { display: block; font-size: 13.5px; font-weight: 700; margin-top: 1px; color: var(--violet); }
.pg-timer { display: flex; align-items: center; justify-content: center; gap: 7px; margin-top: 16px;
  font-size: 12px; color: var(--dim); font-weight: 600; }
.pg-timer .icon { width: 14px; height: 14px; fill: currentColor; stroke: none; }
.pg-paid { display: block; width: 100%; margin-top: 14px; font-size: 13.5px; font-weight: 700;
  color: var(--violet); padding: 6px; }

/* the badge the server sends is lowercase; the design shouts it */
.cn-tag { text-transform: uppercase; }

/* ============ COIN FEEDBACK + DAILY RUN ============ */
/* A balance that changes quietly is a balance nobody reads, so both
   directions are animated: spends lift off the pill, the daily collect flies
   into it. Everything here is transform and opacity only — these run on every
   message and have to stay off the main thread on a cheap phone. */

@keyframes cpBump {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}
.cp-bump { animation: cpBump 420ms var(--spring, cubic-bezier(.34,1.56,.64,1)); }

.coin-delta {
  position: fixed;
  z-index: 9000;
  transform: translate(-50%, 0);
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: .2px;
  pointer-events: none;
  text-shadow: 0 2px 10px rgba(0, 0, 0, .55);
  animation: coinDelta 1.2s cubic-bezier(.2, .8, .3, 1) forwards;
}
.coin-delta svg { width: 13px; height: 13px; }
.coin-delta.minus { color: #ff6b8a; }
.coin-delta.plus  { color: #ffd34d; }
@keyframes coinDelta {
  0%   { opacity: 0; transform: translate(-50%, -2px) scale(.8); }
  18%  { opacity: 1; transform: translate(-50%, 6px) scale(1.06); }
  100% { opacity: 0; transform: translate(-50%, 34px) scale(.92); }
}

.fly-coin {
  position: fixed;
  z-index: 9000;
  width: 26px; height: 26px;
  pointer-events: none;
  transition: transform 640ms cubic-bezier(.3, .7, .2, 1), opacity 640ms ease-in;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, .45));
}
.fly-coin svg { width: 100%; height: 100%; }

/* ---- the seven day card ---- */
.dz-scrim {
  position: fixed; inset: 0; z-index: 8000;
  display: flex; align-items: center; justify-content: center;
  padding: max(18px, env(safe-area-inset-left, 0px)) 18px;
  background: rgba(6, 9, 14, .72);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 240ms ease;
}
.dz-scrim.show { opacity: 1; }

.dz-card {
  position: relative;
  width: 100%; max-width: 360px;
  border-radius: 24px;
  padding: 22px 18px 16px;
  background: linear-gradient(180deg, #1b2130, #121722);
  border: 1px solid rgba(255, 255, 255, .1);
  box-shadow: 0 22px 60px rgba(0, 0, 0, .6);
  text-align: center;
  overflow: hidden;
  transform: translateY(14px) scale(.96);
  transition: transform 320ms cubic-bezier(.34, 1.4, .64, 1);
}
.dz-scrim.show .dz-card { transform: none; }

/* a warm bloom behind the grid so the card does not read as a dialog */
.dz-glow {
  position: absolute; left: 50%; top: -70px;
  width: 260px; height: 190px; transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(255, 196, 61, .3), transparent 70%);
  pointer-events: none;
}

.dz-title {
  position: relative;
  font-family: var(--serif, Georgia, serif);
  font-size: 25px; font-weight: 600; color: #fff;
}
.dz-sub {
  position: relative;
  font-size: 12.5px; color: rgba(255, 255, 255, .58);
  margin-top: 4px; margin-bottom: 16px;
}

.dz-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 16px;
}
.dz-day {
  border-radius: 13px;
  padding: 9px 4px 8px;
  background: rgba(255, 255, 255, .045);
  border: 1px solid rgba(255, 255, 255, .07);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 0;
}
/* day seven is the payoff, so it takes the whole last row and says so */
.dz-day.finale { grid-column: span 4; flex-direction: row; justify-content: center; gap: 9px; padding: 10px; }

.dz-n   { font-size: 10px; letter-spacing: .4px; color: rgba(255, 255, 255, .45); text-transform: uppercase; }
.dz-art { font-size: 19px; line-height: 1.1; }
.dz-amt { font-size: 14px; font-weight: 800; color: #ffd34d; }

.dz-day.done { background: rgba(255, 255, 255, .025); border-color: transparent; }
.dz-day.done .dz-art { color: #5ad18f; font-size: 16px; }
.dz-day.done .dz-amt { color: rgba(255, 255, 255, .3); }
.dz-day.soon { opacity: .45; }

.dz-day.live {
  background: linear-gradient(180deg, rgba(255, 196, 61, .2), rgba(255, 140, 60, .09));
  border-color: rgba(255, 196, 61, .55);
  box-shadow: 0 0 0 3px rgba(255, 196, 61, .12);
  animation: dzBreathe 2.1s ease-in-out infinite;
}
@keyframes dzBreathe {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}
.dz-day.live .dz-art { animation: dzWobble 1.5s ease-in-out infinite; }
@keyframes dzWobble {
  0%, 100% { transform: rotate(-7deg); }
  50%      { transform: rotate(7deg); }
}
.dz-day.popped { animation: dzPop 420ms cubic-bezier(.34, 1.56, .64, 1); }
@keyframes dzPop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.22); }
  100% { transform: scale(1); }
}

.dz-collect {
  position: relative;
  width: 100%;
  border: 0; border-radius: 999px;
  padding: 14px 18px;
  font-size: 16px; font-weight: 800; color: #1a1205;
  background: linear-gradient(135deg, #ffd34d, #ffa53d);
  box-shadow: 0 8px 22px rgba(255, 170, 60, .34);
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  cursor: pointer;
}
.dz-collect:active { transform: scale(.97); }
.dz-collect.spent {
  background: rgba(255, 255, 255, .1);
  color: #9fe7bd;
  box-shadow: none;
}
.dz-box { font-size: 18px; }
.dz-later {
  margin-top: 8px;
  background: none; border: 0;
  font-size: 13.5px; color: rgba(255, 255, 255, .42);
  padding: 8px; cursor: pointer;
}

@media (max-height: 640px) {
  .dz-title { font-size: 21px; }
  .dz-grid { gap: 6px; }
  .dz-art { font-size: 16px; }
}
