/* ============================================================================
   Oremi UI — shared surface layer
   ----------------------------------------------------------------------------
   One stylesheet, linked from every page. The site had no shared CSS at all:
   each of 24 pages carried its own inline copy, so a change to the background
   meant 24 edits and they had already drifted apart. Anything defined here
   overrides the per-page `.bg-stage` blocks without touching them.

   Three ideas, in order of importance:
     1. Depth you fall into  — parallax layers on a real perspective plane
     2. Air                  — a light sky field that drifts, never distracts
     3. Restraint            — motion is slow, low-contrast and always optional

   Everything animates on transform/opacity only, so it stays on the compositor
   and costs nothing on scroll. All motion is off under prefers-reduced-motion.
   ============================================================================ */

:root{
  --sky-0:#f7fbff;   /* horizon, lightest */
  --sky-1:#eaf4ff;
  --sky-2:#dcecfe;
  --sky-3:#cfe4fd;   /* deepest field */
  --brand:#2563eb;
  --brand-strong:#1b3fae;
  --accent:#0fb5a6;
  --ink:#0b1220;
  --ink-2:#334155;
  --ink-3:#64748b;
  --line:rgba(15,23,42,.08);

  /* Spatial elevation scale — each step is further from the page, not just darker */
  --lift-1:0 1px 2px rgba(15,23,42,.04), 0 4px 12px -6px rgba(37,99,235,.14);
  --lift-2:0 2px 6px rgba(15,23,42,.05), 0 14px 32px -14px rgba(37,99,235,.22);
  --lift-3:0 6px 14px rgba(15,23,42,.06), 0 34px 64px -28px rgba(37,99,235,.30);
}

/* ---------------------------------------------------------------------------
   1. The sky
   Fixed behind everything. Four layers at different depths; the far ones move
   slowly and blur more, which is what sells distance. `will-change` is set only
   on the layers that actually animate.
   --------------------------------------------------------------------------- */
.bg-stage,
.oremi-sky{
  position:fixed; inset:0; z-index:0; overflow:hidden; pointer-events:none;
  background:
    radial-gradient(120% 80% at 50% 120%, var(--sky-3) 0%, transparent 62%),
    linear-gradient(180deg, var(--sky-0) 0%, var(--sky-1) 46%, var(--sky-2) 100%);
}

.oremi-sky__layer{
  position:absolute; border-radius:50%;
  will-change:transform; backface-visibility:hidden;
}

/* Far field — big, soft, barely moves */
.oremi-sky__layer--far{
  width:78vmax; height:78vmax; left:-18vmax; top:-26vmax;
  background:radial-gradient(circle at 38% 38%, rgba(37,99,235,.16), transparent 62%);
  filter:blur(48px);
  animation:oremiDriftFar 64s ease-in-out infinite alternate;
}

/* Mid field — the teal counterweight, keeps the blue from going cold */
.oremi-sky__layer--mid{
  width:62vmax; height:62vmax; right:-20vmax; top:4vmax; left:auto;
  background:radial-gradient(circle at 60% 40%, rgba(15,181,166,.15), transparent 60%);
  filter:blur(40px);
  animation:oremiDriftMid 48s ease-in-out infinite alternate;
}

/* Near field — smallest and fastest, gives the parallax a reference point */
.oremi-sky__layer--near{
  width:44vmax; height:44vmax; left:32vmax; bottom:-22vmax; top:auto;
  background:radial-gradient(circle at 50% 50%, rgba(99,102,241,.16), transparent 58%);
  filter:blur(30px);
  animation:oremiDriftNear 36s ease-in-out infinite alternate;
}

/* Horizon glow — anchors the bottom so the page feels like it rests on light */
.oremi-sky__horizon{
  position:absolute; left:50%; bottom:-34vh; width:150vw; height:70vh;
  transform:translateX(-50%);
  background:radial-gradient(60% 60% at 50% 50%, rgba(255,255,255,.92), transparent 70%);
  filter:blur(24px);
}

/* A whisper of grain. Without it, big soft gradients band on wide displays. */
.oremi-sky__grain{
  position:absolute; inset:-50%; opacity:.035; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

@keyframes oremiDriftFar{
  0%  { transform:translate3d(0,0,0) scale(1); }
  100%{ transform:translate3d(7vw,5vh,0) scale(1.10); }
}
@keyframes oremiDriftMid{
  0%  { transform:translate3d(0,0,0) scale(1.04); }
  100%{ transform:translate3d(-8vw,7vh,0) scale(1); }
}
@keyframes oremiDriftNear{
  0%  { transform:translate3d(0,0,0) scale(1); }
  100%{ transform:translate3d(-10vw,-8vh,0) scale(1.14); }
}

/* Scroll-linked descent: the far layers lag, so scrolling reads as moving
   *through* the field rather than past a picture. Progressive enhancement —
   browsers without scroll-timeline simply keep the ambient drift. */
@supports (animation-timeline: scroll()){
  @media (prefers-reduced-motion:no-preference){
    .oremi-sky__layer--far{  animation:oremiDriftFar 64s ease-in-out infinite alternate, oremiFallFar auto linear; animation-timeline:auto, scroll(root); }
    .oremi-sky__layer--near{ animation:oremiDriftNear 36s ease-in-out infinite alternate, oremiFallNear auto linear; animation-timeline:auto, scroll(root); }
  }
}
@keyframes oremiFallFar { to{ translate:0 12vh; } }
@keyframes oremiFallNear{ to{ translate:0 -20vh; } }

/* ---------------------------------------------------------------------------
   2. Spatial primitives
   --------------------------------------------------------------------------- */

/* A pane that sits above the sky rather than on top of it. */
.o-pane{
  position:relative; isolation:isolate;
  background:linear-gradient(160deg, rgba(255,255,255,.82), rgba(255,255,255,.62));
  border:1px solid rgba(255,255,255,.75);
  border-radius:22px;
  box-shadow:var(--lift-2), inset 0 1px 0 rgba(255,255,255,.9);
  backdrop-filter:blur(18px) saturate(180%);
  -webkit-backdrop-filter:blur(18px) saturate(180%);
}
.o-pane--flush{ border-radius:0; border-left:0; border-right:0; }

/* Opt-in hover lift. Transform only — no layout thrash. */
.o-lift{ transition:transform .35s cubic-bezier(.2,.8,.2,1), box-shadow .35s; }
.o-lift:hover{ transform:translateY(-3px); box-shadow:var(--lift-3); }

/* Perspective container for anything that should tilt in space. */
.o-stage{ perspective:1400px; transform-style:preserve-3d; }

/* ---------------------------------------------------------------------------
   3. Bottom bars — footers and any sticky dock
   Frosted, edge-lit along the top, so the page appears to continue underneath
   instead of stopping at a solid slab.
   --------------------------------------------------------------------------- */
.o-bottombar{
  position:relative;
  background:linear-gradient(180deg, rgba(255,255,255,.72), rgba(255,255,255,.88));
  border-top:1px solid rgba(255,255,255,.8);
  backdrop-filter:blur(20px) saturate(180%);
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  box-shadow:0 -18px 40px -30px rgba(37,99,235,.45);
}
.o-bottombar::before{
  content:''; position:absolute; left:0; right:0; top:-1px; height:1px;
  background:linear-gradient(90deg, transparent, rgba(37,99,235,.35), rgba(15,181,166,.30), transparent);
}

/* Sticky dock variant, for a persistent action bar on mobile. */
.o-dock{
  position:sticky; bottom:0; z-index:60;
  padding-bottom:max(.75rem, env(safe-area-inset-bottom));
}

/* ---------------------------------------------------------------------------
   4. Reduced motion — everything holds still, nothing disappears
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .oremi-sky__layer{ animation:none !important; }
  .o-lift{ transition:none; }
  .o-lift:hover{ transform:none; }
}

/* ============================================================================
   5. Device — a phone you can put real content inside
   Frame is drawn, not an image: it scales cleanly, themes with the palette and
   costs no download. The screen is a flex column so a chat, a screenshot or a
   live component can all sit in the same shell.
   ============================================================================ */
.o-phone{
  position:relative; width:clamp(248px,25vw,306px); aspect-ratio:9/19.5;
  border-radius:42px; padding:9px;
  background:linear-gradient(160deg,#1c2438,#0b1220 60%);
  box-shadow:
    0 2px 3px rgba(255,255,255,.35) inset,
    0 60px 100px -40px rgba(15,23,42,.55),
    0 20px 44px -28px rgba(37,99,235,.5);
}
.o-phone__screen{
  position:relative; height:100%; border-radius:34px; overflow:hidden;
  background:#f6f9ff; display:flex; flex-direction:column;
}
.o-phone__island{
  position:absolute; top:9px; left:50%; transform:translateX(-50%);
  width:31%; height:20px; border-radius:999px; background:#0b1220; z-index:3;
}
/* Direct child only. As a descendant rule this also matched the chat
   avatar — one class plus an element outranks a single class, so the
   30px avatar rule lost and the logo filled the entire header. */
.o-phone__screen > img{ width:100%; height:100%; object-fit:cover; display:block; }

/* chat surface ---------------------------------------------------------- */
.o-chat{ flex:1; display:flex; flex-direction:column; gap:.5rem; padding:2.6rem .75rem 1rem; overflow:hidden; }
.o-chat__bar{
  position:absolute; inset:0 0 auto 0; height:2.3rem; z-index:2;
  background:linear-gradient(180deg,rgba(255,255,255,.96),rgba(255,255,255,.7));
  backdrop-filter:blur(10px); display:flex; align-items:flex-end; gap:.45rem; padding:0 .8rem .35rem;
  border-bottom:1px solid rgba(15,23,42,.06);
}
.o-chat__bar b{ font-family:'Outfit',sans-serif; font-size:.78rem; letter-spacing:-.01em; color:var(--ink); }
.o-chat__bar i{ width:16px; height:16px; border-radius:50%; background:linear-gradient(135deg,var(--brand),var(--accent)); display:inline-block; }
.o-chat__bar span{ font-size:.6rem; color:var(--accent); font-weight:600; margin-left:auto; }

.o-msg{
  max-width:82%; padding:.5rem .68rem; border-radius:15px; font-size:.72rem; line-height:1.42;
  opacity:0; transform:translateY(9px);
  animation:oMsgIn .5s cubic-bezier(.2,.8,.2,1) forwards;
}
.o-msg--them{ align-self:flex-start; background:#fff; color:var(--ink); border-bottom-left-radius:5px; box-shadow:0 2px 8px -4px rgba(15,23,42,.22); }
.o-msg--me{ align-self:flex-end; background:linear-gradient(135deg,var(--brand),#3b74f2); color:#fff; border-bottom-right-radius:5px; box-shadow:0 4px 12px -6px rgba(37,99,235,.6); }
.o-msg b{ font-weight:700; }
.o-msg small{ display:block; font-size:.62rem; opacity:.62; margin-top:.2rem; }
@keyframes oMsgIn{ to{ opacity:1; transform:translateY(0); } }

/* Only run once the phone is on screen, so the conversation plays for the reader */
.o-reveal .o-msg{ animation-play-state:paused; }
.o-reveal.is-in .o-msg{ animation-play-state:running; }

.o-reveal{ opacity:0; transform:translateY(26px) scale(.985); transition:opacity .9s ease, transform .9s cubic-bezier(.2,.8,.2,1); }
.o-reveal.is-in{ opacity:1; transform:none; }

@media (prefers-reduced-motion:reduce){
  .o-msg{ opacity:1; transform:none; animation:none; }
  .o-reveal{ opacity:1; transform:none; transition:none; }
}

/* the two showcase bands ------------------------------------------------- */
.o-band{ position:relative; z-index:10; padding:clamp(4.5rem,10vw,8rem) 1.5rem; }
.o-band__inner{ max-width:1080px; margin:0 auto; display:grid; gap:clamp(2.5rem,6vw,4.5rem); align-items:center; grid-template-columns:1fr; }
@media (min-width:900px){
  .o-band__inner{ grid-template-columns:1fr 1fr; }
  .o-band--flip .o-band__media{ order:-1; }
}
.o-band__media{ display:flex; justify-content:center; }
.o-eyebrow{
  display:inline-flex; align-items:center; gap:.5rem; font-size:.7rem; font-weight:700;
  letter-spacing:.16em; text-transform:uppercase; color:var(--brand-strong);
  background:rgba(37,99,235,.07); border:1px solid rgba(37,99,235,.14);
  padding:.4rem .78rem; border-radius:999px;
}
.o-h2{ font-family:'Outfit',sans-serif; font-weight:800; letter-spacing:-.025em; line-height:1.08;
  font-size:clamp(1.9rem,4vw,2.9rem); margin:1.1rem 0 0; color:var(--ink); }
.o-h2 em{ font-style:normal; background:linear-gradient(100deg,var(--brand),#6366f1 55%,var(--accent));
  -webkit-background-clip:text; background-clip:text; color:transparent; }
.o-p{ color:var(--ink-3); font-weight:300; line-height:1.68; font-size:clamp(.96rem,1.25vw,1.06rem); margin:1rem 0 0; max-width:36ch; }
.o-cta{ display:inline-flex; align-items:center; gap:.5rem; margin-top:1.6rem; text-decoration:none;
  font-weight:700; color:var(--brand-strong); font-size:.95rem; }
.o-cta:hover{ gap:.75rem; } .o-cta{ transition:gap .25s ease; }

/* ============================================================================
   6. Type & rhythm — one scale for the whole page
   The homepage carried three competing scales: a viewport-unit hero, ~100 uses
   of text-xs/text-sm for everything else, and clamp() headings on the newer
   sections. Nothing lined up, which is what made the page read as assembled
   rather than designed. These are the only sizes the page should use.
   ============================================================================ */
.o-display{ font-family:'Outfit',sans-serif; font-weight:800; letter-spacing:-.03em; line-height:1.04;
  font-size:clamp(2.4rem,5.4vw,4.1rem); color:var(--ink); }
.o-h2{ font-family:'Outfit',sans-serif; font-weight:800; letter-spacing:-.025em; line-height:1.08;
  font-size:clamp(1.9rem,4vw,2.9rem); margin:1.1rem 0 0; color:var(--ink); }
.o-h3{ font-family:'Outfit',sans-serif; font-weight:700; letter-spacing:-.015em; font-size:1.09rem; color:var(--ink); }
.o-lead{ color:var(--ink-2); font-weight:300; line-height:1.6; font-size:clamp(1.02rem,1.5vw,1.2rem); }
.o-p{ color:var(--ink-3); font-weight:300; line-height:1.68; font-size:clamp(.96rem,1.25vw,1.06rem); margin:1rem 0 0; max-width:36ch; }
.o-small{ color:var(--ink-3); font-size:.86rem; font-weight:400; line-height:1.6; }

/* One vertical rhythm for every band on the page. */
.o-band{ position:relative; z-index:10; padding:clamp(4.5rem,10vw,8rem) 1.5rem; }
.o-band__inner{ max-width:1080px; margin:0 auto; display:grid; gap:clamp(2.5rem,6vw,4.5rem);
  align-items:center; grid-template-columns:1fr; }
@media (min-width:900px){
  .o-band__inner{ grid-template-columns:1fr 1fr; }
  .o-band--flip .o-band__media{ order:-1; }
}
.o-band__media{ display:flex; justify-content:center; }

/* One card. Replaces .glass-card and the ad-hoc bubble styling. */
.o-card{
  position:relative; border-radius:20px; padding:1.5rem;
  background:linear-gradient(160deg, rgba(255,255,255,.86), rgba(255,255,255,.66));
  border:1px solid rgba(255,255,255,.78);
  box-shadow:var(--lift-1), inset 0 1px 0 rgba(255,255,255,.9);
  backdrop-filter:blur(16px) saturate(180%); -webkit-backdrop-filter:blur(16px) saturate(180%);
  transition:transform .35s cubic-bezier(.2,.8,.2,1), box-shadow .35s;
}
.o-card:hover{ transform:translateY(-3px); box-shadow:var(--lift-2), inset 0 1px 0 rgba(255,255,255,.95); }
.o-card__icon{ width:38px; height:38px; border-radius:11px; display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg, rgba(37,99,235,.12), rgba(15,181,166,.12)); margin-bottom:.9rem; }

/* The old decoration is retired rather than restyled — waves under a drifting
   sky is two weather systems at once, and the floating coin bubbles competed
   with the phone they were orbiting. */
.wave-band, .wave-top, .wave-bottom{ display:none !important; }

/* ============================================================================
   7. Deeper motion
   The first pass drifted too gently to read as alive on a short page — on the
   download page, which is one screen tall, it looked static. These add a fourth
   slow-turning layer and lift the blur so the field reads as atmosphere rather
   than as flat gradients sitting behind the content.
   ============================================================================ */
.oremi-sky__layer--far { filter:blur(64px); animation-duration:52s; }
.oremi-sky__layer--mid { filter:blur(56px); animation-duration:40s; }
.oremi-sky__layer--near{ filter:blur(44px); animation-duration:30s; }

/* A fourth body, rotating rather than translating, so the field never repeats
   the same shape twice on a short page. */
.oremi-sky__layer--swirl{
  width:58vmax; height:58vmax; left:8vmax; top:18vmax;
  background:conic-gradient(from 0deg at 50% 50%,
    rgba(37,99,235,.13), rgba(15,181,166,.11), rgba(99,102,241,.13), rgba(37,99,235,.13));
  filter:blur(72px); opacity:.85;
  animation:oremiSwirl 90s linear infinite;
}
@keyframes oremiSwirl{ to{ transform:rotate(360deg); } }

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

/* ============================================================================
   8. The hero device — a real WhatsApp thread, not a bubble mock
   Generic blue/grey bubbles read as an illustration of a chat app. The product
   claim is "your wallet lives in WhatsApp", so the screen has to be WhatsApp:
   iOS status bar, the real header with a verified business badge, WhatsApp's
   own bubble colours and tails, delivery ticks, and the compose bar.
   Colours are WhatsApp iOS light theme.
   ============================================================================ */
.o-phone__screen{ background:#efeae2; }

/* ---- iOS status bar ---- */
.wa-status{
  display:flex; align-items:center; justify-content:space-between;
  padding:.62rem .95rem .18rem; background:#f6f6f6; color:#000;
  font-size:.72rem; font-weight:700; letter-spacing:-.01em; z-index:4;
  font-family:-apple-system,'SF Pro Text','Inter',sans-serif;
}
.wa-status__right{ display:flex; align-items:center; gap:.28rem; }
.wa-bars{ display:flex; align-items:flex-end; gap:1.5px; height:9px; }
.wa-bars i{ width:2.5px; background:#000; border-radius:1px; display:block; }
.wa-bars i:nth-child(1){ height:3px } .wa-bars i:nth-child(2){ height:5px }
.wa-bars i:nth-child(3){ height:7px } .wa-bars i:nth-child(4){ height:9px }
.wa-batt{ width:20px; height:10px; border:1.3px solid rgba(0,0,0,.4); border-radius:3px; position:relative; }
.wa-batt::after{ content:''; position:absolute; right:-3px; top:3px; width:1.6px; height:4px; background:rgba(0,0,0,.4); border-radius:0 1px 1px 0; }
.wa-batt i{ position:absolute; inset:1.3px; width:74%; background:#000; border-radius:1.4px; display:block; }

/* ---- conversation header ---- */
.wa-head{
  display:flex; align-items:center; gap:.5rem; padding:.3rem .7rem .55rem;
  background:#f6f6f6; border-bottom:.5px solid rgba(0,0,0,.14); z-index:4;
}
.wa-head__back{ color:#007aff; font-size:1.15rem; line-height:1; margin-right:-.15rem; }
.wa-head__av{
  width:30px; height:30px; border-radius:50%; flex:none; object-fit:cover;
  background:linear-gradient(135deg,#1b3fae,#2563eb);
}
.wa-head__id{ min-width:0; }
.wa-head__name{
  display:flex; align-items:center; gap:.24rem;
  font-size:.79rem; font-weight:650; color:#111b21; line-height:1.15;
  font-family:-apple-system,'SF Pro Text','Inter',sans-serif;
}
/* Verified business badge — WhatsApp's green check, not a generic tick. */
.wa-verified{ width:12px; height:12px; flex:none; }
.wa-head__sub{ font-size:.63rem; color:#667781; line-height:1.2; margin-top:1px; }
.wa-head__icons{ margin-left:auto; display:flex; gap:.65rem; color:#007aff; font-size:.82rem; }

/* ---- thread ---- */
.wa-thread{
  flex:1; display:flex; flex-direction:column; gap:.28rem; padding:.6rem .5rem .45rem;
  overflow:hidden; position:relative;
  /* WhatsApp's doodle wallpaper, reduced to a faint tint so the bubbles lead */
  background-image:radial-gradient(rgba(0,0,0,.035) 1px, transparent 1px);
  background-size:22px 22px;
}
.wa-day{
  align-self:center; font-size:.56rem; font-weight:600; color:#54656f;
  background:#fff; padding:.2rem .5rem; border-radius:7px; margin-bottom:.15rem;
  box-shadow:0 1px 1px rgba(0,0,0,.06);
}
.wa-msg{
  position:relative; max-width:78%; padding:.34rem .5rem .3rem;
  border-radius:8px; font-size:.7rem; line-height:1.34; color:#111b21;
  font-family:-apple-system,'SF Pro Text','Inter',sans-serif;
  box-shadow:0 1px .5px rgba(11,20,26,.13);
  opacity:0; transform:translateY(7px);
  animation:oMsgIn .45s cubic-bezier(.2,.8,.2,1) forwards;
}
.wa-msg--in { align-self:flex-start; background:#fff; border-top-left-radius:2px; }
.wa-msg--out{ align-self:flex-end;   background:#d9fdd3; border-top-right-radius:2px; }
/* the little tail */
.wa-msg--in::before,.wa-msg--out::before{ content:''; position:absolute; top:0; width:8px; height:9px; }
.wa-msg--in::before { left:-7px;  background:radial-gradient(circle at 100% 0, transparent 8px, #fff 8px); }
.wa-msg--out::before{ right:-7px; background:radial-gradient(circle at 0 0, transparent 8px, #d9fdd3 8px); }
.wa-msg b{ font-weight:650; }
.wa-msg .wa-meta{ float:right; margin:.28rem -.12rem -.1rem .42rem; font-size:.53rem; color:#667781; display:inline-flex; align-items:center; gap:2px; white-space:nowrap; }
.wa-tick{ width:13px; height:8px; }

.wa-compose{
  display:flex; align-items:center; gap:.42rem; padding:.42rem .55rem;
  background:#f6f6f6; border-top:.5px solid rgba(0,0,0,.12);
}
.wa-compose__field{
  flex:1; background:#fff; border:.5px solid rgba(0,0,0,.10); border-radius:999px;
  padding:.3rem .62rem; font-size:.66rem; color:#8e9296;
}
.wa-compose i{ color:#007aff; font-size:.86rem; line-height:1; }

@media (prefers-reduced-motion:reduce){ .wa-msg{ opacity:1; transform:none; animation:none; } }

/* ============================================================================
   9. Hero row — owned outright, not delegated to a CDN
   The side-by-side switch was a Tailwind responsive variant (md:flex-row).
   Tailwind's browser build generates classes by scanning the DOM at runtime, so
   a variant can quietly fail to materialise and the row silently stays stacked
   with nothing in the markup to show for it. This is the same rule, in a file
   that is always loaded and always last.
   ============================================================================ */
@media (min-width:768px){
  .o-hero-row{ flex-direction:row !important; align-items:center; }
}
@media (max-width:767.98px){
  .o-hero-row{ flex-direction:column !important; }
}

/* ============================================================================
   10. Feature cards
   Flat slate boxes with a 1px border. They now sit on the sky like the rest of
   the page, animate in as you reach them, and answer the cursor — a sheen that
   follows the pointer, a lift, and the icon coming forward. Nothing moves that
   the reader did not cause, except the entrance.
   ============================================================================ */
.o-feature{
  position:relative; isolation:isolate; overflow:hidden;
  padding:2rem; border-radius:26px; cursor:pointer;
  background:linear-gradient(160deg, rgba(255,255,255,.90), rgba(255,255,255,.68));
  border:1px solid rgba(255,255,255,.8);
  box-shadow:var(--lift-1), inset 0 1px 0 rgba(255,255,255,.9);
  backdrop-filter:blur(16px) saturate(180%); -webkit-backdrop-filter:blur(16px) saturate(180%);
  transition:transform .4s cubic-bezier(.2,.8,.2,1), box-shadow .4s, border-color .4s;
  /* entrance */
  opacity:0; transform:translateY(22px);
  animation:oFeatureIn .7s cubic-bezier(.2,.8,.2,1) forwards;
  animation-play-state:paused;
}
.o-features.is-in .o-feature{ animation-play-state:running; }
@keyframes oFeatureIn{ to{ opacity:1; transform:none; } }

/* Stagger by position so the grid resolves as a wave, not a flash. */
.o-feature:nth-child(1){ animation-delay:0s }    .o-feature:nth-child(2){ animation-delay:.08s }
.o-feature:nth-child(3){ animation-delay:.16s }  .o-feature:nth-child(4){ animation-delay:.24s }
.o-feature:nth-child(5){ animation-delay:.32s }  .o-feature:nth-child(6){ animation-delay:.40s }

.o-feature:hover{
  transform:translateY(-6px);
  box-shadow:var(--lift-3), inset 0 1px 0 rgba(255,255,255,.95);
  border-color:rgba(37,99,235,.22);
}
/* A soft highlight that tracks the pointer — set by JS as --mx/--my. */
.o-feature::before{
  content:''; position:absolute; inset:-1px; border-radius:inherit; z-index:-1;
  background:radial-gradient(340px circle at var(--mx,50%) var(--my,0%),
             rgba(37,99,235,.13), rgba(15,181,166,.07) 42%, transparent 68%);
  opacity:0; transition:opacity .4s;
}
.o-feature:hover::before{ opacity:1; }

.o-feature__icon{
  width:54px; height:54px; border-radius:16px; display:flex; align-items:center; justify-content:center;
  transition:transform .45s cubic-bezier(.2,.8,.2,1), box-shadow .45s;
}
.o-feature:hover .o-feature__icon{ transform:translateY(-2px) scale(1.07); box-shadow:var(--lift-1); }
.o-feature__more{ display:inline-flex; align-items:center; gap:.35rem; transition:gap .3s ease; }
.o-feature:hover .o-feature__more{ gap:.6rem; }

@media (prefers-reduced-motion:reduce){
  .o-feature{ opacity:1; transform:none; animation:none; }
  .o-feature:hover{ transform:none; }
}

/* ---- the panel that opens on click ---- */
.o-modal-panel{
  background:linear-gradient(160deg, rgba(255,255,255,.94), rgba(255,255,255,.86)) !important;
  border:1px solid rgba(255,255,255,.85) !important;
  box-shadow:0 40px 90px -30px rgba(15,23,42,.45), inset 0 1px 0 rgba(255,255,255,.95) !important;
  backdrop-filter:blur(26px) saturate(180%); -webkit-backdrop-filter:blur(26px) saturate(180%);
  animation:oPanelIn .45s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes oPanelIn{ from{ opacity:0; transform:translateY(20px) scale(.975); } to{ opacity:1; transform:none; } }
.o-modal-panel #modal-title{ font-family:'Outfit',sans-serif; letter-spacing:-.02em; }
.o-modal-panel #modal-content{ line-height:1.72; }
.o-modal-panel #modal-content h4{ font-family:'Outfit',sans-serif; font-weight:700; color:var(--ink); margin-top:1.6rem; }
@media (prefers-reduced-motion:reduce){ .o-modal-panel{ animation:none; } }

/* ============================================================================
   11. Hero headline
   Two problems, one cause. The pulsing heart is absolutely positioned at
   left:100% — past the right edge of the h1 — so it lives outside the element's
   box and nothing reserves space for it. Once the headline wrapped it ran into
   the viewport edge and was clipped, most visibly on mobile.
   Reserve the space with padding, and stop ancestors from cropping it.
   ============================================================================ */
.o-display{
  font-size:clamp(1.85rem, 4.6vw, 3.5rem);   /* a notch down from before */
  padding-right:1.55em;                       /* the heart lives here */
  overflow:visible;
}
/* The heart is sized in em, so it shrinks with the headline automatically. */
.o-display + *, .o-display{ overflow:visible; }

@media (max-width:640px){
  .o-display{
    font-size:clamp(1.6rem, 7.4vw, 2.1rem);
    padding-right:1.45em;
    /* Long single words (Companion) would otherwise force a horizontal scroll
       at the narrowest widths. */
    overflow-wrap:break-word;
  }
}

/* ============================================================================
   12. The pulsing heart, on narrow screens
   It is positioned left:100% — which resolves to the OUTER edge of the padding
   box, so reserving padding on the headline pushed it further out rather than
   making room. On a phone the headline fills the width, so anything hanging off
   its right edge is guaranteed to be clipped by the viewport.
   Let it flow inline after the last word instead. `relative` rather than
   `static` because its children are inset-0 and need a positioned ancestor.
   ============================================================================ */
@media (max-width:640px){
  .o-display{ padding-right:0; }
  .o-heart{
    position:relative !important;
    left:auto !important; top:auto !important;
    transform:none !important;
    margin:0 0 0 .18em !important;
    display:inline-block; vertical-align:-.18em;
  }
}

/* ============================================================================
   13. Navigation drawer
   Plain text links on a flat white panel. Now: a frosted sheet, each link a
   tinted glass tile from the palette, staggered in when the drawer opens so
   the list arrives rather than appears.
   ============================================================================ */
.o-drawer{
  background:linear-gradient(200deg, rgba(255,255,255,.86), rgba(255,255,255,.72)) !important;
  border-left:1px solid rgba(255,255,255,.8) !important;
  box-shadow:-30px 0 70px -30px rgba(15,23,42,.35) !important;
  backdrop-filter:blur(28px) saturate(190%);
  -webkit-backdrop-filter:blur(28px) saturate(190%);
}
/* Colour bleeding in from behind, so the sheet feels lit rather than painted. */
.o-drawer::after{
  content:''; position:absolute; inset:0; pointer-events:none; z-index:-1;
  background:
    radial-gradient(70% 40% at 100% 0%, rgba(37,99,235,.13), transparent 70%),
    radial-gradient(60% 40% at 0% 100%, rgba(15,181,166,.12), transparent 70%);
}

.o-navgroup{ font-size:.62rem; font-weight:800; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 .55rem; padding-left:.15rem; }

.o-navlink{
  position:relative; display:flex; align-items:center; gap:.7rem; overflow:hidden;
  padding:.72rem .85rem; margin-bottom:.42rem; border-radius:14px;
  font-family:'Outfit',sans-serif; font-weight:700; font-size:.9rem; letter-spacing:-.01em;
  color:var(--ink); text-decoration:none;
  background:rgba(255,255,255,.55);
  border:1px solid rgba(255,255,255,.7);
  box-shadow:var(--lift-1);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  transition:transform .32s cubic-bezier(.2,.8,.2,1), box-shadow .32s, background .32s, border-color .32s;
  /* staggered arrival — delay is set per-item below */
  opacity:0; transform:translateX(16px);
}
.o-drawer.is-open .o-navlink{ animation:oNavIn .5s cubic-bezier(.2,.8,.2,1) forwards; }
@keyframes oNavIn{ to{ opacity:1; transform:none; } }
.o-navlink:nth-of-type(1){ animation-delay:.06s } .o-navlink:nth-of-type(2){ animation-delay:.11s }
.o-navlink:nth-of-type(3){ animation-delay:.16s } .o-navlink:nth-of-type(4){ animation-delay:.21s }
.o-navlink:nth-of-type(5){ animation-delay:.26s }

.o-navlink:hover{ transform:translateX(4px); box-shadow:var(--lift-2); border-color:rgba(255,255,255,.95); }
.o-navlink:active{ transform:translateX(2px) scale(.985); }

/* A dot carrying each link's own hue, and a matching wash on hover. Colours come
   from the palette rather than per-link one-offs. */
.o-navlink i{ width:9px; height:9px; border-radius:50%; flex:none; background:var(--dot,var(--brand)); box-shadow:0 0 0 3px color-mix(in srgb, var(--dot,var(--brand)) 18%, transparent); }
.o-navlink::before{
  content:''; position:absolute; inset:0; z-index:-1; opacity:0; transition:opacity .32s;
  background:linear-gradient(100deg, color-mix(in srgb, var(--dot,var(--brand)) 15%, transparent), transparent 70%);
}
.o-navlink:hover::before{ opacity:1; }
/* The arrow only commits on hover, so the resting state stays quiet. */
.o-navlink span.arrow{ margin-left:auto; opacity:0; transform:translateX(-5px); transition:opacity .3s, transform .3s; color:var(--dot,var(--brand)); font-weight:800; }
.o-navlink:hover span.arrow{ opacity:1; transform:none; }

@media (prefers-reduced-motion:reduce){
  .o-navlink{ opacity:1; transform:none; animation:none !important; }
  .o-navlink:hover{ transform:none; }
}

/* Dots removed. The hue still drives the hover wash and the arrow, so the
   per-link colour survives without a bullet in front of every label. */
.o-navlink i{ display:none; }
.o-navlink{ gap:0; }

/* Battery was drawn at 74%, which reads as "needs charging" in a hero shot. */
.wa-batt i{ width:92% !important; }

/* ---- typing indicator ---- */
.wa-typing{
  align-self:flex-start; background:#fff; border-top-left-radius:2px;
  border-radius:8px; padding:.5rem .62rem; display:inline-flex; gap:3.5px; align-items:center;
  box-shadow:0 1px .5px rgba(11,20,26,.13);
  animation:oMsgIn .3s cubic-bezier(.2,.8,.2,1) both;
}
.wa-typing span{ width:5.5px; height:5.5px; border-radius:50%; background:#9aa6ad; display:block;
  animation:waDot 1.25s ease-in-out infinite; }
.wa-typing span:nth-child(2){ animation-delay:.18s }
.wa-typing span:nth-child(3){ animation-delay:.36s }
@keyframes waDot{ 0%,60%,100%{ transform:translateY(0); opacity:.45 } 30%{ transform:translateY(-3.5px); opacity:1 } }

/* The thread scrolls itself as the conversation grows. */
.wa-thread{ overflow-y:auto; scrollbar-width:none; scroll-behavior:smooth; }
.wa-thread::-webkit-scrollbar{ display:none; }

@media (prefers-reduced-motion:reduce){ .wa-typing span{ animation:none } }

/* An image inside a WhatsApp bubble: the picture is the message, so the bubble
   tightens to it and the caption sits underneath. */
.wa-msg--img{ padding:.22rem .22rem .3rem; max-width:62%; }
.wa-msg--img img{ display:block; width:100%; border-radius:6px; }
.wa-msg--img .cap{ display:block; font-size:.66rem; line-height:1.35; padding:.3rem .3rem 0; color:#111b21; }

/* ============================================================================
   14. Adopting the sky on pages that were built without one
   Their own background lives on <body> as a solid fill, so it has to be cleared
   and the content lifted above the fixed sky layer. Applied via a class rather
   than a bare `body` rule so a page can opt out simply by not having it.
   ============================================================================ */
body.o-skyed{ background:transparent !important; }
/* Push the sky behind everything instead of lifting every child above it.
   The earlier version set `position:relative` on each direct child, which
   dropped these pages' 600x600 absolutely-positioned glow decorations into the
   layout — over a thousand pixels of blank page — and un-fixed a modal. Nothing
   about the page's own positioning needs to change for the sky to sit behind. */
body.o-skyed .oremi-sky{ z-index:-1; }

/* ============================================================================
   15. Long-form reading surfaces
   Privacy, Terms and account deletion are pages of continuous text that used to
   sit on a solid body fill. Making the body transparent put that text straight
   onto a moving gradient, which is miserable to read and looks unfinished. Give
   them back an opaque sheet; the sky stays visible around the edges.
   ============================================================================ */
.o-readable{
  background:rgba(255,255,255,.93);
  border:1px solid rgba(255,255,255,.9);
  border-radius:22px;
  box-shadow:var(--lift-2);
  backdrop-filter:blur(20px) saturate(160%);
  -webkit-backdrop-filter:blur(20px) saturate(160%);
  padding:clamp(1.5rem,4vw,3rem) !important;
  margin-top:2rem; margin-bottom:3rem;
}
@media (max-width:640px){
  .o-readable{ border-radius:16px; margin-top:1rem; }
}

/* ============================================================================
   16. Long-form legal
   A policy is read in fragments: people arrive from a link, look for one
   clause, and leave. So it needs a persistent contents rail, headings that can
   be linked to directly, and measure short enough to actually read.
   ============================================================================ */
.lg-shell{ max-width:1120px; margin:0 auto; padding:0 1.5rem clamp(4rem,8vw,7rem); }
.lg-grid{ display:grid; gap:2.5rem; grid-template-columns:1fr; align-items:start; }
@media (min-width:960px){ .lg-grid{ grid-template-columns:250px 1fr; gap:3.5rem; } }

.lg-rail{ position:sticky; top:1.5rem; align-self:start; display:none; }
@media (min-width:960px){ .lg-rail{ display:block; } }
.lg-rail h4{ font-family:'Outfit',sans-serif; font-size:.68rem; font-weight:800; letter-spacing:.15em;
  text-transform:uppercase; color:var(--ink-3); margin:0 0 .7rem; }
.lg-rail a{ display:block; padding:.34rem .6rem; margin-bottom:.12rem; border-radius:9px;
  font-size:.82rem; color:var(--ink-3); text-decoration:none; border-left:2px solid transparent;
  transition:color .22s, background .22s, border-color .22s; }
.lg-rail a:hover{ color:var(--brand-strong); background:rgba(37,99,235,.06); border-left-color:var(--brand); }

.lg-doc{
  background:rgba(255,255,255,.94); border:1px solid rgba(255,255,255,.9);
  border-radius:24px; box-shadow:var(--lift-2);
  backdrop-filter:blur(20px) saturate(160%); -webkit-backdrop-filter:blur(20px) saturate(160%);
  padding:clamp(1.5rem,4vw,3.25rem);
}
.lg-doc h2{ font-family:'Outfit',sans-serif; font-size:clamp(1.5rem,3vw,2rem); font-weight:800;
  letter-spacing:-.025em; color:var(--ink); margin:0 0 .4rem; scroll-margin-top:1.5rem; }
.lg-doc h3{ font-family:'Outfit',sans-serif; font-size:1.02rem; font-weight:700; color:var(--ink);
  margin:2rem 0 .5rem; scroll-margin-top:1.5rem; }
.lg-doc h3:first-of-type{ margin-top:1.5rem; }
.lg-doc p, .lg-doc li{ color:var(--ink-2); font-weight:300; line-height:1.75; font-size:.945rem; }
.lg-doc p{ margin:.6rem 0; max-width:68ch; }
.lg-doc ul{ margin:.6rem 0; padding-left:1.15rem; }
.lg-doc li{ margin:.3rem 0; max-width:66ch; }
.lg-doc strong{ color:var(--ink); font-weight:600; }
.lg-meta{ font-size:.8rem; color:var(--ink-3); border-bottom:1px solid var(--line); padding-bottom:1rem; }
.lg-note{ background:#eef4ff; border-left:3px solid var(--brand); border-radius:0 10px 10px 0;
  padding:.9rem 1.1rem; margin:1.2rem 0; }
.lg-note p{ margin:0; color:var(--ink-2); }
.lg-tabs{ display:flex; gap:.5rem; margin:0 0 1.75rem; flex-wrap:wrap; }
.lg-tabs a{ padding:.55rem 1rem; border-radius:12px; text-decoration:none; font-family:'Outfit',sans-serif;
  font-weight:700; font-size:.9rem; color:var(--ink-3); background:rgba(255,255,255,.6);
  border:1px solid rgba(255,255,255,.8); transition:all .25s; }
.lg-tabs a:hover{ color:var(--brand-strong); }
.lg-tabs a.on{ background:linear-gradient(135deg,var(--brand-strong),var(--brand)); color:#fff; border-color:transparent; box-shadow:var(--lift-1); }
