/* Delight layer — motion only, no layout.
 *
 * Isolated on purpose: every rule here is an ADDITION triggered by a class the
 * delight.js module adds and removes. Nothing here restyles an existing
 * element, so deleting this file and its <link> reverts the app exactly, the
 * same way the staff redesign layer works.
 *
 * Rules for anything added here:
 *   1. Never animate a money FIGURE's position — a number sliding around while
 *      somebody reads it is how you get "the app took my money" support chats.
 *      Numbers may count, glow or bloom in place. They may not fly.
 *   2. Everything is under 600ms. This is a wallet, not a slot machine.
 *   3. Everything stops under prefers-reduced-motion (block at the bottom).
 */

/* ---------------------------------------------------------------- pressing */
/* A press should feel like pressing something physical. Scale only — no
 * translate — so nothing shifts under the thumb mid-tap. */
.fx-press {
  animation: fxPress 180ms cubic-bezier(.3, .8, .4, 1);
}
@keyframes fxPress {
  0%   { transform: scale(1); }
  45%  { transform: scale(.955); }
  100% { transform: scale(1); }
}

/* The ripple starts where the finger actually landed (--fx-x/--fx-y set in JS),
 * because a ripple from the centre of a wide button looks like a glitch. */
.fx-ripple-host { position: relative; overflow: hidden; }
/* For a button that is ALREADY positioned: it is its own containing
   block, so it needs the clipping and must never be given a position,
   which would move it out of the spot it was placed in. */
.fx-ripple-clip { overflow: hidden; }
.fx-ripple {
  position: absolute;
  left: var(--fx-x, 50%);
  top: var(--fx-y, 50%);
  width: 12px; height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: currentColor;
  opacity: .22;
  pointer-events: none;
  animation: fxRipple 520ms cubic-bezier(.2, .7, .3, 1) forwards;
}
@keyframes fxRipple {
  to { transform: scale(26); opacity: 0; }
}

/* ------------------------------------------------------------- money moments */
/* Counting numbers get a subtle warmth so the eye follows the change without
 * the digits moving. Paired with the count-up in JS. */
.fx-counting { animation: fxCounting 520ms ease-out; }
@keyframes fxCounting {
  0%   { transform: scale(1);    filter: brightness(1); }
  35%  { transform: scale(1.045); filter: brightness(1.18); }
  100% { transform: scale(1);    filter: brightness(1); }
}

/* Money ARRIVING is the one moment worth a real flourish. */
.fx-received { animation: fxReceived 700ms cubic-bezier(.2, .9, .3, 1); }
@keyframes fxReceived {
  0%   { transform: scale(.86); opacity: .3; }
  40%  { transform: scale(1.09); opacity: 1; }
  70%  { transform: scale(.98); }
  100% { transform: scale(1); }
}

/* A coin arcs from the button to the balance on a deposit. Positioned by JS. */
.fx-coin {
  position: fixed;
  z-index: 9999;
  width: 26px; height: 26px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 15px;
  background: radial-gradient(circle at 32% 30%, #ffe9a3, #f6c344 58%, #d69a12);
  box-shadow: 0 3px 10px rgba(214, 154, 18, .45), inset 0 -2px 4px rgba(0,0,0,.18);
  pointer-events: none;
  will-change: transform, opacity;
}

/* Confetti for a genuinely good moment. Each piece gets its own drift/spin/delay
 * from JS so it never reads as a repeating pattern. */
.fx-confetti {
  position: fixed;
  z-index: 9999;
  width: 9px; height: 14px;
  border-radius: 2px;
  pointer-events: none;
  will-change: transform, opacity;
  animation: fxConfetti var(--fx-dur, 1400ms) cubic-bezier(.15, .6, .35, 1) forwards;
}
@keyframes fxConfetti {
  0%   { transform: translate3d(0,0,0) rotate(0deg); opacity: 1; }
  100% { transform: translate3d(var(--fx-dx, 0), var(--fx-dy, 60vh), 0)
                    rotate(var(--fx-spin, 540deg)); opacity: 0; }
}

/* ------------------------------------------------------------------ status */
/* A tick that DRAWS itself reads as "it completed" far better than one that
 * simply appears. */
.fx-tick { display: inline-block; }
.fx-tick path {
  stroke-dasharray: 32;
  stroke-dashoffset: 32;
  animation: fxDraw 420ms cubic-bezier(.6, .1, .3, 1) forwards;
}
@keyframes fxDraw { to { stroke-dashoffset: 0; } }

/* Refusals shake horizontally only — a vertical shake reads as a crash. */
.fx-nope { animation: fxNope 420ms cubic-bezier(.36, .07, .19, .97); }
@keyframes fxNope {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(3px); }
  30%, 50%, 70% { transform: translateX(-5px); }
  40%, 60% { transform: translateX(5px); }
}

/* Something worth noticing, without a sound: one slow breath. */
.fx-attention { animation: fxAttention 1.6s ease-in-out 2; }
@keyframes fxAttention {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.03); }
}

/* --------------------------------------------------------------- screens */
/* Sheets and screens get a soft rise. Short, because this fires constantly. */
.fx-rise { animation: fxRise 260ms cubic-bezier(.2, .8, .3, 1); }
@keyframes fxRise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* List rows arrive one after another. JS sets --fx-i per row; the cap in JS
 * stops a long history turning into a slow cascade. */
.fx-stagger { animation: fxRise 260ms cubic-bezier(.2,.8,.3,1) both;
              animation-delay: calc(var(--fx-i, 0) * 38ms); }

/* The QR scanner locking onto a code. */
.fx-locked { animation: fxLocked 420ms cubic-bezier(.2, .9, .3, 1); }
@keyframes fxLocked {
  0%   { transform: scale(1);   box-shadow: 0 0 0 0 rgba(52, 199, 89, .5); }
  50%  { transform: scale(1.04); box-shadow: 0 0 0 12px rgba(52, 199, 89, 0); }
  100% { transform: scale(1);   box-shadow: 0 0 0 0 rgba(52, 199, 89, 0); }
}

/* ------------------------------------------------------- the cute details */
/* Idle wiggle on the joystick, so the games button has a pulse of its own.
 * Rare on purpose (7s) — a thing that moves constantly stops being noticed and
 * starts being irritating. */
.fx-idle-wiggle { animation: fxWiggle 7s ease-in-out infinite; }
@keyframes fxWiggle {
  0%, 88%, 100% { transform: rotate(0deg); }
  90%  { transform: rotate(-9deg); }
  93%  { transform: rotate(7deg); }
  96%  { transform: rotate(-4deg); }
}

/* An empty screen should feel friendly rather than broken. */
.fx-float { animation: fxFloat 3.4s ease-in-out infinite; }
@keyframes fxFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}

/* --------------------------------------------------- accessibility opt-out */
/* Someone who has asked their phone for less motion has asked THIS app too.
 * Sounds are governed separately, by the existing sound settings. */
@media (prefers-reduced-motion: reduce) {
  .fx-press, .fx-ripple, .fx-counting, .fx-received, .fx-coin, .fx-confetti,
  .fx-tick path, .fx-nope, .fx-attention, .fx-rise, .fx-stagger, .fx-locked,
  .fx-idle-wiggle, .fx-float {
    animation: none !important;
    transition: none !important;
  }
  .fx-coin, .fx-confetti { display: none !important; }
}

/* ------------------------------------------------- a poor line, a cheap phone
   app.js publishes the connection class on <html data-net>. A device on 2G or
   with Data Saver on is usually also a device that cannot spare the CPU for
   thirty confetti pieces, so the expensive decoration stops there. Everything
   that communicates STATE — press, counting, refusals — keeps working, because
   those are feedback, not decoration. */
:root[data-net="lite"] .fx-confetti,
:root[data-net="lite"] .fx-coin{display:none!important}
:root[data-net="lite"] .fx-ripple{animation-duration:220ms}
:root[data-net="lite"] .fx-idle-wiggle,
:root[data-net="lite"] .fx-float{animation:none}

/* ------------------------------------------------------- feeling like an app
   Two browser behaviours are what make a WebView feel like a web page:

     * the grey/blue flash box the engine paints over anything tapped, and
     * long-press selecting the label inside a button, complete with handles
       and a "Copy / Share" callout.

   Neither exists in a native app, so both go — but only on CHROME. Message
   text, amounts, receipt numbers and wallet tags stay selectable, because
   people genuinely copy those and taking that away is worse than the flash. */
html{-webkit-tap-highlight-color:transparent;tap-highlight-color:transparent}

/* Naming every control that must not be selectable was the wrong shape: the
   list can only ever be as complete as the last time somebody remembered to
   add to it, and it kept missing things — the Search in chat button, the pin,
   the joystick. So the rule is inverted. NOTHING is selectable, and the few
   places where selecting is the point ask for it back below.

   The old rule also set user-select on `button *` but never touch-callout,
   and on iOS it is touch-callout that raises the Copy / Look Up bubble. That
   is why holding an icon still felt like holding a web page. */
html, body{
  -webkit-user-select:none;user-select:none;
  -webkit-touch-callout:none;
}

/* Typing, pasting and copying — the places where a long press should work.
   Inputs especially: without this iOS cannot place a cursor or offer Paste,
   which would break entering a $tag or a PIN. */
input, textarea, select, [contenteditable="true"], [contenteditable=""],
.selectable-message, .selectable-message *,
[data-selectable], [data-selectable] *{
  -webkit-user-select:text;user-select:text;
  -webkit-touch-callout:default;
}

/* The tag on the Receive screen is shown so it can be copied — one press takes
   the whole thing.
   Two declarations on purpose. Safari does not support the `all` VALUE, so on
   an iPhone it dropped that declaration, the tag inherited `none` from the rule
   above, and the one thing on the screen that exists to be copied could not be
   touched. `text` is declared first as a floor: a browser that understands
   `all` takes the later one, a browser that does not still gets a selectable
   tag. Caught by the WebKit run in e2e/tests/native-feel.spec.js. */
.wallet-receive-tag{
  -webkit-user-select:text;user-select:text;
  -webkit-user-select:all;user-select:all;
  -webkit-touch-callout:default;
}

/* The receipt number is the one thing a customer is ever asked to quote back
   to us — "which payment?" — so it has to be copyable. Deny-by-default had
   quietly taken that away, which an earlier comment in this file had promised
   would not happen. The amount and the note go with it: they are prose and
   figures on a document, not controls. */
.receipt-ref dd, .receipt-rows dd, .receipt-note, .receipt-amount{
  -webkit-user-select:text;user-select:text;
  -webkit-touch-callout:default;
}

/* Dragging an image out of a button is another web-page giveaway. */
button img, .tap-button img, .icon-button img{-webkit-user-drag:none;user-drag:none;pointer-events:none}

/* ------------------------------------------------- transaction row badges
   An icon, a word and a colour on every row. The badge is a circle so it reads
   at a glance from arm's length, which is how most people check a balance. */
.money-row{gap:12px}
.money-badge{
  flex:0 0 auto;width:40px;height:40px;border-radius:50%;
  display:grid;place-items:center;
  font-size:19px;font-weight:700;line-height:1;
  background:rgba(0,0,0,.06);color:#3c3c43;
}
.money-badge.tone-in   {background:rgba(28,150,70,.14); color:#1c8f46}
.money-badge.tone-out  {background:rgba(0,122,255,.13); color:#0a6fd8}
.money-badge.tone-wait {background:rgba(255,149,0,.16); color:#a35c00}
.money-badge.tone-warn {background:rgba(255,59,48,.14); color:#c0271d}
.money-badge.tone-free {background:rgba(175,82,222,.14);color:#8e3fbe}
.money-badge.tone-off  {background:rgba(120,120,128,.16);color:#6d6d72}

/* Cancelled reads as struck through and faded, not merely a different colour. */
.money-row.is-off{opacity:.62}
.money-row.is-off .money-right strong{text-decoration:line-through}

/* Something still happening should look unsettled. */
.money-row.is-wait .money-badge{animation:fxAttention 2.4s ease-in-out infinite}

@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .money-badge{background:rgba(255,255,255,.09);color:#d1d1d6}
  :root:not([data-theme="light"]) .money-badge.tone-in   {background:rgba(48,209,88,.18); color:#4cd964}
  :root:not([data-theme="light"]) .money-badge.tone-out  {background:rgba(10,132,255,.20);color:#6cb4ff}
  :root:not([data-theme="light"]) .money-badge.tone-wait {background:rgba(255,159,10,.20);color:#ffb340}
  :root:not([data-theme="light"]) .money-badge.tone-warn {background:rgba(255,69,58,.20); color:#ff6961}
  :root:not([data-theme="light"]) .money-badge.tone-free {background:rgba(191,90,242,.20);color:#d08cff}
  :root:not([data-theme="light"]) .money-badge.tone-off  {background:rgba(255,255,255,.10);color:#9a9a9f}
}
:root[data-theme="dark"] .money-badge{background:rgba(255,255,255,.09);color:#d1d1d6}
:root[data-theme="dark"] .money-badge.tone-in   {background:rgba(48,209,88,.18); color:#4cd964}
:root[data-theme="dark"] .money-badge.tone-out  {background:rgba(10,132,255,.20);color:#6cb4ff}
:root[data-theme="dark"] .money-badge.tone-wait {background:rgba(255,159,10,.20);color:#ffb340}
:root[data-theme="dark"] .money-badge.tone-warn {background:rgba(255,69,58,.20); color:#ff6961}
:root[data-theme="dark"] .money-badge.tone-free {background:rgba(191,90,242,.20);color:#d08cff}
:root[data-theme="dark"] .money-badge.tone-off  {background:rgba(255,255,255,.10);color:#9a9a9f}

/* --------------------------------------------------- confirm a payment
   A full screen, not a small dialog. The whole point is that it cannot be
   dismissed by muscle memory, so it takes over and asks one question. */
/* A <dialog> now, so it lands in the top layer above the send sheet. That
   brings the UA's own dialog styling with it — border, padding, auto margins,
   a max-width and max-height — all of which have to go, and display has to be
   tied to [open] or a closed dialog would sit there visible. */
.confirm-pay{
  position:fixed;inset:0;z-index:9998;
  border:0;margin:0;width:100%;height:100%;max-width:none;max-height:none;
  display:none;place-items:center;padding:24px;
  color:var(--text);
  background:var(--panel,#fff);
  opacity:0;transform:translateY(12px);
  transition:opacity .2s ease,transform .2s cubic-bezier(.2,.8,.3,1);
  overflow-y:auto;
}
.confirm-pay[open]{display:grid}
.confirm-pay.is-open{opacity:1;transform:none}
/* The panel itself is opaque and covers everything; the backdrop only shows
   during the fade, so it stays plain rather than adding a second surface. */
.confirm-pay::backdrop{background:rgba(0,0,0,.45)}
.confirm-inner{width:100%;max-width:380px;text-align:center}

.confirm-kicker{font-size:15px;color:var(--muted,#6d6d72);margin-bottom:22px}

.confirm-face{
  width:96px;height:96px;border-radius:50%;object-fit:cover;display:block;margin:0 auto 16px;
  background:var(--soft,#eef3fb);
}
.confirm-initials{
  display:grid;place-items:center;font-size:38px;font-weight:700;color:var(--primary,#0084ff);
}

.confirm-name{font-size:24px;font-weight:700;line-height:1.25}
.confirm-tag{font-size:17px;color:var(--primary,#0084ff);margin-top:4px;font-weight:600}

/* The number, then the same number in words underneath. */
.confirm-amount{
  margin-top:26px;font-size:52px;font-weight:800;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;line-height:1;
}
.confirm-words{margin-top:10px;font-size:18px;color:var(--muted,#6d6d72)}
.confirm-note{
  margin-top:16px;font-size:16px;line-height:1.45;color:var(--muted,#6d6d72);
  background:var(--soft,#f2f4f8);border-radius:14px;padding:12px 14px;
}

/* Big, and a long way from the way out — nothing destructive sits next to it. */
.confirm-go{
  margin-top:32px;width:100%;min-height:60px;border:0;border-radius:16px;
  background:var(--primary,#0084ff);color:#fff;
  font:inherit;font-size:19px;font-weight:700;cursor:pointer;
}
.confirm-go:active{transform:scale(.99)}
.confirm-back{
  margin-top:14px;width:100%;min-height:52px;border:0;background:none;
  color:var(--muted,#6d6d72);font:inherit;font-size:17px;cursor:pointer;
}
@media (prefers-reduced-motion: reduce){
  .confirm-pay{transition:none;transform:none}
}

/* ==========================================================================
   READABILITY  —  bigger text, honest contrast, targets you cannot miss
   --------------------------------------------------------------------------
   Written for the oldest customer on the platform, on the theory that what is
   comfortable at 70 is not worse at 25.

   --fc-text is the app's Text size setting multiplied by whatever the PHONE is
   set to (measured in app.js, because px ignores the system setting). Every
   size below is written against it, so one control moves the whole app instead
   of the three chat rules it used to move.
   ========================================================================== */
:root{--fc-os:1;--fc-text:calc(var(--fzoom,1)*var(--fc-os))}

/* The three that already scaled — now on the combined figure, and a step up. */
.message-list .bubble{font-size:calc(15.5px*var(--fc-text))}
.composer textarea{font-size:calc(16.5px*var(--fc-text))}
.typing-indicator,.reply-preview{font-size:calc(13.5px*var(--fc-text))}

/* Money. Every figure a customer might act on. */
.money-left strong{font-size:calc(17.5px*var(--fc-text))}
.money-right strong{font-size:calc(19px*var(--fc-text))}
.money-left small,.money-right small{font-size:calc(14px*var(--fc-text))}
.money-day{font-size:calc(13.5px*var(--fc-text))}
.money-empty,.wa-empty{font-size:calc(16px*var(--fc-text))}
.receipt-amount{font-size:calc(40px*var(--fc-text))}
.receipt-title{font-size:calc(18.5px*var(--fc-text))}
.receipt-sub,.receipt-rows dt{font-size:calc(14.5px*var(--fc-text))}
.receipt-rows dd{font-size:calc(15.5px*var(--fc-text))}
.receipt-note{font-size:calc(14.5px*var(--fc-text))}

/* Wallet. */
.wa-balance{font-size:calc(46px*var(--fc-text))}
.wa-tile{font-size:calc(15.5px*var(--fc-text))}
.wa-section{font-size:calc(13.5px*var(--fc-text))}
.wa-row-main strong,.wa-game-main strong{font-size:calc(16.5px*var(--fc-text))}
.wa-row-main small,.wa-game-main small{font-size:calc(14.5px*var(--fc-text))}
.wa-primary{font-size:calc(17.5px*var(--fc-text))}
.wa-link{font-size:calc(16.5px*var(--fc-text))}
.wa-note,.wa-error{font-size:calc(14.5px*var(--fc-text))}
.confirm-amount{font-size:calc(52px*var(--fc-text))}
.confirm-words{font-size:calc(17px*var(--fc-text))}

/* Chat furniture. 11px was too small to be worth printing. */
.message-meta,.pin-mark{font-size:calc(12px*var(--fc-text))}
.brand-copy strong{font-size:calc(19px*var(--fc-text))}
.brand-copy>span{font-size:calc(14px*var(--fc-text))}
.settings-card,.wide-button,.theme-row,.toggle-row{font-size:calc(16px*var(--fc-text))}
.install-help{font-size:calc(14px*var(--fc-text))}

/* Long lines are harder to track back from at any age; loosen them up. */
.message-list .bubble,.money-empty,.wa-empty,.wa-note{line-height:1.5}

/* --------------------------------------------------------------- contrast
   Secondary text was #65676b on white — legible, but it is doing real work in
   this app: it carries the date, the game name, who a payment was with. It is
   only "secondary" in the visual sense, so it is now dark enough to read in
   sunlight and with an ageing eye, while still ranking below the primary line.
   Every theme measures at least 7:1 (AAA) against its own background.

   Scoped carefully. Cute, Warm, Ocean and Business are light palettes with no
   dark form — they keep their light palette on a dark phone, so lifting their
   secondary text to a pale grey would put pale grey on pale pink. Only the
   themes that actually go dark get the dark value. */
:root{--muted:#4b4f56}
:root[data-style-theme="messenger"]{--muted:#4b4f56}
/* styles.css sets this one with two attributes, so it needs two attributes to
   answer it — same specificity, later file, this wins. */
:root[data-style-theme="messenger"][data-color-mode="light"]{--muted:#4b4f56}
:root[data-style-theme="business"]{--muted:#41565e}
:root[data-style-theme="cute"]{--muted:#77455c}
:root[data-style-theme="warm"]{--muted:#6d5138}
:root[data-style-theme="ocean"]{--muted:#385a66}

/* Light-on-dark reads heavier than it measures, so these lift rather than
   darken. The media query covers "follow the phone" and the moment before
   app.js has resolved the setting; the attribute rules cover an explicit
   choice, which has to win over the phone. */
@media (prefers-color-scheme: dark){
  :root:not([data-style-theme]):not([data-theme="light"]),
  :root[data-style-theme="messenger"]:not([data-color-mode="light"]){--muted:#c2c6cc}
}
:root[data-style-theme="messenger"][data-color-mode="dark"],
:root[data-style-theme="midnight"]{--muted:#c2c6cc}

/* ----------------------------------------------------------- tap targets
   The whole row, everywhere. A 20px checkbox is a fine target for somebody
   with steady hands and good eyes and a bad one for everybody else — so the
   row around it does the tapping, and the row tells you it did. */
.theme-row,.toggle-row{
  min-height:60px;padding:12px 4px;border-radius:12px;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.theme-row:active,.toggle-row:active{background:var(--input)}
.toggle-row input[type="checkbox"]{width:26px;height:26px;flex:0 0 26px}
.theme-row select{min-height:44px;font-size:calc(15.5px*var(--fc-text))}
.identifier-row{min-height:56px}
.identifier-row button{min-height:44px}
.wide-button{min-height:56px;display:flex;align-items:center}
.money-row{min-height:68px}
.wa-row{min-height:68px}
.wa-game{min-height:76px}
/* Anything that is a row is a target for its whole width, not just its text.
   .wide-button is NOT in this list, and must not be: the menu it lives in has
   no padding of its own, so those buttons inset themselves with a 16px margin
   each side and a width of calc(100% - 32px). Forcing 100% here made every one
   of them a full viewport wide starting 16px in — so the main menu ran 32px
   past its own right edge and could be dragged sideways. */
.money-row,.wa-row,.wa-game{width:100%}

/* The Text size control itself has to be usable by the person who needs it,
   which means it cannot be small. */
.zoom-row .zoom-controls{display:flex;align-items:center;gap:10px}
.zoom-row .zoom-controls button{
  min-width:46px;min-height:46px;border-radius:12px;
  border:1px solid var(--border);background:var(--input);color:var(--text);
  font-size:22px;line-height:1;cursor:pointer;
}
.zoom-row .zoom-controls button:disabled{opacity:.4}
#zoomLevelLabel{min-width:74px;font-size:calc(15px*var(--fc-text));font-weight:700}

/* Empty screens that teach. Roomy on purpose: this is the one moment somebody
   is reading rather than scanning, so it is given the space of a real screen. */
.fc-empty{
  display:flex;flex-direction:column;align-items:center;
  padding:34px 22px 30px;text-align:center;
}
.fc-empty-icon{font-size:calc(42px*var(--fc-text));line-height:1;margin-bottom:14px;opacity:.9}
.fc-empty-title{font-size:calc(18px*var(--fc-text));font-weight:700;color:var(--text)}
.fc-empty-body{
  margin:9px 0 0;max-width:34ch;         /* short lines are easier to track back */
  font-size:calc(15.5px*var(--fc-text));line-height:1.55;color:var(--muted);
}
.fc-empty-action{width:100%;max-width:320px;margin-top:22px}

/* ==========================================================================
   ONE PERSON  —  the whole story between you and somebody, full screen
   --------------------------------------------------------------------------
   It used to be a bottom sheet with a face, a run-on sentence of totals and
   four buttons of three different styles stacked on top of each other. Nothing
   said which of them you were meant to press.

   Now it reads top to bottom in the order the questions get asked: who is
   this, what has passed between us, what do I want to do, what happened when.
   ========================================================================== */
.person-bar{
  display:grid;grid-template-columns:44px 1fr 44px;align-items:center;
  gap:4px;padding:6px 6px calc(6px) 6px;
  padding-top:calc(6px + env(safe-area-inset-top));
  border-bottom:1px solid var(--border);background:var(--panel);
}
.person-bar strong{
  text-align:center;font-size:calc(17px*var(--fc-text));font-weight:650;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.person-back{
  width:44px;height:44px;border:0;border-radius:50%;background:transparent;
  color:var(--primary);font-size:30px;line-height:1;cursor:pointer;
}
.person-back:active{background:var(--input)}
.person-bar-spacer{width:44px}

.person-scroll{
  flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:0 16px calc(28px + env(safe-area-inset-bottom));
}

/* Who they are. */
.wallet-person-head{
  display:flex;flex-direction:column;align-items:center;gap:14px;
  padding:22px 0 18px;
}

/* What has passed between you. Two figures, not one sentence — they answer two
   different questions, and a number is read far faster than a clause. */
.person-stats{display:grid;grid-template-columns:1fr 1fr;gap:10px;width:100%}
.person-stat{
  display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:14px 10px;border-radius:16px;background:var(--input);
}
.person-stat small{font-size:calc(13px*var(--fc-text));color:var(--muted)}
.person-stat strong{
  font-size:calc(20px*var(--fc-text));font-weight:700;
  font-variant-numeric:tabular-nums;
}

/* What you can do. One filled button, one outlined, and the two rare settings
   demoted to chips so they stop competing with paying somebody. */
.wallet-person-actions{display:flex;flex-direction:column;gap:10px;padding-bottom:6px}
.wallet-person-actions .primary-button,
.wallet-person-actions .secondary-button{
  min-height:54px;font-size:calc(16.5px*var(--fc-text));font-weight:600;
}
.person-minor{display:flex;gap:10px;margin-top:2px}
.person-chip{
  flex:1;min-height:46px;border:1px solid var(--border);border-radius:14px;
  background:transparent;color:var(--text);cursor:pointer;
  font-size:calc(14.5px*var(--fc-text));font-weight:600;
}
.person-chip:active{background:var(--input)}
.person-chip.is-on{
  border-color:transparent;background:color-mix(in srgb,var(--primary) 14%,transparent);
  color:var(--primary);
}

/* What happened when. */
.person-list-title{
  margin:24px 0 2px;font-size:calc(13px*var(--fc-text));font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;color:var(--muted);
}
#walletPersonList .money-day{background:var(--bg,var(--panel))}
#walletPersonList:empty{display:none}

/* This dialog is in the shared "wallet sheet" rule, which rounds the top
   corners and slides up from the bottom. Both belong to a sheet: on a full
   screen the radius leaves slivers of the page behind showing at the top, and
   rising from the bottom still reads as something you have to dismiss. Going
   deeper into an app moves sideways, so it does. Same specificity as the rule
   it answers, later in the cascade. */
/* Deliberately slower than the rest of the app. These three are the screens
   somebody opens to READ — the full history, one person, one receipt — and a
   page that takes a moment to arrive is a page you have arrived at. The quick
   snap the rest of the wallet uses is right for a control and wrong for a
   destination.

   620ms against the app's usual 280-420. This is about as far as it goes:
   much past ~650ms the settle stops reading as weight and starts reading as
   the app being busy, and somebody taps a second time.
   The easing does the work: it covers most of the distance immediately and
   spends the rest settling, so it reads as weight, not delay. */
#walletPersonDialog[open], #walletReceiptDialog[open]{
  border-radius:0;
  animation:waPersonIn 620ms var(--wa-enter,cubic-bezier(.16,1,.3,1)) both;
}
@keyframes waPersonIn{
  from{opacity:0;transform:translateX(26px)}
  to{opacity:1;transform:none}
}

/* The whole history is still a sheet, so it keeps rising from the bottom —
   the same slower timing, the direction it already had. */
#walletHistoryDialog[open]{
  animation:waSheetUp 620ms var(--wa-enter,cubic-bezier(.16,1,.3,1)) both;
}

/* The scrim has to take just as long. Fading it in at the old speed left the
   background dimmed and waiting while the panel was still on its way. */
#walletPersonDialog[open]::backdrop,
#walletReceiptDialog[open]::backdrop,
#walletHistoryDialog[open]::backdrop{
  animation:waScrim 620ms var(--wa-enter,cubic-bezier(.16,1,.3,1)) both;
}

/* Leaving stays quick, and now leaves the way it came. The shared rule slid
   these DOWN, which fought an entrance that came from the side. Kept under the
   320ms failsafe in closeDialog, or the dialog would be forced shut mid-slide. */
#walletPersonDialog.is-closing, #walletReceiptDialog.is-closing{
  animation:waPersonOut 260ms var(--wa-exit,cubic-bezier(.4,0,1,1)) both;
}
@keyframes waPersonOut{
  from{opacity:1;transform:none}
  to{opacity:0;transform:translateX(26px)}
}
#walletHistoryDialog.is-closing{
  animation:waSheetDown 260ms var(--wa-exit,cubic-bezier(.4,0,1,1)) both;
}

@media (prefers-reduced-motion: reduce){
  /* waFadeOnly, not none: every other wallet sheet fades over 120ms with motion
     turned down, and these three popping instantly would be the odd ones out.
     The keyframes live in styles.css inside this same query, so they are
     available exactly when this rule applies. */
  #walletPersonDialog[open], #walletReceiptDialog[open],
  #walletHistoryDialog[open]{animation:waFadeOnly 120ms linear both}
  /* closeDialog already skips the exit animation when motion is reduced, but
     these rules sit later in the cascade than the ones in styles.css that
     cancel it — so without this they would win if that guard ever moved. */
  #walletPersonDialog.is-closing, #walletReceiptDialog.is-closing,
  #walletHistoryDialog.is-closing{animation:none}
  /* The scrim was left out of this and kept its 620ms fade, so on a phone with
     motion turned down the page snapped in while the background was still
     darkening behind it. A fade is not motion, but it still has to agree with
     what it is fading behind. */
  #walletPersonDialog[open]::backdrop,
  #walletReceiptDialog[open]::backdrop,
  #walletHistoryDialog[open]::backdrop{animation:waScrim 120ms linear both}
}

/* The receipt, full screen. The card keeps its own edges and sits on the page
   with room around it — a document, which is what it is. The buttons moved
   OUT of the card: they are things you do about the receipt, not part of it,
   and printing them inside made the card look like it ran on forever. */
.receipt-scroll{
  flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:18px 16px calc(28px + env(safe-area-inset-bottom));
}
.receipt-scroll .receipt{max-width:520px;margin:0 auto}
.receipt-actions{
  display:flex;flex-direction:column;gap:10px;
  max-width:520px;margin:18px auto 0;
}
.receipt-actions .primary-button,
.receipt-actions .secondary-button{
  min-height:54px;font-size:calc(16.5px*var(--fc-text));font-weight:600;
}
.receipt-actions .person-chip{min-height:46px}



/* ==========================================================================
   THE GAMES BUTTON  —  findable, then out of the way
   --------------------------------------------------------------------------
   It sat in a row of grey header icons and read as decoration. Customers were
   being talked through finding it in chat, one at a time, which is the clearest
   possible sign it was invisible.

   Two changes, and deliberately no more: a filled shape so it stops being a
   grey glyph among grey glyphs, and — for somebody who has never opened it —
   a slow breath and a short label pointing at it. Both stop the moment it is
   tapped once, and never come back on any device.
   ========================================================================== */
.game-button{
  position:relative;
  background:linear-gradient(140deg,#7c4dff,#e8579a);
  border-radius:50%;
  box-shadow:0 2px 10px color-mix(in srgb,#7c4dff 45%,transparent);
}
/* styles.css builds the old look by spinning a rainbow halo behind the button
   and covering the middle with a panel-coloured disc — .game-glow plus
   .game-button::after. The gradient above replaces that whole design, so both
   have to go.
   They were left in place at first, and the breathing-ring rule happened to
   override the disc, so it looked right. The first tap removed the marker class,
   the disc came back over the gradient, and with the emoji sitting at the same
   z-index the disc covered that too: a panel-coloured circle on a
   panel-coloured bar. The button had not moved. It had been painted out. */
.game-button::after{content:none}
.game-button .game-glow{display:none}

.game-button .game-emoji{
  /* Above the ring, whether or not the ring is there. */
  position:relative;z-index:2;
  font-size:calc(20px*var(--fc-text));
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.35));
}
.game-button:active{transform:scale(.94)}

/* The breath. Only while it has never been opened, and gentle enough to catch
   the eye without pulling at it — this sits above a chat somebody is reading. */
.game-button.games-live::after{
  content:'';position:absolute;inset:-4px;border-radius:50%;
  border:2px solid color-mix(in srgb,#e8579a 80%,transparent);
  animation:gameBreath 1.9s ease-out infinite;
  pointer-events:none;
}
/* The ripple rides on top of the button's own scale, so it reaches further
   than 1.5 suggests. It is a 2px line that is already fading by the time it
   crosses anything, which is why it can be this wide without making a mess. */
@keyframes gameBreath{
  0%{transform:scale(1);opacity:.95}
  55%,100%{transform:scale(1.5);opacity:0}
}

/* The button itself breathes with the ring. The ring alone is a thin outline
   two shades off the header — it reads at a glance but not out of the corner
   of an eye, which is where this has to work: the customer is reading a chat,
   not auditing the header. A shape that changes SIZE gets noticed there.

   Slow on purpose. Fast is an alarm; this is an invitation, and it may be on
   screen for days before anybody taps it. The shadow swells with the scale so
   it reads as one thing lifting rather than a button twitching. */
.game-button.games-live{
  animation:gamePulse 1.9s cubic-bezier(.34,1.4,.64,1) infinite;
  /* It now grows wider than the gap to its neighbours, so it has to grow OVER
     them rather than under. */
  z-index:3;
  /* Promoted to its own layer: this repaints continuously above a scrolling
     chat, and on a mid-range Android that is the difference between a swell
     and a stutter. */
  will-change:transform;
}
/* A double beat, then a rest — not a breath.
   A sine in and out is what a UI does when it does not really want anything;
   the eye adapts to it in seconds and it stops registering. Two quick hits
   followed by nearly a second of stillness reads as something asking, and it
   cannot be tuned out the same way, because the rest keeps resetting it. */
@keyframes gamePulse{
  0%      {transform:scale(1)    translateY(0);
           box-shadow:0 2px 10px color-mix(in srgb,#7c4dff 45%,transparent)}
  14%     {transform:scale(1.24) translateY(-3px);
           box-shadow:0 10px 26px color-mix(in srgb,#e8579a 75%,transparent)}
  26%     {transform:scale(1.02) translateY(0);
           box-shadow:0 2px 10px color-mix(in srgb,#7c4dff 45%,transparent)}
  38%     {transform:scale(1.18) translateY(-2px);
           box-shadow:0 8px 22px color-mix(in srgb,#e8579a 65%,transparent)}
  52%,100%{transform:scale(1)    translateY(0);
           box-shadow:0 2px 10px color-mix(in srgb,#7c4dff 45%,transparent)}
}

/* The joystick rocks inside the disc, on a cycle twice as long as the breath.
   Two motions on the same period lock together and become one movement the eye
   files away after a minute; offset, they keep catching it. Most of this
   keyframe is deliberately still — the rock happens once per pass, then waits. */
/* The joystick shakes on the same beat as the disc, deliberately in sync.
   The earlier version offset them so the movement stayed quiet — the point now
   is the opposite, so they land together as one hit and the glyph settles
   through a few decaying swings rather than snapping back. */
.game-button.games-live .game-emoji{
  animation:gameRock 1.9s cubic-bezier(.34,1.4,.64,1) infinite;
}
@keyframes gameRock{
  0%      {transform:rotate(0deg)   scale(1)}
  10%     {transform:rotate(-18deg) scale(1.2)}
  22%     {transform:rotate(15deg)  scale(1.15)}
  33%     {transform:rotate(-10deg) scale(1.1)}
  44%     {transform:rotate(6deg)   scale(1.05)}
  54%,100%{transform:rotate(0deg)   scale(1)}
}

/* A press still has to feel like a press. A running animation beats an ordinary
   declaration on the same property, so both :active rules — the button's
   scale(.94) in this file and the emoji's scale(.85) in styles.css — would be
   silently ignored while the pulse runs. Stopping the animations hands the
   property back. It only matters for a press that never completes: a real tap
   clears .games-live and everything here stops. */
.game-button.games-live:active{animation:none;transform:scale(.94)}
.game-button.games-live:active .game-emoji{animation:none}

/* The label. Says what is behind the button rather than "tap here" — somebody
   who does not want games should be able to read it and decide not to. */
/* Named fc-games-coach, NOT game-hint: .game-hint already exists 58 times
   across this app as ordinary centred help text, and styling it as a floating
   dark tooltip turned every one of those into a mess. Caught only because a
   browser check read back the wrong element's words. */
.fc-games-coach{
  position:absolute;z-index:60;
  padding:8px 12px;border-radius:12px;
  background:#1c1c1e;color:#fff;
  font-size:calc(13.5px*var(--fc-text));font-weight:600;
  box-shadow:0 8px 24px rgba(0,0,0,.35);
  animation:gameHintIn 420ms cubic-bezier(.16,1,.3,1) both;
  pointer-events:none;max-width:62vw;
}
.fc-games-coach::before{
  content:'';position:absolute;top:-5px;width:10px;height:10px;
  background:inherit;transform:rotate(45deg);
  /* Follows the button, not the label: on a narrow phone the label gets nudged
     inwards to stay on screen and a centred arrow would point at nothing. */
  left:calc(var(--arrow-x, 50%) - 5px);
}
@keyframes gameHintIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion: reduce){
  .game-button.games-live::after{animation:none;opacity:.7}
  .fc-games-coach{animation:none}
  /* Somebody who has asked their phone to stop moving things has usually asked
     for a reason. The button still has to stand out, so it keeps the larger
     size and the brighter shadow — it just holds them still instead of
     breathing. */
  .game-button.games-live{animation:none;transform:scale(1.12);
    box-shadow:0 6px 20px color-mix(in srgb,#e8579a 70%,transparent)}
  .game-button.games-live .game-emoji{animation:none}
  .game-button.games-live::after{transform:scale(1.12);opacity:.9}
}


/* The hot badge, turned UP — the owner asked for the hot decoration to be more
   exaggerated. Flame flickers, chip glows. (Keyframes live in styles.css.) */
.wa-game-flame{display:inline-block;font-size:1.25em;line-height:1;transform-origin:60% 90%;
  filter:drop-shadow(0 0 6px rgba(245,158,11,.9));animation:fcHotFlame 1.1s ease-in-out infinite}
.wa-game-hotchip{
  align-self:flex-start;margin-top:3px;
  font-size:11px;font-weight:900;letter-spacing:.04em;text-transform:uppercase;
  padding:2px 9px;border-radius:999px;
  color:#fff;background:linear-gradient(120deg,#f59e0b,#ef4444);
  box-shadow:0 2px 10px rgba(239,68,68,.55);white-space:nowrap;
  animation:fcHotChip 1.8s ease-in-out infinite;
}
@media (prefers-reduced-motion:reduce){
  .wa-game-flame,.wa-game-hotchip{animation:none}.wa-game-flame{transform:none}}


/* ================================================================
   DELUXE GAME HUB — an arcade/casino lobby for the games list.
   Scoped to #waGamesList so nothing else in the wallet app changes.
   Motion is mostly ONE-SHOT (entrance) or on-press; only the ambient
   glow and hot cards move continuously, so a phone full of coming-soon
   games stays cheap. Everything stops under prefers-reduced-motion
   (bottom of block). color-mix tints degrade gracefully — if a webview
   can't parse them the base .wa-game look from styles.css still applies.
   ================================================================ */

/* Ambient neon aurora behind the whole list. */
#waGamesList{position:relative;isolation:isolate;padding-top:2px}
#waGamesList::before{
  content:"";position:absolute;inset:-30px -8px 0;z-index:0;pointer-events:none;
  background:
    radial-gradient(58% 38% at 14% 6%, color-mix(in srgb,var(--primary) 30%,transparent), transparent 72%),
    radial-gradient(52% 40% at 92% 20%, rgba(168,85,247,.22), transparent 72%),
    radial-gradient(48% 34% at 50% 96%, rgba(34,211,238,.16), transparent 72%);
  filter:blur(8px);opacity:.85;
  animation:fcHubAura 18s ease-in-out infinite alternate;
}
@keyframes fcHubAura{
  0%{transform:translate3d(0,0,0) scale(1)}
  50%{transform:translate3d(0,-1.5%,0) scale(1.06)}
  100%{transform:translate3d(0,1%,0) scale(1.03)}
}
#waGamesList>*{position:relative;z-index:1}

/* Section headings: a glowing label with a gradient rule trailing off. */
#waGamesList .game-section-heading{display:flex;align-items:center;gap:9px}
#waGamesList .game-section-heading::after{
  content:"";flex:1;height:1px;border-radius:1px;
  background:linear-gradient(90deg, color-mix(in srgb,var(--primary) 55%,transparent), transparent);
}

/* ---------- the card ---------- */
#waGamesList .wa-game{
  position:relative;overflow:hidden;isolation:isolate;
  border:1px solid color-mix(in srgb,var(--primary) 15%, transparent);
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 7%, var(--panel,#fff)), var(--panel,#fff));
  box-shadow:0 1px 2px rgba(0,0,0,.06), 0 10px 24px rgba(0,0,0,.10);
  transition:transform .18s cubic-bezier(.2,.7,.3,1.35), box-shadow .25s ease, border-color .25s ease;
  animation:fcCardIn .5s cubic-bezier(.2,.7,.3,1) backwards;
  animation-delay:calc(var(--i,0) * 45ms);
}
@keyframes fcCardIn{from{opacity:0;transform:translateY(15px) scale(.96)}to{opacity:1;transform:none}}
/* glassy top sheen */
#waGamesList .wa-game::before{
  content:"";position:absolute;inset:0 0 auto;height:44%;pointer-events:none;z-index:0;
  background:linear-gradient(180deg, rgba(255,255,255,.12), transparent);
}
/* light sweep, fired on press / hover */
#waGamesList .wa-game::after{
  content:"";position:absolute;top:0;bottom:0;left:-70%;width:48%;pointer-events:none;z-index:2;
  background:linear-gradient(105deg, transparent, rgba(255,255,255,.38), transparent);
  transform:skewX(-18deg);opacity:0;
}
#waGamesList .wa-game:active{transform:scale(.98);
  box-shadow:0 1px 2px rgba(0,0,0,.06), 0 6px 18px color-mix(in srgb,var(--primary) 34%, transparent)}
#waGamesList .wa-game:active::after{animation:fcShine .6s ease-out}
@keyframes fcShine{0%{left:-70%;opacity:0}18%{opacity:1}100%{left:130%;opacity:0}}
@media (hover:hover){
  #waGamesList .wa-game:hover{transform:translateY(-2px);
    border-color:color-mix(in srgb,var(--primary) 42%,transparent);
    box-shadow:0 6px 14px rgba(0,0,0,.10),0 16px 34px color-mix(in srgb,var(--primary) 22%,transparent)}
  #waGamesList .wa-game:hover::after{animation:fcShine .85s ease-out}
}
/* keep content above the sheen/sweep layers */
#waGamesList .wa-game>*{position:relative;z-index:1}

/* logo badge — bigger, lit from within, glossy */
#waGamesList .wa-game-badge{
  width:52px;height:52px;flex-basis:52px;border-radius:15px;
  background:radial-gradient(circle at 50% 28%, color-mix(in srgb,var(--primary) 24%,transparent), var(--incoming,rgba(0,0,0,.05)));
  box-shadow:0 0 0 1px rgba(255,255,255,.10) inset, 0 6px 14px color-mix(in srgb,var(--primary) 26%, transparent);
}
#waGamesList .wa-game-badge::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(150deg, rgba(255,255,255,.30), transparent 46%)}
#waGamesList .wa-game-badge img{border-radius:inherit}

/* chevron in a soft accent pill that leans on interaction */
#waGamesList .wa-game .wa-row-go{
  display:flex;align-items:center;justify-content:center;width:27px;height:27px;border-radius:50%;
  background:color-mix(in srgb,var(--primary) 13%,transparent);color:var(--primary,#0084ff);
  font-size:19px;line-height:1;transition:transform .2s ease, background .2s ease}
#waGamesList .wa-game:active .wa-row-go{transform:translateX(3px);background:color-mix(in srgb,var(--primary) 24%,transparent)}
@media (hover:hover){#waGamesList .wa-game:hover .wa-row-go{transform:translateX(3px);background:color-mix(in srgb,var(--primary) 24%,transparent)}}

/* ---------- HOT cards ---------- */
#waGamesList .wa-game-hot{
  border-color:color-mix(in srgb,#f59e0b 48%, transparent);
  background:linear-gradient(180deg, rgba(245,158,11,.12), var(--panel,#fff));
  animation:fcCardIn .5s cubic-bezier(.2,.7,.3,1) backwards, fcHotAura 2.4s ease-in-out infinite;
  animation-delay:calc(var(--i,0)*45ms), 0s;
}
@keyframes fcHotAura{
  0%,100%{box-shadow:0 8px 20px rgba(0,0,0,.10), 0 0 0 0 rgba(245,158,11,0), 0 10px 30px rgba(245,158,11,.20)}
  50%{box-shadow:0 8px 20px rgba(0,0,0,.10), 0 0 0 2px rgba(245,158,11,.30), 0 16px 42px rgba(239,68,68,.32)}
}
#waGamesList .wa-game-hot .wa-game-badge{box-shadow:0 0 0 1px rgba(255,255,255,.12) inset, 0 6px 18px rgba(245,158,11,.6)}
/* corner ribbon, injected in JS */
.wa-hot-ribbon{position:absolute;top:11px;right:-34px;z-index:3;transform:rotate(45deg);
  background:linear-gradient(120deg,#f59e0b,#ef4444);color:#fff;
  font-size:9px;font-weight:900;letter-spacing:.14em;padding:2px 36px;
  box-shadow:0 2px 8px rgba(239,68,68,.5)}

/* ---------- coming-soon cards (static, so a wall of them stays cheap) ---------- */
#waGamesList .wa-game.is-closed{opacity:.92;filter:saturate(.7)}
#waGamesList .wa-game.is-closed .wa-game-badge img{filter:grayscale(.45) brightness(.92)}
#waGamesList .wa-game.is-closed::before{height:100%;
  background:repeating-linear-gradient(115deg, rgba(148,163,184,.09) 0 11px, transparent 11px 22px),
             linear-gradient(180deg, rgba(255,255,255,.06), transparent 40%)}
.wa-soon-tag{align-self:center;margin-left:auto;flex:0 0 auto;
  font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);
  border:1px solid color-mix(in srgb,var(--muted) 38%,transparent);border-radius:999px;padding:2px 9px;white-space:nowrap}
#waGamesList .wa-game.is-closed .wa-row-go{display:none}

/* ---------- "Recently played" hero carousel ---------- */
.wa-games-carousel{display:flex;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:6px 2px 12px;margin:0 -2px;-webkit-overflow-scrolling:touch}
.wa-games-carousel::-webkit-scrollbar{display:none}
.wa-gtile{scroll-snap-align:start;flex:0 0 auto;width:124px;position:relative;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;gap:7px;padding:14px 10px 12px;
  border:1px solid color-mix(in srgb,var(--primary) 16%,transparent);border-radius:20px;
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 12%, var(--panel,#fff)), var(--panel,#fff));
  box-shadow:0 1px 2px rgba(0,0,0,.06), 0 12px 26px rgba(0,0,0,.12);
  font:inherit;color:inherit;cursor:pointer;
  animation:fcCardIn .5s cubic-bezier(.2,.7,.3,1) backwards;animation-delay:calc(var(--i,0)*60ms)}
.wa-gtile:active{transform:scale(.97)}
.wa-gtile-badge{width:66px;height:66px;border-radius:19px;overflow:hidden;display:flex;align-items:center;justify-content:center;
  font-size:30px;background:radial-gradient(circle at 50% 28%, color-mix(in srgb,var(--primary) 26%,transparent), var(--incoming,rgba(0,0,0,.05)));
  box-shadow:0 0 0 1px rgba(255,255,255,.12) inset, 0 8px 18px color-mix(in srgb,var(--primary) 32%,transparent);position:relative}
.wa-gtile-badge::after{content:"";position:absolute;inset:0;border-radius:inherit;background:linear-gradient(150deg,rgba(255,255,255,.32),transparent 46%)}
.wa-gtile-badge img{width:100%;height:100%;object-fit:cover;border-radius:inherit}
.wa-gtile strong{font-size:calc(13.5px*var(--fc-text,1));font-weight:700;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wa-gtile small{font-size:calc(11.5px*var(--fc-text,1));color:var(--muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wa-gtile.wa-game-hot{border-color:color-mix(in srgb,#f59e0b 50%,transparent);
  background:linear-gradient(180deg,rgba(245,158,11,.16),var(--panel,#fff));animation:fcCardIn .5s cubic-bezier(.2,.7,.3,1) backwards, fcHotAura 2.4s ease-in-out infinite;animation-delay:calc(var(--i,0)*60ms),0s}
.wa-gtile-flame{position:absolute;top:8px;right:9px;font-size:15px;filter:drop-shadow(0 0 6px rgba(245,158,11,.9));animation:fcHotFlame 1.1s ease-in-out infinite}

@media (prefers-reduced-motion:reduce){
  #waGamesList::before,#waGamesList .wa-game,#waGamesList .wa-game-hot,
  .wa-gtile,.wa-gtile.wa-game-hot,.wa-gtile-flame,
  #waGamesList .wa-game::after{animation:none!important}
  #waGamesList .wa-game{opacity:1;transform:none}
  .wa-gtile{opacity:1;transform:none}
}


/* ================================================================
   PREMIUM WALLET HOME — balance hero, action tiles, freeplay bonus
   card, recent list. Scoped to #waHome; reuses the wallet's own
   tokens (--wa-value gold, --wa-e*, --wa-enter/press) so it sits in
   the existing system. One-shot entrance + a slow sheen; the only
   continuous motion is the ambient glow, the sheens and the star.
   Money legibility is kept — the CASH balance stays a solid,
   high-contrast number; gold (--wa-value) is reserved for freeplay,
   the way the wallet already uses it. Reduced-motion kills it all.
   ================================================================ */
#waHome{position:relative;isolation:isolate}
#waHome::before{
  content:"";position:absolute;top:-24px;left:-18px;right:-18px;height:300px;z-index:0;pointer-events:none;
  background:
    radial-gradient(72% 60% at 50% 0%, color-mix(in srgb,var(--primary) 26%,transparent), transparent 70%),
    radial-gradient(46% 50% at 88% 8%, color-mix(in srgb,var(--wa-value) 22%,transparent), transparent 72%);
  filter:blur(12px);opacity:.9;animation:fcHubAura 20s ease-in-out infinite alternate;
}
#waHome>*{position:relative;z-index:1}

/* balance hero */
.wa-hero{
  margin-top:8px;padding:22px 20px 24px;border-radius:var(--wa-r-card,22px);position:relative;overflow:hidden;
  border:1px solid color-mix(in srgb,var(--primary) 18%,transparent);
  background:linear-gradient(158deg, color-mix(in srgb,var(--primary) 15%, var(--panel,#fff)), var(--panel,#fff) 72%);
  box-shadow:var(--wa-e3,0 16px 32px rgba(0,0,0,.28));
  animation:fcHomeIn .6s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards;
}
.wa-hero::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(120deg, transparent 32%, rgba(255,255,255,.10) 48%, transparent 64%);
  background-size:220% 100%;animation:fcHeroSheen 7s ease-in-out infinite}
.wa-hero::after{content:"";position:absolute;top:-45%;right:-12%;width:62%;height:130%;pointer-events:none;border-radius:50%;
  background:radial-gradient(circle, color-mix(in srgb,var(--wa-value) 18%,transparent), transparent 62%)}
@keyframes fcHeroSheen{0%,100%{background-position:125% 0}50%{background-position:-25% 0}}
#waHome .wa-balance-label{margin:0;text-align:left;font-size:calc(12.5px*var(--fc-text,1));font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
#waHome .wa-balance{margin:8px 0 0;text-align:left;font-size:clamp(40px,12vw,52px);font-weight:800;letter-spacing:-.03em;line-height:1;
  text-shadow:0 2px 22px color-mix(in srgb,var(--primary) 24%,transparent)}

/* action tiles */
#waHome .wa-tiles{margin-top:16px}
#waHome .wa-tile{position:relative;overflow:hidden;
  border:1px solid color-mix(in srgb,var(--primary) 14%,transparent);
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 9%, var(--panel,#fff)), var(--panel,#fff));
  box-shadow:var(--wa-e2,0 8px 16px rgba(0,0,0,.20));
  transition:transform .16s var(--wa-press,cubic-bezier(.2,0,0,1)), box-shadow .25s ease, border-color .25s ease;
  animation:fcHomeIn .6s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards;animation-delay:.07s}
#waHome .wa-tile:nth-child(2){animation-delay:.13s}
#waHome .wa-tile::after{content:"";position:absolute;top:0;bottom:0;left:-70%;width:48%;pointer-events:none;
  background:linear-gradient(105deg, transparent, rgba(255,255,255,.32), transparent);transform:skewX(-18deg);opacity:0}
#waHome .wa-tile:active{transform:scale(.97);border-color:color-mix(in srgb,var(--primary) 34%,transparent);
  box-shadow:0 2px 10px color-mix(in srgb,var(--primary) 30%,transparent)}
#waHome .wa-tile:active::after{animation:fcShine .6s ease-out}
#waHome .wa-tile-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:50%;font-size:24px;
  color:var(--primary,#0084ff);
  background:radial-gradient(circle at 50% 32%, color-mix(in srgb,var(--primary) 30%,transparent), color-mix(in srgb,var(--primary) 8%,transparent));
  box-shadow:0 0 0 1px rgba(255,255,255,.10) inset, 0 6px 16px color-mix(in srgb,var(--primary) 32%,transparent)}

/* freeplay = the gold "bonus" card */
#waHome .wa-freeplay{position:relative;overflow:hidden;border-radius:20px;
  border:1px solid color-mix(in srgb,var(--wa-value) 42%,transparent);
  background:linear-gradient(125deg, color-mix(in srgb,var(--wa-value) 20%,var(--panel,#fff)), var(--panel,#fff) 68%);
  box-shadow:0 10px 26px color-mix(in srgb,var(--wa-value) 24%,transparent);
  animation:fcHomeIn .6s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards;animation-delay:.18s}
#waHome .wa-freeplay::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(115deg, transparent 36%, color-mix(in srgb,var(--wa-value) 30%,transparent) 50%, transparent 64%);
  background-size:230% 100%;animation:fcHeroSheen 5.5s ease-in-out infinite}
#waHome .wa-freeplay-icon{color:var(--wa-value);animation:fcStarPulse 2.6s ease-in-out infinite}
#waHome #waFreeplayAmount{color:var(--wa-value)}
@keyframes fcStarPulse{
  0%,100%{transform:scale(1);filter:drop-shadow(0 0 5px color-mix(in srgb,var(--wa-value) 50%,transparent))}
  50%{transform:scale(1.14);filter:drop-shadow(0 0 12px color-mix(in srgb,var(--wa-value) 85%,transparent))}}

/* recent list: a gentle staggered entrance, no colour noise (money clarity) */
#waHome #waRecent>*{animation:fcHomeIn .5s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards}
#waHome #waRecent>*:nth-child(1){animation-delay:.04s}
#waHome #waRecent>*:nth-child(2){animation-delay:.09s}
#waHome #waRecent>*:nth-child(3){animation-delay:.14s}
#waHome #waRecent>*:nth-child(n+4){animation-delay:.18s}

@keyframes fcHomeIn{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion:reduce){
  #waHome::before,.wa-hero,.wa-hero::before,#waHome .wa-tile,#waHome .wa-tile::after,
  #waHome .wa-freeplay,#waHome .wa-freeplay::before,#waHome .wa-freeplay-icon,
  #waHome #waRecent>*{animation:none!important}
  .wa-hero,#waHome .wa-tile,#waHome .wa-freeplay,#waHome #waRecent>*{opacity:1;transform:none}
}


/* ================================================================
   PREMIUM PAY + BOTTOM NAV. The bottom tab bar gets a glassy lift and
   an animated active state (icon 1.2x + primary + a glowing pill);
   the Pay screen gets glowing, tactile action bubbles, glowing
   favourite rings, an accent request card that gently pulses, and a
   staggered entrance. Wallet tokens + themes honoured; money-clarity
   kept (Send = brand, Request = gold --wa-value); reduced-motion off.
   ================================================================ */

/* ---- bottom tab bar ---- */
.wallet-app .wa-tabs{position:relative;
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 6%, var(--panel,#fff)), var(--panel,#fff));
  border-top:1px solid color-mix(in srgb,var(--primary) 14%,transparent);
  box-shadow:0 -8px 24px rgba(0,0,0,.12)}
.wallet-app .wa-tabs::before{content:"";position:absolute;top:-1px;left:10%;right:10%;height:1px;pointer-events:none;
  background:linear-gradient(90deg, transparent, color-mix(in srgb,var(--primary) 55%,transparent), transparent)}
.wallet-app .wa-tab{position:relative;overflow:visible}
/* the glowing pill behind the active tab's icon */
.wallet-app .wa-tab::before{content:"";position:absolute;top:5px;left:50%;width:54px;height:32px;border-radius:999px;pointer-events:none;
  transform:translateX(-50%) scale(.5);opacity:0;
  background:radial-gradient(circle, color-mix(in srgb,var(--primary) 32%,transparent), color-mix(in srgb,var(--primary) 8%,transparent) 74%);
  transition:opacity .3s var(--wa-enter,cubic-bezier(.16,1,.3,1)), transform .3s var(--wa-enter,cubic-bezier(.16,1,.3,1))}
.wallet-app .wa-tab.is-on::before{opacity:1;transform:translateX(-50%) scale(1)}
.wallet-app .wa-tab svg{position:relative;transition:transform .28s var(--wa-enter,cubic-bezier(.16,1,.3,1)), filter .28s ease}
.wallet-app .wa-tab.is-on svg{transform:translateY(-1px) scale(1.2);
  filter:drop-shadow(0 3px 8px color-mix(in srgb,var(--primary) 55%,transparent))}
.wallet-app .wa-tab:active svg{transform:scale(.85)}
.wallet-app .wa-tab.is-on span{font-weight:700}

/* ---- Pay screen ---- */
#waPay{position:relative;isolation:isolate}
#waPay::before{content:"";position:absolute;top:-20px;left:-18px;right:-18px;height:220px;z-index:0;pointer-events:none;
  background:radial-gradient(70% 60% at 50% 0%, color-mix(in srgb,var(--primary) 22%,transparent), transparent 72%);
  filter:blur(10px);opacity:.85;animation:fcHubAura 20s ease-in-out infinite alternate}
#waPay>*{position:relative;z-index:1}

/* balance strip → a small glass card */
#waPay .wa-paybal{border-radius:16px;border:1px solid color-mix(in srgb,var(--primary) 16%,transparent);
  background:linear-gradient(160deg, color-mix(in srgb,var(--primary) 12%,var(--panel,#fff)), var(--panel,#fff) 74%);
  box-shadow:var(--wa-e2,0 8px 16px rgba(0,0,0,.2));animation:fcHomeIn .5s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards}

/* a request is someone waiting — accent card, gentle pulse */
#waPay .wa-request{border:1px solid color-mix(in srgb,var(--primary) 32%,transparent);
  background:linear-gradient(155deg, color-mix(in srgb,var(--primary) 15%,var(--panel,#fff)), var(--panel,#fff) 70%);
  box-shadow:0 8px 22px color-mix(in srgb,var(--primary) 20%,transparent);
  animation:fcHomeIn .5s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards, fcReqPulse 2.8s ease-in-out infinite}
@keyframes fcReqPulse{0%,100%{box-shadow:0 8px 22px color-mix(in srgb,var(--primary) 16%,transparent)}
  50%{box-shadow:0 8px 28px color-mix(in srgb,var(--primary) 34%,transparent)}}

/* the four action bubbles — glowing, glossy, tactile */
#waPay .wa-actions{margin-top:14px}
#waPay .wa-act{animation:fcHomeIn .5s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards}
#waPay .wa-act:nth-child(1){animation-delay:.03s}#waPay .wa-act:nth-child(2){animation-delay:.08s}
#waPay .wa-act:nth-child(3){animation-delay:.13s}#waPay .wa-act:nth-child(4){animation-delay:.18s}
#waPay .wa-act-bub{position:relative;overflow:hidden;width:60px;height:60px;
  transition:transform .18s var(--wa-press,cubic-bezier(.2,0,0,1)), box-shadow .25s ease}
#waPay .wa-act-bub svg{position:relative;z-index:1}
#waPay .wa-act-bub::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background:linear-gradient(180deg, rgba(255,255,255,.22), transparent 55%)}
#waPay .wa-act-bub::after{content:"";position:absolute;top:0;bottom:0;left:-80%;width:55%;pointer-events:none;z-index:2;
  background:linear-gradient(105deg, transparent, rgba(255,255,255,.4), transparent);transform:skewX(-18deg);opacity:0}
#waPay .wa-act-bub:not(.is-primary):not(.is-value){
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 12%,var(--panel,#fff)), var(--panel,#fff));
  border-color:color-mix(in srgb,var(--primary) 22%,transparent);color:var(--primary,#0084ff);
  box-shadow:0 6px 16px color-mix(in srgb,var(--primary) 20%,transparent)}
#waPay .wa-act-bub.is-primary{box-shadow:0 8px 22px color-mix(in srgb,var(--primary) 48%,transparent)}
#waPay .wa-act-bub.is-value{color:var(--wa-value);border-color:color-mix(in srgb,var(--wa-value) 42%,transparent);
  background:linear-gradient(180deg, color-mix(in srgb,var(--wa-value) 16%,var(--panel,#fff)), var(--panel,#fff));
  box-shadow:0 6px 18px color-mix(in srgb,var(--wa-value) 30%,transparent)}
#waPay .wa-act:active .wa-act-bub{transform:scale(.9) translateY(2px)}
#waPay .wa-act:active .wa-act-bub::after{animation:fcShine .6s ease-out}

/* favourites — glowing rings, tactile */
#waPay .wa-face{animation:fcHomeIn .5s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards}
#waPay .wa-face:nth-child(1){animation-delay:.04s}#waPay .wa-face:nth-child(2){animation-delay:.09s}
#waPay .wa-face:nth-child(3){animation-delay:.13s}#waPay .wa-face:nth-child(n+4){animation-delay:.17s}
#waPay .wa-face-avatar{transition:transform .18s var(--wa-press,cubic-bezier(.2,0,0,1)), box-shadow .25s ease;
  box-shadow:0 0 0 2px color-mix(in srgb,var(--primary) 34%,transparent), 0 6px 16px color-mix(in srgb,var(--primary) 26%,transparent)}
#waPay .wa-face:active .wa-face-avatar{transform:scale(.93)}
@media (hover:hover){#waPay .wa-face:hover .wa-face-avatar{
  box-shadow:0 0 0 2px color-mix(in srgb,var(--primary) 55%,transparent), 0 8px 20px color-mix(in srgb,var(--primary) 34%,transparent)}}

/* section headings get a trailing gradient rule; people rows enter gently */
#waPay .wa-section{display:flex;align-items:center;gap:9px}
#waPay .wa-section::after{content:"";flex:1;height:1px;border-radius:1px;
  background:linear-gradient(90deg, color-mix(in srgb,var(--primary) 50%,transparent), transparent)}
#waPay .wa-people>*{animation:fcHomeIn .45s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards}

@media (prefers-reduced-motion:reduce){
  .wallet-app .wa-tab::before,.wallet-app .wa-tab svg,
  #waPay::before,#waPay .wa-paybal,#waPay .wa-request,#waPay .wa-act,
  #waPay .wa-act-bub::after,#waPay .wa-face,#waPay .wa-people>*{animation:none!important;transition:none!important}
  #waPay .wa-paybal,#waPay .wa-request,#waPay .wa-act,#waPay .wa-face,#waPay .wa-people>*{opacity:1;transform:none}
  .wallet-app .wa-tab.is-on svg{transform:scale(1.12)}
}


/* ================================================================
   PREMIUM ACTIVITY — the transaction history. Ambient glow, FROSTED
   sticky day headers with a gradient rule, glassy rows that rise in
   with a press shine, and the tone icon badges GLOWING in their own
   colour (the existing in/out/wait/warn/free/off meanings kept — the
   glow just uses each badge's own currentColor). Reduced-motion off.
   ================================================================ */
#waActivity{position:relative;isolation:isolate}
#waActivity::before{content:"";position:absolute;top:-20px;left:-18px;right:-18px;height:220px;z-index:0;pointer-events:none;
  background:radial-gradient(70% 60% at 50% 0%, color-mix(in srgb,var(--primary) 20%,transparent), transparent 72%);
  filter:blur(10px);opacity:.8;animation:fcHubAura 20s ease-in-out infinite alternate}
#waActivityList{position:relative;z-index:1}

/* frosted sticky day headers + a trailing gradient rule */
#waActivityList .money-day{display:flex;align-items:center;gap:9px;
  background:color-mix(in srgb,var(--panel,#fff) 82%, transparent);
  backdrop-filter:blur(8px) saturate(1.1);-webkit-backdrop-filter:blur(8px) saturate(1.1)}
#waActivityList .money-day::after{content:"";flex:1;height:1px;border-radius:1px;
  background:linear-gradient(90deg, color-mix(in srgb,var(--primary) 45%,transparent), transparent)}

/* rows → glass cards, tactile, press shine */
#waActivityList .money-row{position:relative;overflow:hidden;
  border:1px solid color-mix(in srgb,var(--primary) 10%,transparent);
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 5%, var(--panel,#fff)), var(--panel,#fff));
  box-shadow:0 1px 2px rgba(0,0,0,.05), 0 8px 18px rgba(0,0,0,.08);
  transition:transform .16s var(--wa-press,cubic-bezier(.2,0,0,1)), box-shadow .25s ease, border-color .25s ease}
#waActivityList .money-row::after{content:"";position:absolute;top:0;bottom:0;left:-70%;width:46%;pointer-events:none;
  background:linear-gradient(105deg, transparent, rgba(255,255,255,.28), transparent);transform:skewX(-18deg);opacity:0}
#waActivityList .money-row:active{transform:scale(.985);
  box-shadow:0 1px 2px rgba(0,0,0,.05), 0 4px 14px color-mix(in srgb,var(--primary) 24%,transparent)}
#waActivityList .money-row:active::after{animation:fcShine .6s ease-out}

/* cascade entrance for the whole list (headers fade only so sticky stays clean) */
#waActivityList > *{animation:fcHomeIn .45s var(--wa-enter,cubic-bezier(.16,1,.3,1)) backwards}
#waActivityList .money-day{animation-name:fcFadeIn}
@keyframes fcFadeIn{from{opacity:0}to{opacity:1}}
#waActivityList > *:nth-child(1){animation-delay:.02s}
#waActivityList > *:nth-child(2){animation-delay:.05s}
#waActivityList > *:nth-child(3){animation-delay:.08s}
#waActivityList > *:nth-child(4){animation-delay:.11s}
#waActivityList > *:nth-child(5){animation-delay:.14s}
#waActivityList > *:nth-child(6){animation-delay:.17s}
#waActivityList > *:nth-child(7){animation-delay:.20s}
#waActivityList > *:nth-child(n+8){animation-delay:.23s}

/* tone icon badges glow in their own colour */
#waActivityList .money-badge{box-shadow:0 3px 12px color-mix(in srgb,currentColor 32%,transparent)}

@media (prefers-reduced-motion:reduce){
  #waActivity::before,#waActivityList > *,#waActivityList .money-row::after{animation:none!important}
  #waActivityList > *{opacity:1;transform:none}
}


/* ================================================================
   PREMIUM RECEIPT — the shareable transaction document. Elevated to a
   banknote/ticket: an accent-tinted card with a foil top bar that
   presents ITSELF in (rise + one-shot sheen), a glowing guilloche
   turning slowly behind, a directional amount that glows, a status
   SEAL (✓ / Pending / Cancelled), a ringed counterpart avatar and a
   tear-line note. It is a DOCUMENT people READ and SCREENSHOT, so the
   only ongoing motion is the very-slow guilloche. NOTE: this dialog is
   a `.sheet.money`, NOT `.wallet-app`, so it has --money-in but not the
   wallet tokens — fallbacks are inlined. Reduced-motion off (bottom).
   ================================================================ */
#walletReceiptBody .receipt{
  border:1px solid color-mix(in srgb,var(--primary) 14%,transparent);
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 7%, var(--panel,#fff)), var(--panel,#fff) 26%);
  box-shadow:0 2px 6px rgba(0,0,0,.08), 0 24px 56px color-mix(in srgb,var(--primary) 14%, rgba(0,0,0,.16));
  animation:fcReceiptIn .55s cubic-bezier(.16,1,.3,1) backwards}
@keyframes fcReceiptIn{from{opacity:0;transform:translateY(26px) scale(.94)}to{opacity:1;transform:none}}
/* foil top bar */
#walletReceiptBody .receipt::after{content:"";position:absolute;top:0;left:0;right:0;height:4px;z-index:2;
  background:linear-gradient(90deg, color-mix(in srgb,var(--primary) 75%,transparent), var(--wa-value,#d9b75a), color-mix(in srgb,var(--primary) 75%,transparent))}
/* one-shot foil sweep as it presents itself in */
#walletReceiptBody .receipt::before{content:"";position:absolute;top:0;bottom:0;left:-60%;width:48%;pointer-events:none;z-index:3;
  background:linear-gradient(105deg, transparent, rgba(255,255,255,.26), transparent);transform:skewX(-16deg);
  animation:fcReceiptSheen 1.15s ease-out .3s 1 backwards}
@keyframes fcReceiptSheen{0%{left:-60%;opacity:0}30%{opacity:1}100%{left:145%;opacity:0}}
/* guilloche: accent, lit, turning very slowly */
#walletReceiptBody .receipt-guilloche{opacity:.14;stroke:var(--primary);
  filter:drop-shadow(0 0 7px color-mix(in srgb,var(--primary) 40%,transparent));
  animation:fcGuilloche 60s linear infinite}
@keyframes fcGuilloche{from{transform:translateX(-50%) rotate(0)}to{transform:translateX(-50%) rotate(360deg)}}
/* amount glows in its direction colour */
#walletReceiptBody .receipt-amount{text-shadow:0 2px 22px color-mix(in srgb,var(--primary) 20%,transparent)}
#walletReceiptBody .receipt-amount.in{text-shadow:0 2px 22px color-mix(in srgb,var(--money-in,#118a4e) 34%,transparent)}
/* status seal */
#walletReceiptBody .receipt-seal{position:absolute;top:16px;right:16px;z-index:2;display:grid;place-items:center;
  min-width:46px;height:46px;border-radius:999px;font-size:10px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;
  background:var(--panel,#fff);animation:fcSealIn .5s cubic-bezier(.16,1,.3,1) .32s backwards}
#walletReceiptBody .receipt-seal.is-done{width:46px;color:var(--money-in,#118a4e);
  border:2px solid color-mix(in srgb,var(--money-in,#118a4e) 55%,transparent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--money-in,#118a4e) 12%,transparent), 0 6px 16px color-mix(in srgb,var(--money-in,#118a4e) 26%,transparent)}
#walletReceiptBody .receipt-seal.is-done svg{width:22px;height:22px}
#walletReceiptBody .receipt-seal.is-wait{padding:0 12px;color:#a35c00;border:2px solid rgba(255,149,0,.5);box-shadow:0 6px 16px rgba(255,149,0,.25)}
#walletReceiptBody .receipt-seal.is-void{padding:0 12px;color:#c0271d;border:2px solid rgba(255,59,48,.5);box-shadow:0 6px 16px rgba(255,59,48,.22)}
@keyframes fcSealIn{from{opacity:0;transform:scale(.35)}to{opacity:1;transform:scale(1)}}
/* the counterpart avatar, ringed and lit */
#walletReceiptBody .receipt-who-avatar{box-shadow:0 0 0 2px color-mix(in srgb,var(--primary) 30%,transparent), 0 6px 16px color-mix(in srgb,var(--primary) 26%,transparent)}
/* note gets an accent tear-edge */
#walletReceiptBody .receipt-note{border-left:3px solid color-mix(in srgb,var(--primary) 45%,transparent)}
/* actions rise in under the card */
#walletReceiptBody .receipt-actions{animation:fcHomeIn .5s cubic-bezier(.16,1,.3,1) .14s backwards}

@media (prefers-reduced-motion:reduce){
  #walletReceiptBody .receipt,#walletReceiptBody .receipt::before,#walletReceiptBody .receipt-guilloche,
  #walletReceiptBody .receipt-seal,#walletReceiptBody .receipt-actions{animation:none!important}
  #walletReceiptBody .receipt,#walletReceiptBody .receipt-seal,#walletReceiptBody .receipt-actions{opacity:1;transform:none}
  #walletReceiptBody .receipt-guilloche{transform:translateX(-50%)}
}


/* ================================================================
   PREMIUM "BETWEEN YOU TWO" (per-person). Also a `.sheet.money` dialog
   (has --money-in, not the wallet tokens → inline fallbacks). Ambient
   glow, glass person card with a ringed avatar, directional stat cards
   (They sent = money IN, green), premium actions, and the history gets
   the same glass rows + glowing tone badges as Activity. RM off.
   ================================================================ */
#walletPersonDialog .person-scroll{position:relative;isolation:isolate}
#walletPersonDialog .person-scroll::before{content:"";position:absolute;top:-6px;left:-18px;right:-18px;height:240px;z-index:0;pointer-events:none;
  background:radial-gradient(72% 60% at 50% 0%, color-mix(in srgb,var(--primary) 22%,transparent), transparent 72%);
  filter:blur(11px);opacity:.85;animation:fcHubAura 20s ease-in-out infinite alternate}
#walletPersonDialog .person-scroll > *{position:relative;z-index:1}

/* person card + ringed, lit avatar */
#walletPersonHead .wallet-person{border-radius:20px;
  background:linear-gradient(160deg, color-mix(in srgb,var(--primary) 12%,var(--panel,#fff)), var(--panel,#fff) 72%);
  border:1px solid color-mix(in srgb,var(--primary) 16%,transparent);
  box-shadow:0 10px 26px color-mix(in srgb,var(--primary) 16%,transparent);
  animation:fcHomeIn .5s cubic-bezier(.16,1,.3,1) backwards}
#walletPersonHead .wallet-person-avatar{box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 20%,transparent), 0 8px 20px color-mix(in srgb,var(--primary) 34%,transparent)}

/* stat cards — glass, staggered; "They sent" (money IN) reads green */
#walletPersonHead .person-stat{
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 8%, var(--panel,#fff)), var(--panel,#fff));
  border:1px solid color-mix(in srgb,var(--primary) 14%,transparent);box-shadow:0 6px 16px rgba(0,0,0,.08);
  animation:fcHomeIn .5s cubic-bezier(.16,1,.3,1) backwards;animation-delay:.06s}
#walletPersonHead .person-stat:nth-child(2){animation-delay:.1s}
#walletPersonHead .person-stat:nth-child(2) strong{color:var(--money-in,#118a4e)}

/* premium actions */
#walletPersonActions .primary-button{position:relative;overflow:hidden;
  box-shadow:0 8px 22px color-mix(in srgb,var(--primary) 42%,transparent);
  animation:fcHomeIn .5s cubic-bezier(.16,1,.3,1) .04s backwards}
#walletPersonActions .primary-button::after{content:"";position:absolute;top:0;bottom:0;left:-70%;width:48%;pointer-events:none;
  background:linear-gradient(105deg, transparent, rgba(255,255,255,.4), transparent);transform:skewX(-18deg);opacity:0}
#walletPersonActions .primary-button:active::after{animation:fcShine .6s ease-out}
#walletPersonActions .secondary-button{border:1px solid color-mix(in srgb,var(--primary) 22%,transparent);
  animation:fcHomeIn .5s cubic-bezier(.16,1,.3,1) .08s backwards}
#walletPersonActions .person-chip{transition:transform .16s cubic-bezier(.2,0,0,1), border-color .2s ease}
#walletPersonActions .person-chip:active{transform:scale(.97)}

/* the "Between you two" list — same treatment as Activity */
#walletPersonDialog .person-list-title{display:flex;align-items:center;gap:9px}
#walletPersonDialog .person-list-title::after{content:"";flex:1;height:1px;border-radius:1px;
  background:linear-gradient(90deg, color-mix(in srgb,var(--primary) 45%,transparent), transparent)}
#walletPersonList .money-day{display:flex;align-items:center;gap:9px;
  background:color-mix(in srgb,var(--panel,#fff) 82%, transparent);
  backdrop-filter:blur(8px) saturate(1.1);-webkit-backdrop-filter:blur(8px) saturate(1.1)}
#walletPersonList .money-day::after{content:"";flex:1;height:1px;border-radius:1px;
  background:linear-gradient(90deg, color-mix(in srgb,var(--primary) 45%,transparent), transparent)}
#walletPersonList .money-row{position:relative;overflow:hidden;
  border:1px solid color-mix(in srgb,var(--primary) 10%,transparent);
  background:linear-gradient(180deg, color-mix(in srgb,var(--primary) 5%, var(--panel,#fff)), var(--panel,#fff));
  box-shadow:0 1px 2px rgba(0,0,0,.05), 0 8px 18px rgba(0,0,0,.08);
  transition:transform .16s cubic-bezier(.2,0,0,1), box-shadow .25s ease, border-color .25s ease}
#walletPersonList .money-row::after{content:"";position:absolute;top:0;bottom:0;left:-70%;width:46%;pointer-events:none;
  background:linear-gradient(105deg, transparent, rgba(255,255,255,.28), transparent);transform:skewX(-18deg);opacity:0}
#walletPersonList .money-row:active{transform:scale(.985);
  box-shadow:0 1px 2px rgba(0,0,0,.05), 0 4px 14px color-mix(in srgb,var(--primary) 24%,transparent)}
#walletPersonList .money-row:active::after{animation:fcShine .6s ease-out}
#walletPersonList > *{animation:fcHomeIn .45s cubic-bezier(.16,1,.3,1) backwards}
#walletPersonList .money-day{animation-name:fcFadeIn}
#walletPersonList > *:nth-child(1){animation-delay:.02s}#walletPersonList > *:nth-child(2){animation-delay:.05s}
#walletPersonList > *:nth-child(3){animation-delay:.08s}#walletPersonList > *:nth-child(4){animation-delay:.11s}
#walletPersonList > *:nth-child(5){animation-delay:.14s}#walletPersonList > *:nth-child(n+6){animation-delay:.17s}
#walletPersonList .money-badge{box-shadow:0 3px 12px color-mix(in srgb,currentColor 32%,transparent)}

@media (prefers-reduced-motion:reduce){
  #walletPersonDialog .person-scroll::before,#walletPersonHead .wallet-person,#walletPersonHead .person-stat,
  #walletPersonActions .primary-button,#walletPersonActions .primary-button::after,#walletPersonActions .secondary-button,
  #walletPersonList > *,#walletPersonList .money-row::after{animation:none!important}
  #walletPersonHead .wallet-person,#walletPersonHead .person-stat,#walletPersonActions .primary-button,
  #walletPersonActions .secondary-button,#walletPersonList > *{opacity:1;transform:none}
}
