/* ============================================================
   Lucky Dream — Staff UI Enhancement Layer  (enhance.css)
   Purely ADDITIVE polish: animations, shadows, depth, labels.
   ------------------------------------------------------------
   TO UNDO EVERYTHING:
     1. Delete the <link ... enhance.css> line in staff/index.html
     2. Delete this file (enhance.css)
   Nothing in styles.css / redesign.css / app.js is touched, so
   removing this file restores the exact previous look.
   ============================================================ */

:root{
  --ez:cubic-bezier(.22,.61,.36,1);
  --ez-out:cubic-bezier(.16,1,.3,1);
  --ez-pop:cubic-bezier(.34,1.56,.64,1);
  --dur:.18s;
  --lift:0 6px 18px rgba(0,0,0,.12);
  --lift-lg:0 14px 34px rgba(0,0,0,.20);
  --glow:0 6px 18px color-mix(in srgb,var(--primary) 42%,transparent);
}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]){--lift:0 8px 22px rgba(0,0,0,.45);--lift-lg:0 16px 40px rgba(0,0,0,.60)}}
:root[data-theme="dark"]{--lift:0 8px 22px rgba(0,0,0,.45);--lift-lg:0 16px 40px rgba(0,0,0,.60)}

/* ---- global smooth transitions -------------------------------------- */
button,select,input,textarea,a,
.conversation-card,.icon-button,.composer-button,.tap-button,
.header-avatar,.label-chip,.pane-tabs button,.media-filter button,
.theme-card,.send-button,dialog{
  transition:background-color var(--dur) var(--ez),color var(--dur) var(--ez),
             border-color var(--dur) var(--ez),box-shadow var(--dur) var(--ez),
             transform .2s var(--ez-out),filter var(--dur) var(--ez);
}

/* ---- keyframes ------------------------------------------------------- */
@keyframes dialogIn{from{opacity:0;transform:translateY(14px) scale(.97)}to{opacity:1;transform:none}}
@keyframes sheetIn{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}
@keyframes slideDown{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
@keyframes toastIn{from{opacity:0;transform:translate(-50%,18px) scale(.95)}to{opacity:1;transform:translate(-50%,0) scale(1)}}
@keyframes popIn{0%{opacity:0;transform:scale(.4)}60%{transform:scale(1.12)}100%{opacity:1;transform:scale(1)}}
@keyframes tipIn{from{opacity:0;transform:translate(-50%,4px)}to{opacity:1;transform:translate(-50%,0)}}
@keyframes shimmer{100%{background-position:200% 0}}
@keyframes softPulse{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--primary) 40%,transparent)}50%{box-shadow:0 0 0 6px transparent}}

/* ---- structural depth ----------------------------------------------- */
.sidebar{box-shadow:4px 0 24px rgba(0,0,0,.05)}
.details-panel{box-shadow:-4px 0 24px rgba(0,0,0,.05)}
.conversation-header{box-shadow:0 3px 14px rgba(0,0,0,.05);position:relative;z-index:3}
.composer{box-shadow:0 -3px 16px rgba(0,0,0,.06);position:relative;z-index:2}
.toolbar{position:relative;z-index:2}
.pane-tabs{box-shadow:0 2px 8px rgba(0,0,0,.04)}

/* ---- generic buttons: give every button a bit of life --------------- */
/* Press feedback for normal buttons only. Buttons that rely on a transform
   for POSITIONING (the funnel, the scroll-to-latest button) are excluded, or
   this would clobber their centering and move them out from under the cursor. */
button:not(:disabled):not(.filter-toggle):not(.scroll-latest):not(.hover-reply-button):active{transform:translateY(1px) scale(.985)}
/* The reply icon centers itself with translateY(-50%); like the funnel and the
   scroll-to-latest button, it must never be moved/resized by press or hover, or
   the click lands off it. Lock its centering transform in every state. */
.hover-reply-button,
.hover-reply-button:hover,
.hover-reply-button:active,
.hover-reply-button:focus,
.hover-reply-button:focus-visible{transform:translateY(-50%)!important}
button:disabled{opacity:.55;cursor:not-allowed}

/* primary / accent buttons: gradient + colored glow + hover lift ------ */
.primary-button,.record-send{
  background:linear-gradient(135deg,color-mix(in srgb,var(--primary) 88%,#fff 12%),var(--primary));
  box-shadow:var(--glow);border:none;font-weight:700;letter-spacing:.2px;
}
.primary-button:hover,.record-send:hover{transform:translateY(-2px);box-shadow:0 10px 26px color-mix(in srgb,var(--primary) 50%,transparent);filter:brightness(1.05)}
.primary-button:active,.record-send:active{transform:translateY(0)}

/* danger buttons */
.danger-button,.remove-filters{transition:transform .18s var(--ez-out),box-shadow .18s var(--ez),filter .18s}
.danger-button:hover{transform:translateY(-1px);box-shadow:0 8px 20px color-mix(in srgb,var(--danger) 34%,transparent);filter:brightness(1.03)}

/* details-panel + menu action buttons: hover slide + shadow ----------- */
.details-panel section button,.menu-section button,.dialog-actions button{
  border-radius:11px;
}
.details-panel section button:hover,.menu-section button:hover{
  transform:translateX(3px);box-shadow:var(--lift);
  border-color:color-mix(in srgb,var(--primary) 45%,var(--line));
}

/* ---- icon buttons: circular hover halo + press ---------------------- */
.icon-button{position:relative;border-radius:11px}
.icon-button:hover{background:color-mix(in srgb,var(--primary) 12%,transparent);color:var(--primary);transform:translateY(-1px)}
.icon-button:active{transform:scale(.92)}
.alerts-button:hover{transform:translateY(-1px) rotate(-8deg)}

/* ---- BUTTON LABELS ------------------------------------------------- */
/* All header nav buttons (Alerts, Menu, Find, Details) are icon-only. */

/* ---- composer buttons: playful hover + instant tooltip from title --- */
.composer-button{position:relative;border-radius:12px}
.composer-button:hover{background:color-mix(in srgb,var(--primary) 14%,transparent);color:var(--primary);transform:translateY(-2px) scale(1.06)}
.composer-button:active{transform:scale(.9)}
#cameraButton:hover,#galleryButton:hover{transform:translateY(-2px) scale(1.08) rotate(-6deg)}
#voiceButton:hover{transform:translateY(-2px) scale(1.08) rotate(6deg)}
.composer-button[title]:hover::after{
  content:attr(title);position:absolute;bottom:calc(100% + 9px);left:50%;
  transform:translateX(-50%);background:var(--text);color:var(--panel);
  padding:5px 9px;border-radius:8px;font-size:11px;font-weight:600;white-space:nowrap;
  pointer-events:none;box-shadow:var(--lift);z-index:40;animation:tipIn .14s var(--ez-out);
}

/* send button: gradient orb that pops on hover ------------------------ */
.send-button{background:linear-gradient(135deg,color-mix(in srgb,var(--primary) 85%,#fff 15%),var(--primary))!important;box-shadow:var(--glow)}
.send-button:hover{transform:translateY(-2px) scale(1.08);box-shadow:0 10px 26px color-mix(in srgb,var(--primary) 55%,transparent)}
.send-button:active{transform:scale(.94)}

/* ---- conversation cards: modern hover lift + active accent ---------- */
.conversation-card{border-radius:13px;margin:3px 7px;will-change:transform}
.conversation-card:hover{transform:translateX(3px);box-shadow:var(--lift);background:var(--hover)}
.conversation-card.active{box-shadow:inset 3px 0 0 var(--primary),var(--lift)}
.conversation-card.unread-card{box-shadow:inset 3px 0 0 var(--primary)}
.conversation-card.unread-card:hover{box-shadow:inset 3px 0 0 var(--primary),var(--lift)}

/* ---- filter panel reveal ------------------------------------------- */
#filterPanel:not(.hidden){animation:slideDown .22s var(--ez-out)}
/* Lock the funnel's vertical centering in EVERY state. Otherwise the global
   button-press transform (or any :active rule) overrides translateY(-50%) and
   drops the funnel ~20px, so the pointer ends up off it and the click is lost.
   The 180° flip lives on the child <svg>, so the button itself never moves. */
.filter-toggle,
.filter-toggle:hover,
.filter-toggle:active,
.filter-toggle:focus,
.filter-toggle:focus-visible,
.filter-toggle.active{transform:translateY(-50%)!important}
.filter-toggle svg{transition:transform .25s var(--ez-pop)}
.filter-toggle.active svg{transform:rotate(180deg)}
.filter-active-dot{animation:popIn .3s var(--ez-pop)}
#removeFiltersButton:not(.hidden){animation:slideDown .2s var(--ez-out)}

/* ---- pane tabs: animated active underline --------------------------- */
.pane-tabs button{position:relative;overflow:hidden}
.pane-tabs button::after{content:"";position:absolute;left:50%;right:50%;bottom:0;height:3px;border-radius:3px 3px 0 0;background:var(--primary);transition:left .25s var(--ez-out),right .25s var(--ez-out)}
.pane-tabs button.active::after{left:14%;right:14%}
.pane-tabs button:hover::after{left:32%;right:32%}

/* ---- dialogs: entrance + elevated shadow + blurred backdrop --------- */
dialog[open]{animation:dialogIn .22s var(--ez-out);box-shadow:var(--lift-lg)}
dialog.action-sheet[open]{animation:sheetIn .24s var(--ez-out)}
dialog::backdrop{background:rgba(15,20,30,.42);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
dialog header button[data-close]{border-radius:9px;transition:transform .2s var(--ez-out),background-color .2s}
dialog header button[data-close]:hover{transform:rotate(90deg);background:color-mix(in srgb,var(--danger) 16%,transparent);color:var(--danger)}

/* search results / list rows in dialogs */
.search-result:hover,.referrer-picker .search-result:hover{transform:translateX(3px);box-shadow:var(--lift)}

/* ---- toast ---------------------------------------------------------- */
.toast:not(.hidden){animation:toastIn .28s var(--ez-out);box-shadow:var(--lift-lg)}

/* ---- floating "scroll to latest" button ----------------------------- */
/* The base centers this with left:50% + transform:translateX(-50%). If ANY
   state changes that transform (a lift, a shrink, or an off-center appear
   frame) the button shifts out from under the pointer and the click is lost.
   So we LOCK the transform to the centering in every state (incl. the shared
   .tap-button:active) and only ever change shadow/brightness. The appear
   animation fades opacity only and never touches transform. Result: the button
   never moves or resizes, so a click always lands on it. */
.scroll-latest,
.scroll-latest:hover,
.scroll-latest:active,
.scroll-latest:focus,
.scroll-latest:focus-visible,
.scroll-latest.tap-button:active{transform:translateX(-50%)!important}
@keyframes scrollLatestIn{from{opacity:0}to{opacity:1}}
.scroll-latest:not(.hidden){animation:scrollLatestIn .18s ease}
.scroll-latest{box-shadow:var(--lift);transition:box-shadow var(--dur) var(--ez),filter var(--dur) var(--ez),background-color var(--dur) var(--ez)}
.scroll-latest:hover{box-shadow:var(--lift-lg);filter:brightness(1.03)}
.scroll-latest:active{filter:brightness(.92)}

/* ---- inputs & selects: focus glow + gentle lift --------------------- */
.search-wrap input:focus,.filter-row select:focus,.toolbar input:focus,
input:focus,textarea:focus,select:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 20%,transparent),var(--lift)!important}
.search-wrap:focus-within svg{color:var(--primary)}

/* ---- avatars: subtle ring + hover pop ------------------------------- */
.header-avatar{transition:transform .2s var(--ez-out),box-shadow .2s}
.header-avatar:hover{transform:scale(1.05)}
.online-dot{box-shadow:0 0 0 2px var(--panel)}
.online-dot:not(.hidden){animation:softPulse 2.4s var(--ez) infinite}

/* ---- typing indicator glow ----------------------------------------- */
.typing-indicator:not(.hidden){animation:slideDown .2s var(--ez-out)}

/* ---- loading shimmer for skeleton/edge loaders --------------------- */
.edge-loader:not(.hidden){animation:slideDown .2s var(--ez-out)}

/* ---- viewer (image lightbox) arrows -------------------------------- */
.viewer-arrow:hover{transform:scale(1.12)}
.viewer-close:hover{transform:rotate(90deg)}

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

/* ---- games & site balance (details panel + connect dialog) ------------ */
.staff-wallet-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;margin-bottom:8px;
  border-radius:12px;background:var(--hover)}
.staff-wallet-row span{color:var(--muted);font-size:12.5px;text-transform:uppercase;letter-spacing:.04em}
.staff-wallet-row strong{font-size:19px;font-weight:800}
.staff-game-list{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.staff-game-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--line);border-radius:10px}
.staff-game-label{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}
.staff-game-label strong{font-size:13.5px}
.staff-game-label small{color:var(--muted);font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.staff-game-label small.ok{color:#15803d}
.staff-game-label small.warn{color:#b45309}
.staff-game-balance{font-weight:700;font-size:13.5px;white-space:nowrap}
.link-button{background:none;border:none;color:var(--primary);font-size:12.5px;cursor:pointer;padding:2px 4px}
.game-connect-list{display:flex;flex-direction:column;gap:8px;padding:12px 14px}
.game-connect-row{display:flex;align-items:center;gap:12px;padding:10px 12px;border:1px solid var(--line);border-radius:12px}
.game-connect-row .primary-button{width:auto;padding:8px 16px;white-space:nowrap}
#gameConnectForm{display:flex;flex-direction:column;gap:10px;padding:0 14px 16px}
#gameConnectName{margin:0;font-weight:700}
.game-connect-note{margin:0;color:var(--muted);font-size:12.5px}
.game-captcha{align-self:flex-start;height:52px;border-radius:8px;background:#fff;border:1px solid var(--line)}
.inline-error{margin:0;color:#d92d20;font-size:13px;font-weight:600}

/* ---- games: bigger captcha, history rows, mini refresh ---------------- */
.game-captcha{align-self:center;height:96px;image-rendering:crisp-edges;border-radius:10px;background:#fff;
  border:1px solid var(--line);padding:4px}
#gameCaptchaInput{font-size:20px;letter-spacing:.28em;text-align:center;font-weight:700}
.mini-refresh{margin-left:auto;background:none;border:none;color:var(--primary);font-size:16px;cursor:pointer;
  padding:2px 6px;border-radius:8px;line-height:1}
.mini-refresh:hover{background:var(--hover)}
.staff-history-list{display:flex;flex-direction:column;gap:6px;padding:12px 14px;max-height:60vh;overflow-y:auto}
.staff-history-row{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:10px}
.staff-history-row.voided{opacity:.55}
.staff-history-row.voided strong,.staff-history-row.voided .staff-history-amount{text-decoration:line-through}
.staff-history-amount{font-weight:800;font-size:14px;white-space:nowrap}
.staff-history-amount.in{color:#15803d}
.staff-history-amount.out{color:#b42318}
.link-button.danger{color:#b42318}

/* ---- game disconnect banner (all staff see it at once) ---------------- */
.game-alert-banner{position:fixed;top:0;left:0;right:0;z-index:60;display:block;width:100%;padding:11px 16px;border:none;
  background:#b45309;color:#fff;font-size:13.5px;font-weight:700;text-align:center;cursor:pointer;
  box-shadow:0 2px 10px rgba(0,0,0,.25)}
.game-alert-banner:hover{background:#92400e}

/* ---- team chat: seen-by avatars + message info ----------------------- */
.team-seen-row{display:flex;gap:4px;justify-content:flex-end;padding:2px 12px 6px;flex-wrap:wrap}
.seen-avatar{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;
  background:linear-gradient(135deg,var(--primary),color-mix(in srgb,var(--primary) 55%,#000));
  color:#fff;font-size:9.5px;font-weight:800;letter-spacing:.02em;flex:0 0 auto;box-shadow:0 1px 3px rgba(0,0,0,.25)}
.info-section-head{margin:14px 0 6px;font-size:13px;font-weight:800;color:var(--text)}
.info-muted{margin:2px 0;color:var(--muted);font-size:12.5px}
.info-person{display:flex;align-items:center;gap:8px;padding:5px 0}
.info-person .seen-avatar{width:24px;height:24px;font-size:10.5px}
.info-person-name{flex:1;font-size:13.5px}
.info-person-time{color:var(--muted);font-size:12px;white-space:nowrap}

/* ---- staff reactions: "+" opens full emoji picker -------------------- */
.quick-reactions .more-reactions{font-size:20px;font-weight:700;line-height:1;color:var(--muted);
  min-width:38px;display:inline-flex;align-items:center;justify-content:center}
.quick-reactions .more-reactions:hover{color:var(--primary)}
.reaction-picker-sheet{border:none;border-radius:16px;padding:0;max-width:420px;width:92vw;
  background:var(--panel);color:var(--text)}
.reaction-picker-sheet header{display:flex;align-items:center;justify-content:space-between;
  padding:12px 16px;border-bottom:1px solid var(--line)}
.reaction-picker-sheet header button{background:none;border:0;font-size:20px;color:var(--muted);cursor:pointer}
.reaction-picker-grid{display:grid;grid-template-columns:repeat(8,1fr);gap:2px;padding:12px;
  max-height:52vh;overflow-y:auto}
.reaction-picker-grid button{font-size:23px;background:none;border:0;border-radius:9px;padding:6px 0;cursor:pointer}
.reaction-picker-grid button:hover{background:var(--hover)}
@media(max-width:520px){.reaction-picker-grid{grid-template-columns:repeat(6,1fr)}}

/* ---- staff who-reacted popover (long-press a reaction chip) ----------- */
.reaction-info-sheet{border:none;border-radius:16px;padding:0;max-width:380px;width:90vw;
  background:var(--panel);color:var(--text)}
.reaction-info-sheet header{display:flex;align-items:center;justify-content:space-between;
  padding:12px 16px;border-bottom:1px solid var(--line)}
.reaction-info-sheet header button{background:none;border:0;font-size:20px;color:var(--muted);cursor:pointer}
.reaction-info-list{padding:6px 0 12px;max-height:56vh;overflow-y:auto}
.reaction-info-row{display:flex;align-items:center;gap:13px;padding:10px 18px;border-bottom:1px solid var(--line)}
.reaction-info-row:last-child{border-bottom:0}
.reaction-info-emoji{font-size:26px;line-height:1;filter:drop-shadow(0 2px 2px rgba(0,0,0,.28))}
.reaction-info-copy{display:flex;flex-direction:column;gap:2px}
.reaction-info-copy strong{font-size:14.5px}
.reaction-info-copy small{color:var(--muted);font-size:12.5px}
.reaction-chip{cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}

/* ---- monitoring mode: small floating draggable bubble ---------------- */
.monitor-bubble{position:fixed;z-index:80;display:inline-flex;align-items:center;gap:7px;
  padding:6px 8px 6px 12px;border-radius:999px;background:rgba(29,78,216,.68);
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);color:#fff;font-size:12px;font-weight:700;
  white-space:nowrap;cursor:grab;user-select:none;-webkit-user-select:none;touch-action:none;
  box-shadow:0 6px 18px rgba(0,0,0,.28);animation:monitorFloat 3.6s ease-in-out infinite}
.monitor-bubble.monitor-away{background:rgba(180,83,9,.72)}
.monitor-bubble.dragging{cursor:grabbing;animation:none;box-shadow:0 10px 26px rgba(0,0,0,.4)}
.monitor-bubble button{background:rgba(255,255,255,.24);border:0;color:#fff;width:19px;height:19px;
  border-radius:50%;font-size:14px;line-height:1;cursor:pointer;display:grid;place-items:center;flex:0 0 auto}
.monitor-bubble button:hover{background:rgba(255,255,255,.4)}
@keyframes monitorFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}
@media(prefers-reduced-motion:reduce){.monitor-bubble{animation:none}}
.monitor-employee-list{display:flex;flex-direction:column;gap:6px;padding:6px 4px 12px;max-height:56vh;overflow-y:auto}
.monitor-employee-row{display:flex;flex-direction:column;gap:2px;text-align:left;padding:11px 13px;
  border:1px solid var(--line);border-radius:12px;background:var(--panel);color:var(--text);cursor:pointer}
.monitor-employee-row:hover{background:var(--hover)}
.monitor-employee-row strong{font-size:14px}
.monitor-employee-row small{color:var(--muted);font-size:12px}

/* ---- customer details: grouped, icon-led, animated ---------------------- */
.details-panel>#detailsBody{padding:12px;border-bottom:0;display:grid;gap:10px}
.details-panel .identity-card{display:flex;align-items:center;gap:12px;padding:14px 13px;border:1px solid var(--line);border-bottom:1px solid var(--line);border-radius:16px;position:relative;overflow:hidden;background:linear-gradient(135deg,color-mix(in srgb,var(--primary),transparent 90%),var(--panel) 62%);box-shadow:0 2px 4px rgba(0,0,0,.04),0 18px 34px -24px rgba(0,0,0,.65)}
.identity-card:before{content:"";position:absolute;top:-60%;left:0;width:55%;height:220%;pointer-events:none;background:linear-gradient(90deg,transparent,rgba(255,255,255,.22),transparent);animation:identitySheen 7.5s ease-in-out infinite}
@keyframes identitySheen{0%,72%{transform:translateX(-140%) rotate(18deg)}100%{transform:translateX(330%) rotate(18deg)}}
.identity-avatar{position:relative;width:52px;height:52px;flex:none;border-radius:50%;display:grid;place-items:center;background:#dbeafe;color:#0759bd;font-weight:700;font-size:21px;box-shadow:0 4px 14px rgba(0,0,0,.22),inset 0 1px 0 rgba(255,255,255,.55)}
.identity-avatar img{width:100%;height:100%;border-radius:50%;object-fit:cover}
.identity-dot{position:absolute;right:0;bottom:2px;width:13px;height:13px;border-radius:50%;border:2px solid var(--panel);background:var(--muted)}
.identity-dot.online{background:#31a24c;animation:identityPulse 2.8s ease-in-out infinite}
@keyframes identityPulse{0%,100%{box-shadow:0 0 0 0 rgba(49,162,76,.5)}50%{box-shadow:0 0 0 7px rgba(49,162,76,0)}}
.identity-copy{display:grid;gap:2px;min-width:0;position:relative}
.identity-copy strong{font-size:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.identity-copy span{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.detail-chips{display:flex;flex-wrap:wrap;gap:6px}
.detail-chip{display:inline-flex;align-items:center;gap:5px;padding:5px 10px;border-radius:999px;border:1px solid var(--line);background:var(--panel2);font-size:12px;font-weight:600;cursor:default;box-shadow:0 1px 2px rgba(0,0,0,.05);transition:transform .32s cubic-bezier(.34,1.56,.64,1),box-shadow .32s ease}
.detail-chip:hover{transform:translateY(-2px);box-shadow:0 7px 16px -7px rgba(0,0,0,.5)}
.detail-chip i{font-style:normal;font-size:13px;filter:drop-shadow(0 1px 1px rgba(0,0,0,.25))}
.detail-chip.good{color:#15803d;border-color:color-mix(in srgb,#15803d,transparent 70%);background:color-mix(in srgb,#15803d,transparent 92%)}
.detail-chip.muted{color:var(--muted)}

.details-panel .detail-group{padding:0;border:1px solid var(--line);border-radius:14px;background:var(--panel);overflow:hidden;box-shadow:0 1px 2px rgba(0,0,0,.04),0 12px 26px -20px rgba(0,0,0,.55);transition:box-shadow .38s ease,border-color .38s ease}
.details-panel>.detail-group{margin:10px 12px}
.details-panel .detail-group:hover{border-color:color-mix(in srgb,var(--primary),var(--line) 62%)}
.details-panel .detail-group.open{box-shadow:0 2px 5px rgba(0,0,0,.05),0 20px 38px -24px rgba(0,0,0,.62)}
/* .details-panel button already sets a flat background, so these need the extra
   specificity or the header gradient silently loses. */
.details-panel .detail-group-head{position:relative;display:flex;align-items:center;gap:9px;width:100%;margin:0;padding:11px 12px;border:0;border-radius:0;background:linear-gradient(180deg,color-mix(in srgb,var(--panel2),transparent 25%),var(--panel));text-align:left;font-weight:700;font-size:13.5px;min-height:46px;transition:background .3s ease}
.details-panel .detail-group-head:hover{background:var(--hover)}
.detail-group-head:after{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--primary);opacity:0;transition:opacity .38s ease}
.detail-group.open .detail-group-head:after{opacity:1}
.dg-icon{font-size:16px;line-height:1;filter:drop-shadow(0 1px 2px rgba(0,0,0,.3));transition:transform .45s cubic-bezier(.34,1.56,.64,1)}
.detail-group.open .dg-icon{transform:scale(1.16) rotate(-6deg)}
.dg-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dg-badge{flex:none;min-width:20px;padding:1px 7px;border-radius:999px;background:color-mix(in srgb,var(--primary),transparent 86%);color:var(--primary);font-size:11px;font-weight:700;text-align:center}
.dg-caret{flex:none;color:var(--muted);font-size:12px;transition:transform .4s cubic-bezier(.4,0,.2,1)}
.detail-group.open .dg-caret{transform:rotate(180deg)}
.detail-group-body{display:grid;grid-template-rows:0fr;transition:grid-template-rows .42s cubic-bezier(.4,0,.2,1)}
.detail-group.open .detail-group-body{grid-template-rows:1fr}
.dg-inner{overflow:hidden;min-height:0;padding:0 12px;opacity:0;transform:translateY(-5px);transition:opacity .32s ease .05s,transform .38s ease .05s,padding .42s cubic-bezier(.4,0,.2,1)}
.detail-group.open .dg-inner{opacity:1;transform:none;padding:2px 12px 12px}
.dg-inner>button,.dg-inner>input{width:100%;margin:4px 0}
.dg-row{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0;padding:6px 0;border-bottom:1px dashed color-mix(in srgb,var(--line),transparent 45%);font-size:13px}
.dg-row:last-child{border-bottom:0}
.dg-row-label{flex:none;color:var(--muted)}
.dg-row-value{text-align:right;font-weight:600;overflow-wrap:anywhere}
.contact-card{padding:8px 0;border-bottom:1px dashed color-mix(in srgb,var(--line),transparent 45%)}
.contact-card:last-child{border-bottom:0}
.contact-card strong{display:block;font-size:13px;overflow-wrap:anywhere}
@media(prefers-reduced-motion:reduce){
  .identity-card:before,.identity-dot.online{animation:none}
  .detail-group-body,.dg-inner,.dg-caret,.dg-icon,.detail-chip,.detail-group{transition-duration:.01ms}
}

/* Pinned messages sits with the search control, not in the tab cluster: it
   takes over the margin-left:auto so the pair stays right-aligned together. */
.pane-tabs #staffPinnedButton{margin-left:auto;width:36px;height:36px;min-height:36px;padding:0;border-radius:9px;display:grid;place-items:center;background:var(--panel2);font-size:16px;line-height:1;transition:transform .3s cubic-bezier(.34,1.56,.64,1),background .25s ease}
.pane-tabs #staffPinnedButton:hover{background:var(--hover);transform:translateY(-1px) rotate(-12deg)}
.pane-tabs #staffPinnedButton+#conversationSearchButton{margin-left:6px}

/* Search scope: names by default, messages/notes one tap away. */
.search-scope{display:flex;align-items:center;flex-wrap:wrap;gap:5px;padding:2px 1px 0;font-size:12px;animation:slideDown .22s var(--ez-out)}
.search-scope>span{color:var(--muted);margin-right:2px}
.search-scope button{min-height:26px;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600;color:var(--muted);background:var(--panel2);border:1px solid var(--line)}
.search-scope button:hover{color:var(--primary);border-color:color-mix(in srgb,var(--primary) 45%,var(--line))}
.search-scope button.active{color:var(--primary);background:color-mix(in srgb,var(--primary) 14%,var(--panel));border-color:color-mix(in srgb,var(--primary) 45%,var(--line))}

/* ---- on-screen alert stack ---------------------------------------------
   Sits over the sidebar brand block and stops short of the ☰ menu button, so
   alerts never cover the control you need to dismiss them from.            */
.staff-alert-stack{position:fixed;z-index:10050;top:max(10px,env(safe-area-inset-top));left:10px;
  width:238px;max-width:calc(100vw - 96px);display:flex;flex-direction:column;gap:6px;pointer-events:none}
.staff-alert{display:flex;align-items:flex-start;gap:6px;padding:9px 8px 9px 11px;border-radius:12px;
  border:1px solid var(--line);background:var(--panel);color:var(--text);pointer-events:auto;
  box-shadow:0 12px 34px -12px rgba(0,0,0,.5),0 0 0 1px color-mix(in srgb,var(--primary) 22%,transparent);
  animation:staffAlertIn .22s cubic-bezier(.16,1,.3,1)}
@keyframes staffAlertIn{from{opacity:0;transform:translateY(-10px) scale(.97)}to{opacity:1;transform:none}}
.staff-alert-copy{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;padding:0;margin:0;border:0;
  background:transparent;text-align:left;min-height:0;color:inherit;cursor:pointer}
.staff-alert-copy strong{font-size:12.5px;line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.staff-alert-copy span{font-size:12px;line-height:1.35;color:var(--muted);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.staff-alert-copy span.hidden{display:none!important}
.staff-alert-close{flex:none;width:22px;height:22px;min-height:22px;padding:0;border:0;border-radius:50%;
  background:transparent;color:var(--muted);font-size:16px;line-height:1;display:grid;place-items:center;cursor:pointer}
.staff-alert-close:hover{background:var(--hover);color:var(--text)}

/* ---- formatting toolbar + live preview ---------------------------------- */
.format-bar{display:flex;flex-wrap:wrap;gap:4px;padding:6px 4px 2px}
.format-bar button{min-height:30px;padding:3px 9px;border-radius:8px;font-size:13px;
  background:var(--panel2);border:1px solid var(--line);color:var(--text)}
.format-bar button:hover{background:var(--hover);border-color:color-mix(in srgb,var(--primary) 45%,var(--line))}
.composer-preview{margin:0 0 6px;padding:8px 10px;border-radius:12px;background:var(--panel2);
  border:1px solid var(--line);animation:slideDown .18s var(--ez-out)}
.composer-preview>small{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;
  color:var(--muted);margin-bottom:5px}
.composer-preview.preview-error{background:color-mix(in srgb,var(--danger) 10%,var(--panel));
  border-color:color-mix(in srgb,var(--danger) 42%,var(--line))}
.composer-preview.preview-error>small{color:var(--danger);text-transform:none;font-size:12px;letter-spacing:0}
.preview-bubble{padding:8px 11px;border-radius:14px;background:var(--bubble-in,var(--panel));
  font-size:13.5px;line-height:1.4;overflow-wrap:anywhere;white-space:pre-wrap}
.preview-chip{display:inline-block;padding:1px 7px;margin:0 1px;border-radius:7px;
  background:rgba(125,125,125,.22);font-weight:600}
.preview-button{display:block;margin:7px 0 1px;padding:8px 12px;border-radius:10px;
  background:var(--primary);color:#fff;font-weight:700;text-align:center}
.code-prompt-fields{display:grid;gap:10px}
.code-prompt-fields label{display:grid;gap:4px;font-size:13px;color:var(--muted)}
.code-prompt-fields input{padding:11px;font-size:15px}
.code-prompt-note{color:var(--muted);font-size:12px}

/* ---- prompt builder inside Saved replies -------------------------------- */
.prompt-builder{margin-top:4px;padding:10px 11px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
.prompt-builder-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
.prompt-builder-head strong{font-size:13px}
.prompt-builder-head button{min-height:28px;padding:3px 10px;border-radius:8px;font-size:12px}
.prompt-builder>small{display:block;margin:5px 0 8px;font-size:11.5px;line-height:1.45;color:var(--muted)}
.prompt-builder code{padding:1px 5px;border-radius:5px;background:var(--hover);font-size:11.5px}
.prompt-field-list{display:grid;gap:7px}
.prompt-field{display:grid;grid-template-columns:1fr 1.4fr auto auto auto;gap:6px;align-items:center}
.prompt-field input[type=text]{padding:7px 9px;font-size:13px;min-width:0}
.prompt-field select{padding:7px 6px;font-size:12px}
.prompt-field label{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:var(--muted);white-space:nowrap}
.prompt-field button{width:28px;height:28px;min-height:28px;padding:0;border-radius:8px;color:var(--danger)}
@media(max-width:760px){.prompt-field{grid-template-columns:1fr 1fr}}

/* Formatted messages inside the staff thread, matching the customer view. */
.bubble .preview-chip{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;margin:0 1px;
  border:1px solid rgba(125,125,125,.35);border-radius:7px;background:rgba(125,125,125,.22);
  font:inherit;font-weight:600;color:inherit;vertical-align:baseline}
.bubble .preview-chip.copyable{cursor:pointer}
.bubble .preview-chip.copyable:hover{background:rgba(125,125,125,.34)}
.bubble .preview-button{display:block;margin:8px 0 2px;padding:9px 13px;border-radius:11px;
  background:rgba(255,255,255,.22);color:inherit;font-weight:700;text-align:center}
.employee .bubble .preview-button{background:rgba(255,255,255,.24)}
.customer .bubble .preview-button{background:var(--primary);color:#fff}

/* ---- animated emoji ----------------------------------------------------
   Ordinary glyphs animated with CSS: nothing to download, works offline,
   stays sharp at any size. Motion is disabled for anyone who asks for that. */
.fc-gif{display:inline-block;font-style:normal;line-height:1;vertical-align:-.12em;will-change:transform}
.fc-gif-loading{animation:fcgSpin 1.6s linear infinite}
.fc-gif-spinner{animation:fcgSpin 1s linear infinite}
.fc-gif-clock{animation:fcgSpin 2.4s steps(8) infinite}
.fc-gif-hourglass{animation:fcgFlip 2s ease-in-out infinite}
.fc-gif-check{animation:fcgPop 1.8s ease-out infinite}
.fc-gif-cross{animation:fcgShake .9s ease-in-out infinite}
.fc-gif-warning{animation:fcgBlink 1.1s ease-in-out infinite}
.fc-gif-bell{animation:fcgRing 1.6s ease-in-out infinite;transform-origin:50% 0}
.fc-gif-fire{animation:fcgFlicker .55s ease-in-out infinite alternate}
.fc-gif-money{animation:fcgBounce 1s ease-in-out infinite}
.fc-gif-party{animation:fcgShake 1.2s ease-in-out infinite}
.fc-gif-star{animation:fcgTwinkle 1.4s ease-in-out infinite}
.fc-gif-heart{animation:fcgBeat .9s ease-in-out infinite}
.fc-gif-wave{animation:fcgWave 1.1s ease-in-out infinite;transform-origin:70% 80%}
.fc-gif-thumbsup{animation:fcgPop 1.5s ease-out infinite}
.fc-gif-rocket{animation:fcgRise 1.6s ease-in-out infinite}
.fc-gif-gift{animation:fcgShake 1.6s ease-in-out infinite}
.fc-gif-crown{animation:fcgTwinkle 1.8s ease-in-out infinite}
.fc-gif-dice{animation:fcgSpin 1.4s ease-in-out infinite}
.fc-gif-gem{animation:fcgTwinkle 1.2s ease-in-out infinite}
@keyframes fcgSpin{to{transform:rotate(360deg)}}
@keyframes fcgFlip{0%,45%{transform:rotate(0)}55%,100%{transform:rotate(180deg)}}
@keyframes fcgPop{0%,70%,100%{transform:scale(1)}80%{transform:scale(1.28)}}
@keyframes fcgShake{0%,100%{transform:rotate(0)}25%{transform:rotate(11deg)}75%{transform:rotate(-11deg)}}
@keyframes fcgBlink{0%,100%{opacity:1}50%{opacity:.35}}
@keyframes fcgRing{0%,60%,100%{transform:rotate(0)}70%{transform:rotate(14deg)}85%{transform:rotate(-14deg)}}
@keyframes fcgFlicker{from{transform:scale(1) translateY(0);filter:brightness(1)}to{transform:scale(1.13) translateY(-1px);filter:brightness(1.25)}}
@keyframes fcgBounce{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
@keyframes fcgTwinkle{0%,100%{transform:scale(1) rotate(0);opacity:1}50%{transform:scale(1.22) rotate(18deg);opacity:.75}}
@keyframes fcgBeat{0%,100%{transform:scale(1)}30%{transform:scale(1.24)}45%{transform:scale(1.05)}}
@keyframes fcgWave{0%,100%{transform:rotate(0)}30%{transform:rotate(22deg)}60%{transform:rotate(-12deg)}}
@keyframes fcgRise{0%,100%{transform:translateY(0) rotate(0)}50%{transform:translateY(-6px) rotate(-8deg)}}
/* These are CONTENT — a staff member inserts one the way they would a GIF,
   and a GIF plays regardless of this setting. So reduced motion slows them
   right down rather than stopping them, which previously made them look
   broken on any device with battery saver or "remove animations" on.
   Decorative UI animation elsewhere still honours the setting fully. */
@media(prefers-reduced-motion:reduce){.fc-gif{animation-duration:3.2s!important}}
.contact-shared-note{display:block;margin:3px 0 2px;font-size:11.5px;color:var(--muted)}
.may-know-row{display:flex;align-items:stretch;gap:5px}
.may-know-row .may-know-person{flex:1;min-width:0}
.may-know-remove{flex:none;width:28px;min-height:28px;padding:0;border-radius:8px;color:var(--danger);align-self:center}
.may-know-remove:hover{background:color-mix(in srgb,var(--danger) 14%,transparent)}
.color-picker-body{display:grid;gap:12px;padding:14px}
.color-swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(42px,1fr));gap:8px}
.color-swatch{height:42px;min-height:42px;padding:0;border-radius:10px;border:1px solid rgba(125,125,125,.35);
  cursor:pointer;transition:transform .18s cubic-bezier(.34,1.56,.64,1),box-shadow .18s ease}
.color-swatch:hover{transform:translateY(-2px) scale(1.06);box-shadow:0 8px 18px -8px rgba(0,0,0,.6)}
.color-custom{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:13px;
  padding:9px 11px;border:1px solid var(--line);border-radius:11px;background:var(--panel2)}
.color-custom input[type=color]{width:52px;height:32px;padding:0;border-radius:8px;cursor:pointer}
.color-hint{color:var(--muted);font-size:12px;line-height:1.45}

/* Recharge and Cash Out sit side by side and are colour-coded, so the
   direction the money moves is decided by which button you press rather than
   by remembering a minus sign. */
.wallet-action-row{display:flex;gap:8px;margin:4px 0}
.wallet-action-row.hidden{display:none}
.dg-inner>.wallet-action-row>button{flex:1;width:auto;margin:0}
.wallet-action{position:relative;overflow:hidden;font-weight:600;transition:transform .18s ease,box-shadow .28s ease,filter .28s ease}
.wallet-action.recharge{border-color:rgba(52,199,89,.45);box-shadow:inset 0 0 0 1px rgba(52,199,89,.12)}
.wallet-action.cashout{border-color:rgba(255,149,0,.45);box-shadow:inset 0 0 0 1px rgba(255,149,0,.12)}
.wallet-action:hover{transform:translateY(-1px);filter:brightness(1.08)}
.wallet-action.recharge:hover{box-shadow:0 8px 18px -10px rgba(52,199,89,.8),inset 0 0 0 1px rgba(52,199,89,.3)}
.wallet-action.cashout:hover{box-shadow:0 8px 18px -10px rgba(255,149,0,.8),inset 0 0 0 1px rgba(255,149,0,.3)}
.wallet-action:active{transform:translateY(0) scale(.985)}
@media (prefers-reduced-motion:reduce){.wallet-action{transition-duration:.01ms}}

/* ---- reports: leaderboard + one person's record ---------------------- */
.report-body{padding:12px 14px 22px;display:flex;flex-direction:column;gap:12px}
.report-periods,.report-sorts{display:flex;flex-wrap:wrap;gap:6px}
.report-periods button,.report-sorts button{padding:6px 12px;border:1px solid var(--line);border-radius:999px;
  background:var(--panel2);color:var(--muted);font-size:12.5px;cursor:pointer;
  transition:background .22s ease,color .22s ease,border-color .22s ease,transform .16s ease}
.report-periods button:hover,.report-sorts button:hover{transform:translateY(-1px);color:var(--text)}
.report-periods button.active,.report-sorts button.active{background:var(--accent,#0084ff);border-color:transparent;color:#fff;font-weight:600}
.report-heading{margin:6px 0 0;font-size:13px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
.report-lead{margin:0;font-size:13px;color:var(--muted)}
.report-totals{display:grid;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));gap:8px}
.report-totals.compact{grid-template-columns:repeat(auto-fit,minmax(92px,1fr))}
.report-card{padding:11px 12px;border:1px solid var(--line);border-radius:13px;background:var(--panel2);
  display:flex;flex-direction:column;gap:2px;box-shadow:inset 0 1px 0 rgba(255,255,255,.04)}
.report-card strong{font-size:16px;font-variant-numeric:tabular-nums}
.report-card small{font-size:11px;color:var(--muted)}
.report-card.in strong{color:#34c759}
.report-card.out strong{color:#ff9500}
.report-board{display:flex;flex-direction:column;gap:6px}
.report-row{display:grid;grid-template-columns:30px minmax(90px,1fr) auto;align-items:center;gap:8px;
  padding:9px 10px;border:1px solid var(--line);border-radius:12px;background:var(--panel2);
  transition:transform .18s ease,box-shadow .28s ease}
.report-row:hover{transform:translateY(-1px);box-shadow:0 8px 18px -12px rgba(0,0,0,.7)}
.report-rank{font-size:14px;text-align:center;color:var(--muted);font-variant-numeric:tabular-nums}
.report-name{border:0;background:transparent;color:var(--text);font-weight:600;font-size:13.5px;
  text-align:left;padding:0;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.report-name:hover:not(:disabled){text-decoration:underline}
.report-name:disabled{cursor:default}
.report-figures{display:flex;flex-wrap:wrap;gap:4px 10px;justify-content:flex-end}
.report-figure{display:flex;flex-direction:column;align-items:flex-end;min-width:58px}
.report-figure strong{font-size:12.5px;font-variant-numeric:tabular-nums}
.report-figure small{font-size:10px;color:var(--muted)}
.report-figure.in strong{color:#34c759}
.report-figure.out strong{color:#ff9500}
.report-empty{margin:0;padding:14px;text-align:center;color:var(--muted);font-size:13px}
.report-csv{margin-top:6px}
@media (max-width:520px){
  .report-row{grid-template-columns:26px 1fr;grid-template-areas:'rank name' 'figs figs'}
  .report-rank{grid-area:rank}.report-name{grid-area:name}
  .report-figures{grid-area:figs;justify-content:flex-start;margin-top:4px}
}
@media (prefers-reduced-motion:reduce){
  .report-row,.report-periods button,.report-sorts button{transition-duration:.01ms}
}

/* Storing a token is what connects a game; the login button is only a way to
   fetch one. Saying so here saves the same question being asked again. */
.game-connect-hint{margin:0 0 10px;padding:9px 11px;border-radius:11px;
  background:var(--panel2);border:1px solid var(--line);
  color:var(--muted);font-size:12px;line-height:1.5}
.game-connect-manual{color:var(--muted);font-size:11.5px;text-align:right;white-space:nowrap}

/* The inbox loads a page at a time; this is the marker at the bottom. */
.conversation-more{padding:14px;text-align:center;color:var(--muted);font-size:12.5px;letter-spacing:.02em}
/* A name change is only useful with the name it replaced. */
.name-history-change{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px}
.name-was{color:var(--muted);text-decoration:line-through;text-decoration-thickness:1px}
.name-arrow{color:var(--muted);font-size:12px}
.name-now{color:var(--text)}
.staff-game-move{display:flex;gap:6px;margin-left:auto}
.staff-game-move button{padding:3px 9px;font-size:12px;border-radius:8px}

/* Requests parked while a game panel was down. They clear themselves when a
   token arrives; these are the manual ways out. */
.staff-pending-list{display:flex;flex-direction:column;gap:6px;margin:2px 0 8px}
.staff-pending-head{margin:0;font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:#ff9500}
.staff-pending-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:9px 10px;border:1px solid rgba(255,149,0,.4);border-radius:12px;
  background:color-mix(in srgb,#ff9500 8%,var(--panel2));
  box-shadow:inset 0 0 0 1px rgba(255,149,0,.08)}
.staff-pending-row .staff-game-label{flex:1;min-width:130px}
.staff-pending-actions{display:flex;gap:6px;margin-left:auto}
.staff-pending-actions button{padding:4px 10px;font-size:12px;border-radius:9px}

/* Automatic customer messages — the wording of everything the system says on
   its own, kept apart from saved replies. */
.sysmsg-body{padding:12px 14px 22px;display:flex;flex-direction:column;gap:12px}
.sysmsg-intro{margin:0;padding:10px 12px;border-radius:11px;background:var(--panel2);
  border:1px solid var(--line);color:var(--muted);font-size:12.5px;line-height:1.55}
.sysmsg-card{display:flex;flex-direction:column;gap:7px;padding:12px;border:1px solid var(--line);
  border-radius:13px;background:var(--panel2);transition:opacity .25s ease,border-color .25s ease}
.sysmsg-card.off{opacity:.62;border-color:rgba(255,149,0,.4)}
.sysmsg-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.sysmsg-head strong{font-size:14px}
.sysmsg-toggle{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);cursor:pointer;user-select:none}
.sysmsg-toggle input{width:16px;height:16px;cursor:pointer}
.sysmsg-why{color:var(--muted);font-size:12px;line-height:1.5}
.sysmsg-text{width:100%;min-height:64px;resize:vertical;padding:9px 11px;border-radius:10px;
  border:1px solid var(--line);background:var(--panel);color:var(--text);font:inherit;font-size:13px;line-height:1.5}
.sysmsg-chips{display:flex;flex-wrap:wrap;align-items:center;gap:5px}
.sysmsg-chips small{color:var(--muted);font-size:11px;margin-right:2px}
.sysmsg-chip{padding:3px 8px;border:1px solid var(--line);border-radius:999px;background:var(--panel);
  color:var(--muted);font-size:11.5px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;cursor:pointer;
  transition:transform .16s ease,color .2s ease}
.sysmsg-chip:hover{transform:translateY(-1px);color:var(--text)}
.sysmsg-actions{display:flex;align-items:center;gap:10px}
.sysmsg-actions .primary-button{padding:5px 14px;font-size:13px}
.sysmsg-status{color:var(--muted);font-size:11.5px;margin-left:auto}
.sysmsg-empty{padding:16px;text-align:center;color:var(--muted);font-size:13px}
@media (prefers-reduced-motion:reduce){.sysmsg-card,.sysmsg-chip{transition-duration:.01ms}}

/* Why a game card would not save, shown on the card itself. */
.sysmsg-status.gs-error{color:var(--danger,#e0245e);font-weight:600}

/* Per-game "keep the session alive" control. */
.gs-auto{display:grid;gap:6px}
.gs-auto-why{color:var(--muted);font-size:12px;line-height:1.45}
.gs-auto-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;cursor:pointer}
.gs-auto-line input[type=checkbox]{width:18px;height:18px;margin:0;flex:none}
.gs-auto-every{font-size:12.5px;color:var(--muted)}
.gs-auto-seconds{width:92px;padding:6px 8px}
.gs-auto-seconds:disabled{opacity:.5}

/* The connections screen: one Check button per game, beside its login button. */
.game-connect-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.game-connect-actions .ghost-button{padding:7px 13px;font-size:13px;font-weight:600;
  border:1px solid var(--line);border-radius:9px;background:transparent;color:var(--text);
  min-height:34px;cursor:pointer}
.game-connect-actions .ghost-button:hover:not(:disabled){background:var(--hover)}
.game-connect-actions .ghost-button:disabled{opacity:.55;cursor:default}

/* One click on a name in the chat header copies that name, a double click
   copies all of it. The only feedback is a brief pill, so nothing is added to
   the header that has to be read. */
.copyable-name{cursor:pointer;position:relative;user-select:none;-webkit-user-select:none}
/* `.header-copy span` styles the small grey meta line under the name. Splitting
   the name into word spans put it inside that selector, so the name has to take
   its size, weight and colour back from the <strong> it lives in. */
.copyable-name .name-part{font:inherit;color:inherit;letter-spacing:inherit;
  max-width:none;white-space:inherit;overflow:visible;text-overflow:clip;
  border-radius:6px;padding:0 2px;margin:0 -2px;
  transition:background .12s ease}
@media (hover:hover){.copyable-name .name-part:hover{background:rgba(128,128,140,.22)}}
.copyable-name .name-part:active{background:rgba(128,128,140,.3)}
.copied-pill{position:fixed;z-index:9999;transform:translate(-50%,-4px);
  padding:3px 10px;border-radius:999px;background:var(--primary,#0084ff);color:#fff;
  font-size:11.5px;font-weight:600;letter-spacing:.02em;white-space:nowrap;
  max-width:70vw;overflow:hidden;text-overflow:ellipsis;
  box-shadow:0 6px 16px -8px rgba(0,0,0,.6);
  opacity:0;pointer-events:none;transition:opacity .14s ease,transform .14s ease}
.copied-pill.show{opacity:1;transform:translate(-50%,0)}
@media (prefers-reduced-motion:reduce){.copied-pill{transition-duration:.01ms}}
/* The copy button shows it is working while the image is fetched and encoded. */
.image-copy-button.busy{opacity:.55;pointer-events:none}
.image-copy-button.busy svg{animation:fcSpinCopy .8s linear infinite}
@keyframes fcSpinCopy{to{transform:rotate(360deg)}}

/* Game agent logins and download links. */
.gs-card{gap:10px}
.gs-state{padding:2px 9px;border-radius:999px;font-size:11px;font-weight:600}
.gs-state.ok{background:color-mix(in srgb,#34c759 18%,transparent);color:#34c759}
.gs-state.warn{background:color-mix(in srgb,#ff9500 18%,transparent);color:#ff9500}
.gs-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px}
.gs-field{display:flex;flex-direction:column;gap:3px;min-width:0}
.gs-field small{color:var(--muted);font-size:11px}
.gs-field input{width:100%;padding:8px 10px;border-radius:9px;border:1px solid var(--line);
  background:var(--panel);color:var(--text);font-size:13px}

/* A balance costs a call to the game's panel, so staff ask for one at a time. */
.staff-game-balance.tap-to-load{font-size:12px;font-weight:600;color:var(--primary,#0084ff);
  padding:4px 9px;border-radius:999px;background:rgba(0,132,255,.10);cursor:pointer;white-space:nowrap}
.staff-game-balance.tap-to-load:hover{background:rgba(0,132,255,.18)}
/* The game rows sat in one dense block; this gives each its own line and air. */
.staff-game-row{align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--line)}
.staff-game-row:last-child{border-bottom:0}
.staff-game-move{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}

/* The customer's game rows: name + username on the left, the last known
   balance, its own refresh, then + / - / unlink as icons. Words took the space
   these rows needed for sixteen games. */
.staff-game-row{display:flex;align-items:center;gap:8px}
.staff-game-row .staff-game-label{flex:1;min-width:0}
.staff-game-row .staff-game-balance{font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap}
.staff-game-row .wallet-action{min-width:30px;padding:4px 8px;font-size:15px;line-height:1;font-weight:700}
.staff-game-row .gs-reread{font-size:14px;font-weight:400;opacity:.75}
.staff-game-row .gs-reread:hover:not(:disabled){opacity:1}
.staff-game-row .gs-reread:disabled{opacity:.4}
.staff-game-row .link-button{font-size:15px;padding:2px 6px;line-height:1}

/* The (i) beside a game balance, and what it says.

   Every game number on this screen is the stored one — the last answer that
   panel gave — and nothing about a two-day-old figure looks different from a
   live one. The marker is deliberately quiet: it is there for the moment
   somebody needs to know, not competing with the balance itself.

   It sits to the LEFT of the ↻ so the reading (how old) is next to the number
   it describes, and the action (read it now) stays where the hand already
   expects it. */
.staff-game-row .gs-age{
  background:none;border:0;margin:0;padding:0 1px;
  font-size:12px;line-height:1;color:var(--muted);opacity:.65;
  cursor:help;
  /* A 12px glyph is not a tap target. This keeps the ink small and the
     touchable area the size of a fingertip. */
  min-width:24px;min-height:24px;
  display:inline-flex;align-items:center;justify-content:center;
  /* Reclaims what that padding would otherwise add to a sixteen-game row. */
  margin-inline:-4px;
}
.staff-game-row .gs-age:hover,
.staff-game-row .gs-age:focus-visible{opacity:1;color:var(--primary)}

.gs-agetip{
  position:fixed;z-index:200;max-width:min(280px,calc(100vw - 16px));
  padding:8px 10px;border-radius:8px;
  background:#1c1c1e;color:#fff;
  font-size:12px;line-height:1.45;font-weight:400;
  box-shadow:0 6px 20px rgba(0,0,0,.28);
  /* Hidden with visibility rather than display, so it can still be measured
     before it is placed — otherwise it lands in the wrong spot on first show. */
  opacity:0;visibility:hidden;transition:opacity .12s ease;
  /* Never steals the pointer: hovering the tooltip must not count as leaving
     the button that opened it. */
  pointer-events:none;
}
.gs-agetip.is-on{opacity:1;visibility:visible}
@media(prefers-reduced-motion:reduce){.gs-agetip{transition:none}}

/* The owner's open/closed switch on each game card. */
.gs-power{display:inline-flex;align-items:center;gap:6px;margin-left:auto;margin-right:8px;
  font-size:12px;font-weight:700;color:var(--muted);cursor:pointer;user-select:none}
.gs-power input{width:34px;height:19px;margin:0;cursor:pointer}
.gs-state.off{background:rgba(224,36,94,.14);color:var(--danger,#e0245e)}

/* Freeplay in the staff panel. Brass, and never styled like the cash row above
   it: staff quote these numbers to customers, and the two must not blur. */
.staff-freeplay-row{align-items:baseline}
.staff-freeplay-row strong{color:#9A7B12}
.staff-freeplay-worth{margin-left:8px;font-size:12px;color:var(--muted,#6b7480)}
.wallet-action.freeplay{background:rgba(154,123,18,.14);color:#7a610e}
.wallet-action.freeplay-out{background:rgba(0,0,0,.05)}
@media (prefers-color-scheme:dark){
  .staff-freeplay-row strong{color:#D9B75A}
  .wallet-action.freeplay{background:rgba(217,183,90,.18);color:#E8CE8A}
  .wallet-action.freeplay-out{background:rgba(255,255,255,.07)}
}

/* ---- live game activity ------------------------------------------------
   A feed that is read while something is going wrong, so it is built for
   scanning: failures carry colour, timings carry colour, and the newest row
   arrives at the top rather than making somebody scroll for it. */
#gameFeedDialog>header{gap:10px}
.feed-toggle{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--muted);white-space:nowrap}
.feed-toggle input{width:auto}
.feed-live{font-size:12px;color:#22c55e;margin-left:auto}

.feed-health{display:flex;flex-wrap:wrap;gap:8px;padding:12px 14px;border-bottom:1px solid var(--line)}
.feed-chip{display:flex;flex-direction:column;gap:2px;padding:8px 11px;border-radius:10px;
  border:1px solid var(--line);background:var(--panel2);font-size:12px;min-width:150px}
.feed-chip strong{font-size:13px}
.feed-chip span{color:var(--muted)}
/* A panel that is failing is the reason this window exists. */
.feed-chip.is-bad{border-color:#ef4444;background:rgba(239,68,68,.08)}
.feed-chip.is-resting{opacity:.7}
.feed-chip em{color:#f59e0b;font-style:normal}
.feed-chip-speed.is-middling{color:#f59e0b}
.feed-chip-speed.is-slow{color:#ef4444}

.feed-list{overflow:auto;max-height:60dvh;padding:6px 0}
.feed-row{display:grid;grid-template-columns:74px 1fr auto 58px;gap:10px;align-items:baseline;
  padding:8px 14px;border-bottom:1px solid var(--line);font-size:13px}
.feed-row.is-fail{background:rgba(239,68,68,.07)}
/* Only the arrival is animated — a list that keeps moving is unreadable. */
.feed-row.is-new{animation:feedIn .35s ease}
@keyframes feedIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.feed-row.is-new{animation:none}}

.feed-when{color:var(--muted);font-size:12px;white-space:nowrap}
.feed-what{min-width:0}
.feed-who{border:0;background:transparent;padding:0;font:inherit;font-weight:600;
  color:var(--primary);cursor:pointer;text-align:left}
.feed-who:disabled{color:inherit;cursor:default}
.feed-who:hover:not(:disabled){text-decoration:underline}
.feed-said{color:inherit}
.feed-by{color:var(--muted);font-size:12px}
.feed-outcome{color:var(--muted);font-size:12px;text-align:right;max-width:34ch;
  overflow-wrap:anywhere}
.feed-row.is-fail .feed-outcome{color:#ef4444}
/* Tapping shows what the panel really said. */
.feed-outcome.has-detail{cursor:pointer;text-decoration:underline dotted}
.feed-took{text-align:right;font-variant-numeric:tabular-nums;color:var(--muted);font-size:12px}
.feed-took.is-middling{color:#f59e0b}
.feed-took.is-slow{color:#ef4444;font-weight:700}
.feed-empty{padding:26px 16px;text-align:center;color:var(--muted)}

@media(max-width:640px){
  .feed-row{grid-template-columns:1fr auto;row-gap:2px}
  .feed-when{grid-column:1}
  .feed-took{grid-column:2}
  .feed-what,.feed-outcome{grid-column:1/-1;text-align:left;max-width:none}
}

/* Day headings in the activity feed — seven days of rows need somewhere to
   break, or finding "that afternoon" means scrolling by feel. */
.feed-day{position:sticky;top:0;z-index:1;padding:7px 14px;
  background:var(--panel);border-bottom:1px solid var(--line);
  font-size:12px;font-weight:700;color:var(--muted);letter-spacing:.02em}
