/* oracle.css — extracted from oracle.html <style> block (v9.10.500).
   Served by command-center-server.mjs. Edit here, hard-refresh to apply. */
:root{
  --bg:#04070d;
  --bg-2:#070b14;
  --panel:rgba(13,19,32,0.72);
  --panel-2:rgba(9,14,24,0.85);
  --panel-solid:#0a0f1b;
  --rail:rgba(7,11,20,0.92);
  --border:rgba(255,255,255,0.07);
  --border-2:rgba(255,255,255,0.04);
  --accent:#22d9e6;
  --accent-2:#0ea5b8;
  --accent-glow:rgba(34,217,230,0.22);
  --text:#e9eef7;
  --muted:#6b7a90;
  --muted-2:#475263;
  --good:#4ade80;
  --bad:#f87171;
  --warn:#fbbf24;
  --star:#fbbf24;
  --mono:'JetBrains Mono',monospace;
  --ui:'Outfit',sans-serif;

  /* social feed color tokens */
  --c-indigo:#6366f1;
  --c-violet:#8b5cf6;
  --c-amber:#f59e0b;
  --c-rose:#fda4af;
  --c-card-bg:rgba(13,19,32,.78);
  --c-card-hover:rgba(15,22,36,.82);

  /* per-agent accents (MODEL_COLORS) */
  --c-kai:#4ade80;
  --c-leo:#ff4da6;
  --c-gemini:#22d3ee;
  --c-claudey:#a78bfa;
  --c-x:#e2e8f0;
  --c-groq:#f472b6;
  --c-analyst:#60a5fa;
  --c-researcher:#34d399;
  --c-coder:#fb923c;
  --c-oracle:#22d9e6;
  --c-ryan:#fbbf24;
  --c-system:#475569;
}

/* ══ Collectible Themes ═══════════════════════════════════════════════════════
   Each theme overrides CSS custom properties and adds unique visual effects.
   Applied via body.theme-<id>. The JS theme engine adds/removes the class. */

/* ── Shared theme surface overrides (applies to ALL collectible themes) ────── */
/* Panels, cards, containers */
[class*="theme-"] .guest-card,[class*="theme-"] .gmodal,[class*="theme-"] .set2-nav,
[class*="theme-"] .set2-body,[class*="theme-"] .gpost-composer,
[class*="theme-"] .gm-stab,[class*="theme-"] details{
  background:var(--panel)!important;border-color:var(--border)!important;color:var(--text)!important;
}
/* Quick menu */
[class*="theme-"] #quick-menu{
  background:linear-gradient(180deg,var(--panel-solid),var(--bg))!important;
  border-right-color:var(--border)!important;
}
[class*="theme-"] .qm-head{border-bottom-color:var(--border)!important}
[class*="theme-"] .qm-title{color:var(--text)!important}
[class*="theme-"] .qm-close{background:var(--panel)!important;color:var(--muted)!important}
[class*="theme-"] .qm-sec{color:var(--muted-2)!important}
[class*="theme-"] .qm-grp{background:var(--panel)!important;border-color:var(--border)!important}
[class*="theme-"] .qm-row{color:var(--text)!important}
[class*="theme-"] .qm-row:hover{background:var(--accent-glow)!important}
[class*="theme-"] .qm-row .qm-ico{color:var(--muted)!important}
[class*="theme-"] .qm-row:hover .qm-ico{color:var(--accent)!important}
[class*="theme-"] #quick-menu-backdrop{background:rgba(0,0,0,.55)!important}
/* Top bar / nav rail */
[class*="theme-"] #nav-rail,[class*="theme-"] .top-bar{
  background:var(--rail)!important;border-color:var(--border)!important;
}
/* Inputs */
[class*="theme-"] input,[class*="theme-"] textarea,[class*="theme-"] select{
  background:var(--bg-2)!important;border-color:var(--border)!important;color:var(--text)!important;
}
[class*="theme-"] input:focus,[class*="theme-"] textarea:focus{
  border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-glow)!important;
}
/* Links and scrollbars */
[class*="theme-"] a{color:var(--accent)!important}
[class*="theme-"] ::-webkit-scrollbar-thumb{background:var(--accent-glow)!important}
/* Buttons */
[class*="theme-"] button.gc-btn,[class*="theme-"] .gm-primary,[class*="theme-"] .gm-ghost{
  font-family:var(--ui),Outfit,sans-serif!important;
}
/* Text colors */
[class*="theme-"] .gc-h,[class*="theme-"] h3,[class*="theme-"] .gc-k{color:var(--text)!important}
[class*="theme-"] .gc-v,[class*="theme-"] .gc-msg{color:var(--muted)!important}
/* Settings nav tabs */
[class*="theme-"] .set2-nav button{color:var(--muted)!important}
[class*="theme-"] .set2-nav button:hover{background:var(--accent-glow)!important;color:var(--text)!important}
[class*="theme-"] .set2-nav button.on{background:var(--accent-glow)!important;color:var(--accent)!important}
/* Feed post containers */
[class*="theme-"] .gfeed-wrap,[class*="theme-"] .guest-col-right .guest-card{
  background:var(--panel)!important;border-color:var(--border)!important;
}
/* Sidebar widget text follows theme */
[class*="theme-"] .gsb-name,[class*="theme-"] .gsb-tag,[class*="theme-"] .gsb-sname{color:var(--text)!important}
[class*="theme-"] .gsb-handle,[class*="theme-"] .gsb-tagmeta,[class*="theme-"] .gsb-sl,[class*="theme-"] .gsb-swhy{color:var(--muted)!important}
[class*="theme-"] .gsb-sv{color:var(--accent)!important}
[class*="theme-"] .gsb-stat{background:rgba(255,255,255,.03)!important;border-color:var(--border)!important}
[class*="theme-"] .gsb-trending-item:hover,[class*="theme-"] .gsb-suggested-row:hover{background:var(--accent-glow)!important}
[class*="theme-"] .gcomposer-opt{background:rgba(255,255,255,.05)!important;border-color:var(--border)!important;color:var(--muted)!important}
[class*="theme-"] .gcomposer-opt:hover{background:rgba(255,255,255,.10)!important;color:var(--text)!important}
/* DM / messaging panels */
[class*="theme-"] .bv-wrap,[class*="theme-"] .bv-header,[class*="theme-"] .bv-compose{
  background:var(--panel)!important;border-color:var(--border)!important;
}
/* Messaging / DM area */
[class*="theme-"] .bot-view{background:var(--panel-solid)!important;border-left-color:var(--border)!important}
[class*="theme-"] .transcript{background:var(--bg)!important}
[class*="theme-"] .dm.me .dm-bub{background:linear-gradient(135deg,var(--accent),var(--accent-2))!important;color:#fff!important;box-shadow:0 2px 12px var(--accent-glow)!important}
[class*="theme-"] .dm.them .dm-bub{background:var(--panel)!important;border-color:var(--border)!important;color:var(--text)!important}
[class*="theme-"] .dm.sys .dm-bub{background:rgba(255,255,255,.02)!important;border-color:var(--border)!important;color:var(--muted)!important}
[class*="theme-"] .dm .dm-who{color:var(--muted)!important}
[class*="theme-"] .dm-status{color:var(--muted-2)!important}
.dm-copy-btn{background:none;border:none;cursor:pointer;font-size:12px;opacity:0;transition:opacity .15s;padding:2px 6px;margin-top:2px}
.dm.them:hover .dm-copy-btn{opacity:.5}
.dm-copy-btn:hover{opacity:1!important}
[class*="theme-"] .dm-status.seen{color:var(--accent)!important}
[class*="theme-"] .bv-compose textarea{background:var(--bg-2)!important;border-color:var(--border)!important;color:var(--text)!important}
[class*="theme-"] .bv-compose textarea:focus{border-color:var(--accent)!important;box-shadow:0 0 0 3px var(--accent-glow)!important}
/* Channel/topology chat bubbles */
[class*="theme-"] .turn .bubble{background:var(--panel)!important;border-color:var(--border)!important;color:var(--text)!important}
[class*="theme-"] .turn.right .bubble{background:linear-gradient(135deg,var(--accent),var(--accent-2))!important;color:#fff!important;border-color:transparent!important}
/* Channel tabs */
[class*="theme-"] .ch-tabs{background:var(--panel-2)!important;border-bottom-color:var(--border)!important}
[class*="theme-"] .ch-tab{color:var(--muted)!important}
[class*="theme-"] .ch-tab:hover{color:var(--text)!important;background:rgba(255,255,255,.04)!important}
[class*="theme-"] .ch-tab.active{color:var(--accent)!important;background:var(--accent-glow)!important;border-color:var(--accent)!important}
/* Metrics cards */
[class*="theme-"] .met-card{border-color:var(--border)!important;background:var(--panel)!important}
[class*="theme-"] .met-card .mc-v{color:var(--accent)!important}
/* Side-panel bot view */
[class*="theme-"] .bv-header,[class*="theme-"] .bv-top{background:var(--panel-2)!important;border-bottom-color:var(--border)!important}
[class*="theme-"] .bv-name{color:var(--text)!important}
[class*="theme-"] .bv-sub{color:var(--muted)!important}
/* Topology / nervous system view */
[class*="theme-"] #view-topology,[class*="theme-"] #view-nervous{background:var(--bg)!important}
/* Buttons in messaging */
[class*="theme-"] .btn{border-color:var(--border)!important;color:var(--text)!important}
[class*="theme-"] .btn:hover{background:var(--accent-glow)!important}
[class*="theme-"] .btn.primary,[class*="theme-"] .btn.kai{border-color:var(--accent)!important;color:var(--accent)!important}
/* Left rail */
[class*="theme-"] .rail{background:var(--rail)!important;border-right-color:var(--border)!important}
[class*="theme-"] .rail-btn{color:var(--muted)!important}
[class*="theme-"] .rail-btn:hover{color:var(--text)!important;background:var(--accent-glow)!important}
[class*="theme-"] .rail-btn.active{color:var(--accent)!important;background:var(--accent-glow)!important}
/* Column headers */
[class*="theme-"] .col-header{background:var(--panel-2)!important;border-bottom-color:var(--border)!important;color:var(--text)!important}
[class*="theme-"] #col-left{background:var(--panel-solid)!important;border-right-color:var(--border)!important}
[class*="theme-"] #col-right{background:var(--panel-solid)!important;border-left-color:var(--border)!important}
/* Agent list items */
[class*="theme-"] .agent-item{border-bottom-color:var(--border)!important}
[class*="theme-"] .agent-item:hover{background:var(--accent-glow)!important}
[class*="theme-"] .agent-item .ai-name{color:var(--text)!important}
[class*="theme-"] .agent-item .ai-sub{color:var(--muted)!important}
/* Spark charts */
[class*="theme-"] .spark{border-color:var(--border)!important;background:var(--panel)!important}
[class*="theme-"] .spark .bar{background:linear-gradient(180deg,var(--accent),var(--accent-2))!important}
/* Config pane */
[class*="theme-"] .config-pane{background:var(--bg)!important}
/* Mobile tab bar */
[class*="theme-"] .m-tabbar{background:var(--rail)!important;border-top-color:var(--border)!important}
[class*="theme-"] .m-tab{color:var(--muted)!important}
[class*="theme-"] .m-tab.active{color:var(--accent)!important}
/* Top bar */
[class*="theme-"] .top-bar{background:var(--panel-2)!important;border-bottom-color:var(--border)!important}
[class*="theme-"] .top-bar .tb-title{color:var(--text)!important}
/* Side dock chat tabs */
[class*="theme-"] .cdt-tab{background:var(--panel)!important;border-color:var(--border)!important}
[class*="theme-"] .cdt-tab:hover{border-color:var(--accent)!important}
/* Notification panel */
[class*="theme-"] #tb-notif-panel{background:var(--panel-solid)!important;border-color:var(--border)!important}
/* Profile cards */
[class*="theme-"] .side-card{background:var(--panel)!important;border-color:var(--border)!important}
/* Theme body background glow follows accent */
[class*="theme-"]{
  background-image:
    radial-gradient(900px 500px at 18% -8%, var(--accent-glow), transparent 60%),
    radial-gradient(1000px 600px at 100% 0%, var(--accent-glow), transparent 55%)!important;
}
[class*="theme-"]::before{
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px)!important;
}

/* Dragon's Breath — dark lava rock, fire effects, ember glow */
body.theme-dragons-breath{
  --bg:#0d0400;--bg-2:#1a0800;--panel:rgba(26,8,0,.8);--panel-2:rgba(20,5,0,.9);--panel-solid:#140500;
  --rail:rgba(18,5,0,.92);
  --border:rgba(239,68,68,.15);--border-2:rgba(239,68,68,.08);
  --accent:#ef4444;--accent-2:#dc2626;--accent-glow:rgba(239,68,68,.18);
  --text:#fde8e0;--muted:#a0756b;--muted-2:#6b4940;
  --ui:'Cinzel',Outfit,serif;
}
body.theme-dragons-breath .guest-card,body.theme-dragons-breath .gmodal,body.theme-dragons-breath .qm-grp{
  border-radius:6px!important;
  box-shadow:inset 0 1px 0 rgba(239,68,68,.12),inset 0 -1px 0 rgba(245,158,11,.06),0 4px 20px rgba(0,0,0,.5)!important;
  border:1px solid rgba(239,68,68,.18)!important;
  background:linear-gradient(175deg,rgba(26,8,0,.85),rgba(13,4,0,.95))!important;
  border-top:2px solid rgba(239,68,68,.2)!important;
}
body.theme-dragons-breath button.gc-btn,body.theme-dragons-breath .gm-primary{
  background:linear-gradient(135deg,#b91c1c,#dc2626)!important;text-shadow:0 1px 4px rgba(0,0,0,.4);border-radius:6px!important;
}
body.theme-dragons-breath .gm-ghost{border-color:rgba(239,68,68,.3)!important;color:#fca5a5!important}
/* Dragon's Breath messaging */
body.theme-dragons-breath .dm.me .dm-bub{border-radius:14px 14px 4px 14px!important;box-shadow:0 2px 14px rgba(239,68,68,.2),inset 0 1px 0 rgba(255,255,255,.06)!important}
body.theme-dragons-breath .dm.them .dm-bub{border-radius:14px 14px 14px 4px!important;background:rgba(26,8,0,.7)!important;border:1px solid rgba(239,68,68,.12)!important}
body.theme-dragons-breath .transcript{background:linear-gradient(180deg,#0d0400,#0a0300)!important}
body.theme-dragons-breath .bv-compose{background:rgba(20,5,0,.8)!important;border-top:1px solid rgba(239,68,68,.12)!important}
/* Custom arrow cursor for Dragon's Breath */
body.theme-dragons-breath,body.theme-dragons-breath *{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M4 2L4 20L9 15L14 22L17 20L12 13L19 13Z' fill='%23ef4444' stroke='%23000' stroke-width='1'/%3E%3C/svg%3E") 4 2,auto;
}
body.theme-dragons-breath a,body.theme-dragons-breath button,body.theme-dragons-breath [onclick],body.theme-dragons-breath select,body.theme-dragons-breath label[style*="cursor"]{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M11 1C10 1 9 2 9 3L9 11.5L7 9.5C6 8.5 4.5 8.5 3.5 9.5C2.5 10.5 2.8 12 3.5 12.8L9 19C10 20.2 11.5 21 13.2 21L16 21C18.5 21 20.5 19 20.5 16.5L20.5 11C20.5 10 19.5 9 18.5 9C18 9 17.5 9.3 17.5 9.5L17.5 9C17.5 8 16.5 7 15.5 7C15 7 14.5 7.3 14.3 7.6C14 6.8 13.2 6 12.2 6C11.8 6 11.5 6.2 11.2 6.4L11 3C11 2 10 1 11 1Z' fill='%23f59e0b' stroke='%23000' stroke-width='1'/%3E%3C/svg%3E") 10 1,pointer!important;
}

/* Arctic Frost — ice blue glow, crystalline borders */
body.theme-arctic-frost{
  --bg:#030810;--bg-2:#050d1a;--panel:rgba(5,13,26,.85);--panel-2:rgba(3,8,16,.92);--panel-solid:#040a14;
  --rail:rgba(4,10,20,.92);
  --border:rgba(56,189,241,.12);--border-2:rgba(56,189,241,.06);
  --accent:#38bdf8;--accent-2:#0ea5e9;--accent-glow:rgba(56,189,241,.15);
  --text:#e0f2fe;--muted:#7ba5c4;--muted-2:#4a7a9c;
}
/* Arctic Frost messaging */
body.theme-arctic-frost .dm.me .dm-bub{border-radius:20px 20px 4px 20px!important;box-shadow:0 2px 16px rgba(56,189,241,.15)!important}
body.theme-arctic-frost .dm.them .dm-bub{border-radius:20px 20px 20px 4px!important;background:rgba(5,13,26,.8)!important;border:1px solid rgba(56,189,241,.1)!important;backdrop-filter:blur(6px)!important}
body.theme-arctic-frost .transcript{background:linear-gradient(180deg,#030810,#040a14)!important}
body.theme-arctic-frost .bv-compose{background:rgba(4,10,20,.85)!important;border-top:1px solid rgba(56,189,241,.1)!important}
body.theme-arctic-frost .guest-card,body.theme-arctic-frost .gmodal,body.theme-arctic-frost .qm-grp{
  border-radius:16px!important;
  box-shadow:0 0 24px rgba(56,189,241,.06),inset 0 1px 0 rgba(255,255,255,.08),0 4px 16px rgba(0,0,0,.3)!important;
  border:1px solid rgba(56,189,241,.15)!important;backdrop-filter:blur(12px)!important;
  background:linear-gradient(175deg,rgba(10,20,40,.75),rgba(5,13,26,.9))!important;
}
body.theme-arctic-frost button.gc-btn,body.theme-arctic-frost .gm-primary{
  background:linear-gradient(135deg,#0284c7,#0ea5e9)!important;border-radius:14px!important;
}
body.theme-arctic-frost .gm-ghost{border-color:rgba(56,189,241,.25)!important;color:#7dd3fc!important}
body.theme-arctic-frost,body.theme-arctic-frost *{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M4 2L4 20L9 15L14 22L17 20L12 13L19 13Z' fill='%2338bdf8' stroke='%23082040' stroke-width='1'/%3E%3C/svg%3E") 4 2,auto;
}
body.theme-arctic-frost a,body.theme-arctic-frost button,body.theme-arctic-frost [onclick],body.theme-arctic-frost select{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M11 1C10 1 9 2 9 3L9 11.5L7 9.5C6 8.5 4.5 8.5 3.5 9.5C2.5 10.5 2.8 12 3.5 12.8L9 19C10 20.2 11.5 21 13.2 21L16 21C18.5 21 20.5 19 20.5 16.5L20.5 11C20.5 10 19.5 9 18.5 9C18 9 17.5 9.3 17.5 9.5L17.5 9C17.5 8 16.5 7 15.5 7C15 7 14.5 7.3 14.3 7.6C14 6.8 13.2 6 12.2 6C11.8 6 11.5 6.2 11.2 6.4L11 3C11 2 10 1 11 1Z' fill='%230ea5e9' stroke='%23082040' stroke-width='1'/%3E%3C/svg%3E") 10 1,pointer!important;
}

/* Neon Pulse — electric purple, cyberpunk */
body.theme-neon-pulse{
  --bg:#05001a;--bg-2:#0a0025;--panel:rgba(10,0,37,.85);--panel-2:rgba(5,0,20,.92);--panel-solid:#08001a;
  --rail:rgba(8,0,26,.92);
  --border:rgba(168,85,247,.18);--border-2:rgba(168,85,247,.08);
  --accent:#a855f7;--accent-2:#9333ea;--accent-glow:rgba(168,85,247,.2);
  --text:#f3e8ff;--muted:#9b7fc4;--muted-2:#6b4fa0;
  --ui:'Orbitron',Outfit,sans-serif;
}
/* Neon Pulse messaging */
body.theme-neon-pulse .dm.me .dm-bub{border-radius:4px 4px 4px 4px!important;box-shadow:0 0 14px rgba(168,85,247,.25),inset 0 0 1px rgba(168,85,247,.4)!important;text-transform:none!important}
body.theme-neon-pulse .dm.them .dm-bub{border-radius:4px!important;background:rgba(10,0,37,.8)!important;border:1px solid rgba(168,85,247,.15)!important;box-shadow:inset 0 0 1px rgba(168,85,247,.2)!important}
body.theme-neon-pulse .transcript{background:linear-gradient(180deg,#05001a,#08001a)!important}
body.theme-neon-pulse .bv-compose{background:rgba(8,0,26,.85)!important;border-top:1px solid rgba(168,85,247,.15)!important}
body.theme-neon-pulse .ch-tab.active{box-shadow:0 0 10px rgba(168,85,247,.2)!important}
body.theme-neon-pulse .guest-card,body.theme-neon-pulse .gmodal,body.theme-neon-pulse .qm-grp{
  border-radius:3px!important;
  box-shadow:0 0 20px rgba(168,85,247,.08),inset 0 0 1px rgba(168,85,247,.4),0 0 1px rgba(168,85,247,.5)!important;
  border:1px solid rgba(168,85,247,.25)!important;
  background:linear-gradient(175deg,rgba(15,0,45,.85),rgba(5,0,20,.95))!important;
  border-left:2px solid rgba(168,85,247,.35)!important;
}
body.theme-neon-pulse button.gc-btn,body.theme-neon-pulse .gm-primary{
  background:linear-gradient(135deg,#7c3aed,#a855f7)!important;box-shadow:0 0 14px rgba(168,85,247,.35)!important;
  border-radius:4px!important;text-transform:uppercase!important;letter-spacing:.5px!important;
}
body.theme-neon-pulse .gm-ghost{border-color:rgba(168,85,247,.35)!important;color:#c4b5fd!important;text-transform:uppercase!important}
body.theme-neon-pulse,body.theme-neon-pulse *{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M4 2L4 20L9 15L14 22L17 20L12 13L19 13Z' fill='%23a855f7' stroke='%23200040' stroke-width='1'/%3E%3C/svg%3E") 4 2,auto;
}
body.theme-neon-pulse a,body.theme-neon-pulse button,body.theme-neon-pulse [onclick],body.theme-neon-pulse select{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M11 1C10 1 9 2 9 3L9 11.5L7 9.5C6 8.5 4.5 8.5 3.5 9.5C2.5 10.5 2.8 12 3.5 12.8L9 19C10 20.2 11.5 21 13.2 21L16 21C18.5 21 20.5 19 20.5 16.5L20.5 11C20.5 10 19.5 9 18.5 9C18 9 17.5 9.3 17.5 9.5L17.5 9C17.5 8 16.5 7 15.5 7C15 7 14.5 7.3 14.3 7.6C14 6.8 13.2 6 12.2 6C11.8 6 11.5 6.2 11.2 6.4L11 3C11 2 10 1 11 1Z' fill='%23c084fc' stroke='%23200040' stroke-width='1'/%3E%3C/svg%3E") 10 1,pointer!important;
}

/* Solar Flare — warm gold, sun corona */
body.theme-solar-flare{
  --bg:#0d0800;--bg-2:#1a1000;--panel:rgba(26,16,0,.82);--panel-2:rgba(20,10,0,.9);--panel-solid:#140a00;
  --rail:rgba(20,10,0,.92);
  --border:rgba(245,158,11,.15);--border-2:rgba(245,158,11,.06);
  --accent:#f59e0b;--accent-2:#d97706;--accent-glow:rgba(245,158,11,.18);
  --text:#fef3c7;--muted:#b88a40;--muted-2:#7a5c2a;
}
/* Solar Flare messaging */
body.theme-solar-flare .dm.me .dm-bub{border-radius:16px 16px 4px 16px!important;box-shadow:0 2px 12px rgba(245,158,11,.15)!important}
body.theme-solar-flare .dm.them .dm-bub{border-radius:16px 16px 16px 4px!important;background:rgba(26,16,0,.75)!important;border:1px solid rgba(245,158,11,.1)!important}
body.theme-solar-flare .transcript{background:linear-gradient(180deg,#0d0800,#0a0600)!important}
body.theme-solar-flare .bv-compose{background:rgba(20,10,0,.8)!important;border-top:1px solid rgba(245,158,11,.1)!important}
body.theme-solar-flare .guest-card,body.theme-solar-flare .gmodal{
  border-radius:14px!important;box-shadow:0 0 16px rgba(245,158,11,.06),0 4px 16px rgba(0,0,0,.3)!important;
  border:1px solid rgba(245,158,11,.15)!important;
}
body.theme-solar-flare button.gc-btn,body.theme-solar-flare .gm-primary{
  background:linear-gradient(135deg,#b45309,#d97706)!important;border-radius:12px!important;
}
body.theme-solar-flare .gm-ghost{border-color:rgba(245,158,11,.25)!important;color:#fcd34d!important}
body.theme-solar-flare,body.theme-solar-flare *{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M4 2L4 20L9 15L14 22L17 20L12 13L19 13Z' fill='%23f59e0b' stroke='%23402000' stroke-width='1'/%3E%3C/svg%3E") 4 2,auto;
}
body.theme-solar-flare a,body.theme-solar-flare button,body.theme-solar-flare [onclick],body.theme-solar-flare select{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M11 1C10 1 9 2 9 3L9 11.5L7 9.5C6 8.5 4.5 8.5 3.5 9.5C2.5 10.5 2.8 12 3.5 12.8L9 19C10 20.2 11.5 21 13.2 21L16 21C18.5 21 20.5 19 20.5 16.5L20.5 11C20.5 10 19.5 9 18.5 9C18 9 17.5 9.3 17.5 9.5L17.5 9C17.5 8 16.5 7 15.5 7C15 7 14.5 7.3 14.3 7.6C14 6.8 13.2 6 12.2 6C11.8 6 11.5 6.2 11.2 6.4L11 3C11 2 10 1 11 1Z' fill='%23fbbf24' stroke='%23402000' stroke-width='1'/%3E%3C/svg%3E") 10 1,pointer!important;
}

/* Void Walker — pure black, monochrome, stark */
body.theme-void-walker{
  --bg:#000;--bg-2:#050505;--panel:rgba(5,5,5,.9);--panel-2:rgba(0,0,0,.95);--panel-solid:#030303;
  --rail:rgba(0,0,0,.95);
  --border:rgba(255,255,255,.06);--border-2:rgba(255,255,255,.03);
  --accent:#e2e8f0;--accent-2:#cbd5e1;--accent-glow:rgba(226,232,240,.08);
  --text:#f1f5f9;--muted:#64748b;--muted-2:#475569;
}
/* Void Walker messaging */
body.theme-void-walker .dm.me .dm-bub{border-radius:2px!important;background:rgba(255,255,255,.08)!important;box-shadow:none!important;border:1px solid rgba(255,255,255,.1)!important}
body.theme-void-walker .dm.them .dm-bub{border-radius:2px!important;background:rgba(5,5,5,.9)!important;border:1px solid rgba(255,255,255,.06)!important}
body.theme-void-walker .transcript{background:#000!important}
body.theme-void-walker .bv-compose{background:rgba(0,0,0,.95)!important;border-top:1px solid rgba(255,255,255,.06)!important}
body.theme-void-walker .guest-card,body.theme-void-walker .gmodal{
  border-radius:2px!important;border:1px solid rgba(255,255,255,.08)!important;box-shadow:none!important;
}
body.theme-void-walker button.gc-btn,body.theme-void-walker .gm-primary{
  background:rgba(255,255,255,.08)!important;border:1px solid rgba(255,255,255,.12)!important;color:#f1f5f9!important;border-radius:2px!important;
}
body.theme-void-walker .gm-ghost{border-color:rgba(255,255,255,.1)!important;color:#94a3b8!important}

/* Emerald Grove — forest green, organic, warm */
body.theme-emerald-grove{
  --bg:#001a0a;--bg-2:#002d12;--panel:rgba(0,26,10,.85);--panel-2:rgba(0,20,8,.92);--panel-solid:#001408;
  --rail:rgba(0,20,8,.92);
  --border:rgba(34,197,94,.12);--border-2:rgba(34,197,94,.06);
  --accent:#22c55e;--accent-2:#16a34a;--accent-glow:rgba(34,197,94,.15);
  --text:#dcfce7;--muted:#5da06b;--muted-2:#3d7a4c;
}
/* Emerald Grove messaging */
body.theme-emerald-grove .dm.me .dm-bub{border-radius:22px 22px 4px 22px!important;box-shadow:0 2px 12px rgba(34,197,94,.12)!important}
body.theme-emerald-grove .dm.them .dm-bub{border-radius:22px 22px 22px 4px!important;background:rgba(0,26,10,.75)!important;border:1px solid rgba(34,197,94,.1)!important}
body.theme-emerald-grove .transcript{background:linear-gradient(180deg,#001a0a,#001408)!important}
body.theme-emerald-grove .bv-compose{background:rgba(0,20,8,.85)!important;border-top:1px solid rgba(34,197,94,.1)!important}
body.theme-emerald-grove .guest-card,body.theme-emerald-grove .gmodal{
  border-radius:18px!important;box-shadow:0 0 16px rgba(34,197,94,.05),0 4px 16px rgba(0,0,0,.3)!important;
  border:1px solid rgba(34,197,94,.12)!important;
}
body.theme-emerald-grove button.gc-btn,body.theme-emerald-grove .gm-primary{
  background:linear-gradient(135deg,#15803d,#22c55e)!important;border-radius:20px!important;
}
body.theme-emerald-grove .gm-ghost{border-color:rgba(34,197,94,.25)!important;color:#86efac!important;border-radius:20px!important}
body.theme-emerald-grove,body.theme-emerald-grove *{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M4 2L4 20L9 15L14 22L17 20L12 13L19 13Z' fill='%2322c55e' stroke='%23003010' stroke-width='1'/%3E%3C/svg%3E") 4 2,auto;
}
body.theme-emerald-grove a,body.theme-emerald-grove button,body.theme-emerald-grove [onclick],body.theme-emerald-grove select{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M11 1C10 1 9 2 9 3L9 11.5L7 9.5C6 8.5 4.5 8.5 3.5 9.5C2.5 10.5 2.8 12 3.5 12.8L9 19C10 20.2 11.5 21 13.2 21L16 21C18.5 21 20.5 19 20.5 16.5L20.5 11C20.5 10 19.5 9 18.5 9C18 9 17.5 9.3 17.5 9.5L17.5 9C17.5 8 16.5 7 15.5 7C15 7 14.5 7.3 14.3 7.6C14 6.8 13.2 6 12.2 6C11.8 6 11.5 6.2 11.2 6.4L11 3C11 2 10 1 11 1Z' fill='%234ade80' stroke='%23003010' stroke-width='1'/%3E%3C/svg%3E") 10 1,pointer!important;
}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100vh;height:100dvh;overflow:hidden;overscroll-behavior:none}/* dvh: track the DYNAMIC mobile viewport so the bottom tab bar sits flush — kills the black gap below the nav when the browser toolbar retracts (v9.10.222). 100vh kept as fallback for browsers w/o dvh; on desktop dvh==vh so no change. overscroll-behavior:none prevents WebView pull-to-refresh from hijacking scroll-up in the feed (v9.10.338). */
body{
  background:var(--bg);color:var(--text);
  font-family:var(--ui),Inter,sans-serif;font-size:13px;
  display:flex;flex-direction:column;
  background-image:
    radial-gradient(900px 500px at 18% -8%, var(--accent-glow), transparent 60%),
    radial-gradient(1000px 600px at 100% 0%, rgba(124,58,237,0.06), transparent 55%);
}
/* subtle lattice grid overlay */
body::before{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:0;
  background-image:
    linear-gradient(rgba(255,255,255,0.015) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.015) 1px, transparent 1px);
  background-size:42px 42px;
  mask-image:radial-gradient(circle at 50% 30%, #000 0%, transparent 80%);
}
::-webkit-scrollbar{width:6px;height:6px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.09);border-radius:10px}
::-webkit-scrollbar-thumb:hover{background:rgba(34,217,230,0.35)}

.lbl{font-family:var(--ui);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:1.6px;color:var(--muted)}
.mono{font-family:var(--mono)}

/* ── TOP BAR ─────────────────────────────────────────── */
.topbar{
  position:relative;z-index:5;flex-shrink:0;height:54px;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 18px;background:var(--panel-2);
  border-bottom:1px solid var(--border);backdrop-filter:blur(20px);
}
.tb-left{display:flex;align-items:center;gap:16px;min-width:0}
.brand{display:flex;align-items:center;gap:11px}
.brand .logo{
  width:30px;height:30px;border-radius:8px;flex-shrink:0;
  background:linear-gradient(140deg,var(--accent),#0070a8);
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 0 18px var(--accent-glow);
}
.brand .logo svg{width:18px;height:18px}
.brand .titles{display:flex;flex-direction:column;line-height:1.15}
.brand .os{font-family:var(--ui);font-weight:800;font-size:14px;letter-spacing:1.5px;
  background:linear-gradient(100deg,#fff,#86d8e0);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.brand .sub{font-size:9px;letter-spacing:2px;text-transform:uppercase;color:var(--muted)}
.tb-divider{width:1px;height:26px;background:var(--border)}
.view-title{font-family:var(--ui);font-size:12px;font-weight:600;color:var(--text);letter-spacing:0.5px}
.view-title span{color:var(--muted);font-weight:400}

.tb-right{display:flex;align-items:center;gap:10px}
.tb-clock{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15}
.tb-clock .tbc-time{font-family:var(--mono);font-size:14px;font-weight:600;color:var(--accent);letter-spacing:0.5px;font-variant-numeric:tabular-nums}
.tb-clock .tbc-date{font-size:8.5px;letter-spacing:1px;text-transform:uppercase;color:var(--muted)}
.metric{
  display:flex;flex-direction:column;align-items:flex-end;line-height:1.2;
  padding:5px 14px;border-left:1px solid var(--border-2);min-width:78px;
}
.metric .mv{font-family:var(--mono);font-size:15px;font-weight:600;color:var(--accent)}
.metric .ml{font-size:8px;text-transform:uppercase;letter-spacing:1.5px;color:var(--muted);margin-top:1px}
.metric.warn .mv{color:var(--warn)}
.live{
  display:flex;align-items:center;gap:7px;padding:6px 13px;margin-left:6px;
  border:1px solid rgba(74,222,128,0.3);border-radius:20px;background:rgba(74,222,128,0.06);
}
.live .dot{width:8px;height:8px;border-radius:50%;background:var(--good);
  box-shadow:0 0 8px var(--good);animation:pulse 1.8s infinite}
.live.down{border-color:rgba(248,113,113,0.3);background:rgba(248,113,113,0.06)}
.live.down .dot{background:var(--bad);box-shadow:0 0 8px var(--bad);animation:none}
.live .txt{font-family:var(--ui);font-size:10px;font-weight:700;letter-spacing:1.5px;color:var(--good)}
.live.down .txt{color:var(--bad)}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:0.55;transform:scale(0.82)}}
@keyframes wave{0%{transform:scaleY(0.4);opacity:0.5}100%{transform:scaleY(1.2);opacity:1}}
@keyframes vitPulse{0%,100%{box-shadow:0 0 0 0 rgba(74,222,128,0.0)}50%{box-shadow:0 0 10px 0 rgba(74,222,128,0.35)}}

/* ── SHELL ───────────────────────────────────────────── */
.shell{position:relative;z-index:1;flex:1;display:flex;overflow:hidden}

/* 2026-07-17 v9.10.333: Web + Antigravity fill the center; no wasted black half */
body[data-view="radio"] #col-left,
body[data-view="webview"] #col-left,
body[data-view="antigravity"] #col-left{display:none !important;width:0 !important;min-width:0 !important}
/* v9.10.468 — primary full-width views: fill .col-center, never collapse to 0 height */
body[data-view="webview"] #view-webview,
body[data-view="antigravity"] #view-antigravity,
body[data-view="transcripts"] #view-transcripts,
body[data-view="learning"] #view-learning,
body[data-view="home"] #view-home,
body[data-view="radio"] #view-radio{
  flex:1 1 auto !important; min-height:0 !important; width:100% !important; max-width:none !important;
}
body[data-view="webview"] .col-center,
body[data-view="antigravity"] .col-center,
body[data-view="transcripts"] .col-center,
body[data-view="learning"] .col-center,
body[data-view="radio"] .col-center{
  display:flex !important; flex-direction:column !important; min-height:0 !important;
}
/* v9.10.472 — CHATS LIST PINNED TO THE RIGHT HALF (regression fix).
   FACT (verified in-browser via DOMParser on the served HTML, not by reading):
   `.col-center` closes early in the markup, so only #view-home / #view-profile /
   #view-topology / #view-nervous are its children. #view-transcripts, #view-learning,
   #view-webview, #view-radio, #view-portfolio and #view-antigravity are SIBLINGS of
   .col-center inside `.shell` — and `.shell` is `display:flex;flex-direction:row`.
   So whenever one of those views is active, the now-EMPTY .col-center is still a flex
   item with `flex:1` (:546) — on mobile `flex:1 1 auto!important;width:100%!important`
   (oracle-kv-mobile.css:524) — and it claims an equal track. Measured at 356px:
   .col-center 178px (empty black LEFT half) + #view-transcripts 178px at x=178, which
   squeezed .msgpane-list to 124px and wrapped every row. Exactly the owner's report.
   v9.10.459 REMOVED the old `body[data-view=...] .col-center{display:none}` rule on the
   stated belief that "views are children of col-center, not siblings" — that belief is
   wrong for these six panes, and v9.10.468 above then force-set display:flex on it.
   FIX: collapse the empty column's flex TRACK (not display, so nothing is removed from
   the tree and the Workspace blank-screen failure mode of v9.10.459 cannot recur).
   #view-antigravity is deliberately EXCLUDED — immersive Workspace already takes
   .col-center out of flow (fixed positioning, below) and that pane has a blank-screen
   history; owner to confirm before it is added. No @media gate, so no force-mobile
   mirror is needed and desktop is fixed by the same rule. Longhands only; adds no
   scroll-container and no positioning declarations. Reversible: delete this block. */
/* v9.10.515 — REMOVED the col-center collapse block from v9.10.472. Its premise was
   that #view-transcripts / #view-learning / #view-webview / #view-radio / #view-portfolio
   are SIBLINGS of .col-center. That is WRONG — all view panes are CHILDREN of .col-center
   (verified: col-center opens at line 344 and closes at line 1252, encompassing every
   view-pane). Collapsing .col-center to width:0 therefore hid the active view's content,
   causing blank Messages / Browser / Dreams / Radio screens. */
/* ── Workspace immersive computer (v9.10.459) ──
   Hide social chrome; OS fills the viewport. Exit only via Start → Log off.
   IMPORTANT: #view-antigravity lives INSIDE .col-center (not as a sibling).
   Never display:none .col-center while Workspace is active — that blanked the
   whole computer (boot/login/desktop) and made immersive look like a no-op. */
body.os-workspace-immersive .topbar,
body.os-workspace-immersive .rail,
body.os-workspace-immersive .m-tabbar,
body.os-workspace-immersive .m-appbar,
body.os-workspace-immersive #col-left,
body.os-workspace-immersive #col-right,
body.os-workspace-immersive .tab-strip,
body.os-workspace-immersive #gshort-fab,
body.os-workspace-immersive .cmd-bar,
body.os-workspace-immersive #cmd-bar{display:none !important}
body.os-workspace-immersive .shell{position:fixed !important;inset:0 !important;padding:0 !important;margin:0 !important;max-width:none !important;height:100% !important;z-index:40;display:flex !important}
body.os-workspace-immersive .col-center{position:fixed !important;inset:0 !important;padding:0 !important;margin:0 !important;height:100% !important;max-height:none !important;width:100% !important;max-width:none !important;z-index:41;display:flex !important;flex-direction:column !important;overflow:hidden !important}
body.os-workspace-immersive #view-antigravity{position:fixed !important;inset:0 !important;display:flex !important;z-index:42;width:100% !important;height:100% !important;max-height:none !important;background:#0a0f1a;flex:1 !important}
body.os-workspace-immersive #os-desktop{position:absolute !important;inset:0 !important;width:100% !important;height:100% !important;display:flex !important;flex-direction:column !important}
/* Taskbar always usable in immersive (Log off / Start) — even on mobile */
body.os-workspace-immersive #os-taskbar{display:flex !important;z-index:40 !important;pointer-events:auto !important}
body.os-workspace-immersive #os-startmenu{z-index:45 !important}
body.os-workspace-immersive #os-logoff-tray{display:flex !important}
/* v9.10.459 — REMOVED the old "hide .col-center for sibling views" rule.
   Those panes are children of .col-center in the real DOM; hiding the parent
   made Web / Workspace / Dreams / Messages / Config paint a blank center. */
/* 2026-07-18: collapsible Web Oracle Reader panel (wider browser) */
#view-webview.reader-collapsed #wv-ask{display:none !important}
#view-webview.reader-collapsed #wv-reader-btn{background:rgba(99,102,241,0.28) !important;color:#fff !important}
#view-webview{width:100% !important;max-width:none !important}
#view-webview > div:last-child{width:100% !important}
/* v9.10.450 — ENTITLEMENT-DRIVEN, not plan-name-driven. `ag-ok` is set from
   me.antigravityWorkspace (computed server-side by canAccessFeature), so Antigravity
   stays visible even when me.plan and me.planCard.id disagree — which was making a
   paid Team account fall through to the guest hide rule and disappear after sign-in.
   Listed FIRST so the plan-name rules below remain a harmless fallback. */
body.scope-guest.ag-ok .rail .rail-btn[data-view="antigravity"],
body.scope-guest.ag-ok .m-tabbar .m-tab[data-view="antigravity"]{display:flex !important}
/* Builder+ guests: show Antigravity (default guest CSS hides it) */
body.scope-guest.plan-builder .rail .rail-btn[data-view="antigravity"],
body.scope-guest.plan-team .rail .rail-btn[data-view="antigravity"],
body.scope-guest.plan-enterprise .rail .rail-btn[data-view="antigravity"],
body.scope-guest.plan-builder .m-tabbar .m-tab[data-view="antigravity"],
body.scope-guest.plan-team .m-tabbar .m-tab[data-view="antigravity"],
body.scope-guest.plan-enterprise .m-tabbar .m-tab[data-view="antigravity"]{display:flex !important}

/* ── ORACLE OS DESKTOP (v9.10.465 boot) ───────────────────── */
/* Boot MUST paint above everything (fixed + huge z). Absolute-inside-desktop
   was invisible when the pane hadn't laid out yet → looked "already loaded". */
#os-boot-overlay{position:fixed !important;inset:0 !important;z-index:200000 !important;display:none;flex-direction:column;background:#000;color:#00ff41;font:13px 'JetBrains Mono',monospace;overflow:hidden;pointer-events:auto}
#os-boot-overlay.os-boot-active{display:flex !important;visibility:visible !important;opacity:1 !important}
#os-boot-bios{padding:16px 20px;flex:1;overflow:hidden;position:relative}
#os-boot-bios .bios-line{opacity:0;animation:biosIn .12s forwards;white-space:pre-wrap}
#os-boot-bios .bios-ok{color:#34d399}
#os-boot-bios .bios-warn{color:#fbbf24}
#os-boot-bios .bios-hdr{color:#67e8f9;font-weight:700}
#os-boot-bios .bios-dim{color:#166534}
@keyframes biosIn{to{opacity:1}}
#os-boot-bios .bios-mark{position:absolute;right:18px;top:14px;width:56px;height:56px;opacity:.35;pointer-events:none}
#os-boot-bios .bios-mark img{width:100%;height:100%;object-fit:contain;filter:drop-shadow(0 0 8px rgba(0,255,65,.35))}
#os-boot-splash{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(ellipse at 50% 35%,#141e35 0%,#0a0f1a 50%,#040710 100%);color:#e2e8f0}
#os-boot-splash::before{content:'';position:absolute;inset:0;background:radial-gradient(600px at 50% 45%,rgba(99,102,241,.08),transparent 60%);pointer-events:none;animation:bootGlow 3s ease-in-out infinite alternate}
@keyframes bootGlow{from{opacity:.5}to{opacity:1}}
#os-boot-splash.active{display:flex}
#os-boot-splash .boot-mark{position:relative;width:110px;height:110px;margin-bottom:22px}
#os-boot-splash .boot-mark img{width:68px;height:68px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);animation:bootPulse 1.6s ease-in-out infinite;z-index:1;filter:drop-shadow(0 0 16px rgba(99,102,241,.4))}
#os-boot-splash .boot-mark-ring{position:absolute;inset:0;border:2px solid rgba(99,102,241,.15);border-top-color:#6366f1;border-right-color:rgba(139,92,246,.5);border-radius:50%;animation:bootSpin .9s linear infinite}
#os-boot-splash .boot-mark::after{content:'';position:absolute;inset:-4px;border:1px solid rgba(34,211,230,.08);border-top-color:rgba(34,211,230,.3);border-radius:50%;animation:bootSpin 2.2s linear infinite reverse}
#os-boot-splash .boot-title{font:800 26px Outfit,Inter,sans-serif;letter-spacing:.25em;color:#f1f5f9;text-shadow:0 0 30px rgba(99,102,241,.3)}
#os-boot-splash .boot-sub{font:12px Inter,sans-serif;color:#64748b;margin-top:6px;letter-spacing:.12em;text-transform:uppercase}
#os-boot-splash .boot-progress-wrap{width:min(320px,75vw);height:3px;border-radius:3px;background:rgba(148,163,184,.1);margin-top:32px;overflow:hidden;position:relative}
#os-boot-splash .boot-progress-wrap::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,.08),transparent);animation:bootShimmer 2s infinite}
@keyframes bootShimmer{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
#os-boot-splash .boot-progress-bar{height:100%;width:0%;background:linear-gradient(90deg,#22d3ee,#6366f1,#8b5cf6,#a855f7);border-radius:3px;transition:width .4s cubic-bezier(.4,0,.2,1);box-shadow:0 0 12px rgba(99,102,241,.4)}
#os-boot-splash .boot-status{font:11px JetBrains Mono,monospace;color:#94a3b8;margin-top:14px;min-height:16px;letter-spacing:.03em}
#os-boot-splash .boot-checks{margin-top:18px;width:min(320px,80vw);font:10.5px JetBrains Mono,monospace;color:#64748b;line-height:1.6}
#os-boot-splash .boot-checks .ck-ok{color:#34d399}
#os-boot-splash .boot-checks .ck-wait{color:#64748b}
#os-boot-splash .boot-checks .ck-fail{color:#fbbf24}
@keyframes bootPulse{0%,100%{transform:translate(-50%,-50%) scale(1);opacity:.95}50%{transform:translate(-50%,-50%) scale(1.06);opacity:1}}
@keyframes bootSpin{to{transform:rotate(360deg)}}
/* Login screen */
#os-login-screen{position:fixed !important;inset:0 !important;z-index:200001 !important;display:none;flex-direction:column;align-items:center;justify-content:center;background:linear-gradient(160deg,#060a14 0%,#0c1424 30%,#151030 60%,#0a0e1c 100%);background-size:cover;background-position:center}
#os-login-screen::before{content:'';position:absolute;inset:0;background:radial-gradient(800px at 50% 40%,rgba(99,102,241,.1),transparent 55%),radial-gradient(600px at 75% 25%,rgba(34,211,230,.06),transparent 45%),radial-gradient(500px at 25% 75%,rgba(139,92,246,.07),transparent 45%);pointer-events:none;animation:loginGlow 6s ease-in-out infinite alternate}
@keyframes loginGlow{from{opacity:.7}to{opacity:1}}
#os-login-screen::after{content:'';position:absolute;inset:0;background:linear-gradient(rgba(255,255,255,.008) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.008) 1px,transparent 1px);background-size:48px 48px;mask-image:radial-gradient(circle at 50% 40%,#000,transparent 70%);pointer-events:none;opacity:.5}
#os-login-screen.active{display:flex !important;visibility:visible !important;opacity:1 !important}
#os-login-screen .login-avatar{width:96px;height:96px;border-radius:50%;border:3px solid rgba(99,102,241,.35);object-fit:cover;margin-bottom:16px;background:#1e293b;box-shadow:0 0 40px rgba(99,102,241,.2),0 12px 40px rgba(0,0,0,.5)}
#os-login-screen .login-name{font:600 22px Outfit,Inter,sans-serif;color:#e2e8f0;margin-bottom:6px;letter-spacing:.02em}
#os-login-screen .login-time{font:200 64px Outfit,Inter,sans-serif;color:#f1f5f9;margin-bottom:2px;letter-spacing:-.02em;text-shadow:0 0 40px rgba(99,102,241,.15)}
#os-login-screen .login-date{font:400 15px Outfit,Inter,sans-serif;color:#7b8aa0;margin-bottom:36px;letter-spacing:.06em}
#os-login-screen .login-btn{padding:14px 44px;border-radius:14px;border:1px solid rgba(99,102,241,.4);background:rgba(99,102,241,.12);color:#c7d2fe;font:600 15px Outfit,Inter,sans-serif;cursor:pointer;transition:all .25s;backdrop-filter:blur(8px);letter-spacing:.04em}
#os-login-screen .login-btn:hover{background:rgba(99,102,241,.25);border-color:#6366f1;box-shadow:0 0 24px rgba(99,102,241,.3);transform:translateY(-1px)}
#os-login-screen .login-btn:active{transform:translateY(0);box-shadow:none}
#os-login-screen .login-tray{position:absolute;bottom:24px;right:24px;display:flex;align-items:center;gap:14px;color:#7b8aa0;font:11px Outfit,Inter,sans-serif}
#os-login-screen .login-bars{display:flex;align-items:flex-end;gap:2px;height:14px}
#os-login-screen .login-bars span{width:3px;background:#6366f1;border-radius:1px}
/* Services bars (tray) */
.os-svc-bars{display:inline-flex;align-items:flex-end;gap:1.5px;height:12px}
.os-svc-bars span{width:2.5px;background:#6366f1;border-radius:1px}
#os-tray-date{font:10px Inter,sans-serif;color:#94a3b8;line-height:1.1}
/* Update banner */
@keyframes osUpdateSlide{from{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}
/* Browser loading bar */
@keyframes osBrowserLoad{0%{left:-30%;width:30%}50%{left:30%;width:40%}100%{left:100%;width:30%}}
#os-browser-loadbar{position:absolute;top:0;left:0;right:0;height:2px;z-index:2;overflow:hidden;display:none}
#os-browser-loadbar.active{display:block}
#os-browser-loadbar::after{content:'';position:absolute;top:0;height:100%;background:linear-gradient(90deg,transparent,#6366f1,#8b5cf6,transparent);animation:osBrowserLoad 1.2s ease-in-out infinite}
/* File Manager */
.os-fm-loc:hover{background:rgba(99,102,241,.08)!important}
.os-fm-loc-active{background:rgba(99,102,241,.12)!important;color:#e2e8f0!important}
.os-fm-row{display:flex;align-items:center;padding:4px 12px;cursor:pointer;font:12px Inter,sans-serif;color:#cbd5e1;border-bottom:1px solid rgba(148,163,184,.04);user-select:none}
.os-fm-row:hover{background:rgba(99,102,241,.08)}
.os-fm-row.os-fm-selected{background:rgba(99,102,241,.18)}
.os-fm-row span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* FM context menu */
#os-fm-ctx{position:fixed;z-index:40;background:rgba(15,23,42,.97);border:1px solid rgba(148,163,184,.2);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.6);padding:4px;min-width:180px;font:12px Inter,sans-serif;display:none}
#os-fm-ctx.os-open{display:block}
#os-fm-ctx .os-ctx-item{padding:7px 12px;border-radius:4px;color:#e2e8f0;cursor:pointer;display:flex;align-items:center;gap:8px}
#os-fm-ctx .os-ctx-item:hover{background:rgba(99,102,241,.12)}
#os-fm-ctx .os-ctx-sep{height:1px;background:rgba(148,163,184,.12);margin:3px 8px}
#os-fm-ctx .os-ctx-sub{color:#64748b;font-size:10px;padding:4px 12px;text-transform:uppercase;letter-spacing:.3px}
/* Windows-style File Manager transfer / delete progress (v9.10.471) */
/* File Manager — Windows Explorer chrome */
.os-fm-tabs{display:flex;align-items:center;gap:2px;padding:4px 6px 0;background:rgba(9,14,24,.65);border-bottom:1px solid rgba(148,163,184,.12);min-height:34px;overflow-x:auto;flex-shrink:0}
.os-fm-tab{display:flex;align-items:center;gap:6px;padding:6px 10px;max-width:180px;border-radius:8px 8px 0 0;background:rgba(255,255,255,.03);color:#94a3b8;font:12px Inter,sans-serif;cursor:pointer;border:1px solid transparent;border-bottom:none}
.os-fm-tab:hover{background:rgba(99,102,241,.1);color:#e2e8f0}
.os-fm-tab-active{background:rgba(30,41,59,.9);color:#f1f5f9;border-color:rgba(148,163,184,.15)}
.os-fm-tab-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.os-fm-tab-x{border:none;background:transparent;color:#64748b;cursor:pointer;font-size:14px;line-height:1;padding:0 2px;border-radius:4px}
.os-fm-tab-x:hover{background:rgba(248,113,113,.2);color:#fca5a5}
.os-fm-tab-new{width:28px;height:28px;border:none;border-radius:6px;background:transparent;color:#94a3b8;cursor:pointer;font-size:16px;flex-shrink:0}
.os-fm-tab-new:hover{background:rgba(99,102,241,.15);color:#e2e8f0}
.os-fm-nav{display:flex;align-items:center;gap:4px;padding:6px 8px;border-bottom:1px solid rgba(148,163,184,.1);background:rgba(15,23,42,.45);flex-shrink:0}
.os-fm-navbtn{width:28px;height:28px;border-radius:6px;border:1px solid rgba(148,163,184,.12);background:transparent;color:#94a3b8;cursor:pointer;font-size:11px;display:flex;align-items:center;justify-content:center}
.os-fm-navbtn:hover:not(:disabled){background:rgba(99,102,241,.12);color:#e2e8f0}
.os-fm-navbtn:disabled{opacity:.35;cursor:default}
.os-fm-addr{flex:1;display:flex;align-items:center;gap:2px;height:28px;border-radius:6px;border:1px solid rgba(148,163,184,.15);background:rgba(255,255,255,.04);padding:0 10px;font:12px Inter,sans-serif;color:#e2e8f0;overflow:hidden;white-space:nowrap;min-width:0}
.os-fm-addr-drive{color:#64748b;cursor:pointer}
.os-fm-addr-drive:hover{color:#a5b4fc}
.os-fm-addr-sep{color:#475569;margin:0 4px}
.os-fm-search{width:160px;height:28px;border-radius:6px;border:1px solid rgba(148,163,184,.15);background:rgba(255,255,255,.04);color:#e2e8f0;padding:0 10px;font:12px Inter,sans-serif;outline:none;flex-shrink:0}
.os-fm-cmdbar{display:flex;align-items:center;gap:4px;padding:4px 8px;border-bottom:1px solid rgba(148,163,184,.1);background:rgba(15,23,42,.35);flex-shrink:0;position:relative;z-index:5}
.os-fm-cmd{padding:5px 10px;border-radius:6px;border:1px solid transparent;background:transparent;color:#cbd5e1;font:600 11.5px Inter,sans-serif;cursor:pointer}
.os-fm-cmd:hover{background:rgba(99,102,241,.12);border-color:rgba(148,163,184,.12)}
.os-fm-cmd-wrap{position:relative}
.os-fm-dd{display:none;position:absolute;top:100%;left:0;margin-top:2px;min-width:180px;background:rgba(15,23,42,.98);border:1px solid rgba(148,163,184,.2);border-radius:8px;box-shadow:0 10px 28px rgba(0,0,0,.55);padding:4px;z-index:50}
.os-fm-dd.os-open{display:block}
.os-fm-dd-right{left:auto;right:0}
.os-fm-sidebar{width:200px;display:flex;flex-direction:column;background:rgba(15,23,42,.3);border-right:1px solid rgba(148,163,184,.12);overflow-y:auto;padding:6px 0;flex-shrink:0}
.os-fm-sec{padding:8px 12px 3px;font:10px Inter,sans-serif;text-transform:uppercase;letter-spacing:.5px;color:#475569}
.os-fm-sidebar .os-fm-loc{padding:5px 12px;display:flex;align-items:center;gap:8px;cursor:pointer;font:12px Inter,sans-serif;color:#94a3b8;border-radius:4px;margin:0 4px}
.os-fm-sidebar .os-fm-loc:hover{background:rgba(99,102,241,.1);color:#e2e8f0}
.os-fm-sidebar .os-fm-loc-active{background:rgba(99,102,241,.18);color:#e2e8f0}
.os-fm-sidebar .os-fm-loc-muted{opacity:.75}
.os-fm-cols{display:flex;align-items:center;padding:0 12px;height:28px;border-bottom:1px solid rgba(148,163,184,.1);background:rgba(15,23,42,.3);font:11px Inter,sans-serif;color:#64748b;flex-shrink:0;user-select:none}
.os-fm-filelist{flex:1;overflow-y:auto;padding:0}
.os-fm-filelist .os-fm-row{display:flex;align-items:center;padding:4px 12px;cursor:default;font:12.5px Inter,sans-serif;color:#e2e8f0;border-bottom:1px solid rgba(148,163,184,.04)}
.os-fm-filelist .os-fm-row:hover{background:rgba(99,102,241,.08)}
.os-fm-filelist .os-fm-row.os-fm-selected{background:rgba(99,102,241,.18)}
.os-fm-filelist .os-fm-ico{font-size:14px;margin-right:8px;flex-shrink:0}
.os-fm-filelist .os-fm-name{flex:2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.os-fm-filelist .os-fm-meta{color:#64748b;font-size:11px}
.os-fm-filelist .os-fm-date{flex:1}
.os-fm-filelist .os-fm-type{width:100px}
.os-fm-filelist .os-fm-size{width:70px;text-align:right}
.os-fm-filelist .os-fm-lnk{color:#475569;font-size:10px;margin-left:6px}
.os-fm-view-icons{display:flex;flex-wrap:wrap;align-content:flex-start;gap:8px;padding:12px !important}
.os-fm-view-icons .os-fm-row{flex-direction:column;width:96px;height:100px;padding:10px 6px;border:1px solid transparent;border-radius:8px;text-align:center}
.os-fm-view-icons .os-fm-ico{font-size:32px;margin:0 0 6px}
.os-fm-view-icons .os-fm-name{flex:none;width:100%;font-size:11px;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.os-fm-view-icons .os-fm-meta{display:none}
.os-fm-status{height:22px;padding:0 12px;display:flex;align-items:center;border-top:1px solid rgba(148,163,184,.08);font:10px Inter,sans-serif;color:#64748b;background:rgba(15,23,42,.3)}
.os-fm-preview{width:240px;border-left:1px solid rgba(148,163,184,.12);overflow:auto;background:rgba(15,23,42,.2);display:flex;flex-direction:column;flex-shrink:0}
#os-fm-props{display:none;position:fixed;inset:0;z-index:200060;background:rgba(0,0,0,.45);align-items:center;justify-content:center;padding:16px}
#os-fm-props.os-open{display:flex}
#os-fm-props .fp-card{width:min(400px,94vw);background:linear-gradient(180deg,#1a2336 0%,#121a2c 100%);border:1px solid rgba(148,163,184,.22);border-radius:12px;box-shadow:0 20px 50px rgba(0,0,0,.55);overflow:hidden;font-family:Inter,Segoe UI,sans-serif}
#os-fm-props .fp-row{display:flex;gap:10px;padding:6px 0;font:12px Inter,sans-serif;border-bottom:1px solid rgba(148,163,184,.08)}
#os-fm-props .fp-k{width:90px;color:#64748b;flex-shrink:0}
#os-fm-props .fp-v{color:#e2e8f0;word-break:break-all}
#os-fm-progress{display:none;position:fixed;inset:0;z-index:200050;background:rgba(0,0,0,.45);align-items:center;justify-content:center;font-family:Inter,Segoe UI,sans-serif;padding:16px}
#os-fm-progress.os-open{display:flex}
#os-fm-progress .fp-card{width:min(420px,94vw);background:linear-gradient(180deg,#1a2336 0%,#121a2c 100%);border:1px solid rgba(148,163,184,.22);border-radius:12px;box-shadow:0 20px 50px rgba(0,0,0,.55);overflow:hidden}
#os-fm-progress .fp-titlebar{display:flex;align-items:center;gap:10px;padding:12px 14px;background:rgba(99,102,241,.12);border-bottom:1px solid rgba(148,163,184,.12)}
#os-fm-progress .fp-titlebar .fp-ico{font-size:18px}
#os-fm-progress .fp-title{font:600 13px Inter,sans-serif;color:#e2e8f0;flex:1}
#os-fm-progress .fp-close{border:none;background:transparent;color:#94a3b8;cursor:pointer;font-size:16px;padding:2px 8px;border-radius:6px}
#os-fm-progress .fp-close:hover{background:rgba(248,113,113,.15);color:#fca5a5}
#os-fm-progress .fp-body{padding:14px 16px 16px}
#os-fm-progress .fp-action{font:600 12px Inter,sans-serif;color:#a5b4fc;margin-bottom:6px;text-transform:uppercase;letter-spacing:.04em}
#os-fm-progress .fp-file{font:13px Inter,sans-serif;color:#f1f5f9;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:12px}
#os-fm-progress .fp-bar-wrap{height:10px;border-radius:6px;background:rgba(148,163,184,.15);overflow:hidden;margin-bottom:10px}
#os-fm-progress .fp-bar{height:100%;width:0%;border-radius:6px;background:linear-gradient(90deg,#22d3ee,#6366f1,#8b5cf6);transition:width .15s ease}
#os-fm-progress .fp-bar.fp-indeterminate{width:40% !important;animation:fpSlide 1.1s ease-in-out infinite}
@keyframes fpSlide{0%{transform:translateX(-100%)}100%{transform:translateX(280%)}}
#os-fm-progress .fp-stats{display:flex;flex-wrap:wrap;gap:8px 14px;font:11.5px JetBrains Mono,Consolas,monospace;color:#94a3b8}
#os-fm-progress .fp-stats b{color:#cbd5e1;font-weight:600}
#os-fm-progress .fp-foot{display:flex;justify-content:flex-end;gap:8px;margin-top:14px}
#os-fm-progress .fp-btn{padding:7px 14px;border-radius:8px;border:1px solid rgba(148,163,184,.25);background:rgba(15,23,42,.6);color:#e2e8f0;font:600 12px Inter,sans-serif;cursor:pointer}
#os-fm-progress .fp-btn:hover{background:rgba(99,102,241,.2)}
#os-fm-progress .fp-btn.primary{background:rgba(99,102,241,.35);border-color:rgba(99,102,241,.5)}
#os-fm-progress .fp-done{color:#34d399}
#os-fm-progress .fp-err{color:#f87171}
#os-desktop{position:relative;width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden;background:#0c1222}
#os-desktop-bg{position:absolute;inset:0;background:radial-gradient(800px at 50% 25%,rgba(34,211,230,.08),transparent 50%),radial-gradient(600px at 80% 70%,rgba(99,102,241,.1),transparent 45%),radial-gradient(400px at 20% 60%,rgba(139,92,246,.06),transparent 40%),linear-gradient(165deg,#080e1a 0%,#0b1120 40%,#0e1628 100%);z-index:0;background-size:cover;background-position:center}
#os-desktop-bg.os-has-wallpaper::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(8,12,22,.25) 0%,rgba(8,12,22,.45) 100%);pointer-events:none}
#os-taskbar{box-shadow:0 -4px 24px rgba(0,0,0,.35)}
#os-start-btn.os-start-active,#os-start-btn:active{background:rgba(99,102,241,.35)!important;box-shadow:0 0 0 1px rgba(99,102,241,.5)}
#os-startmenu{border:1px solid rgba(99,102,241,.18);box-shadow:0 20px 60px rgba(0,0,0,.6),0 0 0 1px rgba(255,255,255,.03) inset;border-radius:14px;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}
#os-startmenu .os-sm-section{font:700 10px Inter,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#64748b;padding:6px 10px 4px}
#os-login-screen .login-btn{box-shadow:0 6px 24px rgba(99,102,241,.2)}
#os-login-screen .login-avatar{box-shadow:0 0 48px rgba(99,102,241,.2),0 12px 40px rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;font:700 32px Outfit,Inter,sans-serif;color:#a5b4fc}
#os-desktop-icons{position:absolute;top:16px;left:16px;z-index:1;display:flex;flex-direction:column;flex-wrap:wrap;align-content:flex-start;gap:8px;max-height:calc(100% - 68px);width:calc(100% - 32px);pointer-events:none}
#os-desktop-icons>*{pointer-events:auto}
.os-icon{width:76px;padding:10px 4px;border-radius:10px;display:flex;flex-direction:column;align-items:center;gap:6px;cursor:pointer;user-select:none;transition:background .2s,transform .15s}
.os-icon:hover{background:rgba(99,102,241,.12);transform:scale(1.05)}
.os-icon:active{background:rgba(99,102,241,.22);transform:scale(.97)}
.os-icon img,.os-icon svg{width:40px;height:40px;filter:drop-shadow(0 3px 6px rgba(0,0,0,.5))}
.os-icon span{font:10px Outfit,Inter,sans-serif;color:#d1d9e6;text-align:center;text-shadow:0 1px 4px rgba(0,0,0,.8);line-height:1.25;max-width:72px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Windows */
#os-windows{position:absolute;inset:0 0 44px 0;z-index:2;pointer-events:none}
.os-win{position:absolute;pointer-events:auto;display:flex;flex-direction:column;background:rgba(13,19,32,.97);border:1px solid rgba(148,163,184,.12);border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.5),0 0 1px rgba(255,255,255,.05) inset;overflow:hidden;min-width:320px;min-height:200px;transition:box-shadow .2s,border-color .2s;animation:osWinOpen .28s cubic-bezier(.2,.9,.3,1) forwards;backdrop-filter:blur(2px)}
@keyframes osWinOpen{from{opacity:0;transform:scale(.88) translateY(12px)}to{opacity:1;transform:scale(1) translateY(0)}}
@keyframes osWinClose{from{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.85) translateY(16px)}}
.os-win.os-closing{animation:osWinClose .2s cubic-bezier(.4,0,1,1) forwards;pointer-events:none}
.os-win.os-focused{box-shadow:0 16px 56px rgba(99,102,241,.2),0 0 0 1px rgba(99,102,241,.25) inset;border-color:rgba(99,102,241,.3);z-index:100}
.os-win.os-maximized{border-radius:0;inset:0!important;width:100%!important;height:100%!important}
.os-win-title{height:36px;display:flex;align-items:center;padding:0 12px;background:rgba(12,18,30,.9);border-bottom:1px solid rgba(148,163,184,.08);cursor:grab;user-select:none;flex-shrink:0}
.os-win-title .os-win-icon{width:16px;height:16px;margin-right:8px;opacity:.7}
.os-win-title .os-win-name{flex:1;font:12px/1 Inter,sans-serif;font-weight:600;color:#e2e8f0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.os-win-btns{display:flex;gap:6px;align-items:center}
.os-win-btns button{width:14px;height:14px;border-radius:50%;border:none;cursor:pointer;transition:opacity .15s;opacity:.8}
.os-win-btns button:hover{opacity:1}
.os-win-btn-min{background:#f59e0b}
.os-win-btn-max{background:#22c55e}
.os-win-btn-close{background:#ef4444}
.os-win-body{flex:1;overflow:auto;position:relative;min-height:0}
.os-mob-back{display:none}
.os-win.os-hidden{display:none!important}
.os-win.os-restoring{animation:osWinOpen .2s cubic-bezier(.2,.9,.3,1) forwards}
/* Taskbar */
#os-taskbar{position:absolute;bottom:0;left:0;right:0;height:48px;z-index:10;display:flex;align-items:center;padding:0 10px;gap:4px;background:rgba(8,12,22,.88);border-top:1px solid rgba(148,163,184,.08);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);box-shadow:0 -2px 20px rgba(0,0,0,.3)}
#os-start-btn{width:34px;height:34px;border-radius:8px;border:none;background:rgba(99,102,241,.12);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s}
#os-start-btn:hover{background:rgba(99,102,241,.25)}
#os-start-btn img{width:22px;height:22px}
#os-search{flex:0 0 180px;height:30px;border-radius:6px;border:1px solid rgba(148,163,184,.15);background:rgba(255,255,255,.04);color:#e2e8f0;padding:0 10px;font:12px Inter,sans-serif;outline:none;transition:border-color .15s}
#os-search:focus{border-color:rgba(99,102,241,.5)}
#os-pinned{display:flex;gap:2px;margin-left:8px}
.os-pin{width:34px;height:34px;border-radius:6px;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;position:relative;transition:background .15s}
.os-pin:hover{background:rgba(148,163,184,.12)}
.os-pin.os-pin-active{background:rgba(99,102,241,.15)}
.os-pin.os-pin-active::after{content:'';position:absolute;bottom:2px;left:50%;transform:translateX(-50%);width:16px;height:2px;background:#6366f1;border-radius:1px}
.os-pin img,.os-pin svg{width:18px;height:18px}
#os-tray{margin-left:auto;display:flex;align-items:center;gap:10px;color:#94a3b8;font:11px Inter,sans-serif}
#os-clock{color:#cbd5e1;font-weight:500}
/* Start Menu */
#os-startmenu{position:absolute;bottom:48px;left:8px;width:560px;max-height:480px;z-index:20;background:rgba(15,23,42,.97);border:1px solid rgba(148,163,184,.2);border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.6);padding:0;display:none;flex-direction:row;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);overflow:hidden}
#os-sm-left{flex:1;display:flex;flex-direction:column;padding:12px;gap:6px;overflow-y:auto}
#os-sm-right{width:200px;background:rgba(0,0,0,.15);border-left:1px solid rgba(148,163,184,.1);padding:12px;display:flex;flex-direction:column;gap:6px;overflow-y:auto}
#os-sm-right .os-sm-section{margin:0}
#os-sm-search-bottom{width:100%;height:32px;border-radius:6px;border:1px solid rgba(148,163,184,.15);background:rgba(255,255,255,.04);color:#e2e8f0;padding:0 10px;font:12px Inter,sans-serif;outline:none;margin-top:auto;flex-shrink:0}
#os-startmenu.os-open{display:flex}
/* removed: startmenu search top (now at bottom in #os-sm-left) */
.os-sm-section{font:10px Inter,sans-serif;text-transform:uppercase;letter-spacing:.5px;color:#64748b;padding:4px 8px}
.os-sm-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:6px;cursor:pointer;transition:background .12s;color:#e2e8f0;font:13px Inter,sans-serif}
.os-sm-item:hover{background:rgba(99,102,241,.12)}
.os-sm-item img,.os-sm-item svg{width:20px;height:20px;opacity:.8}
/* Context menu */
.os-ctx{position:fixed;z-index:30;background:rgba(15,23,42,.97);border:1px solid rgba(148,163,184,.2);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.5);padding:4px;min-width:160px;font:12px Inter,sans-serif;display:none}
.os-ctx.os-open{display:block}
.os-ctx-item{padding:7px 12px;border-radius:4px;color:#e2e8f0;cursor:pointer;display:flex;align-items:center;gap:8px}
.os-ctx-item:hover{background:rgba(99,102,241,.12)}
.os-ctx-sep{height:1px;background:rgba(148,163,184,.12);margin:3px 8px}

/* ══ v9.10.547 — AI Workspace (IDE) responsive: driven by the WINDOW's width, not the viewport.
   JS toggles #os-ide-root.ide-narrow via a ResizeObserver, so a small window on desktop gets the
   same drawer layout as a phone. All positioning is relative to #os-ide-root (position:relative),
   so it works inside a floating window — not just full-screen. ══════════════════════════════ */
#os-ide-root.ide-narrow{overflow:hidden}
/* Activity bar → bottom tab bar. !important beats the element's inline width/flex-direction. */
#os-ide-root.ide-narrow #os-ide-actbar{position:absolute !important;left:0 !important;right:0 !important;bottom:0 !important;top:auto !important;width:auto !important;min-width:0 !important;height:52px !important;flex-direction:row !important;align-items:center !important;justify-content:space-around !important;gap:2px !important;padding:0 6px !important;border-right:none !important;border-top:1px solid rgba(148,163,184,.14) !important;background:rgba(9,14,24,.97) !important;z-index:41}
#os-ide-root.ide-narrow #os-ide-actbar>div{display:none !important}
#os-ide-root.ide-narrow #os-ide-actbar>button{width:48px !important;height:40px !important;font-size:19px !important;flex:0 0 auto}
/* Center pane fills the window, above the bottom bar */
#os-ide-root.ide-narrow #os-ide-center{flex:1 1 auto;min-width:0;margin-bottom:52px}
/* Explorer → left drawer. Opaque background so the pane behind never shows through. */
#os-ide-root.ide-narrow #os-ide-sidebar{position:absolute !important;left:0 !important;top:0 !important;bottom:52px !important;width:min(300px,84%) !important;min-width:0 !important;max-width:none !important;transform:translateX(-102%);transition:transform .22s ease;z-index:39;background:#0b1120 !important;border-right:1px solid rgba(148,163,184,.16) !important;box-shadow:8px 0 28px rgba(0,0,0,.55)}
#os-ide-root.ide-narrow #os-ide-sidebar.mob-open{transform:translateX(0)}
/* Composer chat → full overlay that slides up (beats inline position:relative + transparent bg) */
#os-ide-root.ide-narrow #os-ide-chat{position:absolute !important;left:0 !important;right:0 !important;top:0 !important;bottom:52px !important;width:auto !important;min-width:0 !important;max-width:none !important;transform:translateY(103%);transition:transform .22s ease;z-index:40;background:#0b1120 !important;border-left:none !important;box-shadow:0 -8px 28px rgba(0,0,0,.6)}
#os-ide-root.ide-narrow #os-ide-chat.mob-open{transform:translateY(0)}
/* No drag handles when stacked */
#os-ide-root.ide-narrow .os-ide-split-v,#os-ide-root.ide-narrow .os-ide-split-h{display:none !important}
/* Roomier touch targets for the composer controls when narrow */
#os-ide-root.ide-narrow #ag-input{font-size:14px;min-height:44px}
#os-ide-root.ide-narrow #ag-send{padding:9px 16px}

@media(max-width:900px){
  /* ══ PHONE MODE — Oracle OS looks like a smartphone OS ══════════════════════ */

  /* v9.10.468 — primary panes fill the mobile shell (no clipped 0-height center) */
  .view-pane{flex:1 1 auto !important;min-height:0 !important;width:100% !important;max-width:100% !important}
  #view-transcripts,#view-webview,#view-home,#view-learning,#view-radio,#view-antigravity{
    max-height:none !important; overflow:hidden !important;
  }
  #view-transcripts .ch-pane, #view-webview > div:last-child{
    min-height:0 !important; flex:1 1 auto !important;
  }

  /* The OS desktop must fit exactly inside the view pane — never overflow behind the platform tabbar */
  #view-antigravity{overflow:hidden !important}
  #os-desktop{height:100% !important;max-height:100% !important;overflow:hidden !important}
  /* v9.10.464 — DO NOT permanently hide #os-taskbar on mobile when Workspace is
     immersive: Start → Log off lived there and was unreachable (display:none
     !important beat every later rule). Platform tab bar is already hidden by
     immersive CSS; the OS dock is the only exit path. */
  body:not(.os-workspace-immersive) #os-taskbar{display:none !important}
  body.os-workspace-immersive #os-taskbar{display:flex !important;z-index:30 !important}
  /* Windows area fills the whole OS desktop (no internal taskbar offset) */
  #os-windows{inset:0 !important;bottom:0 !important}

  /* ── Status bar (top) — subtle overlay ── */
  #os-desktop::before{content:'';position:absolute;top:0;left:0;right:0;height:env(safe-area-inset-top,20px);min-height:20px;background:rgba(0,0,0,.3);z-index:20;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}

  /* ── App grid (home screen) — centered icon grid like iOS/Android ── */
  #os-desktop-icons{
    position:absolute;top:max(28px,env(safe-area-inset-top,20px));left:0;right:0;bottom:12px;
    display:grid !important;grid-template-columns:repeat(4,1fr);gap:12px 8px;
    justify-items:center;align-content:start;padding:16px 20px;overflow-y:auto;max-height:none;width:auto;pointer-events:auto;
    flex-direction:unset;flex-wrap:unset;
  }
  .os-icon{width:68px;text-align:center}
  .os-icon img,.os-icon svg{width:48px;height:48px;border-radius:14px;background:rgba(255,255,255,.06);padding:8px;box-shadow:0 2px 8px rgba(0,0,0,.3)}
  .os-icon span{font-size:10px !important;margin-top:4px;display:block;line-height:1.2}
  /* single-tap opens apps on phone (no double-click) */
  .os-icon{cursor:pointer}

  /* ── Mobile apps: full-screen within the OS desktop container, NOT fixed to viewport ── */
  .os-win,.os-win.os-mobile-app{
    position:absolute !important;inset:0 !important;width:100% !important;height:100% !important;
    border-radius:0 !important;border:none !important;min-width:0 !important;min-height:0 !important;
    z-index:15 !important;max-width:none !important;max-height:none !important;
    left:0 !important;top:0 !important;
  }
  .os-win.os-maximized{inset:0 !important}
  /* Title bar → iOS/Android-style nav bar */
  .os-win-title{
    height:auto;min-height:48px;padding:8px 14px;padding-top:max(8px,env(safe-area-inset-top,0px));
    background:rgba(10,15,26,.97);border-bottom:1px solid rgba(148,163,184,.1);
    cursor:default;display:flex;align-items:center;
  }
  .os-win-title .os-win-name{font:700 16px Outfit,sans-serif}
  /* Hide desktop window controls */
  .os-win-btns,.os-win-btn-min,.os-win-btn-max,.os-win-btn-close{display:none !important}
  /* Back button (mobile only) */
  .os-mob-back{display:flex !important}
  .os-win-body{
    padding-bottom:max(12px,env(safe-area-inset-bottom,0px));
    -webkit-overflow-scrolling:touch;
  }
  /* No resize handles */
  .os-win [style*="cursor:"][style*="resize"]{display:none !important}

  /* ── Dock (bottom) — phone-style app dock ── */
  #os-taskbar{
    position:absolute;bottom:0;left:0;right:0;height:auto;min-height:56px;
    padding:6px 16px;padding-bottom:max(8px,env(safe-area-inset-bottom));
    gap:4px;background:rgba(9,14,24,.85);border-top:none;
    border-radius:20px 20px 0 0;
    backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
    justify-content:space-evenly;
  }
  #os-start-btn{width:44px;height:44px;border-radius:12px}
  #os-start-btn img{width:24px;height:24px}
  .os-tb-item{flex-direction:column;gap:2px;padding:4px 8px !important;min-width:44px;align-items:center}
  .os-tb-item .os-tb-label{font-size:9px !important;display:block !important;color:var(--muted);text-align:center}
  .os-tb-item img,.os-tb-item svg{width:22px;height:22px}
  #os-clock{font-size:9px;padding:0 4px;display:none}
  #os-search{display:none !important}
  #os-systray{display:none}
  /* v9.10.899 — phone dock: real thumb targets, even spacing, iOS-style rounding.
     The 34px desktop pins were cramped and uneven on a phone. */
  #os-pinned{margin-left:0;gap:6px;flex:1;justify-content:space-evenly}
  .os-pin{width:44px;height:44px;border-radius:12px;background:rgba(255,255,255,.04)}
  .os-pin svg{width:22px;height:22px}
  .os-pin.os-pin-active{background:rgba(99,102,241,.18)}
  #os-tray{display:none}

  /* ── Windows container — above everything when an app is open ── */
  #os-windows{inset:0;bottom:0;z-index:12}
  /* Hide dock when a full-screen app is open */
  #os-windows:has(.os-win:not(.os-hidden):not(.os-closing)) ~ #os-taskbar{display:none !important}
  /* Animation: app opens from center like iOS */
  .os-win.os-mobile-app{animation:osMobAppOpen .25s cubic-bezier(.2,.8,.3,1) forwards}
  @keyframes osMobAppOpen{from{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}

  /* ── App content: mobile-responsive layouts ── */
  /* File Manager: hide sidebar, stack vertically */
  #os-body-files > div > div:nth-child(3){flex-direction:column !important}
  #ag-files-sidebar{width:100% !important;max-height:120px;border-right:none !important;border-bottom:1px solid rgba(148,163,184,.12);flex-direction:row !important;flex-wrap:wrap;padding:4px !important;gap:2px !important}
  #ag-files-sidebar .os-fm-loc{padding:4px 8px !important;font-size:11px !important}
  #ag-files-sidebar [style*="text-transform:uppercase"]{display:none !important}
  #os-fm-search{width:100% !important;max-width:none !important}
  #os-body-files [style*="width:180px"]{width:auto !important}
  /* v9.10.512 — File Manager mobile: larger touch targets + simplified nav */
  #os-body-files tr td,#os-body-files tr th{padding:10px 8px !important;min-height:48px !important}
  #os-body-files tr{min-height:48px !important}
  #os-fm-toolbar{flex-wrap:wrap !important;gap:4px !important}
  #os-fm-toolbar button{min-height:36px !important;min-width:36px !important;padding:6px 10px !important}
  #os-fm-breadcrumb{font-size:12px !important;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:60vw}
  /* Hide sort columns on mobile — use dropdown instead */
  #os-fm-sort-cols{display:none !important}

  /* AI Workspace (terminal): the responsive layout is now CONTAINER-driven via
     #os-ide-root.ide-narrow (see the block above this media query). The old viewport rules here
     conflicted with it (forced height:55vh on the chat, column on the root) and are removed. */

  /* Browser app: full width */
  #os-body-browser [style*="width:"]{width:100% !important;max-width:none !important}
  #os-body-browser input[style*="flex"]{min-width:0 !important}

  /* Notes app: full width */
  #os-body-notes{padding:8px !important}
  #os-body-notes textarea{width:100% !important;min-width:0 !important}

  /* Settings app: single column */
  #os-body-settings [style*="display:flex"][style*="gap"]{flex-direction:column !important}
  #os-body-settings [style*="width:200px"],#os-body-settings [style*="width:180px"]{width:100% !important}

  /* General: all app bodies scroll properly on mobile */
  .os-win-body{overflow-y:auto !important;overflow-x:hidden !important;-webkit-overflow-scrolling:touch}
  /* Prevent horizontal overflow in any app */
  .os-win-body > div{max-width:100%;overflow-x:hidden}
  /* Inputs and textareas: never wider than screen */
  .os-win-body input,.os-win-body textarea,.os-win-body select{max-width:100%;box-sizing:border-box}

  /* ── Start menu → full-screen app drawer ── */
  #os-startmenu{
    position:fixed;bottom:0;left:0;right:0;top:20%;
    width:100% !important;max-height:none;
    border-radius:20px 20px 0 0;border:none;
    background:rgba(10,15,26,.97);
    flex-direction:column;
    z-index:25;
  }
  #os-startmenu.os-open{display:flex}
  #os-sm-right{width:100%;border-left:none;border-top:1px solid rgba(148,163,184,.1)}
  /* Home indicator bar at bottom of start menu */
  #os-startmenu::after{content:'';position:sticky;bottom:0;width:100%;padding:8px 0;display:flex;justify-content:center}
}

/* ── ICON RAIL ───────────────────────────────────────── */
.rail{
  width:54px;flex-shrink:0;background:var(--rail);border-right:1px solid var(--border);
  display:flex;flex-direction:column;align-items:center;padding:12px 0;gap:6px;
}
.rail-btn{
  width:38px;height:38px;border-radius:10px;border:1px solid transparent;
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  color:var(--muted);transition:all 0.16s;background:transparent;
}
.rail-btn:hover{color:var(--text);background:rgba(255,255,255,0.05)}
.rail-btn.active{color:var(--accent);background:var(--accent-glow);
  border-color:rgba(34,217,230,0.4);box-shadow:0 0 14px var(--accent-glow)}
.rail-btn svg{width:18px;height:18px}
.rail-spacer{flex:1}

/* ── LEFT COLUMN ─────────────────────────────────────── */
.col-left{
  width:288px;flex-shrink:0;background:var(--panel-2);border-right:1px solid var(--border);
  display:flex;flex-direction:column;overflow:hidden;
}
.col-right.desktop-hidden { display: none !important; }
.col-section-hdr{
  padding:13px 16px 7px;display:flex;align-items:center;justify-content:space-between;
}
.scroll{overflow-y:auto;overflow-x:hidden}
.realm-nav{padding:2px 10px 8px}
.nav-item{
  display:flex;align-items:center;gap:11px;padding:9px 11px;border-radius:9px;
  cursor:pointer;color:var(--muted);transition:all 0.15s;font-size:12.5px;font-weight:500;
  border:1px solid transparent;
}
.nav-item:hover{color:var(--text);background:rgba(255,255,255,0.04)}
.nav-item.active{color:var(--accent);background:var(--accent-glow);border-color:rgba(34,217,230,0.25)}
.nav-item svg{width:16px;height:16px;flex-shrink:0;opacity:0.9}

.chan-group{padding:4px 10px 0}
.chan-group-hdr{padding:11px 8px 5px;display:flex;align-items:center;justify-content:space-between}
.chan-group-hdr .cnt{font-size:9px;color:var(--muted-2);font-family:var(--mono)}
.chan-item{
  display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:10px;
  cursor:pointer;color:#d1d5db;transition:all 0.14s;border:1px solid transparent;
  position:relative;
}
.chan-item:hover{color:#fff;background:rgba(255,255,255,0.06)}
.chan-item.active{color:#fff;background:rgba(34,217,230,0.12);border-color:rgba(34,217,230,0.25)}
.chan-item.active::before{
  content:"";position:absolute;left:-10px;top:50%;transform:translateY(-50%);
  width:4px;height:20px;border-radius:0 4px 4px 0;background:var(--accent);box-shadow:0 0 10px var(--accent);
}
.chan-icon{width:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  color:var(--muted-2);font-family:var(--mono);font-size:14px}
.chan-item.active .chan-icon{color:var(--accent)}
.chan-icon svg{width:16px;height:16px}
.chan-name{flex:1;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600;letter-spacing:0.3px}
.chan-tag{font-size:8px;font-family:var(--mono);padding:1px 5px;border-radius:6px;
  background:rgba(255,255,255,0.05);color:var(--muted);text-transform:uppercase;letter-spacing:0.5px}
.chan-tag.sys{background:rgba(248,113,113,0.1);color:var(--bad)}
.chan-tag.onboard{background:rgba(251,191,36,0.1);color:var(--warn)}
.chan-count{font-size:9px;font-family:var(--mono);color:var(--muted-2);min-width:18px;text-align:right}

/* ── CENTER COLUMN ───────────────────────────────────── */
.col-center{flex:1;min-width:0;display:flex;flex-direction:column;background:rgba(0,0,0,0.18);overflow:hidden}
.center-hdr{
  flex-shrink:0;height:50px;display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding-top:0;padding-right:20px;padding-bottom:0;padding-left:20px;
  border-bottom:1px solid var(--border);background:var(--panel);
}
/* v9.10.422 — the call / video / sound buttons were each a direct flex child of a
   `justify-content:space-between` row, so the browser spread them evenly across the
   FULL header width (owner: "the call buttons up top are to spread apart"). Letting
   the title absorb the free space packs the action buttons together on the right,
   which is what space-between was meant to achieve in the first place. */
.center-hdr .ch-title{display:flex;align-items:center;gap:11px;min-width:0;flex:1 1 auto}
.center-hdr .ch-icon{
  width:30px;height:30px;border-radius:8px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:var(--accent-glow);color:var(--accent);border:1px solid rgba(34,217,230,0.3);
}
.center-hdr .ch-icon svg{width:15px;height:15px}
.center-hdr .ch-meta{display:flex;flex-direction:column;line-height:1.25;min-width:0}
.center-hdr .ch-kicker{font-size:9px;letter-spacing:2px;text-transform:uppercase;color:var(--muted)}
.center-hdr .ch-name{font-family:var(--ui);font-size:14px;font-weight:700;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gear-btn{
  width:34px;height:34px;border-radius:9px;border:1px solid var(--border);background:rgba(255,255,255,0.03);
  color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.16s;
}
.gear-btn:hover{color:var(--accent);border-color:rgba(34,217,230,0.4);transform:rotate(45deg)}
.gear-btn svg{width:17px;height:17px}

.transcript{flex:1;overflow-y:auto;padding:22px 24px;display:flex;flex-direction:column;gap:12px}
@keyframes fadeIn{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:translateY(0)}}
/* ── CHAT BUBBLES — author-aligned (owner/human RIGHT, AIs/others LEFT) ── */
.turn{display:flex;gap:10px;align-items:flex-end;animation:fadeIn 0.28s ease-out;cursor:pointer;
  max-width:100%;}
.turn.right{flex-direction:row-reverse;align-self:flex-end}
.turn.left{align-self:flex-start}
.turn .av{
  width:32px;height:32px;border-radius:9px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:13px;color:#04070d;
  box-shadow:0 3px 12px rgba(0,0,0,0.4);
}
.turn .body{min-width:0;max-width:min(70%,560px);display:flex;flex-direction:column}
.turn.right .body{align-items:flex-end}
.turn .name-row{display:flex;gap:8px;align-items:baseline;margin-bottom:3px;padding:0 4px}
.turn.right .name-row{flex-direction:row-reverse}
.turn .name{font-family:var(--ui);font-weight:700;font-size:12px}
.turn .ts{font-size:9px;color:var(--muted-2);font-family:var(--mono)}
.turn .reply-to{font-size:9.5px;color:var(--muted-2);font-family:var(--mono);margin-bottom:3px;padding:2px 9px;
  border-left:2px solid var(--border-2);background:rgba(255,255,255,0.02);border-radius:0 6px 6px 0;max-width:100%;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.turn.right .reply-to{border-left:none;border-right:2px solid var(--border-2);border-radius:6px 0 0 6px}
.turn .bubble{
  background:var(--panel);border:1px solid var(--border);border-radius:13px 13px 13px 4px;
  padding:9px 14px;line-height:1.55;font-size:12.5px;color:#dce4f1;
  white-space:pre-wrap;word-break:break-word;box-shadow:0 3px 14px rgba(0,0,0,0.22);
  transition:border-color 0.18s;max-width:100%;
}
.turn.right .bubble{
  background:linear-gradient(135deg,var(--c-ryan),#d98f12);color:#1a1206;border-color:transparent;
  border-radius:13px 13px 4px 13px;
}
.turn.right:hover .bubble{filter:brightness(1.05)}
.turn.left:hover .bubble{border-color:rgba(255,255,255,0.16)}
.turn .bubble code{background:rgba(0,0,0,0.18);padding:1px 5px;border-radius:4px;font-family:var(--mono);font-size:11px}
.turn .bubble pre{background:rgba(0,0,0,0.45);padding:9px 11px;border-radius:7px;overflow-x:auto;color:#dce4f1;
  margin-top:6px;font-family:var(--mono);font-size:11px;line-height:1.55;border:1px solid var(--border-2)}
/* ── THREAD sub-view (breadcrumb + list sections) ── */
.thr-crumb{flex-shrink:0;display:flex;align-items:center;gap:8px;padding:9px 20px;border-bottom:1px solid var(--border);
  background:var(--panel-2);font-size:11px;color:var(--muted)}
.thr-crumb .back{cursor:pointer;color:var(--accent);font-weight:700;display:flex;align-items:center;gap:5px;padding:3px 8px;
  border-radius:7px;border:1px solid rgba(34,217,230,0.25)}
.thr-crumb .back:hover{background:var(--accent-glow)}
.thr-crumb .cur{color:var(--text);font-weight:600}
.thr-sec{margin-bottom:6px}
.thr-sec .ms-hdr{font-size:9.5px;letter-spacing:1.4px;text-transform:uppercase;color:var(--muted-2);margin:14px 0 8px;padding:0 2px}
.thr-item{display:flex;align-items:center;gap:11px;padding:10px 12px;border:1px solid var(--border);border-radius:10px;
  background:rgba(255,255,255,0.015);cursor:pointer;margin-bottom:7px;transition:all .14s}
.thr-item:hover{border-color:rgba(34,217,230,0.3);background:var(--accent-glow)}
.thr-ic{width:30px;height:30px;border-radius:8px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:rgba(34,217,230,0.12);color:var(--accent);font-weight:800}
.thr-meta{flex:1;min-width:0}
.thr-name{font-family:var(--ui);font-weight:600;font-size:12.5px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.thr-sub{font-size:9.5px;color:var(--muted-2);font-family:var(--mono);margin-top:2px}
.thr-cnt{font-family:var(--mono);font-size:11px;color:var(--muted);flex-shrink:0}
/* ── CHANNEL PROFILE (settings sub-tab) ── */
.cp-id{display:flex;align-items:center;gap:14px;padding:16px;border:1px solid var(--border);border-radius:13px;
  background:linear-gradient(135deg,rgba(34,217,230,0.05),rgba(255,255,255,0.01))}
.cp-id .cp-ic{width:52px;height:52px;border-radius:13px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:rgba(34,217,230,0.14);color:var(--accent)}
.cp-id .cp-ic svg{width:26px;height:26px}
.cp-id .cp-name{font-family:var(--ui);font-weight:800;font-size:17px;color:#fff}
.cp-id .cp-tags{display:flex;gap:6px;margin-top:5px;flex-wrap:wrap}
.cp-id .cp-tag{font-size:8.5px;font-family:var(--mono);padding:2px 8px;border-radius:6px;background:rgba(255,255,255,0.05);color:var(--muted)}
.cp-worker{display:flex;align-items:center;gap:11px;padding:9px 11px;border:1px solid var(--border);border-radius:10px;
  background:rgba(255,255,255,0.015);margin-bottom:7px}
.cp-worker .cw-av{width:30px;height:30px;border-radius:8px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:12px;color:#04070d}
.cp-worker .cw-name{font-family:var(--ui);font-weight:700;font-size:12.5px}
.cp-worker .cw-role{font-size:9px;letter-spacing:0.8px;text-transform:uppercase;color:var(--muted-2);margin-top:2px}
.cp-sched-row{display:flex;justify-content:space-between;align-items:center;padding:9px 0;border-bottom:1px solid var(--border)}
.cp-sched-row:last-child{border-bottom:none}
.cp-sched-row .k{font-size:11px;color:var(--muted)}
.cp-sched-row .v{font-family:var(--mono);font-size:12px;color:var(--text)}
.cp-sched-row .v.na{color:var(--muted-2);font-family:var(--ui);font-size:10px;font-style:italic}
/* ── richer metrics extras ── */
.met-kv{display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--border);font-size:11.5px}
.met-kv:last-child{border-bottom:none}
.met-kv .k{color:var(--muted)}
.met-kv .v{font-family:var(--mono);color:var(--text)}

.empty-state{
  flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;color:var(--muted);text-align:center;padding:40px;
}
.empty-state .es-icon{
  width:64px;height:64px;border-radius:16px;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--border);background:rgba(255,255,255,0.02);color:var(--muted-2);
}
.empty-state .es-icon svg{width:30px;height:30px}
.empty-state .es-title{font-family:var(--ui);font-size:13px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted)}
.empty-state .es-sub{font-size:11px;color:var(--muted-2);max-width:340px;line-height:1.6}
.empty-state .es-sub b{color:var(--accent);font-weight:600}

/* Channel settings slide-over */
.settings-panel{
  position:absolute;top:50px;right:0;bottom:0;width:300px;z-index:20;
  background:var(--panel-solid);border-left:1px solid var(--border);
  box-shadow:-20px 0 40px rgba(0,0,0,0.5);transform:translateX(100%);
  transition:transform 0.25s ease;display:flex;flex-direction:column;
}
.settings-panel.open{transform:translateX(0)}
.sp-hdr{padding:14px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}
.sp-hdr .x{cursor:pointer;color:var(--muted);width:18px;height:18px;display:flex;align-items:center;justify-content:center}
.sp-hdr .x:hover{color:var(--bad)}
.sp-body{padding:16px;overflow-y:auto;display:flex;flex-direction:column;gap:18px}
.sp-block .sp-k{font-size:9px;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);margin-bottom:7px}
.sp-row{display:flex;align-items:center;justify-content:space-between;font-size:12px;padding:3px 0}
.sp-row .v{color:var(--text);font-family:var(--mono);font-size:11px}
.sp-pill{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--good);font-weight:600}
.sp-speakers{display:flex;flex-wrap:wrap;gap:6px}
.sp-speaker{font-size:10px;padding:3px 9px;border-radius:7px;border:1px solid var(--border);
  background:rgba(255,255,255,0.03);font-family:var(--mono)}
.sp-speakers .none{color:var(--muted-2);font-style:italic;font-size:11px}
#mm-body .sp-block{margin-bottom:16px}
#mm-body .sp-block:last-child{margin-bottom:0}

/* ── RIGHT COLUMN ────────────────────────────────────── */
.col-right{
  width:320px;flex-shrink:0;background:var(--panel-2);border-left:1px solid var(--border);
  display:none !important;flex-direction:column;overflow:hidden;
}
/* v9.10.502 — right column permanently hidden. All admin content lives in the Admin Panel modal now. */
/* v9.10.504 — owner layout: col-right gone, expand center to fill.
   On home view, hide the channel sidebar too so the feed gets full width like guests see. */
body.scope-owner[data-view="home"] #col-left{display:none !important;width:0 !important;min-width:0 !important}
body.scope-owner .col-center{flex:1 !important}
.col-right .scroll{padding:0 0 14px}
/* single scroll region: Lattice Agents + all accordions reachable on desktop */
.col-right-scroll{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;-webkit-overflow-scrolling:touch}
.col-right-scroll::-webkit-scrollbar{width:8px}
.col-right-scroll::-webkit-scrollbar-thumb{background:rgba(34,217,230,0.18);border-radius:4px}
/* Side panel hosted inside the Menu's Side Panel popup — render #col-right as a
   normal block filling the docked #gmodal, overriding the column / hidden / mobile
   drawer positioning it normally uses. */
#gmodal .col-right.in-menu-modal{
  display:flex !important;width:100% !important;min-width:0 !important;max-width:none !important;
  height:auto !important;max-height:72vh !important;flex-shrink:1 !important;
  position:static !important;transform:none !important;opacity:1 !important;
  border-left:none !important;background:transparent !important;padding:0 !important;
}
/* A live dashboard element (agents list, a side-panel accordion) hosted inside an
   Admin Panel section: render flush as a normal block, force-open, hide its own
   header row since the section nav already labels it. */
#gmodal .admin-mounted{
  display:block !important;width:auto !important;min-width:0 !important;max-width:none !important;
  height:auto !important;max-height:64vh !important;overflow-y:auto !important;overflow-x:hidden !important;
  opacity:1 !important;position:static !important;transform:none !important;
  border:none !important;background:transparent !important;padding:0 !important;margin:0 !important;
}
#gmodal .admin-mounted .acc-hdr{ display:none !important; }
#gmodal .admin-mounted .acc-body,
#gmodal .admin-mounted.acc.collapsed .acc-body{ display:block !important; }
.root-admin{
  margin:12px 14px 6px;padding:13px;border-radius:12px;
  background:linear-gradient(135deg,rgba(251,191,36,0.10),rgba(251,191,36,0.02));
  border:1px solid rgba(251,191,36,0.25);display:flex;align-items:center;gap:12px;
}
.root-admin .ra-av{
  width:42px;height:42px;border-radius:11px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(140deg,#fbbf24,#d97706);color:#1a1205;font-family:var(--ui);font-weight:800;font-size:17px;
  box-shadow:0 0 16px rgba(251,191,36,0.3);
}
.root-admin .ra-info{flex:1;min-width:0}
.root-admin .ra-name{font-family:var(--ui);font-weight:700;font-size:13.5px;color:#fff;display:flex;align-items:center;gap:6px}
.root-admin .ra-name svg{width:13px;height:13px;color:var(--star)}
.root-admin .ra-role{font-size:9px;letter-spacing:1.5px;text-transform:uppercase;color:var(--warn);margin-top:2px}
.root-admin .ra-dot{width:9px;height:9px;border-radius:50%;background:var(--good);box-shadow:0 0 8px var(--good)}

.agent-list{padding:2px 12px;flex-shrink:0;overflow-x:hidden}
.agent-row{
  display:flex;align-items:center;gap:11px;padding:8px 10px;border-radius:10px;
  transition:background 0.14s;cursor:default;
}
.agent-row:hover{background:rgba(255,255,255,0.03)}
.agent-av{
  width:32px;height:32px;border-radius:9px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:12px;color:#04070d;position:relative;
}
.agent-av .stat{position:absolute;bottom:-2px;right:-2px;width:11px;height:11px;border-radius:50%;
  border:2px solid var(--panel-2);background:var(--good)}
.agent-meta{flex:1;min-width:0}
.agent-name-row{display:flex;align-items:center;gap:7px}
.agent-name{font-family:var(--ui);font-weight:600;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.agent-app-tag{font-size:7.5px;font-family:var(--mono);letter-spacing:0.5px;padding:1px 5px;border-radius:5px;
  background:rgba(255,255,255,0.06);color:var(--muted);text-transform:uppercase}
.agent-role{font-size:9.5px;color:var(--muted-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.agent-health{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex-shrink:0}
.agent-pct{font-family:var(--mono);font-size:11px;font-weight:600;color:var(--good)}
.agent-vitals{display:flex;gap:8px;margin-top:3px}
.av-chip{display:inline-flex;align-items:center;gap:3px;font-family:var(--mono);font-size:9.5px;line-height:1}
.av-chip .av-k{color:var(--muted-2);font-size:8.5px}
.av-chip .av-v{font-weight:700;font-variant-numeric:tabular-nums}
.agent-energy-bar{width:42px;height:5px;border-radius:3px;background:rgba(255,255,255,0.08);overflow:hidden}
.agent-energy-bar .aeb-fill{height:100%;border-radius:3px;transition:width 0.4s ease,background 0.4s ease}
.agent-sync{width:13px;height:13px;color:var(--muted-2);animation:spin 4s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.agent-row{cursor:pointer}
.agent-row.expanded{background:rgba(34,217,230,0.05)}

/* ── RESIZABLE SPLIT (agent list ↑ / accordions ↓) ──────────────────────── */
/* The right column is now a fixed-height flex: a scrollable agent region whose
   height is owner-resizable (persisted in localStorage), a drag handle, then a
   scrollable accordion region that fills the rest. Neither pushes the other off
   screen. */
.rc-agents{display:flex;flex-direction:column}
.agent-list{padding:2px 12px 6px;overflow-x:hidden}
.rc-accordions{padding-bottom:14px}

/* ── INLINE agent expand (live vitals + provider/model + actions) ────────── */
.agent-inline{margin:0 12px 6px;border:1px solid var(--border);border-top:none;
  border-radius:0 0 10px 10px;background:rgba(0,0,0,0.22);padding:10px 11px;display:none;animation:agInline 0.16s ease}
.agent-inline.open{display:block}
@keyframes agInline{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.ai-rows{display:flex;flex-direction:column;gap:3px;margin-bottom:8px}
.ai-rows .r{display:flex;justify-content:space-between;font-size:10px;gap:8px}
.ai-rows .r .k{color:var(--muted-2);text-transform:uppercase;letter-spacing:0.5px;font-size:8.5px;flex-shrink:0}
.ai-rows .r .v{color:var(--muted);font-family:var(--mono);font-size:10px;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ai-vit{display:flex;gap:6px;margin-bottom:8px;flex-wrap:wrap}
.ai-vit .chip{flex:1;min-width:54px;text-align:center;border:1px solid var(--border);border-radius:7px;padding:5px 4px;background:rgba(255,255,255,0.02)}
.ai-vit .chip .vv{font-family:var(--mono);font-weight:700;font-size:12px}
.ai-vit .chip .vl{font-size:7.5px;letter-spacing:0.5px;text-transform:uppercase;color:var(--muted-2);margin-top:2px}
.ai-acts{display:flex;gap:5px}
.cap-pill{display:inline-block;font-size:7px;font-family:var(--mono);letter-spacing:0.5px;padding:1px 5px;border-radius:5px;
  border:1px solid rgba(34,217,230,0.3);color:var(--accent);background:rgba(34,217,230,0.05);margin-left:5px;text-transform:uppercase}

/* ── HUMANS / GUESTS + ADMIN accordion content ──────────────────────────── */
.hu-row{display:flex;align-items:center;gap:10px;padding:7px 8px;border-radius:9px;cursor:pointer;transition:background 0.14s}
.hu-row:hover{background:rgba(255,255,255,0.04)}
.hu-av{width:30px;height:30px;border-radius:8px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:12px;color:#04070d}
.hu-meta{flex:1;min-width:0}
.hu-name{font-family:var(--ui);font-weight:600;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hu-sub{font-size:9.5px;color:var(--muted-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hu-role{font-size:8px;font-family:var(--mono);letter-spacing:0.5px;padding:2px 6px;border-radius:6px;flex-shrink:0;
  border:1px solid var(--border);color:var(--muted);text-transform:uppercase}
.adm-grid{display:flex;flex-direction:column;gap:5px}
.adm-row{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:10.5px;
  padding:6px 8px;border-radius:8px;background:rgba(255,255,255,0.02);border:1px solid var(--border)}
.adm-row .k{color:var(--muted-2);text-transform:uppercase;letter-spacing:0.5px;font-size:8.5px}
.adm-row .v{font-family:var(--mono);font-size:10px;text-align:right}
.adm-dot{width:8px;height:8px;border-radius:50%;display:inline-block;vertical-align:middle;margin-right:5px}

/* per-AI tailored config sections in the editor + portfolio config tab */
.cfg-sec{border:1px solid var(--border);border-radius:9px;padding:9px 11px;margin-top:8px;background:rgba(255,255,255,0.015)}
.cfg-sec > .cfg-sec-t{font-family:var(--ui);font-weight:700;font-size:9.5px;letter-spacing:1px;text-transform:uppercase;
  color:var(--accent);margin-bottom:7px;display:flex;align-items:center;gap:6px}
.cfg-ro{display:flex;justify-content:space-between;gap:8px;font-size:10.5px;padding:3px 0}
.cfg-ro .k{color:var(--muted-2)}
.cfg-ro .v{font-family:var(--mono);color:var(--text);text-align:right;overflow-wrap:anywhere}
.cfg-ro .disp{color:var(--muted-2);font-style:italic;font-size:8.5px;margin-left:4px}

/* right-side stacked accordion panels */
.acc{margin:6px 12px 0;border:1px solid var(--border);border-radius:11px;overflow:hidden;background:rgba(255,255,255,0.015)}
.acc-hdr{
  padding:11px 13px;display:flex;align-items:center;justify-content:space-between;cursor:pointer;
  user-select:none;transition:background 0.14s;
}
.acc-hdr:hover{background:rgba(255,255,255,0.03)}
.acc-hdr .acc-t{display:flex;align-items:center;gap:9px}
.acc-hdr .acc-t svg{width:14px;height:14px;color:var(--muted)}
.acc-hdr .acc-t .lbl{color:var(--text)}
.acc-hdr .chev{width:14px;height:14px;color:var(--muted);transition:transform 0.2s}
.acc.collapsed .acc-body{display:none}
.acc.collapsed .chev{transform:rotate(-90deg)}
.acc-body{padding:4px 12px 12px;display:flex;flex-direction:column;gap:8px}
.stage-tag{display:inline-block;font-size:7.5px;font-family:var(--mono);padding:1px 6px;border-radius:6px;
  border:1px solid rgba(34,217,230,0.3);color:var(--accent);letter-spacing:0.5px;background:rgba(34,217,230,0.05)}
.stub{color:var(--muted-2);font-size:10.5px;line-height:1.6;text-align:center;padding:8px 4px}

/* AI Control cards */
.ai-card{border:1px solid var(--border);border-radius:9px;padding:10px;background:rgba(0,0,0,0.2)}
.ai-card-hdr{display:flex;align-items:center;gap:8px;margin-bottom:7px}
.ai-card-dot{width:8px;height:8px;border-radius:50%}
.ai-card-name{font-family:var(--ui);font-weight:700;font-size:11.5px}
.ai-card-rows{display:flex;flex-direction:column;gap:3px;margin-bottom:8px}
.ai-card-row{display:flex;justify-content:space-between;font-size:10px}
.ai-card-row .k{color:var(--muted-2);text-transform:uppercase;letter-spacing:0.5px;font-size:8.5px}
.ai-card-row .v{color:var(--muted);font-family:var(--mono);font-size:10px}
.ai-card-btns{display:flex;gap:5px}
.mini-btn{flex:1;font-size:8.5px;font-family:var(--ui);font-weight:700;text-transform:uppercase;letter-spacing:0.5px;
  padding:4px;border-radius:6px;border:1px solid var(--border);background:rgba(255,255,255,0.03);
  color:var(--muted-2);cursor:not-allowed;position:relative}
.mini-btn .s2{position:absolute;top:-6px;right:-3px;font-size:6px;color:var(--accent);background:var(--bg);padding:0 3px;border-radius:4px}

/* Server Control buttons (destructive) */
.ctrl-btn{width:100%;margin-bottom:7px;padding:9px 11px;border-radius:8px;cursor:pointer;
  font-family:var(--ui);font-size:10.5px;font-weight:700;letter-spacing:0.8px;text-transform:uppercase;
  border:1px solid rgba(251,191,36,0.45);background:rgba(251,191,36,0.08);color:var(--warn);transition:all 0.14s}
.ctrl-btn:hover{background:rgba(251,191,36,0.16);transform:translateY(-1px)}
.ctrl-btn.danger{border-color:rgba(248,113,113,0.5);background:rgba(248,113,113,0.14);color:#fca5a5}
.ctrl-btn.danger:hover{background:rgba(248,113,113,0.24)}
.ctrl-note{font-size:9px;color:var(--muted-2);line-height:1.5;margin-top:2px}
/* View Mode picker (Auto/Mobile/Desktop) — neutral, non-destructive palette */
.vm-row{display:flex;gap:6px;margin-bottom:8px}
.vm-btn{width:auto;flex:1;margin-bottom:0;border-color:var(--border);
  background:rgba(255,255,255,0.04);color:var(--muted)}
.vm-btn:hover{background:rgba(34,217,230,0.10);color:var(--text)}
.vm-btn.vm-on{border-color:var(--accent);background:rgba(34,217,230,0.16);color:var(--accent)}

/* ── User Management (owner-only) ── */
#user-mgmt{margin-top:10px;border-top:1px solid var(--border);padding-top:8px}
.um-head{font-size:9px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--muted);margin-bottom:6px;display:flex;align-items:center;gap:6px}
.um-tag{font-size:7.5px;background:rgba(34,217,230,0.16);color:var(--accent);padding:1px 5px;border-radius:6px;letter-spacing:.5px}
.um-list{display:flex;flex-direction:column;gap:4px;max-height:220px;overflow-y:auto}
.um-row{display:flex;align-items:center;gap:7px;background:rgba(255,255,255,0.025);border:1px solid var(--border);border-radius:8px;padding:5px 7px}
.um-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto}
.um-meta{flex:1;min-width:0}
.um-name{font-size:10.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.um-handle{color:var(--muted);font-weight:400;font-size:9px}
.um-sub{font-family:var(--mono);font-size:8.5px;color:var(--muted-2)}
.um-role{font-size:9px;color:var(--star)}
.um-rolesel,#um-role{background:rgba(0,0,0,.35);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:9px;padding:2px 4px}
.um-actions{display:flex;gap:3px}
.um-x{background:rgba(0,0,0,.3);border:1px solid var(--border);border-radius:6px;color:var(--muted);cursor:pointer;font-size:11px;width:22px;height:22px;line-height:1}
.um-x:hover{color:var(--text);border-color:var(--accent)}
.um-prot{font-size:8px;color:var(--muted-2)}
.um-mint{margin-top:8px;display:flex;flex-direction:column;gap:5px}
.um-mint input{background:rgba(0,0,0,.4);border:1px solid var(--border);border-radius:7px;color:#fff;font-size:11px;padding:7px 9px;width:100%}
.um-mintrow{display:flex;gap:6px}.um-mintrow .mini-btn{flex:1}
.um-out{font-size:10px}
.um-token{background:rgba(34,217,230,0.07);border:1px solid rgba(34,217,230,0.3);border-radius:8px;padding:8px;font-size:10px}
.um-token code{display:block;word-break:break-all;font-family:var(--mono);font-size:10px;color:var(--accent);margin:4px 0}
.um-copy{background:var(--accent);color:#04070d;border:none;border-radius:6px;padding:3px 10px;font-size:9px;font-weight:700;cursor:pointer}
.um-once{font-size:8px;color:var(--warn);margin-top:3px}
.um-note{font-size:8.5px;color:var(--muted-2);line-height:1.5}
/* Member/viewer scope: hide owner/admin-only control affordances entirely. */
body.scope-member [data-needs="admin"]{display:none !important}
/* v9.10.343 — BOOT LOCK (anti-flash): the <body> ships as scope-member (least
   privilege) but that still PAINTS the operator shell (Channel Lattice + right
   Command-Center panels + host telemetry) for the ~600ms until /api/me returns and
   applyScope() flips the real role. While `scope-booting` is present we hide that
   chrome so a guest — or anyone inspecting the page — never sees the command center
   flash by. applyScope() removes `scope-booting` ONLY once the session role is
   resolved (a safety timeout clears it either way).
   IMPORTANT: this is a VISUAL guard / defense-in-depth ONLY. The real access
   boundary is server-side — every /api/* route is auth-gated on the server, so
   the markup being present in the HTML does not grant a guest any operator access. */
body.scope-booting .col-left,
body.scope-booting .col-right,
body.scope-booting #rc-toggle,
body.scope-booting .tb-right .metric{visibility:hidden !important}
/* v9.10.367 — BOOT CURTAIN (the actual anti-flash fix).
   The v9.10.343 lock above is an ALLOW-LIST of four selectors using
   `visibility:hidden`, and it leaked in two ways the owner could see:
     1) It never covered `.rail` (the Config / Antigravity / Root Admin operator
        buttons), `.col-center` / `#view-home`, or the "Realm Control Center ·
        Command Home · live realm" topbar branding — all of which painted in full
        for the entire /api/me round-trip, to guests included.
     2) `visibility:hidden` PRESERVES layout, so even the four locked selectors
        still reserved the operator 4-column geometry (288px gutters) before
        collapsing to the guest grid — the shape of the command center was visible
        even where its contents were not.
   Enumerating more selectors would just be a longer allow-list with the same
   failure mode. Instead this is FAIL-CLOSED BY CONSTRUCTION: one opaque fixed
   curtain painted above the whole document while the role is unknown. Nothing
   underneath it can be seen no matter what markup exists or gets added later.
   It is pure CSS in <head>, so it is in effect on the FIRST paint — before any
   script runs. applyScope() drops `scope-booting` once the role resolves (with an
   existing safety timeout), taking the curtain with it.
   NOTE: this remains a VISUAL guard. The access boundary is server-side — see
   requireHostRead() in command-center-server.mjs (v9.10.367). */
body.scope-booting::before{
  content:'';
  position:fixed;
  top:0; left:0; right:0; bottom:0;
  background:var(--bg,#04070d);
  z-index:2147483000;
  pointer-events:all;
}
/* v9.10.369 — PAGE BACKDROP (the empty gutters either side of the feed).
   Owner: "on the sides that have nothing can we also have a option for the user to
   change that background look to a theme image picked from the store selction?"
   The "Background Art" uploader already promised "shows on both sides like Steam",
   but the image only ever skinned the profile CARD — the page gutters stayed flat
   black. This is the layer that actually delivers it.

   Implemented as ONE fixed element behind everything rather than by styling any
   layout container, because the feed/dash/post containers and their width+padding
   rules are off-limits, and no scroll-clipping property may be introduced in this
   file. A detached fixed layer touches none of that: no reflow, no scroll
   interaction, no effect on the feed column. (Selector names and that property are
   spelled out nowhere here on purpose — the repo audit greps for them.)
   #app-bg-scrim is a separate dim pass so a bright wallpaper can't make the UI
   unreadable — strength is user-controlled (appBgDim, 0–90%). */
/* ── v9.10.372 — PARALLAX DEPTH ───────────────────────────────────────────────
   Owner: "can you make the page have a 3D depth of view to each layer and help make
   the image look 3d best we can? so it doesnt look like a 2d platform but looks like
   there is depth / illusions?"

   Depth here is built from FOUR cues, stacked, because no single one reads as 3D:
     1. MOTION PARALLAX — the far layer translates further than the near layer as the
        pointer moves. This is the strongest cue the brain has for depth.
     2. DEPTH OF FIELD — the far layer carries a slight blur + a touch of saturation
        loss, so the crisp content column reads as nearer. Real cameras do this.
     3. VIGNETTE — a radial darkening toward the edges bends the flat plane into a
        shallow bowl and pushes focus to the centre.
     4. ATMOSPHERIC HAZE — a subtle bloom that also parallaxes, at a DIFFERENT rate
        from the image, which is what sells "separate layers" rather than one moving
        picture.

   All movement is `transform` only (GPU-composited, never triggers layout), driven by
   two CSS variables written from one rAF-throttled pointer handler. Every layer is
   position:fixed + pointer-events:none, so none of this can affect the feed, the
   scroll container, or any protected layout rule.

   The layers are scaled up ~1.12 so they can translate without ever exposing an edge.
   Scale is applied via transform (not negative insets) specifically so the oversized
   layer contributes nothing to the document's scrollable area. */
#app-bg{
  position:fixed;
  top:0; left:0; right:0; bottom:0;
  z-index:-3;
  background-color:var(--bg,#04070d);
  background-image:var(--app-bg-img,none);
  background-size:cover;
  background-position:center center;
  background-repeat:no-repeat;
  pointer-events:none;
  will-change:transform;
  transform:
    scale(1.12)
    translate3d(calc(var(--depth-x,0) * -22px), calc(var(--depth-y,0) * -16px), 0);
  transition:transform .35s cubic-bezier(.22,.61,.36,1);
  filter:blur(var(--app-bg-blur,1.5px)) saturate(.92);
}
/* Atmospheric haze — parallaxes at roughly HALF the far layer's rate and in the same
   direction. Two elements moving at different speeds is what the eye reads as depth. */
#app-bg-mid{
  position:fixed;
  top:0; left:0; right:0; bottom:0;
  z-index:-2;
  pointer-events:none;
  will-change:transform;
  background:
    radial-gradient(60% 45% at 50% 38%, rgba(120,190,255,.10), transparent 70%),
    radial-gradient(45% 35% at 22% 78%, rgba(160,120,255,.07), transparent 70%);
  transform:
    scale(1.06)
    translate3d(calc(var(--depth-x,0) * -10px), calc(var(--depth-y,0) * -7px), 0);
  transition:transform .45s cubic-bezier(.22,.61,.36,1);
}
/* Scrim now doubles as the VIGNETTE: flat dim in the middle, heavier at the corners,
   which curves the plane and makes the centre feel closer. */
#app-bg-scrim{
  position:fixed;
  top:0; left:0; right:0; bottom:0;
  z-index:-1;
  background:
    radial-gradient(120% 95% at 50% 45%,
      rgba(4,7,14,0) 38%,
      rgba(4,7,14,.34) 74%,
      rgba(4,7,14,.72) 100%),
    var(--bg,#04070d);
  opacity:var(--app-bg-dim,0.20);
  pointer-events:none;
}
/* Only paint the backdrop when one is actually set — otherwise the layers are inert
   and the app keeps its normal flat background byte-for-byte. */
body:not(.has-app-bg) #app-bg,
body:not(.has-app-bg) #app-bg-mid,
body:not(.has-app-bg) #app-bg-scrim{display:none !important}
/* NEAR PLANE — the content must look like it is FLOATING above the backdrop, not
   printed onto it. A deeper, softer drop shadow plus a 1px light top edge is what
   reads as "lifted": the shadow implies distance to the surface behind, the light
   edge implies a face catching light from above.
   Deliberately scoped to `body.has-app-bg` so the normal flat-background app is
   completely unchanged, and deliberately applied ONLY to .guest-card — the feed post
   containers are covered by the do-not-touch rule and are left entirely alone. */
body.has-app-bg .guest-card{
  box-shadow:
    0 1px 0 rgba(255,255,255,.05) inset,
    0 18px 40px -12px rgba(0,0,0,.75),
    0 4px 12px -6px rgba(0,0,0,.5);
  backdrop-filter:blur(3px);
}
/* Motion is decoration. If the OS asks for less of it, keep every STATIC depth cue
   (blur, vignette, haze) and drop only the movement. */
@media (prefers-reduced-motion: reduce){
  body.has-app-bg #app-bg,
  body.has-app-bg #app-bg-mid{transition:none !important}
  body.has-app-bg #app-bg{transform:scale(1.12) !important}
  body.has-app-bg #app-bg-mid{transform:scale(1.06) !important}
}
/* v9.10.371 — MAKE IT ACTUALLY VISIBLE.
   The wallpaper was rendering but arriving washed out to near-nothing, because it
   was being filtered through three stacked layers before reaching the eye:
     1. the 55% default scrim (far too strong as a default),
     2. .col-center's rgba(0,0,0,.18) wash, and
     3. on someone else's profile, #usrprof-overlay's rgba(4,7,14,.82) backdrop —
        an 82% blackout covering the whole viewport, which alone killed it.
   Steam's proportion is the opposite: the wallpaper reads at FULL strength in the
   gutters, and legibility comes from the content column being its own solid panel
   on top — which ours already is (.gpost / .guest-card carry their own backgrounds).
   So when a wallpaper is active we stop the container washes and let it through.
   The user-controlled dim still exists for a busy image; it just no longer defaults
   to hiding the feature. */
body.has-app-bg .col-center{background:transparent !important}
/* v9.10.430 — the profile is a PAGE now (#view-profile), not the #usrprof-overlay
   popup, so there is no full-viewport backdrop left to soften. Point the same
   easing at the pane so a wallpaper still reads behind a profile. */
body.has-app-bg #view-profile{background:rgba(4,7,14,.35)}
/* The wallpaper is decoration; if the user has asked the OS for less motion, don't
   run an animated GIF full-bleed behind everything they read. */
@media (prefers-reduced-motion: reduce){
  body.has-app-bg #app-bg{background-attachment:scroll}
}
/* OWNER-ONLY affordances (stricter than admin): hidden for EVERYONE except a
   resolved owner session. Only owner sessions carry .scope-owner (set in
   applyScope()); the body defaults without it, so these stay hidden (least
   privilege) until owner resolves. Used for Rebuild & Restart (recompiles engine). */
body:not(.scope-owner) [data-needs="owner"]{display:none !important}
/* Member/viewer scope: labels/content shown ONLY to non-admin (member/viewer)
   sessions. Owner/admin never carry .scope-member, so these stay hidden for them.
   Used to relabel admin surfaces (e.g. "Root Admin" → "My Profile") for members. */
.member-only{display:none !important}
body.scope-member .member-only{display:inline !important}
/* Phase 3 — VIEWER scope: 'viewer' is a read-only subset of 'member'. ONLY a
   resolved role:'viewer' session carries .scope-viewer (members/admins/owner
   never do). It hides every [data-needs="member"] affordance (the agent-chat
   composers) so viewers get a look-but-don't-touch portal. The server also
   enforces this (POST /api/bot-chat requires member+), so this hide is UX only. */
body.scope-viewer [data-needs="member"]{display:none !important}
/* Read-only hint shown ONLY to viewers (e.g. where a composer would otherwise be). */
.viewer-only{display:none !important}
body.scope-viewer .viewer-only{display:block !important}
/* ── CLOUD GUEST social portal ─────────────────────────────────────────────
   Guests get Home (social feed) + Chat (public channels) + KAIVERSE.
   HIDDEN: Antigravity, Config, Topology, Learning, host metrics, admin bottom
   (control/tests/logs/mem), industrial AI tools, work channels (server-side). */
body.scope-guest [data-needs="admin"]{display:none !important}
body.scope-guest [data-needs="owner"]{display:none !important}
/* Guests keep social compose (member) for public chat / social DMs */
body.scope-guest .guest-hide{display:none !important}
.guest-only{display:none !important}
body.scope-guest .guest-only{display:inline !important}
body.scope-guest .member-only{display:none !important}
body.scope-guest div.guest-only,
body.scope-guest .guest-card.guest-only{display:block !important}
/* Guest nav: Home, Chat, KAIVERSE, Topology, Web — hide host-only Config/Antigravity */
body.scope-guest .rail .rail-btn[data-view="antigravity"],
body.scope-guest .rail .rail-btn[data-view="config"]{display:none !important}
body.scope-guest .m-tabbar .m-tab[data-view="antigravity"],
body.scope-guest .m-tabbar .m-tab[data-view="config"]{display:none !important}
/* v9.10.451 — MUST follow hide rules: entitlement (ag-ok) OR plan name on BOTH rail + mobile tab */
body.scope-guest.ag-ok .rail .rail-btn[data-view="antigravity"],
body.scope-guest.ag-ok .m-tabbar .m-tab[data-view="antigravity"],
body.scope-guest.plan-builder .rail .rail-btn[data-view="antigravity"],
body.scope-guest.plan-team .rail .rail-btn[data-view="antigravity"],
body.scope-guest.plan-enterprise .rail .rail-btn[data-view="antigravity"],
body.scope-guest.plan-builder .m-tabbar .m-tab[data-view="antigravity"],
body.scope-guest.plan-team .m-tabbar .m-tab[data-view="antigravity"],
body.scope-guest.plan-enterprise .m-tabbar .m-tab[data-view="antigravity"]{display:flex !important}
/* Learning optional for guests — keep Dreams tab available */
/* Host telemetry metrics in top bar — never for guests */
body.scope-guest .tb-right .metric{display:none !important}
/* Right column for guests: no Account/ViewMode/DMs (those live in Me / Chat) */
body.scope-guest #acc-control,
body.scope-guest #acc-tests,
body.scope-guest #acc-logs,
body.scope-guest #acc-mem,
body.scope-guest #acc-admin,
body.scope-guest #acc-viewmode,
body.scope-guest #rc-dms,
body.scope-guest #root-admin,
body.scope-guest #rc-agents,
body.scope-guest .col-right > div[style*="padding:2px 14px"]{display:none !important}
body.scope-guest #guest-right-fill{display:flex !important;flex-direction:column;gap:10px;padding:12px;overflow-y:auto}
/* v9.10.342 — owner: the right OS column ("Explore / Quick jump / Online now /
   Trending") is retired for guests — navigation now lives in the blue quick-menu.
   Hide the whole guest right column + every trigger that opened it (the desktop
   ⟩ toggle and the mobile AI-icon header button) so nothing floats over the feed. */
body.scope-guest #col-right,
body.scope-guest #rc-toggle,
body.scope-guest #m-open-right{display:none !important}
/* Right panel collapse — works on all views */
body.rc-hidden .col-right{width:0 !important;min-width:0 !important;overflow:hidden !important;opacity:0;padding:0 !important;border:none !important}
body.rc-hidden .shell{grid-template-columns:56px 1fr !important}
body.scope-guest.rc-hidden .shell{grid-template-columns:56px 1fr !important}
body.scope-guest.rc-hidden[data-view="home"] .shell{grid-template-columns:56px 0px 1fr !important}
.col-right{transition:width .2s ease,opacity .2s ease}
/* 2026-07-17 FIX: on desktop the right panel opens as a fixed slide-over anchored
   to the RIGHT edge (where the ⟩ button is). Previously it was a flex child, so
   when the sibling panes collapsed it jumped to the LEFT and blanked the page.
   Taking it out of flex flow guarantees it opens on the right and never displaces
   the main content. Mobile drawer rules (<=900px) are unaffected. */
@media (min-width:901px){
  body:not(.rc-hidden) #col-right{
    position:fixed; top:54px; right:0; bottom:0; width:340px; z-index:60;
    box-shadow:-10px 0 30px rgba(0,0,0,.45);
    transform:translateX(0); transition:transform .25s ease, opacity .2s ease;
  }
}
body:not(.rc-hidden) #rc-toggle{display:none !important}
#rc-toggle{display:none !important}
/* Bot portfolio: hide ops/files/admin/host-spec tabs for guests */
body.scope-guest .bv-tab[data-bvt="ops"],
body.scope-guest #bv-ops,
body.scope-guest .pf-tab[data-pft="ops"],
body.scope-guest .pf-tab[data-pft="metrics"],
body.scope-guest .pf-tab[data-pft="files"],
body.scope-guest .pf-tab[data-pft="discord"],
body.scope-guest .pf-tab[data-pft="activity"],
body.scope-guest .pf-tab[data-pft="config"],
body.scope-guest [data-guest-deny="1"]{display:none !important}
/* Host-only AI specs in sidebar expanded cards (provider/port/rss) */
body.scope-guest .ai-rows .r[data-host-spec="1"],
body.scope-guest .agent-vitals,
body.scope-guest .agent-energy-bar,
body.scope-guest .pf-vitals,
body.scope-guest .pf-cfg-grid[data-host-spec="1"],
body.scope-guest .bv-cfg-grid[data-host-spec="1"]{display:none !important}
body.scope-guest .shell{grid-template-columns:56px minmax(220px,280px) 1fr 0px}   /* v9.10.342: right col retired for guests */
/* Home feed: collapse left col so the feed gets more width */
body.scope-guest[data-view="home"] .shell{grid-template-columns:56px 0px 1fr 0px}   /* v9.10.342: right col retired for guests */
body.scope-guest[data-view="home"] #col-left{display:none !important;width:0;overflow:hidden}
/* Right panel smooth transition */
body.scope-guest .col-right{transition:width .25s ease,opacity .2s ease}
body.scope-guest.rc-hidden[data-view="home"] .shell{grid-template-columns:56px 0px 1fr 0px !important}
@media (max-width:900px){
  body.scope-guest .shell{grid-template-columns:1fr !important}
  body.scope-guest[data-view="home"] .shell{grid-template-columns:1fr !important}
}
/* Guest chat rail sections (Friends / AIs / Channels / Workspace) */
body.scope-guest .gchat-sec{margin:0 0 10px}
body.scope-guest .gchat-sec-hdr{display:flex;align-items:center;justify-content:space-between;padding:8px 12px 4px;
  font:700 10px Outfit,sans-serif;letter-spacing:1px;text-transform:uppercase;color:var(--muted)}
body.scope-guest .gchat-sec-hdr .cnt{font-family:var(--mono);color:var(--accent);font-size:10px}
body.scope-guest .gchat-row{display:flex;align-items:center;gap:10px;padding:8px 12px;margin:2px 8px;border-radius:10px;
  cursor:pointer;border:1px solid transparent;background:transparent;width:calc(100% - 16px);text-align:left;color:var(--text)}
body.scope-guest .gchat-row:hover{background:rgba(34,217,230,.07);border-color:rgba(34,217,230,.15)}
body.scope-guest .gchat-row.active{background:rgba(34,217,230,.12);border-color:rgba(34,217,230,.35)}
body.scope-guest .gchat-av{width:36px;height:36px;border-radius:50%;object-fit:cover;flex-shrink:0;background:#1a2233;
  display:flex;align-items:center;justify-content:center;font:700 13px Outfit,sans-serif;color:var(--accent);position:relative;overflow:hidden}
body.scope-guest .gchat-av img{width:100%;height:100%;object-fit:cover;border-radius:50%}
body.scope-guest .gchat-av .gdot{position:absolute;bottom:0;right:0;width:10px;height:10px;border-radius:50%;
  border:2px solid var(--panel-2,#0d1320);background:var(--good)}
body.scope-guest .gchat-av .gdot.off{background:var(--muted-2)}
body.scope-guest .gchat-meta{flex:1;min-width:0}
body.scope-guest .gchat-name{font:600 13px Outfit,sans-serif;color:#e8eef8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.scope-guest .gchat-sub{font-size:10.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.scope-guest .gchat-tag{font-size:9px;padding:2px 6px;border-radius:6px;background:rgba(255,255,255,.06);color:var(--muted);flex-shrink:0}
body.scope-guest .gchat-empty{padding:8px 14px;font-size:11px;color:var(--muted);line-height:1.4}
/* Right-rail agent/DM rows use avatars (not paperclip / neon name colors) */
body.scope-guest .agent-name{color:#e8eef8 !important}
body.scope-guest .agent-av{border-radius:50% !important;overflow:hidden;background:#1a2233 !important;color:var(--accent) !important}
body.scope-guest .agent-av img{width:100%;height:100%;object-fit:cover}
body.scope-guest .rc-dms .chan-item{display:flex;align-items:center;gap:10px}
/* Readable guest buttons — soft, high-contrast, not neon eye-burn */
body.scope-guest .gc-btn,body.scope-guest .mini-btn.go,body.scope-guest .gmodal .gm-primary{
  background:rgba(56,189,210,.18) !important;color:#e8f7fb !important;font-weight:700 !important;
  border:1px solid rgba(56,189,210,.45) !important;box-shadow:none !important;
  text-transform:none !important;letter-spacing:.2px !important}
body.scope-guest .gc-btn:hover,body.scope-guest .gmodal .gm-primary:hover{
  background:rgba(56,189,210,.28) !important;border-color:rgba(125,220,235,.7) !important}
body.scope-guest .gc-btn.ghost,body.scope-guest .gmodal .gm-ghost{
  background:rgba(255,255,255,.04) !important;color:#c5d0e0 !important;border:1px solid rgba(255,255,255,.12) !important}
body.scope-guest .guest-tab-btn{background:rgba(255,255,255,.05) !important;color:#b8c4d6 !important;border:1px solid rgba(255,255,255,.1) !important}
body.scope-guest .guest-tab-btn.on{background:rgba(56,189,210,.2) !important;color:#e8f7fb !important;border-color:rgba(56,189,210,.5) !important}
/* ── VISITOR (unauthenticated) scope — v9.10.448 ─────────────────────────────
   Visitors can see Home feed, Browser, KAI Dreams. Everything else is hidden.
   Interactive actions (post, DM, comment, like) show a login prompt. */
body.scope-visitor [data-needs="admin"],
body.scope-visitor [data-needs="owner"],
body.scope-visitor .guest-hide,
body.scope-visitor .member-only{display:none !important}
body.scope-visitor .rail .rail-btn[data-view="antigravity"],
body.scope-visitor .rail .rail-btn[data-view="config"],
body.scope-visitor .rail .rail-btn[data-view="transcripts"],
body.scope-visitor .rail .rail-btn[data-view="topology"]{display:none !important}
body.scope-visitor .m-tabbar .m-tab[data-view="antigravity"],
body.scope-visitor .m-tabbar .m-tab[data-view="config"],
body.scope-visitor .m-tabbar .m-tab[data-view="transcripts"],
body.scope-visitor .m-tabbar .m-tab[data-view="topology"]{display:none !important}
body.scope-visitor .tb-right .metric{display:none !important}
body.scope-visitor #col-right,
body.scope-visitor #rc-toggle,
body.scope-visitor #m-open-right{display:none !important}
body.scope-visitor .shell{grid-template-columns:56px 0px 1fr 0px}
body.scope-visitor[data-view="home"] .shell{grid-template-columns:56px 0px 1fr 0px}
body.scope-visitor[data-view="home"] #col-left{display:none !important;width:0;overflow:hidden}
@media (max-width:900px){
  body.scope-visitor .shell{grid-template-columns:1fr !important}
  body.scope-visitor[data-view="home"] .shell{grid-template-columns:1fr !important}
}
/* Hide the composer/post box for visitors */
body.scope-visitor .compose-wrap,
body.scope-visitor .gc-compose,
body.scope-visitor .gpost-composer,
body.scope-visitor #compose-box{display:none !important}
/* Hide Settings/Session sections in quick menu for visitors */
body.scope-visitor [data-visitor-hide]{display:none !important}
/* Login prompt banner for visitors */
#visitor-login-banner{display:none;padding:16px 20px;background:linear-gradient(135deg,rgba(99,102,241,.12),rgba(34,217,230,.08));border:1px solid rgba(99,102,241,.25);border-radius:14px;margin:12px 16px;text-align:center}
body.scope-visitor #visitor-login-banner{display:block}
#visitor-login-banner .vlb-text{font:500 14px Inter,sans-serif;color:#c8d6e5;margin-bottom:10px}
#visitor-login-banner .vlb-btn{display:inline-block;padding:10px 28px;border-radius:10px;border:1px solid rgba(99,102,241,.5);background:rgba(99,102,241,.2);color:#c7d2fe;font:600 14px Inter,sans-serif;cursor:pointer;transition:all .2s}
#visitor-login-banner .vlb-btn:hover{background:rgba(99,102,241,.35);border-color:#6366f1}
/* Visitor login modal */
#visitor-login-modal{display:none;position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.65);backdrop-filter:blur(8px);align-items:center;justify-content:center}
#visitor-login-modal.active{display:flex}
#visitor-login-modal .vlm-card{background:#0f172a;border:1px solid rgba(99,102,241,.3);border-radius:18px;padding:32px;max-width:380px;width:90%;text-align:center;box-shadow:0 20px 60px rgba(0,0,0,.5)}
#visitor-login-modal .vlm-title{font:700 20px Inter,sans-serif;color:#e2e8f0;margin-bottom:8px}
#visitor-login-modal .vlm-sub{font:14px Inter,sans-serif;color:#94a3b8;margin-bottom:24px;line-height:1.5}
#visitor-login-modal .vlm-btn{display:block;width:100%;padding:14px;border-radius:12px;border:none;font:600 15px Inter,sans-serif;cursor:pointer;margin-bottom:10px;transition:all .2s}
#visitor-login-modal .vlm-login{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff}
#visitor-login-modal .vlm-login:hover{opacity:.9}
#visitor-login-modal .vlm-create{background:rgba(34,217,230,.15);color:#22d9e6;border:1px solid rgba(34,217,230,.3)}
#visitor-login-modal .vlm-create:hover{background:rgba(34,217,230,.25)}
#visitor-login-modal .vlm-close{background:transparent;color:#64748b;border:1px solid rgba(255,255,255,.08);margin-top:4px}
#visitor-login-modal .vlm-close:hover{color:#94a3b8;border-color:rgba(255,255,255,.15)}
#visitor-login-modal .vlm-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.ghome-tabs{display:flex;gap:0;border-bottom:2px solid rgba(255,255,255,.06);margin-bottom:12px;background:rgba(10,14,22,.8);backdrop-filter:blur(6px);position:sticky;top:0;z-index:5}
.ghome-tab{border:none;background:transparent;color:var(--muted);padding:10px 18px;font:600 13px Inter,sans-serif;cursor:pointer;border-bottom:3px solid transparent;display:flex;align-items:center;gap:6px;transition:color .15s,border-color .15s,background .15s}
.ghome-tab:hover{color:#e0e8f4;background:rgba(255,255,255,.03)}
.ghome-tab.on{color:var(--accent);border-bottom-color:var(--accent)}
.ghome-tab svg{opacity:.6}
.ghome-tab.on svg{opacity:1}
@media(max-width:900px){.ghome-tabs{display:none}}
/* v9.10.374 — the strip, once relocated into the topbar, must stop behaving like a
   sticky section header: no sticky, no own background/blur, no bottom border, no
   bottom margin. Purely presentational overrides on the SAME node, so every handler
   and the underline's data-active state survive the move. */
#topbar-tabs-mount .ghome-tabs{
  position:static;margin:0;border-bottom:none;background:transparent;backdrop-filter:none;z-index:auto;
}
#topbar-tabs-mount .ghome-tab{padding:6px 12px;font-size:12px}
#topbar-tabs-mount .ghome-underline{display:none}
/* v9.10.322 — Home header: Feed/Shorts swipe-pager tabs + a distinct Profile avatar button.
   "Me" left the equal-tab row and became this avatar button (top-right of the Home header). */
.ghome-topbar{display:flex;align-items:center;gap:10px}
.ghome-tabs{position:relative;display:flex;gap:2px;flex:0 0 auto}
.ghome-tabs .ghome-tab{flex:0 0 auto;min-width:78px;text-align:center;border-radius:8px 8px 0 0}
.ghome-underline{position:absolute;left:0;bottom:-2px;height:2px;width:50%;border-radius:2px;
  background:var(--accent);transition:transform .22s ease,opacity .15s;pointer-events:none}
.ghome-tabs[data-active="shorts"] .ghome-underline{transform:translateX(100%)}
.ghome-tabs[data-active="me"] .ghome-underline{opacity:0}
.ghome-plan{margin-left:auto;font-size:11px;color:var(--muted);white-space:nowrap}
.ghome-plan b{color:var(--accent)}
/* v9.10.327 — REQUEST 4: subtle 2-dot swipe pager indicator (replaces the removed Feed/Shorts tab bar) */
.ghome-pager-dots{display:flex;justify-content:center;gap:7px;padding:6px 0 4px}
.ghome-dot{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.22);transition:background .2s,transform .2s}
.ghome-pager-dots[data-active="feed"] .ghome-dot[data-dot="feed"],
.ghome-pager-dots[data-active="shorts"] .ghome-dot[data-dot="shorts"],
.ghome-pager-dots[data-active="me"] .ghome-dot[data-dot="me"]{background:var(--accent);transform:scale(1.25)}
/* v9.10.327 — REQUEST 4: tier verified badge overlaid on avatars (Twitter/YouTube-style) */
.gav-wrap{position:relative;display:inline-flex;flex:0 0 auto;vertical-align:middle}
.gtier-badge{position:absolute;right:8%;bottom:8%;border-radius:50%;display:flex;align-items:center;justify-content:center;
  box-shadow:0 0 0 2px var(--panel-solid,#0d1320);pointer-events:none}
.m-appbar .m-ab-btn.m-ab-profile.has-tier{overflow:visible}
/* v9.10.327 — REQUEST 2: reaction summary chips + tap-to-see-who list */
.gpost-rx{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:8px 0 0;cursor:pointer}
.gpost-rx-chip{display:inline-flex;align-items:center;gap:4px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);
  border-radius:999px;padding:3px 10px;font:500 12px var(--ui),sans-serif;color:#c5d0e0;line-height:1.6;transition:background .12s,border-color .12s;cursor:pointer}
.gpost-rx-chip:hover{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.16)}
.gpost-rx-chip img{width:15px;height:15px;object-fit:contain;vertical-align:middle}
.gpost-rx-more{font-size:11px;color:var(--muted);margin-left:2px}
.gpost-rx-who{margin-top:8px;background:rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.07);border-radius:10px;padding:0 10px;max-height:0;opacity:0;overflow:hidden;transition:max-height .2s ease,opacity .2s ease,padding .2s ease}
.gpost-rx-who.open{max-height:300px;opacity:1;padding:8px 10px}
.gpost-rx-who .rxw-grp{display:flex;gap:8px;align-items:flex-start;padding:4px 0;font-size:12.5px;color:#c5d0e0}
.gpost-rx-who .rxw-emote{flex:0 0 auto;white-space:nowrap}
.gpost-rx-who .rxw-emote img{width:16px;height:16px;object-fit:contain;vertical-align:middle}
.gpost-rx-who .rxw-names{color:#a9b6c8;word-break:break-word}
.gpost-emotes button img{width:18px;height:18px;object-fit:contain;vertical-align:middle}
.gpost-emote-add{border:1px dashed rgba(255,255,255,.28) !important;color:#9fb0c4 !important;font-size:14px !important;font-weight:700}
.ghome-profile-btn{flex:0 0 auto;padding:2px;border-radius:50%;line-height:0;cursor:pointer;display:inline-flex;
  border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.04);transition:border-color .15s,box-shadow .15s}
.ghome-profile-btn:hover{border-color:rgba(56,189,210,.6)}
.ghome-profile-btn.on{border-color:var(--accent);box-shadow:0 0 0 2px rgba(56,189,210,.3)}
.ghome-profile-btn img{display:block;border:none !important}
/* one-shot page-slide feedback when switching via swipe */
.ghome-swipe-l{animation:ghomeSlideL .2s ease}
.ghome-swipe-r{animation:ghomeSlideR .2s ease}
@keyframes ghomeSlideL{from{transform:translateX(26px);opacity:.45}to{transform:translateX(0);opacity:1}}
@keyframes ghomeSlideR{from{transform:translateX(-26px);opacity:.45}to{transform:translateX(0);opacity:1}}
body.scope-guest .gpost-acts button{color:#c5d0e0;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);border-radius:10px}
body.scope-guest .gpost-acts button.on,body.scope-guest .gpost-acts button:hover{
  color:#e8f7fb;background:rgba(56,189,210,.18);border-color:rgba(56,189,210,.4)}
body.scope-guest .gplace-card{background:rgba(20,28,42,.9);border-color:rgba(255,255,255,.08)}
body.scope-guest .guest-banner{background:linear-gradient(135deg,rgba(30,42,68,.55),rgba(40,30,70,.35));border-color:rgba(255,255,255,.1)}
/* In-app modal (never browser prompt) */
.gmodal-backdrop{display:none;position:fixed;inset:0;z-index:9000;background:rgba(4,8,16,.72);backdrop-filter:blur(6px);
  align-items:center;justify-content:center;padding:16px}
.gmodal-backdrop.open{display:flex}
.gmodal{width:min(440px,100%);max-height:min(88vh,640px);overflow:auto;background:#121a28;border:1px solid rgba(255,255,255,.12);
  border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.55);padding:18px 18px 14px;color:#e8eef8}
/* 2026-07-17: wide variant for content-rich modals (Settings → Plan & Usage) */
.gmodal.gm-lg{width:min(1320px,96vw);max-height:min(92vh,880px);padding:clamp(16px,2.2vw,26px)}
@media (max-width:640px){ .gmodal.gm-lg{width:100%;max-height:94vh} }
/* plan cards inside settings: horizontal scroll with snap on mobile */
#s2-plan-cards{-webkit-overflow-scrolling:touch;overflow-x:auto;scroll-snap-type:x proximity;padding-bottom:10px;scrollbar-width:thin;scrollbar-color:rgba(34,217,230,.3) transparent}
#s2-plan-cards::-webkit-scrollbar{height:6px}
#s2-plan-cards::-webkit-scrollbar-thumb{background:rgba(34,217,230,.3);border-radius:4px}
#s2-plan-cards .plan-tile{min-width:165px;max-width:210px;scroll-snap-align:start;flex:1 0 165px}
.s2-swipe-hint{display:none}
@media (max-width:640px){#s2-plan-cards{scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;padding-bottom:12px}
#s2-plan-cards .plan-tile{min-width:260px;flex:0 0 80vw}
#s2-plan-cards::after{content:'';flex:0 0 1px}
.s2-swipe-hint{display:block}}
.gmodal h3{margin:0 0 6px;font:800 16px Outfit,sans-serif;color:#eef3fb}
.gmodal .gm-sub{font-size:12px;color:#8b9bb0;margin:0 0 14px;line-height:1.45}
.gm-stab{border:none;background:transparent;color:var(--muted);padding:10px 14px;font:700 12px Outfit,sans-serif;cursor:pointer;border-bottom:3px solid transparent;transition:color .15s,border-color .15s;flex-shrink:0;white-space:nowrap}
#gm-set-tabs::-webkit-scrollbar{height:5px}
#gm-set-tabs::-webkit-scrollbar-thumb{background:rgba(34,217,230,.25);border-radius:4px}
.gm-srow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:11px 0;border-bottom:1px solid rgba(255,255,255,.05)}
.gm-srow .gm-sr-t{font-size:13px;color:#e0e8f4;font-weight:500}
.gm-srow .gm-sr-d{font-size:11px;color:var(--muted);margin-top:2px}
.gm-note{font-size:11px;color:var(--muted);margin:12px 0 0;line-height:1.5}
.gm-sw{position:relative;width:40px;height:22px;flex-shrink:0;border-radius:12px;background:rgba(255,255,255,.12);border:none;cursor:pointer;transition:background .2s}
.gm-sw::after{content:"";position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;transition:transform .2s}
.gm-sw.on{background:var(--accent)}
.gm-sw.on::after{transform:translateX(18px)}
.gm-stab:hover{color:#e0e8f4;background:rgba(255,255,255,.03)}
.gm-stab.on{color:var(--accent);border-bottom-color:var(--accent)}
/* 2026-07-18: per-category settings — left sub-nav + content pane */
.set2-wrap{display:flex;gap:0;margin:6px -22px -14px;min-height:min(62vh,560px)}
.set2-nav{width:210px;flex-shrink:0;border-right:1px solid rgba(255,255,255,.07);padding:8px 8px 14px;overflow-y:auto}
.set2-nav .s2-cat{font:700 10px Outfit,sans-serif;letter-spacing:.6px;text-transform:uppercase;color:#7b8aa0;padding:8px 10px 6px}
.set2-nav button{display:flex;align-items:center;gap:9px;width:100%;text-align:left;border:none;background:transparent;color:#c5d0e0;font:600 12.5px Outfit,sans-serif;padding:9px 10px;border-radius:9px;cursor:pointer;transition:background .12s,color .12s}
.set2-nav button:hover{background:rgba(255,255,255,.05);color:#fff}
.set2-nav button.on{background:rgba(34,217,230,.14);color:var(--accent)}
.set2-nav button .s2-ic{width:16px;text-align:center;flex-shrink:0}
.set2-body{flex:1;min-width:0;padding:6px 22px 18px;overflow-y:auto;overflow-x:hidden}
@media (max-width:640px){
  .set2-wrap{flex-direction:column;min-height:auto}
  .set2-nav{width:auto;border-right:none;border-bottom:1px solid rgba(255,255,255,.07);display:flex;flex-wrap:wrap;gap:4px;padding:6px;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .set2-nav .s2-cat{width:100%;padding:4px 6px 2px}
  .set2-nav button{width:auto;font-size:11px;padding:6px 8px}
  .set2-body{padding:8px 12px 14px}
}
/* ── Mobile responsive: settings, composer, feed, themes, frames ── */
@media (max-width:640px){
  /* Settings modal — near full screen on mobile */
  .gmodal-backdrop{padding:6px}
  .gmodal{width:100%;max-height:94vh;border-radius:12px;padding:14px 12px 12px}
  .gmodal.gm-lg{padding:10px;border-radius:12px}
  .gmodal h3{font-size:15px}
  /* Settings nav scrolls horizontally */
  .set2-nav{overflow-x:auto;-webkit-overflow-scrolling:touch;flex-wrap:nowrap;gap:2px;padding:4px 6px}
  .set2-nav button{white-space:nowrap;font-size:11px;padding:6px 8px;flex-shrink:0}
  .set2-body{padding:8px 10px 14px}
  /* Settings rows — let controls wrap below label on narrow */
  .set2-body [style*="justify-content:space-between"]{flex-wrap:wrap;gap:8px!important}
  /* Feed composer buttons wrap */
  .gpost-composer .gcomposer-opt{font-size:11px;padding:4px 8px}
  /* Theme grid cards 2-col */
  #s2-theme-grid{grid-template-columns:1fr 1fr!important}
  #s2-theme-grid > div{min-width:0!important}
  /* Frames grid 3-col */
  #s2-avatar-frames{grid-template-columns:repeat(3,1fr)!important}
  #s2-avatar-frames .s2-frame-pick{padding:8px 4px}
  /* Agent builder: avatar row stacks */
  #s2-ab-avatar-preview{width:64px!important;height:64px!important;border-radius:14px!important}
  /* Plan tiles swipe */
  .plan-tile{flex:0 0 80vw!important;min-width:0!important;max-width:none!important}
  .plan-grid{flex-wrap:nowrap!important;overflow-x:auto!important}
  /* Save bars wrap */
  .s2-savebar{flex-wrap:wrap}
  /* Summary card grids 2-col */
  [style*="repeat(auto-fit,minmax(130px"]{grid-template-columns:1fr 1fr!important}
  [style*="grid-template-columns:1fr 1fr 1fr"]{grid-template-columns:1fr 1fr!important}
  [style*="grid-template-columns:repeat(3,1fr)"]{grid-template-columns:1fr 1fr!important}
  /* Billing/payment stacks */
  [style*="gap:14px"][style*="align-items:center"][style*="border-radius:12px"]{flex-wrap:wrap}
  /* Poll inputs */
  #guest-post-poll input{font-size:12px}
  /* Costs vs Free grid stacks */
  [style*="grid-template-columns:1fr 1fr"][style*="margin-bottom:14px"]{grid-template-columns:1fr!important}
  /* Post card style grid */
  [style*="repeat(auto-fill,minmax(150px"]{grid-template-columns:1fr 1fr!important}
  /* Wizard progress bar text smaller */
  [id^="s2-ab-step"] [style*="gap:4px"] > div{min-width:0}
  [id^="s2-ab-step"] [style*="gap:4px"] > div > div:last-child{font-size:9px!important}
  /* Avatar seed style buttons wrap */
  [id^="s2-abs-"]{font-size:9px!important;padding:2px 5px!important}
  /* Color picker preset circles */
  [style*="border-radius:50%"][style*="width:18px"]{width:16px!important;height:16px!important}
  [style*="border-radius:50%"][style*="width:20px"]{width:16px!important;height:16px!important}
  /* Stripe checkout overlay narrower */
  #sim-checkout-ov > div{max-width:100%!important;margin:0 8px}
  /* Workspace Composer history panel */
  #ag-history-panel{top:30px!important}
  /* Composer Plan/Agent buttons smaller */
  #ag-mode-plan,#ag-mode-agent{font-size:9px!important;padding:2px 6px!important}
}
@media (max-width:400px){
  /* Very small phones (iPhone SE etc) */
  .gmodal-backdrop{padding:2px}
  .gmodal{border-radius:8px;padding:10px 8px 8px;max-height:96vh}
  .set2-nav button{font-size:9px;padding:4px 6px}
  .set2-body{padding:4px 8px 10px}
  #s2-theme-grid{grid-template-columns:1fr!important}
  #s2-avatar-frames{grid-template-columns:repeat(2,1fr)!important}
  .gmodal.gm-lg{padding:6px;border-radius:8px;max-height:96vh}
  .plan-tile{flex:0 0 85vw!important}
  /* Settings section headers smaller */
  .set2-body [style*="font:700 10px"]{font-size:9px!important}
  /* Agent builder avatar preview row stacks */
  [style*="display:flex"][style*="gap:16px"][style*="align-items:flex-start"]{flex-direction:column;align-items:center!important}
}
/* ── Quick Menu (left drawer opened by the Oracle OS logo) 2026-07-18 ── */
#quick-menu-backdrop{position:fixed;inset:0;z-index:6000;background:rgba(4,7,13,.5);backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);opacity:0;pointer-events:none;transition:opacity .28s ease}
body.qm-open #quick-menu-backdrop{opacity:1;pointer-events:auto}
#quick-menu{position:fixed;left:0;top:0;bottom:0;width:min(320px,86vw);z-index:6001;background:linear-gradient(180deg,#111a2b,#0b1220);border-right:1px solid rgba(34,217,230,.18);box-shadow:10px 0 46px rgba(0,0,0,.55);transform:translateX(-102%);transition:transform .32s cubic-bezier(.22,.61,.36,1);display:flex;flex-direction:column}
body.qm-open #quick-menu{transform:translateX(0)}
/* 2026-07-18: the Oracle OS logo is now the menu trigger — retire the old right-side ⟩ handle */
#rc-toggle{display:none !important}
/* Settings opens BESIDE the quick menu — offset into the free space on the right,
   menu stays open + clickable, no second dim (the quick-menu backdrop already dims). */
body.qm-panel #gmodal-backdrop{background:transparent !important;backdrop-filter:none !important;-webkit-backdrop-filter:none !important;justify-content:flex-start !important;padding-left:calc(min(320px,86vw) + 72px) !important;z-index:6001 !important;pointer-events:none}
body.qm-panel #gmodal{pointer-events:auto}
body.qm-panel #quick-menu{z-index:6002 !important}
@media (max-width:900px){ body.qm-panel #gmodal-backdrop{padding-left:0 !important;justify-content:center !important} }
/* 2026-07-18: notifications bell + panel */
body.scope-guest:not(.force-mobile) #tb-notif-wrap,body.scope-guest.force-desktop #tb-notif-wrap{display:block}
@media (max-width:900px){ body.scope-guest:not(.force-desktop) #tb-notif-wrap{display:none !important} }
#notif-panel{position:fixed;top:58px;right:14px;width:min(340px,92vw);max-height:min(70vh,460px);z-index:6500;background:linear-gradient(180deg,#111a2b,#0b1220);border:1px solid rgba(34,217,230,.18);border-radius:14px;box-shadow:0 18px 50px rgba(0,0,0,.55);display:none;flex-direction:column;overflow:hidden}
#notif-panel.open{display:flex;animation:npIn .16s ease}
@keyframes npIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
#notif-panel .np-head{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-bottom:1px solid rgba(255,255,255,.07);font:700 13px Outfit,sans-serif;color:#eef3fb}
#notif-panel .np-head button{border:none;background:transparent;color:var(--muted);cursor:pointer;font-size:15px}
#notif-panel .np-body{overflow-y:auto;padding:4px}
/* bottom-right notification toasts (fade out after a few seconds) */
#notif-toasts{position:fixed;right:16px;bottom:76px;z-index:7000;display:flex;flex-direction:column;gap:8px;pointer-events:none;max-width:340px}
.notif-toast{pointer-events:auto;background:linear-gradient(135deg,#111a2b,#0b1220);border:1px solid rgba(34,217,230,.28);border-radius:12px;padding:11px 14px;box-shadow:0 10px 34px rgba(0,0,0,.5);opacity:0;transform:translateX(24px);transition:opacity .3s ease,transform .3s ease;cursor:pointer}
.notif-toast.in{opacity:1;transform:none}
.notif-toast .nt-title{font:700 12.5px Outfit,sans-serif;color:#eef3fb}
.notif-toast .nt-body{font-size:11.5px;color:var(--muted);margin-top:3px}
.qm-head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0}
.qm-title{font:800 15px Outfit,sans-serif;color:#eef3fb;letter-spacing:.3px}
.qm-close{border:none;background:rgba(255,255,255,.05);color:var(--muted);width:30px;height:30px;border-radius:8px;cursor:pointer;font-size:14px;transition:background .15s}
.qm-close:hover{background:rgba(255,255,255,.1);color:#fff}
/* v9.10.400 (owner: "the chat side menu that pops up needs improved") — the Quick
   Menu stays a drawer; it was just loose and off-language. Three fixes, no
   destinations removed: (1) emoji glyphs -> drawn SVG line icons matching the
   header/nav set, (2) tighter vertical rhythm so the whole menu fits without
   scrolling, (3) each section is now a bounded card so GO TO vs SETTINGS read as
   distinct groups. Padding uses LONGHANDS. No `overflow` declaration added — the
   pre-existing .qm-scroll one is left exactly as it was. */
.qm-scroll{flex:1;overflow-y:auto;padding-top:8px;padding-right:10px;padding-bottom:18px;padding-left:10px}
.qm-sec{font:700 9.5px Outfit,sans-serif;color:var(--muted-2);letter-spacing:1px;text-transform:uppercase;padding-top:12px;padding-right:8px;padding-bottom:5px;padding-left:8px}
.qm-grp{background:rgba(255,255,255,.028);border:1px solid rgba(255,255,255,.05);border-radius:12px;padding-top:3px;padding-right:3px;padding-bottom:3px;padding-left:3px}
.qm-row{display:flex;align-items:center;gap:11px;width:100%;border:none;background:transparent;color:#d7e0ee;font:600 13.5px Outfit,sans-serif;padding-top:8.5px;padding-right:10px;padding-bottom:8.5px;padding-left:10px;border-radius:9px;cursor:pointer;text-align:left;transition:background .15s,transform .1s}
.qm-row:hover{background:rgba(34,217,230,.1);transform:translateX(3px)}
.qm-row .qm-ico{width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#7f92ab;transition:color .15s}
.qm-row .qm-ico svg{width:17px;height:17px;display:block}
.qm-row:hover .qm-ico{color:var(--accent)}
/* v9.10.405 — MESSAGING PAGE SPLIT (owner ask: the desktop pane was mostly dead space).
   Phone/base = single column, exactly as before. Desktop = list column + preview panel.
   No `overflow` declaration anywhere here: the list keeps scrolling inside .transcript's
   existing overflow-y, which is the container it already lived in. Padding LONGHANDS. */
/* v9.10.408 — on the Messaging PAGE the old left MESSAGES rail duplicates the list, so
   its grid track is collapsed to 0. Mirrors the existing `[data-view="home"]` pattern
   (same file, a few rules up) rather than inventing a new mechanism, and is scoped to
   desktop — on phones the rail is already a drawer and is never beside the list. */
@media (min-width:901px){
  body.scope-guest.msg-page:not(.force-mobile) .shell{grid-template-columns:56px 0px 1fr 0px}
  body.msg-page:not(.force-mobile) #col-left{display:none}
}
body.force-desktop.msg-page .shell{grid-template-columns:56px 0px 1fr 0px}
body.force-desktop.msg-page #col-left{display:none}
/* v9.10.408b — channels render twice (right panel on desktop, list foot on phones);
   exactly one is ever visible. Base = phone, so the list copy shows and the panel is
   already display:none from the .msgpane-side rule below. */
.msg-chan-m{display:block}
@media (min-width:901px){ .msg-chan-m{display:none} }
body.force-mobile .msg-chan-m{display:block}
body.force-desktop .msg-chan-m{display:none}
.msgpane{display:flex;flex-direction:column;width:100%;min-width:0}
.msgpane-list{width:100%;min-width:0}
.msgpane-side{display:none}
@media (min-width:901px){
  .msgpane{flex-direction:row;align-items:flex-start;gap:0}
  .msgpane-list{flex:0 0 560px;width:560px;border-right:1px solid rgba(148,163,184,.07)}
  .msgpane-side{display:block;flex:1 1 auto;min-width:0;align-self:stretch}
  .msgpane-side-inner{padding-top:22px;padding-right:26px;padding-bottom:22px;padding-left:26px;max-width:620px}
}
/* force-mobile mirror — a prior bug shipped a mobile block without its twin, so the
   forced-mobile layout must explicitly collapse back to the single column. */
body.force-mobile .msgpane{flex-direction:column}
body.force-mobile .msgpane-list{flex:1 1 auto;width:100%;border-right:none}
body.force-mobile .msgpane-side{display:none}
body.force-desktop .msgpane{flex-direction:row;align-items:flex-start}
body.force-desktop .msgpane-list{flex:0 0 560px;width:560px;border-right:1px solid rgba(148,163,184,.07)}
body.force-desktop .msgpane-side{display:block;flex:1 1 auto;min-width:0}
.qm-row.qm-danger{color:#f87171}
.qm-row.qm-danger .qm-ico{color:#f87171}
.qm-row.qm-danger:hover{background:rgba(248,113,113,.12)}
/* v9.10.345 — in-menu BACK button on the settings popup. Only on mobile (where the
   Quick-Menu closes to open settings); on desktop the menu stays open beside the
   panel so a Back control would be redundant. */
.s2-back{display:none;align-items:center;gap:4px;background:rgba(34,217,230,.12);border:1px solid rgba(34,217,230,.28);color:var(--accent);font:700 12px Outfit,sans-serif;padding:7px 12px;border-radius:9px;cursor:pointer;margin:0 0 10px}
.s2-back:hover{background:rgba(34,217,230,.2)}
@media(max-width:900px){ .s2-back{display:inline-flex} }
body.force-mobile .s2-back{display:inline-flex}
.brand{cursor:pointer;user-select:none}
.brand:hover .logo{box-shadow:0 0 0 2px rgba(34,217,230,.4)}
.gm-ucard{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.06);border-radius:10px;padding:12px 10px;text-align:center}
.gm-uval{font:700 20px Outfit,sans-serif;color:#eef3fb}
.gm-ulbl{font-size:11px;color:var(--muted);margin-top:2px}
.gmodal label{display:block;font-size:11px;font-weight:700;color:#8b9bb0;margin:10px 0 4px;letter-spacing:.4px;text-transform:uppercase}
.gmodal input,.gmodal textarea,.gmodal select{width:100%;box-sizing:border-box;border-radius:10px;border:1px solid rgba(255,255,255,.12);
  background:rgba(0,0,0,.35);color:#e8eef8;padding:10px 12px;font:13px/1.4 Inter,sans-serif;outline:none}
.gmodal input:focus,.gmodal textarea:focus,.gmodal select:focus{border-color:rgba(56,189,210,.55)}
.gmodal textarea{min-height:72px;resize:vertical}
.gmodal .gm-acts{display:flex;gap:8px;justify-content:flex-end;margin-top:16px;flex-wrap:wrap}
.gmodal .gm-acts button{border-radius:10px;padding:9px 14px;font:700 12px Outfit,sans-serif;cursor:pointer}
.gmodal .gm-msg{font-size:12px;color:#8b9bb0;margin-top:8px;min-height:1.2em}
/* Guest right-rail diversify cards */
.grf-card{background:rgba(16,22,36,.9);border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:12px 14px}
.grf-card .grf-h{font:700 10px Outfit,sans-serif;letter-spacing:1px;text-transform:uppercase;color:#8b9bb0;margin-bottom:8px}
.grf-card .grf-row{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.05);cursor:pointer;color:#e8eef8;background:none;border-left:none;border-right:none;border-top:none;width:100%;text-align:left}
.grf-card .grf-row:last-child{border-bottom:none}
.grf-card .grf-row:hover{color:#7dd3e8}
.grf-card .grf-av{width:32px;height:32px;border-radius:50%;object-fit:cover;background:#1a2233;flex-shrink:0}
/* Unread badge on mobile Chats tab */
.m-tab .m-tab-badge{position:absolute;top:4px;right:calc(50% - 22px);min-width:14px;height:14px;padding:0 4px;border-radius:8px;
  background:#f43f5e;color:#fff;font:700 9px Outfit,sans-serif;display:none;align-items:center;justify-content:center;line-height:1}
.m-tab{position:relative}
.m-tab .m-tab-badge.on{display:inline-flex}
/* Social profile (Me) — FB-style, soft on eyes */
.gprof{max-width:920px;margin:0 auto;position:relative;z-index:1}
/* Steam-style themed shell: page bg color + optional theme image + cover + showcase */
.gprof-theme-shell{position:relative;border-radius:16px;overflow:hidden;padding:0 0 12px;
  background:var(--gprof-theme-bg,#0a0e16);border:1px solid rgba(255,255,255,.06);
  box-shadow:0 12px 40px rgba(0,0,0,.35)}
.gprof-theme-shell::before{content:'';position:absolute;inset:0;background-image:var(--gprof-theme-img,none) !important;
  background-size:cover !important;background-position:center center !important;background-repeat:no-repeat !important;background-attachment:fixed !important;opacity:var(--gprof-theme-opacity,.42);pointer-events:none;z-index:0;
  filter:none}
/* v9.10.543 — readability scrim over the profile background image. UNIFORM (not a bottom-heavy
   gradient): the shell now wraps the whole profile (header + tabs + body), so a gradient dumped
   maximum darkness on the body and it read as a black "inside area". A flat tint keeps the image
   / colour consistent top-to-bottom. Darkness is driven by the user's Dim slider
   (--gprof-theme-scrim); with no image it defaults low so a picked colour shows near-true. */
.gprof-theme-shell::after{content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background:rgba(0,0,0,var(--gprof-theme-scrim,.12))}
.gprof-theme-shell > *{position:relative;z-index:1}
.gprof-theme-shell .guest-card{background:rgba(10,14,22,.78);backdrop-filter:blur(8px);border-color:rgba(255,255,255,.08)}
.gprof-cover{height:220px;border-radius:16px 16px 0 0;background:linear-gradient(135deg,#1a2744 0%,#0d3a4a 45%,#1a1540 100%);
  background-size:cover;background-position:center;position:relative;overflow:hidden;border:1px solid var(--border);border-bottom:none;
  cursor:pointer}
.gprof-cover.has-img{background-color:#111}
.gprof-cover:hover .gprof-cover-btn{background:rgba(0,0,0,.75);border-color:rgba(34,217,230,.45)}
.gprof-cover-btn{position:absolute;bottom:12px;right:16px;display:flex;gap:6px;align-items:center;
  background:rgba(0,0,0,.55);padding:7px 14px;border-radius:8px;font-size:12px;color:#fff;cursor:pointer;
  backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.12);font-weight:600}
.gprof-showcase-wrap{margin-top:10px}
.gprof-showcase-label{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:#8899aa;margin-bottom:6px;font-weight:700}
.gprof-showcase{display:flex;flex-wrap:wrap;gap:8px;align-items:center;min-height:28px}
.gprof-showcase .gb-chip{display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border-radius:999px;
  border:1px solid rgba(34,217,230,.35);background:rgba(34,217,230,.12);font-size:12px;color:#e8eef8;font-weight:600;
  box-shadow:0 2px 8px rgba(0,0,0,.25)}
.gprof-showcase .gb-chip .gb-ic{font-size:16px;line-height:1}
.gprof-showcase .gb-empty{font-size:12px;color:#7a8a9c;cursor:pointer}
.gprof-showcase .gb-empty:hover{color:var(--accent)}
.gprof-theme-presets{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px}
.gprof-theme-presets button{width:32px;height:32px;border-radius:8px;border:2px solid rgba(255,255,255,.15);cursor:pointer;padding:0}
.gprof-theme-presets button.on{border-color:var(--accent);box-shadow:0 0 0 2px rgba(34,217,230,.35)}
/* v9.10.544 — the Background Image presets are TEXT pills (None, Nebula, Neon Grid, Aurora,
   Night City, Lattice), not colour swatches, so they must NOT inherit the 32x32 square sizing
   above — that crushed the labels into tiny boxes so only a few were legible. Let them size to
   their text and wrap to the next line. */
#gm-appbg-presets button,#gm-themeimg-presets button{width:auto;height:auto;min-height:30px;padding:6px 12px;border-radius:8px;
  border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.05);color:#cdd6e4;
  font:600 11.5px Outfit,sans-serif;white-space:nowrap;line-height:1}
#gm-appbg-presets button:hover,#gm-themeimg-presets button:hover{background:rgba(255,255,255,.1);color:#eef3fb}
#gm-appbg-presets button.on,#gm-themeimg-presets button.on{border-color:var(--accent);color:var(--accent);background:rgba(34,217,230,.12);box-shadow:none}
.gprof-theme-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.gprof-theme-row input[type=color]{width:44px;height:36px;padding:2px;border:1px solid var(--border);border-radius:8px;
  background:transparent;cursor:pointer}
.gprof-theme-preview{height:72px;border-radius:10px;border:1px solid var(--border);margin:10px 0 4px;position:relative;overflow:hidden;
  background:#0a0e16}
.gprof-theme-preview .pv-cover{height:36px;background:linear-gradient(135deg,#1a2744,#0d3a4a)}
.gprof-theme-preview .pv-label{position:absolute;bottom:6px;left:10px;font-size:10px;color:#c5d0e0;font-weight:600}
.gprof-badge-pick{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:8px;max-height:200px;overflow:auto;margin-top:8px}
.gprof-badge-pick label{display:flex;align-items:center;gap:6px;padding:8px;border-radius:10px;border:1px solid var(--border);
  background:rgba(0,0,0,.25);font-size:11px;color:#c5d0e0;cursor:pointer}
.gprof-badge-pick label.on{border-color:var(--accent);background:rgba(34,217,230,.1)}
.gprof-badge-pick input{accent-color:var(--accent)}
.gprof-head{display:flex;flex-wrap:wrap;gap:16px;align-items:flex-end;padding:0 24px 16px;margin-top:-64px;position:relative}
.gprof-av{width:148px;height:148px;border-radius:50%;border:5px solid #0a0e16;background:#111;object-fit:cover;box-shadow:0 8px 24px rgba(0,0,0,.5);cursor:pointer;transition:filter .2s}
.gprof-av:hover{filter:brightness(1.1)}
/* ── Avatar Shapes (v9.10.545) ── */
.av-shape-circle{border-radius:50%!important}
.av-shape-square{border-radius:8px!important}
.av-shape-roundsq{border-radius:22%!important}
.av-shape-hexagon{clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%)!important;border-radius:0!important;border:none!important}
.av-shape-diamond{clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%)!important;border-radius:0!important;border:none!important}
.av-shape-shield{clip-path:polygon(50% 0%,100% 10%,100% 65%,50% 100%,0% 65%,0% 10%)!important;border-radius:0!important;border:none!important}
.av-shape-octagon{clip-path:polygon(30% 0%,70% 0%,100% 30%,100% 70%,70% 100%,30% 100%,0% 70%,0% 30%)!important;border-radius:0!important;border:none!important}
.av-shape-star{clip-path:polygon(50% 0%,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%)!important;border-radius:0!important;border:none!important}
.av-shape-heart{clip-path:polygon(50% 18%,55% 10%,63% 3%,74% 0%,84% 2%,92% 8%,97% 18%,100% 30%,98% 42%,90% 55%,78% 68%,65% 79%,50% 92%,35% 79%,22% 68%,10% 55%,2% 42%,0% 30%,3% 18%,8% 8%,16% 2%,26% 0%,37% 3%,45% 10%,50% 18%)!important;border-radius:0!important;border:none!important}
.av-shape-drop{clip-path:polygon(50% 0%,85% 35%,100% 65%,85% 85%,50% 100%,15% 85%,0% 65%,15% 35%)!important;border-radius:0!important;border:none!important}
.av-shape-cross{clip-path:polygon(35% 0%,65% 0%,65% 35%,100% 35%,100% 65%,65% 65%,65% 100%,35% 100%,35% 65%,0% 65%,0% 35%,35% 35%)!important;border-radius:0!important;border:none!important}
.av-shape-flower{clip-path:polygon(50% 0%,65% 15%,85% 5%,80% 28%,100% 35%,82% 50%,100% 65%,80% 72%,85% 95%,65% 85%,50% 100%,35% 85%,15% 95%,20% 72%,0% 65%,18% 50%,0% 35%,20% 28%,15% 5%,35% 15%)!important;border-radius:0!important;border:none!important}
.av-shape-clover{clip-path:polygon(50% 38%,62% 18%,75% 5%,90% 8%,95% 22%,82% 38%,100% 50%,82% 62%,95% 78%,90% 92%,75% 95%,62% 82%,50% 100%,38% 82%,25% 95%,10% 92%,5% 78%,18% 62%,0% 50%,18% 38%,5% 22%,10% 8%,25% 5%,38% 18%)!important;border-radius:0!important;border:none!important}
/* Clip-path shapes need a wrapper for the border effect */
.av-shape-wrap{position:relative;display:inline-block}
.av-shape-wrap::before{content:'';position:absolute;inset:-5px;background:var(--accent,#22d9e6);z-index:-1}
.av-shape-hexagon+.av-shape-wrap::before,.av-shape-wrap.hex::before{clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%)}
/* ── Player Card Frame Glow Tiers ── */
.pcard-glow-6{box-shadow:0 0 12px rgba(34,217,230,.15)}
.pcard-glow-11{box-shadow:0 0 20px rgba(99,102,241,.25),0 0 40px rgba(99,102,241,.1)}
.pcard-glow-16{box-shadow:0 0 24px rgba(251,191,36,.3),0 0 50px rgba(251,191,36,.12)}
.pcard-glow-21{box-shadow:0 0 28px rgba(239,68,68,.3),0 0 60px rgba(239,68,68,.12),inset 0 0 20px rgba(239,68,68,.05)}
/* ── XP Progress Bar ── */
.xp-bar-wrap{height:6px;background:rgba(255,255,255,.08);border-radius:3px;overflow:hidden;flex:1}
.xp-bar-fill{height:100%;background:linear-gradient(90deg,var(--accent,#22d9e6),#6366f1);border-radius:3px;transition:width .4s ease}
.gprof-id{flex:1;min-width:160px;padding-bottom:4px;padding-top:16px}
.gprof-id h1{margin:0;font:800 26px Outfit,sans-serif;color:#eef3fb}
.gprof-id .gh{color:var(--accent);font-size:13px;margin-top:2px}
.gprof-id .bio{color:#c5d0e0;font-size:14px;line-height:1.5;margin-top:8px;max-width:480px}
.gprof-highlights{display:flex;gap:6px;flex-wrap:wrap;padding:2px 24px 0;font-size:13px;color:#a0acbf}
.gprof-highlights .gph-item{display:flex;align-items:center;gap:5px}
.gprof-highlights .gph-item svg{width:14px;height:14px;fill:currentColor;opacity:.6}
.gprof-highlights .gph-sep{color:rgba(255,255,255,.15);margin:0 2px}
.gprof-stats{display:flex;gap:18px;padding:10px 24px;font-size:12px;color:var(--muted)}
.gprof-stats b{color:#e8eef8;font-size:14px;display:block}
.gprof-divider{border:none;border-top:1px solid rgba(255,255,255,.06);margin:0 24px}
.gprof-tabs{display:flex;gap:0;padding:0 12px;border-bottom:2px solid rgba(255,255,255,.06);flex-wrap:wrap;position:sticky;top:56px;z-index:2;background:rgba(10,14,22,.82);backdrop-filter:blur(8px)}
.gprof-tabs button{border:none;background:transparent;color:var(--muted);padding:12px 16px;font:700 13px Outfit,sans-serif;cursor:pointer;border-bottom:3px solid transparent;transition:color .15s,border-color .15s}
.gprof-tabs button:hover{color:#e0e8f4;background:rgba(255,255,255,.04)}
.gprof-tabs button.on{color:var(--accent);border-bottom-color:var(--accent)}
.gprof-body{display:grid;grid-template-columns:1fr;gap:14px;padding:14px 0}
@media (min-width:900px){
  .gprof-body{grid-template-columns:280px minmax(0,1fr)}
}
/* v9.10.543 — a touch more translucent + blur so the profile background image/colour is sensed
   through the inside cards too (owner: "i need the added option for the inside area for image").
   Text stays crisp thanks to the backdrop blur inherited from .gprof-theme-shell .guest-card. */
.gprof-side .guest-card,.gprof-main .guest-card{background:rgba(16,22,36,.74);backdrop-filter:blur(9px)}
/* Soft place cards (Me map) — no eye-burn cyan bars */
.gplace-card{display:block;width:100%;text-align:left;margin:0 0 8px;padding:12px 14px;border-radius:12px;cursor:pointer;
  border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.03);color:#e8eef8;transition:border-color .15s,background .15s}
.gplace-card:hover{border-color:rgba(34,217,230,.35);background:rgba(34,217,230,.06)}
.gplace-title{font:700 13px Outfit,sans-serif;color:#e8eef8}
.gplace-sub{font-size:11px;color:#8b9bb0;margin-top:3px;line-height:1.4}
/* Call + video header buttons */
#ch-videobtn{display:none}
#ch-callbtn,#ch-videobtn{align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;
  border:1px solid rgba(34,217,230,.35);background:rgba(34,217,230,.1);color:var(--accent);cursor:pointer}
#ch-callbtn:hover,#ch-videobtn:hover{background:rgba(34,217,230,.22)}
/* ══ CALL OVERLAY — voice/video calling UI ══════════════════════════════════ */
#call-overlay{position:fixed;inset:0;z-index:9500;display:none;align-items:center;justify-content:center;background:rgba(4,8,18,.92);backdrop-filter:blur(18px);flex-direction:column}
#call-overlay.active{display:flex}
/* v9.10.910 — minimized call = compact floating pill (Messenger-style). The call
   keeps running (streams/audio/timer untouched); only the UI shrinks. */
#call-overlay.minimized{inset:auto;right:14px;bottom:calc(84px + env(safe-area-inset-bottom,0px));width:auto;max-width:min(88vw,280px);height:auto;padding:9px 12px;border-radius:18px;border:1px solid rgba(34,217,230,.30);box-shadow:0 14px 44px rgba(0,0,0,.6);background:rgba(9,15,26,.98);backdrop-filter:blur(20px);flex-direction:row;align-items:center;gap:10px;cursor:grab;touch-action:none}
#call-overlay.minimized:active{cursor:grabbing}
#call-overlay.minimized .call-flip-btn,#call-overlay.minimized #call-min-btn,#call-overlay.minimized .call-status,#call-overlay.minimized .call-signal,#call-overlay.minimized .call-participants,#call-overlay.minimized .call-add-panel,#call-overlay.minimized .call-settings-panel,#call-overlay.minimized .call-device-picker,#call-overlay.minimized .call-video-container{display:none !important}
#call-overlay.minimized .call-peer-card{flex-direction:row;align-items:center;gap:9px;padding:0;margin:0}
#call-overlay.minimized .call-peer-avatar{width:42px;height:42px;min-width:42px;font-size:16px;border-width:2px;margin:0}
#call-overlay.minimized .call-peer-name{font-size:14px;margin:0;max-width:110px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#call-overlay.minimized .call-timer{display:block !important;font-size:11px;margin:2px 0 0}
#call-overlay.minimized .call-controls{padding:0;margin:0;gap:8px;width:auto;background:none;flex-wrap:nowrap}
#call-overlay.minimized .call-controls .call-ctrl{width:40px;height:40px}
#call-overlay.minimized .call-ctrl.mic-switch,#call-overlay.minimized .call-ctrl.cam,#call-overlay.minimized .call-ctrl.speaker,#call-overlay.minimized .call-ctrl.screen,#call-overlay.minimized .call-ctrl.add,#call-overlay.minimized .call-ctrl.answer{display:none !important}
/* the minimize button in the normal full-screen call view */
.call-min-btn{position:absolute;top:calc(14px + env(safe-area-inset-top,0px));left:14px;width:40px;height:40px;border-radius:50%;border:none;background:rgba(255,255,255,.10);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:7;transition:background .15s}
.call-min-btn:hover{background:rgba(255,255,255,.18)}
#call-overlay:not(.active) .call-min-btn,#call-overlay.incoming .call-min-btn{display:none}
.call-status{font:600 13px Outfit,sans-serif;color:var(--muted);letter-spacing:.5px;text-transform:uppercase;margin-bottom:12px}
.call-peer-card{display:flex;flex-direction:column;align-items:center;gap:14px;padding:30px}
.call-peer-avatar{width:120px;height:120px;border-radius:50%;border:3px solid rgba(34,217,230,.4);overflow:hidden;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;font:800 42px Outfit,sans-serif;color:#e8eef8}
.call-peer-avatar img{width:100%;height:100%;object-fit:cover}
.call-peer-name{font:700 22px Outfit,sans-serif;color:#eef3fb}
.call-timer{font:500 14px 'JetBrains Mono',monospace;color:var(--muted);margin-top:4px}
/* Signal strength indicator */
.call-signal{display:flex;align-items:center;gap:6px;margin-top:6px}
.csig-bars{display:flex;align-items:flex-end;gap:2px;height:16px}
.csig-bars span{display:block;width:4px;border-radius:1px;background:rgba(255,255,255,.15);transition:height .3s,background .3s}
.csig-bars span:nth-child(1){height:4px}
.csig-bars span:nth-child(2){height:7px}
.csig-bars span:nth-child(3){height:10px}
.csig-bars span:nth-child(4){height:13px}
.csig-bars span:nth-child(5){height:16px}
.csig-bars.sig-5 span{background:#22c55e}
.csig-bars.sig-4 span:nth-child(-n+4){background:#22c55e}
.csig-bars.sig-3 span:nth-child(-n+3){background:#eab308}
.csig-bars.sig-2 span:nth-child(-n+2){background:#f97316}
.csig-bars.sig-1 span:nth-child(1){background:#ef4444}
.csig-bars.sig-0 span{background:rgba(255,255,255,.1)}
.csig-label{font:500 10px 'JetBrains Mono',monospace;color:var(--muted)}
@keyframes callPulse{0%,100%{box-shadow:0 0 0 0 rgba(34,217,230,.4)}50%{box-shadow:0 0 0 18px rgba(34,217,230,0)}}
.call-ringing .call-peer-avatar{animation:callPulse 2s ease infinite}
.call-controls{display:flex;gap:14px;align-items:center;padding:18px 24px}
.call-ctrl{width:48px;height:48px;border-radius:50%;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,transform .1s;color:#fff}
.call-ctrl:hover{transform:scale(1.08)}
.call-ctrl.end{background:#dc2626}
.call-ctrl.end:hover{background:#ef4444}
.call-ctrl.mute{background:rgba(255,255,255,.12)}
.call-ctrl.mute.active{background:#f59e0b;color:#000}
.call-ctrl.cam{background:rgba(255,255,255,.12)}
.call-ctrl.cam.active{background:#3b82f6}
.call-ctrl.add{background:rgba(255,255,255,.12)}
.call-ctrl.mic-switch{background:rgba(255,255,255,.08)}
.call-device-picker{position:absolute;bottom:70px;left:50%;transform:translateX(-50%);
  background:rgba(13,19,32,.97);border:1px solid rgba(99,102,241,.2);border-radius:12px;
  padding:6px 0;min-width:240px;max-width:320px;box-shadow:0 12px 40px rgba(0,0,0,.6);z-index:10;
  backdrop-filter:blur(12px)}
.call-device-picker .cdp-item{display:block;width:100%;border:none;background:none;color:#c8d6e5;
  font:12px Outfit,sans-serif;padding:10px 16px;cursor:pointer;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.call-device-picker .cdp-item:hover{background:rgba(99,102,241,.15)}
.call-device-picker .cdp-item.active{color:var(--accent,#22d9e6);font-weight:600}
/* mic-switch stays visible on all sizes — flex-wrap on .call-controls handles overflow */
/* Add people panel */
.call-add-panel{position:absolute;top:12px;left:12px;width:min(300px,85vw);max-height:70vh;
  background:rgba(13,19,32,.97);border:1px solid rgba(99,102,241,.2);border-radius:14px;
  box-shadow:0 16px 48px rgba(0,0,0,.6);z-index:10;overflow:hidden;display:flex;flex-direction:column;
  backdrop-filter:blur(12px)}
.cap-head{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-bottom:1px solid rgba(255,255,255,.06)}
.cap-title{font:700 14px Outfit,sans-serif;color:#eef3fb}
.cap-close{border:none;background:none;color:#64748b;font-size:20px;cursor:pointer;padding:2px 6px}
.call-add-panel input{margin:10px 12px;padding:9px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.1);
  background:rgba(255,255,255,.05);color:#e2e8f0;font:12px Outfit,sans-serif;outline:none}
.cap-list{flex:1;overflow-y:auto;padding:4px 0}
.cap-item{display:flex;align-items:center;gap:10px;padding:8px 14px;cursor:pointer;transition:background .1s}
.cap-item:hover{background:rgba(99,102,241,.12)}
.cap-item .cap-av{width:32px;height:32px;border-radius:50%;overflow:hidden;flex-shrink:0;background:#1a2236;
  display:flex;align-items:center;justify-content:center;font-size:14px}
.cap-item .cap-av img{width:100%;height:100%;object-fit:cover}
.cap-item .cap-name{font:600 12px Outfit,sans-serif;color:#e2e8f0}
.cap-item .cap-role{font:10px Outfit,sans-serif;color:var(--muted)}
.cap-item .cap-badge{font:600 9px Outfit,sans-serif;padding:2px 6px;border-radius:4px;margin-left:auto}
.cap-item .cap-badge.ai{background:rgba(99,102,241,.15);color:#a5b4fc}
.cap-item .cap-badge.human{background:rgba(34,197,94,.15);color:#4ade80}
.cap-item .cap-badge.in-call{background:rgba(251,191,36,.15);color:#fbbf24}
.cap-in-call{border-top:1px solid rgba(255,255,255,.06);padding:8px 14px}
.cap-in-call .cap-label{font:700 9px Outfit,sans-serif;letter-spacing:.6px;text-transform:uppercase;color:var(--muted-2);margin-bottom:6px}
/* Call participants strip */
.call-participants{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:10px}
.call-participant{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:56px}
.call-participant .cp-av{width:clamp(32px,8vw,44px);height:clamp(32px,8vw,44px);border-radius:50%;overflow:hidden;border:2px solid var(--accent-glow,rgba(34,217,230,.3));
  display:flex;align-items:center;justify-content:center;background:#1a2236;font-size:18px}
.call-participant .cp-av img{width:100%;height:100%;object-fit:cover}
.call-participant .cp-av.speaking{border-color:var(--accent,#22d9e6);box-shadow:0 0 12px var(--accent-glow,rgba(34,217,230,.3));animation:cp-pulse .8s ease-in-out infinite alternate}
.call-participant .cp-name{font:600 10px Outfit,sans-serif;color:#c8d6e5;max-width:64px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@keyframes cp-pulse{0%{box-shadow:0 0 8px var(--accent-glow)}100%{box-shadow:0 0 20px var(--accent-glow)}}
/* Voice room thinking indicator */
.thinking{animation:vr-think 1s ease-in-out infinite alternate!important}
@keyframes vr-think{from{box-shadow:0 0 8px rgba(251,191,36,.2)}to{box-shadow:0 0 20px rgba(251,191,36,.4)}}
.call-ctrl.speaker{background:rgba(255,255,255,.08)}
.call-ctrl.speaker.active{background:var(--accent-glow,rgba(34,217,230,.2));color:var(--accent,#22d9e6)}
.call-video-container{position:relative;width:100%;flex:1;background:#000;border-radius:14px;overflow:hidden;min-height:200px}
.call-video-container video.remote{width:100%;height:100%;object-fit:cover}
.call-video-container .self-pip{position:absolute;bottom:12px;right:12px;width:160px;height:120px;border-radius:12px;overflow:hidden;border:2px solid var(--accent-glow,rgba(34,217,230,.35));cursor:move;z-index:2;background:#111;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.call-video-container .self-pip video{width:100%;height:100%;object-fit:cover}
/* screen-share mode: screen fills the container, remote cam is a small PIP top-right */
.call-video-container .remote-cam-pip{position:absolute;top:12px;right:12px;width:180px;height:135px;border-radius:10px;overflow:hidden;border:2px solid rgba(34,217,230,.35);z-index:3;background:#111;display:none}
.call-video-container .remote-cam-pip video{width:100%;height:100%;object-fit:cover}
.call-video-container.screen-share-mode{max-width:1100px;aspect-ratio:auto;height:70vh}
.call-video-container.screen-share-mode video.remote{object-fit:contain}
/* incoming call banner */
.call-incoming{position:fixed;top:70px;right:18px;z-index:9600;background:linear-gradient(135deg,#111a2b,#0b1220);border:1px solid rgba(34,217,230,.35);border-radius:16px;padding:16px 20px;box-shadow:0 12px 40px rgba(0,0,0,.5);display:flex;align-items:center;gap:14px;animation:slideInRight .3s ease;max-width:calc(100vw - 36px)}
@keyframes slideInRight{from{opacity:0;transform:translateX(30px)}to{opacity:1;transform:none}}
.call-incoming .ci-avatar{width:48px;height:48px;border-radius:50%;overflow:hidden;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;font:700 18px Outfit,sans-serif;color:#e8eef8;flex-shrink:0}
.call-incoming .ci-avatar img{width:100%;height:100%;object-fit:cover}
.call-incoming .ci-info{flex:1}
.call-incoming .ci-name{font:700 14px Outfit,sans-serif;color:#eef3fb}
.call-incoming .ci-sub{font-size:11px;color:var(--muted);margin-top:2px}
.call-incoming .ci-btns{display:flex;gap:8px}
.call-incoming .ci-btn{width:40px;height:40px;border-radius:50%;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .1s}
.call-incoming .ci-btn:hover{transform:scale(1.1)}
.call-incoming .ci-btn.accept{background:#22c55e;color:#fff}
.call-incoming .ci-btn.decline{background:#dc2626;color:#fff}
/* call settings panel */
.call-settings-panel{position:absolute;bottom:80px;right:20px;width:280px;background:linear-gradient(180deg,#111a2b,#0b1220);border:1px solid rgba(34,217,230,.2);border-radius:14px;padding:16px;z-index:2;box-shadow:0 12px 40px rgba(0,0,0,.5);display:none}
.call-settings-panel.open{display:block}
.call-settings-panel .cs-title{font:700 13px Outfit,sans-serif;color:#eef3fb;margin-bottom:12px}
.call-settings-panel label{display:block;font-size:11.5px;color:var(--muted);margin-bottom:4px;margin-top:10px}
.call-settings-panel select{width:100%;padding:7px 10px;border-radius:8px;border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.06);color:#e8eef8;font-size:12px;outline:none;appearance:none;-webkit-appearance:none}
.call-settings-panel select option{background:#111a2b;color:#e8eef8;padding:6px}
/* ── v9.10.424 — CALL-SETTINGS TRAP FIX ───────────────────────────────────────
   Owner: "when I call someone ... and I go in the settings I can't tap to get out
   of the settings, it glitches so I have to close the app and reopen the app."
   REAL CAUSE (measured, not guessed): .call-settings-panel is
   position:absolute;bottom:80px;right:20px;z-index:2 while .call-controls was a
   STATIC flex item with no position and no z-index. #call-overlay is a centred
   flex column, so on a phone-height viewport the centred controls row lands at
   roughly y 470-560 while the ~225px-tall panel spans roughly y 476-700 — the
   positioned panel painted straight OVER the gear button, and the gear was the
   only thing that could close it (no close button, no Escape, no outside-tap, no
   back handler existed). Desktop never reproduced it: at 1080px tall the controls
   sit ~620-710 and the panel ~776-1000, so they never touch. That is why this only
   bit on mobile.
   Three independent guarantees now, so no single failure can trap the user again:
   1. the controls always paint ABOVE the panel and stay tappable,
   2. on short/narrow viewports the panel moves off the controls entirely,
   3. the panel has its own close button (plus Escape / outside-tap / back, in JS).
   NOTE: no `overflow` is set anywhere here on purpose — the panel holds three
   selects and is never tall enough to need scrolling, and one axis of overflow
   would create a scroll container (the bug that froze the feed once). */
.call-controls{position:relative;z-index:6}
.call-settings-panel{z-index:5}
/* ── v9.10.427 — CALL LAYOUT: remote on top, self below, control BAR at bottom ─
   Owner: "the call stuff should be at the bottom and the user I'm calling on top
   and I'm on bottom. plus we need a bar for voice/video."
   BEFORE: #call-overlay centred its column, and .call-video-container was a
   max-width:800px; aspect-ratio:16/9 box — so on a 360px-wide phone it rendered a
   ~360x203 letterboxed strip floating in the vertical middle with huge black bands
   above and below, the self-view as a small PiP over the remote person's face, and
   the control row sitting mid-screen directly under the strip.
   AFTER: the stage fills the screen, the remote fills the top, the self-view is
   its own tile underneath it, and the controls are a real bar pinned to the bottom.
   HOW THE BAR IS PINNED WITHOUT position:fixed: #call-overlay is already a flex
   column, so `margin-top:auto` on .call-controls pushes it to the bottom edge —
   no new fixed positioning anywhere (hard constraint), and no `overflow` either. */
.call-controls{margin-top:auto;width:100%;justify-content:center;flex-wrap:wrap;row-gap:10px;background:linear-gradient(180deg,rgba(8,14,26,0),rgba(8,14,26,.85));padding-bottom:calc(18px + env(safe-area-inset-bottom,0px))}
/* ── the 360px arithmetic (the clipped-gear bug) ─────────────────────────────
   The connected-call row is mute+cam+end+screen+add(48px each) + settings(36px).
   OLD: 48*5 + 36 + gaps(5*14=70) + padding(24*2=48) = 394px > 360px viewport, so
   the LAST control — the gear — was pushed off the right edge and could not be
   tapped at all. Not a scroll problem; the row was simply wider than the phone.
   NEW at <=430px: 42*5 + 34 + gaps(5*8=40) + padding(10*2=20) = 304px, which fits
   360px with 56px to spare and still fits a 320px iPhone SE. flex-wrap is belt-and
   -braces: if a future button is added the row wraps to a second line instead of
   ever putting a control out of reach again. */
/* ── 600px intermediate breakpoint — mid-size phones ──────────────────────── */
@media (max-width:600px){
  .call-ctrl{width:44px;height:44px}
  .call-participant .cp-av{width:36px;height:36px;font-size:15px}
  .call-peer-avatar{width:100px;height:100px;font:800 36px Outfit,sans-serif}
}
/* ── landscape / short viewport — prevent overflow ────────────────────────── */
@media (max-height:500px) and (orientation:landscape){
  .call-peer-card{padding:12px 20px;gap:8px}
  .call-peer-avatar{width:64px;height:64px;font:800 24px Outfit,sans-serif}
  .call-peer-name{font-size:16px}
  .call-controls{padding-top:6px;padding-bottom:calc(6px + env(safe-area-inset-bottom,0px))}
}
@media (max-width:430px){
  .call-controls{gap:8px;padding-left:10px;padding-right:10px;padding-top:12px}
  .call-ctrl{width:42px;height:42px}
  .call-ctrl.settings{width:34px;height:34px}
  /* remote fills the top, self-view becomes its own tile beneath it */
  .call-video-container{flex:1 1 auto;width:100%;max-width:none;aspect-ratio:auto;height:auto;min-height:0;border-radius:12px;margin-top:6px}
  .call-video-container video.remote{width:100%;height:100%;object-fit:cover;border-radius:10px}
  .call-video-container .self-pip{position:absolute;bottom:10px;right:10px;width:100px;height:75px;border-radius:10px}
  /* voice calls: keep the peer card comfortably in the upper area, not dead centre */
  #call-overlay.active .call-peer-card{padding-top:40px;padding-bottom:20px}
}
body.force-mobile .call-controls{gap:8px;padding-left:10px;padding-right:10px;padding-top:12px}
body.force-mobile .call-ctrl{width:42px;height:42px}
body.force-mobile .call-ctrl.settings{width:34px;height:34px}
body.force-mobile .call-video-container{flex:1 1 auto;width:100%;max-width:none;aspect-ratio:auto;height:auto;min-height:0;border-radius:12px;margin-top:6px}
body.force-mobile .call-video-container video.remote{width:100%;height:100%;object-fit:cover;border-radius:10px}
body.force-mobile .call-video-container .self-pip{position:absolute;bottom:10px;right:10px;width:100px;height:75px;border-radius:10px}
/* ── v9.10.427 — FLIP CAMERA, top-right, where the owner asked for it ──────── */
.call-flip-btn{position:absolute;top:calc(14px + env(safe-area-inset-top,0px));right:14px;z-index:7;width:40px;height:40px;border:none;border-radius:50%;cursor:pointer;background:rgba(255,255,255,.14);color:#e8eef8;display:none;align-items:center;justify-content:center}
.call-flip-btn:hover{background:rgba(255,255,255,.24)}
#call-overlay.active.has-cam .call-flip-btn{display:flex}
#call-overlay.incoming .call-flip-btn{display:none}
/* v9.10.437 - AI CALL, asymmetric video. An agent has no camera, so the remote
   <video> in an AI call would render as a black rectangle - which reads as "broken
   call", not "this participant has no camera". In .aicall-video the remote element
   is hidden and OUR self preview fills the tile instead; the agent is represented by
   the peer card above it (avatar + the existing pulse cue when it speaks). Scoped
   entirely under #call-overlay.aicall-video so no human call can ever match it.
   Adds no scroll-clipping property (the base .self-pip rule already clips) and no
   fixed positioning - the two rules below are display + box sizing only. */
#call-overlay.aicall-video .call-video-container video.remote{display:none}
/* AI call: self camera is the main stage (agent has no camera) — make it LARGE */
#call-overlay.aicall-video .call-video-container{
  flex:1 1 auto;width:min(96vw,920px);max-width:none;aspect-ratio:auto;min-height:42vh;
  height:auto;display:flex;flex-direction:column;margin:8px auto 0;border-radius:16px
}
#call-overlay.aicall-video .call-video-container .self-pip,
#call-overlay.aicall-video .call-video-container .self-pip.aicall-self-large{
  position:static;width:100%;flex:1 1 auto;min-height:38vh;height:100%;
  border-radius:14px;cursor:default;border:2px solid rgba(34,217,230,.35)
}
#call-overlay.aicall-video .call-video-container .self-pip video{
  width:100%;height:100%;object-fit:cover;transform:scaleX(-1) /* mirror selfie */
}
/* Human call PiP — bigger than 140×105 so you can actually see yourself */
.call-video-container .self-pip{width:min(42vw,220px);height:min(32vw,165px)}
@media (max-width:430px){
  #call-overlay.aicall-video .call-video-container{min-height:48vh;width:100%;max-width:none;margin-top:4px}
  #call-overlay.aicall-video .call-video-container .self-pip{min-height:44vh}
  .call-video-container .self-pip{flex:0 0 38% !important}
}
/* screen-share unavailable (mobile browsers have no getDisplayMedia) */
.call-ctrl.screen.unavailable{opacity:.4;cursor:not-allowed}
/* ── v9.10.425 — INCOMING-CALL MODE ───────────────────────────────────────────
   Owner: "when I call user they should get the same layout pop up when I call but
   a green answer button instead of the red button that I have."
   So the incoming screen REUSES #call-overlay verbatim — same centred avatar,
   name, status and control row the caller sees — and just swaps which controls
   are visible. No second layout, no new positioning, and because #call-overlay is
   already position:fixed;inset:0;z-index:9500 it covers whatever view the
   recipient happens to be on, which is what makes an incoming call app-global. */
.call-ctrl.answer{display:none;background:#22c55e}
.call-ctrl.answer:hover{background:#16a34a}
#call-overlay.incoming .call-ctrl.answer{display:flex}
#call-overlay.incoming .call-ctrl.mute,
#call-overlay.incoming .call-ctrl.cam,
#call-overlay.incoming .call-ctrl.screen,
#call-overlay.incoming .call-ctrl.add,
#call-overlay.incoming .call-ctrl.settings{display:none}
/* the red button beside the green one is DECLINE while ringing in */
#call-overlay.incoming .call-ctrl.end{background:#dc2626}
.cs-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}
.cs-head .cs-title{margin-bottom:0}
.cs-close{flex:none;width:32px;height:32px;border:none;border-radius:50%;cursor:pointer;background:rgba(255,255,255,.1);color:#e8eef8;font:700 15px Outfit,sans-serif;line-height:32px;padding-top:0;padding-right:0;padding-bottom:0;padding-left:0}
.cs-close:hover{background:rgba(255,255,255,.2)}
@media (max-width:900px),(max-height:820px){
  /* move the panel to the TOP of the call overlay — the centred peer card and the
     controls both live in the lower half, so nothing interactive is underneath. */
  .call-settings-panel{bottom:auto;top:calc(64px + env(safe-area-inset-top,0px));right:12px;left:12px;width:auto}
}
/* force-mobile mirror (a prior bug shipped a mobile block without its twin) */
body.force-mobile .call-settings-panel{bottom:auto;top:calc(64px + env(safe-area-inset-top,0px));right:12px;left:12px;width:auto}
.call-ctrl.screen{background:rgba(255,255,255,.12)}
.call-ctrl.screen.active{background:#8b5cf6}
/* ══ RADIO STATION UI ══════════════════════════════════════════════════════ */
/* v9.10.501 — Radio redesign: Pandora-style 3-view layout */
.radio-station{display:flex;flex-direction:column;min-height:100%;background:linear-gradient(180deg,#0a0e18,#0c1222)}
/* When inside .transcript, radio fills it and the transcript handles scroll */
.transcript:has(.radio-station){padding:0 !important;gap:0 !important;overflow-y:auto;-webkit-overflow-scrolling:touch}
.radio-header{display:flex;align-items:center;gap:12px;padding:14px 18px;background:rgba(0,0,0,.3);border-bottom:1px solid rgba(148,163,184,.1);flex-shrink:0}
.radio-header .radio-logo{width:42px;height:42px;border-radius:12px;background:linear-gradient(135deg,var(--accent,#22d9e6),var(--accent-2,#0ea5b8));display:flex;align-items:center;justify-content:center;font-size:20px;box-shadow:0 0 20px var(--accent-glow,rgba(34,217,230,.3))}
.radio-header .radio-info{flex:1;min-width:0}
.radio-header .radio-name{font:700 16px Outfit,sans-serif;color:#eef3fb}
.radio-header .radio-sub{font:11px Outfit,sans-serif;color:var(--muted)}
.radio-body{display:flex;flex:1;min-height:0;overflow:hidden}
.radio-main{flex:1;display:flex;flex-direction:column;min-width:0}
.radio-player{flex-shrink:0;background:rgba(0,0,0,.2);border-bottom:1px solid rgba(148,163,184,.08)}
.radio-player .rp-now{display:flex;align-items:center;gap:14px;padding:14px 18px}
.radio-player .rp-art{width:72px;height:72px;border-radius:10px;background:rgba(99,102,241,.15);display:flex;align-items:center;justify-content:center;font-size:32px;overflow:hidden;flex-shrink:0;box-shadow:0 4px 20px rgba(0,0,0,.4)}
.radio-player .rp-art img{width:100%;height:100%;object-fit:cover}
.radio-player .rp-meta{flex:1;min-width:0}
.radio-player .rp-title{font:700 15px Outfit,sans-serif;color:#eef3fb;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.radio-player .rp-artist{font:12px Outfit,sans-serif;color:var(--muted);margin-top:2px}
.radio-player .rp-tag{font:600 9px Outfit,sans-serif;color:#a78bfa;background:rgba(167,139,250,.12);padding:2px 7px;border-radius:4px;margin-top:4px;display:inline-block;letter-spacing:.3px}
.radio-video{height:clamp(200px,40vh,400px);flex-shrink:0;background:#000;display:flex;align-items:center;justify-content:center;position:relative}
.radio-video iframe{width:100%;height:100%;border:none}
.radio-video .rv-placeholder{color:var(--muted);font:13px Outfit,sans-serif;text-align:center;padding:20px}
.radio-lyrics{padding:14px 18px;max-height:120px;overflow-y:auto;font:13px Outfit,sans-serif;color:var(--muted);line-height:1.7;border-top:1px solid rgba(148,163,184,.06);flex-shrink:0;white-space:pre-wrap}
.radio-sidebar{width:300px;display:flex;flex-direction:column;border-left:1px solid rgba(148,163,184,.08);flex-shrink:0;background:rgba(0,0,0,.15);overflow-y:auto}
/* Saved songs section */
.radio-saved{padding:8px 12px;border-top:1px solid rgba(148,163,184,.08);flex-shrink:0}
.radio-saved .rs-title{font:700 10px Outfit,sans-serif;letter-spacing:.6px;text-transform:uppercase;color:var(--muted-2);margin-bottom:6px}
.radio-saved .rs-item{display:flex;align-items:center;gap:8px;padding:4px 0;font:12px Outfit,sans-serif;color:#c8d6e5}
.radio-saved .rs-item button{border:none;background:rgba(255,255,255,.06);color:var(--muted);padding:3px 8px;border-radius:5px;font-size:10px;cursor:pointer}
.radio-chat{flex:1;display:flex;flex-direction:column;min-height:0}
.radio-chat-msgs{flex:1;overflow-y:auto;padding:10px 12px;display:flex;flex-direction:column;gap:6px;-webkit-overflow-scrolling:touch}
.radio-chat-msg{font:12.5px Outfit,sans-serif;color:#c8d6e5;line-height:1.4}
.radio-chat-msg .rcm-name{font-weight:700;margin-right:6px}
.radio-chat-msg.rcm-dj{background:rgba(99,102,241,.08);border-radius:8px;padding:6px 8px}
.radio-chat-msg.rcm-dj .rcm-name{color:#a78bfa}
.radio-chat-msg.rcm-user .rcm-name{color:var(--accent)}
.radio-chat-msg.rcm-system{color:var(--muted);font-size:11px;font-style:italic}
.radio-chat-input{display:flex;gap:8px;padding:8px 12px;border-top:1px solid rgba(148,163,184,.08);flex-shrink:0}
.radio-chat-input input{flex:1;padding:8px 12px;border-radius:8px;border:1px solid rgba(148,163,184,.12);background:rgba(255,255,255,.04);color:#e2e8f0;font:12px Outfit,sans-serif;outline:none}
.radio-chat-input button{padding:8px 14px;border-radius:8px;border:none;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font:600 11px Outfit,sans-serif;cursor:pointer;flex-shrink:0}
.radio-queue{border-top:1px solid rgba(148,163,184,.08);max-height:180px;overflow-y:auto;padding:8px 12px;flex-shrink:0}
.radio-queue .rq-title{font:700 10px Outfit,sans-serif;letter-spacing:.6px;text-transform:uppercase;color:var(--muted-2);margin-bottom:6px}
.radio-queue .rq-item{display:flex;align-items:center;gap:8px;padding:5px 0;font:12px Outfit,sans-serif;color:#c8d6e5;border-bottom:1px solid rgba(255,255,255,.03)}
.radio-queue .rq-item .rq-num{color:var(--muted-2);font-size:10px;width:16px;text-align:center}
.radio-queue .rq-item .rq-by{color:var(--muted);font-size:10px;margin-left:auto}
.radio-listeners{padding:8px 12px;border-top:1px solid rgba(148,163,184,.08);flex-shrink:0;font:11px Outfit,sans-serif;color:var(--muted)}
/* v9.10.501 — Pandora-style navigation tabs */
.radio-nav{display:flex;gap:0;padding:0 18px;border-bottom:1px solid rgba(148,163,184,.1);flex-shrink:0;background:rgba(0,0,0,.2)}
.radio-nav-btn{border:none;background:transparent;color:var(--muted);padding:12px 16px;font:600 12px Outfit,sans-serif;
  cursor:pointer;border-bottom:2px solid transparent;transition:color .15s,border-color .15s;white-space:nowrap}
.radio-nav-btn:hover{color:#e0e8f4}
.radio-nav-btn.on{color:#fff;border-bottom-color:var(--accent,#22d9e6)}
.radio-nav-btn .rnb-dot{width:6px;height:6px;border-radius:50%;background:#6366f1;display:inline-block;margin-left:4px;vertical-align:middle}
/* Radio view panes */
.radio-pane{display:none;flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;min-height:0}
.radio-pane.on{display:flex;flex-direction:column}
/* Now Playing view — large centered artwork */
.rnp-center{display:flex;flex-direction:column;align-items:center;padding:28px 18px 18px;flex:1}
.rnp-art{width:220px;height:220px;border-radius:14px;overflow:hidden;box-shadow:0 16px 48px rgba(0,0,0,.55);margin-bottom:20px;flex-shrink:0}
.rnp-art img{width:100%;height:100%;object-fit:cover}
.rnp-title{font:700 20px Outfit,sans-serif;color:#eef3fb;text-align:center;line-height:1.3;word-break:break-word;max-width:360px}
.rnp-artist{font:13px Outfit,sans-serif;color:var(--muted);margin-top:4px;text-align:center}
.rnp-album{font:11px Outfit,sans-serif;color:var(--muted-2);margin-top:2px;text-align:center}
/* Mode chips (like Pandora's station filters) */
.rnp-modes{display:flex;flex-wrap:wrap;gap:6px;margin-top:16px;justify-content:center}
.rnp-mode{padding:6px 14px;border-radius:999px;border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.04);
  color:var(--muted);font:600 11px Outfit,sans-serif;cursor:pointer;transition:all .15s}
.rnp-mode:hover{background:rgba(99,102,241,.12);color:#c7d2fe;border-color:rgba(99,102,241,.3)}
.rnp-mode.on{background:rgba(99,102,241,.2);color:#fff;border-color:rgba(99,102,241,.5)}
/* Transport controls */
/* ── Radio search dropdown ── */
.rsearch-wrap{position:relative}
.rsearch-wrap input{width:280px;padding:10px 16px;border-radius:12px;border:1px solid rgba(148,163,184,.15);
  background:rgba(255,255,255,.06);color:#e2e8f0;font:13px Outfit,sans-serif;outline:none;transition:border-color .15s,width .2s}
.rsearch-wrap input:focus{border-color:rgba(99,102,241,.5);background:rgba(255,255,255,.1);width:340px}
.rsearch-drop{display:none;position:absolute;top:100%;left:0;right:0;margin-top:6px;min-width:280px;width:100%;
  max-height:420px;overflow-y:auto;background:rgba(13,19,32,.97);border:1px solid rgba(99,102,241,.2);
  border-radius:14px;box-shadow:0 16px 48px rgba(0,0,0,.6);z-index:100;padding:6px 0;
  backdrop-filter:blur(12px)}
.rsearch-label{font:700 9px Outfit,sans-serif;letter-spacing:.8px;text-transform:uppercase;
  color:var(--muted-2);padding:8px 14px 4px}
.rsearch-item{display:flex;align-items:center;gap:10px;padding:8px 14px;cursor:pointer;transition:background .1s}
.rsearch-item:hover{background:rgba(99,102,241,.12)}
.rsearch-thumb{width:44px;height:33px;border-radius:6px;overflow:hidden;flex-shrink:0;background:#111;
  display:flex;align-items:center;justify-content:center;font-size:14px}
.rsearch-thumb img{width:100%;height:100%;object-fit:cover}
.rsearch-meta{flex:1;min-width:0;overflow:hidden}
.rsearch-title{font:600 12px Outfit,sans-serif;color:#e2e8f0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rsearch-sub{font:10px Outfit,sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rsearch-dur{font:10px JetBrains Mono,monospace;color:var(--muted-2);flex-shrink:0}
@media(max-width:600px){.radio-header .rsearch-wrap input{width:140px}.radio-header .rsearch-wrap input:focus{width:180px}}
/* old .rnp-btn removed — replaced by .rnp-act-btn */
/* removed: .rnp-btn.play — replaced by .rnp-act-btn.rnp-play */
.rnp-btn-gone{display:none;/* placeholder */
  box-shadow:0 8px 28px rgba(99,102,241,.45)}
.rnp-btn.play:hover{box-shadow:0 10px 32px rgba(99,102,241,.55)}
/* Station sidebar */
.rnp-stations{width:220px;flex-shrink:0;border-right:1px solid rgba(148,163,184,.08);overflow-y:auto;padding:12px}
.rnp-st-item{display:flex;align-items:center;gap:9px;padding:8px;border-radius:10px;cursor:pointer;transition:background .12s;margin-bottom:2px}
.rnp-st-item:hover{background:rgba(255,255,255,.05)}
.rnp-st-item.on{background:rgba(99,102,241,.12)}
.rnp-st-item img{width:42px;height:42px;border-radius:8px;object-fit:cover;background:#111;flex-shrink:0}
.rnp-st-item .rst-name{font:600 11px Outfit,sans-serif;color:#e0e8f4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* My Collection view */
.rcol-section{padding:18px}
.rcol-section .rcol-h{font:700 16px Outfit,sans-serif;color:#eef3fb;margin-bottom:14px}
.rcol-grid{display:flex;gap:12px;overflow-x:auto;padding-bottom:8px;scrollbar-width:none;-webkit-overflow-scrolling:touch;flex-wrap:wrap}
.rcol-grid::-webkit-scrollbar{display:none}
/* All Songs — organized wrapping grid with larger cards */
.rcol-allsongs-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px;padding-bottom:8px}
.rcol-song-card{display:flex;align-items:center;gap:12px;padding:8px;border-radius:12px;cursor:pointer;
  background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.04);transition:all .15s}
.rcol-song-card:hover{background:rgba(99,102,241,.08);border-color:rgba(99,102,241,.2);transform:translateY(-1px)}
.rcol-song-card.rcol-song-on{background:rgba(99,102,241,.12);border-color:rgba(99,102,241,.3)}
.rcol-song-thumb{width:56px;height:56px;border-radius:10px;overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center;position:relative}
.rcol-song-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.rcol-song-playing{position:absolute;inset:0;background:rgba(99,102,241,.4);display:flex;align-items:center;justify-content:center;font-size:18px;color:#fff;border-radius:10px}
.rcol-song-info{flex:1;min-width:0;overflow:hidden}
.rcol-song-title{font:600 13px Outfit,sans-serif;color:#e0e8f4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rcol-song-artist{font:11px Outfit,sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
.rcol-song-artist span{font-size:9px;margin-left:4px}
@media(max-width:600px){.rcol-allsongs-grid{grid-template-columns:1fr}.rcol-song-thumb{width:48px;height:48px}}
.rcol-card{flex:0 0 auto;width:140px;cursor:pointer;transition:transform .15s}
.rcol-card:hover{transform:translateY(-3px)}
.rcol-card img{width:140px;height:140px;border-radius:10px;object-fit:cover;background:#111;display:block}
.rcol-card .rcol-title{font:600 12px Outfit,sans-serif;color:#e0e8f4;margin-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rcol-card .rcol-sub{font:11px Outfit,sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Browse view */
.rbrowse-row{display:flex;gap:14px;overflow-x:auto;padding:0 18px 14px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.rbrowse-row::-webkit-scrollbar{display:none}
.rbrowse-circle{flex:0 0 auto;width:96px;text-align:center;cursor:pointer}
.rbrowse-circle img{width:80px;height:80px;border-radius:50%;object-fit:cover;background:#111;border:2px solid rgba(255,255,255,.08);transition:border-color .15s,transform .15s}
.rbrowse-circle:hover img{border-color:rgba(99,102,241,.4);transform:scale(1.05)}
.rbrowse-circle .rbr-name{font:500 10px Outfit,sans-serif;color:var(--muted);margin-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rbrowse-genre{flex:0 0 auto;width:160px;height:90px;border-radius:10px;overflow:hidden;position:relative;cursor:pointer}
.rbrowse-genre img{width:100%;height:100%;object-fit:cover}
.rbrowse-genre .rbg-label{position:absolute;bottom:0;left:0;right:0;padding:8px 10px;background:linear-gradient(transparent,rgba(0,0,0,.8));
  font:700 13px Outfit,sans-serif;color:#fff}
/* Persistent player bar (bottom) */
.radio-bar{display:flex;flex-direction:column;align-items:stretch;padding:0;border-top:1px solid rgba(148,163,184,.12);
  background:rgba(6,10,18,.95);backdrop-filter:blur(12px);flex-shrink:0}
.rb-top{display:flex;align-items:center;gap:10px;padding:6px 16px}
.radio-bar .rb-art{width:38px;height:38px;border-radius:8px;overflow:hidden;flex-shrink:0;background:#111}
.radio-bar .rb-art img{width:100%;height:100%;object-fit:cover}
.radio-bar .rb-meta{min-width:0;flex-shrink:1;max-width:180px}
.radio-bar .rb-title{font:600 12px Outfit,sans-serif;color:#eef3fb;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.radio-bar .rb-artist{font:10px Outfit,sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.radio-bar .rb-btn{border:none;background:none;color:var(--muted);cursor:pointer;width:36px;height:36px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;font-size:18px;transition:color .15s,background .15s}
.radio-bar .rb-btn:hover{color:#fff;background:rgba(255,255,255,.08)}
.radio-bar .rb-btn.rb-play{background:linear-gradient(135deg,var(--accent,#22d9e6),var(--accent-2,#0ea5b8));color:#fff;width:40px;height:40px;font-size:18px;
  box-shadow:0 4px 14px rgba(99,102,241,.35)}
.radio-bar .rb-progress{flex:1;height:3px;background:rgba(255,255,255,.08);border-radius:2px;min-width:60px;cursor:pointer;position:relative}
.radio-bar .rb-progress-fill{height:100%;background:linear-gradient(90deg,#6366f1,#8b5cf6);border-radius:2px;transition:width .3s}
/* ── KAI Watch (v9.10.506): themed frame around a VISIBLE YouTube player ── */
#radio-pane-watch{padding-bottom:14px}
/* ── Now Playing: animated neon background ── */
.rnp-bg{position:absolute;inset:0;z-index:0;overflow:hidden;background:var(--panel,#06080e)}
.rnp-bg-art{position:absolute;inset:-20%;width:140%;height:140%;object-fit:cover;filter:blur(60px) brightness(.15) saturate(1.8);opacity:.7}
.rnp-bg-canvas{position:absolute;inset:0;width:100%;height:100%;opacity:.6}
/* rnp-float keyframes removed — background is now canvas-driven */
/* Art container with ring visualizer */
.rnp-art-wrap{position:relative;width:280px;height:280px;flex-shrink:0}
.rnp-vis-ring{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:150%;height:150%;pointer-events:none;z-index:0}
.rnp-art-inner{position:absolute;inset:17%;border-radius:18px;overflow:hidden;z-index:1;
  box-shadow:0 0 30px var(--accent-glow,rgba(34,217,230,.2)),0 16px 48px rgba(0,0,0,.5);
  transition:transform .12s ease-out,box-shadow .15s ease-out;will-change:transform}
/* Title/artist in NP */
.rnp-title{font:700 20px Outfit,sans-serif;color:#fff;text-shadow:0 2px 10px rgba(0,0,0,.5);text-align:center;line-height:1.3;word-break:break-word;max-width:360px}
.rnp-artist{font:13px Outfit,sans-serif;color:rgba(255,255,255,.6);margin-top:4px;text-align:center;text-shadow:0 1px 4px rgba(0,0,0,.3)}
/* Transport controls in Now Playing center */
.rnp-transport{display:flex;align-items:center;gap:14px;margin-top:18px}
.rnp-act-btn{border:none;background:rgba(255,255,255,.08);color:rgba(255,255,255,.6);width:44px;height:44px;
  border-radius:50%;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;
  transition:all .15s;backdrop-filter:blur(8px)}
.rnp-act-btn:hover{background:rgba(255,255,255,.15);color:#fff;transform:scale(1.1)}
.rnp-volume{display:flex;align-items:center;gap:8px;margin-top:10px;justify-content:center}
.rnp-vol-slider{-webkit-appearance:none;appearance:none;height:4px;border-radius:2px;background:rgba(255,255,255,.15);outline:none;width:100px;cursor:pointer}
.rnp-vol-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;border-radius:50%;background:#22d3ee;cursor:pointer}
.rnp-vol-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;background:#22d3ee;cursor:pointer;border:none}
.rnp-act-btn.rnp-play{width:58px;height:58px;font-size:22px;background:linear-gradient(135deg,var(--accent,#22d9e6),var(--accent-2,#0ea5b8));
  color:#fff;box-shadow:0 8px 28px var(--accent-glow,rgba(34,217,230,.3))}
.rnp-act-btn.rnp-play:hover{transform:scale(1.08);box-shadow:0 10px 36px var(--accent-glow,rgba(34,217,230,.45))}
/* Radio Mode toggle pill */
.radio-mode-toggle{border:1px solid rgba(148,163,184,.2);background:rgba(255,255,255,.06);color:rgba(255,255,255,.5);
  padding:8px 16px;border-radius:20px;font:600 12px Outfit,sans-serif;cursor:pointer;
  transition:all .2s;white-space:nowrap}
.radio-mode-toggle:hover{background:rgba(99,102,241,.15);color:rgba(255,255,255,.8);border-color:rgba(99,102,241,.3)}
.radio-mode-toggle.on{background:linear-gradient(135deg,rgba(99,102,241,.25),rgba(139,92,246,.25));
  color:#c4b5fd;border-color:rgba(99,102,241,.5);box-shadow:0 0 16px rgba(99,102,241,.25),0 0 4px rgba(139,92,246,.3)}
/* Station label */
.radio-station-label{font:600 11px Outfit,sans-serif;color:#a5b4fc;text-transform:uppercase;letter-spacing:.8px;
  margin-top:12px;padding:6px 14px;border-radius:12px;background:rgba(99,102,241,.1);
  border:1px solid rgba(99,102,241,.15);text-align:center;max-width:320px}
/* v9.10.563 — playback-source line + toggle states.
   The transport used to give no feedback at all: shuffle had no button in the
   main player, repeat/shuffle showed their state only as an inline colour, and
   nothing on screen told you whether the next track would come from your own
   list or from a station. These make the player's actual state legible. */
.radio-station-label{display:inline-flex;align-items:center;gap:8px;text-transform:none;letter-spacing:.3px}
.radio-src-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto}
.radio-src-station .radio-src-dot{background:#8b5cf6;box-shadow:0 0 8px rgba(139,92,246,.8);
  animation:radioSrcPulse 2s ease-in-out infinite}
.radio-src-playlist{color:rgba(255,255,255,.55);background:rgba(255,255,255,.05);
  border-color:rgba(255,255,255,.08)}
.radio-src-playlist .radio-src-dot{background:#34d399}
.radio-src-sub{color:rgba(255,255,255,.4);font-weight:400}
@keyframes radioSrcPulse{0%,100%{opacity:1}50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){
  .radio-src-station .radio-src-dot{animation:none}
}
/* Active states for the toggle buttons (shuffle / repeat / love). Previously
   these were inline `style="color:..."` with no background or border change, so
   on a phone it was genuinely hard to tell whether shuffle was on. */
.rnp-act-btn.on,.radio-bar .rb-btn.on{color:#c4b5fd;background:rgba(99,102,241,.22);
  box-shadow:inset 0 0 0 1px rgba(139,92,246,.45)}
.rnp-act-btn.on-love,.radio-bar .rb-btn.on-love{color:#f87171;background:rgba(239,68,68,.16);
  box-shadow:inset 0 0 0 1px rgba(239,68,68,.4)}
.rnp-act-btn sup,.radio-bar .rb-btn sup{font-size:9px;margin-left:1px;vertical-align:super}
/* Keyboard focus was invisible on these round buttons. */
.rnp-act-btn:focus-visible,.radio-bar .rb-btn:focus-visible,.radio-mode-toggle:focus-visible{
  outline:2px solid var(--accent,#22d9e6);outline-offset:2px}
/* Auto-queue items in Up Next */
.radio-autoq-item{border-left:2px solid rgba(139,92,246,.4)}
.radio-autoq-item:hover{border-left-color:#8b5cf6}
/* Up Next sidebar */
.rnp-upnext{width:300px;flex-shrink:0;border-left:1px solid rgba(255,255,255,.06);overflow-y:auto;padding:14px 14px}
.rbrowse-card{cursor:pointer;transition:transform .15s,box-shadow .15s}
.rbrowse-card:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.4)}
/* Netflix-style browse category rows */
/* Browse search bar */
.rbrowse-search-bar{display:flex;gap:8px;padding:12px 18px 8px;align-items:center}
.rbrowse-search-bar input{width:100%;padding:11px 16px;border-radius:12px;border:1px solid rgba(148,163,184,.18);background:rgba(255,255,255,.06);color:#e2e8f0;font:13px Outfit,sans-serif;outline:none;box-sizing:border-box}
.rbrowse-search-bar input:focus{border-color:rgba(99,102,241,.5);background:rgba(255,255,255,.08)}
.rbrowse-search-btn{padding:10px 12px;border-radius:12px;border:none;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:16px;cursor:pointer;flex-shrink:0;line-height:1;display:flex;align-items:center;justify-content:center}
/* Genre pills row — removed v9.10.510 */
.rbrowse-empty{text-align:center;padding:64px 24px}
/* Playlist modal */
.rpl-modal-bg{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:9999;display:flex;align-items:center;justify-content:center;padding:16px;backdrop-filter:blur(4px)}
.rpl-modal{background:rgba(15,20,35,.97);border:1px solid rgba(99,102,241,.2);border-radius:18px;padding:24px;width:min(440px,100%);max-height:80vh;overflow-y:auto;box-shadow:0 24px 64px rgba(0,0,0,.7)}
.rpl-modal-h{font:700 18px Outfit,sans-serif;color:#eef3fb;margin-bottom:14px}
.rpl-song-row{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:8px;transition:background .1s;font:12px Outfit,sans-serif;color:#e0e8f4}
.rpl-song-row:hover{background:rgba(99,102,241,.1)}
.rpl-song-row.rpl-done{opacity:.4}
.rpl-song-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rpl-song-src{font:10px Outfit,sans-serif;color:var(--muted);flex-shrink:0}
.rpl-cb{accent-color:#6366f1;flex-shrink:0}
.rpl-btn-primary{padding:10px 20px;border-radius:10px;border:none;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font:700 12px Outfit,sans-serif;cursor:pointer}
.rpl-btn-secondary{padding:10px 20px;border-radius:10px;border:1px solid rgba(148,163,184,.2);background:rgba(255,255,255,.04);color:var(--muted);font:600 12px Outfit,sans-serif;cursor:pointer}
/* Playlist card — big clickable tile */
.rpl-card{display:flex;align-items:center;gap:14px;padding:10px 14px;border-radius:14px;cursor:pointer;
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.06);transition:all .15s;min-width:220px;flex:0 0 auto}
.rpl-card:hover{background:rgba(99,102,241,.1);border-color:rgba(99,102,241,.25);transform:translateY(-2px)}
.rpl-mosaic{display:grid;grid-template-columns:1fr 1fr;width:64px;height:64px;border-radius:10px;overflow:hidden;flex-shrink:0;gap:1px;background:rgba(0,0,0,.3)}
.rpl-mosaic img{width:100%;height:100%;object-fit:cover;display:block}
.rpl-mosaic-single{width:64px;height:64px;border-radius:10px;overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center}
.rpl-mosaic-single img{width:100%;height:100%;object-fit:cover;display:block}
.rpl-card-meta{min-width:0;overflow:hidden}
.rpl-card-name{font:700 14px Outfit,sans-serif;color:#eef3fb;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rpl-card-count{font:11px Outfit,sans-serif;color:var(--muted);margin-top:2px}
/* Legacy deck (auto-playlists still use rcol-card + rpl-deck) */
.rpl-deck{width:140px;height:140px;position:relative;display:flex;align-items:center;justify-content:center}
.rpl-deck-card{position:absolute;width:100px;height:100px;border-radius:10px;overflow:hidden;box-shadow:0 4px 12px rgba(0,0,0,.4);border:2px solid rgba(255,255,255,.1);transition:transform .2s}
.rpl-deck-card img{width:100%;height:100%;object-fit:cover;background:#111}
.rpl-deck-empty{width:100px;height:100px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:32px;border:2px solid rgba(255,255,255,.08)}
.rcol-card:hover .rpl-deck-card{box-shadow:0 6px 20px rgba(0,0,0,.5)}
.rpl-expanded{background:rgba(99,102,241,.06);border:1px solid rgba(99,102,241,.15);border-radius:14px;padding:14px;margin-bottom:12px;animation:rplOpen .25s ease-out}
@keyframes rplOpen{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.rpl-exp-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.rpl-exp-title{font:700 16px Outfit,sans-serif;color:#eef3fb}
.rpl-spread{display:flex;gap:10px;overflow-x:auto;padding:0 0 12px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.rpl-spread::-webkit-scrollbar{display:none}
.rpl-spread-card{flex:0 0 auto;width:90px;cursor:pointer;text-align:center;transition:transform .15s}
.rpl-spread-card:hover{transform:translateY(-3px)}
.rpl-spread-thumb{width:90px;height:90px;border-radius:10px;overflow:hidden;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px rgba(0,0,0,.3)}
.rpl-spread-thumb img{width:100%;height:100%;object-fit:cover}
.rpl-spread-name{font:600 10px Outfit,sans-serif;color:#e0e8f4;margin-top:5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rpl-exp-songs{max-height:200px;overflow-y:auto;margin-bottom:8px}
.rpl-exp-song{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;cursor:pointer;font:12px Outfit,sans-serif;color:#e0e8f4;transition:background .1s}
.rpl-exp-song:hover{background:rgba(99,102,241,.12)}
.rpl-exp-num{font:600 10px JetBrains Mono,monospace;color:var(--muted-2);width:18px;text-align:right;flex-shrink:0}
.rpl-exp-sname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rpl-exp-rm{border:none;background:none;color:var(--muted);cursor:pointer;font-size:14px;padding:0 4px;flex-shrink:0;opacity:.5;transition:opacity .1s}
.rpl-exp-rm:hover{opacity:1;color:#ef4444}
/* Netflix-style browse category rows */
.rbrowse-cat-row{padding:4px 18px 20px}
.rbrowse-cat-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.rbrowse-cat-title{font:700 17px Outfit,sans-serif;color:#eef3fb;letter-spacing:.2px}
.rbrowse-cat-arrows{display:flex;gap:6px}
.rbrowse-arrow{width:32px;height:32px;border-radius:50%;border:1px solid rgba(148,163,184,.2);background:rgba(255,255,255,.06);
  color:#c8d6e5;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .15s}
.rbrowse-arrow:hover{background:rgba(99,102,241,.2);border-color:rgba(99,102,241,.4);color:#fff}
.rbrowse-cat-scroll{display:flex;gap:16px;overflow-x:auto;padding-bottom:8px;scrollbar-width:none;-webkit-overflow-scrolling:touch;scroll-behavior:smooth}
.rbrowse-cat-scroll::-webkit-scrollbar{display:none}
.rbrowse-big-card{flex:0 0 auto;width:clamp(200px,22vw,280px);background:rgba(255,255,255,.04);border-radius:14px;overflow:hidden;
  border:1px solid rgba(148,163,184,.08);transition:transform .18s,box-shadow .18s,border-color .18s;cursor:pointer}
.rbrowse-big-card:hover{transform:translateY(-4px);box-shadow:0 12px 36px rgba(0,0,0,.5);border-color:rgba(99,102,241,.3)}
.rbrowse-big-thumb{position:relative;width:100%;aspect-ratio:16/9;background:#0a0e18;overflow:hidden}
.rbrowse-big-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.rbrowse-big-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:32px;background:linear-gradient(135deg,#1e1b4b,#312e81)}
.rbrowse-big-dur{position:absolute;bottom:6px;right:6px;background:rgba(0,0,0,.85);color:#fff;font:600 10px JetBrains Mono,monospace;
  padding:2px 6px;border-radius:4px}
.rbrowse-big-play{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:32px;color:#fff;
  background:rgba(0,0,0,.3);opacity:0;transition:opacity .15s}
.rbrowse-big-card:hover .rbrowse-big-play{opacity:1}
.rbrowse-big-info{padding:12px 14px 4px}
.rbrowse-big-title{font:600 14px Outfit,sans-serif;color:#e0e8f4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rbrowse-big-artist{font:12px Outfit,sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px}
.rbrowse-big-actions{display:flex;gap:8px;padding:8px 14px 14px}
.rbrowse-act{flex:1;border:none;padding:8px 0;border-radius:8px;font:600 12px Outfit,sans-serif;cursor:pointer;transition:all .15s}
.rbrowse-act.play{background:rgba(139,92,246,.18);color:#c4b5fd}
.rbrowse-act.play:hover{background:rgba(139,92,246,.32)}
.rbrowse-act.watch{background:rgba(99,102,241,.15);color:#c7d2fe}
.rbrowse-act.watch:hover{background:rgba(99,102,241,.28)}
/* Play All banner at top of Browse results */
.rbrowse-play-all{display:flex;align-items:center;justify-content:center;gap:8px;padding:12px 20px;margin:0 0 16px;border-radius:12px;background:linear-gradient(135deg,rgba(99,102,241,.18),rgba(139,92,246,.14));border:1px solid rgba(99,102,241,.22);cursor:pointer;font:600 14px Outfit,sans-serif;color:#c7d2fe;transition:all .2s;user-select:none}
.rbrowse-play-all:hover{background:linear-gradient(135deg,rgba(99,102,241,.28),rgba(139,92,246,.22));border-color:rgba(99,102,241,.35)}
.rbrowse-play-all-icon{font-size:18px;color:#a5b4fc}
.rbrowse-act.save{background:rgba(34,197,94,.12);color:#4ade80}
.rbrowse-act.save:hover{background:rgba(34,197,94,.22)}
.rbrowse-act.save.saved{background:rgba(34,197,94,.25);color:#22c55e}
@media(max-width:600px){.rbrowse-big-card{width:180px}.rbrowse-cat-title{font-size:14px}.rbrowse-cat-arrows{display:none}}
.rbrowse-active{outline:2px solid var(--accent,#22d9e6);outline-offset:2px}
/* Saved songs card grid (Collection view) */
.rsaved-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px;padding:4px 0}
.rsaved-card{position:relative;background:rgba(255,255,255,.04);border-radius:12px;overflow:hidden;border:1px solid rgba(148,163,184,.08);
  transition:transform .15s,box-shadow .15s;cursor:pointer}
.rsaved-card:hover{transform:translateY(-3px);box-shadow:0 8px 24px rgba(0,0,0,.4);border-color:rgba(99,102,241,.25)}
.rsaved-thumb{position:relative;width:100%;aspect-ratio:1;overflow:hidden;background:#0a0e18}
.rsaved-thumb img{width:100%;height:100%;object-fit:cover;display:block;position:relative;z-index:1}
.rsaved-thumb-bg{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.rsaved-play-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:28px;color:#fff;
  background:rgba(0,0,0,.35);opacity:0;transition:opacity .15s;z-index:2}
.rsaved-card:hover .rsaved-play-overlay{opacity:1}
.rsaved-info{padding:10px 12px 8px}
.rsaved-title{font:600 13px Outfit,sans-serif;color:#e0e8f4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rsaved-artist{font:11px Outfit,sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
.rsaved-remove{position:absolute;top:6px;right:6px;width:24px;height:24px;border-radius:50%;border:none;background:rgba(0,0,0,.65);
  color:#ef4444;font-size:16px;cursor:pointer;opacity:0;transition:opacity .15s;display:flex;align-items:center;justify-content:center;z-index:3}
.rsaved-card:hover .rsaved-remove{opacity:1}
.rsaved-remove:hover{background:rgba(239,68,68,.3)}
@media(max-width:600px){.rsaved-grid{grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px}}
.rnp-uq-item{display:flex;gap:10px;align-items:center;padding:8px 10px;border-radius:10px;cursor:pointer;margin-bottom:4px;
  background:rgba(255,255,255,.02);border:1px solid transparent;transition:all .15s}
.rnp-uq-item:hover{background:rgba(99,102,241,.1);border-color:rgba(99,102,241,.18);transform:translateX(2px)}
.rnp-uq-item:first-child{background:rgba(99,102,241,.06);border-color:rgba(99,102,241,.12)}
.rnp-uq-num{font:700 11px JetBrains Mono,monospace;color:rgba(255,255,255,.2);width:16px;text-align:center;flex-shrink:0}
.rnp-uq-item:hover .rnp-uq-num{color:var(--accent,#22d9e6)}
.rnp-uq-thumb{width:52px;height:42px;border-radius:8px;overflow:hidden;flex-shrink:0;display:flex;align-items:center;
  justify-content:center;font-size:14px;position:relative}
.rnp-uq-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.rnp-uq-thumb::after{content:'▶';position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.45);color:#fff;font-size:14px;opacity:0;transition:opacity .15s;border-radius:8px}
.rnp-uq-item:hover .rnp-uq-thumb::after{opacity:1}
.rnp-uq-meta{min-width:0;overflow:hidden;flex:1}
.rnp-uq-badge{font:700 8px Outfit,sans-serif;color:var(--accent,#22d9e6);letter-spacing:.8px;text-transform:uppercase;margin-bottom:2px}
.rnp-uq-title{font:600 12px Outfit,sans-serif;color:#e0e8f4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.3}
.rnp-uq-artist{font:10px Outfit,sans-serif;color:rgba(255,255,255,.35);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
@media(max-width:700px){
  .rnp-upnext{display:none !important}
  .rnp-art-wrap{width:200px;height:200px}
  /* Mobile radio UI polish */
  .rnp-transport{gap:10px;flex-wrap:wrap;justify-content:center}
  .rnp-act-btn{width:48px;height:48px;font-size:18px}
  .rnp-act-btn.rnp-play{width:62px;height:62px;font-size:24px}
  .radio-mode-toggle{padding:10px 18px;font-size:13px}
  .radio-bar .rb-btn{width:40px;height:40px}
  .radio-bar .rb-btn.rb-play{width:46px;height:46px;font-size:20px}
  .rbrowse-big-card{width:clamp(160px,42vw,220px)}
  .rbrowse-big-thumb{aspect-ratio:4/3}
  .rbrowse-search-bar{padding:10px 12px 6px}
  .rbrowse-search-bar input{padding:12px 14px;font-size:14px}
  .rcol-song-card{padding:10px 12px}
  .rcol-song-thumb{width:48px;height:48px}
  .rsearch-item{padding:10px 12px}
}
/* Bottom bar: visualizer-as-progress (full width bottom row) */
.rb-progress-row{display:flex;align-items:center;gap:8px;padding:0 16px 6px;width:100%}
.rb-vis-wrap{flex:1;height:32px;position:relative;border-radius:4px;overflow:hidden;cursor:pointer}
.rb-vis{display:block;width:100%;height:100%}
.rb-vis-mask{position:absolute;top:0;right:0;bottom:0;left:100%;background:rgba(6,8,14,.7);pointer-events:none;transition:left .15s linear;border-left:2px solid var(--accent-glow,rgba(34,217,230,.4))}
.rb-time{font:10px JetBrains Mono,monospace;color:var(--muted-2);flex-shrink:0;white-space:nowrap;min-width:32px;text-align:center}
.rwatch-strip{display:flex;align-items:center;gap:12px;padding:12px 18px;background:rgba(0,0,0,.35);
  border-bottom:1px solid var(--accent-glow)}
.rwatch-badge{width:38px;height:38px;flex-shrink:0;border-radius:10px;display:flex;align-items:center;justify-content:center;
  font-size:18px;background:linear-gradient(135deg,var(--accent),var(--accent-2));box-shadow:0 0 18px var(--accent-glow)}
.rwatch-title{font:700 14px Outfit,sans-serif;color:#eef3fb;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rwatch-sub{font:11px Outfit,sans-serif;color:var(--accent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rwatch-clear{border:1px solid var(--accent-glow);background:rgba(255,255,255,.04);color:var(--muted);cursor:pointer;
  width:30px;height:30px;border-radius:8px;flex-shrink:0;font-size:13px;line-height:1}
.rwatch-clear:hover{color:#fff;background:var(--accent-glow)}
.rwatch-stage{padding:16px 18px 6px}
.rwatch-frame{position:relative;width:100%;aspect-ratio:16/9;border-radius:14px;overflow:hidden;background:#000;
  border:1px solid var(--accent-glow);box-shadow:0 12px 40px rgba(0,0,0,.5),0 0 0 1px rgba(255,255,255,.02) inset}
.rwatch-iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.rwatch-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:24px;background:radial-gradient(circle at 50% 40%,rgba(34,217,230,.06),transparent 70%)}
.rwatch-card{position:relative}
.rwatch-card .rwatch-play{position:absolute;top:6px;left:6px;background:rgba(0,0,0,.72);color:#fff;
  font:700 11px Outfit,sans-serif;padding:3px 8px;border-radius:6px;opacity:0;transition:opacity .15s}
.rwatch-card:hover .rwatch-play{opacity:1}
.rwatch-card.on{outline:2px solid var(--accent);outline-offset:2px;border-radius:12px}
.rwatch-card.on .rwatch-play{opacity:1;background:linear-gradient(135deg,var(--accent),var(--accent-2));color:#04121a}
@media (max-width:900px){
  .rnp-stations{display:none}
  .rnp-art{width:180px;height:180px}
  .rnp-title{font-size:17px}
  .radio-nav-btn{padding:10px 12px;font-size:11px}
  .rcol-card{width:120px}
  .rcol-card img{width:120px;height:120px}
}
@media(max-width:900px){
  .radio-body{flex-direction:column;overflow:visible}
  .radio-main{overflow:visible}
  .radio-sidebar{width:100%;border-left:none;border-top:1px solid rgba(148,163,184,.08);max-height:none;overflow:visible}
  .radio-video{height:clamp(180px,35vh,300px)}
  .radio-chat-msgs{max-height:200px}
  .radio-queue{max-height:150px}
}
/* ── Global Mini-Player (visible outside Radio view when music is playing) ── */
.radio-mini{display:none;position:fixed;bottom:0;left:0;right:0;z-index:200;
  background:rgba(6,10,18,.96);backdrop-filter:blur(14px);border-top:1px solid rgba(148,163,184,.12);
  padding:6px 12px;align-items:center;gap:8px;font-family:Outfit,sans-serif}
.radio-mini.on{display:flex}
@media(max-width:900px){.radio-mini{bottom:calc(52px + env(safe-area-inset-bottom,0px))}}
.radio-mini .rm-art{width:36px;height:36px;border-radius:8px;overflow:hidden;flex-shrink:0;background:#111}
.radio-mini .rm-art img{width:100%;height:100%;object-fit:cover}
.radio-mini .rm-meta{flex:1;min-width:0}
.radio-mini .rm-title{font:600 12px Outfit,sans-serif;color:#eef3fb;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.radio-mini .rm-artist{font:10px Outfit,sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.radio-mini .rm-btn{border:none;background:rgba(255,255,255,.08);color:rgba(255,255,255,.7);
  width:32px;height:32px;border-radius:50%;font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.radio-mini .rm-btn:hover{color:#fff;background:rgba(255,255,255,.15)}
.radio-mini .rm-btn.rm-play{background:linear-gradient(135deg,var(--accent,#22d9e6),var(--accent-2,#0ea5b8));color:#fff;width:34px;height:34px;font-size:15px}
.radio-mini .rm-progress{position:absolute;top:-2px;left:0;height:2px;background:var(--accent,#22d9e6);transition:width .3s linear}
.radio-mini .rm-go{border:none;background:none;color:var(--accent);font:600 10px Outfit,sans-serif;cursor:pointer;padding:4px 8px;white-space:nowrap}
@media(min-width:769px){.radio-mini{left:var(--rail-w,60px)}}
/* Public-user feed density (display prefs — no host secrets) */
body[data-guest-density="compact"] .guest-card{padding:10px 12px;margin-bottom:8px}
body[data-guest-density="cozy"] .guest-card{padding:18px 20px;margin-bottom:16px}
body[data-guest-density="compact"] .guest-dash{padding:12px 14px 24px}
/* Guest profile card rows touch-friendly on mobile */
@media (max-width:900px){
  body.scope-guest .guest-card .gc-btn{min-height:40px;padding:10px 14px}
  body.scope-guest .guest-card .gc-row{font-size:13px;padding:4px 0}
}
/* Guest home workspace — desktop + mobile (wider, multi-column fill) */
.guest-dash{padding:16px 24px 32px;max-width:none;margin:0;width:100%}
.plan-grid::-webkit-scrollbar{height:8px}
.plan-grid::-webkit-scrollbar-thumb{background:rgba(148,163,184,.35);border-radius:8px}
.plan-grid::-webkit-scrollbar-thumb:hover{background:rgba(148,163,184,.55)}
.plan-grid::-webkit-scrollbar-track{background:transparent}
body.scope-guest .view-pane#view-home,
body.scope-owner .view-pane#view-home{background:radial-gradient(ellipse at 50% 0%,rgba(34,217,230,.06),transparent 55%)}
.guest-dash-grid{display:grid;grid-template-columns:1fr;gap:14px}
/* v9.10.66 — right sidebar restored on wide desktop with useful widgets.
   Hidden on mobile/tablet and narrow desktop. */
.guest-dash-grid .guest-col-right{display:none}
:root{
  --feed-col-w: 680px;
  --feed-col-w-xl: 780px;
}
@media (min-width:1000px){
  .guest-dash-grid{grid-template-columns:min(var(--feed-col-w,680px),100%);justify-content:center;align-items:start;gap:20px}
  .guest-dash-grid .guest-col-main{grid-column:1;min-width:0}
  .guest-dash-grid .guest-col-left{display:none !important}
}
/* Wide desktop: show sidebar beside feed */
@media (min-width:1300px){
  .guest-dash-grid{grid-template-columns:minmax(0,var(--feed-col-w-xl)) 280px;justify-content:center}
  .guest-dash-grid .guest-col-right{display:block;position:sticky;top:16px;align-self:start}
  .guest-dash-grid .guest-col-right .guest-card{padding:12px 14px;margin-bottom:10px}
}
@media (min-width:1600px){
  .guest-dash-grid{grid-template-columns:minmax(0,850px) 300px;gap:24px}
}
/* v9.10.342 XL column override — now handled by the 1300/1600px breakpoints above */
/* v9.10.500 — the feed wrapper on desktop is just a container, posts have their own cards.
   Remove the card look from the wrapper so posts float cleanly. */
@media (min-width:1000px){
  .gfeed-wrap{background:transparent !important;border:none !important;padding:0 !important}
  .gfeed-wrap>.gc-h{padding:0 2px;margin-bottom:14px}
}
/* keep post media comfortable regardless of column width (v9.10.476: matched to the narrow column) */
.gpost-img{max-height:620px}
/* v9.10.327 — REQUEST 1: on mobile the feed post cards were a thin center strip
   (nested dash+wrapper+post padding). Gate to mobile (<1000px single-column);
   desktop unchanged. Cards now fill width minus an ~8px gutter each side. */
@media (max-width:999px){
  body.scope-guest .guest-dash{padding-left:8px;padding-right:8px}
  body.scope-guest .gfeed-wrap{padding-left:0;padding-right:0;background:transparent;border:none;margin-bottom:0}
  body.scope-guest .gfeed-wrap>.gc-h{padding-left:4px}
}
.guest-banner{border:1px solid rgba(34,217,230,.28);background:linear-gradient(135deg,rgba(34,217,230,.10),rgba(124,58,237,.08));
  border-radius:14px;padding:16px 18px;margin-bottom:14px}
.guest-banner h2{font-family:var(--ui);font-size:16px;font-weight:800;letter-spacing:.4px;margin:0 0 6px;color:#e9eef7}
.guest-banner p{margin:0;font-size:12.5px;line-height:1.55;color:var(--muted)}
.guest-card{background:rgba(13,19,32,.72);border:1px solid var(--border);border-radius:14px;padding:14px 16px;margin-bottom:12px}
body.scope-guest .tb-user-chip{display:inline-flex !important}
body.scope-guest .tb-user-chip:hover{border-color:var(--accent);background:rgba(34,217,230,.16)}
/* Desktop Chat icon (next to User) + dropdown */
body.scope-guest .tb-chat-btn{display:none;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;
  border:1px solid rgba(34,217,230,.35);background:rgba(34,217,230,.08);color:var(--accent);cursor:pointer;position:relative;flex-shrink:0}
body.scope-guest.force-desktop .tb-chat-btn,
body.scope-guest:not(.force-mobile) .tb-chat-btn{display:inline-flex}
@media (max-width:900px){
  body.scope-guest:not(.force-desktop) .tb-chat-btn{display:none !important}
}
.tb-chat-btn:hover{border-color:var(--accent);background:rgba(34,217,230,.16)}
.tb-chat-btn svg{width:18px;height:18px}
.tb-chat-btn .tb-chat-badge{position:absolute;top:-2px;right:-2px;min-width:14px;height:14px;padding:0 3px;border-radius:8px;
  background:#f43f5e;color:#fff;font:700 9px Outfit,sans-serif;display:none;align-items:center;justify-content:center}
.tb-chat-dd{display:none;position:absolute;top:calc(100% + 8px);right:0;width:320px;max-height:min(70vh,480px);overflow:hidden;
  background:rgba(10,14,22,.97);border:1px solid var(--border);border-radius:14px;box-shadow:0 16px 48px rgba(0,0,0,.55);z-index:5000;
  flex-direction:column}
.tb-chat-dd.open{display:flex}
.tb-chat-dd .tcd-head{padding:10px 12px;border-bottom:1px solid var(--border);font:700 11px Outfit,sans-serif;letter-spacing:.8px;
  text-transform:uppercase;color:var(--muted);display:flex;justify-content:space-between;align-items:center}
.tb-chat-dd .tcd-online{display:flex;gap:8px;padding:10px 12px;overflow-x:auto;border-bottom:1px solid var(--border);flex-shrink:0}
.tb-chat-dd .tcd-av{width:44px;flex-shrink:0;text-align:center;cursor:pointer;color:var(--text);background:none;border:none;padding:0}
.tb-chat-dd .tcd-av img,.tb-chat-dd .tcd-av .tcd-letter{width:40px;height:40px;border-radius:50%;object-fit:cover;background:#1a2233;
  border:2px solid rgba(34,217,230,.35);display:flex;align-items:center;justify-content:center;margin:0 auto;font:700 13px Outfit,sans-serif;color:var(--accent)}
.tb-chat-dd .tcd-av .tcd-dot{width:10px;height:10px;border-radius:50%;background:var(--good);border:2px solid #0a0e16;position:absolute;right:2px;bottom:14px}
.tb-chat-dd .tcd-av-wrap{position:relative;display:inline-block}
.tb-chat-dd .tcd-av span{display:block;font-size:9px;margin-top:4px;max-width:48px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted)}
.tb-chat-dd .tcd-msgs{flex:1;overflow-y:auto;padding:6px 0;min-height:80px}
.tb-chat-dd .tcd-row{display:flex;gap:10px;align-items:center;padding:8px 12px;cursor:pointer;border:none;background:none;width:100%;text-align:left;color:var(--text)}
.tb-chat-dd .tcd-row:hover{background:rgba(34,217,230,.08)}
.tb-chat-dd .tcd-row img,.tb-chat-dd .tcd-row .tcd-letter{width:36px;height:36px;border-radius:50%;flex-shrink:0;object-fit:cover;background:#1a2233;
  display:flex;align-items:center;justify-content:center;font:700 12px Outfit,sans-serif;color:var(--accent)}
.tb-chat-dd .tcd-row .tcd-meta{flex:1;min-width:0}
.tb-chat-dd .tcd-row .tcd-name{font:700 12px Outfit,sans-serif}
.tb-chat-dd .tcd-row .tcd-prev{font-size:11px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tb-chat-dd .tcd-foot{padding:8px 12px;border-top:1px solid var(--border);font-size:11px}
.tb-chat-dd .tcd-foot button{width:100%;padding:8px;border-radius:8px;border:1px solid var(--border);background:rgba(255,255,255,.04);
  color:var(--accent);cursor:pointer;font:600 11px Outfit,sans-serif}
/* Facebook-style bottom chat dock (desktop) */
#chat-dock{display:none;position:fixed;right:16px;bottom:0;z-index:4500;flex-direction:row-reverse;align-items:flex-end;gap:8px;
  pointer-events:none;max-width:calc(100vw - 32px)}
body.scope-guest.force-desktop #chat-dock,
body.scope-guest:not(.force-mobile) #chat-dock{display:flex}
@media (max-width:900px){
  body.scope-guest:not(.force-desktop) #chat-dock{display:none !important}
}
.chat-dock-tab{pointer-events:auto;width:300px;background:rgba(12,16,26,.98);border:1px solid var(--border);border-radius:12px 12px 0 0;
  box-shadow:0 -8px 32px rgba(0,0,0,.45);display:flex;flex-direction:column;max-height:420px;overflow:hidden}
.chat-dock-tab.minimized{max-height:none;height:auto}
.chat-dock-tab .cdt-head{display:flex;align-items:center;gap:8px;padding:8px 10px;background:linear-gradient(135deg,rgba(34,217,230,.18),rgba(124,58,237,.12));
  cursor:pointer;user-select:none;flex-shrink:0}
.chat-dock-tab .cdt-head .cdt-name{flex:1;font:700 12px Outfit,sans-serif;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-dock-tab .cdt-head .cdt-dot{width:8px;height:8px;border-radius:50%;background:var(--good);flex-shrink:0}
.chat-dock-tab .cdt-head button{border:none;background:transparent;color:var(--muted);cursor:pointer;width:24px;height:24px;border-radius:6px;
  font-size:14px;line-height:1;padding:0}
.chat-dock-tab .cdt-head button:hover{background:rgba(255,255,255,.08);color:var(--text)}
.chat-dock-tab .cdt-body{display:flex;flex-direction:column;flex:1;min-height:0;height:340px}
.chat-dock-tab.minimized .cdt-body{display:none}
.chat-dock-tab .cdt-thread{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:6px;min-height:0}
.chat-dock-tab .cdt-msg{max-width:88%;padding:7px 10px;border-radius:12px;font-size:12px;line-height:1.4;word-break:break-word}
.chat-dock-tab .cdt-msg.me{align-self:flex-end;background:linear-gradient(135deg,var(--accent),#0070a8);color:#04070d;border-radius:12px 12px 4px 12px}
.chat-dock-tab .cdt-msg.them{align-self:flex-start;background:rgba(255,255,255,.06);border:1px solid var(--border);color:var(--text);border-radius:12px 12px 12px 4px}
.chat-dock-tab .cdt-compose{display:flex;gap:6px;padding:8px;border-top:1px solid var(--border);flex-shrink:0}
.chat-dock-tab .cdt-compose input{flex:1;border-radius:18px;border:1px solid var(--border);background:rgba(0,0,0,.35);color:var(--text);
  padding:8px 12px;font-size:12px;outline:none}
.chat-dock-tab .cdt-compose button{border:none;border-radius:18px;padding:8px 12px;background:var(--accent);color:#04070d;font:700 11px Outfit,sans-serif;cursor:pointer}
/* Feed post cards */
.gpost{background:rgba(13,19,32,.78);border:1px solid rgba(255,255,255,.06);border-radius:16px;padding:18px 20px;margin-bottom:14px;
  transition:border-color .2s,box-shadow .25s,background .2s;backdrop-filter:blur(4px)}
.gpost:hover{border-color:rgba(99,102,241,.2);box-shadow:0 8px 28px rgba(0,0,0,.3);background:var(--c-card-hover)}
.gpost:last-child{margin-bottom:0}
.gpost-head{display:flex;gap:12px;align-items:center;margin-bottom:12px}
/* v9.10.311 — per-post options menu */
.gpost-menu-wrap{position:relative;flex:0 0 auto}
.gpost-menu-btn{background:none;border:none;color:var(--muted);font-size:22px;line-height:1;cursor:pointer;padding:2px 10px;border-radius:8px}
.gpost-menu-btn:hover{background:rgba(255,255,255,.08);color:var(--text)}
.gpost-menu{position:absolute;right:0;top:30px;z-index:30;background:#0d1320;border:1px solid var(--border);border-radius:12px;box-shadow:0 10px 28px rgba(0,0,0,.55);min-width:150px;overflow:hidden;
  transform:scale(.95);transform-origin:top right;opacity:0;pointer-events:none;transition:transform .15s ease,opacity .15s ease}
.gpost-menu.open{transform:scale(1);opacity:1;pointer-events:auto}
.gpost-menu button{display:block;width:100%;text-align:left;background:none;border:none;color:var(--text);padding:11px 15px;font-size:13px;cursor:pointer}
.gpost-menu button:hover{background:rgba(255,255,255,.06)}
.gpost-menu button.danger{color:var(--c-rose)}
.gpost-menu button.danger:hover{background:rgba(248,113,113,.12)}
.gpost-head b{color:var(--accent)}
.gpost-text{font-size:15.5px;line-height:1.62;margin:2px 0 12px;color:var(--text);white-space:pre-wrap;word-break:break-word}
@media (max-width:900px){
  .gpost{padding:14px 14px;border-radius:14px;margin-bottom:8px;border-left:none;border-right:none}
  .gpost-text{font-size:15px;line-height:1.6}
  .gpost-head{gap:10px}
  /* Action buttons: icon-only but with good touch targets (44px min) */
  .gpost-acts{gap:4px;padding:4px 0 0}
  .gpost-acts button{font-size:0;padding:12px 10px;gap:0;border-radius:8px;min-height:44px;min-width:44px}
  .gpost-acts button svg{width:20px;height:20px}
  .gpost-acts button.on svg{filter:drop-shadow(0 0 4px var(--accent))}
  .gpost-stats{font-size:11px;gap:8px;padding:8px 0}
  .gcomposer-opt{padding:6px 10px !important;font-size:11px !important}
  /* Composer: subtle rounded corners on mobile */
  .gpost-composer{border-radius:12px;border-left:none;border-right:none;margin-bottom:0;padding:12px 14px}
  .gcomp-text{font-size:15px;min-height:40px}
  .gcomp-post-btn{padding:8px 20px;font-size:12px}
  /* v9.10.552 — stories rail on mobile: slightly smaller tall cards, same design */
  .gstories-row{gap:8px;padding:6px 4px 12px}
  .gstory-card,.gstory-skel{width:92px;height:150px}
  .gstory-create-top{height:96px}
  .gstory-ring-av{width:30px;height:30px}
  /* Feed tabs: full-width on mobile */
  .gfeed-tabs{margin-bottom:0;border-radius:0}
  .gfeed-tabs button{flex:1;padding:10px 8px;font-size:12px}
}
/* v9.10.476 — show the FULL image (was object-fit:cover, which cropped). height:auto
   scales the whole picture to the column width; max-height + contain letterboxes only
   extreme portraits so they don't run off-screen. */
.gpost-img{margin-top:8px;width:100%;height:auto;max-height:620px;object-fit:contain;border-radius:10px;background:#0b0f14;display:block}
.gpost-repost{font-size:10px;color:var(--muted);margin-bottom:6px}
/* v9.10.500 — subtle fade-in for posts entering the feed */
@keyframes gpostFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.gpost{animation:gpostFadeIn .25s ease-out both}
/* v9.10.520 — AI vitals indicator on posts */
.post-vitals{display:inline-flex;align-items:center;gap:3px;vertical-align:middle}
.pv-dot{display:inline-block;width:7px;height:7px;border-radius:50%;flex-shrink:0}
.pv-label{font-size:10.5px;color:var(--muted);font-weight:500}
/* v9.10.520 — THE KAI CODEX VIEWER */
.codex-shell{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden;
  background:linear-gradient(175deg,rgba(10,22,40,.95) 0%,rgba(6,14,28,.98) 40%,rgba(4,10,20,1) 100%);
  border-left:1px solid rgba(0,230,255,.04);position:relative}
.codex-shell::before{content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse 80% 50% at 50% 0%,rgba(0,230,255,.03) 0%,transparent 70%),
             radial-gradient(ellipse 60% 40% at 80% 100%,rgba(0,150,200,.02) 0%,transparent 60%);z-index:0}
.codex-shell>*{position:relative;z-index:1}
.codex-header{padding:16px 24px 14px;border-bottom:1px solid rgba(0,230,255,.06);flex-shrink:0}
.codex-title-row{display:flex;align-items:center;gap:14px;margin-bottom:14px}
.codex-main-title{font:700 22px var(--ui),Inter,sans-serif;color:var(--text);letter-spacing:-.3px}
.codex-subtitle{font:500 12px var(--ui),Inter,sans-serif;color:var(--muted)}
.codex-search-row{display:flex;gap:8px;align-items:center}
.codex-search{flex:1;padding:10px 14px;border-radius:10px;border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.04);color:var(--text);font:400 14px var(--ui),Inter,sans-serif;outline:none;transition:border-color .2s}
.codex-search:focus{border-color:var(--accent)}
.codex-clear-btn{padding:8px 14px;border-radius:8px;border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.05);color:var(--muted);font:500 12px var(--ui),Inter,sans-serif;cursor:pointer}
.codex-clear-btn:hover{background:rgba(255,255,255,.08);color:var(--text)}
.codex-toc{flex:1;overflow-y:auto;padding:8px 0}
.codex-entry{border-bottom:1px solid rgba(255,255,255,.03);transition:background .15s,border-color .15s;border-left:2px solid transparent}
.codex-entry:hover{background:rgba(0,230,255,.02);border-left-color:rgba(0,230,255,.12)}
.codex-entry.open{background:rgba(0,230,255,.04);border-left:2px solid var(--accent);box-shadow:inset 0 0 20px rgba(0,230,255,.02)}
.codex-entry-head{display:flex;align-items:center;gap:8px;padding:12px 16px 12px 0;cursor:pointer;user-select:none}
.codex-arrow{font-size:10px;color:var(--muted);width:14px;text-align:center;flex-shrink:0}
.codex-entry-title{flex:1;font:600 14px var(--ui),Inter,sans-serif;color:var(--text);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.codex-entry-lines{font:400 11px var(--ui),Inter,sans-serif;color:var(--muted);flex-shrink:0;margin-right:4px}
.codex-tts-btn,.codex-ai-btn{border:none;background:rgba(255,255,255,.05);border-radius:6px;padding:4px 8px;cursor:pointer;font-size:14px;color:var(--muted);transition:background .15s,color .15s;flex-shrink:0}
.codex-tts-btn:hover,.codex-ai-btn:hover{background:rgba(0,230,255,.12);color:var(--accent)}
.codex-snippet{font:400 12px var(--ui),Inter,sans-serif;color:var(--muted);padding:0 16px 8px 22px;line-height:1.5}
.codex-entry-body{overflow:hidden;transition:max-height .3s ease}
.codex-entry:not(.open) .codex-entry-body{max-height:0}
.codex-entry.open .codex-entry-body{max-height:none}
.codex-content{padding:14px 20px 18px;font:400 14px/1.65 var(--ui),Inter,sans-serif;color:var(--text);word-break:break-word}
.codex-content p{margin:0 0 8px}
.codex-content p:last-child{margin-bottom:0}
.codex-content strong{color:var(--accent);font-weight:700}
.codex-content code{background:rgba(255,255,255,.06);padding:2px 6px;border-radius:4px;font-size:13px}
.codex-loading{padding:16px 24px;color:var(--muted);font-size:13px}
/* v9.10.521 — Law-Book Codex + Document Library */
.codex-tab-bar{display:flex;gap:0;border-bottom:1px solid rgba(0,230,255,.08);flex-shrink:0;padding:0 24px;
  background:rgba(0,0,0,.15)}
.codex-tab{padding:12px 22px;font:600 13px var(--ui),Inter,sans-serif;color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;transition:color .2s,border-color .2s,background .2s;background:none;border-top:none;border-left:none;border-right:none}
.codex-tab:hover{color:var(--text);background:rgba(255,255,255,.02)}
.codex-tab.active{color:var(--accent);border-bottom-color:var(--accent);background:rgba(0,230,255,.03)}
.codex-law-title{font:700 26px Georgia,'Times New Roman',serif;color:var(--text);text-align:center;padding:24px 24px 14px;letter-spacing:.5px;
  text-shadow:0 0 30px rgba(0,230,255,.08)}
.codex-law-title::before{content:'\2726';display:block;font-size:14px;color:rgba(0,230,255,.25);margin-bottom:8px;letter-spacing:12px}
.codex-law-title::after{content:'';display:block;width:120px;height:1px;
  background:linear-gradient(90deg,transparent,rgba(0,230,255,.3),transparent);margin:12px auto 0}
.codex-breadcrumb{display:flex;align-items:center;gap:6px;padding:6px 24px;font:400 12px var(--ui),Inter,sans-serif;color:var(--muted);flex-shrink:0;flex-wrap:wrap}
.codex-breadcrumb span{cursor:pointer;transition:color .15s}
.codex-breadcrumb span:hover{color:var(--accent)}
.codex-breadcrumb .bc-sep{color:rgba(255,255,255,.2);cursor:default}
.codex-breadcrumb .bc-sep:hover{color:rgba(255,255,255,.2)}
.codex-article-group{border-bottom:1px solid rgba(0,230,255,.04);margin:0}
.codex-article-header{display:flex;align-items:center;gap:12px;padding:14px 24px;cursor:pointer;user-select:none;
  background:linear-gradient(90deg,rgba(0,230,255,.03),rgba(0,230,255,.01) 60%,transparent);
  border-left:2px solid rgba(0,230,255,.08);transition:background .15s,border-color .15s}
.codex-article-header:hover{background:linear-gradient(90deg,rgba(0,230,255,.06),rgba(0,230,255,.02) 60%,transparent);border-left-color:rgba(0,230,255,.2)}
.codex-article-group.open>.codex-article-header{border-left-color:var(--accent);background:linear-gradient(90deg,rgba(0,230,255,.05),rgba(0,230,255,.015) 60%,transparent)}
.codex-article-num{font:700 13px Georgia,'Times New Roman',serif;color:var(--accent);min-width:75px;text-shadow:0 0 12px rgba(0,230,255,.15)}
.codex-article-title{flex:1;font:600 15px var(--ui),Inter,sans-serif;color:var(--text)}
.codex-article-arrow{font-size:10px;color:var(--muted);transition:transform .2s}
.codex-article-group.open .codex-article-arrow{transform:rotate(90deg)}
.codex-article-body{overflow:hidden;max-height:0;transition:max-height .3s ease}
.codex-article-group.open .codex-article-body{max-height:none}
.codex-section-ref{display:inline-block;padding:2px 8px;border-radius:10px;background:rgba(0,230,255,.1);color:var(--accent);font:600 11px var(--ui),Inter,sans-serif;margin-right:6px;flex-shrink:0;
  border:1px solid rgba(0,230,255,.12);text-shadow:0 0 8px rgba(0,230,255,.2)}
.codex-frontmatter{padding:12px 24px;font:italic 400 13px/1.7 Georgia,'Times New Roman',serif;color:var(--muted)}
.codex-changelog-zone{border-top:1px solid rgba(255,255,255,.06);margin-top:8px;padding:12px 24px}
.codex-changelog-zone .codex-version-badge{display:inline-block;padding:2px 8px;border-radius:10px;background:rgba(0,230,255,.06);color:var(--accent);font:600 11px var(--ui),Inter,sans-serif;margin-right:6px}
.codex-changelog-btn{padding:10px 18px;border-radius:8px;border:1px solid rgba(0,230,255,.15);background:rgba(0,230,255,.04);color:var(--accent);font:600 13px var(--ui),Inter,sans-serif;cursor:pointer;transition:background .15s}
.codex-changelog-btn:hover{background:rgba(0,230,255,.1)}
.codex-library-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px;padding:16px 24px}
.codex-doc-card{border-radius:12px;border:1px solid rgba(255,255,255,.06);background:rgba(255,255,255,.02);overflow:hidden;cursor:pointer;transition:border-color .15s,background .15s,transform .1s}
.codex-doc-card:hover{border-color:rgba(0,230,255,.2);background:rgba(0,230,255,.03);transform:translateY(-1px)}
.codex-doc-card .card-stripe{height:3px}
.codex-doc-card .card-body{padding:14px 16px}
/* v9.10.517 - was one line + ellipsis, which hid most document names. */
.codex-doc-card .card-title{font:600 14px/1.35 var(--ui),Inter,sans-serif;color:var(--text);margin-bottom:5px;
  white-space:normal;overflow-wrap:anywhere;display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden}
.codex-doc-card .card-body{display:flex;flex-direction:column;justify-content:space-between;min-height:74px}
.codex-doc-card .card-meta{font:400 11px var(--ui),Inter,sans-serif;color:var(--muted)}
.codex-category-header{display:flex;align-items:center;gap:8px;padding:16px 24px 8px;font:700 14px var(--ui),Inter,sans-serif;color:var(--text);letter-spacing:.3px}
.codex-category-header .cat-icon{font-size:16px}
.codex-table{width:100%;border-collapse:collapse;margin:8px 0;font-size:13px}
.codex-table th,.codex-table td{padding:6px 10px;border:1px solid rgba(255,255,255,.08);text-align:left}
.codex-table th{background:rgba(255,255,255,.04);font-weight:600;color:var(--accent)}
.codex-codeblock{display:block;background:rgba(0,0,0,.3);border:1px solid rgba(255,255,255,.06);border-radius:8px;padding:12px 16px;font:400 13px/1.5 'Cascadia Code',monospace;color:var(--text);overflow-x:auto;margin:8px 0;white-space:pre}
.codex-blockquote{border-left:3px solid var(--accent);padding:8px 16px;margin:8px 0;color:var(--muted);font-style:italic;background:rgba(0,230,255,.02);border-radius:0 6px 6px 0}
.codex-hr{border:none;height:1px;background:rgba(255,255,255,.08);margin:16px 0}
.codex-content .katex-display{margin:12px 0;padding:12px 16px;background:rgba(0,0,0,.2);border-radius:8px;border:1px solid rgba(255,255,255,.04);overflow-x:auto}
.codex-content .katex{color:var(--text);font-size:1.05em}
.codex-content .katex-display>.katex{font-size:1.15em}
.codex-math-fallback{font-family:'Cascadia Code',monospace;color:var(--accent);background:rgba(0,0,0,.2);padding:2px 6px;border-radius:4px}
.codex-mermaid{margin:12px 0;padding:16px;background:rgba(0,0,0,.25);border:1px solid rgba(255,255,255,.06);border-radius:10px;overflow-x:auto;text-align:center}
.codex-mermaid:not(.mermaid-done){font:400 12px 'Cascadia Code',monospace;color:var(--muted);text-align:left;white-space:pre}
.codex-mermaid.mermaid-done svg{max-width:100%;height:auto}
/* v9.10.516 - a diagram must never blow out a book page; scroll it instead. */
.codex-mermaid.mermaid-done svg{max-height:56vh}
.cbk-body .codex-mermaid{margin:10px 0;padding:10px}
.cbk-body .codex-mermaid.mermaid-done svg{max-height:38vh}
/* fallback shown when a fence will not parse even after repair */
.codex-mermaid .mermaid-note{font:600 10.5px var(--ui),Inter,sans-serif;letter-spacing:.6px;color:var(--muted-2);text-align:left;margin-bottom:8px;text-transform:none}
.codex-mermaid .mermaid-src{margin:0;font:400 11.5px/1.55 'Cascadia Code',ui-monospace,monospace;color:var(--muted);text-align:left;white-space:pre;overflow-x:auto;max-height:34vh;overflow-y:auto}
.codex-code-lang{display:inline-block;padding:2px 8px;border-radius:6px 6px 0 0;background:rgba(255,255,255,.06);font:600 10px var(--ui),Inter,sans-serif;color:var(--muted);text-transform:uppercase;letter-spacing:.5px}
.codex-link{color:var(--accent);text-decoration:none;border-bottom:1px solid rgba(0,230,255,.3);transition:border-color .15s}
.codex-link:hover{border-bottom-color:var(--accent)}
.codex-content del{color:var(--muted);text-decoration:line-through}
.codex-read-full-btn{padding:4px 12px;border-radius:6px;border:1px solid rgba(0,230,255,.15);background:rgba(0,230,255,.04);color:var(--accent);font:600 11px var(--ui),Inter,sans-serif;cursor:pointer;transition:background .15s;margin-left:auto;margin-right:8px}
.codex-read-full-btn:hover{background:rgba(0,230,255,.12)}
.codex-full-section-heading{font:700 16px Georgia,'Times New Roman',serif;color:var(--accent);padding:20px 28px 8px;border-top:1px solid rgba(0,230,255,.06);margin-top:8px;text-shadow:0 0 12px rgba(0,230,255,.1)}
/* Book reader mode */
.codex-book-reader{display:flex;flex-direction:column;flex:1;min-height:0;padding:0}
.codex-book-nav{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 24px;border-bottom:1px solid rgba(0,230,255,.06);flex-shrink:0}
.codex-book-btn{padding:8px 16px;border-radius:8px;border:1px solid rgba(0,230,255,.15);background:rgba(0,230,255,.04);color:var(--accent);font:600 13px var(--ui),Inter,sans-serif;cursor:pointer;transition:background .15s}
.codex-book-btn:hover:not(:disabled){background:rgba(0,230,255,.1)}
.codex-book-btn:disabled{opacity:.3;cursor:default}
.codex-book-page{font:500 12px var(--ui),Inter,sans-serif;color:var(--muted)}
.codex-book-close{width:32px;height:32px;border-radius:8px;border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.04);color:var(--muted);font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,color .15s}
.codex-book-close:hover{background:rgba(255,100,100,.1);color:#ff6b6b}
.codex-book-title{font:700 20px Georgia,'Times New Roman',serif;color:var(--text);padding:20px 24px 12px;text-align:center;
  border-bottom:1px solid rgba(0,230,255,.04);text-shadow:0 0 20px rgba(0,230,255,.06)}
.codex-book-body{flex:1;overflow-y:auto;padding:8px 0}
.codex-book-body .codex-content{margin:0 20px 4px;border:none;border-radius:8px;background:rgba(0,0,0,.08);padding:20px 28px;font:400 15px/1.7 var(--ui),Inter,sans-serif}
@media(max-width:900px){
  .codex-book-nav{padding:10px 16px}
  .codex-book-btn{padding:6px 12px;font-size:12px}
  .codex-book-title{font-size:17px;padding:14px 16px 10px}
  .codex-book-body .codex-content{margin:0 12px;padding:14px 16px;font-size:14px}
}

/* ── v9.10.516 — BOOK SPREAD ────────────────────────────────────────────────
   Owner: "the read mode should look a lot better like a book left and right
   pages it flips and it shows the other pages."
   Two leaves and a gutter at >=900px, one leaf on a phone. The .codex-book-*
   rules ABOVE are intentionally untouched — _codexPaintFullReader (the
   continuous whole-document reader) still uses them.
   To revert the whole decision: delete this block and restore _codexPaintBook
   from oracle-core.js.bak-codexbook-20260727. */
.cbk{display:flex;flex-direction:column;flex:1;min-height:0}

/* one compact bar instead of the two near-identical nav rows this replaced */
.cbk-bar{display:flex;align-items:center;gap:12px;padding:10px 18px;flex-shrink:0;
  border-bottom:1px solid rgba(0,230,255,.06)}
.cbk-x{padding:6px 12px;border-radius:8px;border:1px solid rgba(255,255,255,.1);
  background:rgba(255,255,255,.04);color:var(--muted);font:600 12px var(--ui),Inter,sans-serif;
  cursor:pointer;white-space:nowrap;transition:color .15s,border-color .15s}
.cbk-x:hover{color:var(--accent);border-color:var(--accent)}
.cbk-meta{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:5px}
.cbk-loc{font:600 11px var(--ui),Inter,sans-serif;color:var(--muted);letter-spacing:.6px;white-space:nowrap}
.cbk-prog{width:100%;max-width:340px;height:2px;border-radius:2px;background:rgba(255,255,255,.07);overflow:hidden}
.cbk-prog>i{display:block;height:100%;background:var(--accent);box-shadow:0 0 8px var(--accent-glow);transition:width .25s ease}
.cbk-tools{display:flex;gap:6px;flex-shrink:0}
.cbk-icon{width:32px;height:32px;border-radius:8px;border:1px solid rgba(255,255,255,.1);
  background:rgba(255,255,255,.04);color:var(--muted);font-size:15px;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;transition:border-color .15s}
.cbk-icon:hover{border-color:var(--accent)}

/* the open book */
.cbk-spread{position:relative;flex:1;min-height:0;display:flex;padding:14px 18px;perspective:1800px}
.cbk-leaf{flex:1 1 0;min-width:0;display:flex}
.cbk-page{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden;border-radius:4px;
  border:1px solid rgba(255,255,255,.07);
  background:linear-gradient(180deg,rgba(255,255,255,.028),rgba(0,0,0,.10));
  box-shadow:0 10px 30px rgba(0,0,0,.35)}
/* the gutter shadow is what makes two panels read as ONE open book */
.cbk-spread.is-spread .cbk-leaf[data-side="l"] .cbk-page{border-top-right-radius:0;border-bottom-right-radius:0;
  box-shadow:inset -22px 0 26px -24px #000,0 10px 30px rgba(0,0,0,.35)}
.cbk-spread.is-spread .cbk-leaf[data-side="r"] .cbk-page{border-top-left-radius:0;border-bottom-left-radius:0;
  box-shadow:inset 22px 0 26px -24px #000,0 10px 30px rgba(0,0,0,.35)}
.cbk-spine{flex:0 0 2px;width:2px;align-self:stretch;
  background:linear-gradient(180deg,transparent,rgba(0,0,0,.55) 12%,rgba(0,0,0,.55) 88%,transparent)}
/* "it shows the other pages" — the unread block, drawn as stacked page edges */
.cbk-spread.is-spread::before,.cbk-spread.is-spread::after{content:'';position:absolute;top:22px;bottom:22px;
  width:9px;border-radius:3px;pointer-events:none;
  background:repeating-linear-gradient(90deg,rgba(255,255,255,.10) 0 1px,transparent 1px 3px)}
.cbk-spread.is-spread::before{left:9px}
.cbk-spread.is-spread::after{right:9px}

.cbk-head{flex-shrink:0;padding:16px 26px 10px;text-align:center;border-bottom:1px solid rgba(255,255,255,.05)}
.cbk-ref{font:700 10px var(--ui),Inter,sans-serif;color:var(--accent);letter-spacing:1.2px;opacity:.85;margin-bottom:5px}
.cbk-title{font:700 18px/1.3 var(--codex-read)}
.cbk-body{flex:1;min-height:0;overflow-y:auto;padding:4px 0 6px;-webkit-overflow-scrolling:touch}
/* a one-paragraph section used to leave the page 60% empty and read as broken */
.cbk-body.is-short{display:flex;flex-direction:column;justify-content:center}
.cbk-body .codex-content{margin:0;padding:16px 26px;border:none;background:transparent;
  font:400 15px/1.75 var(--codex-read);color:var(--text)}
.cbk-body .cbk-note{color:var(--muted);font-style:italic;text-align:center}
.cbk-num{flex-shrink:0;padding:8px 26px 12px;text-align:center;letter-spacing:1px;
  font:500 10.5px var(--ui),Inter,sans-serif;color:var(--muted-2)}

.cbk-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 18px 12px;
  flex-shrink:0;border-top:1px solid rgba(0,230,255,.06)}
.cbk-nav{padding:9px 18px;border-radius:9px;border:1px solid rgba(0,230,255,.16);
  background:rgba(0,230,255,.05);color:var(--accent);font:600 13px var(--ui),Inter,sans-serif;
  cursor:pointer;white-space:nowrap;transition:background .15s}
.cbk-nav:hover:not(:disabled){background:rgba(0,230,255,.12)}
.cbk-nav:disabled{opacity:.28;cursor:default}
.cbk-hint{flex:1;min-width:0;text-align:center;font:500 10.5px var(--ui),Inter,sans-serif;
  color:var(--muted-2);letter-spacing:.5px}

/* the turn */
@keyframes cbkTurnNext{from{opacity:0;transform:rotateY(-11deg) translateX(16px)}to{opacity:1;transform:none}}
@keyframes cbkTurnPrev{from{opacity:0;transform:rotateY(11deg) translateX(-16px)}to{opacity:1;transform:none}}
.cbk-turn-next .cbk-page{transform-origin:left center;animation:cbkTurnNext .34s cubic-bezier(.22,.61,.36,1) both}
.cbk-turn-prev .cbk-page{transform-origin:right center;animation:cbkTurnPrev .34s cubic-bezier(.22,.61,.36,1) both}
.cbk-turn-next .cbk-leaf[data-side="r"] .cbk-page{animation-delay:.05s}
.cbk-turn-prev .cbk-leaf[data-side="l"] .cbk-page{animation-delay:.05s}
@media(prefers-reduced-motion:reduce){.cbk-turn-next .cbk-page,.cbk-turn-prev .cbk-page{animation:none}}

@media(max-width:900px){
  .cbk-bar{padding:8px 12px;gap:8px}
  .cbk-x{padding:5px 9px;font-size:11px}
  .cbk-icon{width:29px;height:29px;font-size:14px}
  .cbk-spread{padding:8px 10px}
  .cbk-head{padding:13px 16px 9px}
  .cbk-title{font-size:16px}
  .cbk-body .codex-content{padding:12px 16px;font-size:14.5px;line-height:1.72}
  .cbk-num{padding:7px 16px 10px}
  /* clear the bottom tab bar */
  .cbk-foot{padding:8px 10px 16px}
  .cbk-nav{padding:9px 13px;font-size:12.5px}
  .cbk-hint{font-size:10px}
}
.codex-content ul,.codex-content ol{padding-left:24px;margin:4px 0}
.codex-content li{margin:2px 0}
/* ── v9.10.516 — Codex readability (owner request) ───────────────────────────
   (a) 2-column key/value tables: give the label column a real fixed width so it
       stops collapsing to one letter per line beside a giant value cell.
   (b) section headings: h2/h3/h4 used to be near-identical inline styles
       (16/14/13px, all accent, all bold) so nothing read as a hierarchy.
       They now emit .codex-h2/.codex-h3/.codex-h4 and are styled here. */
.codex-table[data-cols="2"]{table-layout:fixed}
.codex-table[data-cols="2"] th:first-child,.codex-table[data-cols="2"] td:first-child{width:190px;vertical-align:top}
.codex-table[data-cols="2"] th:last-child,.codex-table[data-cols="2"] td:last-child{vertical-align:top}
.codex-table th,.codex-table td{overflow-wrap:anywhere}
.codex-tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:8px 0;max-width:100%}
.codex-tablewrap>.codex-table{margin:0;min-width:100%;width:auto}
.codex-content .codex-h{font-family:var(--ui),Inter,sans-serif;letter-spacing:.2px}
.codex-content .codex-h2{font-size:19px;font-weight:800;color:var(--accent);margin:22px 0 8px;padding-bottom:6px;
  border-bottom:1px solid rgba(0,230,255,.14);text-shadow:0 0 14px rgba(0,230,255,.12)}
.codex-content .codex-h3{font-size:15.5px;font-weight:700;color:var(--text);margin:18px 0 6px}
.codex-content .codex-h4{font-size:12.5px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.8px;margin:14px 0 5px}
/* ── v9.10.516 — READING FACE ────────────────────────────────────────────────
   The Dragon's Breath theme sets --ui:'Cinzel'. Cinzel is a Roman inscriptional
   face with NO lowercase — its lowercase codepoints ARE small capitals. That is
   correct and handsome for buttons, tabs and titles, and unreadable for twelve
   thousand words of body prose. Reading surfaces below get a real lowercase
   serif; every other surface keeps the theme font untouched.
   To revert the whole decision: delete this block. */
:root{--codex-read:Georgia,'Iowan Old Style','Palatino Linotype',Palatino,'Times New Roman',serif}
.codex-content,.codex-content p,.codex-content li,.codex-content td,.codex-content th,
.codex-frontmatter,.codex-content .codex-h3{font-family:var(--codex-read)}
.codex-book-body .codex-content{font-family:var(--codex-read)}
/* the label column of a key/value table stays in the theme face — short, and it
   is a label, not prose */
.codex-table[data-cols="2"] th:first-child,.codex-table[data-cols="2"] td:first-child{font-family:var(--ui),Inter,sans-serif}
@media(max-width:900px){
  .codex-header{padding:14px 16px 12px}
  .codex-main-title{font-size:18px}
  .codex-entry-head{padding:10px 12px 10px 0}
  .codex-entry-title{font-size:13px}
  .codex-content{padding:8px 16px 16px 16px;font-size:13px}
  .codex-tab-bar{padding:0 16px}
  .codex-tab{padding:8px 14px;font-size:12px}
  .codex-law-title{font-size:20px;padding:14px 16px 10px}
  .codex-breadcrumb{padding:6px 16px}
  .codex-article-header{padding:12px 16px}
  .codex-library-grid{grid-template-columns:1fr;padding:12px 16px;gap:10px}
  .codex-category-header{padding:12px 16px 6px}
  .codex-changelog-zone{padding:10px 16px}
  /* v9.10.516 — owner: "it should be above on mobile".
     Key/value tables stack into one card per row, label line ABOVE the value. */
  .codex-table[data-cols="2"]{table-layout:auto;display:block;font-size:13px;margin:10px 0}
  .codex-table[data-cols="2"] thead,.codex-table[data-cols="2"] tbody,.codex-table[data-cols="2"] tr{display:block;width:100%}
  .codex-table[data-cols="2"] tr{border:1px solid rgba(255,255,255,.09);border-radius:10px;
    background:rgba(255,255,255,.015);margin:0 0 8px;overflow:hidden}
  .codex-table[data-cols="2"] th,.codex-table[data-cols="2"] td{display:block;width:auto;border:none;padding:0}
  .codex-table[data-cols="2"] tr>*:first-child{font:700 10.5px var(--ui),Inter,sans-serif;color:var(--accent);
    text-transform:uppercase;letter-spacing:.7px;background:rgba(0,230,255,.05);
    border-bottom:1px solid rgba(0,230,255,.09);padding:7px 12px 6px}
  .codex-table[data-cols="2"] tr>*:last-child{font:400 13px/1.65 var(--ui),Inter,sans-serif;color:var(--text);
    background:transparent;padding:9px 12px 11px}
  /* 3+ columns: scroll sideways instead of squeezing to one letter per line */
  .codex-table:not([data-cols="2"]){display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;font-size:12px}
  .codex-table:not([data-cols="2"]) th,.codex-table:not([data-cols="2"]) td{min-width:104px}
  .codex-content .codex-h2{font-size:17px;margin:18px 0 7px}
  .codex-content .codex-h3{font-size:14.5px;margin:14px 0 5px}
  .codex-content .codex-h4{font-size:11.5px;margin:12px 0 4px}
  /* v9.10.516 fix-up — the desktop rule above pins the label column to 190px and
     outranks the generic mobile th/td rule, so the stacked label bar stopped
     short of the card edge. Undo the width here explicitly. */
  .codex-table[data-cols="2"] th:first-child,.codex-table[data-cols="2"] td:first-child,
  .codex-table[data-cols="2"] th:last-child,.codex-table[data-cols="2"] td:last-child{width:auto;display:block}
  .codex-table[data-cols="2"] tr>*:last-child{font-family:var(--codex-read)}
  /* v9.10.516 — TOC rows: three action buttons plus a "N lines" counter left
     roughly 120px for the title, so every entry truncated to "RECURSIVE SPAR...".
     Drop the counter, shrink the buttons, let the title wrap to three lines. */
  .codex-entry-head{gap:5px;padding:10px 10px 10px 0;align-items:flex-start}
  .codex-entry-title{font:600 13.5px/1.4 var(--codex-read);white-space:normal;text-overflow:clip;
    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
  .codex-entry-lines{display:none}
  .codex-tts-btn,.codex-ai-btn{padding:5px 7px;font-size:13px;line-height:1}
  .codex-arrow{margin-top:2px}
  /* the breadcrumb repeated the title verbatim at root level ("The KAI Codex"
     under "The KAI Codex"). Hide it until it actually has a trail. */
  .codex-breadcrumb:not(:has(.bc-sep)){display:none}
  /* library cards: calmer stripe, two-line titles instead of an ellipsis */
  .codex-doc-card .card-stripe{height:2px;opacity:.75}
  .codex-doc-card .card-body{padding:11px 13px}
  .codex-doc-card .card-title{font:600 13.5px/1.35 var(--codex-read);white-space:normal;text-overflow:clip;overflow-wrap:anywhere;
    display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden}
  .codex-doc-card .card-body{min-height:0}
  /* let the last row clear the bottom tab bar */
  .codex-toc,.codex-library-grid{padding-bottom:28px}
}
.gpost-stats{display:flex;flex-wrap:wrap;gap:14px;padding:10px 0;border-top:1px solid rgba(255,255,255,.06);border-bottom:1px solid rgba(255,255,255,.06);margin:10px 0 0;font:500 12px var(--ui),Inter,sans-serif;color:var(--muted)}
.gpost-stats span{transition:color .15s;cursor:default}
.gpost-stats span:hover{color:var(--text)}
.gpost-acts{display:flex;flex-wrap:wrap;gap:2px;margin:0;padding:6px 0 2px}
.gpost-acts button{flex:1;text-align:center;padding:9px 4px;border:none;border-radius:10px;background:transparent;color:var(--muted);
  font:600 13px var(--ui),Inter,sans-serif;cursor:pointer;transition:background .15s,color .15s,transform .1s;display:flex;align-items:center;justify-content:center;gap:6px}
.gpost-acts button:hover{background:rgba(255,255,255,.07);color:var(--text);transform:translateY(-0.5px)}
.gpost-acts button:active{transform:translateY(0)}
.gpost-acts button.on{color:var(--accent);background:rgba(34,217,230,.08)}
/* v9.10.500 — bookmark button in action bar */
.gpost-acts button.on svg[viewBox="0 0 24 24"] path[d*="M19 21l-7"]{filter:drop-shadow(0 0 3px var(--accent))}
.gpost-emotes{display:flex;gap:4px;margin-top:6px;flex-wrap:wrap;max-height:0;opacity:0;overflow:hidden;transition:max-height .2s ease,opacity .2s ease}
.gpost-emotes.open{max-height:200px;opacity:1}
.gpost-emotes button{border:none;background:rgba(255,255,255,.06);border-radius:8px;padding:4px 8px;font-size:16px;cursor:pointer;transition:background .12s,transform .1s}
.gpost-emotes button:hover{background:rgba(255,255,255,.12);transform:scale(1.1)}
/* v9.10.353 — belt-and-braces: expanded comments can never exceed the card, and a
   long unbroken string (URL/token) wraps instead of pushing the page wide.
   v9.10.354 — `overflow-x:hidden` REMOVED from this rule. Per CSS overflow, when
   one axis is not `visible` the other computes to `auto` — so overflow-x:hidden
   silently turned this into a SCROLL CONTAINER. Never set a single-axis overflow
   on anything inside the .home-scroll flex column. max-width alone is enough. */
.gpost-comments{margin-top:8px;background:transparent;max-width:100%;max-height:0;opacity:0;overflow:hidden;transition:max-height .25s ease,opacity .2s ease}
.gpost-comments.open{max-height:2000px;opacity:1;overflow:visible}
.gpost-cmt{display:flex;gap:8px;align-items:flex-start;padding:9px 0;border-bottom:1px solid rgba(255,255,255,.04);min-width:0;max-width:100%;transition:background .12s;border-radius:6px;margin:0 -4px;padding-left:4px;padding-right:4px}
.gpost-cmt:hover{background:rgba(255,255,255,.02)}
.gpost-cmt:last-child{border-bottom:none}
.gpost-cmt-body{flex:1 1 auto;min-width:0;font-size:13px;line-height:1.45;overflow-wrap:anywhere;word-break:break-word}
.gpost-cmt-body b{color:var(--accent);font-size:12px;font-weight:700}
/* v9.10.317 — comment-level engagement (like/emote/reply per comment) */
.gpost-cmt-acts{display:flex;gap:14px;margin-top:5px;align-items:center;flex-wrap:wrap}
.gpost-cmt-acts button{background:none;border:none;color:var(--muted);cursor:pointer;font:600 11px Inter,sans-serif;padding:0;display:inline-flex;align-items:center;gap:4px}
.gpost-cmt-acts button:hover{color:var(--text)}
.gpost-cmt-acts button.on{color:var(--accent)}
.gpost-cmt-rx{font-size:11px;color:var(--muted)}
.gpost-cmt-emotes{display:flex;gap:4px;margin-top:5px;flex-wrap:wrap;max-height:0;opacity:0;overflow:hidden;transition:max-height .2s ease,opacity .2s ease}
.gpost-cmt-emotes.open{max-height:200px;opacity:1}
.gpost-cmt-emotes button{border:none;background:rgba(255,255,255,.06);border-radius:7px;padding:2px 6px;font-size:14px;cursor:pointer}
.gpost-replies{margin:6px 0 2px 36px;border-left:2px solid rgba(255,255,255,.07);padding-left:10px}
.gpost-reply-form{display:flex;gap:6px;align-items:center;margin-top:6px;max-height:0;opacity:0;overflow:hidden;transition:max-height .2s ease,opacity .2s ease}
.gpost-reply-form.open{max-height:80px;opacity:1}
.gpost-reply-form input{flex:1;min-width:0;border-radius:16px;border:1px solid var(--border);background:rgba(0,0,0,.35);color:var(--text);padding:6px 12px;font-size:12px;outline:none}
.gpost-reply-form input:focus{border-color:rgba(34,217,230,.4)}
.gpost-reply-form button{border:none;border-radius:16px;padding:6px 12px;background:var(--accent);color:#04070d;font:700 10px Outfit,sans-serif;cursor:pointer;white-space:nowrap}
/* v9.10.353 — HORIZONTAL-OVERFLOW FIX. The composer row is a flex row; the <input>
   had flex:1 but NOT min-width:0, so its automatic minimum size (min-width:auto ≈
   the default `size` ~20ch + 28px padding ≈ 205px) stopped it shrinking. avatar +
   gaps + Send + card padding then exceeded a 360px viewport, and the overflow
   widened the whole PAGE (sideways panning). .gpost-reply-form input (above) and
   .gsheet-foot .gpost-cmt-form input (below) already had min-width:0 — this one
   was simply missed. Also cap the row so it can never exceed the card. */
.gpost-cmt-form{display:flex;gap:8px;align-items:center;margin-top:10px;min-width:0;max-width:100%}
.gpost-cmt-form input{flex:1 1 auto;min-width:0;width:0;border-radius:20px;border:1px solid var(--border);background:rgba(0,0,0,.35);color:var(--text);padding:8px 14px;font-size:13px;outline:none}
.gpost-cmt-form>:not(input){flex-shrink:0}
.gpost-cmt-form input:focus{border-color:rgba(34,217,230,.4)}
.gpost-cmt-form button{border:none;border-radius:20px;padding:8px 14px;background:var(--accent);color:#04070d;font:700 11px Outfit,sans-serif;cursor:pointer;white-space:nowrap}
/* v9.10.297: immersive TikTok/YouTube-Shorts vertical feed — snap one short per
   screen, scroll up/down to the next. The feed is its own scroll container so it
   pages instead of scrolling like a document. */
.gshorts-feed{display:flex;flex-direction:column;align-items:center;gap:0;height:calc(100vh - 210px);max-height:900px;overflow-y:auto;scroll-snap-type:y mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none;overscroll-behavior:contain}
.gshorts-feed::-webkit-scrollbar{display:none}
.gshort-card{position:relative;width:100%;max-width:440px;height:100%;flex:0 0 100%;scroll-snap-align:start;scroll-snap-stop:always;border-radius:16px;overflow:hidden;background:#0a0e14;display:flex;flex-direction:column;justify-content:flex-end}
@media (max-width:900px){ .gshorts-feed{height:calc(100vh - 150px)} .gshort-card{max-width:100%;border-radius:0} }
.gshort-card .gshort-bg{position:absolute;inset:0;background-size:cover;background-position:center}
.gshort-card .gshort-bg video{width:100%;height:100%;object-fit:cover}
.gshort-card .gshort-bg img{width:100%;height:100%;object-fit:cover}
.gshort-card .gshort-grad{position:absolute;inset:0;background:linear-gradient(transparent 40%,rgba(0,0,0,.85))}
/* v9.10.494 — poster handle + caption must sit CLEAR of the centred (+) create FAB
   (bottom-centre) and the right action rail. padding-bottom lifts the text above the
   FAB band (tunable via --gshort-cta-clear); padding-right keeps it off the rail.
   Longhands only (never re-add the shorthand — it would reset these). */
.gshort-card .gshort-overlay{position:relative;padding-top:16px;padding-right:64px;padding-bottom:var(--gshort-cta-clear,92px);padding-left:16px;z-index:1}
.gshort-card .gshort-author{display:flex;gap:10px;align-items:center;margin-bottom:8px}
.gshort-card .gshort-author img{width:36px;height:36px;border-radius:50%;border:2px solid rgba(255,255,255,.3)}
.gshort-card .gshort-author-name{font-weight:700;font-size:14px;color:#fff}
.gshort-card .gshort-caption{font-size:14px;line-height:1.4;color:#eee;word-break:break-word}
.gshort-actions{position:absolute;right:12px;bottom:80px;display:flex;flex-direction:column;gap:16px;align-items:center;z-index:2}
.gshort-actions button{background:rgba(255,255,255,.12);border:none;border-radius:50%;width:44px;height:44px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#fff;transition:background .15s}
.gshort-actions button:hover{background:rgba(255,255,255,.25)}
.gshort-actions .gshort-count{font-size:11px;color:rgba(255,255,255,.8);margin-top:-8px;text-align:center}
/* v9.10.495 — expanded right rail: avatar + subscribe badge (top) and a "…" menu. */
.gshort-actions .gshort-rail-av{position:relative;display:flex;flex-direction:column;align-items:center;margin-bottom:6px}
.gshort-actions .gshort-rail-av > span{cursor:pointer;display:block;line-height:0}
.gshort-actions .gshort-rail-av img{width:46px;height:46px;border-radius:50%;border:2px solid rgba(255,255,255,.85)}
.gshort-actions .gshort-follow{position:absolute;bottom:-9px;left:50%;transform:translateX(-50%);width:20px;height:20px;min-width:0;border-radius:50%;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border:2px solid #0a0e14;font-size:13px;line-height:1;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer}
.gshort-actions .gshort-follow.on{background:#22c55e}
.gshort-menu{position:absolute;z-index:70;min-width:180px;background:rgba(18,24,38,.98);border:1px solid var(--border);border-radius:12px;padding:6px;box-shadow:0 10px 30px rgba(0,0,0,.5);display:flex;flex-direction:column;gap:2px}
.gshort-menu button{background:transparent;border:none;color:var(--text);text-align:left;padding:10px 12px;border-radius:8px;font:500 13px Outfit,sans-serif;cursor:pointer;white-space:nowrap}
.gshort-menu button:hover{background:rgba(255,255,255,.08)}
.gshort-card .gshort-bg video{cursor:pointer}
.gshort-sound{position:absolute;top:12px;left:12px;z-index:2;background:rgba(0,0,0,.55);color:#fff;font-size:11px;font-weight:600;padding:5px 10px;border-radius:999px;cursor:pointer;backdrop-filter:blur(4px);user-select:none}
.gshort-comments-panel{display:none;background:rgba(13,19,32,.95);border:1px solid var(--border);border-radius:14px;padding:14px;margin-top:10px;max-width:380px;width:100%}
.gshort-comments-panel.open{display:block}
/* ── v9.10.340 — Shorts Phase 1: YouTube-Shorts immersive layout ──────────────
   When the Shorts tab is active we strip the home padding + pager chrome so the
   video fills the content area edge-to-edge; the creation composer moves out of
   the feed and into a (+) bottom-sheet, and comments open in a bottom sheet.
   All gated behind body.guest-shorts-active so nothing else is touched. */
@media(max-width:900px){
  body.guest-shorts-active .home-scroll{padding:0 !important;gap:0 !important;overflow:hidden}
  body.guest-shorts-active .guest-dash{padding:0 !important;height:100%}
  body.guest-shorts-active #guest-tab-body{height:100%}
  body.guest-shorts-active .ghome-pager-dots{display:none}
  body.guest-shorts-active .gshorts-feed{height:100%;max-height:none;max-width:none}
  body.guest-shorts-active .gshort-card{max-width:none;border-radius:0}
}
@media(min-width:901px){
  /* desktop keeps the Feed/Shorts/Me tab row; just remove the form + give the column height */
  body.guest-shorts-active .gshorts-feed{height:calc(100vh - 150px)}
}
/* scoped-to-uploader header bar (tap a handle → their shorts page) */
body.guest-shorts-active #guest-tab-body{position:relative}
.gshorts-scopebar{display:flex;align-items:center;gap:9px;position:absolute;top:10px;left:10px;z-index:6;background:rgba(0,0,0,.55);color:#fff;padding:6px 12px 6px 8px;border-radius:999px;backdrop-filter:blur(6px);font-size:13px;font-weight:600}
.gshorts-scopebar .gshorts-scopeback{background:rgba(255,255,255,.16);border:none;color:#fff;width:24px;height:24px;border-radius:50%;cursor:pointer;font-size:15px;line-height:1;display:flex;align-items:center;justify-content:center}
.gshort-author-name{cursor:pointer}
.gshort-author img{cursor:pointer}
/* ── v9.10.341 Shorts Phase 2 — For You/Popular toggle, channel header, #tags ── */
.gshorts-modebar{display:flex;gap:6px;position:absolute;top:10px;left:50%;transform:translateX(-50%);z-index:6;background:rgba(0,0,0,.5);padding:4px;border-radius:999px;backdrop-filter:blur(6px)}
.gshorts-mode{background:transparent;border:none;color:rgba(255,255,255,.72);font:600 12px Outfit,sans-serif;padding:5px 14px;border-radius:999px;cursor:pointer}
.gshorts-mode.on{background:#fff;color:#04070d}
/* v9.10.496 — hashtag discovery: modebar "#" button, trending chips, tag-view sort. */
.gshorts-modebar .gshorts-discover{font-weight:700}
.gshorts-tagsort{display:flex;gap:4px;margin-left:auto;background:rgba(0,0,0,.35);padding:3px;border-radius:999px}
.gshorts-tagsort .gshorts-mode{padding:4px 12px;font-size:11px}
.gshort-trending{display:flex;flex-wrap:wrap;gap:8px}
.gshort-tagchip{display:inline-flex;align-items:center;gap:7px;background:rgba(90,209,255,.12);border:1px solid rgba(90,209,255,.3);color:#5ad1ff;border-radius:999px;padding:7px 13px;font:600 13px Outfit,sans-serif;cursor:pointer}
.gshort-tagchip:hover{background:rgba(90,209,255,.2)}
.gshort-tagchip .gshort-tagcount{color:rgba(255,255,255,.55);font-weight:500;font-size:11px}
.gshorts-channelhead{display:flex;align-items:center;gap:11px;position:absolute;top:10px;left:10px;right:10px;z-index:6;background:rgba(0,0,0,.6);color:#fff;padding:8px 12px;border-radius:16px;backdrop-filter:blur(8px)}
.gshorts-channelhead .gshorts-scopeback{background:rgba(255,255,255,.16);border:none;color:#fff;width:26px;height:26px;border-radius:50%;cursor:pointer;font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.gshorts-channelhead .gch-av img{width:44px;height:44px;border-radius:50%;border:2px solid rgba(255,255,255,.28)}
.gshorts-channelhead .gch-meta{flex:1 1 auto;min-width:0}
.gshorts-channelhead .gch-name{font-weight:700;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gshorts-channelhead .gch-sub{font-size:11px;color:rgba(255,255,255,.6)}
.gch-subbtn{flex:0 0 auto;border:none;border-radius:999px;padding:8px 16px;font:700 12px Outfit,sans-serif;cursor:pointer;background:#ff2d55;color:#fff}
.gch-subbtn.on{background:rgba(255,255,255,.16);color:#fff}
.gch-selfbadge{flex:0 0 auto;font-size:11px;color:rgba(255,255,255,.6);padding:6px 10px;border:1px solid rgba(255,255,255,.2);border-radius:999px}
.gshort-caption .gtag,.gpost-text .gtag{color:#5ad1ff;font-weight:600;cursor:pointer}
/* ── v9.10.346 — @mention autocomplete + mention links + mini profile card ──── */
.gshort-caption .gmention,.gpost-text .gmention,.gpost-cmt .gmention{color:#a78bfa;font-weight:600;cursor:pointer}
.gshort-caption .gmention:hover,.gpost-text .gmention:hover{text-decoration:underline}
#mention-box{position:fixed;z-index:6800;display:none;flex-direction:column;max-height:262px;overflow-y:auto;
  background:linear-gradient(180deg,#111a2b,#0b1220);border:1px solid rgba(167,139,250,.3);border-radius:12px;
  box-shadow:0 14px 40px rgba(0,0,0,.55);padding:4px}
#mention-box.open{display:flex}
#mention-box .mb-row{display:flex;align-items:center;gap:9px;width:100%;border:none;background:transparent;
  color:#d7e0ee;font:600 13px Outfit,sans-serif;padding:8px 9px;border-radius:9px;cursor:pointer;text-align:left}
#mention-box .mb-row.on,#mention-box .mb-row:hover{background:rgba(167,139,250,.16)}
#mention-box .mb-row img{width:28px;height:28px;border-radius:50%;object-fit:cover;background:rgba(255,255,255,.06);flex-shrink:0}
#mention-box .mb-n{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#mention-box .mb-h{color:var(--muted);font-weight:500;font-size:12px;white-space:nowrap}
#mention-box .mb-f{margin-left:auto;font-size:10px;color:var(--accent);flex-shrink:0}
#mention-card{position:fixed;z-index:6900;display:none;width:250px;padding:14px;
  background:linear-gradient(180deg,#141d2f,#0c1322);border:1px solid rgba(167,139,250,.32);border-radius:14px;
  box-shadow:0 18px 50px rgba(0,0,0,.6)}
/* v9.10.361 — never wider than a narrow phone, so the horizontal clamp in
   mcPositionCard() always has a real solution. No overflow property is used. */
#mention-card{max-width:calc(100vw - 16px)}
#mention-card.open{display:block}
#mention-card .mc-top{display:flex;align-items:center;gap:10px}
#mention-card .mc-top img{width:46px;height:46px;border-radius:50%;object-fit:cover;background:rgba(255,255,255,.06)}
#mention-card .mc-n{font:700 14px Outfit,sans-serif;color:#eef3fb}
#mention-card .mc-h{font-size:12px;color:var(--muted)}
#mention-card .mc-acts{display:flex;gap:7px;margin-top:12px}
#mention-card .mc-acts button{flex:1;border:none;border-radius:9px;padding:8px;font:700 12px Outfit,sans-serif;cursor:pointer}
#mention-card .mc-add{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff}
#mention-card .mc-msg{background:rgba(255,255,255,.08);color:#d7e0ee}
#mention-card .mc-state{font-size:11.5px;color:var(--accent);margin-top:10px;text-align:center}
/* ── v9.10.347 — post-detail page (post + comments + Back) ─────────────────── */
#post-detail-overlay{position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.82);backdrop-filter:blur(4px);
  display:flex;align-items:flex-start;justify-content:center;padding:24px 14px 40px;overflow-y:auto}
#post-detail-overlay .pd-wrap{position:relative;max-width:640px;width:100%}
#post-detail-overlay .pd-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}
#post-detail-overlay .pd-back{background:rgba(34,217,230,.14);border:1px solid rgba(34,217,230,.3);color:var(--accent);
  font:700 13px Outfit,sans-serif;padding:9px 15px;border-radius:10px;cursor:pointer}
#post-detail-overlay .pd-back:hover{background:rgba(34,217,230,.24)}
#post-detail-overlay .pd-x{background:rgba(255,255,255,.1);border:none;color:#fff;width:34px;height:34px;
  border-radius:50%;cursor:pointer;font-size:15px;flex-shrink:0}
body.pd-open{overflow:hidden}
@media(max-width:900px){ #post-detail-overlay{padding:12px 8px 30px} }
#notif-panel .np-item.np-clickable:hover{background:rgba(34,217,230,.12) !important}
/* ── v9.10.356 user-profile overlay ── additive, body-appended, position:fixed.
   Touches NO existing container/layout selector; mirrors #post-detail-overlay. */
.uname-link{cursor:pointer}
.uname-link:active{opacity:.6}
/* ── v9.10.430 — PROFILE IS A PAGE, NOT A POPUP ──────────────────────────────
   Owner: "it shouldn't be a popup, it should be a page it goes to."
   These rules used to hang off #usrprof-overlay, a position:fixed full-screen
   floating card. They now target #view-profile, an ordinary .view-pane, so the
   profile occupies the content area under the app's own top bar and bottom nav
   exactly like Home / Messages / KAIVERSE.
   NOTE: no `position:fixed` and NO `overflow` property is declared anywhere in
   this block — the pane scrolls by reusing the existing .cfg-scroll container on
   #usrprof-inner. Padding/margin longhands only. */
#view-profile .upage-bar{display:flex;align-items:center;justify-content:space-between;
  gap:8px;padding-top:10px;padding-right:12px;padding-bottom:10px;padding-left:12px;
  border-bottom:1px solid rgba(255,255,255,.07);flex-shrink:0}
#view-profile .upage-bar button{border:none;background:transparent;color:var(--muted);
  cursor:pointer;font:600 13px Outfit,sans-serif}
#view-profile .upage-back{color:#22d9e6}
#view-profile .upage-acts{display:flex;gap:8px;align-items:center}
#view-profile .upage-body{padding-top:0;padding-right:0;padding-bottom:28px;padding-left:0;gap:0}
#view-profile .up-cover{height:96px;background:linear-gradient(135deg,#1b2740,#0d1524)}
#view-profile .up-id{display:flex;gap:12px;align-items:center;padding:0 14px 12px;margin-top:-26px}
#view-profile .up-nm{font:700 17px Outfit,sans-serif;color:#eef3fb}
#view-profile .up-hd{font-size:12px;color:var(--muted);margin-top:2px}
#view-profile .up-bio{padding:0 14px 10px;font-size:13px;color:#c8d3e2;line-height:1.45}
#view-profile .up-stats{display:flex;gap:16px;padding:0 14px 12px;font-size:11.5px;color:var(--muted);flex-wrap:wrap}
#view-profile .up-stats b{color:#eef3fb;font-size:13px}
#view-profile .up-acts{display:flex;gap:8px;padding:0 14px 14px;flex-wrap:wrap}
#view-profile .up-acts button{border:1px solid rgba(34,217,230,.3);background:rgba(34,217,230,.1);
  color:#22d9e6;border-radius:9px;padding:7px 14px;font:600 12.5px Outfit,sans-serif;cursor:pointer}
#view-profile .up-acts button[disabled]{opacity:.5;cursor:default}
#view-profile .up-tabs{display:flex;border-top:1px solid rgba(255,255,255,.07)}
#view-profile .up-tabs button{flex:1;border:none;background:transparent;color:var(--muted);
  padding:10px;font:600 12.5px Outfit,sans-serif;cursor:pointer;border-bottom:2px solid transparent}
#view-profile .up-tabs button.on{color:#22d9e6;border-bottom-color:#22d9e6}
#view-profile .up-body{padding:12px}
#view-profile .up-empty{padding:26px;text-align:center;color:var(--muted);font-size:12.5px}
#view-profile .up-item{padding:10px 12px;border:1px solid rgba(255,255,255,.06);
  border-radius:11px;margin-bottom:8px;background:rgba(255,255,255,.02)}
#view-profile .up-item .up-t{font-size:13px;color:#dbe4f0;line-height:1.45;white-space:pre-wrap;word-break:break-word}
#view-profile .up-item .up-m{font-size:10.5px;color:var(--muted-2);margin-top:5px}
body.up-open{overflow:hidden}
.gshort-caption .gtag:hover,.gpost-text .gtag:hover{text-decoration:underline}
/* center-bottom (+) create FAB — sits above the mobile bottom nav (YouTube-style) */
/* v9.10.494 — centred create (+) button, enlarged modestly (52 -> 60px). Stays
   horizontally centred (left:50% + translateX). Size is easy to re-tune here. */
.gshort-fab{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(60px + env(safe-area-inset-bottom));z-index:60;width:60px;height:60px;border-radius:18px;border:none;cursor:pointer;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:34px;font-weight:300;line-height:1;display:none;align-items:center;justify-content:center;box-shadow:0 6px 20px rgba(99,102,241,.5)}
.gshort-fab.on{display:flex}
.gshort-fab:active{transform:translateX(-50%) scale(.94)}
@media(min-width:901px){ .gshort-fab{bottom:26px;border-radius:50%} }
/* bottom sheets (comments + create) — YouTube-style slide-up panels */
.gsheet-backdrop{position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.45);display:none}
.gsheet-backdrop.open{display:block}
.gsheet{position:fixed;left:0;right:0;bottom:0;z-index:201;background:var(--panel-solid,#0d1320);border-top-left-radius:18px;border-top-right-radius:18px;border-top:1px solid var(--border);max-height:76dvh;display:flex;flex-direction:column;transform:translateY(102%);transition:transform .24s ease,opacity .24s ease,visibility .24s ease;padding-bottom:env(safe-area-inset-bottom);opacity:0;visibility:hidden;pointer-events:none}
/* v9.10.342 — a CLOSED sheet must fully disappear. On mobile bottom:0 + translateY(102%)
   cleared the viewport, but the desktop override (bottom:24px) left the translate short by
   that offset, so a ~20px sliver of the create/comments sheet leaked at the bottom-right of
   the desktop feed. opacity/visibility/pointer-events guarantee it's gone until .open. */
.gsheet.open{transform:translateY(0);opacity:1;visibility:visible;pointer-events:auto}
@media(min-width:901px){ .gsheet{left:auto;right:24px;width:430px;bottom:24px;border-radius:16px;max-height:72vh} }
.gsheet-hd{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--border);font-weight:700;font-size:14px;color:#fff;flex:0 0 auto}
.gsheet-hd .gsheet-x{background:rgba(255,255,255,.1);border:none;color:#fff;width:28px;height:28px;border-radius:50%;cursor:pointer;font-size:16px;line-height:1}
.gsheet-body{overflow-y:auto;padding:12px 16px;flex:1 1 auto;min-height:60px}
.gsheet-foot{border-top:1px solid var(--border);padding:10px 12px;flex:0 0 auto}
.gsheet-foot .gpost-cmt-form{display:flex;gap:8px}
.gsheet-foot .gpost-cmt-form input{flex:1;min-width:0;padding:9px 12px;border-radius:999px;border:1px solid var(--border);background:rgba(0,0,0,.3);color:var(--text);font-size:13px;outline:none}
.gsheet-foot .gpost-cmt-form button{border:none;border-radius:999px;padding:9px 16px;background:var(--accent);color:#04070d;font-weight:700;font-size:13px;cursor:pointer}
/* v9.10.511 — polished composer */
.gpost-composer{background:rgba(13,19,32,.78);border:1px solid rgba(255,255,255,.08);border-radius:16px;
  padding:16px 18px;margin-bottom:16px;backdrop-filter:blur(6px);
  transition:border-color .2s,box-shadow .2s}
.gpost-composer:focus-within{border-color:rgba(99,102,241,.3);box-shadow:0 4px 20px rgba(99,102,241,.08)}
.gcomp-row{display:flex;gap:12px;align-items:flex-start}
.gcomp-text{width:100%;min-height:48px;max-height:200px;border:none;background:transparent;
  border-radius:0;padding:6px 0;color:var(--text);font:15px/1.5 Inter,sans-serif;resize:none;outline:none}
.gcomp-text::placeholder{color:rgba(148,163,184,.6)}
.gcomp-side{display:flex;flex-direction:column;gap:4px;flex-shrink:0;padding-top:4px}
.gcomp-icon{background:none;border:1px solid rgba(255,255,255,.06);border-radius:10px;width:36px;height:36px;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--muted);transition:all .15s}
.gcomp-icon:hover{color:var(--accent);border-color:rgba(34,217,230,.35);background:rgba(34,217,230,.08)}
.gcomp-foot{display:flex;align-items:center;gap:8px;margin-top:10px;border-top:1px solid rgba(255,255,255,.05);padding-top:10px;flex-wrap:wrap}
.gcomp-search{width:100%;padding:8px 12px 8px 30px;border-radius:999px;border:1px solid rgba(255,255,255,.06);
  background:rgba(255,255,255,.03);color:var(--text);font:12px Inter,sans-serif;outline:none;transition:border-color .15s}
.gcomp-search:focus{border-color:rgba(99,102,241,.35)}
.gcomp-post-btn{padding:9px 26px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font:700 13px var(--ui),sans-serif;
  border-radius:999px;border:none;cursor:pointer;box-shadow:0 4px 14px -4px rgba(99,102,241,.5);
  transition:transform .12s,box-shadow .15s,opacity .15s;flex-shrink:0}
.gcomp-post-btn:hover{transform:translateY(-1px);box-shadow:0 6px 18px -4px rgba(99,102,241,.6)}
.gcomp-post-btn:active{transform:translateY(0)}
.gcomp-upload-label{display:inline-flex;align-items:center;gap:5px;padding:6px 12px;border-radius:10px;
  background:rgba(255,255,255,.06);border:1px dashed rgba(255,255,255,.12);color:#c5d0e0;cursor:pointer;font-size:12px;transition:all .15s}
.gcomp-upload-label:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2)}
/* v9.10.513 — composer inline style extraction */
.gcomp-avatar-wrap{cursor:pointer;flex-shrink:0}
.gcomp-textarea-wrap{flex:1;min-width:0}
.gcomp-imgwrap{display:none;margin-top:8px}
.gcomp-img-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.gcomp-url-input{flex:1;min-width:100px;padding:7px 10px;border-radius:10px;border:1px solid var(--border);background:rgba(0,0,0,.35);color:var(--text);font-size:12px}
.gcomp-preview{display:none;margin-top:8px;position:relative}
.gcomp-preview img{max-width:100%;max-height:200px;border-radius:8px;object-fit:cover}
.gcomp-preview-close{position:absolute;top:4px;right:4px;background:rgba(0,0,0,.7);border:none;color:#fff;width:24px;height:24px;border-radius:50%;cursor:pointer;font-size:14px;line-height:1}
.gcomp-emojibar{display:none;margin-top:8px;gap:4px;flex-wrap:wrap}
.gcomp-poll{display:none;margin-top:8px;padding:10px;background:rgba(99,102,241,.06);border:1px solid rgba(99,102,241,.2);border-radius:10px}
.gcomp-poll-label{font:600 11px Outfit,sans-serif;color:#a5b4fc;margin-bottom:8px}
.gcomp-poll-input{width:100%;margin-bottom:6px;padding:8px 10px;border-radius:8px;border:1px solid var(--border);background:rgba(0,0,0,.3);color:var(--text);font-size:13px}
.gcomp-poll-input:last-of-type{margin-bottom:0}
.gcomp-poll-footer{display:flex;align-items:center;gap:8px;margin-top:8px}
.gcomp-poll-footer span{font:11px Outfit,sans-serif;color:var(--muted)}
.gcomp-poll-select{padding:4px 8px;border-radius:6px;border:1px solid var(--border);background:rgba(0,0,0,.3);color:var(--text);font-size:12px}
.gcomp-charcount{font:700 9px JetBrains Mono,monospace;color:var(--muted-2)}
.gcomp-search-icon{position:absolute;left:10px;top:50%;transform:translateY(-50%);opacity:.35;pointer-events:none}
.gcomp-or{color:var(--muted);font-size:11px}
.gcomp-foot-spacer{flex:1;position:relative}
/* ── v9.10.552 — FB-style labeled action chips + X-style char ring ────────── */
.gcomp-actions{display:flex;gap:6px;margin-top:12px;padding-top:10px;border-top:1px solid rgba(255,255,255,.05);flex-wrap:wrap}
.gcomp-chip{display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border-radius:10px;border:none;
  background:transparent;color:#aab8cc;font:600 12.5px var(--ui),sans-serif;cursor:pointer;transition:background .15s,color .15s}
.gcomp-chip:hover{background:rgba(255,255,255,.06);color:var(--text)}
.gcomp-chip.chip-photo svg{color:#45bd62}
.gcomp-chip.chip-feel svg{color:#f7b928}
.gcomp-chip.chip-poll svg{color:#a78bfa}
.gcomp-chip.chip-story svg{color:#f0507a}
.gcomp-chip-hash{color:#22d9e6;font:800 15px var(--ui),sans-serif;line-height:1}
.gcomp-ring-wrap{display:inline-flex;align-items:center;gap:5px;flex-shrink:0}
.gcomp-ring-wrap svg{display:block}
#gcomp-ring{transition:stroke-dashoffset .3s ease,stroke .3s}
.gcomp-post-btn:disabled{opacity:.45;cursor:default;transform:none;box-shadow:none}
@media (max-width:640px){
  .gcomp-row{flex-wrap:wrap}
  .gcomp-actions{gap:2px}
  .gcomp-chip{padding:8px 10px;font-size:11.5px}
}
/* ══ v9.10.552 — REAL STORIES (24h ephemeral, FB/IG model) ══════════════════
   Rail: FB-web-style tall preview cards (~105x170). Unseen = IG conic-gradient
   ring on the mini avatar; seen = gray ring + dimmed card. */
.gstories-row{display:flex;gap:10px;overflow-x:auto;padding:8px 4px 14px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.gstories-row::-webkit-scrollbar{display:none}
.gstory-skel{flex:0 0 auto;width:105px;height:170px;border-radius:14px;background:linear-gradient(110deg,rgba(255,255,255,.04) 30%,rgba(255,255,255,.09) 50%,rgba(255,255,255,.04) 70%);background-size:200% 100%;animation:gskel 1.4s linear infinite}
.gstory-card{flex:0 0 auto;width:105px;height:170px;border-radius:14px;overflow:hidden;cursor:pointer;position:relative;
  background:var(--panel-solid,#0a0f1b);border:1px solid rgba(255,255,255,.09);
  transition:transform .18s,box-shadow .18s;box-shadow:0 4px 14px rgba(0,0,0,.35)}
.gstory-card:hover{transform:translateY(-3px) scale(1.02);box-shadow:0 10px 26px rgba(0,0,0,.5)}
.gstory-card-media{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.gstory-card-snippet{font:700 11px var(--ui),sans-serif;color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.5);
  display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden;text-align:center;line-height:1.35}
.gstory-has-preview::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.18),transparent 35%,transparent 55%,rgba(0,0,0,.62));pointer-events:none}
.gstory-card-name{position:absolute;left:7px;right:7px;bottom:7px;z-index:2;font:700 10.5px var(--ui),sans-serif;color:#fff;
  text-shadow:0 1px 4px rgba(0,0,0,.8);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* IG-signature gradient ring on the author avatar (unseen) vs gray (seen) */
.gstory-ring-av{position:absolute;top:7px;left:7px;z-index:2;width:34px;height:34px;border-radius:50%;padding:2.5px;
  background:conic-gradient(from 45deg,#f9ce34,#ee2a7b,#6228d7,#f9ce34)}
.gstory-ring-av.seen{background:rgba(255,255,255,.25)}
.gstory-ring-av img{width:100%;height:100%;border-radius:50%;object-fit:cover;border:2px solid #0a0f1b;display:block}
.gstory-seen{opacity:.62}
.gstory-count-chip{position:absolute;top:9px;right:9px;z-index:2;font:800 9px var(--ui),sans-serif;color:#fff;
  background:rgba(0,0,0,.55);border:1px solid rgba(255,255,255,.25);padding:2px 7px;border-radius:20px}
.gstory-mini-add{position:absolute;top:9px;left:9px;z-index:3;width:26px;height:26px;border-radius:50%;border:2px solid #fff;
  background:#2f7cf6;color:#fff;font:800 15px/1 var(--ui),sans-serif;cursor:pointer;display:flex;align-items:center;justify-content:center}
/* Create card: your avatar top 2/3, plus-button riding the seam (FB pattern) */
.gstory-create{background:var(--panel-solid,#0a0f1b)}
.gstory-create-top{height:112px;overflow:hidden}
.gstory-create-top img{width:100%;height:100%;object-fit:cover;transition:transform .25s}
.gstory-create:hover .gstory-create-top img{transform:scale(1.06)}
.gstory-create-bottom{position:relative;height:58px;text-align:center;padding-top:20px}
.gstory-create-plus{position:absolute;top:-16px;left:50%;transform:translateX(-50%);width:32px;height:32px;border-radius:50%;
  background:#2f7cf6;color:#fff;font:800 20px/1 var(--ui),sans-serif;display:flex;align-items:center;justify-content:center;
  border:3.5px solid var(--panel-solid,#0a0f1b);transition:transform .18s}
.gstory-create:hover .gstory-create-plus{transform:translateX(-50%) scale(1.12)}
.gstory-create .gstory-card-name{position:static;text-shadow:none;color:var(--text)}
/* ── Story composer modal ── */
#story-composer-ov{position:fixed;inset:0;z-index:99980;background:rgba(2,4,10,.8);backdrop-filter:blur(4px);
  display:flex;align-items:center;justify-content:center;padding:16px}
.stc-panel{width:min(420px,94vw);background:#0c1220;border:1px solid rgba(255,255,255,.1);border-radius:18px;
  box-shadow:0 24px 70px rgba(0,0,0,.6);overflow:hidden;display:flex;flex-direction:column;max-height:92vh}
.stc-head{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid rgba(255,255,255,.07)}
.stc-title{font:800 15px var(--ui),sans-serif;color:var(--text)}
.stc-ttl-hint{font:11px var(--ui),sans-serif;color:var(--muted);flex:1}
.stc-x{width:32px;height:32px;border-radius:50%;border:none;background:rgba(255,255,255,.07);color:var(--text);
  font-size:18px;cursor:pointer;transition:background .15s}
.stc-x:hover{background:rgba(255,255,255,.14)}
.stc-tabs{display:flex;gap:6px;padding:10px 16px 0}
.stc-tabs button{flex:1;padding:8px 0;border-radius:10px;border:1px solid rgba(255,255,255,.08);background:transparent;
  color:var(--muted);font:700 12px var(--ui),sans-serif;cursor:pointer;transition:all .15s}
.stc-tabs button.on{background:rgba(47,124,246,.16);border-color:rgba(47,124,246,.45);color:#7cabff}
.stc-preview{position:relative;margin:12px 16px;height:300px;border-radius:14px;overflow:hidden;display:flex;align-items:center;justify-content:center}
.stc-preview textarea{position:absolute;inset:0;background:transparent;border:none;resize:none;outline:none;
  color:#fff;font:700 24px var(--ui),sans-serif;text-align:center;padding:24px 18px;text-shadow:0 1px 8px rgba(0,0,0,.35);
  display:flex}
.stc-preview textarea::placeholder{color:rgba(255,255,255,.65)}
.stc-preview img{max-width:100%;max-height:100%;object-fit:contain}
.stc-grads{display:flex;gap:8px;padding:0 16px;flex-wrap:wrap}
.stc-grads button{width:30px;height:30px;border-radius:50%;border:2px solid transparent;cursor:pointer;transition:transform .12s}
.stc-grads button.on{border-color:#fff;transform:scale(1.14)}
.stc-photo-row{display:flex;align-items:center;gap:10px;padding:0 16px}
.stc-upload{padding:9px 16px;border-radius:10px;border:1px dashed rgba(255,255,255,.25);color:var(--text);
  font:600 12px var(--ui),sans-serif;cursor:pointer;transition:border-color .15s}
.stc-upload:hover{border-color:#7cabff}
.stc-file-name{font:11px var(--ui),sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:150px}
.stc-foot{display:flex;align-items:center;gap:10px;padding:14px 16px}
.stc-msg{flex:1;font:11.5px var(--ui),sans-serif;color:#fda4af}
.stc-share{padding:10px 22px;border-radius:12px;border:none;background:linear-gradient(135deg,#2f7cf6,#6d5df6);
  color:#fff;font:800 13px var(--ui),sans-serif;cursor:pointer;transition:filter .15s,transform .12s}
.stc-share:hover{filter:brightness(1.12)}
.stc-share:disabled{opacity:.6;cursor:default}
/* ── Story viewer (full-screen) ── */
#story-viewer-ov{position:fixed;inset:0;z-index:99985;background:#000;display:flex;align-items:center;justify-content:center}
.stv-stage{position:relative;width:min(440px,100vw);height:min(94vh,820px);border-radius:14px;overflow:hidden;background:#050508;user-select:none;-webkit-user-select:none;touch-action:manipulation}
@media(max-width:640px){.stv-stage{width:100vw;height:100vh;height:100dvh;border-radius:0}}
.stv-bars{position:absolute;top:8px;left:10px;right:10px;z-index:6;display:flex;gap:4px}
.stv-bar{flex:1;height:3px;border-radius:3px;background:rgba(255,255,255,.28);overflow:hidden}
.stv-bar-fill{height:100%;width:0;background:#fff;border-radius:3px}
.stv-bar-fill.done{width:100%}
.stv-bar-fill.animating{animation-name:stvfill;animation-timing-function:linear;animation-fill-mode:forwards}
@keyframes stvfill{from{width:0}to{width:100%}}
.stv-top{position:absolute;top:18px;left:12px;right:12px;z-index:6;display:flex;align-items:center;gap:9px;transition:opacity .25s}
.stv-held .stv-top,.stv-held .stv-bars,.stv-held .stv-hint{opacity:0}
.stv-av{width:36px;height:36px;border-radius:50%;object-fit:cover;border:2px solid rgba(255,255,255,.85);cursor:pointer}
.stv-name{font:700 13.5px var(--ui),sans-serif;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,.7)}
.stv-time{font:12px var(--ui),sans-serif;color:rgba(255,255,255,.75);flex:1}
.stv-views{font:700 12px var(--ui),sans-serif;color:#fff;background:rgba(0,0,0,.45);padding:4px 10px;border-radius:20px;cursor:default}
.stv-del{width:32px;height:32px;border-radius:50%;border:none;background:rgba(0,0,0,.45);color:#fff;font-size:14px;cursor:pointer}
.stv-del:hover{background:rgba(220,38,38,.7)}
.stv-x{width:34px;height:34px;border-radius:50%;border:none;background:rgba(0,0,0,.45);color:#fff;font-size:20px;cursor:pointer}
.stv-x:hover{background:rgba(255,255,255,.2)}
.stv-canvas{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.stv-media{max-width:100%;max-height:100%;object-fit:contain}
.stv-text{position:relative;z-index:2;font:800 26px/1.4 var(--ui),sans-serif;color:#fff;text-align:center;padding:30px 26px;
  text-shadow:0 2px 10px rgba(0,0,0,.4);max-height:70%;overflow-y:auto;word-break:break-word}
.stv-text.on-media{position:absolute;left:0;right:0;bottom:56px;font-size:17px;padding:12px 20px;
  background:linear-gradient(180deg,transparent,rgba(0,0,0,.55));max-height:40%}
.stv-hint{position:absolute;bottom:14px;left:0;right:0;z-index:5;text-align:center;font:10.5px var(--ui),sans-serif;
  color:rgba(255,255,255,.45);pointer-events:none;transition:opacity .25s}
/* v9.10.551 — story reply bar (DM) + quick heart */
.stv-reply{position:absolute;left:10px;right:10px;bottom:12px;z-index:6;display:flex;gap:8px;align-items:center}
.stv-reply input{flex:1;min-width:0;height:42px;border-radius:999px;border:1px solid rgba(255,255,255,.4);
  background:rgba(0,0,0,.35);color:#fff;padding:0 16px;font:13.5px var(--ui),sans-serif;outline:none;backdrop-filter:blur(4px)}
.stv-reply input::placeholder{color:rgba(255,255,255,.65)}
.stv-reply input:focus{border-color:rgba(255,255,255,.85)}
.stv-reply-send,.stv-reply-heart{width:42px;height:42px;border-radius:50%;border:none;cursor:pointer;font-size:17px;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:transform .12s}
.stv-reply-send{background:rgba(47,124,246,.9);color:#fff}
.stv-reply-heart{background:rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.3)}
.stv-reply-send:hover,.stv-reply-heart:hover{transform:scale(1.1)}
.stv-heart-burst{position:absolute;bottom:70px;right:24px;z-index:7;font-size:34px;opacity:0;pointer-events:none}
.stv-heart-burst.fly{animation:stvheart .85s ease-out forwards}
@keyframes stvheart{0%{opacity:0;transform:translateY(0) scale(.6)}20%{opacity:1}100%{opacity:0;transform:translateY(-120px) scale(1.5)}}
@keyframes gskel{from{background-position:200% 0}to{background-position:-200% 0}}
/* v9.10.501 — feed flows directly without wrapper card */
.gfeed-flow{display:flex;flex-direction:column;gap:0}
/* Reels band interspersed in feed */
.gfeed-reels{margin:6px 0 14px;padding:0}
.gfeed-reels .gc-h{font:600 12px var(--ui),sans-serif;color:var(--text);margin-bottom:10px;letter-spacing:0;text-transform:none}
.gfeed-reels-scroll{display:flex;gap:10px;overflow-x:auto;padding:0 0 8px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.gfeed-reels-scroll::-webkit-scrollbar{display:none}
.gfeed-reel-thumb{flex:0 0 auto;width:110px;border-radius:12px;overflow:hidden;position:relative;cursor:pointer;background:#0a0e14;aspect-ratio:9/16;max-height:180px}
.gfeed-reel-thumb img{width:100%;height:100%;object-fit:cover}
.gfeed-reel-thumb .gfr-overlay{position:absolute;inset:0;background:linear-gradient(transparent 50%,rgba(0,0,0,.75));
  display:flex;flex-direction:column;justify-content:flex-end;padding:8px;font:500 10px var(--ui),sans-serif;color:#fff}
.gfeed-reel-thumb:hover{box-shadow:0 4px 16px rgba(0,0,0,.4);transform:translateY(-2px);transition:transform .15s}
/* v9.10.500 — composer option pills: soft rounded pills with subtle icon+label feel */
.gcomposer-opt{display:inline-flex;align-items:center;gap:5px;border-radius:999px !important;
  padding:7px 14px !important;font:600 12px var(--ui),Inter,sans-serif !important;
  background:rgba(255,255,255,.05) !important;border:1px solid rgba(255,255,255,.08) !important;
  color:#b0bfd0 !important;cursor:pointer;transition:background .15s,border-color .15s,color .15s;
  text-transform:none !important;letter-spacing:0 !important;box-shadow:none !important}
.gcomposer-opt:hover{background:rgba(255,255,255,.10) !important;border-color:rgba(255,255,255,.16) !important;color:#e0e8f4 !important}
.guest-card .gc-h{font-family:var(--ui);font-size:10px;font-weight:700;letter-spacing:1.2px;text-transform:uppercase;color:var(--muted);margin-bottom:10px}
/* v9.10.500 — right sidebar widget styling */
.gsb-user-row{display:flex;gap:10px;align-items:center}
.gsb-user-row img{border-radius:12px;background:#111;cursor:pointer;border:1px solid rgba(255,255,255,.08)}
.gsb-user-info{min-width:0}
.gsb-user-info .gsb-name{font:700 14px var(--ui),sans-serif;color:var(--text)}
.gsb-user-info .gsb-handle{font-size:11px;color:var(--muted)}
.gsb-trending-item{display:flex;align-items:center;gap:9px;padding:7px 0;border-bottom:1px solid rgba(255,255,255,.04);cursor:pointer;transition:background .12s;border-radius:6px;margin:0 -4px;padding-left:4px;padding-right:4px}
.gsb-trending-item:last-child{border-bottom:none}
.gsb-trending-item:hover{background:rgba(255,255,255,.04)}
.gsb-trending-item .gsb-hash{font:700 15px var(--ui),sans-serif;width:22px;text-align:center;flex-shrink:0}
.gsb-trending-item .gsb-tag{font:600 12.5px var(--ui),sans-serif;color:var(--text)}
.gsb-trending-item .gsb-tagmeta{font-size:10px;color:var(--muted)}
.gsb-stat-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.gsb-stat{text-align:center;padding:10px 8px;background:rgba(255,255,255,.03);border-radius:10px;border:1px solid rgba(255,255,255,.04);transition:border-color .15s}
.gsb-stat:hover{border-color:rgba(255,255,255,.10)}
.gsb-stat .gsb-sv{font:700 18px var(--ui),sans-serif;color:var(--accent);line-height:1.2}
.gsb-stat .gsb-sl{font:500 10px var(--ui),sans-serif;color:var(--muted);letter-spacing:.5px;text-transform:uppercase;margin-top:2px}
.gsb-presence{display:flex;flex-direction:column;gap:4px}
.gsb-presence-row{display:flex;align-items:center;gap:8px;padding:4px 0;font-size:12px;color:var(--text)}
.gsb-presence-row .gsb-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.gsb-presence-row .gsb-dot.online{background:var(--good)}
.gsb-presence-row .gsb-dot.idle{background:var(--warn)}
.gsb-suggested-row{display:flex;align-items:center;gap:10px;padding:8px 4px;border-radius:8px;transition:background .12s;margin:0 -4px}
.gsb-suggested-row:hover{background:rgba(255,255,255,.04)}
.gsb-suggested-row img{width:34px;height:34px;border-radius:50%;object-fit:cover;background:#111;border:1px solid rgba(255,255,255,.08)}
.gsb-suggested-row .gsb-sname{font:600 12px var(--ui),sans-serif;color:var(--text)}
.gsb-suggested-row .gsb-swhy{font-size:10px;color:var(--muted)}
.gsb-suggested-row .gsb-follow-btn{margin-left:auto;border:1px solid rgba(34,217,230,.4);background:rgba(34,217,230,.10);
  color:var(--accent);border-radius:999px;padding:4px 12px;font:600 10px var(--ui),sans-serif;cursor:pointer;transition:background .15s}
.gsb-suggested-row .gsb-follow-btn:hover{background:rgba(34,217,230,.22)}
/* v9.10.513 — sidebar widget polish */
.gsb-user-row:hover{background:rgba(255,255,255,.03);border-radius:8px;margin:-4px;padding:4px;transition:background .15s}
.gsb-trending-item:hover{border-left:3px solid var(--c-indigo);padding-left:6px}
.gsb-presence-row .gsb-dot.online{animation:gsb-pulse 2s ease-in-out infinite}
@keyframes gsb-pulse{0%,100%{box-shadow:0 0 0 0 rgba(74,222,128,.4)}50%{box-shadow:0 0 0 4px rgba(74,222,128,0)}}
.gsb-suggested-row:hover{background:rgba(255,255,255,.06);transform:translateY(-1px);transition:background .15s,transform .15s}
.gsb-stat{border-bottom:1px solid rgba(255,255,255,.03)}
/* v9.10.550 — Sidebar Radio card (prominent, animated) */
.gsb-radio-card{position:relative;overflow:hidden;padding:0!important;
  background:linear-gradient(135deg,#1a1040 0%,#0d1117 50%,#111827 100%)!important;
  border:1px solid rgba(139,92,246,.25)!important;transition:transform .2s,box-shadow .2s}
.gsb-radio-card:hover{transform:translateY(-2px);box-shadow:0 4px 20px rgba(139,92,246,.2)}
.gsb-radio-bg{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.gsb-radio-bars{display:flex;align-items:flex-end;gap:3px;position:absolute;right:12px;top:10px;height:20px;opacity:.3}
.gsb-radio-bars span{width:3px;background:var(--accent);border-radius:2px;animation:gsb-bar 1.2s ease-in-out infinite}
.gsb-radio-bars span:nth-child(1){height:6px;animation-delay:0s}
.gsb-radio-bars span:nth-child(2){height:12px;animation-delay:.15s}
.gsb-radio-bars span:nth-child(3){height:8px;animation-delay:.3s}
.gsb-radio-bars span:nth-child(4){height:16px;animation-delay:.45s}
.gsb-radio-bars span:nth-child(5){height:10px;animation-delay:.6s}
.gsb-radio-card.playing .gsb-radio-bars span{opacity:1}
@keyframes gsb-bar{0%,100%{height:4px}50%{height:18px}}
.gsb-radio-body{position:relative;z-index:1;display:flex;align-items:center;gap:12px;padding:14px 14px 8px}
.gsb-radio-icon{font-size:28px;filter:drop-shadow(0 0 8px rgba(139,92,246,.4))}
.gsb-radio-info{flex:1;min-width:0}
.gsb-radio-title{font:700 13px var(--ui),sans-serif;color:#e2e8f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gsb-radio-sub{font:400 11px var(--ui),sans-serif;color:rgba(167,139,250,.8);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gsb-radio-play{width:32px;height:32px;border-radius:50%;border:none;
  background:linear-gradient(135deg,#8b5cf6,#6366f1);color:#fff;cursor:pointer;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
  transition:transform .15s,box-shadow .15s;box-shadow:0 2px 8px rgba(99,102,241,.3)}
.gsb-radio-play:hover{transform:scale(1.1);box-shadow:0 4px 16px rgba(99,102,241,.5)}
.gsb-radio-play svg{margin-left:2px}
.gsb-radio-genres{position:relative;z-index:1;display:flex;gap:6px;padding:4px 14px 12px;flex-wrap:wrap}
.gsb-radio-tag{font:500 10px var(--ui),sans-serif;padding:2px 8px;border-radius:999px;
  background:rgba(139,92,246,.12);color:rgba(167,139,250,.9);border:1px solid rgba(139,92,246,.15);
  transition:background .15s}
.gsb-radio-tag:hover{background:rgba(139,92,246,.22)}
/* v9.10.550 — Discover grid (sidebar exploration cards) */
.gsb-discover-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:8px}
.gsb-discover-btn{display:flex;flex-direction:column;align-items:center;gap:2px;padding:12px 8px;
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.06);border-radius:10px;
  cursor:pointer;transition:background .15s,transform .15s,border-color .15s;color:var(--text);font:600 11px var(--ui),sans-serif}
.gsb-discover-btn:hover{background:rgba(139,92,246,.12);border-color:rgba(139,92,246,.25);transform:translateY(-1px)}
.gsb-discover-btn:active{transform:scale(.97)}
/* color classes for trending hash symbols */
.gsb-hash-accent{color:var(--accent)}
.gsb-hash-amber{color:var(--c-amber)}
.gsb-hash-purple{color:var(--c-violet)}
/* v9.10.513 — focus-visible rings for social interactive elements */
.gpost-acts button:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
.gpost-cmt-acts button:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
.gcomp-icon:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
.gcomposer-opt:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent) !important}
.gpost-rx-chip:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
.gpost-menu-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
.gfeed-tabs button:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
.gcomp-text:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(34,217,230,.3)}
.gcomp-search:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(34,217,230,.3)}
.gpost-reply-form input:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(34,217,230,.3)}
/* ── v9.10.376 — PROFILE ACTION BAR + new components ──────────────────────────
   Owner: "can the buttons and text be better please its plain or crappy style".
   The profile actions (Share a thought / Edit profile / Theme / Badges) were square,
   flat, same-weight boxes with no hierarchy — nothing said which one was the primary
   action, and they read as a row of placeholders. Now: a clear primary, quieter
   secondaries, real radius, and a lift on hover so they feel pressable.

   v9.10.617 — this comment used to CLOSE here, with the paragraph below left as
   bare text. CSS then read that paragraph as a selector, and a selector consumes
   the next {...} block as its body — so the `.gprof-acts .gc-btn` rule that
   follows (radius, padding, font, transition, shadow) has never once applied
   since it was written. The `:hover`/`:active` rules after it parsed fine, which
   is why the row half-worked and the bug stayed invisible. One closer, at the end.

   NOTE: those buttons carry heavy INLINE styles (each sets its own background and
   padding), and inline beats a class selector — so the properties that actually make
   them feel like buttons are forced here, while their individual colours are left
   alone. That keeps the visual identity the owner already chose and fixes only the
   "plain / crappy" part: shape, weight, spacing and feedback. */
.gprof-acts .gc-btn{
  border-radius:11px !important;
  padding:9px 16px !important;
  font-family:var(--ui),Inter,sans-serif !important;
  font-size:12px !important;
  letter-spacing:.3px;
  border:1px solid rgba(255,255,255,.12);
  transition:transform .14s ease, box-shadow .18s ease, filter .18s ease !important;
  box-shadow:0 2px 6px -3px rgba(0,0,0,.6);
}
.gprof-acts .gc-btn:hover{
  transform:translateY(-1.5px);
  box-shadow:0 10px 22px -10px rgba(0,0,0,.85);
  filter:brightness(1.12);
}
.gprof-acts .gc-btn:active{transform:translateY(0);filter:brightness(.96)}
/* The primary action gets a real glow so the row has a clear first step. */
.gprof-acts .gc-btn:first-child{box-shadow:0 8px 22px -10px rgba(124,58,237,.85)}

/* Filter chips (profile posts + avatar style picker) */
.gprof-filters{display:flex;gap:5px;align-items:center}
.gpf-chip{
  border:1px solid rgba(255,255,255,.10);
  background:rgba(255,255,255,.04);
  color:var(--muted);
  border-radius:999px;
  padding:5px 12px;
  font:600 11px var(--ui),Inter,sans-serif;
  letter-spacing:.3px;
  cursor:pointer;
  transition:background .16s ease,color .16s ease,border-color .16s ease;
}
.gpf-chip:hover{background:rgba(255,255,255,.09);color:#dfe8f5}
.gpf-chip.on{background:var(--accent,#22d9e6);color:#04070d;border-color:transparent;font-weight:700}

/* v9.10.379 — profile form: tag box + typeahead dropdown */
.s2-tagbox{display:flex;flex-wrap:wrap;gap:5px;align-items:center;min-height:24px}
.s2-tag{
  display:inline-flex;align-items:center;gap:5px;
  background:rgba(34,217,230,.13);border:1px solid rgba(34,217,230,.34);
  color:#dff6fa;border-radius:999px;padding:3px 6px 3px 10px;
  font:600 11px var(--ui),Inter,sans-serif;letter-spacing:.2px;
}
.s2-tag button{
  border:none;background:transparent;color:#9fd8e2;cursor:pointer;
  font-size:14px;line-height:1;padding:0 2px;border-radius:50%;
}
.s2-tag button:hover{color:#fff;background:rgba(255,255,255,.14)}
/* The dropdown is absolutely positioned so it overlays what's below rather than
   pushing the form around as you type — a shifting form is very hard to use. */
.s2-ac{
  display:none;position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:40;
  background:#111a2b;border:1px solid rgba(255,255,255,.14);border-radius:10px;
  box-shadow:0 14px 34px -12px rgba(0,0,0,.8);
  max-height:210px;
}
.s2-ac.open{display:block}
.s2-ac button{
  display:block;width:100%;text-align:left;border:none;background:transparent;
  color:#e6edf7;padding:8px 11px;font:500 12.5px Inter,sans-serif;cursor:pointer;
}
.s2-ac button:hover{background:rgba(255,255,255,.07)}
.s2-ac button:first-child{border-radius:10px 10px 0 0}
.s2-ac button:last-child{border-radius:0 0 10px 10px}

/* Avatar builder */
.av-build{display:flex;gap:16px;align-items:flex-start;margin:6px 0 14px;flex-wrap:wrap}
.av-preview{display:flex;flex-direction:column;gap:8px;align-items:center;flex:0 0 auto}
.av-preview img{
  width:132px;height:132px;border-radius:20px;background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.12);
  box-shadow:0 14px 34px -14px rgba(0,0,0,.85);
}
.av-reroll{width:132px;text-align:center}
.av-opts{flex:1;min-width:210px;display:flex;flex-direction:column;gap:4px}
.av-styles{display:grid;grid-template-columns:repeat(auto-fill,minmax(66px,1fr));gap:6px;margin-bottom:8px}
.av-styles .gpf-chip{
  display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:6px 4px;border-radius:10px;line-height:1.1;
}
.av-styles .gpf-chip img{width:34px;height:34px;border-radius:8px;background:rgba(255,255,255,.05)}
.av-styles .gpf-chip span{font-size:9.5px;letter-spacing:.2px}
.av-bgs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:8px}
.av-swatch{
  width:26px;height:26px;border-radius:8px;cursor:pointer;
  border:1px solid rgba(255,255,255,.16);
  color:var(--muted);font-size:11px;line-height:1;
  transition:transform .14s ease,box-shadow .14s ease;
}
.av-swatch:hover{transform:translateY(-1px)}
.av-swatch.on{box-shadow:0 0 0 2px var(--accent,#22d9e6);border-color:transparent}
.guest-card .gc-row{display:flex;justify-content:space-between;gap:10px;padding:6px 0;border-bottom:1px solid rgba(255,255,255,.04);font-size:12px}
.guest-card .gc-row:last-child{border-bottom:none}
.guest-card .gc-k{color:var(--muted)} .guest-card .gc-v{color:var(--text);font-family:var(--mono);font-size:11px;word-break:break-all;text-align:right}
.guest-card textarea{width:100%;min-height:120px;resize:vertical;background:rgba(0,0,0,.35);border:1px solid var(--border);
  border-radius:10px;color:#fff;padding:10px 12px;font:12.5px/1.5 Inter,sans-serif;outline:none}
.guest-card textarea:focus{border-color:rgba(34,217,230,.5)}
.guest-card .gc-acts{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap}
.guest-card .gc-btn{border:none;border-radius:9px;padding:9px 14px;font:700 11px Outfit,sans-serif;letter-spacing:.6px;
  text-transform:uppercase;cursor:pointer;background:linear-gradient(135deg,var(--accent),#0070a8);color:#04070d}
.guest-card .gc-btn:disabled{opacity:.55;cursor:wait}
.guest-card .gc-msg{font-size:11px;color:var(--muted);margin-top:8px;min-height:1.2em}
@media (max-width:900px){
  .guest-dash{padding:10px 10px 88px}
  .guest-banner h2{font-size:15px}
  .guest-card textarea{font-size:16px;min-height:140px}
}

/* Confirm modal */
.modal-overlay{position:fixed;inset:0;z-index:8000;background:rgba(2,4,9,0.78);backdrop-filter:blur(4px);
  display:none;align-items:center;justify-content:center;padding:20px}
.modal-overlay.open{display:flex}
.modal{width:min(440px,92vw);max-height:92vh;background:var(--panel-solid);border:1px solid rgba(248,113,113,0.4);
  border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,0.6);overflow:hidden;display:flex;flex-direction:column}
.modal-hdr{padding:16px 20px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:11px}
.modal-hdr .mi{width:34px;height:34px;border-radius:9px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:rgba(248,113,113,0.12);color:var(--bad)}
.modal-hdr .mi svg{width:18px;height:18px}
.modal-hdr .mt{font-family:var(--ui);font-weight:800;font-size:14px;letter-spacing:0.5px;color:#fff}
.modal-body{padding:18px 20px;font-size:12.5px;line-height:1.6;color:#c8d2e0;max-height:60vh;overflow-y:auto}
.modal-body b{color:var(--warn)}
/* A5 Leo config fit: Leo section can be long (voice+tools), ensure scrolls inside modal */
.modal-body .leo-config, .modal-body .cap-leo { max-height: 45vh; overflow-y:auto; }
.modal-token{margin-top:12px}
.modal-token label{display:block;font-size:9px;letter-spacing:1px;text-transform:uppercase;color:var(--muted);margin-bottom:5px}
.modal-token input{width:100%;background:rgba(0,0,0,0.4);border:1px solid var(--border);border-radius:8px;
  padding:9px 11px;color:#fff;font-family:var(--mono);font-size:12px;outline:none}
.modal-token input:focus{border-color:rgba(34,217,230,0.5)}
.modal-acts{padding:14px 20px 18px;display:flex;gap:10px;justify-content:flex-end}
.modal-btn{padding:9px 18px;border-radius:9px;font-family:var(--ui);font-size:11px;font-weight:700;
  letter-spacing:0.5px;text-transform:uppercase;cursor:pointer;border:1px solid var(--border);transition:all 0.14s}
.modal-btn.cancel{background:rgba(255,255,255,0.04);color:var(--text)}
.modal-btn.cancel:hover{background:rgba(255,255,255,0.09)}
.modal-btn.confirm{background:linear-gradient(135deg,#f87171,#b91c1c);color:#fff;border:none}
.modal-btn.confirm:hover{filter:brightness(1.08)}
.modal-state{padding:26px 22px;text-align:center;display:none;flex-direction:column;align-items:center;gap:14px}
.modal-state.show{display:flex}
.modal-spin{width:34px;height:34px;border-radius:50%;border:3px solid rgba(34,217,230,0.2);
  border-top-color:var(--accent);animation:spin 0.9s linear infinite}
.modal-state .ms-t{font-family:var(--ui);font-weight:700;font-size:13px;color:var(--accent)}
.modal-state .ms-s{font-size:11px;color:var(--muted)}
/* neutral (non-destructive) modal accent for config edits */
.modal.neutral{border-color:rgba(34,217,230,0.4)}
.modal.neutral .modal-hdr .mi{background:rgba(34,217,230,0.12);color:var(--accent)}
.modal.neutral .modal-btn.confirm{background:linear-gradient(135deg,#22d9e6,#0070a8)}
.modal-body b.acc{color:var(--accent)}

/* ── inline editors (AI config + channel settings) ──────────────────────── */
.editor{display:flex;flex-direction:column;gap:11px}
.ed-field{display:flex;flex-direction:column;gap:5px}
.ed-field label{font-size:8.5px;letter-spacing:1px;text-transform:uppercase;color:var(--muted);font-family:var(--ui);font-weight:700}
.ed-field input,.ed-field select{width:100%;background:rgba(0,0,0,0.4);border:1px solid var(--border);border-radius:8px;
  padding:8px 10px;color:#fff;font-family:var(--mono);font-size:12px;outline:none}
.ed-field input:focus,.ed-field select:focus{border-color:rgba(34,217,230,0.5)}
.ed-field select option{background:#0a0f1b;color:#fff}
.ed-hint{font-size:9px;color:var(--muted-2);line-height:1.5}
.ed-toggle{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 11px;
  border:1px solid var(--border);border-radius:9px;background:rgba(0,0,0,0.2)}
.ed-toggle .et-lbl{font-size:11px;color:var(--text);font-weight:600}
.ed-toggle .et-sub{font-size:9px;color:var(--muted-2);margin-top:2px}
.switch{position:relative;width:38px;height:20px;flex-shrink:0;cursor:pointer}
.switch input{opacity:0;width:0;height:0;position:absolute}
.switch .track{position:absolute;inset:0;border-radius:20px;background:rgba(255,255,255,0.12);transition:.18s}
.switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;transition:.18s}
.switch input:checked + .track{background:var(--accent)}
.switch input:checked + .track + .knob{transform:translateX(18px)}
.spk-toggles{display:flex;flex-wrap:wrap;gap:6px}
.spk-tog{font-family:var(--ui);font-size:9.5px;font-weight:700;letter-spacing:0.3px;padding:5px 10px;border-radius:7px;
  border:1px solid var(--border);background:rgba(255,255,255,0.03);color:var(--muted-2);cursor:pointer;transition:.13s;user-select:none}
.spk-tog.on{background:rgba(34,217,230,0.1)}
.spk-tog:hover{border-color:rgba(34,217,230,0.4)}
.mini-btn.go{cursor:pointer;color:var(--accent);border-color:rgba(34,217,230,0.3);background:rgba(34,217,230,0.06)}
.mini-btn.go:hover{background:rgba(34,217,230,0.14)}
.ed-saved{font-size:10px;color:var(--good);font-family:var(--mono);display:flex;align-items:center;gap:6px}
.ed-err{font-size:10px;color:var(--bad);font-family:var(--mono)}

/* ── HOME OPS TELEMETRY (real, actionable) ──────────────────────────────── */
.ops-grid{padding:13px 14px;display:grid;grid-template-columns:1fr 1fr;gap:13px}
.meter{border:1px solid var(--border);border-radius:11px;padding:11px 12px;background:rgba(0,0,0,0.2)}
.meter .m-top{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:7px}
.meter .m-lbl{font-family:var(--ui);font-size:9px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--muted)}
.meter .m-val{font-family:var(--mono);font-size:15px;font-weight:600}
.meter .m-sub{font-size:8.5px;font-family:var(--mono);color:var(--muted-2);margin-top:5px}
.meter-track{height:9px;border-radius:6px;background:rgba(255,255,255,0.06);overflow:hidden}
.meter-fill{height:100%;border-radius:6px;transition:width 0.4s}
.ok-c{color:var(--good)} .warn-c{color:var(--warn)} .bad-c{color:var(--bad)}
.ok-bg{background:var(--good)} .warn-bg{background:var(--warn)} .bad-bg{background:var(--bad)}
/* provider cooldown table */
.cd-table{width:100%;border-collapse:collapse;font-size:11px}
.cd-table th{font-family:var(--ui);font-size:8px;font-weight:700;letter-spacing:1px;text-transform:uppercase;
  color:var(--muted);text-align:left;padding:6px 9px;border-bottom:1px solid var(--border)}
.cd-table th.r,.cd-table td.r{text-align:right}
.cd-table td{padding:7px 9px;border-bottom:1px solid var(--border-2);font-family:var(--mono);font-size:10.5px}
.cd-prov{color:var(--text);font-weight:600}
.cd-model{color:var(--muted-2);font-size:9.5px}
.cd-badge{font-family:var(--mono);font-size:8px;font-weight:700;letter-spacing:0.5px;padding:2px 7px;border-radius:6px;text-transform:uppercase}
.cd-badge.ok{background:rgba(74,222,128,0.12);color:var(--good)}
.cd-badge.cool{background:rgba(251,191,36,0.14);color:var(--warn)}
.cd-badge.standby{background:rgba(148,163,184,0.14);color:var(--muted)}
.cd-badge.off{background:rgba(248,113,113,0.14);color:var(--bad)}
.bots-grid{padding:10px 12px 12px;display:flex;flex-direction:column;gap:6px}
.bot-line{display:flex;align-items:center;gap:9px;padding:6px 9px;border:1px solid var(--border);border-radius:9px;background:rgba(0,0,0,0.16)}
.bot-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.bot-nm{font-family:var(--ui);font-weight:600;font-size:11.5px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bot-up{font-family:var(--mono);font-size:9px;color:var(--muted-2);flex-shrink:0}
.bot-state{font-family:var(--mono);font-size:8px;font-weight:700;text-transform:uppercase;letter-spacing:0.5px;flex-shrink:0}

.test-card{
  background:rgba(244,114,182,0.05);border:1px solid rgba(244,114,182,0.22);
  border-radius:8px;padding:9px;font-size:11px;
}
.test-card .tc-from{font-family:var(--ui);font-weight:700;font-size:10px;color:var(--c-groq);margin-bottom:3px}
.test-card .tc-cmd{font-family:var(--mono);font-size:10px;color:var(--text);word-break:break-all}
.test-card.done{border-color:rgba(74,222,128,0.25);background:rgba(74,222,128,0.04)}
.test-card.done .tc-from{color:var(--good)}

/* ── LOGS / ISSUES panel ─────────────────────────────── */
.logs-bar{display:flex;align-items:center;gap:8px;margin-bottom:7px;flex-wrap:wrap}
.logs-bar select{background:var(--panel-2);color:var(--text);border:1px solid var(--border);
  border-radius:6px;font-family:var(--mono);font-size:10px;padding:3px 6px}
.logs-issues{display:flex;align-items:center;gap:4px;font-size:9.5px;color:var(--muted-2);
  font-family:var(--ui);cursor:pointer}
.logs-issues input{accent-color:var(--accent)}
.logs-meta{font-size:8.5px;font-family:var(--mono);color:var(--muted-2);margin-left:auto}
.logs-view{max-height:300px;overflow:auto;background:rgba(0,0,0,0.32);border:1px solid var(--border);
  border-radius:8px;padding:6px 8px;font-family:var(--mono);font-size:10px;line-height:1.5}
.log-ln{white-space:pre-wrap;word-break:break-word;padding:1px 0;border-bottom:1px solid rgba(255,255,255,0.03)}
.log-ln.error{color:#f87171}
.log-ln.warn{color:#fbbf24}
.log-ln.info{color:var(--muted-2)}

/* ── MEMORY / LATTICE panel ──────────────────────────── */
.mem-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:9px}
.mem-stat{background:rgba(124,58,237,0.05);border:1px solid rgba(124,58,237,0.20);
  border-radius:7px;padding:7px 9px}
.mem-stat .msv{font-family:var(--mono);font-weight:700;font-size:13px;color:var(--text)}
.mem-stat .msv.na{font-size:9px;color:var(--muted-2);font-weight:500}
.mem-stat .msl{font-family:var(--ui);font-size:8px;letter-spacing:1px;text-transform:uppercase;color:var(--muted-2);margin-top:2px}
.mem-sec-hdr{font-family:var(--ui);font-size:8.5px;letter-spacing:1.2px;text-transform:uppercase;
  color:var(--muted-2);margin:4px 0 5px}
.mem-item{background:rgba(255,255,255,0.02);border:1px solid var(--border);border-radius:7px;
  padding:6px 8px;margin-bottom:5px;font-size:10px}
.mem-item .mi-meta{font-family:var(--mono);font-size:8px;color:var(--muted-2);margin-bottom:2px}
.mem-item .mi-txt{color:var(--text);word-break:break-word;line-height:1.45}

/* ── TEST OUTPUTS panel (sandbox files) ──────────────── */
.sbx-card{background:rgba(251,146,60,0.05);border:1px solid rgba(251,146,60,0.22);
  border-radius:8px;padding:8px;margin-bottom:6px}
.sbx-card .sc-name{font-family:var(--mono);font-weight:700;font-size:10px;color:var(--c-kaicoder,#fb923c);word-break:break-all}
.sbx-card .sc-meta{font-family:var(--mono);font-size:8px;color:var(--muted-2);margin:2px 0 4px}
.sbx-card pre{margin:0;max-height:140px;overflow:auto;background:rgba(0,0,0,0.32);border-radius:6px;
  padding:6px;font-family:var(--mono);font-size:9px;line-height:1.45;color:var(--muted-2);white-space:pre-wrap;word-break:break-word}

/* ── BOTTOM COMMAND BAR ──────────────────────────────── */
.cmdbar{
  position:relative;z-index:5;flex-shrink:0;background:var(--panel-2);
  border-top:1px solid var(--border);backdrop-filter:blur(24px);padding:11px 18px 12px;
}
.cmd-row{display:flex;gap:12px;align-items:stretch}
.cmd-input-wrap{flex:1;position:relative;display:flex;flex-direction:column;gap:7px}
.cmd-input-box{position:relative;flex:1}
.cmd-input-box .prefix{
  position:absolute;left:14px;top:13px;color:var(--accent);font-family:var(--mono);font-size:13px;pointer-events:none;opacity:0.7}
#cmd-input{
  width:100%;height:54px;background:rgba(0,0,0,0.4);color:#fff;
  border:1px solid var(--border);border-radius:10px;padding:14px 14px 14px 30px;
  font-family:var(--mono);font-size:12.5px;resize:none;outline:none;transition:all 0.18s;line-height:1.5;
}
#cmd-input:focus{border-color:rgba(34,217,230,0.5);box-shadow:0 0 0 3px var(--accent-glow)}
#cmd-input::placeholder{color:var(--muted-2)}
.roster-chips{display:flex;gap:6px;flex-wrap:wrap}
.rchip{
  font-size:9px;padding:3px 9px;border-radius:20px;border:1px solid var(--border);
  color:var(--muted);cursor:pointer;transition:all 0.14s;font-family:var(--mono);display:flex;align-items:center;gap:5px;
}
.rchip .rdot{width:6px;height:6px;border-radius:50%}
.rchip:hover{border-color:rgba(255,255,255,0.2)}
.rchip.active{background:rgba(255,255,255,0.04)}

.cmd-btns{display:flex;flex-direction:column;gap:7px;justify-content:flex-start;width:170px}
.btn{
  border:none;border-radius:9px;padding:9px 14px;font-family:var(--ui);
  font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:1px;
  cursor:pointer;transition:all 0.15s;white-space:nowrap;display:flex;align-items:center;justify-content:center;gap:7px;
}
.btn svg{width:14px;height:14px}
.btn.execute{background:linear-gradient(135deg,var(--accent),#0070a8);color:#04070d;
  box-shadow:0 4px 16px var(--accent-glow)}
.btn.execute:hover{filter:brightness(1.08);transform:translateY(-1px)}
.btn.sec{background:rgba(255,255,255,0.05);color:var(--text);border:1px solid var(--border)}
.btn.sec:hover{background:rgba(255,255,255,0.09);transform:translateY(-1px)}
.btn-secondary-row{display:flex;gap:7px}
.btn-secondary-row .btn{flex:1;padding:8px 6px;font-size:9px}
.btn.kai{color:var(--c-kai);border-color:rgba(74,222,128,0.35)}
.btn.talk{color:var(--c-claudey);border-color:rgba(167,139,250,0.35)}

/* ── CHANNEL SUB-TABS (Chat / Metrics / Settings) ────── */
.ch-tabs{
  flex-shrink:0;display:flex;align-items:center;gap:4px;padding:7px 18px;
  border-bottom:1px solid var(--border);background:var(--panel-2);
}
.ch-tab{
  font-family:var(--ui);font-size:10px;font-weight:700;letter-spacing:1.2px;text-transform:uppercase;
  padding:6px 14px;border-radius:8px;cursor:pointer;color:var(--muted);border:1px solid transparent;
  transition:all 0.15s;display:flex;align-items:center;gap:6px;
}
.ch-tab svg{width:13px;height:13px}
.ch-tab:hover{color:var(--text);background:rgba(255,255,255,0.04)}
.ch-tab.active{color:var(--accent);background:var(--accent-glow);border-color:rgba(34,217,230,0.3)}
.ch-pane{flex:1;min-height:0;display:none;flex-direction:column;overflow:hidden}
.ch-pane.active{display:flex}

/* ── METRICS PANE ────────────────────────────────────── */
.metrics-pane{flex:1;overflow-y:auto;padding:20px 24px;display:flex;flex-direction:column;gap:18px}
.met-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.met-card{border:1px solid var(--border);border-radius:11px;padding:14px;background:rgba(255,255,255,0.015)}
.met-card .mc-v{font-family:var(--mono);font-size:22px;font-weight:600;color:var(--accent)}
.met-card .mc-l{font-size:9px;text-transform:uppercase;letter-spacing:1.3px;color:var(--muted);margin-top:4px}
.met-section .ms-hdr{font-size:10px;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);margin-bottom:10px}
.spark{display:flex;align-items:flex-end;gap:4px;height:74px;padding:8px 10px;border:1px solid var(--border);border-radius:11px;background:rgba(0,0,0,0.2)}
.spark .bar{flex:1;min-height:3px;border-radius:3px 3px 0 0;background:linear-gradient(180deg,var(--accent),var(--accent-2));opacity:0.85}
.spark .bar:hover{opacity:1}
.spk-list{display:flex;flex-direction:column;gap:7px}
.spk-row{display:flex;align-items:center;gap:10px}
.spk-av{width:26px;height:26px;border-radius:7px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:11px;color:#04070d}
.spk-name{flex:1;font-family:var(--ui);font-weight:600;font-size:12px}
.spk-bar-wrap{flex:2;height:7px;border-radius:5px;background:rgba(255,255,255,0.05);overflow:hidden}
.spk-bar{height:100%;border-radius:5px}
.spk-cnt{font-family:var(--mono);font-size:11px;color:var(--muted);min-width:34px;text-align:right}

/* SETTINGS pane reuses sp-* classes in the center column */
.config-pane{flex:1;overflow-y:auto;padding:20px 24px;display:flex;flex-direction:column;gap:18px}

/* ── BOT PROFILE + DM VIEW (slide-over) ──────────────── */
.bot-view{
  /* 2026-07-10: fixed + viewport-capped — the absolute 420px card could clip past
     the window edge on desktop ("can't see it"); fixed-positioning always fits. */
  position:fixed;top:50px;right:0;bottom:0;width:min(440px,92vw);z-index:30;
  background:var(--panel-solid);border-left:1px solid var(--border);
  box-shadow:-26px 0 50px rgba(0,0,0,0.55);transform:translateX(100%);
  transition:transform 0.26s ease;display:flex;flex-direction:column;
}
.bot-view.open{transform:translateX(0)}
.bv-hdr{padding:16px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:13px}
.bv-av{width:46px;height:46px;border-radius:12px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:19px;color:#04070d;box-shadow:0 0 18px rgba(0,0,0,0.4)}
.bv-meta{flex:1;min-width:0}
.bv-name{font-family:var(--ui);font-weight:800;font-size:16px;color:#fff;display:flex;align-items:center;gap:8px}
.bv-status{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.bv-role{font-size:9.5px;letter-spacing:1.4px;text-transform:uppercase;color:var(--muted);margin-top:3px}
.bv-x{cursor:pointer;color:var(--muted);width:20px;height:20px;display:flex;align-items:center;justify-content:center}
.bv-x:hover{color:var(--bad)}
.bv-config{padding:14px 18px;border-bottom:1px solid var(--border);display:flex;flex-direction:column;gap:10px}
.bv-cfg-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.bv-cfg{border:1px solid var(--border);border-radius:9px;padding:9px 11px;background:rgba(255,255,255,0.015)}
.bv-cfg .k{font-size:8.5px;letter-spacing:1px;text-transform:uppercase;color:var(--muted-2)}
.bv-cfg .v{font-family:var(--mono);font-size:12px;color:var(--text);margin-top:3px;word-break:break-word}
.bv-edit-note{font-size:9.5px;color:var(--muted-2);display:flex;align-items:center;gap:7px}
.bv-thread{flex:1;overflow-y:auto;padding:16px 18px;display:flex;flex-direction:column;gap:11px}
.bv-empty{color:var(--muted-2);text-align:center;font-size:11px;padding:30px 10px;line-height:1.7}
/* bio block in the config header */
.bv-bio{border:1px solid var(--border);border-radius:9px;padding:10px 12px;background:rgba(255,255,255,0.015)}
.bv-bio-txt{font-size:11.5px;line-height:1.55;color:#c8d2e0}
.bv-bio-tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.bv-bio-tag{font-size:8.5px;font-family:var(--mono);padding:2px 7px;border-radius:6px;background:rgba(34,217,230,0.1);color:var(--accent);border:1px solid rgba(34,217,230,0.25)}
/* entity-popup: gear, key-stats, timeline/activity sub-tabs */
.ov-gear{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;margin-left:auto;border-radius:7px;cursor:pointer;color:var(--muted);transition:color .15s,background .15s}
.ov-gear:hover{color:var(--accent);background:rgba(34,217,230,0.1)}
.ov-gear svg{width:15px;height:15px}
.ov-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin:11px 0 4px}
.ov-stat{border:1px solid var(--border);border-radius:9px;padding:8px 6px;text-align:center;background:rgba(255,255,255,0.015)}
.ovs-v{font-family:var(--mono);font-size:14px;font-weight:600;color:#dce4f1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ovs-l{font-size:8px;letter-spacing:.6px;text-transform:uppercase;color:var(--muted-2);margin-top:3px}
.ov-tabs{display:flex;gap:4px;margin-top:10px;border-bottom:1px solid var(--border)}
.ov-tab{flex:1;font-family:var(--ui);font-size:11px;font-weight:700;padding:8px 6px;background:none;border:none;border-bottom:2px solid transparent;color:var(--muted-2);cursor:pointer}
.ov-tab:hover{color:#c8d2e0}
.ov-tab.on{color:var(--accent);border-bottom-color:var(--accent)}
/* timeline/activity feed rows in the popup + entity portfolio */
.bvp-hdr{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:5px}
.bvp-chan{font-size:8.5px;font-family:var(--mono);color:var(--accent);padding:1px 6px;border-radius:5px;background:rgba(34,217,230,0.08)}
.bvp-ts{font-family:var(--mono);font-size:8.5px;color:var(--muted-2);margin-left:auto}
.bvp-txt{font-size:12px;line-height:1.5;color:#dce4f1;white-space:pre-wrap;word-break:break-word}
/* profile tabs */
.bv-tabs{display:flex;gap:4px;padding:8px 14px 0;border-bottom:1px solid var(--border)}
.bv-tab{flex:1;font-family:var(--ui);font-size:11px;font-weight:700;padding:8px 6px;background:none;border:none;border-bottom:2px solid transparent;color:var(--muted-2);cursor:pointer}
.bv-tab:hover{color:#c8d2e0}
.bv-tab.on{color:var(--accent);border-bottom-color:var(--accent)}
/* social feed of the bot's posts */
.bv-feed,.bv-ops{flex:1;overflow-y:auto;padding:14px 16px;display:flex;flex-direction:column;gap:9px}
.bv-post{border:1px solid var(--border);border-radius:10px;padding:10px 12px;background:rgba(255,255,255,0.015)}
.bv-post.stressed{border-color:rgba(255,180,84,0.5);background:rgba(255,180,84,0.06)}
.bp-hdr{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:5px}
.bp-ts{font-family:var(--mono);font-size:8.5px;color:var(--muted-2)}
.bp-ch{font-size:8px;font-family:var(--mono);color:var(--muted-2);padding:1px 5px;border-radius:5px;background:rgba(255,255,255,0.05)}
.bp-met{font-family:var(--mono);font-size:8.5px}
.bp-flag{font-size:8.5px;font-family:var(--mono);color:#ffb454;margin-left:auto}
.bp-body{font-size:12px;line-height:1.5;color:#dce4f1;white-space:pre-wrap;word-break:break-word}
.bv-ops .act-row{padding:6px 4px}
.dm{display:flex;flex-direction:column;gap:3px;max-width:82%}
.dm.me{align-self:flex-end;align-items:flex-end;max-width:78%;margin-right:4px}
.dm.them{align-self:flex-start;align-items:flex-start;max-width:78%}
.dm .dm-who{font:500 10px Inter,sans-serif;color:#64748b;padding:0 4px 2px;letter-spacing:0}
.dm .dm-bub{padding:10px 14px;border-radius:18px;font:400 14px/1.55 Inter,sans-serif;white-space:pre-wrap;word-break:break-word}
.dm.me .dm-bub{background:linear-gradient(135deg,#6366f1,#4f46e5);color:#fff;border-radius:18px 18px 4px 18px;box-shadow:0 2px 8px rgba(99,102,241,.2)}
.dm.them .dm-bub{background:rgba(30,41,59,.8);border:1px solid rgba(148,163,184,.12);color:#e2e8f0;border-radius:18px 18px 18px 4px}
.dm.sys .dm-bub{background:rgba(255,255,255,0.03);border:1px dashed var(--border);color:var(--muted);font-style:italic;font-size:12px}
/* 2026-07-17 — DM read receipts + typing indicator */
.dm-status{font:500 10px Inter,sans-serif;color:#64748b;padding:2px 6px 0;align-self:flex-end;letter-spacing:.3px}
.dm-status.seen{color:var(--accent,#22d9e6)}
.dm-status.pending{color:#475569;opacity:.6}
.typing-dots{display:inline-flex;align-items:center;gap:4px;min-height:14px}
.typing-dots .td{width:6px;height:6px;border-radius:50%;background:var(--muted,#8aa);opacity:.4;animation:tdBlink 1.2s infinite ease-in-out}
.typing-dots .td:nth-child(2){animation-delay:.2s}
.typing-dots .td:nth-child(3){animation-delay:.4s}
@keyframes tdBlink{0%,60%,100%{opacity:.25;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
.dm.sys{align-self:center;max-width:90%;align-items:center}
.bv-compose{flex-shrink:0;padding:12px 16px;border-top:1px solid var(--border);display:flex;gap:9px;align-items:flex-end}
.bv-compose textarea{flex:1;height:42px;max-height:120px;background:rgba(0,0,0,0.4);color:#fff;border:1px solid var(--border);
  border-radius:10px;padding:11px 13px;font-family:var(--ui);font-size:12.5px;resize:none;outline:none;line-height:1.4}
.bv-compose textarea:focus{border-color:rgba(34,217,230,0.5);box-shadow:0 0 0 3px var(--accent-glow)}
.bv-send{flex-shrink:0;width:42px;height:42px;border-radius:10px;border:none;cursor:pointer;
  background:linear-gradient(135deg,var(--accent),#0070a8);color:#04070d;display:flex;align-items:center;justify-content:center}
.bv-send:hover{filter:brightness(1.1)}
.bv-send svg{width:18px;height:18px}
.agent-row{cursor:pointer}
.agent-dm-ic{width:15px;height:15px;color:var(--muted-2);flex-shrink:0}
.agent-row:hover .agent-dm-ic{color:var(--accent)}
.bv-actions{display:flex;gap:8px;margin-top:6px;flex-wrap:wrap}
.bv-actions .mini-btn{flex:1}

/* ── BROWSER-STYLE TAB STRIP (center area) ──────────────── */
.tab-strip{display:flex;align-items:stretch;gap:4px;padding:5px 8px 0;background:rgba(0,0,0,0.28);
  border-bottom:1px solid var(--border);overflow-x:auto;overflow-y:hidden;flex-shrink:0;scrollbar-width:thin}
.tab-strip::-webkit-scrollbar{height:5px}
.tab-strip::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.12);border-radius:3px}
.tab-strip.empty{display:none}
.os-tab{display:flex;align-items:center;gap:7px;padding:7px 9px 7px 11px;max-width:190px;min-width:110px;
  background:rgba(255,255,255,0.03);border:1px solid var(--border);border-bottom:none;
  border-radius:9px 9px 0 0;cursor:pointer;flex-shrink:0;position:relative;user-select:none;transition:background 0.15s}
.os-tab:hover{background:rgba(255,255,255,0.06)}
.os-tab.active{background:var(--panel-solid);border-color:var(--border);box-shadow:0 -2px 10px rgba(0,0,0,0.3)}
.os-tab.active::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--accent)}
.os-tab.dragging{opacity:0.45}
.os-tab .ot-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;box-shadow:0 0 6px currentColor}
.os-tab .ot-label{flex:1;font-family:var(--ui);font-size:11.5px;font-weight:600;color:#c8d2e0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.os-tab.active .ot-label{color:#fff}
.os-tab .ot-close{width:16px;height:16px;border-radius:5px;flex-shrink:0;display:flex;align-items:center;justify-content:center;color:var(--muted-2)}
.os-tab .ot-close:hover{background:rgba(248,113,113,0.16);color:var(--bad)}
.os-tab .ot-close svg{width:11px;height:11px}

/* ── CENTER PORTFOLIO PAGE ──────────────────────────────── */
.view-pane#view-portfolio{overflow:hidden}
.pf-scroll{flex:1;min-height:0;overflow-y:auto;padding:0 0 40px}
.pf-hero{display:flex;align-items:flex-start;gap:18px;padding:24px 28px 20px;
  background:linear-gradient(180deg,rgba(255,255,255,0.03),transparent);border-bottom:1px solid var(--border)}
.pf-av{width:72px;height:72px;border-radius:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:30px;color:#04070d;box-shadow:0 0 30px rgba(0,0,0,0.5)}
.pf-id{flex:1;min-width:0}
.pf-name{font-family:var(--ui);font-weight:800;font-size:26px;color:#fff;display:flex;align-items:center;gap:12px}
.pf-name .pf-status{width:11px;height:11px;border-radius:50%}
.pf-role{font-size:11px;letter-spacing:1.6px;text-transform:uppercase;color:var(--muted);margin:5px 0 12px}
.pf-bio{font-size:13px;line-height:1.6;color:#c8d2e0;max-width:760px}
.pf-bio-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.pf-bio-tag{font-size:9.5px;font-family:var(--mono);padding:3px 9px;border-radius:7px;background:rgba(34,217,230,0.1);color:var(--accent);border:1px solid rgba(34,217,230,0.25)}
.pf-vitals{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;padding:18px 28px;border-bottom:1px solid var(--border)}
.pf-vital{border:1px solid var(--border);border-radius:11px;padding:12px 14px;background:rgba(255,255,255,0.015)}
.pf-vital .vv{font-family:var(--mono);font-size:20px;font-weight:600;color:#fff}
.pf-vital .vl{font-size:8.5px;letter-spacing:1px;text-transform:uppercase;color:var(--muted-2);margin-top:4px}
.pf-vital .vn{font-size:8px;color:var(--muted-2);margin-top:3px;font-style:italic}
.pf-secthdr{font-family:var(--ui);font-weight:700;font-size:12px;letter-spacing:0.6px;color:#fff;
  padding:18px 28px 8px;display:flex;align-items:center;gap:10px}
.pf-secthdr .pf-count{font-size:9px;font-family:var(--mono);color:var(--muted-2);font-weight:400}
.pf-cfg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px;padding:0 28px 8px}
.pf-cfg{border:1px solid var(--border);border-radius:10px;padding:11px 13px;background:rgba(255,255,255,0.015)}
.pf-cfg .k{font-size:8.5px;letter-spacing:1px;text-transform:uppercase;color:var(--muted-2)}
.pf-cfg .v{font-family:var(--mono);font-size:12.5px;color:var(--text);margin-top:4px;word-break:break-word}
.pf-tabs{display:flex;gap:6px;padding:8px 28px 0;border-bottom:1px solid var(--border);position:sticky;top:0;
  background:var(--panel-solid);z-index:2;flex-wrap:wrap}
.pf-tab{font-family:var(--ui);font-size:12px;font-weight:700;padding:9px 14px;background:none;border:none;
  border-bottom:2px solid transparent;color:var(--muted-2);cursor:pointer}
.pf-tab:hover{color:#c8d2e0}
.pf-tab.on{color:var(--accent);border-bottom-color:var(--accent)}
.pf-pane{padding:14px 28px;display:none;flex-direction:column;gap:9px}
.pf-pane.on{display:flex}
.pf-edit-row{padding:4px 28px 8px}
.pf-empty{color:var(--muted-2);text-align:center;font-size:12px;padding:36px 10px;line-height:1.7}
.pf-dm-thread{display:flex;flex-direction:column;gap:11px;min-height:120px}

/* ── CHANNEL DETAIL slide-over (mirrors .bot-view) ───── */
.chan-view{
  position:absolute;top:50px;right:0;bottom:0;width:440px;z-index:30;
  background:var(--panel-solid);border-left:1px solid var(--border);
  box-shadow:-26px 0 50px rgba(0,0,0,0.55);transform:translateX(100%);
  transition:transform 0.26s ease;display:flex;flex-direction:column;
}
.chan-view.open{transform:translateX(0)}
/* ── right-edge scrim fix (2026-07-10, v9.10.234) ──────────────────────────
   The off-canvas slide-overs (.settings-panel / .bot-view / .chan-view) sit at
   right:0 and are pushed fully off-screen with translateX(100%) when closed, but
   their LEFTWARD box-shadow (-20..-26px x, 40-50px blur, up to rgba(0,0,0,.55)) is
   painted at z-index 20-30 — ABOVE the z-5 composer — so it bled a persistent dark
   fade back onto the visible right edge, dimming the Send button / composer. While
   closed, drop the shadow (nothing to overlay) and make them inert. The depth shadow
   returns the moment a panel is actually .open, so open-state looks unchanged. */
.settings-panel:not(.open),.bot-view:not(.open),.chan-view:not(.open){box-shadow:none;pointer-events:none}
.cv-hdr{padding:16px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:13px}
.cv-av{width:46px;height:46px;border-radius:12px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:20px;color:var(--accent);background:var(--accent-glow);box-shadow:0 0 18px rgba(0,0,0,0.4)}
.cv-av svg{width:22px;height:22px}
.cv-meta{flex:1;min-width:0}
.cv-name{font-family:var(--ui);font-weight:800;font-size:16px;color:#fff;display:flex;align-items:center;gap:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cv-status{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.cv-role{font-size:9.5px;letter-spacing:1.4px;text-transform:uppercase;color:var(--muted);margin-top:3px}
.cv-x{cursor:pointer;color:var(--muted);width:20px;height:20px;display:flex;align-items:center;justify-content:center}
.cv-x:hover{color:var(--bad)}
.cv-body{flex:1;overflow-y:auto;padding:16px 18px;display:flex;flex-direction:column;gap:18px;-webkit-overflow-scrolling:touch}
.cv-acts{flex-shrink:0;padding:12px 16px;border-top:1px solid var(--border);display:flex;gap:9px}
.cv-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:7px;cursor:pointer;
  font-family:var(--ui);font-size:10.5px;font-weight:700;letter-spacing:0.6px;text-transform:uppercase;
  padding:11px 10px;border-radius:10px;border:1px solid var(--border);background:rgba(255,255,255,0.03);color:var(--muted-2);transition:all 0.14s}
.cv-btn svg{width:14px;height:14px}
.cv-btn.go{color:#04070d;background:linear-gradient(135deg,var(--accent),#0070a8);border:none}
.cv-btn.go:hover{filter:brightness(1.1)}
.cv-btn:hover{background:rgba(255,255,255,0.07);color:var(--accent);border-color:rgba(34,217,230,0.4)}
.cv-pill{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:11px;padding:5px 11px;border-radius:8px;border:1px solid var(--border);background:rgba(0,0,0,0.2)}
.cv-pill .dot{width:8px;height:8px;border-radius:50%}
.cv-sp{display:flex;flex-wrap:wrap;gap:6px}
.cv-sp .tag{font-family:var(--ui);font-size:10px;font-weight:600;padding:3px 9px;border-radius:7px;border:1px solid var(--border)}
.cv-row{display:flex;justify-content:space-between;gap:10px;font-size:11.5px;padding:3px 0}
.cv-row span:first-child{color:var(--muted)}
.cv-row .v{font-family:var(--mono);color:var(--text);text-align:right}

/* ── TOPOLOGY interactivity (hover/select highlight + tooltip) ─ */
.topo-node{cursor:pointer;transition:opacity 0.16s ease}
.topo-edge{transition:stroke-opacity 0.16s ease,stroke-width 0.16s ease}
svg.topo-svg.has-focus .topo-node:not(.focus){opacity:0.22}
svg.topo-svg.has-focus .topo-edge:not(.focus){stroke-opacity:0.04!important}
.topo-node.focus .node-ring{opacity:1}
.node-ring{opacity:0;transition:opacity 0.16s ease}
.topo-tip{position:absolute;pointer-events:none;z-index:50;opacity:0;transform:translate(-50%,-130%);
  background:var(--panel-solid);border:1px solid var(--border);border-radius:8px;padding:6px 10px;
  font-family:var(--ui);font-size:11px;font-weight:600;white-space:nowrap;box-shadow:0 6px 20px rgba(0,0,0,0.5);transition:opacity 0.12s}
.topo-tip .tip-sub{font-family:var(--mono);font-size:9px;color:var(--muted);font-weight:400;margin-top:2px}

/* ── RAIL TOOLTIPS ───────────────────────────────────── */
.rail-btn{position:relative}
.rail-tip{
  position:absolute;left:48px;top:50%;transform:translateY(-50%) translateX(-6px);
  background:var(--panel-solid);border:1px solid var(--border);color:var(--text);
  font-family:var(--ui);font-size:11px;font-weight:600;letter-spacing:0.4px;white-space:nowrap;
  padding:5px 10px;border-radius:8px;pointer-events:none;opacity:0;z-index:60;
  box-shadow:0 6px 20px rgba(0,0,0,0.5);transition:opacity 0.15s,transform 0.15s;
}
.rail-btn:hover .rail-tip{opacity:1;transform:translateY(-50%) translateX(0)}

/* ── VIEW PANES (switched by rail) ───────────────────── */
.view-pane{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}

/* ── HOME / MISSION CONTROL DASHBOARD ────────────────── */
.home-scroll{flex:1;overflow-y:auto;padding:22px 24px 40px;display:flex;flex-direction:column;gap:22px}
.home-status{
  display:grid;grid-template-columns:repeat(6,1fr);gap:14px;
  padding:20px 22px;border:1px solid var(--border);border-radius:14px;
  background:linear-gradient(135deg,rgba(34,217,230,0.05),rgba(255,255,255,0.012));
}
.hs-cell{display:flex;flex-direction:column;gap:4px;border-left:1px solid var(--border-2);padding-left:16px}
.hs-cell:first-child{border-left:none;padding-left:0}
.hs-cell .hsv{font-family:var(--mono);font-size:23px;font-weight:600;color:var(--accent)}
.hs-cell .hsl{font-size:9.5px;text-transform:uppercase;letter-spacing:1.3px;color:var(--muted)}
.hs-cell .hsv.ok{color:var(--good)}
.hs-cell .hsv.bad{color:var(--bad)}

/* glassy mission-control card */
.mc-card{border:1px solid var(--border);border-radius:14px;
  background:linear-gradient(160deg,rgba(255,255,255,0.022),rgba(0,0,0,0.10));
  overflow:hidden;display:flex;flex-direction:column;min-width:0;
  box-shadow:0 8px 26px rgba(0,0,0,0.22)}
/* LEARNING & DREAMS fix: that view stacks .mc-card panels inside a fixed-height
   flex column (#learn-body / .learn-scroll). Flex children shrink by default and
   .mc-card has overflow:hidden, so each section (Scorecard, Training Activity,
   Vitals, Pipeline, Dreams) was squished into a tiny clipped window. Pin the
   cards to their natural content height so the whole view scrolls instead. */
.learn-scroll > .mc-card{flex-shrink:0}
.mc-hdr{padding:14px 17px;border-bottom:1px solid var(--border);
  display:flex;align-items:center;justify-content:space-between;gap:10px}
.mc-hdr .mc-t .lbl{font-size:13.5px;font-weight:700}
.mc-hdr .mc-t{display:flex;align-items:center;gap:9px;min-width:0}
.mc-hdr .mc-t svg{width:14px;height:14px;color:var(--accent);flex-shrink:0}
.mc-hdr .mc-t .lbl{color:var(--text)}
.mc-hdr .mc-cnt{font-size:9px;font-family:var(--mono);color:var(--muted);flex-shrink:0}
.mc-hdr.link{cursor:pointer;transition:background 0.14s}
.mc-hdr.link:hover{background:rgba(34,217,230,0.05)}
.mc-open{display:inline-flex;align-items:center;gap:5px;font-family:var(--ui);font-size:8px;
  font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--muted-2);
  border:1px solid var(--border);border-radius:7px;padding:3px 7px;transition:all 0.14s;flex-shrink:0}
.mc-hdr.link:hover .mc-open{color:var(--accent);border-color:rgba(34,217,230,0.4)}
.mc-open svg{width:10px;height:10px}

/* ── KAI VITALS card (Learning view) — 4 grouped sections, scannable rows ── */
.vit-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:18px}
.vit-sec{border:1px solid var(--border);border-radius:11px;padding:15px 17px 16px;
  background:linear-gradient(160deg,rgba(255,255,255,0.018),rgba(0,0,0,0.06))}
.vit-h{font-size:11px;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;
  color:var(--accent);margin-bottom:11px;padding-bottom:7px;border-bottom:1px solid var(--border)}
.vit-row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;
  padding:6px 0;font-size:12.5px;border-bottom:1px dotted rgba(255,255,255,0.04)}
.vit-row:last-child{border-bottom:none}
.vit-l{color:var(--muted);min-width:0}
.vit-v{font-family:var(--mono);font-size:13px;color:var(--text);text-align:right;white-space:nowrap}
.vit-v.na{color:var(--muted-2);font-style:italic;font-size:11.5px}
/* OVERLAP FIX: long label + long value (e.g. "Hippocampus CA3/CA1" + "patterns 0 ·
   pending 0 · promoted 0") collided because the nowrap value spilled LEFT over the
   label. Let the row wrap so a too-wide value drops to its own right-aligned line. */
.vit-row{flex-wrap:wrap}
.vit-row .vit-l{flex:1 1 auto}
.vit-row .vit-v{flex:0 0 auto;margin-left:auto;max-width:100%}
.vit-tag{font-size:7.5px;font-weight:700;letter-spacing:0.04em;text-transform:uppercase;margin-left:6px;padding:1px 4px;border-radius:4px;vertical-align:middle;background:rgba(255,255,255,0.05);color:var(--muted-2)}
.vit-tag.engine{background:rgba(34,217,230,0.14);color:#22d9e6}
.vit-tag.derived{background:rgba(167,139,250,0.14);color:#a78bfa}
.vit-tag.bot{background:rgba(74,222,128,0.14);color:#4ade80}
.pl-stepper{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.pl-step{font-size:10px;font-weight:700;letter-spacing:0.04em;text-transform:uppercase;padding:4px 9px;border-radius:7px;border:1px solid var(--border);color:var(--muted-2);background:rgba(255,255,255,0.02)}
.pl-step.active{border-color:#22d9e6;color:#22d9e6;background:rgba(34,217,230,0.1)}
.pl-step.done{border-color:#4ade80;color:#4ade80}
.pl-arrow{color:var(--muted-2);font-size:11px}
.pl-win{font-weight:700;font-size:10px;letter-spacing:0.03em;padding:1px 6px;border-radius:5px}
.pl-win.run{background:rgba(34,217,230,0.16);color:#22d9e6}
.pl-win.open{background:rgba(251,191,36,0.16);color:#fbbf24}
.pl-win.closed{background:rgba(148,163,184,0.14);color:var(--muted-2)}
.vit-bar-row{padding:6px 0;border-bottom:1px dotted rgba(255,255,255,0.04)}
.vit-src{font-size:7px;margin-left:5px;vertical-align:middle;cursor:help}
.vit-src.eng{color:#4ade80}
.vit-src.der{color:#fbbf24}

/* ── KAI TRAINING (Learning view): scorecard + live terminal + composer ──
   Fully responsive: the scorecard reflows via auto-fit; the terminal is a
   min-height:0 flex child with its own overflow so it never clips the view. */
.trn-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px}
.trn-cell{border:1px solid var(--border);border-radius:11px;padding:10px 12px;min-width:0;
  background:linear-gradient(160deg,rgba(255,255,255,0.02),rgba(0,0,0,0.06))}
.trn-cell .k{font-size:9px;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;color:var(--muted-2);display:block;margin-bottom:5px}
.trn-cell .v{font-family:var(--mono);font-size:21px;font-weight:600;color:var(--text);line-height:1.1;word-break:break-word}
.trn-cell .v.na{color:var(--muted-2);font-style:italic;font-size:13px}
.trn-cell .sub{font-family:var(--mono);font-size:9.5px;color:var(--muted-2);margin-top:3px}
.trn-status{display:inline-block;padding:2px 9px;border-radius:6px;font-size:11px;font-weight:700;font-family:var(--mono)}
.trn-status.pass{background:rgba(74,222,128,0.14);color:#4ade80}
.trn-status.fail{background:rgba(248,113,113,0.14);color:#f87171}
.trn-status.idle{background:rgba(255,255,255,0.05);color:var(--muted-2)}
.trn-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.trn-chip{background:rgba(251,191,36,0.12);color:#fbbf24;border-radius:6px;padding:2px 8px;font-size:10px;font-family:var(--mono)}
.trn-chip.topic{background:rgba(34,217,230,0.10);color:#22d9e6}
/* live terminal */
.train-term{font-family:var(--mono);font-size:11px;line-height:1.5;color:var(--muted);
  background:rgba(0,0,0,0.22);border-top:1px solid var(--border);
  height:clamp(260px,42vh,560px);overflow-y:auto;padding:10px 12px 14px;
  display:flex;flex-direction:column;gap:7px;min-height:0;scroll-behavior:smooth}
.train-term:focus{outline:1px solid rgba(34,217,230,0.4);outline-offset:-1px}
.trn-entry{border-left:2px solid var(--border);padding:5px 0 5px 9px}
.trn-entry .hd{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:2px}
.trn-entry .ph{font-size:10px;font-weight:700;letter-spacing:0.03em}
.trn-entry .tm{font-size:9px;color:var(--muted-2)}
.trn-entry .bd{color:var(--text);white-space:pre-wrap;word-break:break-word;font-size:10.5px;line-height:1.5}
.train-composer{display:flex;gap:8px;padding:9px 11px;border-top:1px solid var(--border);background:rgba(255,255,255,0.02)}
.train-composer input{flex:1;min-width:0;background:rgba(0,0,0,0.25);border:1px solid var(--border);
  border-radius:8px;padding:8px 11px;color:var(--text);font-family:var(--ui);font-size:12px;outline:none}
.train-composer input:focus{border-color:rgba(34,217,230,0.5)}
.train-composer button{flex:0 0 auto;background:var(--accent);color:#04121a;border:none;border-radius:8px;
  padding:8px 16px;font-weight:600;font-size:12px;cursor:pointer;font-family:var(--ui)}
.train-composer button:disabled{opacity:0.5;cursor:default}
.train-composer-note{font-size:9.5px;color:var(--muted-2);padding:6px 12px 9px;line-height:1.4}
@media (max-width:560px){ .trn-cell .v{font-size:18px} .train-term{height:clamp(220px,38vh,440px)} }

/* ── TETRIS GRID: dense, balanced mission-control layout (no dead space) ──
   12-col grid; cards span columns + rows so they pack tightly. The tall cards
   (radar, ops, provider tabs) sit beside short ones so columns stay level. */
.home-grid{
  display:grid;grid-template-columns:repeat(12,1fr);gap:20px;align-items:stretch;
  grid-auto-flow:row dense;
}
/* Less dense / more readable: each card gets a real minimum height so sections
   are big enough to read and you SCROLL down through them (webpage-style) rather
   than everything crushed onto one screen. */
.home-grid > .mc-card{min-height:240px}
.g-sys{grid-column:span 7;grid-row:span 2;min-height:340px}   /* System Resources (wide, tall) */
.g-radar{grid-column:span 5;grid-row:span 3;min-height:480px} /* System Radar (tall) */
/* A6 radar trim: hide providers per backlog. (2026-07-10: this rule also hid
   .g-board .leaderboard — the agent leaderboard TABLE — so the card rendered its
   "N/N online" header but ZERO rows. That was an overreaching selector, not the
   intended "leaderboard axes" trim. Un-hidden so the 9 agents list again.) */
.g-prov { display: none !important; }
.g-prov{grid-column:span 5;grid-row:span 2;min-height:340px}  /* Provider/Connections tabbed box */
.g-lat{grid-column:span 7;grid-row:span 1;min-height:240px}   /* Lattice Metrics — WIDER (was span 3): uses the horizontal room */
.g-board{grid-column:1 / -1;grid-row:span 1;min-height:300px} /* agent leaderboard — full-width band */
.g-ops{grid-column:1 / -1;grid-row:span 1;min-height:300px}   /* live operations — full-width */
/* let inner scroll areas breathe inside fixed-height rows */
.g-board .leaderboard,.g-ops .activity-stream,.g-prov .ptab-body{max-height:none}

/* ── lattice key-metrics tiles ─────────────────────────── */
/* WIDER: lay the tiles out across the available width (auto-fit, ~3 across on a
   wide card) instead of a tall narrow 2-col block. Bigger type for readability. */
.lat-grid{padding:14px 16px 16px;display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:13px;align-content:start}
.lat-cell{border:1px solid var(--border);border-radius:11px;background:rgba(0,0,0,0.18);padding:12px 14px;display:flex;flex-direction:column;gap:4px}
.lat-cell .lcv{font-family:var(--mono);font-size:20px;font-weight:600;color:var(--accent)}
.lat-cell .lcv.na{color:var(--muted-2);font-size:13px}
.lat-cell .lcl{font-size:9px;text-transform:uppercase;letter-spacing:1px;color:var(--muted)}
.lat-cell .lcd{font-size:9px;font-family:var(--mono);color:var(--muted-2)}
.lat-cell.pos .lcv{color:var(--good)} .lat-cell.neg .lcv{color:var(--bad)}

/* ── PROVIDER / CONNECTIONS tabbed box ─────────────────── */
.ptabs{display:flex;gap:4px;align-items:center}
.ptab-btn{font-family:var(--ui);font-size:9px;font-weight:700;letter-spacing:0.8px;text-transform:uppercase;
  padding:4px 10px;border-radius:7px;background:rgba(255,255,255,0.04);color:var(--muted-2);
  border:1px solid transparent;cursor:pointer;transition:all 0.14s}
.ptab-btn:hover{color:#c8d2e0;background:rgba(255,255,255,0.08)}
.ptab-btn.on{background:rgba(34,217,230,0.16);color:var(--accent);border-color:rgba(34,217,230,0.4)}
.ptab-body{flex:1;overflow-y:auto;min-height:0}

/* ── agent leaderboard (summary table, vitals visible) ── */
.leaderboard{padding:4px 6px 8px;overflow-x:auto;flex:1;overflow-y:auto}
.lb-table{width:100%;border-collapse:collapse;font-size:11px}
.lb-table th{font-family:var(--ui);font-size:8px;font-weight:700;letter-spacing:1px;text-transform:uppercase;
  color:var(--muted);text-align:right;padding:6px 8px;border-bottom:1px solid var(--border);position:sticky;top:0;background:var(--panel-solid);z-index:1}
.lb-table th.l{text-align:left}
.lb-row td{padding:6px 8px;border-bottom:1px solid var(--border-2);vertical-align:middle;text-align:right;font-family:var(--mono);font-size:10.5px}
.lb-row td.l{text-align:left}
.lb-row:hover td{background:rgba(255,255,255,0.022)}
.lb-row.lb-top td{background:rgba(255,210,122,0.05)}
.lb-row.lb-top:hover td{background:rgba(255,210,122,0.09)}
.lb-agent{display:flex;align-items:center;gap:8px;min-width:0}
.lb-av{width:22px;height:22px;border-radius:6px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:10px;color:#04070d;position:relative}
.lb-av .pdot{position:absolute;bottom:-2px;right:-2px;width:7px;height:7px;border-radius:50%;border:2px solid var(--panel-solid)}
.lb-nm{font-family:var(--ui);font-weight:700;font-size:11px;white-space:nowrap;cursor:pointer}
.lb-bar-wrap{display:inline-block;width:46px;height:5px;border-radius:4px;background:rgba(255,255,255,0.06);overflow:hidden;vertical-align:middle;margin-right:6px}
.lb-bar{height:100%;border-radius:4px}
.lb-on{font-size:8px;font-family:var(--mono);padding:1px 6px;border-radius:5px}

/* ── traffic chart card ────────────────────────────────── */
.traffic-wrap{padding:8px 12px 12px;display:flex;flex-direction:column;gap:4px;flex:1}
.traffic-wrap svg{width:100%}
.traffic-note{font-size:8.5px;font-family:var(--mono);color:var(--muted-2)}
/* per-core load strip under the CPU meter */
.core-strip{display:flex;align-items:flex-end;gap:2px;height:22px;margin-top:7px}
.core-strip .core-cell{flex:1;min-width:2px;border-radius:2px 2px 0 0;opacity:0.85;transition:height 0.4s ease,background 0.4s ease}

/* ── SYSTEM METRICS OVERVIEW (graphical widgets) ──────── */
.metrics-overview{padding:14px;display:grid;grid-template-columns:1fr 1fr;gap:13px}
.widget{border:1px solid var(--border);border-radius:11px;padding:11px 12px 9px;
  background:rgba(0,0,0,0.20);display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0}
.widget .w-lbl{font-family:var(--ui);font-size:8.5px;font-weight:700;letter-spacing:1px;
  text-transform:uppercase;color:var(--muted);text-align:center}
.widget .w-val{font-family:var(--mono);font-size:11px;color:var(--accent);font-weight:600}
.widget svg{display:block;overflow:visible}
.widget.full{grid-column:1 / -1;align-items:stretch}

/* ── CONNECTIONS / SERVICES ───────────────────────────── */
.conn-list{padding:9px 12px 12px;display:flex;flex-direction:column;gap:6px;flex:1;overflow-y:auto}
.conn-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--border);
  border-radius:10px;background:rgba(0,0,0,0.16)}
.conn-ic{width:28px;height:28px;border-radius:8px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:11px;color:#04070d;position:relative}
.conn-ic .cdot{position:absolute;bottom:-2px;right:-2px;width:9px;height:9px;border-radius:50%;border:2px solid var(--panel-solid)}
.conn-meta{flex:1;min-width:0}
.conn-name{font-family:var(--ui);font-weight:600;font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.conn-sub{font-size:9px;color:var(--muted-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--mono)}
.conn-stat{display:flex;flex-direction:column;align-items:flex-end;gap:2px;flex-shrink:0}
.conn-badge{font-size:8px;font-family:var(--mono);font-weight:600;letter-spacing:0.5px;padding:2px 7px;border-radius:6px;text-transform:uppercase}
.conn-metric{font-size:8.5px;font-family:var(--mono);color:var(--muted-2)}

/* ── AI PORTFOLIO (table) ─────────────────────────────── */
.portfolio{padding:6px 6px 8px;overflow-x:auto;flex:1;overflow-y:auto;max-height:330px}
.pf-table{width:100%;border-collapse:collapse;font-size:11px}
.pf-table th{font-family:var(--ui);font-size:8px;font-weight:700;letter-spacing:1px;text-transform:uppercase;
  color:var(--muted);text-align:left;padding:7px 9px;border-bottom:1px solid var(--border);position:sticky;top:0;background:var(--panel-solid);z-index:1}
.pf-table th.r{text-align:right}
.pf-row td{padding:8px 9px;border-bottom:1px solid var(--border-2);vertical-align:middle}
.pf-row:hover td{background:rgba(255,255,255,0.022)}
.pf-agent{display:flex;align-items:center;gap:9px;min-width:0}
.pf-av{width:26px;height:26px;border-radius:7px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--ui);font-weight:800;font-size:11px;color:#04070d;position:relative}
.pf-av .pdot{position:absolute;bottom:-2px;right:-2px;width:8px;height:8px;border-radius:50%;border:2px solid var(--panel-solid)}
.pf-nm{font-family:var(--ui);font-weight:700;font-size:11.5px;white-space:nowrap}
.pf-rl{font-size:8.5px;color:var(--muted-2);white-space:nowrap}
.pf-prov{font-family:var(--mono);font-size:10px;color:var(--muted)}
.pf-model{font-family:var(--mono);font-size:9.5px;color:var(--muted-2)}
.pf-hp{display:flex;align-items:center;gap:7px}
.pf-bar-wrap{width:54px;height:6px;border-radius:5px;background:rgba(255,255,255,0.06);overflow:hidden}
.pf-bar{height:100%;border-radius:5px}
.pf-pct{font-family:var(--mono);font-size:9.5px;color:var(--muted);min-width:26px}
.pf-acts{display:flex;gap:5px;justify-content:flex-end}
.pf-btn{font-family:var(--ui);font-size:8px;font-weight:700;letter-spacing:0.5px;text-transform:uppercase;
  padding:4px 8px;border-radius:6px;border:1px solid var(--border);background:rgba(255,255,255,0.03);
  color:var(--muted-2);cursor:pointer;transition:all 0.14s;white-space:nowrap;position:relative}
.pf-btn.dm{color:var(--accent);border-color:rgba(34,217,230,0.3)}
.pf-btn.cfg:hover,.pf-btn.dm:hover{background:rgba(255,255,255,0.07);transform:translateY(-1px)}
.pf-btn.dis{cursor:not-allowed;opacity:0.55}
.pf-btn .s2{position:absolute;top:-6px;right:-3px;font-size:6px;color:var(--accent);background:var(--bg);padding:0 3px;border-radius:4px}

/* ── activity stream (kept, scrollable) ───────────────── */
.activity-stream{flex:1;overflow-y:auto;max-height:330px;padding:8px 12px 12px;display:flex;flex-direction:column;gap:2px}
.act-row{display:flex;gap:10px;align-items:baseline;padding:7px 8px;border-radius:8px;transition:background 0.12s}
.act-row:hover{background:rgba(255,255,255,0.025)}
.act-ts{font-family:var(--mono);font-size:9px;color:var(--muted-2);flex-shrink:0;width:54px;font-variant-numeric:tabular-nums}
.act-who{font-family:var(--ui);font-weight:700;font-size:11px;flex-shrink:0;white-space:nowrap}
.act-chan{font-size:8.5px;font-family:var(--mono);color:var(--muted-2);flex-shrink:0;padding:1px 5px;border-radius:5px;background:rgba(255,255,255,0.04)}
.act-text{flex:1;min-width:0;font-size:11.5px;color:#c8d2e0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.op-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;align-self:center;box-shadow:0 0 6px currentColor}
.op-type{font-size:10px;flex-shrink:0;opacity:.8;width:14px;text-align:center}
.ops-fbtn{font-family:var(--mono);font-size:8.5px;text-transform:uppercase;letter-spacing:.5px;padding:2px 7px;border-radius:6px;background:rgba(255,255,255,0.05);color:var(--muted-2);border:1px solid transparent;cursor:pointer}
.ops-fbtn:hover{background:rgba(255,255,255,0.09);color:#c8d2e0}
.ops-fbtn.on{background:rgba(34,217,230,0.16);color:var(--accent);border-color:rgba(34,217,230,0.4)}

/* ── TOPOLOGY ────────────────────────────────────────── */
.topo-wrap{flex:1;overflow:hidden;display:flex;align-items:center;justify-content:center;padding:16px;position:relative}
.topo-wrap svg{width:100%;height:100%;max-height:100%}
.topo-legend{position:absolute;top:16px;left:18px;display:flex;flex-direction:column;gap:6px;font-size:10px;color:var(--muted)}
.topo-legend .ll{display:flex;align-items:center;gap:7px}
.topo-legend .lk{width:9px;height:9px;border-radius:50%}

/* ── ORACLE NERVOUS SYSTEM VIEW ──────────────────────── */
#view-nervous{flex:1;min-height:0;flex-direction:column}
.ns-wrap{flex:1;position:relative;overflow:hidden;min-height:0;
  background:
    radial-gradient(680px 480px at 50% 46%, rgba(34,217,230,0.05), transparent 70%),
    radial-gradient(circle at 50% 50%, rgba(124,58,237,0.04), transparent 60%);
  touch-action:none;cursor:grab}
.ns-wrap.dragging{cursor:grabbing}
.ns-wrap canvas,.ns-wrap .ns-svg{position:absolute;inset:0;width:100%;height:100%}
.ns-svg{z-index:2}
.ns-wrap canvas{z-index:1}
.ns-edge{transition:stroke 0.5s ease,stroke-opacity 0.18s ease,stroke-width 0.18s ease}
.ns-node{cursor:pointer}
.ns-node text{pointer-events:none;user-select:none}
.ns-svg.has-focus .ns-node:not(.focus){opacity:0.18}
.ns-svg.has-focus .ns-edge:not(.focus){stroke-opacity:0.05!important}
.ns-edge.hot{stroke-width:2.4!important}
.ns-legend{position:absolute;top:14px;left:16px;z-index:6;display:flex;flex-direction:column;gap:5px;
  font-size:10px;color:var(--muted);background:var(--panel-2);border:1px solid var(--border);
  border-radius:11px;padding:11px 13px;backdrop-filter:blur(10px);pointer-events:none;max-width:200px}
.ns-legend-title{font-family:var(--ui);font-size:9px;font-weight:700;letter-spacing:1.6px;color:var(--muted-2);margin-bottom:2px}
.ns-legend .ll{display:flex;align-items:center;gap:8px;color:var(--text)}
.ns-legend .lk{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.ns-counters{position:absolute;top:14px;right:16px;z-index:6;display:flex;gap:8px}
.ns-ctr{display:flex;flex-direction:column;align-items:center;gap:1px;background:var(--panel-2);
  border:1px solid var(--border);border-radius:11px;padding:8px 14px;backdrop-filter:blur(10px);min-width:72px}
.ns-ctr-v{font-family:var(--mono);font-size:18px;font-weight:600;color:var(--accent);line-height:1}
.ns-ctr.err .ns-ctr-v{color:var(--bad)}
.ns-ctr-l{font-size:8px;text-transform:uppercase;letter-spacing:1px;color:var(--muted);margin-top:3px}
.ns-status{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:6;
  font-family:var(--mono);font-size:10px;letter-spacing:1px;color:var(--muted);
  background:var(--panel-2);border:1px solid var(--border);border-radius:20px;padding:5px 16px;
  backdrop-filter:blur(10px);pointer-events:none;white-space:nowrap}
.ns-tip{position:absolute;z-index:8;opacity:0;pointer-events:none;transform:translate(-50%,-118%);
  background:var(--panel-solid);border:1px solid var(--accent-glow);border-radius:9px;padding:8px 11px;
  font-size:11px;color:var(--text);box-shadow:0 8px 26px rgba(0,0,0,0.6);transition:opacity 0.12s ease;
  min-width:140px;max-width:230px}
.ns-tip .tt-nm{font-family:var(--ui);font-weight:700;font-size:12px;margin-bottom:3px}
.ns-tip .tt-r{display:flex;justify-content:space-between;gap:14px;font-family:var(--mono);font-size:10px;color:var(--muted);line-height:1.7}
.ns-tip .tt-r b{font-weight:500}
/* sits ABOVE the area-map radar (which occupies the bottom-right corner) */
/* KAIVERSE agent-click popup. DESKTOP-FIX(oraclefix): the panel was mobile-first —
   anchored bottom-RIGHT where the area-map radar now lives (JS bumps the radar up
   to bottom:170px), so on a wide desktop the popup collided with / sat under the
   radar and looked broken. Anchor it bottom-LEFT (a clean, uncluttered corner on
   desktop), give it a comfortable readable width, box-sizing, and a viewport-aware
   height so a tall body scrolls instead of overflowing. The mobile @media rule
   below still overrides this to a full-width bottom sheet, so phones are unchanged. */
.ns-edge-panel{position:absolute;left:16px;right:auto;bottom:24px;z-index:11;width:328px;max-width:calc(100vw - 32px);
  box-sizing:border-box;max-height:min(60vh,420px);
  background:var(--panel-2);border:1px solid var(--border);border-radius:13px;backdrop-filter:blur(14px);
  display:none;flex-direction:column;overflow:hidden;box-shadow:0 14px 40px rgba(0,0,0,0.55)}
.ns-edge-panel{transition:opacity 0.22s ease}
.ns-edge-panel.open{display:flex}
.ns-ep-hdr{display:flex;align-items:center;justify-content:space-between;padding:11px 14px;
  border-bottom:1px solid var(--border);font-family:var(--ui);font-weight:700;font-size:12px;color:var(--text)}
.ns-ep-x{cursor:pointer;color:var(--muted);font-size:13px;padding:0 4px}
.ns-ep-x:hover{color:var(--text)}
.ns-ep-body{flex:1;min-height:0;max-height:min(46vh,320px);overflow-y:auto;padding:6px 0}
.ns-ep-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:7px 14px;font-size:11px;border-bottom:1px solid var(--border-2)}
.ns-ep-row:last-child{border-bottom:none}
/* DESKTOP-FIX(oraclefix): the click-panel body renders <span class="ns-ep-k">/<span
   class="ns-ep-v"> key/value rows, but these two classes had NO CSS (the old rule set
   only styled a dot/timestamp/text activity layout) — so on desktop the rows rendered
   as cramped, unstyled, left-bunched text. Give the key a muted uppercase label and
   the value a right-aligned mono readout that wraps instead of overflowing the panel. */
.ns-ep-k{flex:0 0 auto;color:var(--muted-2);font-size:9.5px;letter-spacing:.5px;text-transform:uppercase;white-space:nowrap}
.ns-ep-v{flex:1 1 auto;min-width:0;text-align:right;color:var(--text);font-family:var(--mono);font-size:11px;line-height:1.5;word-break:break-word}
.ns-ep-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.ns-ep-ts{font-family:var(--mono);font-size:9px;color:var(--muted-2);flex-shrink:0;width:34px}
.ns-ep-txt{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.ns-ep-empty{padding:22px 14px;text-align:center;color:var(--muted-2);font-size:11px}
@media (max-width:900px){
  .ns-counters{gap:5px;top:auto;bottom:64px;right:10px}
  .ns-ctr{padding:6px 10px;min-width:58px}
  .ns-ctr-v{font-size:15px}
  .ns-legend{top:auto;bottom:64px;left:10px;font-size:9px;padding:8px 10px;max-width:150px}
  .ns-edge-panel{left:10px;right:10px;bottom:110px;width:auto}
  .ns-status{bottom:108px}
}

/* ── KAIVERSE 3D explorer chrome (overlays the WebGL canvas) ───────────── */
/* TRUE-BLACK SPACE BACKDROP. The previous blue the owner saw was NOT the
   renderer — it was (a) the .ns-wrap blue/purple radial-gradient still applied
   to this same element (it carries BOTH classes), and (b) the transparent
   canvas (renderer alpha:true) letting the page body's blue radial-gradients +
   lattice grid show THROUGH. Fixed here by: forcing an opaque near-black bg with
   !important to beat the .ns-wrap gradient, killing any inherited image, and
   (in JS) building the renderer with alpha:false so nothing bleeds through. */
.kv-wrap{background:#010205 !important;background-image:none !important;cursor:grab}
.kv-wrap::before{content:none !important}     /* no grid/gradient pseudo bleed */
.kv-wrap.dragging{cursor:grabbing}
/* pointer-lock active → hide the OS cursor entirely over the canvas + all overlays */
.kv-wrap.locked,.kv-wrap.locked *{cursor:none !important}
#kv-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:1;display:block;touch-action:none;background:#010205}
.kv-fallback{position:absolute;inset:0;z-index:5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;text-align:center;padding:30px}
.kv-fb-icon{font-size:34px;color:var(--warn)}
.kv-fb-title{font-family:var(--ui);font-weight:700;font-size:16px;color:var(--text)}
.kv-fb-sub{font-size:12px;color:var(--muted);max-width:380px;line-height:1.6}
.kv-hud{position:absolute;top:14px;left:16px;z-index:6;display:flex;flex-direction:column;gap:7px;
  background:var(--panel-2);border:1px solid var(--border);border-radius:13px;padding:13px 15px;
  backdrop-filter:blur(12px);min-width:236px;pointer-events:none;box-shadow:0 10px 34px rgba(0,0,0,0.5)}
.kv-hud-title{font-family:var(--ui);font-size:9px;font-weight:700;letter-spacing:1.8px;color:var(--accent);margin-bottom:2px}
.kv-stat{display:flex;align-items:baseline;justify-content:space-between;gap:16px}
.kv-sl{font-size:10.5px;color:var(--muted)}
.kv-sl em{font-style:normal;color:var(--muted-2);font-size:9px}
.kv-sv{font-family:var(--mono);font-size:13px;font-weight:600;color:var(--accent);line-height:1.5}
.kv-sv.na{color:var(--muted-2);font-style:italic;font-size:11px}
.kv-legend{top:14px;left:auto;right:16px;max-width:230px;pointer-events:none}
.kv-hint{margin-top:6px;padding-top:6px;border-top:1px solid var(--border-2);font-size:9px;color:var(--muted-2);line-height:1.5}
.kv-status{pointer-events:none}
.kv-node-panel{width:288px}
/* ── THROTTLE / SPEED indicator (bottom-centre, above status) ── */
.kv-throttle{position:absolute;left:50%;bottom:52px;transform:translateX(-50%);z-index:6;
  display:flex;align-items:center;gap:10px;pointer-events:none;
  background:var(--panel-2);border:1px solid var(--border);border-radius:20px;padding:6px 14px;
  backdrop-filter:blur(10px);box-shadow:0 8px 26px rgba(0,0,0,0.5)}
.kv-throttle .kv-th-lbl{font-family:var(--ui);font-size:9px;font-weight:700;letter-spacing:1.4px;color:var(--muted)}
.kv-throttle .kv-th-bar{width:120px;height:6px;border-radius:4px;background:rgba(255,255,255,0.08);overflow:hidden}
.kv-throttle .kv-th-fill{height:100%;width:30%;border-radius:4px;
  background:linear-gradient(90deg,#22d9e6,#7c3aed);transition:width 0.12s ease}
.kv-throttle .kv-th-val{font-family:var(--mono);font-size:11px;font-weight:600;color:var(--accent);min-width:36px;text-align:right}
/* Immersive-vr entry — desktop HUD + mobile (not hidden with throttle chrome) */
.kv-vr-btn{position:absolute;right:16px;bottom:52px;z-index:8;min-width:52px;height:36px;padding:0 14px;
  border-radius:10px;border:1px solid rgba(34,217,230,.45);background:rgba(8,14,24,.82);color:#7ee8f5;
  font:700 12px Outfit,sans-serif;letter-spacing:.06em;cursor:pointer;backdrop-filter:blur(6px);
  box-shadow:0 4px 16px rgba(0,0,0,.35)}
.kv-vr-btn:hover{border-color:var(--accent);background:rgba(34,217,230,.15)}
.kv-vr-btn.on{background:rgba(34,217,230,.28);color:#fff;border-color:#22d9e6}
body.force-mobile .kv-vr-btn, body.kv-hud-hidden .kv-vr-btn{display:block !important;bottom:calc(18px + env(safe-area-inset-bottom,0px));right:12px}
/* ── COMPASS → CORE (top-centre) — always points home + shows distance ── */
.kv-compass{display:none;position:absolute;left:50%;top:14px;transform:translateX(-50%);z-index:6;
  display:flex;align-items:center;gap:9px;pointer-events:auto;cursor:pointer;
  background:var(--panel-2);border:1px solid var(--border);border-radius:20px;padding:6px 13px;
  backdrop-filter:blur(10px);box-shadow:0 8px 26px rgba(0,0,0,0.5)}
.kv-compass:hover{border-color:var(--accent-glow)}
.kv-compass .kv-cmp-dial{width:26px;height:26px;flex-shrink:0;position:relative}
.kv-compass .kv-cmp-arrow{position:absolute;inset:0;transform-origin:50% 50%;transition:transform 0.1s linear}
.kv-compass .kv-cmp-txt{display:flex;flex-direction:column;line-height:1.2}
.kv-compass .kv-cmp-t1{font-family:var(--ui);font-size:9px;font-weight:700;letter-spacing:1px;color:var(--accent)}
.kv-compass .kv-cmp-t2{font-family:var(--mono);font-size:9px;color:var(--muted)}
/* off-screen CORE edge marker — a chevron pinned to the viewport edge */
.kv-coremark{position:absolute;z-index:6;pointer-events:none;display:none;
  width:30px;height:30px;margin:-15px 0 0 -15px;color:var(--accent);
  filter:drop-shadow(0 0 6px var(--accent-glow))}
.kv-coremark.show{display:block}
/* RECENT ERRORS readout (restored error-source attribution) */
/* HUD overlays sit ABOVE the WebGL canvas (z-index:1) AND take pointer events so
   the panel + its "⤢ full" button reliably receive clicks. The canvas mousedown
   handler also bails when the target is inside one of these (see nsWireWrapOnce),
   so clicking UI never triggers pointer-lock / fly-to. (owner complaint #4) */
.ns-errbox{pointer-events:auto !important;min-width:280px;z-index:12}
.ns-errbox *{pointer-events:auto}
.ns-edge-panel,.kv-node-panel{pointer-events:auto;z-index:11}
/* ── AREA MAP / RADAR (owner #2) — bottom-right corner overlay ── */
/* AREA MAP / radar — owner #1: was clipped off-screen + too dim. Now FULLY inset
   from the corner (24px), a higher-contrast opaque panel with a clear border, and
   constrained so it can never overflow the viewport at any resolution. */
/* owner #3: lifted UP well clear of the bottom status bar (.ns-status sits at
   bottom:16px, ~30px tall). bottom:92px keeps the whole dial inside the viewport
   at every resolution and off the click-area where moving bodies are grabbed. */
.kv-radar{position:absolute;right:18px;bottom:18px;z-index:9;opacity:0.85;pointer-events:auto;
  background:rgba(6,12,22,0.92);border:1.5px solid rgba(34,217,230,0.55);border-radius:13px;padding:9px 10px 10px;
  backdrop-filter:blur(13px);box-shadow:0 10px 38px rgba(0,0,0,0.62), 0 0 0 1px rgba(0,0,0,0.4);
  width:188px;max-width:calc(100vw - 48px);box-sizing:border-box}
.kv-radar-hd{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.kv-radar-hd span:first-child{font-family:var(--ui);font-size:9.5px;font-weight:800;letter-spacing:1.7px;color:var(--accent)}
.kv-radar-rng{font-family:var(--mono);font-size:9px;color:#cfe0f2}
.kv-radar canvas{display:block;width:168px;height:168px;max-width:100%;border-radius:9px;
  background:radial-gradient(circle at 50% 50%, rgba(8,16,28,0.96), rgba(2,5,11,0.98));
  border:1px solid rgba(120,150,190,0.28);cursor:pointer}
/* keep it visible but a touch smaller on short/narrow viewports so it never clips */
@media (max-height:560px){ .kv-radar{bottom:200px;right:16px;width:150px}
  .kv-radar canvas{width:130px;height:130px} }
@media (max-width:560px){ .kv-radar{right:14px;bottom:210px;width:148px}
  .kv-radar canvas{width:128px;height:128px} }
.ns-errlist{display:flex;flex-direction:column;gap:5px;max-height:208px;overflow-y:auto;margin-top:3px}
.ns-err-empty{font-size:10px;color:var(--muted-2);font-style:italic;padding:2px 0}
.ns-err-row{display:flex;flex-direction:column;gap:1px;padding:5px 7px;border-radius:8px;cursor:pointer;
  background:rgba(248,113,113,0.07);border:1px solid rgba(248,113,113,0.22);transition:background 0.14s ease}
.ns-err-row:hover{background:rgba(248,113,113,0.16)}
.ns-err-row.warn{background:rgba(251,191,36,0.06);border-color:rgba(251,191,36,0.2)}
.ns-err-path{font-family:var(--mono);font-size:10.5px;font-weight:600;color:#f87171}
.ns-err-row.warn .ns-err-path{color:#fbbf24}
.ns-err-what{font-size:9.5px;color:var(--muted);line-height:1.35}
.ns-err-time{font-size:8.5px;color:var(--muted-2);font-family:var(--mono)}
/* the ⚠ events pill is a MOBILE-ONLY affordance — never shown on desktop */
.ns-events-toggle{display:none}
/* MOBILE: hide the RECENT ERRORS / signal-flow feed by default so it never
   covers the KAIVERSE. The pill (.ns-events-toggle) toggles #ns-errbox.open. */
@media (max-width:900px){
  .ns-errbox{display:none}
  .ns-errbox.open{display:flex !important;max-width:80vw !important;min-width:0;left:10px !important;bottom:170px !important}
  .ns-errlist{max-height:38vh}
  .ns-events-toggle{display:flex;align-items:center;gap:6px;position:absolute;left:10px;bottom:118px;z-index:8;
    padding:7px 12px;border-radius:999px;font-family:var(--ui);font-size:11px;font-weight:700;letter-spacing:0.4px;
    color:#fbbf24;background:rgba(12,18,28,0.92);border:1px solid rgba(251,191,36,0.45);
    box-shadow:0 4px 16px rgba(0,0,0,0.55);backdrop-filter:blur(8px);cursor:pointer;-webkit-tap-highlight-color:transparent}
  .ns-events-toggle.open{color:#22d9e6;border-color:rgba(34,217,230,0.5);background:rgba(10,20,28,0.94)}
}
@media (max-width:900px){
  .kv-hud{top:10px;left:10px;min-width:0;padding:10px 12px;gap:5px;max-width:54vw}
  .kv-sl{font-size:9px}.kv-sv{font-size:11px}
  .kv-legend{top:auto;bottom:118px;right:10px;max-width:150px}
  .kv-node-panel{left:10px;right:10px;bottom:118px;width:auto}
}

/* ── COCKPIT HUD FRAME (Unit 1) ─────────────────────────── */
#kv-cockpit-frame{position:absolute;inset:0;z-index:5;pointer-events:none;
  border:1px solid rgba(34,217,230,0.08);
  box-shadow:inset 0 0 80px rgba(0,0,0,0.4)}
#kv-cockpit-frame::before,#kv-cockpit-frame::after{content:'';position:absolute;width:40px;height:40px;
  border-color:rgba(34,217,230,0.25);border-style:solid;border-width:0}
#kv-cockpit-frame::before{top:12px;left:12px;border-top-width:2px;border-left-width:2px}
#kv-cockpit-frame::after{top:12px;right:12px;border-top-width:2px;border-right-width:2px}
.kv-hud{box-shadow:0 10px 34px rgba(0,0,0,0.5),0 0 12px rgba(34,217,230,0.08) !important;
  font-family:var(--mono,monospace) !important}
.kv-hud-title{font-family:var(--mono,monospace) !important}
/* Throttle gauge ticks */
.kv-th-ticks{position:absolute;inset:0;display:flex;justify-content:space-between;padding:0 1px}
.kv-th-ticks::before{content:'';position:absolute;left:25%;top:0;bottom:0;width:1px;background:rgba(255,255,255,0.12)}
.kv-th-ticks::after{content:'';position:absolute;left:75%;top:0;bottom:0;width:1px;background:rgba(255,255,255,0.12)}
.kv-th-bar{position:relative}
.kv-th-sep{color:var(--muted-2);font-size:10px;margin:0 2px}
.kv-th-speed,.kv-th-alt{font-family:var(--mono);font-size:10px;color:var(--accent);white-space:nowrap}
.kv-th-alt{color:var(--muted)}

/* ── COCKPIT PANELS (Unit 2) ── Inventory, Star Chart, Ship Status ── */
.kv-cockpit-panel{position:absolute;z-index:14;background:var(--panel-2);border:1px solid var(--border);
  border-radius:13px;backdrop-filter:blur(13px);box-shadow:0 14px 40px rgba(0,0,0,0.55),0 0 14px rgba(34,217,230,0.06);
  overflow:hidden;pointer-events:auto}
.kv-cp-hdr{display:flex;align-items:center;justify-content:space-between;padding:11px 14px;
  border-bottom:1px solid var(--border);font-family:var(--mono,monospace);font-size:10px;font-weight:700;
  letter-spacing:1.8px;color:var(--accent)}
.kv-cp-close{cursor:pointer;color:var(--muted);font-size:16px;padding:0 4px}
.kv-cp-close:hover{color:var(--text)}
/* Inventory */
#kv-inv{right:16px;top:60px;width:240px}
.kv-inv-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;padding:12px}
.kv-inv-slot{aspect-ratio:1;border:1px solid var(--border-2);border-radius:8px;background:rgba(255,255,255,0.02)}
/* Star Chart */
.kv-starchart-panel{left:50%;top:50%;transform:translate(-50%,-50%);width:min(640px,90vw);height:min(440px,70vh)}
#kv-starchart-cv{width:100%;height:calc(100% - 40px);display:block;background:rgba(2,5,11,0.9);cursor:crosshair}
/* Ship Status */
#kv-shipstatus{left:16px;top:60px;width:260px}
.kv-ss-body{padding:8px 0}
.kv-ss-row{display:flex;align-items:center;justify-content:space-between;padding:6px 14px;font-size:11px;
  border-bottom:1px solid var(--border-2)}
.kv-ss-row:last-child{border-bottom:none}
.kv-ss-k{color:var(--muted-2);font-size:9px;letter-spacing:.5px;font-family:var(--mono)}
.kv-ss-v{color:var(--accent);font-family:var(--mono);font-size:11px}

/* ── POST-PROCESSING OVERLAYS (Unit 3) ───────────────── */
#kv-vignette{position:absolute;inset:0;z-index:4;pointer-events:none;
  background:radial-gradient(ellipse at 50% 50%,transparent 55%,rgba(0,0,0,0.35) 100%);opacity:0.3}
#kv-scanlines{position:absolute;inset:0;z-index:4;pointer-events:none;
  background:repeating-linear-gradient(to bottom,transparent 0px,transparent 2px,rgba(0,0,0,0.06) 2px,rgba(0,0,0,0.06) 4px);
  opacity:0.04}
#kv-speedlines{position:absolute;inset:0;z-index:4;pointer-events:none;
  background:radial-gradient(ellipse at 50% 50%,transparent 30%,rgba(180,220,255,0.06) 70%,rgba(120,180,255,0.12) 100%);
  opacity:0;transition:opacity 0.2s ease}
#kv-blackout{position:absolute;inset:0;z-index:50;pointer-events:none;background:#000;opacity:0;
  transition:opacity 0.5s ease}

/* ── GLOBAL CONFIG VIEW ──────────────────────────────── */
.cfg-scroll{flex:1;overflow-y:auto;padding:20px 22px;display:flex;flex-direction:column;gap:22px}
.cfg-sec-hdr{font-size:11px;letter-spacing:1.6px;text-transform:uppercase;color:var(--muted);margin-bottom:2px;display:flex;align-items:center;gap:9px}
.cfg-ai-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.cfg-chan-list{display:flex;flex-direction:column;gap:8px}
.cfg-chan-row{display:flex;align-items:center;gap:12px;padding:10px 13px;border:1px solid var(--border);border-radius:10px;background:rgba(255,255,255,0.012)}
.cfg-chan-ic{width:26px;height:26px;border-radius:7px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:var(--accent-glow);color:var(--accent);font-family:var(--mono);font-size:13px}
.cfg-chan-ic svg{width:13px;height:13px}
.cfg-chan-meta{flex:1;min-width:0}
.cfg-chan-name{font-family:var(--ui);font-weight:600;font-size:12.5px}
.cfg-chan-sub{font-size:9.5px;color:var(--muted-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cfg-chan-stat{font-size:9px;font-family:var(--mono);color:var(--good);display:flex;align-items:center;gap:5px;flex-shrink:0}

/* responsive guard for narrower desktops */
@media(max-width:1500px){
  .col-left{width:262px}
  .col-right{width:288px}
  /* 2-up: keep tall cards beside short ones but on a 6-col base */
  .home-grid{grid-template-columns:repeat(6,1fr)}
  .g-sys{grid-column:span 6;grid-row:span 1}
  .g-radar{grid-column:span 3;grid-row:span 2}
  .g-prov{grid-column:span 3;grid-row:span 2}
  .g-lat{grid-column:span 3}
  .g-traffic{grid-column:span 3}
  .g-board{grid-column:span 6;grid-row:span 1}
  .g-ops{grid-column:span 6;grid-row:span 1}
}
@media(max-width:1280px){
  .metric{min-width:64px;padding:5px 9px}
  .col-left{width:240px}
  .col-right{width:268px}
  .home-status{grid-template-columns:repeat(3,1fr);gap:14px 12px}
  .home-grid{grid-template-columns:1fr}
  .g-sys,.g-radar,.g-prov,.g-lat,.g-traffic,.g-board,.g-ops{grid-column:1 / -1;grid-row:auto}
}

/* ═══════════════════════════════════════════════════════════════════════
   DESKTOP-TABLET RESPONSIVENESS (901–1400px) — the gap the owner hit. Above
   900px the three columns stay side-by-side; without this band a fixed 320px
   right panel + 288px left rail CRUSH the center so cards (KAI Vitals 4-up,
   training scorecard) crunch and the bottom clips. Here we: (1) guarantee the
   center column owns its width (min-width:0) and every view scroll-container
   can actually scroll (min-height:0 + overflow auto) so nothing is unreachable;
   (2) progressively narrow the side columns as width shrinks so the center
   keeps usable space; (3) let the dense grids reflow via auto-fit/minmax.
   CSS-only — no behavior/logic touched. ─────────────────────────────────── */

/* every main view + its inner scroller must be a min-0 flex child that scrolls,
   so content past the fold is always reachable (no scroll trap, no clip). */
.col-center,.view-pane{min-width:0;min-height:0}
.home-scroll,.cfg-scroll,.learn-scroll,.metrics-pane,.config-pane,
.transcript,.bv-thread,.pf-scroll,.cv-body{min-height:0}

/* KAI Vitals + training scorecard: keep them honest auto-fit grids so they
   reflow 4→3→2→1 instead of crunching. (vit-grid/trn-grid already auto-fit;
   this just lowers the floor so cards stay readable on a squeezed center.) */
.vit-grid{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.trn-grid{grid-template-columns:repeat(auto-fit,minmax(132px,1fr))}

@media(max-width:1400px){
  /* center first: reclaim space from a slightly slimmer right panel */
  .col-right{width:300px}
  .vit-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
}
@media(max-width:1180px){
  /* tighter still — side columns shrink, center never crushes */
  .col-left{width:230px}
  .col-right{width:264px}
  .vit-grid{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
  .trn-grid{grid-template-columns:repeat(auto-fit,minmax(120px,1fr))}
  .met-grid{grid-template-columns:repeat(2,1fr)}
  .ov-stats{grid-template-columns:repeat(2,1fr)}
  .cfg-ai-grid{grid-template-columns:repeat(2,1fr)}
  .home-status{grid-template-columns:repeat(3,1fr)}
}
@media(max-width:1000px) and (min-width:901px){
  /* last desktop band before the off-canvas drawers kick in at 900px: the
     right panel goes lean so the center stays comfortably readable. */
  .col-left{width:212px}
  .col-right{width:240px}
  .vit-grid,.met-grid,.ov-stats,.cfg-ai-grid{grid-template-columns:1fr 1fr}
  .home-status{grid-template-columns:repeat(2,1fr)}
}

/* ═══════════════════════════════════════════════════════════════════════
   MOBILE / RESPONSIVE  — desktop layout above is untouched. Everything
   below only activates at <=900px (tablet) and <=560px (phone). Adds an
   app-bar + bottom tab bar, turns the left/right columns into off-canvas
   drawers, reflows grids to single column, full-screens modals/slide-overs.
   ════════════════════════════════════════════════════════════════════════ */

/* mobile-only chrome (app bar / bottom tabs / drawer backdrop) — hidden on desktop */
.m-appbar,.m-tabbar,.m-backdrop,.drawer-close,.m-drawer-nav{display:none}

/* ── VIEW MODE forced-layout overrides (2026-07-10) ──────────────────────────
   The View Mode picker also swaps the viewport meta width so ALL the @media
   rules below resolve to the chosen layout; these class-keyed rules pin the
   core chrome switch independently of viewport scaling. Auto adds no class, so
   default (responsive-by-viewport) behavior is completely unchanged. */
body.force-mobile .topbar,
body.force-mobile .rail{display:none !important}
body.force-mobile .m-appbar{display:flex !important}
body.force-mobile .m-tabbar{display:flex !important}
body.force-desktop .m-appbar,
body.force-desktop .m-tabbar,
body.force-desktop .m-backdrop{display:none !important}
body.force-desktop .topbar,
body.force-desktop .rail{display:flex !important}

@media(max-width:900px){
  /* ── APP BAR (top): hamburger=channels/nav drawer, star=agents drawer ── */
  .m-appbar{
    display:flex;align-items:center;gap:10px;flex-shrink:0;height:var(--m-ab-height, 56px);padding:0 12px;
    padding-left:max(12px,env(safe-area-inset-left));padding-right:max(12px,env(safe-area-inset-right));
    background:var(--panel-2);border-bottom:1px solid var(--border);z-index:6;position:relative;
  }
  .m-appbar .m-ab-btn{
    width:var(--m-ab-btn-size, 46px);height:var(--m-ab-btn-size, 46px);flex-shrink:0;border-radius:12px;border:1px solid rgba(255,255,255,0.08);
    background:rgba(255,255,255,0.04);color:var(--text);display:flex;align-items:center;justify-content:center;cursor:pointer;
    transition: all 0.2s ease;
  }
  .m-appbar .m-ab-btn:hover { background: rgba(255,255,255,0.08); border-color: rgba(34,217,230,0.3); color: var(--accent); }
  .m-appbar .m-ab-btn:active{background:rgba(34,217,230,0.12); transform: scale(0.96); }
  .m-appbar .m-ab-btn svg{width:20px;height:20px}
  /* v9.10.323 — profile avatar button in the header (30px avatar centered in the 46px tap target) */
  .m-appbar .m-ab-btn.m-ab-profile{padding:0;overflow:hidden}
  .m-appbar .m-ab-btn.m-ab-profile img{width:30px;height:30px;border-radius:50%;object-fit:cover;display:block;background:rgba(255,255,255,.06)}
  .m-appbar .m-ab-btn.m-ab-profile.on{border-color:var(--accent);box-shadow:0 0 0 2px rgba(56,189,210,.35)}
  .m-appbar .m-ab-title{flex:1;min-width:0;font-family:var(--ui);font-weight:700;font-size:13px;color:#fff;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .m-appbar .m-ab-title span{color:var(--muted);font-weight:400;font-size:11px}

  /* ── shared backdrop for any open drawer ── */
  .m-backdrop{
    display:block;position:fixed;inset:0;z-index:90;background:rgba(2,4,9,0.6);
    backdrop-filter:blur(2px);opacity:0;pointer-events:none;transition:opacity 0.22s;
  }
  .m-backdrop.open{opacity:1;pointer-events:auto}

  /* ── desktop chrome hidden on mobile; app-bar + bottom tabs replace it ── */
  .topbar{display:none !important}
  .rail{display:none}

  /* ── MOBILE DRAWER FIX: dissolve .shell's stacking context (desktop z-index:1)
     so the fixed off-canvas drawers (z-index:100) and the backdrop (z-index:90)
     resolve at the root level. Without this, .col-left/.col-right are trapped
     inside .shell(z=1) which paints BELOW the body-level backdrop(z=90) — leaving
     the opened drawer dimmed and intercepting every tap on the scrim. ── */
  .shell{z-index:auto}

  /* ── LEFT column → off-canvas drawer from the left ── */
  .col-left{
    position:fixed;top:0;left:0;bottom:0;width:var(--m-drawer-width, clamp(280px, 85vw, 360px));z-index:100;
    transform:translateX(-100%);transition:transform 0.26s ease;
    box-shadow:18px 0 44px rgba(0,0,0,0.55);
    padding-top:env(safe-area-inset-top);padding-bottom:env(safe-area-inset-bottom);
    display:flex !important;  /* JS toggles .open; ignore desktop setView display:none */
  }
  .col-left.m-open{transform:translateX(0)}

  /* ── RIGHT column → off-canvas drawer from the right ── */
  .col-right{
    position:fixed;top:0;right:0;bottom:0;width:var(--m-drawer-right-width, clamp(280px, 85vw, 380px));z-index:100;
    transform:translateX(100%);transition:transform 0.26s ease;
    box-shadow:-18px 0 44px rgba(0,0,0,0.55);
    padding-top:env(safe-area-inset-top);padding-bottom:env(safe-area-inset-bottom);
    display:flex !important;  /* match col-left: ignore desktop setView display:none so the drawer actually shows */
  }
  .col-right.m-open{transform:translateX(0)}
  /* right-column drawer scrolls as one region on mobile */

  /* close button shown inside each drawer header on mobile */
  .drawer-close{
    display:flex;align-items:center;justify-content:center;width:34px;height:34px;flex-shrink:0;
    border-radius:9px;border:1px solid var(--border);background:rgba(255,255,255,0.04);
    color:var(--muted);cursor:pointer;
  }
  .drawer-close svg{width:18px;height:18px}
  .col-left .col-section-hdr,.col-right .col-section-hdr{align-items:center}

  /* ── in-drawer view switcher — REMOVED 2026-07-10 (owner): the bottom tab bar
     already switches views, so the drawer is now PURELY the channel lattice
     (channels + Direct Messages). No duplicated nav. ── */
  .m-drawer-nav{display:none !important}

  /* ── center is the full-width primary ── */
  .col-center{flex:1;min-width:0}

  /* ── top metrics bar: never clip — horizontal scroll ── */
  .tb-right{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:60vw;gap:0}
  .tb-right::-webkit-scrollbar{height:0}
  .metric{flex-shrink:0}

  /* ── BOTTOM TAB BAR (primary view switching on phone) ── */
  /* Shell must not overflow past the tabbar */
  .shell{flex:1;min-height:0;overflow:hidden}
  .col-center{min-height:0;overflow:hidden}
  .view-pane{min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}
  /* Guest home content must fit between appbar and tabbar */
  .guest-dash{max-height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch}

  .m-tabbar{
    display:flex;flex-shrink:0;z-index:6;background:var(--panel-2);border-top:1px solid var(--border);
    padding-bottom:env(safe-area-inset-bottom);
  }
  .m-tabbar .m-tab{
    flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    padding:8px 4px;min-height:48px;color:var(--muted);cursor:pointer;background:transparent;border:none;
  }
  .m-tabbar .m-tab svg{width:20px;height:20px}
  .m-tabbar .m-tab .m-tab-l{font-family:var(--ui);font-size:8.5px;font-weight:700;letter-spacing:0.5px;text-transform:uppercase}
  .m-tabbar .m-tab.active{color:var(--accent)}

  /* ── card grids → single column, full width ── */
  .home-status{grid-template-columns:repeat(2,1fr)}
  .home-grid{grid-template-columns:1fr}
  .g-sys,.g-radar,.g-prov,.g-lat,.g-traffic,.g-board,.g-ops{grid-column:1 / -1;grid-row:auto}
  .lat-grid{grid-template-columns:1fr 1fr}
  .ops-grid,.metrics-overview,.bv-cfg-grid{grid-template-columns:1fr}
  .met-grid{grid-template-columns:1fr 1fr}
  .cfg-ai-grid{grid-template-columns:1fr}
  .ops-grid .meter[style*="grid-column"],.metrics-overview .widget.full{grid-column:auto}

  /* ── slide-overs (bot profile + DM, channel settings) → near full-screen ── */
  .bot-view{top:0;width:100vw;z-index:120;padding-top:env(safe-area-inset-top)}
  .chan-view{top:0;width:100vw;z-index:120;padding-top:env(safe-area-inset-top)}
  .chan-view .cv-acts{padding-bottom:max(12px,env(safe-area-inset-bottom))}
  .settings-panel{top:0;width:100vw;z-index:120;padding-top:env(safe-area-inset-top)}
  .bv-compose{padding-bottom:max(12px,env(safe-area-inset-bottom))}

  /* topology already uses a viewBox; just guarantee it fits the viewport */
  .topo-wrap{padding:8px;overflow:auto;-webkit-overflow-scrolling:touch}
  .topo-wrap svg{max-width:100%;height:auto}

  /* smooth momentum scrolling on all live lists */
  .transcript,.bv-thread,.scroll,.agent-list,.metrics-pane,.config-pane,
  .home-scroll,.cfg-scroll,.activity-stream,.portfolio,.conn-list,.leaderboard,.ptab-body{-webkit-overflow-scrolling:touch}

  /* touch targets */
  .chan-item,.nav-item,.rchip,.ch-tab,.mini-btn,.pf-btn{min-height:40px}
  .rchip{padding:8px 12px}

  /* ── browser tabs + portfolio on mobile: tabs scroll horizontally, page
       sections gain breathing room, vitals/config reflow to fewer columns ── */
  .tab-strip{padding:5px 8px 0;-webkit-overflow-scrolling:touch}
  .os-tab{min-width:96px;max-width:150px}
  .pf-hero{flex-direction:column;align-items:flex-start;gap:12px;padding:18px 16px 16px}
  .pf-av{width:56px;height:56px;font-size:24px}
  .pf-name{font-size:21px}
  .pf-vitals{grid-template-columns:repeat(2,1fr);padding:14px 16px}
  .pf-cfg-grid{grid-template-columns:1fr 1fr;padding:0 16px 8px}
  .pf-secthdr,.pf-tabs,.pf-pane,.pf-edit-row{padding-left:16px;padding-right:16px}
  .pf-tabs{overflow-x:auto;flex-wrap:nowrap;-webkit-overflow-scrolling:touch}
}

@media(max-width:560px){
  /* phone: command bar stacks, input full width, buttons wrap & stay usable */
  .topbar{padding:0 10px;padding-left:max(10px,env(safe-area-inset-left));padding-right:max(10px,env(safe-area-inset-right))}
  .brand .sub{display:none}
  .tb-right{max-width:50vw}
  .metric{min-width:58px;padding:5px 8px}

  .cmdbar{padding:9px 12px 10px;padding-bottom:max(10px,env(safe-area-inset-bottom))}
  .cmd-row{flex-direction:column;gap:9px}
  .cmd-btns{flex-direction:row;flex-wrap:wrap;width:100%}
  .cmd-btns .btn.execute{flex:1 1 100%;min-height:46px}
  .btn-secondary-row{flex:1 1 100%}
  #cmd-input{height:48px}

  .home-status{grid-template-columns:1fr 1fr}
  .met-grid{grid-template-columns:1fr 1fr}

  /* modals (restart + Edit AI Config) → near full-screen, scrollable, sticky footer */
  .modal-overlay{padding:0;align-items:stretch;justify-content:stretch}
  .modal-overlay .modal{
    width:100vw;max-width:100vw;min-height:100vh;border-radius:0;display:flex;flex-direction:column;
    padding-top:env(safe-area-inset-top);padding-bottom:env(safe-area-inset-bottom);
  }
  .modal-overlay .modal > div{display:flex;flex-direction:column;flex:1;min-height:0}
  .modal-body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch}
  .modal-acts{position:sticky;bottom:0;background:var(--panel-solid);border-top:1px solid var(--border)}
  .modal-btn{flex:1;min-height:46px;justify-content:center;display:flex;align-items:center}

  .bv-cfg-grid{grid-template-columns:1fr 1fr}

  /* Hide bulky 3D UI overlays on mobile so they don't block the screen */
  .kv-hud, .ns-legend, .ns-errbox, .kv-throttle, .ns-events-toggle { display: none !important; }

  /* Fullscreen mobile immersion: Hide ALL UI chrome when fullscreen is toggled */
  :fullscreen .topbar, :fullscreen .m-appbar, :fullscreen .rail, :fullscreen .tab-strip, :fullscreen .col-left, :fullscreen .col-right, :fullscreen .m-tabbar { display: none !important; }
  :fullscreen .shell { padding: 0 !important; margin: 0 !important; }
  :fullscreen .col-center { padding: 0 !important; margin: 0 !important; height: 100vh !important; max-height: 100vh !important; }
  
  :-webkit-full-screen .topbar, :-webkit-full-screen .m-appbar, :-webkit-full-screen .rail, :-webkit-full-screen .tab-strip, :-webkit-full-screen .col-left, :-webkit-full-screen .col-right, :-webkit-full-screen .m-tabbar { display: none !important; }
  :-webkit-full-screen .shell { padding: 0 !important; margin: 0 !important; }
  :-webkit-full-screen .col-center { padding: 0 !important; margin: 0 !important; height: 100vh !important; max-height: 100vh !important; }
}

/* v9.10.509 — Player card level effects */
.pcard-glow-6{box-shadow:0 0 12px var(--accent-glow,rgba(34,217,230,.3))}
.pcard-glow-11{background-size:200% 200%;animation:pcardGrad 3s ease infinite}
.pcard-glow-16{animation:pcardShimmer 2s ease infinite}
@keyframes pcardGrad{0%,100%{background-position:0 50%}50%{background-position:100% 50%}}
@keyframes pcardShimmer{0%,100%{box-shadow:0 0 12px var(--accent-glow),0 0 24px rgba(168,85,247,.2)}50%{box-shadow:0 0 20px var(--accent-glow),0 0 40px rgba(168,85,247,.35)}}
/* v9.10.539 — player-card holographic finish (EPIC static sheen / MYTHIC+ animated sweep) */
.pcard-holo-anim{background-size:250% 100% !important;animation:pcardHoloSweep 3.6s linear infinite}
@keyframes pcardHoloSweep{0%{background-position:190% 0}100%{background-position:-90% 0}}
/* XP progress bar */
.xp-bar-wrap{width:100%;height:6px;background:rgba(255,255,255,.08);border-radius:3px;overflow:hidden;margin-top:4px}
.xp-bar-fill{height:100%;border-radius:3px;background:linear-gradient(90deg,var(--accent,#22d9e6),rgba(168,85,247,.8));transition:width .3s}
/* Voice invite toast */
.voice-invite-toast{position:fixed;top:20px;right:20px;z-index:99999;background:rgba(13,19,32,.95);border:1px solid var(--accent,#22d9e6);
  border-radius:16px;padding:16px 20px;box-shadow:0 12px 40px rgba(0,0,0,.6);backdrop-filter:blur(12px);
  display:flex;align-items:center;gap:14px;animation:viToastIn .3s ease}
.voice-invite-toast .vi-av{width:48px;height:48px;border-radius:50%;background:linear-gradient(135deg,#6366f1,#8b5cf6);
  display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0}
.voice-invite-toast .vi-info{flex:1;min-width:0}
.voice-invite-toast .vi-name{font:700 14px Outfit,sans-serif;color:#eef3fb}
.voice-invite-toast .vi-msg{font:12px Outfit,sans-serif;color:var(--muted);margin-top:2px}
.voice-invite-toast .vi-btns{display:flex;gap:8px;margin-top:8px}
.voice-invite-toast .vi-btn{border:none;padding:8px 18px;border-radius:10px;font:600 12px Outfit,sans-serif;cursor:pointer}
.voice-invite-toast .vi-answer{background:linear-gradient(135deg,#22c55e,#16a34a);color:#fff}
.voice-invite-toast .vi-decline{background:rgba(239,68,68,.15);color:#f87171}
@keyframes viToastIn{from{transform:translateX(100px);opacity:0}to{transform:none;opacity:1}}

/* ── Unit 1: Multi-Image Grid + Lightbox ───────────────────────────────────── */
.gpost-images-grid{display:grid;gap:3px;margin-top:8px;border-radius:10px;overflow:hidden;background:#0b0f14}
.gpost-images-grid.g1{grid-template-columns:1fr}
.gpost-images-grid.g2{grid-template-columns:1fr 1fr}
.gpost-images-grid.g3{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}
.gpost-images-grid.g3 .gpost-grid-img:first-child,.gpost-images-grid.g3 .gcomp-thumb:first-child{grid-column:1/-1}
.gpost-images-grid.g4{grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr}
.gpost-grid-img{width:100%;height:100%;object-fit:cover;cursor:pointer;min-height:120px;max-height:340px;display:block;transition:opacity .15s}
.gpost-grid-img:hover{opacity:.88}
.gpost-images-grid.g1 .gpost-grid-img{max-height:620px;object-fit:contain}
.img-lightbox{position:fixed;inset:0;z-index:9500;background:rgba(0,0,0,.92);display:flex;align-items:center;justify-content:center;
  backdrop-filter:blur(8px);opacity:0;transition:opacity .2s ease}
.img-lightbox.open{opacity:1}
.img-lightbox img{max-width:92vw;max-height:90vh;object-fit:contain;border-radius:6px;user-select:none}
.img-lightbox-close{position:absolute;top:16px;right:18px;background:rgba(255,255,255,.1);border:none;color:#fff;width:36px;height:36px;
  border-radius:50%;font-size:20px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s}
.img-lightbox-close:hover{background:rgba(255,255,255,.2)}
.img-lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);background:rgba(255,255,255,.08);border:none;color:#fff;
  width:44px;height:44px;border-radius:50%;font-size:22px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s}
.img-lightbox-nav:hover{background:rgba(255,255,255,.18)}
.img-lightbox-nav.prev{left:14px}
.img-lightbox-nav.next{right:14px}
.img-lightbox-counter{position:absolute;bottom:18px;left:50%;transform:translateX(-50%);font:500 13px Outfit,sans-serif;color:rgba(255,255,255,.6);
  background:rgba(0,0,0,.5);padding:4px 14px;border-radius:20px}

/* ── Unit 2: Share Sheet Popup ─────────────────────────────────────────────── */
.gpost-share-sheet{position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);background:#151d2e;border:1px solid rgba(255,255,255,.12);
  border-radius:12px;padding:6px 0;min-width:180px;box-shadow:0 8px 28px rgba(0,0,0,.5);z-index:200;animation:shareSheetIn .15s ease}
@keyframes shareSheetIn{from{opacity:0;transform:translateX(-50%) translateY(4px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
.gpost-share-sheet button{display:flex;align-items:center;gap:10px;width:100%;padding:10px 16px;border:none;background:transparent;
  color:var(--text);font:500 13px Outfit,sans-serif;cursor:pointer;transition:background .12s}
.gpost-share-sheet button:hover{background:rgba(255,255,255,.06)}
.gpost-share-sheet button svg{flex-shrink:0;opacity:.7}

/* ── Unit 3: Feed Tabs ─────────────────────────────────────────────────────── */
.gfeed-tabs{display:flex;gap:0;margin-bottom:12px;border-bottom:2px solid rgba(255,255,255,.06);padding:0}
.gfeed-tabs button{border:none;background:transparent;color:var(--muted);font:600 13px Outfit,sans-serif;padding:10px 18px;cursor:pointer;
  position:relative;transition:color .15s}
.gfeed-tabs button::after{content:'';position:absolute;bottom:-2px;left:0;right:0;height:2px;background:transparent;border-radius:2px;transition:background .15s}
.gfeed-tabs button.active{color:var(--accent)}
.gfeed-tabs button.active::after{background:var(--accent)}
.gfeed-tabs button:hover:not(.active){color:var(--text)}

/* ── Unit 4: Mobile Trending Strip ─────────────────────────────────────────── */
.gfeed-trending-strip{display:none;gap:8px;overflow-x:auto;padding:4px 0 12px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.gfeed-trending-strip::-webkit-scrollbar{display:none}
@media(max-width:899px){.gfeed-trending-strip{display:flex}}
.gfeed-trending-pill{flex:0 0 auto;padding:6px 14px;border-radius:20px;background:rgba(99,102,241,.1);border:1px solid rgba(99,102,241,.25);
  color:#a5b4fc;font:600 12px Outfit,sans-serif;cursor:pointer;white-space:nowrap;transition:background .15s,border-color .15s}
.gfeed-trending-pill:hover{background:rgba(99,102,241,.2);border-color:rgba(99,102,241,.4)}

/* ── Unit 5: Notification Bell Ring ────────────────────────────────────────── */
/* ── Double-tap heart animation ────────────────────────────────────────────── */
.gpost-dblheart{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);font-size:64px;
  pointer-events:none;z-index:50;opacity:0;transition:none}
.gpost-dblheart.pop{animation:dblHeartPop .7s ease forwards}
@keyframes dblHeartPop{0%{opacity:1;transform:translate(-50%,-50%) scale(0)}
  15%{opacity:1;transform:translate(-50%,-50%) scale(1.2)}
  30%{transform:translate(-50%,-50%) scale(1)}
  70%{opacity:1;transform:translate(-50%,-50%) scale(1)}
  100%{opacity:0;transform:translate(-50%,-50%) scale(1.4)}}

/* ── Enhanced post menu ───────────────────────────────────────────────────── */
.gpost-menu button{white-space:nowrap}

@keyframes notifBellRing{
  0%{transform:rotate(0)}10%{transform:rotate(14deg)}20%{transform:rotate(-14deg)}
  30%{transform:rotate(10deg)}40%{transform:rotate(-10deg)}50%{transform:rotate(6deg)}
  60%{transform:rotate(-4deg)}70%{transform:rotate(2deg)}80%{transform:rotate(0)}100%{transform:rotate(0)}}
.notif-bell-ring{animation:notifBellRing .6s ease-in-out}

/* v9.10.525 - the reader no longer says "Loading". A page already in the cache
   paints with the spread; a page that really is cold gets this wordless
   skeleton, which reads as paper rather than as a notice. */
.cbk-skel{padding:14px 24px 0;display:flex;flex-direction:column;gap:11px}
.cbk-skel i{display:block;height:11px;border-radius:3px;
  background:linear-gradient(90deg,rgba(255,255,255,.045) 0%,rgba(255,255,255,.11) 50%,rgba(255,255,255,.045) 100%);
  background-size:220% 100%;animation:cbkSkel 1.5s ease-in-out infinite}
.cbk-skel i:nth-child(3n){width:88%}
.cbk-skel i:nth-child(4n){width:72%}
.cbk-skel i:nth-child(5n){width:94%}
@keyframes cbkSkel{0%{background-position:120% 0}100%{background-position:-20% 0}}
@media (prefers-reduced-motion: reduce){ .cbk-skel i{animation:none} }
.cbk-skel-toc{padding:22px 24px;gap:14px}
.cbk-skel-toc i{height:14px;border-radius:4px}

/* ── v9.10.530 — Feed skeleton shimmer cards ─────────────────────────────── */
.gfeed-skel{padding:0}
.gfeed-skel-card{background:rgba(13,19,32,.78);border:1px solid rgba(255,255,255,.06);border-radius:16px;padding:18px 20px;margin-bottom:14px}
.gfeed-skel-row{display:flex;gap:12px;align-items:center;margin-bottom:14px}
.gfeed-skel-circle{width:44px;height:44px;border-radius:50%;flex-shrink:0}
.gfeed-skel-bar{height:12px;border-radius:6px}
.gfeed-skel-bar.w40{width:40%}.gfeed-skel-bar.w25{width:25%}.gfeed-skel-bar.w90{width:90%}.gfeed-skel-bar.w70{width:70%}.gfeed-skel-bar.w55{width:55%}
.gfeed-skel-rect{width:100%;height:180px;border-radius:10px;margin-top:8px}
.gfeed-skel-circle,.gfeed-skel-bar,.gfeed-skel-rect{
  background:linear-gradient(90deg,rgba(255,255,255,.04) 0%,rgba(255,255,255,.09) 50%,rgba(255,255,255,.04) 100%);
  background-size:220% 100%;animation:bootShimmer 1.6s ease-in-out infinite}
@media(prefers-reduced-motion:reduce){.gfeed-skel-circle,.gfeed-skel-bar,.gfeed-skel-rect{animation:none}}

/* ── v9.10.530 — Poll rendering ─────────────────────────────────────────── */
.gpost-poll{margin:10px 0 4px}
.gpost-poll-opt{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1px solid rgba(255,255,255,.10);border-radius:10px;margin-bottom:6px;cursor:pointer;transition:background .12s,border-color .15s;position:relative;overflow:hidden}
.gpost-poll-opt:hover{background:rgba(99,102,241,.08);border-color:rgba(99,102,241,.3)}
.gpost-poll-opt .poll-dot{width:18px;height:18px;border-radius:50%;border:2px solid rgba(255,255,255,.3);flex-shrink:0;transition:border-color .15s,background .15s}
.gpost-poll-opt:hover .poll-dot{border-color:var(--accent)}
.gpost-poll-opt .poll-label{flex:1;font:500 14px var(--ui),Inter,sans-serif;color:var(--text)}
.gpost-poll-result{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1px solid rgba(255,255,255,.07);border-radius:10px;margin-bottom:6px;position:relative;overflow:hidden}
.gpost-poll-result.mine{border-color:rgba(99,102,241,.35)}
.gpost-poll-result.winner .poll-label{font-weight:700}
.gpost-poll-fill{position:absolute;left:0;top:0;bottom:0;background:rgba(99,102,241,.12);border-radius:10px;transition:width .5s cubic-bezier(.4,0,.2,1)}
.gpost-poll-result .poll-label{flex:1;font:500 14px var(--ui),Inter,sans-serif;color:var(--text);position:relative;z-index:1}
.gpost-poll-result .poll-pct{font:700 13px JetBrains Mono,monospace;color:var(--accent);position:relative;z-index:1;min-width:38px;text-align:right}
.gpost-poll-result .poll-check{color:var(--accent);font-size:14px;position:relative;z-index:1}
.gpost-poll-footer{font:12px var(--ui),Inter,sans-serif;color:var(--muted);margin-top:4px;padding:0 2px}

/* ── v9.10.530 — Quote post embed ────────────────────────────────────────── */
.gpost-quote{border:1px solid rgba(255,255,255,.08);border-left:3px solid var(--accent,#6366f1);border-radius:10px;padding:12px 14px;margin:8px 0;background:rgba(99,102,241,.04);cursor:pointer;transition:background .12s}
.gpost-quote:hover{background:rgba(99,102,241,.08)}
.gpost-quote-head{display:flex;gap:8px;align-items:center;margin-bottom:6px}
.gpost-quote-name{font:700 13px var(--ui),Inter,sans-serif;color:var(--text)}
.gpost-quote-handle{font:12px var(--ui),Inter,sans-serif;color:var(--muted)}
.gpost-quote-text{font:14px/1.5 var(--ui),Inter,sans-serif;color:#c5d0e0;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.gpost-quote-thumb{width:48px;height:48px;border-radius:6px;object-fit:cover;flex-shrink:0;margin-left:auto}

/* ── v9.10.530 — End-of-feed indicator ───────────────────────────────────── */
.gfeed-end{display:flex;align-items:center;gap:14px;padding:28px 0 12px;color:var(--muted);font:500 13px var(--ui),Inter,sans-serif}
.gfeed-end::before,.gfeed-end::after{content:'';flex:1;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.1),transparent)}

/* ── v9.10.530 — Empty state per tab ─────────────────────────────────────── */
.gfeed-empty{text-align:center;padding:48px 20px 32px;color:var(--muted)}
.gfeed-empty-icon{font-size:36px;margin-bottom:10px}
.gfeed-empty-msg{font:500 15px var(--ui),Inter,sans-serif;margin-bottom:6px;color:var(--text)}
.gfeed-empty-sub{font:13px var(--ui),Inter,sans-serif;margin-bottom:16px}
.gfeed-empty-btn{display:inline-block;padding:8px 20px;border-radius:10px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font:600 13px var(--ui),Inter,sans-serif;cursor:pointer;border:none;transition:opacity .12s}
.gfeed-empty-btn:hover{opacity:.85}

/* ── v9.10.530 — New posts banner ────────────────────────────────────────── */
.gfeed-newbar{position:sticky;top:0;z-index:12;text-align:center;padding:10px;cursor:pointer;background:linear-gradient(135deg,rgba(99,102,241,.92),rgba(139,92,246,.92));color:#fff;font:600 13px var(--ui),Inter,sans-serif;border-radius:0 0 12px 12px;backdrop-filter:blur(8px);box-shadow:0 4px 16px rgba(99,102,241,.25);transition:opacity .2s}
.gfeed-newbar:hover{opacity:.9}

/* ── v9.10.530 — Scroll-to-top FAB ───────────────────────────────────────── */
.gfeed-fab-top{position:fixed;bottom:28px;right:28px;z-index:50;width:44px;height:44px;border-radius:50%;background:rgba(99,102,241,.85);color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 16px rgba(0,0,0,.35);opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;transform:translateY(10px)}
.gfeed-fab-top.visible{opacity:1;pointer-events:auto;transform:translateY(0)}
.gfeed-fab-top:hover{background:rgba(99,102,241,1)}
.gfeed-fab-top svg{width:20px;height:20px}
@media(max-width:768px){.gfeed-fab-top{bottom:80px;right:16px}}
/* v9.10.553 — profile story highlights (IG circles) */
.gprof-highlights{display:flex;gap:14px;overflow-x:auto;padding:10px 16px 4px;scrollbar-width:none}
.gprof-highlights::-webkit-scrollbar{display:none}
.gprof-hl{position:relative;flex:0 0 auto;width:72px;text-align:center;cursor:pointer}
.gprof-hl-ring{display:block;width:64px;height:64px;margin:0 auto;border-radius:50%;padding:3px;
  background:conic-gradient(from 45deg,#f9ce34,#ee2a7b,#6228d7,#f9ce34);transition:transform .15s}
.gprof-hl:hover .gprof-hl-ring{transform:scale(1.07)}
.gprof-hl-cover{display:flex;align-items:center;justify-content:center;width:100%;height:100%;border-radius:50%;
  border:2.5px solid var(--panel-solid,#0a0f1b);overflow:hidden}
.gprof-hl-snippet{font:700 8px var(--ui),sans-serif;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.6);padding:0 4px;text-align:center}
.gprof-hl-title{display:block;margin-top:5px;font:600 10.5px var(--ui),sans-serif;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gprof-hl-x{position:absolute;top:-4px;right:0;width:20px;height:20px;border-radius:50%;border:none;
  background:rgba(0,0,0,.7);color:#f87171;font-size:13px;line-height:1;cursor:pointer;display:none}
.gprof-hl:hover .gprof-hl-x{display:block}
.stv-hl{width:32px;height:32px;border-radius:50%;border:none;background:rgba(0,0,0,.45);color:#fbbf24;font-size:14px;cursor:pointer}
.stv-hl:hover{background:rgba(251,191,36,.3)}
/* v9.10.553 — onboarding checklist card */
.gfeed-ob-card{margin-bottom:14px;padding:14px 16px;border-radius:14px;
  background:linear-gradient(135deg,rgba(99,102,241,.10),rgba(34,217,230,.06));border:1px solid rgba(99,102,241,.28)}
.gfeed-ob-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.gfeed-ob-title{font:800 14px var(--ui),sans-serif;color:var(--text)}
.gfeed-ob-count{font:700 11px var(--ui),sans-serif;color:#a5b4fc;margin-left:6px}
.gfeed-ob-x{width:26px;height:26px;border-radius:50%;border:none;background:rgba(255,255,255,.07);color:var(--muted);
  font-size:15px;cursor:pointer}
.gfeed-ob-x:hover{background:rgba(255,255,255,.14);color:var(--text)}
.gfeed-ob-bar{height:6px;border-radius:3px;background:rgba(255,255,255,.08);overflow:hidden;margin-bottom:10px}
.gfeed-ob-fill{height:100%;border-radius:3px;background:linear-gradient(90deg,#6366f1,#22d9e6);transition:width .4s ease}
.gfeed-ob-steps{display:flex;flex-wrap:wrap;gap:6px}
.gfeed-ob-step{display:inline-flex;align-items:center;gap:7px;padding:7px 13px;border-radius:999px;
  border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);color:#c5d0e0;
  font:600 12px var(--ui),sans-serif;cursor:pointer;transition:all .14s}
.gfeed-ob-step:hover{border-color:rgba(99,102,241,.5);background:rgba(99,102,241,.1)}
.gfeed-ob-step.done{border-color:rgba(74,222,128,.35);background:rgba(74,222,128,.08);color:#4ade80;cursor:default}
.gfeed-ob-check{font-size:13px}
/* v9.10.552 — schedule picker + scheduled manager + GIF panel */
.gcomp-chip.chip-sched.active{background:rgba(56,189,248,.14);color:#38bdf8}
.gcomp-chip.chip-sched.active svg{color:#38bdf8}
.gcomp-chip-gif-badge{font:800 10px var(--ui),sans-serif;border:1.5px solid currentColor;border-radius:5px;padding:1px 5px;color:#4ade80}
.gcomp-sched-panel{display:flex;align-items:center;gap:8px;margin-top:10px;padding:10px 12px;border-radius:10px;
  background:rgba(56,189,248,.07);border:1px solid rgba(56,189,248,.25);flex-wrap:wrap}
.gcomp-sched-panel>span:first-child{font:600 11.5px var(--ui),sans-serif;color:#7dd3fc}
.gcomp-sched-panel input[type=datetime-local]{padding:7px 10px;border-radius:8px;border:1px solid rgba(255,255,255,.15);
  background:rgba(0,0,0,.35);color:var(--text);font:12.5px var(--ui),sans-serif;outline:none;color-scheme:dark}
.gcomp-sched-link{font:600 11.5px var(--ui),sans-serif;color:#7dd3fc;cursor:pointer;margin-left:auto}
.gcomp-sched-link:hover{text-decoration:underline}
#gsched-ov{position:fixed;inset:0;z-index:99970;background:rgba(2,4,10,.75);backdrop-filter:blur(3px);
  display:flex;align-items:center;justify-content:center;padding:16px}
.gsched-panel{width:min(460px,94vw);max-height:80vh;overflow-y:auto;background:#0c1220;border:1px solid rgba(255,255,255,.1);
  border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,.6);padding:14px 16px}
.gsched-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;color:var(--text);font:15px var(--ui),sans-serif}
.gsched-row{display:flex;align-items:center;gap:10px;padding:10px 0;border-top:1px solid rgba(255,255,255,.06)}
.gsched-row-main{flex:1;min-width:0}
.gsched-when{font:700 11.5px var(--ui),sans-serif;color:#7dd3fc;margin-bottom:2px}
.gsched-text{font:12.5px var(--ui),sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gsched-cancel{padding:6px 13px;border-radius:8px;border:1px solid rgba(248,113,113,.4);background:transparent;
  color:#f87171;font:700 11.5px var(--ui),sans-serif;cursor:pointer}
.gsched-cancel:hover{background:rgba(248,113,113,.12)}
.gcomp-gif-panel{margin-top:10px;padding:10px 12px;border-radius:10px;background:rgba(74,222,128,.05);border:1px solid rgba(74,222,128,.22)}
.gcomp-gif-panel input{width:100%;padding:8px 12px;border-radius:8px;border:1px solid rgba(255,255,255,.14);
  background:rgba(0,0,0,.35);color:var(--text);font:12.5px var(--ui),sans-serif;outline:none;margin-bottom:8px}
.gcomp-gif-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;max-height:220px;overflow-y:auto}
.gcomp-gif-grid img{width:100%;height:80px;object-fit:cover;border-radius:8px;cursor:pointer;transition:transform .12s}
.gcomp-gif-grid img:hover{transform:scale(1.05)}
.gcomp-gif-loading{grid-column:1/-1;font:12px var(--ui),sans-serif;color:var(--muted);text-align:center;padding:14px 0}
@media(max-width:640px){.gcomp-gif-grid{grid-template-columns:repeat(3,1fr)}}
/* v9.10.551 — audience selector + feeling picker + link cards + views */
.gcomp-aud{padding:7px 13px;border-radius:999px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.04);
  color:#aab8cc;font:700 11.5px var(--ui),sans-serif;cursor:pointer;flex-shrink:0;transition:all .15s;min-width:86px}
.gcomp-aud:hover{border-color:rgba(255,255,255,.3);color:var(--text)}
.gcomp-aud.friends{border-color:rgba(74,222,128,.45);color:#4ade80;background:rgba(74,222,128,.08)}
.gcomp-chip.active{background:rgba(247,185,40,.14);color:#f7b928}
.gcomp-feel-sec{width:100%;font:700 10px var(--ui),sans-serif;letter-spacing:.6px;text-transform:uppercase;color:var(--muted-2);margin:6px 0 2px}
.gcomp-feel-row{display:flex;flex-wrap:wrap;gap:5px;width:100%}
.gcomp-emoji-btn{background:rgba(255,255,255,.06);border:1px solid var(--border);border-radius:8px;padding:4px 7px;font-size:16px;cursor:pointer}
.gcomp-feel-opt{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.1);border-radius:999px;padding:5px 11px;
  color:#c5d0e0;font:600 11.5px var(--ui),sans-serif;cursor:pointer;transition:all .13s}
.gcomp-feel-opt:hover{background:rgba(247,185,40,.12);border-color:rgba(247,185,40,.4);color:#f7b928}
.gcomp-feel-opt.on{background:rgba(247,185,40,.16);border-color:rgba(247,185,40,.55);color:#f7b928}
.gcomp-feel-clear{margin-top:6px;background:none;border:none;color:#fda4af;font:600 11px var(--ui),sans-serif;cursor:pointer;padding:2px 0}
#guest-post-emojibar{flex-direction:column;align-items:flex-start}
.gpost-feeling{font-weight:500;font-size:13px;color:var(--muted)}
.gpost-views{margin-left:auto}
.gpost-linkcard{display:flex;flex-direction:column;margin-top:8px;border:1px solid rgba(255,255,255,.12);border-radius:12px;
  overflow:hidden;text-decoration:none;background:rgba(255,255,255,.03);transition:border-color .15s,background .15s}
.gpost-linkcard:hover{border-color:rgba(99,102,241,.45);background:rgba(99,102,241,.06)}
.gpost-linkcard-img{width:100%;max-height:240px;object-fit:cover;display:block}
.gpost-linkcard-body{display:flex;flex-direction:column;gap:2px;padding:10px 12px;min-width:0}
.gpost-linkcard-domain{font:600 10.5px var(--ui),sans-serif;color:var(--muted-2);text-transform:uppercase;letter-spacing:.4px}
.gpost-linkcard-title{font:700 13.5px var(--ui),sans-serif;color:var(--text);overflow:hidden;text-overflow:ellipsis;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.gpost-linkcard-desc{font:12px/1.45 var(--ui),sans-serif;color:var(--muted);overflow:hidden;text-overflow:ellipsis;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
/* v9.10.551 — long-post clamp ("See more") */
.gpost-text.gpost-clamped{display:-webkit-box;-webkit-line-clamp:6;-webkit-box-orient:vertical;overflow:hidden}
.gpost-seemore{border:none;background:none;color:#7cabff;font:700 12.5px var(--ui),sans-serif;cursor:pointer;padding:2px 0 0;text-align:left}
.gpost-seemore:hover{text-decoration:underline}
/* v9.10.551 — pull-to-refresh (mobile) */
#gfeed-ptr{position:sticky;top:0;z-index:11;height:0;overflow:visible;text-align:center;pointer-events:none}
#gfeed-ptr .gfeed-ptr-pill{display:inline-flex;align-items:center;gap:8px;margin-top:8px;padding:8px 16px;border-radius:999px;
  background:rgba(16,24,40,.95);border:1px solid rgba(99,102,241,.4);color:#a5b4fc;font:700 12px var(--ui),sans-serif;
  box-shadow:0 6px 20px rgba(0,0,0,.4);opacity:0;transform:translateY(-14px) scale(.9);transition:opacity .15s,transform .15s}
#gfeed-ptr.pulling .gfeed-ptr-pill,#gfeed-ptr.refreshing .gfeed-ptr-pill{opacity:1;transform:translateY(0) scale(1)}
#gfeed-ptr .gfeed-ptr-spin{width:14px;height:14px;border-radius:50%;border:2px solid rgba(165,180,252,.3);border-top-color:#a5b4fc;animation:gptrspin .7s linear infinite}
@keyframes gptrspin{to{transform:rotate(360deg)}}
/* v9.10.551 — composer multi-image grid preview */
.gcomp-preview-grid .gpost-images-grid{margin-top:2px}
.gcomp-thumb{position:relative;display:block;overflow:hidden;border-radius:10px}
.gcomp-thumb img{width:100%;height:100%;object-fit:cover;display:block;max-height:160px}
.gcomp-thumb-x{position:absolute;top:5px;right:5px;width:24px;height:24px;border-radius:50%;border:none;
  background:rgba(0,0,0,.72);color:#fff;font-size:14px;line-height:1;cursor:pointer}
.gcomp-thumb-x:hover{background:rgba(220,38,38,.85)}
.gcomp-add-more{display:inline-block;margin-top:8px;padding:6px 14px;border-radius:999px;border:1px dashed rgba(255,255,255,.25);
  background:transparent;color:var(--muted);font:600 11.5px var(--ui),sans-serif;cursor:pointer;transition:color .15s,border-color .15s}
.gcomp-add-more:hover{color:var(--text);border-color:rgba(255,255,255,.45)}
/* v9.10.551 — @mention/#hashtag autocomplete dropdown */
#g-ac-dd{display:none;background:#0e1524;border:1px solid rgba(255,255,255,.14);border-radius:12px;
  box-shadow:0 14px 40px rgba(0,0,0,.6);overflow:hidden;max-height:264px;overflow-y:auto}
.g-ac-item{display:flex;align-items:center;gap:9px;padding:9px 12px;cursor:pointer}
.g-ac-item.sel,.g-ac-item:hover{background:rgba(99,102,241,.16)}
.g-ac-item img{width:28px;height:28px;border-radius:50%;object-fit:cover;flex-shrink:0}
.g-ac-hash{width:28px;height:28px;border-radius:50%;background:rgba(34,217,230,.12);color:#22d9e6;
  font:800 15px var(--ui),sans-serif;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.g-ac-name{font:600 13px var(--ui),sans-serif;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.g-ac-sub{font:11px var(--ui),sans-serif;color:var(--muted);margin-left:auto;flex-shrink:0}
/* v9.10.551 — FB-style reaction picker (hover/long-press on Like) */
.gpx-wrap{position:relative;display:inline-flex}
.gpx-picker{position:absolute;bottom:calc(100% + 6px);left:0;z-index:30;display:flex;gap:2px;padding:6px 8px;
  background:#101828;border:1px solid rgba(255,255,255,.14);border-radius:999px;box-shadow:0 10px 30px rgba(0,0,0,.55);
  opacity:0;pointer-events:none;transform:translateY(8px) scale(.88);transform-origin:bottom left;
  transition:opacity .16s ease,transform .18s cubic-bezier(.34,1.56,.64,1)}
.gpx-picker.open{opacity:1;pointer-events:auto;transform:translateY(0) scale(1)}
.gpx-picker button{position:relative;border:none;background:none;font-size:24px;line-height:1;padding:3px 5px;cursor:pointer;
  transition:transform .14s cubic-bezier(.34,1.56,.64,1);border-radius:50%}
.gpx-picker button:hover{transform:translateY(-8px) scale(1.35)}
.gpx-picker button::after{content:attr(data-lbl);position:absolute;bottom:calc(100% + 4px);left:50%;transform:translateX(-50%);
  font:700 9px var(--ui),sans-serif;color:#fff;background:rgba(0,0,0,.75);padding:2px 7px;border-radius:8px;
  opacity:0;pointer-events:none;transition:opacity .12s;white-space:nowrap}
.gpx-picker button:hover::after{opacity:1}
/* v9.10.552 — anonymous-visitor join card (Twitter-style mid-feed CTA) */
.gfeed-join-card{margin:10px 0;padding:22px 24px;border-radius:16px;text-align:center;
  background:linear-gradient(135deg,rgba(99,102,241,.14),rgba(139,92,246,.10),rgba(34,217,230,.08));
  border:1px solid rgba(99,102,241,.3)}
.gfeed-join-title{font:800 19px var(--ui),sans-serif;color:var(--text);margin-bottom:6px}
.gfeed-join-sub{font:13px/1.55 var(--ui),sans-serif;color:var(--muted);max-width:420px;margin:0 auto 14px}
.gfeed-join-btns{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.gfeed-join-btn{padding:10px 26px;border-radius:999px;background:linear-gradient(135deg,#6366f1,#8b5cf6);
  color:#fff;font:700 13px var(--ui),sans-serif;text-decoration:none;transition:filter .15s}
.gfeed-join-btn:hover{filter:brightness(1.12)}
.gfeed-join-btn.ghost{background:transparent;border:1px solid rgba(255,255,255,.25);color:var(--text)}


/* ── v9.10.595 REDUCE MOTION ──────────────────────────────────────────────────
   oracle-core.js:18787 toggles body.reduce-motion, and oracle-core.js:18540 checks
   it to skip the parallax — but no stylesheet ever defined the class, so every CSS
   animation and transition kept running. Mirrors the rule already in
   oracle-os/os-desktop.css so the shell and the app agree. */
body.reduce-motion,
body.reduce-motion *,
body.reduce-motion *::before,
body.reduce-motion *::after {
  animation-duration: .01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .01ms !important;
  scroll-behavior: auto !important;
}

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.597 — APPEARANCE COSMETICS

   The Appearance panes wrote all of the keys below and NOTHING read them: a grep
   for `cardframe-`, `avframe-`, `nametag-`, `feedsep-`, `data-textsize` and
   `accent-scroll` returned zero matches across every stylesheet in the project.
   Fifteen controls that saved, showed a success toast, and changed nothing.

   applyAppearanceSettings() in oracle-core.js now stamps each one onto <body> as a
   data-attribute; these are the rules that give them meaning. Keyed on attributes
   rather than classes so no two settings can clobber each other's className.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── Post card style (appearance.cardFrame) ──────────────────────────────────
   Mirrors the six inline previews the picker renders, so the tile you click and
   the feed you get are the same thing. */
body.cardframe-none .gpost,
body.cardframe-none .gpost       { border:none!important; background:transparent!important; }
body.cardframe-accent .gpost,
body.cardframe-accent .gpost     { border:1px solid var(--accent)!important; }
body.cardframe-gradient .gpost,
body.cardframe-gradient .gpost   { border:1px solid transparent!important;
  background-image:linear-gradient(var(--panel-solid,#0b1220),var(--panel-solid,#0b1220)),
                   linear-gradient(135deg,var(--accent),rgba(168,85,247,.5))!important;
  background-origin:border-box!important; background-clip:padding-box,border-box!important; }
body.cardframe-glow .gpost,
body.cardframe-glow .gpost       { border-radius:14px!important; box-shadow:0 0 16px var(--accent-glow)!important; }
body.cardframe-neon .gpost,
body.cardframe-neon .gpost       { border:1px solid var(--accent)!important; border-radius:4px!important;
  box-shadow:inset 0 0 12px var(--accent-glow),0 0 8px var(--accent-glow)!important; }

/* ── Button style (appearance.buttonStyle) ───────────────────────────────────
   Scoped to real controls. A bare `button` selector would also reshape toggle
   knobs and icon-only rail buttons, which are round on purpose. */
body[data-btnstyle="pill"]    .btn, body[data-btnstyle="pill"]    .gm-primary, body[data-btnstyle="pill"]    button.gc-btn { border-radius:999px!important; }
body[data-btnstyle="sharp"]   .btn, body[data-btnstyle="sharp"]   .gm-primary, body[data-btnstyle="sharp"]   button.gc-btn { border-radius:2px!important; }
body[data-btnstyle="outline"] .btn, body[data-btnstyle="outline"] .gm-primary, body[data-btnstyle="outline"] button.gc-btn {
  background:transparent!important; border:1px solid var(--accent)!important; color:var(--accent)!important; box-shadow:none!important; }
body[data-btnstyle="glass"]   .btn, body[data-btnstyle="glass"]   .gm-primary, body[data-btnstyle="glass"]   button.gc-btn {
  background:rgba(255,255,255,.07)!important; backdrop-filter:blur(10px)!important;
  -webkit-backdrop-filter:blur(10px)!important; border:1px solid rgba(255,255,255,.14)!important; }
body[data-btnstyle="neon"]    .btn, body[data-btnstyle="neon"]    .gm-primary, body[data-btnstyle="neon"]    button.gc-btn {
  border:1px solid var(--accent)!important; color:var(--accent)!important; background:transparent!important;
  box-shadow:0 0 8px var(--accent-glow),inset 0 0 8px var(--accent-glow)!important;
  text-shadow:0 0 6px var(--accent-glow)!important; }

/* ── Name tag effect (appearance.nameTagEffect) ──────────────────────────────
   Applies to YOUR name only: `.me-name` is the opt-in marker added at render
   sites that know the author is the signed-in user, so this never restyles
   someone else's name. */
body[data-nametag="glow"]      .me-name { text-shadow:0 0 8px var(--accent-glow),0 0 2px var(--accent)!important; }
body[data-nametag="gradient"]  .me-name { background:linear-gradient(90deg,var(--accent),var(--accent-2))!important;
  -webkit-background-clip:text!important; background-clip:text!important; -webkit-text-fill-color:transparent!important; }
body[data-nametag="underline"] .me-name { border-bottom:2px solid var(--accent)!important; padding-bottom:1px!important; }
body[data-nametag="badge"]     .me-name { background:var(--accent-glow)!important; border:1px solid var(--accent)!important;
  border-radius:6px!important; padding:1px 7px!important; }
body[data-nametag="fire"]      .me-name { background:linear-gradient(90deg,#f59e0b,#ef4444,#f59e0b)!important;
  background-size:200% auto!important; -webkit-background-clip:text!important; background-clip:text!important;
  -webkit-text-fill-color:transparent!important; animation:nametag-fire 3s linear infinite; }
@keyframes nametag-fire { to { background-position:200% center; } }

/* ── Chat bubble style (appearance.bubbleStyle) — your own messages ───────── */
body[data-bubble="rounded"]  .dm.me .dm-bub, body[data-bubble="rounded"]  .turn.right .bubble { border-radius:20px!important; }
body[data-bubble="flat"]     .dm.me .dm-bub, body[data-bubble="flat"]     .turn.right .bubble { border:none!important; box-shadow:none!important; }
body[data-bubble="gradient"] .dm.me .dm-bub, body[data-bubble="gradient"] .turn.right .bubble {
  background:linear-gradient(135deg,var(--accent),var(--accent-2))!important; color:#fff!important; border-color:transparent!important; }
body[data-bubble="outline"]  .dm.me .dm-bub, body[data-bubble="outline"]  .turn.right .bubble {
  background:transparent!important; border:1px solid var(--accent)!important; color:var(--text)!important; box-shadow:none!important; }
/* Legacy aliases: the Desktop Chat pane offers modern/classic/minimal for the same key. */
body[data-bubble="classic"]  .dm.me .dm-bub, body[data-bubble="classic"]  .turn.right .bubble { border-radius:4px!important; box-shadow:none!important; }
body[data-bubble="minimal"]  .dm.me .dm-bub, body[data-bubble="minimal"]  .turn.right .bubble {
  background:transparent!important; border:none!important; box-shadow:none!important; padding-left:0!important; }

/* ── Feed separator (appearance.feedSeparator) ───────────────────────────── */
body[data-feedsep="line"]     .gpost + .gpost,
body[data-feedsep="line"]     .gpost + .gpost     { border-top:1px solid var(--border)!important; }
body[data-feedsep="gradient"] .gpost + .gpost,
body[data-feedsep="gradient"] .gpost + .gpost     { border-top:1px solid transparent!important;
  border-image:linear-gradient(90deg,transparent,var(--accent),transparent) 1!important; }
body[data-feedsep="dots"]     .gpost + .gpost::before,
body[data-feedsep="dots"]     .gpost + .gpost::before { content:"\2022 \2022 \2022"; display:block; text-align:center;
  color:var(--muted-2); letter-spacing:4px; font-size:10px; margin:-4px 0 10px; }

/* ── Text size (appearance.textSize) ─────────────────────────────────────────
   NOT root font-size: oracle.css sets `body{font-size:13px}` absolutely and has
   zero rem-based font sizes, so scaling the root did nothing at all. These scale
   the READING surfaces — post bodies, messages, comments — which is what the
   control is for. Chrome (nav, labels, badges) deliberately stays fixed so the
   layout cannot break at the larger steps. */
body[data-textsize="small"]  .gpost-text, body[data-textsize="small"]  .dm-bub, body[data-textsize="small"]  .bubble,
body[data-textsize="small"]  .gpost-cmt-body  { font-size:12px!important; }
body[data-textsize="large"]  .gpost-text, body[data-textsize="large"]  .dm-bub, body[data-textsize="large"]  .bubble,
body[data-textsize="large"]  .gpost-cmt-body  { font-size:16px!important; }
body[data-textsize="xlarge"] .gpost-text, body[data-textsize="xlarge"] .dm-bub, body[data-textsize="xlarge"] .bubble,
body[data-textsize="xlarge"] .gpost-cmt-body { font-size:18.5px!important; }

/* ── Line spacing (appearance.lineSpacing) ─────────────────────────────────── */
body[data-linespace="tight"]   .gpost-text, body[data-linespace="tight"]   .dm-bub, body[data-linespace="tight"]   .bubble { line-height:1.3!important; }
body[data-linespace="relaxed"] .gpost-text, body[data-linespace="relaxed"] .dm-bub, body[data-linespace="relaxed"] .bubble { line-height:1.7!important; }
body[data-linespace="double"]  .gpost-text, body[data-linespace="double"]  .dm-bub, body[data-linespace="double"]  .bubble { line-height:2!important; }

/* ── Bold text + accent scrollbar ────────────────────────────────────────── */
body.bold-text { font-weight:600; }
body.bold-text .gpost-text, body.bold-text .dm-bub, body.bold-text .bubble { font-weight:600!important; }
body.accent-scroll ::-webkit-scrollbar-thumb { background:var(--accent)!important; border-radius:8px; }
body.accent-scroll ::-webkit-scrollbar-thumb:hover { background:var(--accent-2)!important; }
body.accent-scroll { scrollbar-color:var(--accent) transparent; }

/* ── Avatar shape (appearance.avatarShape) ───────────────────────────────── */
body[data-avshape="rounded"] .av, body[data-avshape="rounded"] .avatar, body[data-avshape="rounded"] img.av { border-radius:10px!important; }
body[data-avshape="square"]  .av, body[data-avshape="square"]  .avatar, body[data-avshape="square"]  img.av { border-radius:2px!important; }
body[data-avshape="hex"]     .av, body[data-avshape="hex"]     .avatar, body[data-avshape="hex"]     img.av {
  border-radius:0!important; clip-path:polygon(25% 2%,75% 2%,100% 50%,75% 98%,25% 98%,0 50%)!important; }

/* ── Avatar frames (appearance.avatarFrame) ──────────────────────────────────
   The ten frames the Frames & Borders pane offers, as real classes. `.me-av` is
   the opt-in marker for "this avatar belongs to the signed-in user" — a frame is
   a personal cosmetic, so a bare `.av` selector would wrongly decorate everyone
   in the feed with YOUR frame. */
body[data-avframe] .me-av { position:relative; }
body[data-avframe="accent-ring"]  .me-av { box-shadow:0 0 0 3px var(--accent),0 0 8px var(--accent-glow)!important; }
body[data-avframe="pulse-cyan"]   .me-av { box-shadow:0 0 0 3px #22d9e6,0 0 14px rgba(34,217,230,.45),0 0 28px rgba(34,217,230,.15)!important;
  animation:avframe-pulse 2.4s ease-in-out infinite; }
body[data-avframe="pulse-violet"] .me-av { box-shadow:0 0 0 3px #a855f7,0 0 14px rgba(168,85,247,.45),0 0 28px rgba(168,85,247,.15)!important;
  animation:avframe-pulse 2.4s ease-in-out infinite; }
body[data-avframe="ember"]        .me-av { box-shadow:0 0 0 3px #ef4444,0 0 16px rgba(239,68,68,.35),0 0 32px rgba(245,158,11,.1)!important;
  animation:avframe-pulse 3.2s ease-in-out infinite; }
body[data-avframe="lightning"]    .me-av { box-shadow:0 0 0 3px #60a5fa,0 0 18px rgba(96,165,250,.4),0 0 6px rgba(255,255,255,.15)!important; }
body[data-avframe="void-rift"]    .me-av { box-shadow:0 0 0 3px rgba(255,255,255,.5),0 0 20px rgba(0,0,0,.6),0 0 8px rgba(99,102,241,.3)!important; }
/* Conic frames need a rotating ring behind the avatar, which a box-shadow cannot do. */
body[data-avframe="aurora"]       .me-av::before,
body[data-avframe="solar-crown"]  .me-av::before,
body[data-avframe="celestial"]    .me-av::before {
  content:""; position:absolute; inset:-4px; border-radius:inherit; z-index:-1; animation:avframe-spin 6s linear infinite; }
body[data-avframe="aurora"]      .me-av::before { background:conic-gradient(from 0deg,#22c55e,#22d9e6,#6366f1,#a855f7,#ec4899,#f59e0b,#22c55e); }
body[data-avframe="solar-crown"] .me-av::before { background:conic-gradient(from 0deg,#f59e0b,#fbbf24,#f59e0b,#d97706,#f59e0b); animation-duration:9s; }
body[data-avframe="celestial"]   .me-av::before { background:conic-gradient(from 45deg,#fbbf24,#f472b6,#a855f7,#3b82f6,#22d9e6,#4ade80,#fbbf24); animation-duration:12s; }
@keyframes avframe-pulse { 0%,100%{filter:brightness(1)} 50%{filter:brightness(1.35)} }
@keyframes avframe-spin  { to { transform:rotate(360deg) } }

/* ── Font family (appearance.fontFamily) ─────────────────────────────────────
   The pane previews this by writing body.style.fontFamily directly, which is lost
   on the next load. This makes the saved value stick. */
body[data-fontfam="inter"]  { font-family:Inter,system-ui,sans-serif!important; }
body[data-fontfam="system"] { font-family:system-ui,-apple-system,Segoe UI,sans-serif!important; }
body[data-fontfam="mono"]   { font-family:'JetBrains Mono',ui-monospace,monospace!important; }
body[data-fontfam="serif"]  { font-family:Georgia,'Times New Roman',serif!important; }
body[data-fontfam="round"]  { font-family:Nunito,Outfit,sans-serif!important; }

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.597 — THEME DEPTH + 12 NEW THEMES

   The six themes that existed set colour variables, a bubble radius and (for two of
   them) a cursor. Everything else — the backdrop, the panels, the texture — was
   identical, so every theme read as the same interface in a different hue.

   What each theme gets now:
     · a SIGNATURE ANIMATED LAYER on body::after (embers, snow, rain, drifting
       stars, caustics, sheen). body::before was already taken by the lattice grid,
       and ::after was free; it copies that rule's exact layering contract —
       position:fixed; inset:0; pointer-events:none; z-index:0 — so it paints behind
       the app instead of over it.
     · panel and bubble geometry of its own
     · a cursor where the theme has a motif worth one

   Motion is CSS-only and animates `transform` / `background-position`, both of which
   the compositor handles without touching layout. The v9.10.595 `body.reduce-motion`
   rule already collapses every animation here to .01ms, so accessibility is handled
   by the rule that is already in this file — no per-theme opt-out needed.
   ══════════════════════════════════════════════════════════════════════════════ */

/* Shared base. A theme with no signature simply paints nothing. */
body[class*="theme-"]::after{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:0;
}

@keyframes th-rise    { from{transform:translate3d(0,0,0)}      to{transform:translate3d(0,-50%,0)} }
@keyframes th-fall    { from{transform:translate3d(0,-50%,0)}   to{transform:translate3d(0,0,0)} }
@keyframes th-drift   { from{transform:translate3d(0,0,0)}      to{transform:translate3d(-25%,0,0)} }
@keyframes th-diag    { from{transform:translate3d(0,-40%,0)}   to{transform:translate3d(-12%,0,0)} }
@keyframes th-spin    { to  {transform:rotate(360deg)} }
@keyframes th-sheen   { from{background-position:-150% 0}       to{background-position:250% 0} }
@keyframes th-breathe { 0%,100%{opacity:.30} 50%{opacity:.70} }
@keyframes th-flicker { 0%,100%{opacity:.24} 47%{opacity:.30} 48%{opacity:.14} 52%{opacity:.32} }

/* ── Signatures for the six ORIGINAL themes ─────────────────────────────────── */

/* Dragon's Breath — embers lifting off the lava rock. */
body.theme-dragons-breath::after{
  height:200%;
  background-image:
    radial-gradient(2px 2px at 12% 92%, rgba(255,170,60,.85), transparent 60%),
    radial-gradient(1.6px 1.6px at 34% 78%, rgba(255,110,40,.7), transparent 60%),
    radial-gradient(2.4px 2.4px at 58% 96%, rgba(255,200,90,.6), transparent 60%),
    radial-gradient(1.4px 1.4px at 76% 84%, rgba(255,140,50,.75), transparent 60%),
    radial-gradient(2px 2px at 91% 90%, rgba(255,180,70,.55), transparent 60%);
  background-size:100% 50%;
  animation:th-rise 14s linear infinite;
}
/* Arctic Frost — slow snowfall. */
body.theme-arctic-frost::after{
  height:200%;
  background-image:
    radial-gradient(1.8px 1.8px at 15% 10%, rgba(224,242,254,.8), transparent 60%),
    radial-gradient(1.4px 1.4px at 42% 26%, rgba(186,230,253,.6), transparent 60%),
    radial-gradient(2px 2px at 67% 8%,  rgba(224,242,254,.7), transparent 60%),
    radial-gradient(1.5px 1.5px at 84% 32%, rgba(186,230,253,.55), transparent 60%),
    radial-gradient(1.2px 1.2px at 28% 44%, rgba(255,255,255,.5), transparent 60%);
  background-size:100% 50%;
  animation:th-fall 22s linear infinite;
}
/* Neon Pulse — CRT scanlines with an unstable tube. */
body.theme-neon-pulse::after{
  background-image:repeating-linear-gradient(0deg,
    rgba(168,85,247,.14) 0px, rgba(168,85,247,.14) 1px, transparent 1px, transparent 3px);
  animation:th-flicker 5s steps(1,end) infinite;
}
/* Solar Flare — a slow corona sweep. */
body.theme-solar-flare::after{
  background-image:conic-gradient(from 0deg at 78% -12%,
    rgba(245,158,11,.16), transparent 22%, transparent 78%, rgba(251,191,36,.13));
  animation:th-spin 90s linear infinite;
  transform-origin:78% -12%;
}
/* Void Walker — deep starfield drifting sideways. */
body.theme-void-walker::after{
  width:200%;
  background-image:
    radial-gradient(1.4px 1.4px at 8% 18%,  rgba(255,255,255,.7), transparent 60%),
    radial-gradient(1px 1px   at 21% 62%,  rgba(199,210,254,.55), transparent 60%),
    radial-gradient(1.7px 1.7px at 33% 34%, rgba(255,255,255,.6), transparent 60%),
    radial-gradient(1px 1px   at 44% 80%,  rgba(165,180,252,.5), transparent 60%),
    radial-gradient(1.3px 1.3px at 61% 22%, rgba(255,255,255,.65), transparent 60%),
    radial-gradient(1px 1px   at 78% 56%,  rgba(199,210,254,.45), transparent 60%);
  background-size:50% 100%;
  animation:th-drift 120s linear infinite;
}
/* Emerald Grove — dappled canopy light. */
body.theme-emerald-grove::after{
  background-image:
    radial-gradient(320px 220px at 22% 8%,  rgba(74,222,128,.10), transparent 70%),
    radial-gradient(280px 200px at 74% 18%, rgba(34,197,94,.08), transparent 70%);
  animation:th-breathe 11s ease-in-out infinite;
}

/* ══ NEW THEMES ══════════════════════════════════════════════════════════════
   Named to match the player-card art catalog in oracle-core.js (_pcardArt), so an
   equipped card and an equipped theme read as the same collection rather than two
   unrelated cosmetic systems. */

/* ── Midnight City — cold blue dusk over a skyline, slow star drift ───────── */
body.theme-midnight{
  --bg:#05030f;--bg-2:#0a0a1e;--panel:rgba(16,16,51,.72);--panel-2:rgba(10,10,30,.86);--panel-solid:#0b0b20;
  --rail:rgba(8,8,26,.92);
  --border:rgba(139,147,255,.14);--border-2:rgba(139,147,255,.07);
  --accent:#8b93ff;--accent-2:#5b63d6;--accent-glow:rgba(139,147,255,.20);
  --text:#e7e9ff;--muted:#8189bd;--muted-2:#525a8c;
}
body.theme-midnight::after{
  width:200%;
  background-image:
    radial-gradient(1.5px 1.5px at 6% 12%,  rgba(255,255,255,.75), transparent 60%),
    radial-gradient(1px 1px   at 19% 40%,  rgba(205,214,255,.6), transparent 60%),
    radial-gradient(1.8px 1.8px at 31% 18%, rgba(255,255,255,.7), transparent 60%),
    radial-gradient(1px 1px   at 47% 52%,  rgba(205,214,255,.5), transparent 60%),
    radial-gradient(1.4px 1.4px at 64% 26%, rgba(255,255,255,.65), transparent 60%);
  background-size:50% 100%;
  animation:th-drift 160s linear infinite;
}
body.theme-midnight .guest-card,body.theme-midnight .gmodal,body.theme-midnight .gpost{
  border-radius:14px!important;
  box-shadow:inset 0 1px 0 rgba(139,147,255,.10),0 6px 26px rgba(0,0,0,.5)!important;
}
body.theme-midnight .dm.me .dm-bub{border-radius:18px 18px 5px 18px!important}
body.theme-midnight .dm.them .dm-bub{border-radius:18px 18px 18px 5px!important}

/* ── Green Rain — falling code, monospaced chrome ─────────────────────────── */
body.theme-matrix{
  --bg:#001505;--bg-2:#00300f;--panel:rgba(0,32,12,.78);--panel-2:rgba(0,20,8,.88);--panel-solid:#00190a;
  --rail:rgba(0,18,7,.94);
  --border:rgba(34,229,106,.18);--border-2:rgba(34,229,106,.08);
  --accent:#22e56a;--accent-2:#12a04a;--accent-glow:rgba(34,229,106,.18);
  --text:#c9ffd9;--muted:#5f9c75;--muted-2:#3c6b4d;
  --ui:'JetBrains Mono',ui-monospace,monospace;
}
body.theme-matrix::after{
  height:200%;
  background-image:repeating-linear-gradient(180deg,
      rgba(34,229,106,.16) 0px, rgba(34,229,106,.16) 2px, transparent 2px, transparent 16px),
    repeating-linear-gradient(90deg,
      transparent 0px, transparent 28px, rgba(34,229,106,.05) 28px, rgba(34,229,106,.05) 30px);
  background-size:100% 50%, 100% 100%;
  animation:th-fall 5.5s linear infinite;
}
body.theme-matrix .guest-card,body.theme-matrix .gmodal,body.theme-matrix .gpost{
  border-radius:2px!important;border:1px solid rgba(34,229,106,.20)!important;
}
body.theme-matrix .dm.me .dm-bub,body.theme-matrix .dm.them .dm-bub{border-radius:2px!important}
body.theme-matrix,body.theme-matrix *{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22'%3E%3Cpath d='M3 1L3 17L7 13L11 20L14 18L10 12L16 12Z' fill='%2322e56a' stroke='%23001505' stroke-width='1'/%3E%3C/svg%3E") 3 1,auto;
}

/* ── Nebula — deep space clouds, magenta and blue ─────────────────────────── */
body.theme-nebula{
  --bg:#0a0018;--bg-2:#22093a;--panel:rgba(34,9,58,.70);--panel-2:rgba(18,0,42,.86);--panel-solid:#140028;
  --rail:rgba(14,0,32,.92);
  --border:rgba(192,132,252,.16);--border-2:rgba(192,132,252,.08);
  --accent:#c084fc;--accent-2:#8b47d6;--accent-glow:rgba(192,132,252,.22);
  --text:#f0e4ff;--muted:#9b7fc0;--muted-2:#6b5490;
}
body.theme-nebula::after{
  background-image:
    radial-gradient(600px 340px at 74% 22%, rgba(255,77,141,.13), transparent 70%),
    radial-gradient(520px 300px at 22% 34%, rgba(77,109,255,.13), transparent 70%),
    radial-gradient(1.4px 1.4px at 40% 20%, rgba(255,255,255,.7), transparent 60%),
    radial-gradient(1px 1px   at 66% 62%, rgba(255,255,255,.55), transparent 60%);
  animation:th-breathe 16s ease-in-out infinite;
}
body.theme-nebula .guest-card,body.theme-nebula .gmodal,body.theme-nebula .gpost{
  border-radius:16px!important;
  background:linear-gradient(170deg,rgba(34,9,58,.75),rgba(10,0,24,.9))!important;
  box-shadow:inset 0 1px 0 rgba(192,132,252,.12),0 8px 30px rgba(0,0,0,.55)!important;
}
body.theme-nebula .dm.me .dm-bub{border-radius:18px!important;box-shadow:0 2px 18px rgba(192,132,252,.22)!important}

/* ── Blood Moon — crimson eclipse, heavy vignette ─────────────────────────── */
body.theme-bloodmoon{
  --bg:#180000;--bg-2:#450000;--panel:rgba(69,0,0,.72);--panel-2:rgba(30,0,0,.88);--panel-solid:#1e0000;
  --rail:rgba(22,0,0,.94);
  --border:rgba(255,77,77,.18);--border-2:rgba(255,77,77,.08);
  --accent:#ff4d4d;--accent-2:#c22b2b;--accent-glow:rgba(255,77,77,.20);
  --text:#ffe2e2;--muted:#b07070;--muted-2:#7a4848;
  --ui:'Cinzel',Outfit,serif;
}
body.theme-bloodmoon::after{
  background-image:
    radial-gradient(240px 240px at 82% 14%, rgba(255,90,90,.20), transparent 68%),
    radial-gradient(circle at 50% 50%, transparent 42%, rgba(0,0,0,.5) 100%);
  animation:th-breathe 9s ease-in-out infinite;
}
body.theme-bloodmoon .guest-card,body.theme-bloodmoon .gmodal,body.theme-bloodmoon .gpost{
  border-radius:4px!important;border-top:2px solid rgba(255,77,77,.26)!important;
  background:linear-gradient(175deg,rgba(60,0,0,.8),rgba(24,0,0,.95))!important;
}
body.theme-bloodmoon .dm.me .dm-bub{border-radius:12px 12px 3px 12px!important}
body.theme-bloodmoon .dm.them .dm-bub{border-radius:12px 12px 12px 3px!important}

/* ── Aurelian — struck gold, warm sheen sweeping the page ─────────────────── */
body.theme-gold{
  --bg:#241400;--bg-2:#5a4010;--panel:rgba(90,64,16,.55);--panel-2:rgba(36,20,0,.88);--panel-solid:#2a1a00;
  --rail:rgba(30,18,0,.94);
  --border:rgba(251,191,36,.20);--border-2:rgba(251,191,36,.09);
  --accent:#fbbf24;--accent-2:#c48908;--accent-glow:rgba(251,191,36,.22);
  --text:#fff4d6;--muted:#b89a5e;--muted-2:#7d6838;
  --ui:'Cinzel',Outfit,serif;
}
body.theme-gold::after{
  background-image:linear-gradient(105deg,
    transparent 38%, rgba(255,236,170,.10) 47%, rgba(255,255,255,.16) 50%,
    rgba(255,236,170,.10) 53%, transparent 62%);
  background-size:250% 100%;
  animation:th-sheen 9s ease-in-out infinite;
}
body.theme-gold .guest-card,body.theme-gold .gmodal,body.theme-gold .gpost{
  border-radius:6px!important;border:1px solid rgba(251,191,36,.24)!important;
  box-shadow:inset 0 1px 0 rgba(255,236,170,.16),0 4px 22px rgba(0,0,0,.5)!important;
}
body.theme-gold .dm.me .dm-bub{border-radius:10px!important;box-shadow:0 2px 14px rgba(251,191,36,.24)!important}

/* ── Obsidian — matte volcanic glass, near-monochrome ─────────────────────── */
body.theme-obsidian{
  --bg:#050505;--bg-2:#161616;--panel:rgba(22,22,22,.80);--panel-2:rgba(8,8,8,.92);--panel-solid:#0b0b0b;
  --rail:rgba(6,6,6,.96);
  --border:rgba(223,230,239,.12);--border-2:rgba(223,230,239,.06);
  --accent:#dfe6ef;--accent-2:#9aa3b0;--accent-glow:rgba(223,230,239,.12);
  --text:#eef2f7;--muted:#7e8894;--muted-2:#525a64;
}
body.theme-obsidian::after{
  background-image:linear-gradient(122deg,
    transparent 44%, rgba(255,255,255,.05) 49%, rgba(255,255,255,.09) 50.5%,
    rgba(255,255,255,.05) 52%, transparent 57%);
  background-size:250% 100%;
  animation:th-sheen 16s linear infinite;
}
body.theme-obsidian .guest-card,body.theme-obsidian .gmodal,body.theme-obsidian .gpost{
  border-radius:3px!important;
  background:linear-gradient(160deg,rgba(26,26,26,.9),rgba(6,6,6,.95))!important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 4px 18px rgba(0,0,0,.7)!important;
}
body.theme-obsidian .dm.me .dm-bub,body.theme-obsidian .dm.them .dm-bub{border-radius:3px!important}

/* ── Plasma — contained arc reactor, teal discharge ───────────────────────── */
body.theme-plasma{
  --bg:#00201e;--bg-2:#00463c;--panel:rgba(0,70,60,.62);--panel-2:rgba(0,32,30,.88);--panel-solid:#00302a;
  --rail:rgba(0,26,24,.94);
  --border:rgba(45,212,191,.18);--border-2:rgba(45,212,191,.08);
  --accent:#2dd4bf;--accent-2:#0d9488;--accent-glow:rgba(45,212,191,.22);
  --text:#d6fff8;--muted:#6aa89d;--muted-2:#437069;
}
body.theme-plasma::after{
  background-image:
    radial-gradient(420px 420px at 50% 28%, rgba(45,212,191,.13), transparent 68%),
    repeating-conic-gradient(from 0deg at 50% 28%,
      rgba(45,212,191,.055) 0deg, transparent 8deg, transparent 22deg);
  animation:th-spin 44s linear infinite;
  transform-origin:50% 28%;
}
body.theme-plasma .guest-card,body.theme-plasma .gmodal,body.theme-plasma .gpost{
  border-radius:12px!important;box-shadow:inset 0 0 22px rgba(45,212,191,.07),0 4px 20px rgba(0,0,0,.5)!important;
}
body.theme-plasma .dm.me .dm-bub{border-radius:16px!important;box-shadow:0 0 16px rgba(45,212,191,.24)!important}

/* ── Sakura — falling petals, soft pinks ──────────────────────────────────── */
body.theme-cherry{
  --bg:#2b0919;--bg-2:#5a1030;--panel:rgba(90,16,48,.62);--panel-2:rgba(43,9,25,.88);--panel-solid:#3a0a22;
  --rail:rgba(38,8,22,.94);
  --border:rgba(255,143,196,.18);--border-2:rgba(255,143,196,.08);
  --accent:#ff8fc4;--accent-2:#d1548f;--accent-glow:rgba(255,143,196,.20);
  --text:#ffe6f2;--muted:#c08aa4;--muted-2:#8a5b72;
}
body.theme-cherry::after{
  height:200%;
  background-image:
    radial-gradient(4px 7px at 14% 8%,  rgba(255,143,196,.55), transparent 62%),
    radial-gradient(3px 5px at 38% 26%, rgba(255,209,232,.5), transparent 62%),
    radial-gradient(5px 8px at 62% 12%, rgba(255,143,196,.42), transparent 62%),
    radial-gradient(3px 5px at 83% 32%, rgba(255,209,232,.45), transparent 62%),
    radial-gradient(4px 6px at 28% 42%, rgba(255,143,196,.35), transparent 62%);
  background-size:100% 50%;
  animation:th-diag 26s linear infinite;
}
body.theme-cherry .guest-card,body.theme-cherry .gmodal,body.theme-cherry .gpost{border-radius:18px!important}
body.theme-cherry .dm.me .dm-bub{border-radius:20px 20px 6px 20px!important}
body.theme-cherry .dm.them .dm-bub{border-radius:20px 20px 20px 6px!important}

/* ── Abyss — underwater caustics, light from far above ────────────────────── */
body.theme-ocean{
  --bg:#02141f;--bg-2:#023a5e;--panel:rgba(2,58,94,.58);--panel-2:rgba(2,20,31,.88);--panel-solid:#03202f;
  --rail:rgba(2,18,28,.94);
  --border:rgba(34,195,240,.16);--border-2:rgba(34,195,240,.07);
  --accent:#22c3f0;--accent-2:#0a8ab5;--accent-glow:rgba(34,195,240,.20);
  --text:#d8f4ff;--muted:#6d9db4;--muted-2:#456878;
}
body.theme-ocean::after{
  width:200%;
  background-image:
    radial-gradient(180px 90px at 12% 6%, rgba(191,242,255,.09), transparent 70%),
    radial-gradient(220px 110px at 34% 2%, rgba(191,242,255,.07), transparent 70%),
    radial-gradient(160px 80px at 58% 9%, rgba(191,242,255,.08), transparent 70%),
    radial-gradient(200px 100px at 82% 4%, rgba(191,242,255,.06), transparent 70%);
  background-size:50% 100%;
  animation:th-drift 40s linear infinite alternate;
}
body.theme-ocean .guest-card,body.theme-ocean .gmodal,body.theme-ocean .gpost{
  border-radius:16px!important;backdrop-filter:blur(4px)!important;-webkit-backdrop-filter:blur(4px)!important;
}
body.theme-ocean .dm.me .dm-bub{border-radius:20px 20px 6px 20px!important}

/* ── Supernova — detonating star, radiating spokes ────────────────────────── */
body.theme-supernova{
  --bg:#1a0800;--bg-2:#4d1a00;--panel:rgba(77,26,0,.62);--panel-2:rgba(26,8,0,.9);--panel-solid:#200a00;
  --rail:rgba(22,7,0,.94);
  --border:rgba(255,138,30,.20);--border-2:rgba(255,138,30,.09);
  --accent:#ff8a1e;--accent-2:#c25c06;--accent-glow:rgba(255,138,30,.24);
  --text:#ffeddb;--muted:#bd8a63;--muted-2:#835e42;
}
body.theme-supernova::after{
  background-image:
    radial-gradient(300px 300px at 50% 18%, rgba(255,242,194,.16), transparent 66%),
    repeating-conic-gradient(from 0deg at 50% 18%,
      rgba(255,138,30,.07) 0deg, transparent 5deg, transparent 15deg);
  animation:th-spin 70s linear infinite;
  transform-origin:50% 18%;
}
body.theme-supernova .guest-card,body.theme-supernova .gmodal,body.theme-supernova .gpost{
  border-radius:8px!important;box-shadow:inset 0 1px 0 rgba(255,200,120,.12),0 4px 24px rgba(0,0,0,.55)!important;
}
body.theme-supernova .dm.me .dm-bub{border-radius:14px!important;box-shadow:0 2px 18px rgba(255,138,30,.26)!important}

/* ── Prismatic — refracted spectrum drifting across a neutral shell ───────── */
body.theme-prismatic{
  --bg:#0a0a14;--bg-2:#1c1c30;--panel:rgba(28,28,48,.72);--panel-2:rgba(10,10,20,.88);--panel-solid:#0d0d18;
  --rail:rgba(9,9,16,.94);
  --border:rgba(255,255,255,.13);--border-2:rgba(255,255,255,.06);
  --accent:#ffffff;--accent-2:#b9c4d6;--accent-glow:rgba(255,255,255,.12);
  --text:#f2f5fa;--muted:#8b93a7;--muted-2:#5b6376;
}
body.theme-prismatic::after{
  background-image:linear-gradient(100deg,
    transparent 30%,
    rgba(255,45,85,.10) 38%, rgba(255,149,0,.10) 43%, rgba(255,204,0,.10) 48%,
    rgba(52,199,89,.10) 53%, rgba(10,132,255,.10) 58%, rgba(175,82,222,.10) 63%,
    transparent 72%);
  background-size:250% 100%;
  animation:th-sheen 13s linear infinite;
}
body.theme-prismatic .guest-card,body.theme-prismatic .gmodal,body.theme-prismatic .gpost{
  border-radius:14px!important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10),0 6px 26px rgba(0,0,0,.5)!important;
}
body.theme-prismatic .dm.me .dm-bub{
  background:linear-gradient(120deg,#ff2d55,#ff9500,#ffcc00,#34c759,#0a84ff,#af52de)!important;
  background-size:300% auto!important;color:#fff!important;border-color:transparent!important;
  animation:th-sheen 8s linear infinite;
}

/* ── Carbon — woven fibre, industrial and quiet ───────────────────────────── */
body.theme-carbon{
  --bg:#101010;--bg-2:#2c2c2c;--panel:rgba(44,44,44,.72);--panel-2:rgba(13,13,13,.9);--panel-solid:#141414;
  --rail:rgba(11,11,11,.95);
  --border:rgba(183,188,196,.13);--border-2:rgba(183,188,196,.06);
  --accent:#b7bcc4;--accent-2:#828892;--accent-glow:rgba(183,188,196,.13);
  --text:#e8ebef;--muted:#868d97;--muted-2:#565d66;
}
body.theme-carbon::after{
  background-image:
    repeating-linear-gradient(45deg,  rgba(255,255,255,.030) 0 2px, transparent 2px 6px),
    repeating-linear-gradient(-45deg, rgba(0,0,0,.22)        0 2px, transparent 2px 6px);
  opacity:.55;
}
body.theme-carbon .guest-card,body.theme-carbon .gmodal,body.theme-carbon .gpost{
  border-radius:5px!important;box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 3px 14px rgba(0,0,0,.6)!important;
}
body.theme-carbon .dm.me .dm-bub,body.theme-carbon .dm.them .dm-bub{border-radius:5px!important}

/* ── Frames the animated layer must sit behind ───────────────────────────────
   The app shell paints on top because body::after is z-index:0 and the shell's own
   stacking contexts sit above it — the same contract body::before has relied on
   since v9.0. Modals additionally raise themselves, so nothing here can veil a
   dialog. */
body[class*="theme-"] .gmodal,
body[class*="theme-"] .guest-card,
body[class*="theme-"] .gpost{ position:relative; z-index:1; }

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.598 — THEME PRESENCE ON THE PERSISTENT CHROME

   The v9.10.597 signature layers paint on body::after, which sits BEHIND the app
   shell (.shell is z-index:1). That is correct — a backdrop must not veil the UI —
   but it means the effect only reads through the gaps, and the parts of the screen
   you look at all day (top bar, rail, headers, inputs, scrollbars) stayed the same
   dark grey in every theme. Hence "they're all still basic".

   This block gives every theme its identity on that chrome. It is written ONCE
   against each theme's own --accent / --panel / --border tokens rather than
   eighteen times, so a new theme inherits all of it by declaring its variables.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── Scrollbars take the theme colour ─────────────────────────────────────── */
[class*="theme-"] ::-webkit-scrollbar-thumb{
  background:linear-gradient(180deg,var(--accent),var(--accent-2))!important;
  border-radius:10px;
}
[class*="theme-"] ::-webkit-scrollbar-thumb:hover{ background:var(--accent)!important; }

/* ── Text selection + focus rings ─────────────────────────────────────────── */
[class*="theme-"] ::selection{ background:var(--accent-glow); color:var(--text); }
[class*="theme-"] :focus-visible{
  outline:2px solid var(--accent)!important; outline-offset:2px!important;
}

/* ── Top bar: a lit edge in the theme colour ──────────────────────────────── */
[class*="theme-"] .topbar,[class*="theme-"] #topbar{
  background:linear-gradient(180deg,var(--panel-2),transparent)!important;
  border-bottom:1px solid var(--border)!important;
  box-shadow:0 1px 0 var(--accent-glow),0 6px 24px rgba(0,0,0,.35)!important;
  backdrop-filter:blur(10px)!important;-webkit-backdrop-filter:blur(10px)!important;
}

/* ── Rail: the active item gets an accent spine ───────────────────────────── */
[class*="theme-"] .rail,[class*="theme-"] #rail{
  background:var(--rail)!important; border-right:1px solid var(--border)!important;
}
[class*="theme-"] .rail-btn{ position:relative; }
[class*="theme-"] .rail-btn.active::before{
  content:"";position:absolute;left:0;top:14%;bottom:14%;width:3px;border-radius:0 3px 3px 0;
  background:linear-gradient(180deg,var(--accent),var(--accent-2));
  box-shadow:0 0 10px var(--accent-glow);
}

/* ── Section headers get a themed rule under them ─────────────────────────── */
[class*="theme-"] .set2-nav button.on,
[class*="theme-"] .m-tab.active,
[class*="theme-"] .ch-tab.active{
  box-shadow:inset 0 -2px 0 var(--accent)!important;
}

/* ── Inputs pick up the theme instead of staying default-navy ─────────────── */
[class*="theme-"] input[type="text"],[class*="theme-"] input[type="search"],
[class*="theme-"] input[type="password"],[class*="theme-"] input[type="email"],
[class*="theme-"] textarea,[class*="theme-"] select{
  background:var(--panel-2)!important;
  border:1px solid var(--border)!important;
  color:var(--text)!important;
}
[class*="theme-"] input:focus,[class*="theme-"] textarea:focus,[class*="theme-"] select:focus{
  border-color:var(--accent)!important;
  box-shadow:0 0 0 3px var(--accent-glow)!important;
}
[class*="theme-"] ::placeholder{ color:var(--muted-2)!important; }

/* ── Cards get a lit top edge, so panels read as themed material ──────────── */
[class*="theme-"] .guest-card,[class*="theme-"] .gpost,
[class*="theme-"] .gmodal{
  border:1px solid var(--border)!important;
  box-shadow:inset 0 1px 0 var(--accent-glow),0 4px 20px rgba(0,0,0,.42)!important;
}

/* ── Primary actions carry the theme gradient ─────────────────────────────── */
[class*="theme-"] .btn.primary,[class*="theme-"] .gm-primary,[class*="theme-"] button.gc-btn{
  background:linear-gradient(135deg,var(--accent),var(--accent-2))!important;
  border:1px solid transparent!important; color:#06090f!important;
  box-shadow:0 2px 14px var(--accent-glow)!important;
}
[class*="theme-"] .btn.primary:hover,[class*="theme-"] .gm-primary:hover,[class*="theme-"] button.gc-btn:hover{
  filter:brightness(1.12);
}

/* ── Loading/progress bits ────────────────────────────────────────────────── */
[class*="theme-"] progress::-webkit-progress-value{ background:var(--accent)!important; }
[class*="theme-"] .spinner,[class*="theme-"] .loader{ border-top-color:var(--accent)!important; }

/* ── Links ────────────────────────────────────────────────────────────────── */
[class*="theme-"] a:hover{ color:var(--accent-2)!important; }

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.607 — HOME FEED: fill the space, calm the sizes

   Measured on a 1440px viewport before this change:
     · rail 54px, centre column 1386px available
     · .guest-dash-grid is `grid-template-columns: 780px 280px` — FIXED pixels, so
       the layout occupies 1060px and never grows. 306px of the window sat empty,
       and it got worse the wider the screen: at 1899px (the owner's actual width)
       roughly 760px is dead.
     · .gpost-text renders at 15.5px against a 13px app base
     · post avatar 44px, action row 52px tall with 44px buttons

   So the feed read as both empty AND oversized: a narrow column of big controls
   marooned in a wide dark page.

   Fixes here are layout + scale only. No markup, no behaviour, no JS.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── 1. Let the grid breathe ────────────────────────────────────────────────
   The main column becomes fluid with a sane reading cap, and the whole grid is
   centred with a max-width instead of being pinned to 1060px. `minmax(0,…)` is
   required or long words in a post can force the column wider than its track. */
@media (min-width: 1100px){
  .guest-dash-grid{
    grid-template-columns: minmax(0, 1fr) 300px !important;
    max-width: 1320px;
    margin-inline: auto;
    gap: 22px !important;
  }
  /* A text column beyond ~820px is uncomfortable to read, so the main column grows
     into the space only up to that, and the remainder goes to the side rail. */
  .guest-col-main{ max-width: 820px; margin-inline: auto; width: 100%; }
}
/* Very wide screens: give the side rail the extra room rather than stretching
   the post column into a letterbox. */
@media (min-width: 1600px){
  .guest-dash-grid{ grid-template-columns: minmax(0, 1fr) 340px !important; max-width: 1500px; }
}

/* ── 2. Post card: tighter, and actually rounded ───────────────────────────
   Measured radius was 0px, so cards had no edge at all — part of why the feed
   looked like undifferentiated slabs. */
.gpost{
  border-radius: 14px !important;
  padding: 13px 15px !important;
  margin-bottom: 12px !important;
}

/* ── 3. Type scale — the "uncomfortably big" complaint ─────────────────────
   15.5px body text in a 13px UI is a full step out of scale. 14.5px keeps posts
   comfortably readable while sitting in the same family as everything else. */
.gpost-text{ font-size: 14.5px !important; line-height: 1.5 !important; margin-bottom: 10px !important; }
.gpost-head{ margin-bottom: 9px !important; }

/* ── 4. Avatars and controls ───────────────────────────────────────────────
   44px is a touch target for a primary control, not for a row of six secondary
   actions. 36px avatar / 34px action buttons keeps them comfortably tappable
   (still above the 32px practical minimum on touch) without dominating the card. */
.gpost-head .gav-wrap{ width: 38px !important; height: 38px !important; }
.gpost-head .gav-wrap img,
.gpost-head .gav-wrap > div{ width: 38px !important; height: 38px !important; }

.gpost-acts{ padding: 4px 0 0 !important; gap: 2px !important; }
.gpost-acts button{
  height: 34px !important;
  padding: 0 10px !important;
  border-radius: 8px !important;
  font-size: 12px !important;
}
/* Keep the touch target honest on real touch devices, where 34px is tight. */
@media (pointer: coarse){
  .gpost-acts button{ height: 40px !important; }
}

/* ── 5. Composer: the action row was a cramped wrap of 14 controls ─────────
   Left to itself the row wrapped mid-group and the Post button drifted, which is
   what made the buttons feel broken. They all work — they were just badly laid
   out. Explicit wrap + consistent chip sizing, with Post pinned to the end. */
.gpost-composer .gcomp-row{
  display: flex !important;
  flex-wrap: wrap !important;
  align-items: center !important;
  gap: 6px !important;
}
.gpost-composer button{
  height: 32px !important;
  padding: 0 11px !important;
  border-radius: 8px !important;
  font-size: 12px !important;
  white-space: nowrap;
}
.gpost-composer button.gcomp-post,
.gpost-composer button[onclick*="createGuestPost"]{
  margin-left: auto !important;
  height: 34px !important;
  padding: 0 20px !important;
  font-weight: 700 !important;
}
.gpost-composer textarea{ font-size: 14px !important; line-height: 1.5 !important; }

/* ── 6. Stories rail: 105x170 tiles are larger than the posts they sit above ── */
.gstory-card{ width: 92px !important; height: 148px !important; border-radius: 12px !important; }
.gstory-card-name{ font-size: 10.5px !important; }

/* ── 7. Side rail cards match the post card language ───────────────────────── */
.guest-col-right .guest-card{ border-radius: 14px !important; padding: 13px 15px !important; }

/* ── 8. Feed tabs sat in 44px of chrome for three words ────────────────────── */
#ghome-tabs{ height: 38px !important; }
#ghome-tabs button{ font-size: 12.5px !important; padding: 0 14px !important; }

/* ── v9.10.610 — composer attachment strip ─────────────────────────────────
   The composer could carry a photo, GIF, poll, feeling, schedule and audience at
   once with nothing summarising it, so the only way to know what was riding on a
   post was to reopen every panel. Each chip here is removable. */
.gcomp-attachments{
  display:flex; flex-wrap:wrap; gap:6px; margin:8px 0 2px;
}
.gcomp-attach-chip{
  display:inline-flex; align-items:center; gap:6px;
  background:var(--accent-glow,rgba(34,217,230,.14));
  border:1px solid var(--accent,#22d9e6);
  color:var(--text,#e9eef7);
  font:600 11px Outfit,system-ui,sans-serif;
  padding:3px 4px 3px 10px; border-radius:20px;
}
.gcomp-attach-chip button{
  background:transparent; border:none; cursor:pointer;
  color:var(--text,#e9eef7); opacity:.7;
  font:700 14px/1 Outfit,system-ui,sans-serif;
  width:18px; height:18px; border-radius:50%; padding:0;
}
.gcomp-attach-chip button:hover{ opacity:1; background:rgba(255,255,255,.14); }

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.612 — POST CARDS + COMPOSER: give them a surface

   The cards were a flat fill with a hairline border: no depth, no separation from
   the page, no response to the cursor. Everything sat at one visual level, so a
   column of them read as a wall rather than as objects.

   All of this is presentation. No markup, no JS, no behaviour.
   Uses theme tokens throughout, so all 18 themes inherit it.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── The card itself ────────────────────────────────────────────────────────
   A very slight top-down gradient plus a 1px inner highlight reads as a lit
   surface instead of a hole. Kept subtle — this has to survive being repeated
   forty times down a column without becoming noisy. */
.gpost{
  background:
    linear-gradient(180deg, rgba(255,255,255,.030), rgba(255,255,255,0) 120px),
    var(--panel, rgba(13,19,32,.72)) !important;
  border: 1px solid var(--border, rgba(255,255,255,.07)) !important;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.05),
    0 1px 2px rgba(0,0,0,.30),
    0 8px 24px rgba(0,0,0,.22) !important;
  transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
/* Hover lifts it a touch and warms the border to the theme accent. Pointer-only:
   on touch there is no hover, and a stuck :hover state after a tap looks broken. */
@media (hover: hover){
  .gpost:hover{
    border-color: color-mix(in srgb, var(--accent, #22d9e6) 34%, transparent) !important;
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.07),
      0 2px 4px rgba(0,0,0,.32),
      0 14px 34px rgba(0,0,0,.30) !important;
    transform: translateY(-1px);
  }
}

/* ── Author row: build a hierarchy instead of three equal greys ───────────── */
.gpost-head .uname-link{ font-weight: 700 !important; letter-spacing: -.1px; }
.gpost-head .gav-wrap{
  box-shadow: 0 0 0 2px var(--panel-solid, #0a0f1b), 0 0 0 3px rgba(255,255,255,.07);
  border-radius: 50%;
}
@media (hover: hover){
  .gpost-head .gav-wrap{ transition: box-shadow .16s ease; }
  .gpost:hover .gpost-head .gav-wrap{
    box-shadow: 0 0 0 2px var(--panel-solid, #0a0f1b),
                0 0 0 3px color-mix(in srgb, var(--accent, #22d9e6) 55%, transparent);
  }
}

/* ── Body copy ─────────────────────────────────────────────────────────────
   Slightly softer than pure white; pure #fff on dark at this size is harsh over
   a long feed. */
.gpost-text{ color: color-mix(in srgb, var(--text, #e9eef7) 92%, transparent) !important; }

/* ── Stats line ────────────────────────────────────────────────────────────
   "1 LIKES 0 COMMENTS 0 SHARES 0 REPOSTS" was as loud as the post body. It is
   metadata; it should recede until you look for it. */
.gpost-stats{
  font-size: 11px !important;
  color: var(--muted-2, #475263) !important;
  letter-spacing: .2px;
  padding-bottom: 8px !important;
  border-bottom: 1px solid var(--border-2, rgba(255,255,255,.04)) !important;
}

/* ── Reaction chips ────────────────────────────────────────────────────────
   Flat pills with no edge. Now they read as counted tokens. */
.gpost-rx-chip{
  background: var(--panel-2, rgba(9,14,24,.85)) !important;
  border: 1px solid var(--border, rgba(255,255,255,.08)) !important;
  border-radius: 20px !important;
  padding: 3px 9px !important;
  font: 600 11px Outfit, system-ui, sans-serif !important;
  transition: border-color .14s ease, transform .14s ease;
}
@media (hover: hover){
  .gpost-rx-chip:hover{
    border-color: var(--accent, #22d9e6) !important;
    transform: translateY(-1px);
  }
}

/* ── Action row ────────────────────────────────────────────────────────────
   Separated from the body, and each control now shows it is pressable. */
.gpost-acts{ border-top: 1px solid var(--border-2, rgba(255,255,255,.04)) !important; margin-top: 2px !important; }
.gpost-acts button{
  color: var(--muted, #6b7a90) !important;
  font-weight: 600 !important;
  transition: background .13s ease, color .13s ease;
}
@media (hover: hover){
  .gpost-acts button:hover{
    background: var(--accent-glow, rgba(34,217,230,.14)) !important;
    color: var(--text, #e9eef7) !important;
  }
}
.gpost-acts button:active{ transform: scale(.96); }
/* Already liked / already saved should be obvious at a glance. */
.gpost-acts button.on,
.gpost-acts button.liked{
  color: var(--accent, #22d9e6) !important;
  background: var(--accent-glow, rgba(34,217,230,.12)) !important;
}

/* ── Composer: it is the thing you act on, so it should sit forward ──────── */
.gpost-composer{
  background:
    linear-gradient(180deg, rgba(255,255,255,.040), rgba(255,255,255,0) 90px),
    var(--panel, rgba(13,19,32,.72)) !important;
  border: 1px solid var(--border, rgba(255,255,255,.08)) !important;
  border-radius: 16px !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06), 0 10px 30px rgba(0,0,0,.26) !important;
  transition: border-color .18s ease, box-shadow .18s ease;
}
/* Focus-within, not :focus — the composer is a container, and it should light up
   while you are typing anywhere inside it. */
.gpost-composer:focus-within{
  border-color: color-mix(in srgb, var(--accent, #22d9e6) 48%, transparent) !important;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.07),
              0 0 0 3px var(--accent-glow, rgba(34,217,230,.14)),
              0 12px 34px rgba(0,0,0,.30) !important;
}
.gcomp-text{
  background: transparent !important;
  border: none !important;
  outline: none !important;
  color: var(--text, #e9eef7) !important;
}
.gcomp-text::placeholder{ color: var(--muted-2, #475263) !important; }

/* Composer chips: quiet by default, accent on hover, so fourteen of them do not
   shout at once. */
.gpost-composer .gcomp-row button{
  background: var(--panel-2, rgba(255,255,255,.04)) !important;
  border: 1px solid var(--border-2, rgba(255,255,255,.06)) !important;
  color: var(--muted, #6b7a90) !important;
  font-weight: 600 !important;
  transition: border-color .13s ease, color .13s ease, background .13s ease;
}
@media (hover: hover){
  .gpost-composer .gcomp-row button:hover{
    border-color: color-mix(in srgb, var(--accent, #22d9e6) 40%, transparent) !important;
    color: var(--text, #e9eef7) !important;
    background: var(--accent-glow, rgba(34,217,230,.10)) !important;
  }
}
/* The Post button is the one primary action on the page — it should look like it. */
.gpost-composer button.gcomp-post,
.gpost-composer button[onclick*="createGuestPost"]{
  background: linear-gradient(135deg, var(--accent, #22d9e6), var(--accent-2, #0ea5b8)) !important;
  border: none !important;
  color: #06090f !important;
  box-shadow: 0 2px 14px var(--accent-glow, rgba(34,217,230,.30)) !important;
}
@media (hover: hover){
  .gpost-composer button.gcomp-post:hover,
  .gpost-composer button[onclick*="createGuestPost"]:hover{ filter: brightness(1.10); }
}
.gpost-composer button:active{ transform: scale(.97); }

/* ── Media inside a post ──────────────────────────────────────────────────── */
.gpost-img, .gpost-grid-img{
  border-radius: 12px !important;
  border: 1px solid var(--border-2, rgba(255,255,255,.05));
}

/* ── Comments ─────────────────────────────────────────────────────────────── */
.gpost-cmt{
  background: var(--panel-2, rgba(255,255,255,.03)) !important;
  border-radius: 12px !important;
  padding: 9px 12px !important;
}

/* ── Respect the accessibility switch: no lift, no transitions ────────────── */
body.reduce-motion .gpost,
body.reduce-motion .gpost:hover,
body.reduce-motion .gpost-rx-chip:hover{ transform: none !important; }

/* ── v9.10.613 — sidebar empty states ──────────────────────────────────────
   The Trending card used to ship three hard-coded fake hashtags that looked live,
   were not clickable, and never cleared on a quiet instance. An honest empty state
   with a next action is better than invented activity. */
.gsb-empty{ padding:14px 4px; text-align:center; }
.gsb-empty-t{ font:700 12px Outfit,system-ui,sans-serif; color:var(--text,#e9eef7); margin-bottom:3px; }
.gsb-empty-s{ font:11.5px Outfit,system-ui,sans-serif; color:var(--muted,#6b7a90); line-height:1.45; }
.gsb-empty-b{
  margin-top:10px; padding:6px 14px; border-radius:20px; cursor:pointer;
  font:700 11.5px Outfit,system-ui,sans-serif;
  background:var(--accent-glow,rgba(34,217,230,.14));
  border:1px solid var(--accent,#22d9e6);
  color:var(--accent,#22d9e6);
  transition:background .14s ease,color .14s ease;
}
@media (hover:hover){
  .gsb-empty-b:hover{ background:var(--accent,#22d9e6); color:#06090f; }
}

/* ── v9.10.614 — empty-state action button ─────────────────────────────────
   .empty-state existed with an icon, title and subtitle but no way to act. An
   empty room that only tells you it is empty is a dead end; one that points at
   the composer is an invitation. */
.empty-state .es-btn{
  margin-top:14px; padding:8px 18px; border-radius:20px; cursor:pointer;
  font:700 12px Outfit,system-ui,sans-serif;
  background:var(--accent-glow,rgba(34,217,230,.14));
  border:1px solid var(--accent,#22d9e6);
  color:var(--accent,#22d9e6);
  transition:background .14s ease,color .14s ease;
}
@media (hover:hover){
  .empty-state .es-btn:hover{ background:var(--accent,#22d9e6); color:#06090f; }
}

/* ── v9.10.615 — Space message room ────────────────────────────────────────
   Spaces were a shell with no composer. Now a real room; these are its messages. */
.gspace-msgs{ display:flex; flex-direction:column; gap:8px; padding:14px; overflow-y:auto; height:100%; }
.gspace-msg{
  align-self:flex-start; max-width:74%;
  background:var(--panel-2,rgba(255,255,255,.05));
  border:1px solid var(--border-2,rgba(255,255,255,.05));
  border-radius:14px 14px 14px 4px; padding:8px 12px;
}
.gspace-msg.mine{
  align-self:flex-end;
  background:linear-gradient(135deg,var(--accent,#22d9e6),var(--accent-2,#0ea5b8));
  border-color:transparent; color:#06090f;
  border-radius:14px 14px 4px 14px;
}
.gspace-msg-hd{ display:flex; gap:8px; align-items:baseline; margin-bottom:3px; }
.gspace-msg-hd b{ font:700 11.5px Outfit,system-ui,sans-serif; }
.gspace-msg-hd span{ font:10px Outfit,system-ui,sans-serif; opacity:.6; }
.gspace-msg-tx{ font:12.5px/1.5 Outfit,system-ui,sans-serif; white-space:pre-wrap; word-break:break-word; }

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.617 — PLATFORM CONVENTIONS

   Goal: someone arriving from Facebook, X or Instagram should find Oracle's
   controls where their muscle memory expects them. Oracle's feature set is
   Facebook-shaped — mutual friends, Spaces (groups), Stories, a per-post audience
   selector, emoji reactions on a hover picker, inline comments — so Facebook is
   the model. Repost is the one X import and is placed the way X places it.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── Top-bar search (was inside the post composer) ─────────────────────────────
   Facebook/LinkedIn keep search top-LEFT beside the logo; X keeps it top-right.
   Either way it is top chrome, always present, never inside a composer.

   Shown for BOTH social scopes. `scope-visitor` (signed out) is the one that
   matters most here — a newcomer browsing before they register is precisely the
   person who needs to find search where every other platform puts it. Deliberately
   NOT using the `.guest-only` helper: that class is visitor-blind, and its
   `body.scope-guest div.guest-only{display:block}` rule fights the flex layout. */
.tb-search-wrap{ display:none; position:relative; align-items:center; flex:0 1 260px; min-width:0; }
body.scope-guest .tb-search-wrap,
body.scope-visitor .tb-search-wrap{ display:flex; }
.tb-search{
  width:100%; padding:7px 12px 7px 32px; border-radius:999px;
  border:1px solid var(--border, rgba(255,255,255,.08));
  background:var(--panel-2, rgba(255,255,255,.04)); color:var(--text,#e9eef7);
  font:12.5px var(--ui),Inter,system-ui,sans-serif; outline:none;
  transition:border-color .15s, background .15s, box-shadow .15s;
}
.tb-search::placeholder{ color:var(--muted-2,#475263); }
.tb-search:focus{
  border-color:color-mix(in srgb, var(--accent,#22d9e6) 50%, transparent);
  background:var(--panel, rgba(13,19,32,.9));
  box-shadow:0 0 0 3px var(--accent-glow, rgba(34,217,230,.13));
}
.tb-search-icon{
  position:absolute; left:11px; top:50%; transform:translateY(-50%);
  opacity:.42; pointer-events:none; color:var(--text,#e9eef7);
}
/* The top bar is tight on small screens; search collapses there and `/` still
   reaches it. Below tablet the guest UI has its own navigation anyway. */
@media (max-width:900px){ body.scope-guest .tb-search-wrap{ display:none !important; } }

/* ── Rail shortcuts (Saved / Scheduled) — Facebook's left-rail shortcut list ── */
.gsb-shortcuts{
  display:flex; flex-direction:column; gap:2px;
  margin-top:10px; padding-top:10px;
  border-top:1px solid var(--border-2, rgba(255,255,255,.05));
}
.gsb-shortcut{
  display:flex; align-items:center; gap:10px; width:100%;
  padding:8px 10px; border:none; border-radius:9px; background:transparent;
  color:var(--muted,#6b7a90); font:600 12.5px var(--ui),Inter,sans-serif;
  cursor:pointer; text-align:left; transition:background .14s, color .14s;
}
.gsb-shortcut svg{ color:var(--accent,#22d9e6); flex:0 0 auto; opacity:.85; }
@media (hover:hover){
  .gsb-shortcut:hover{ background:var(--accent-glow, rgba(34,217,230,.10)); color:var(--text,#e9eef7); }
}
.gsb-shortcut:active{ transform:scale(.985); }
.gsb-shortcut:focus-visible{ outline:none; box-shadow:0 0 0 2px var(--accent,#22d9e6); }

/* ── Stats row: reactions LEFT, replies/shares RIGHT (Facebook's split) ────────
   The row is only rendered when at least one count is non-zero, so these rules
   never apply to an empty post. Overrides the flat `gap:14px` row above. */
.gpost-stats{
  display:flex !important; align-items:center; justify-content:space-between;
  gap:14px; flex-wrap:wrap;
}
.gps-l,.gps-r{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; min-width:0; }
.gps-r{ margin-left:auto; }
/* A figure that opens the thing it counts must LOOK clickable — the old row was
   `cursor:default` and inert, which teaches people not to try. */
.gpost-stats .gps-hit{ cursor:pointer; }
@media (hover:hover){
  .gpost-stats .gps-hit:hover{ color:var(--text,#e9eef7); text-decoration:underline; }
}
.gpost-stats .gps-hit:focus-visible{ outline:none; box-shadow:0 0 0 2px var(--accent,#22d9e6); border-radius:4px; }

/* ── Action row: 4 labelled primaries, then utilities ──────────────────────────
   Was six equal-width buttons. Facebook shows three (Like/Comment/Share),
   Instagram three plus a right-aligned Save, X four plus a trailing group —
   none of them show six of equal weight, which reads as a toolbar, not actions.
   Now: Like · Comment · Repost · Share carry labels and share the width; the
   emoji picker and Save are icon-only and pushed right, exactly where Instagram
   and X put Save. */
.gpa-util{ display:inline-flex; align-items:center; gap:2px; flex:0 0 auto; margin-left:4px; }
.gpost-acts .gpa-util button{ flex:0 0 auto; min-width:38px; padding:9px 10px; }
.gpx-wrap{ flex:1; }                 /* the Like wrapper must share width like a button */
.gpx-wrap > button{ width:100%; }
/* On mobile the labels are already hidden (font-size:0 above), so the four
   primaries are icons too — keep the utility pair from being cramped. */
@media (max-width:640px){
  .gpa-util{ margin-left:2px; }
  .gpost-acts .gpa-util button{ min-width:44px; }
}

/* ── v9.10.618 — composer "More" group ────────────────────────────────────────
   Three chips on the surface (Photo / Feeling / Poll), four behind More — the
   Facebook arrangement. `display:contents` when open so the chips stay direct
   flex children of .gcomp-actions and the row wraps exactly as it did before;
   a wrapper with its own `display:flex` would have created a second flex context
   and changed the wrap behaviour that v9.10.607 spent a pass getting right. */
.gcomp-more-group{ display:none; }
.gcomp-more-group.open{ display:contents; }
.gcomp-chip.chip-more svg{ color:#8fa3bd; }
.gcomp-chip.chip-more.on{ background:var(--accent-glow, rgba(34,217,230,.12)); color:var(--text,#e9eef7); }
.gcomp-chip.chip-more.on svg{ color:var(--accent,#22d9e6); }

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.621 — THE RIGHT RAIL: reachable, and honest about what it shows

   Ryan: "when i scroll down when my mouse is hovering over that container it
   should scroll down on that instead of ... the feed container, because i cant
   see all the things in that section on the side."

   The rail was `position:sticky; top:16px` with NO height limit and NO overflow,
   so once its cards were taller than the viewport the bottom simply could not be
   reached — sticky pins the top of the element, it does not make it scrollable.
   Radio, Stats and half of Suggested were unreachable at most window heights.
   ══════════════════════════════════════════════════════════════════════════════ */
@media (min-width:1100px){
  .guest-dash-grid .guest-col-right{
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    /* THE bit that answers the request: without this, once the rail hits its
       own end the wheel CHAINS to the page and the feed lurches. `contain`
       stops the scroll at this box's boundary, so the wheel does what the
       cursor says it should. */
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--border, rgba(255,255,255,.14)) transparent;
    padding-right: 4px;
  }
  /* A quiet scrollbar — the rail is secondary furniture and a bright track next
     to the feed reads as a second column of content. */
  .guest-dash-grid .guest-col-right::-webkit-scrollbar{ width:8px }
  .guest-dash-grid .guest-col-right::-webkit-scrollbar-track{ background:transparent }
  .guest-dash-grid .guest-col-right::-webkit-scrollbar-thumb{
    background: var(--border, rgba(255,255,255,.12)); border-radius:8px;
    border:2px solid transparent; background-clip:content-box;
  }
  .guest-dash-grid .guest-col-right:hover::-webkit-scrollbar-thumb{
    background: var(--muted-2, #475263); background-clip:content-box;
  }
  /* Last card should not butt against the bottom edge mid-scroll. */
  .guest-dash-grid .guest-col-right > :last-child{ margin-bottom:14px }
}

/* ── Presence rows: three real states, visibly different ──────────────────── */
.gsb-dot.online  { background:#4ade80; box-shadow:0 0 6px rgba(74,222,128,.65) }
.gsb-dot.idle    { background:#6b7a90; box-shadow:none }
.gsb-dot.sleeping{ background:#a78bfa; box-shadow:none; opacity:.75 }
.gsb-presence-row{ display:flex; align-items:center; gap:8px; padding:5px 2px; min-width:0 }
.gsb-presence-row.is-away{ opacity:.58 }        /* not around reads as not around */
@media (hover:hover){ .gsb-presence-row:hover{ opacity:1 } }
.gsb-pname{
  font:600 11.5px var(--ui),Inter,sans-serif; color:var(--accent);
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.gsb-presence-row.is-away .gsb-pname{ color:var(--muted, #6b7a90) }
.gsb-pwhere{
  color:var(--muted, #6b7a90); font-size:10px; margin-left:auto; flex-shrink:0;
  max-width:52%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.gsb-ai-badge{
  font-size:8px; padding:1px 4px; border-radius:3px; margin-left:4px;
  background:rgba(34,217,230,.12); color:var(--accent);
}

/* ══════════════════════════════════════════════════════════════════════════
   GAME CENTER (v9.10.636)  —  #view-games
   Everything is scoped under .gc-* so it cannot leak into the rest of the OS.
   Uses the existing design tokens only; no new colours are invented here.
   ══════════════════════════════════════════════════════════════════════════ */
#view-games-body{overflow:auto;padding:0}
.gc-wrap{display:flex;flex-direction:column;gap:14px;padding:18px 20px 40px;max-width:1240px;margin:0 auto;width:100%}
.gc-head{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.gc-title{font:600 20px var(--ui);color:var(--text);letter-spacing:.2px}
.gc-title span{font:400 12px var(--ui);color:var(--muted);margin-left:6px}
.gc-search{flex:1;min-width:180px;max-width:340px;background:var(--panel-2);border:1px solid var(--border);
  border-radius:10px;padding:9px 13px;color:var(--text);font:400 13px var(--ui);outline:none}
.gc-search:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}
.gc-count{font:400 11px var(--mono);color:var(--muted-2);margin-left:auto}

.gc-chips{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.gc-chip{background:rgba(255,255,255,.04);border:1px solid var(--border);color:var(--muted);
  border-radius:99px;padding:6px 13px;font:500 11.5px var(--ui);cursor:pointer;transition:.14s}
.gc-chip:hover{background:rgba(255,255,255,.08);color:var(--text)}
.gc-chip.on{background:var(--accent);border-color:var(--accent);color:#04070d}
.gc-chip-sp{flex:1;min-width:8px}

.gc-lobby{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:12px 14px}
.gc-lobby-h{font:600 11px var(--ui);letter-spacing:.9px;text-transform:uppercase;color:var(--muted);margin-bottom:9px}
.gc-lobby-l{display:flex;gap:8px;flex-wrap:wrap}
.gc-room{display:flex;align-items:center;gap:9px;background:rgba(255,255,255,.04);border:1px solid var(--border);
  border-radius:9px;padding:8px 12px;cursor:pointer;color:var(--text);font:400 12px var(--ui);transition:.14s}
.gc-room:hover{border-color:var(--accent);background:var(--accent-glow)}
.gc-room b{font-weight:600}
.gc-room span{color:var(--muted)}
.gc-room i{font:500 10.5px var(--mono);color:var(--accent);font-style:normal}
.gc-dim{color:var(--muted-2);font:400 12px var(--ui)}

.gc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:12px}
.gc-card{display:flex;gap:12px;align-items:flex-start;background:var(--c-card-bg);border:1px solid var(--border);
  border-radius:13px;padding:14px;cursor:pointer;transition:.16s;position:relative;overflow:hidden}
.gc-card::before{content:'';position:absolute;inset:0 auto 0 0;width:3px;background:var(--gc-accent,var(--accent));opacity:.55}
.gc-card:hover{background:var(--c-card-hover);border-color:var(--gc-accent,var(--accent));transform:translateY(-2px)}
.gc-card-ico{font-size:26px;line-height:1;flex:none;width:34px;text-align:center}
.gc-card-b{flex:1;min-width:0}
.gc-card-n{font:600 14px var(--ui);color:var(--text);margin-bottom:3px}
.gc-card-d{font:400 11.5px var(--ui);color:var(--muted);line-height:1.42;margin-bottom:8px}
.gc-card-m{display:flex;gap:5px;flex-wrap:wrap}
.gc-m{font:600 9px var(--ui);letter-spacing:.6px;text-transform:uppercase;border-radius:4px;padding:3px 6px;
  background:rgba(255,255,255,.06);color:var(--muted)}
.gc-m-ai{background:rgba(167,139,250,.16);color:var(--c-claudey)}
.gc-m-mp{background:rgba(74,222,128,.16);color:var(--good)}
.gc-card-s{flex:none;text-align:right;font:600 11px var(--mono);color:var(--accent)}
.gc-card-s i{display:block;font:400 9.5px var(--ui);color:var(--muted-2);font-style:normal;margin-top:2px}
.gc-empty{padding:40px;text-align:center;color:var(--muted-2);font:400 13px var(--ui)}

/* ── player surface ─────────────────────────────────────────────────────── */
.gc-stage{display:flex;flex-direction:column;flex:1;min-height:0;max-width:1100px;margin:0 auto;width:100%;padding:14px 18px 30px;gap:12px}
.gc-stage-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.gc-back{background:rgba(255,255,255,.05);border:1px solid var(--border);color:var(--text);border-radius:9px;
  padding:7px 13px;font:500 12px var(--ui);cursor:pointer}
.gc-back:hover{background:rgba(255,255,255,.09)}
.gc-stage-t{font:600 17px var(--ui);color:var(--text);display:flex;align-items:center;gap:9px}
.gc-stage-ico{font-size:20px}
.gc-modes{display:flex;gap:5px;margin-left:auto}
.gc-mode{background:rgba(255,255,255,.04);border:1px solid var(--border);color:var(--muted);border-radius:8px;
  padding:6px 12px;font:600 11px var(--ui);cursor:pointer;transition:.14s}
.gc-mode.on{background:var(--accent);border-color:var(--accent);color:#04070d}
.gc-sel{background:var(--panel-2);border:1px solid var(--border);color:var(--text);border-radius:8px;
  padding:6px 9px;font:500 11px var(--ui);cursor:pointer}
.gc-stage-body{display:flex;align-items:flex-start;justify-content:center;min-height:0;padding:6px 0}
.gc-stage-foot{display:flex;align-items:center;gap:12px;flex-wrap:wrap;border-top:1px solid var(--border-2);padding-top:11px}
.gc-foot-s{font:400 11.5px var(--mono);color:var(--muted);flex:1}
.gc-btn{background:rgba(255,255,255,.05);border:1px solid var(--border);color:var(--text);border-radius:8px;
  padding:8px 15px;font:500 12px var(--ui);cursor:pointer;transition:.14s}
.gc-btn:hover:not(:disabled){background:rgba(255,255,255,.1)}
.gc-btn:disabled{opacity:.34;cursor:default}
.gc-btn-primary{background:var(--accent);border-color:var(--accent);color:#04070d;font-weight:600}
.gc-board{width:100%;margin-top:10px;display:flex;flex-direction:column;gap:3px}
.gc-board-r{display:flex;align-items:center;gap:10px;font:400 12px var(--ui);color:var(--text);
  background:rgba(255,255,255,.03);border-radius:6px;padding:6px 11px}
.gc-board-r b{width:20px;color:var(--muted-2);font:600 11px var(--mono)}
.gc-board-r span{flex:1}
.gc-board-r i{font:600 12px var(--mono);color:var(--accent);font-style:normal}
.gc-err{padding:26px;text-align:center;color:var(--bad);font:400 13px var(--ui);line-height:1.6;max-width:460px}
.gc-wait{display:flex;flex-direction:column;align-items:center;gap:14px;padding:50px 20px}
.gc-wait-t{font:400 13px var(--ui);color:var(--muted);text-align:center}
.gc-spin{width:26px;height:26px;border:2px solid var(--border);border-top-color:var(--accent);
  border-radius:50%;animation:gcspin .8s linear infinite}
@keyframes gcspin{to{transform:rotate(360deg)}}

/* ── turn-based shell ───────────────────────────────────────────────────── */
.gc-turn{display:flex;flex-direction:column;align-items:center;gap:12px}
.gc-turn-status{font:500 13px var(--ui);color:var(--muted);min-height:19px;text-align:center}
.gc-turn-status.gc-over{color:var(--accent);font-weight:600}
.gc-turn-board{display:flex;justify-content:center}
.gc-turn-bar{display:flex;gap:8px}

.gc-g{display:grid;gap:4px}
.gc-c{background:rgba(255,255,255,.05);border:1px solid var(--border);border-radius:7px;color:var(--text);
  font:600 20px var(--ui);cursor:pointer;aspect-ratio:1;display:flex;align-items:center;justify-content:center;
  transition:.12s;padding:0}
.gc-c:hover:not(:disabled){background:var(--accent-glow);border-color:var(--accent)}
.gc-c:disabled{cursor:default}

.gc-g-t3{width:min(300px,80vw)}
.gc-g-t3 .gc-c{font-size:38px}
.gc-c-x{color:var(--accent)}
.gc-c-o{color:var(--c-amber)}

.gc-g-c4{width:min(430px,92vw);gap:5px;background:rgba(34,90,180,.15);padding:7px;border-radius:11px}
.gc-c4{border-radius:50%;background:var(--bg);border-color:var(--border-2)}
.gc-c4-R{background:#ef4444;border-color:#ef4444}
.gc-c4-Y{background:#facc15;border-color:#facc15}

.gc-g-ov{width:min(430px,92vw);gap:2px;background:rgba(20,80,50,.28);padding:5px;border-radius:9px}
.gc-ov{border-radius:4px;background:rgba(255,255,255,.03);border-color:transparent}
.gc-ov-B{background:#12161f;border:1px solid #000;border-radius:50%}
.gc-ov-W{background:#eef2f8;border:1px solid #cbd5e1;border-radius:50%}
.gc-ov-hint{background:rgba(74,222,128,.2);box-shadow:inset 0 0 0 1px rgba(74,222,128,.5)}

.gc-g-gm{width:min(500px,94vw);gap:1px;background:rgba(180,140,80,.16);padding:4px;border-radius:7px}
.gc-gm{border-radius:2px;font-size:11px;background:rgba(255,255,255,.02);border-color:transparent}
.gc-gm-on{background:rgba(255,255,255,.07)}

.gc-nim{display:flex;flex-direction:column;gap:14px;align-items:center;padding:10px}
.gc-nim-r{display:flex;gap:7px;min-height:44px;align-items:center}
.gc-nim-s{width:13px;height:44px;border-radius:3px;background:linear-gradient(180deg,#c8a06a,#8a6a42);
  border:1px solid rgba(0,0,0,.35);cursor:pointer;transition:.12s}
.gc-nim-s:hover:not(:disabled){transform:translateY(-4px);box-shadow:0 4px 10px rgba(0,0,0,.4)}

.gc-db{display:flex;flex-direction:column;padding:12px}
.gc-db-row,.gc-db-vrow{display:flex;align-items:center}
.gc-db-dot{width:10px;height:10px;border-radius:50%;background:var(--muted);flex:none}
.gc-db-h{width:44px;height:10px;border:none;background:rgba(255,255,255,.07);border-radius:3px;cursor:pointer;padding:0}
.gc-db-v{width:10px;height:44px;border:none;background:rgba(255,255,255,.07);border-radius:3px;cursor:pointer;padding:0}
.gc-db-h:hover:not(:disabled),.gc-db-v:hover:not(:disabled){background:var(--accent)}
.gc-db-h.on,.gc-db-v.on{background:var(--text)}
.gc-db-box{width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  font:700 15px var(--ui);color:transparent}
.gc-db-A{background:rgba(34,217,230,.2);color:var(--accent)}
.gc-db-B{background:rgba(251,191,36,.2);color:var(--warn)}

/* ── arcade shell ───────────────────────────────────────────────────────── */
.gc-arcade{display:flex;flex-direction:column;align-items:center;gap:10px;position:relative}
.gc-hud{display:flex;align-items:center;gap:8px;font:400 12px var(--ui);color:var(--muted);flex-wrap:wrap;justify-content:center}
.gc-hud-k{font:600 9.5px var(--ui);letter-spacing:.8px;text-transform:uppercase;color:var(--muted-2)}
.gc-hud b{font:600 15px var(--mono);color:var(--text)}
.gc-hud-dead{color:var(--bad);font-weight:600}
.gc-win{color:var(--good)!important;font-weight:600}
.gc-canvas{border:1px solid var(--border);border-radius:11px;max-width:100%;height:auto;
  background:#060a12;touch-action:none;display:block}
.gc-pause{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:rgba(4,7,13,.7);border-radius:11px;color:var(--text);font:500 14px var(--ui);pointer-events:none}
.gc-pad{display:none;gap:8px;margin-top:6px}
.gc-pad-b{width:52px;height:52px;border-radius:12px;background:rgba(255,255,255,.07);
  border:1px solid var(--border);color:var(--text);font-size:17px;cursor:pointer;
  -webkit-user-select:none;user-select:none;touch-action:manipulation}
@media (max-width:900px){.gc-pad{display:flex}}

/* ── individual puzzles ─────────────────────────────────────────────────── */
.gc-2048,.gc-ms,.gc-lo,.gc-sl,.gc-mem,.gc-si,.gc-rx,.gc-w5,.gc-an{display:flex;flex-direction:column;
  align-items:center;gap:11px}
.gc-2048-b{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;background:rgba(255,255,255,.04);
  padding:8px;border-radius:11px;width:min(380px,88vw)}
.gc-2048-t{aspect-ratio:1;border-radius:8px;background:rgba(255,255,255,.04);display:flex;align-items:center;
  justify-content:center;font:700 24px var(--ui);color:var(--text)}
.gc-2048-t.v2{background:#3b4252}.gc-2048-t.v4{background:#4c566a}
.gc-2048-t.v8{background:#0ea5b8;color:#04070d}.gc-2048-t.v16{background:#22d9e6;color:#04070d}
.gc-2048-t.v32{background:#4ade80;color:#04070d}.gc-2048-t.v64{background:#fbbf24;color:#04070d}
.gc-2048-t.v128{background:#f59e0b;color:#04070d;font-size:21px}
.gc-2048-t.v256{background:#fb923c;color:#04070d;font-size:21px}
.gc-2048-t.v512{background:#f87171;color:#04070d;font-size:21px}
.gc-2048-t.v1024{background:#a78bfa;color:#04070d;font-size:17px}
.gc-2048-t.v2048{background:#e9eef7;color:#04070d;font-size:17px}
.gc-2048-t.v4096{background:#fff;color:#04070d;font-size:17px}

.gc-g-ms{width:min(560px,94vw);gap:2px}
.gc-ms-c{background:rgba(255,255,255,.09);border:1px solid var(--border);border-radius:3px;aspect-ratio:1;
  font:700 13px var(--mono);cursor:pointer;color:var(--text);display:flex;align-items:center;justify-content:center;padding:0}
.gc-ms-c:hover:not(:disabled){background:rgba(255,255,255,.16)}
.gc-ms-c.open{background:rgba(255,255,255,.02);cursor:default}
.gc-ms-c.boom{background:var(--bad);color:#04070d}
.gc-ms-c.n1{color:#60a5fa}.gc-ms-c.n2{color:#4ade80}.gc-ms-c.n3{color:#f87171}
.gc-ms-c.n4{color:#a78bfa}.gc-ms-c.n5{color:#fbbf24}.gc-ms-c.n6{color:#22d9e6}
.gc-ms-c.n7{color:#e9eef7}.gc-ms-c.n8{color:#6b7a90}

.gc-g-lo{width:min(320px,80vw);gap:7px}
.gc-lo-c{border-radius:9px;background:rgba(255,255,255,.04)}
.gc-lo-c.on{background:var(--warn);border-color:var(--warn);box-shadow:0 0 16px rgba(251,191,36,.45)}

.gc-g-sl{width:min(340px,84vw);gap:6px}
.gc-sl-c{font:600 21px var(--mono);border-radius:9px}
.gc-sl-c.empty{background:transparent;border-color:transparent}

.gc-g-mem{width:min(460px,92vw);gap:7px}
.gc-mem-c{font-size:26px;border-radius:9px;background:rgba(255,255,255,.06)}
.gc-mem-c.up{background:var(--accent-glow);border-color:var(--accent)}
.gc-mem-c.done{opacity:.4}

.gc-g-si{width:min(280px,72vw);gap:10px}
.gc-si-p{border:none;border-radius:14px;aspect-ratio:1;cursor:pointer;opacity:.4;transition:opacity .1s}
.gc-si-p.lit{opacity:1;box-shadow:0 0 26px currentColor}

.gc-rx-p{width:min(420px,88vw);height:190px;border-radius:14px;border:1px solid var(--border);
  background:rgba(255,255,255,.05);color:var(--text);font:600 17px var(--ui);cursor:pointer}
.gc-rx-p.wait{background:var(--bad);color:#04070d}
.gc-rx-p.go{background:var(--good);color:#04070d}
.gc-rx-p.bad{background:var(--warn);color:#04070d}

.gc-w5-b{display:flex;flex-direction:column;gap:5px}
.gc-w5-r{display:flex;gap:5px}
.gc-w5-c{width:48px;height:48px;border:2px solid var(--border);border-radius:6px;display:flex;
  align-items:center;justify-content:center;font:700 21px var(--ui);color:var(--text)}
.gc-w5-c.fill{border-color:var(--muted)}
.gc-w5-c.g{background:var(--good);border-color:var(--good);color:#04070d}
.gc-w5-c.y{background:var(--warn);border-color:var(--warn);color:#04070d}
.gc-w5-c.x{background:rgba(255,255,255,.06);border-color:transparent;color:var(--muted-2)}
.gc-w5-kb{display:flex;flex-direction:column;gap:5px;align-items:center}
.gc-w5-kr{display:flex;gap:4px}
.gc-w5-k{min-width:31px;height:42px;border-radius:5px;border:1px solid var(--border);
  background:rgba(255,255,255,.07);color:var(--text);font:600 12px var(--ui);cursor:pointer;padding:0 6px}
.gc-w5-k.wide{min-width:46px}
.gc-w5-k.g{background:var(--good);color:#04070d;border-color:var(--good)}
.gc-w5-k.y{background:var(--warn);color:#04070d;border-color:var(--warn)}
.gc-w5-k.x{background:rgba(255,255,255,.02);color:var(--muted-2)}
.gc-w5-msg{font:500 12.5px var(--ui);color:var(--muted);min-height:18px;text-align:center}

.gc-an-q{font:700 34px var(--mono);letter-spacing:9px;color:var(--accent);padding:14px}
.gc-an-i{background:var(--panel-2);border:1px solid var(--border);border-radius:9px;padding:11px 15px;
  color:var(--text);font:400 16px var(--ui);outline:none;width:min(320px,84vw);text-align:center}
.gc-an-i:focus{border-color:var(--accent)}

@media (max-width:900px){
  .gc-wrap{padding:14px 12px 72px}
  .gc-stage{padding:10px 10px 20px;min-height:calc(100dvh - 160px)}
  .gc-stage-body{flex:1;align-items:center;justify-content:center}
  .gc-turn-board{max-height:78vw}
  .gc-grid{grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:9px}
  .gc-card{flex-direction:column;gap:8px;padding:12px}
  .gc-card-s{text-align:left}
  .gc-modes{margin-left:0;width:100%}
  .gc-w5-c{width:42px;height:42px;font-size:18px}
}

/* v9.10.637 — Game Center boot failure notice. See gcPaintOrExplain(). */
.gc-boot{margin:auto;text-align:center;padding:48px 24px;display:flex;flex-direction:column;gap:14px;align-items:center;max-width:520px}
.gc-boot-t{font:600 17px var(--ui);color:var(--warn)}
.gc-boot-d{font:400 13px var(--ui);color:var(--muted);line-height:1.65}
.gc-boot-d code{font:500 12px var(--mono);background:rgba(255,255,255,.07);padding:2px 6px;border-radius:4px;color:var(--text)}

/* ══════════════════════════════════════════════════════════════════════════
   GAME CENTER — FRAME, OVERLAY, MOTION & SCALE   (v9.10.638)   APPEND-ONLY
   ──────────────────────────────────────────────────────────────────────────
   WHY THIS BLOCK EXISTS
   The owner's report: "games ... dont have a them background to hold the Stuff
   as its floating in the ecosystem it seems and its kind of hard to see things
   with the container not styling the Game center". His screenshot showed a
   2048 board sitting on the bare OS background on a 1770px-wide screen — no
   surface behind it, the score line orphaned above it, and the board itself
   tiny (min(380px,88vw)) against all that empty space.

   Three fixes live here, in order:
     1. .gc-frame  — a real panel that CONTAINS a game: header (title + tools),
        padded body, stats foot. It reads as a surface, not floating text.
        .gc-overlay covers the play area from inside the frame for win/pause.
     2. Motion utilities (.gc-anim-in .gc-pop .gc-merge .gc-shake .gc-flash
        .gc-pulse) that the games add/remove from JS. All self-clearing.
     3. SCALE — every board width above was min(NNNpx, NNvw), which stops
        growing at a desktop-tiny cap. They are re-declared as
        min(NNvw, clamp(floor, NNvw, ceiling)) so they get meaningfully larger
        on desktop, still never exceed the viewport on a phone, and are also
        capped at 100% of the frame body in case the OS runs games in a
        narrow window (where vw would lie).

   Rules: appended AFTER the originals, so plain single-class overrides win on
   source order — do not raise specificity unless you must. Tokens only; the
   owner runs a red custom theme and every hardcoded hex would fight it.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE FRAME ────────────────────────────────────────────────────────── */
.gc-frame{
  position:relative;isolation:isolate;
  display:flex;flex-direction:column;
  width:100%;max-width:940px;margin:0 auto;
  background:
    radial-gradient(130% 90% at 50% -25%,var(--accent-glow),transparent 62%),
    linear-gradient(180deg,var(--panel-2),var(--panel));
  border:1px solid var(--border);
  border-radius:16px;
  box-shadow:0 24px 60px -28px rgba(0,0,0,.85),0 2px 8px -4px rgba(0,0,0,.6);
  overflow:hidden;
}
/* inner hairline + a faint accent bloom off the top edge, so the panel has
   depth without a second border fighting the theme's own border colour */
.gc-frame::before{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:0;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06),inset 0 0 50px -20px var(--accent);
}
.gc-frame>*{position:relative;z-index:1}
@media (min-width:1500px){.gc-frame{max-width:1120px}}

.gc-frame-head{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:12px 18px;min-height:56px;
  border-bottom:1px solid var(--border-2);
  background:linear-gradient(180deg,rgba(255,255,255,.035),transparent);
}
.gc-frame-title{
  display:flex;align-items:center;gap:9px;min-width:0;
  font:600 16px var(--ui);color:var(--text);letter-spacing:.2px;
}
.gc-frame-title .gc-stage-ico{font-size:21px;line-height:1}
.gc-frame-title small{font:400 11.5px var(--ui);color:var(--muted-2);letter-spacing:.3px}
.gc-frame-tools{display:flex;align-items:center;gap:6px;margin-left:auto;flex-wrap:wrap}
.gc-frame-head .gc-modes{margin-left:auto}
.gc-frame-head .gc-modes+.gc-frame-tools{margin-left:8px}
.gc-frame-head .gc-back,.gc-frame-head .gc-mode,.gc-frame-head .gc-sel{
  height:34px;display:inline-flex;align-items:center;padding-top:0;padding-bottom:0;
}

.gc-frame-body{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;width:100%;
  padding:clamp(16px,2.4vw,30px);
  min-height:clamp(340px,52vh,560px);
}
.gc-frame-body>*{max-width:100%}

.gc-frame-foot{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:11px 18px;min-height:50px;
  border-top:1px solid var(--border-2);
  background:rgba(0,0,0,.18);
}

/* FALLBACK — if the player is still rendered with the old .gc-stage shell
   (no .gc-frame anywhere inside), give the stage the same surface so the game
   is never naked on the background. Deactivates itself the moment a real
   .gc-frame exists. Browsers without :has() simply drop these rules. */
.gc-stage:not(:has(.gc-frame)){
  position:relative;max-width:940px;margin:18px auto 40px;padding:0;gap:0;overflow:hidden;
  background:
    radial-gradient(130% 90% at 50% -25%,var(--accent-glow),transparent 62%),
    linear-gradient(180deg,var(--panel-2),var(--panel));
  border:1px solid var(--border);border-radius:16px;
  box-shadow:0 24px 60px -28px rgba(0,0,0,.85),0 2px 8px -4px rgba(0,0,0,.6);
}
.gc-stage:not(:has(.gc-frame))>.gc-stage-head{
  padding:12px 18px;min-height:56px;border-bottom:1px solid var(--border-2);
  background:linear-gradient(180deg,rgba(255,255,255,.035),transparent);
}
.gc-stage:not(:has(.gc-frame))>.gc-stage-body{
  flex-direction:column;align-items:center;justify-content:center;gap:14px;
  padding:clamp(16px,2.4vw,30px);min-height:clamp(340px,52vh,560px);
}
.gc-stage:not(:has(.gc-frame))>.gc-stage-foot{
  padding:11px 18px;min-height:50px;padding-top:11px;margin:0;
  border-top:1px solid var(--border-2);background:rgba(0,0,0,.18);
}
@media (min-width:1500px){.gc-stage:not(:has(.gc-frame)){max-width:1120px}}

/* ── 2. OVERLAY (lives inside the frame, covers the play surface) ───────── */
.gc-overlay{
  position:absolute;inset:0;z-index:30;border-radius:inherit;
  display:flex;align-items:center;justify-content:center;padding:22px;
  background:rgba(4,7,13,.66);
  -webkit-backdrop-filter:blur(8px) saturate(.85);backdrop-filter:blur(8px) saturate(.85);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .2s ease,visibility 0s linear .2s;
}
.gc-overlay.on{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .2s ease,visibility 0s}
.gc-overlay-card{
  width:min(420px,100%);text-align:center;padding:26px 24px;
  background:linear-gradient(180deg,var(--panel-2),var(--panel-solid));
  border:1px solid var(--border);border-radius:14px;
  box-shadow:0 26px 60px -24px rgba(0,0,0,.9);
  transform:translateY(10px) scale(.97);
  transition:transform .22s cubic-bezier(.2,.8,.3,1);
}
.gc-overlay.on .gc-overlay-card{transform:none}
.gc-overlay-t{font:700 22px var(--ui);color:var(--text);letter-spacing:.2px;margin-bottom:8px}
.gc-overlay-t.win{color:var(--good)}
.gc-overlay-t.lose{color:var(--bad)}
.gc-overlay-t.draw{color:var(--warn)}
.gc-overlay-d{font:400 13.5px var(--ui);color:var(--muted);line-height:1.6;margin-bottom:18px}
.gc-overlay-d b{color:var(--text);font-weight:600}
.gc-overlay-btns{display:flex;gap:9px;justify-content:center;flex-wrap:wrap}

/* ── 3. SMALL ICON BUTTON (frame header tools) ──────────────────────────── */
.gc-icon-btn{
  width:34px;height:34px;flex:none;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.05);border:1px solid var(--border);border-radius:9px;
  color:var(--muted);font:500 15px var(--ui);line-height:1;cursor:pointer;
  transition:background .14s,border-color .14s,color .14s,transform .1s;
}
.gc-icon-btn:hover:not(:disabled){background:var(--accent-glow);border-color:var(--accent);color:var(--text)}
.gc-icon-btn:active:not(:disabled){transform:translateY(1px)}
.gc-icon-btn.on{background:var(--accent-glow);border-color:var(--accent);color:var(--accent)}
.gc-icon-btn:disabled{opacity:.34;cursor:default}
.gc-icon-btn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-glow)}

/* button ENHANCEMENT only — no background/colour here, the theme layer owns
   those with !important and must keep winning */
.gc-btn{transition:background .14s,border-color .14s,box-shadow .14s,transform .1s;letter-spacing:.2px}
.gc-btn:hover:not(:disabled){transform:translateY(-1px)}
.gc-btn:active:not(:disabled){transform:translateY(1px)}
.gc-btn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-glow)}
.gc-btn-primary{box-shadow:0 8px 20px -12px var(--accent)}

/* the score line was "lost above" the board — make it a real stat bar */
.gc-hud{
  gap:8px 16px;padding:9px 16px;border-radius:11px;
  background:var(--panel-2);border:1px solid var(--border-2);
  justify-content:center;
}
.gc-hud b{font-size:17px}

/* ── 4. MOTION UTILITIES (JS adds/removes; every one self-clears) ───────── */
@keyframes gcfxIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.gc-anim-in{animation:gcfxIn .26s cubic-bezier(.2,.8,.3,1) both}

@keyframes gcfxPop{0%{transform:scale(.3);opacity:.25}70%{transform:scale(1.09)}100%{transform:none;opacity:1}}
.gc-pop{animation:gcfxPop .18s cubic-bezier(.2,.9,.3,1.2)}

@keyframes gcfxMerge{0%{transform:scale(1)}45%{transform:scale(1.18);filter:brightness(1.55)}100%{transform:scale(1);filter:none}}
.gc-merge{animation:gcfxMerge .2s ease-out}

@keyframes gcfxShake{
  0%,100%{transform:translateX(0)}15%{transform:translateX(-7px)}30%{transform:translateX(6px)}
  45%{transform:translateX(-4px)}60%{transform:translateX(3px)}80%{transform:translateX(-2px)}}
.gc-shake{animation:gcfxShake .3s ease-in-out}

@keyframes gcfxFlash{
  0%{box-shadow:0 0 0 0 var(--accent-glow);filter:brightness(1)}
  25%{box-shadow:0 0 46px 6px var(--accent-glow);filter:brightness(1.25)}
  60%{box-shadow:0 0 18px 2px var(--accent-glow);filter:brightness(1.06)}
  100%{box-shadow:0 0 0 0 rgba(0,0,0,0);filter:none}}
.gc-flash{animation:gcfxFlash .6s ease-out}

@keyframes gcfxPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.72;transform:scale(1.035)}}
.gc-pulse{animation:gcfxPulse 1.6s ease-in-out infinite}

/* ── 5. SCALE: the boards were desktop-tiny ─────────────────────────────── */
/* never let a board outgrow the frame body, whatever vw says */
.gc-g,.gc-2048-b,.gc-w5-b,.gc-canvas,.gc-nim,.gc-db,.gc-rx-p{max-width:100%}

.gc-g-t3{width:min(86vw,clamp(300px,32vw,430px))}
.gc-g-t3 .gc-c{font-size:clamp(38px,6vw,78px)}
.gc-g-c4{width:min(94vw,clamp(340px,50vw,620px));gap:7px;padding:9px;border-radius:14px}
.gc-g-ov{width:min(94vw,clamp(330px,46vw,560px));gap:3px;padding:7px;border-radius:12px}
.gc-g-gm{width:min(95vw,clamp(340px,54vw,660px))}
.gc-g-gm .gc-gm{font-size:clamp(11px,1.4vw,17px)}
.gc-g-ms{width:min(95vw,clamp(340px,58vw,720px))}
.gc-ms-c{font-size:clamp(13px,1.5vw,19px)}
.gc-g-lo{width:min(88vw,clamp(300px,34vw,440px));gap:9px}
.gc-g-sl{width:min(90vw,clamp(320px,38vw,480px));gap:8px}
.gc-sl-c{font-size:clamp(21px,3vw,40px)}
.gc-g-mem{width:min(94vw,clamp(340px,48vw,600px));gap:9px}
.gc-mem-c{font-size:clamp(26px,3.4vw,46px)}
.gc-g-si{width:min(80vw,clamp(280px,28vw,380px))}
.gc-rx-p{width:min(92vw,clamp(360px,48vw,620px));height:clamp(190px,26vh,270px);font-size:clamp(17px,1.8vw,22px)}

.gc-2048-b{width:min(92vw,clamp(340px,44vw,560px));gap:10px;padding:10px;border-radius:14px}
.gc-2048-t{font-size:clamp(24px,3.2vw,42px);border-radius:10px}
.gc-2048-t.v128,.gc-2048-t.v256,.gc-2048-t.v512{font-size:clamp(21px,2.8vw,35px)}
.gc-2048-t.v1024,.gc-2048-t.v2048,.gc-2048-t.v4096{font-size:clamp(17px,2.2vw,28px)}

.gc-w5-c{width:clamp(48px,4.4vw,62px);height:clamp(48px,4.4vw,62px);font-size:clamp(21px,2.4vw,30px)}
.gc-w5-k{min-width:clamp(31px,3vw,44px);height:clamp(42px,4vw,52px);font-size:clamp(12px,1.2vw,15px)}

.gc-an-q{font-size:clamp(34px,4.6vw,58px)}
.gc-an-i{width:min(84vw,clamp(320px,32vw,440px));font-size:clamp(16px,1.6vw,20px)}

/* the arcade canvas has a fixed bitmap (600x600, 640x520, 400x640, 520x640).
   Driving HEIGHT with width:auto keeps every one of those aspect ratios; the
   object-fit is the safety net for the narrow-window case where max-width
   clips the box. */
@media (min-width:1000px){
  .gc-canvas{width:auto;height:clamp(400px,58vh,660px);max-width:100%;object-fit:contain}
}

/* ── 6. MOBILE ──────────────────────────────────────────────────────────── */
@media (max-width:900px){
  .gc-frame{max-width:100%;border-radius:14px}
  .gc-frame-head{padding:11px 13px;min-height:50px}
  .gc-frame-title{font-size:15px}
  .gc-frame-body{padding:14px 11px;min-height:280px;gap:11px}
  .gc-frame-foot{padding:10px 13px;min-height:46px}
  .gc-frame-tools{margin-left:auto}
  .gc-stage:not(:has(.gc-frame)){margin:10px auto 90px;border-radius:14px}
  .gc-stage:not(:has(.gc-frame))>.gc-stage-head{padding:11px 13px;min-height:50px}
  .gc-stage:not(:has(.gc-frame))>.gc-stage-body{padding:14px 11px;min-height:280px;gap:11px}
  .gc-stage:not(:has(.gc-frame))>.gc-stage-foot{padding:10px 13px;min-height:46px}
  .gc-overlay{padding:14px}
  .gc-overlay-card{padding:20px 16px}
  .gc-overlay-t{font-size:19px}
  .gc-hud{padding:8px 12px;gap:6px 11px}
  .gc-w5-c{width:42px;height:42px;font-size:18px}
  .gc-w5-k{min-width:30px;height:40px}
}

/* ── 7. REDUCED MOTION ──────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .gc-anim-in,.gc-pop,.gc-merge,.gc-shake,.gc-flash,.gc-pulse{animation:none!important}
  .gc-overlay{transition:opacity .01s linear,visibility 0s}
  .gc-overlay-card{transition:none;transform:none}
  .gc-btn:hover:not(:disabled),.gc-btn:active:not(:disabled),
  .gc-icon-btn:active:not(:disabled),.gc-card:hover,
  .gc-nim-s:hover:not(:disabled){transform:none}
}

/* ── v9.10.638 — teaching + progression hosts ────────────────────────────
   oracle-games-howto.js and oracle-games-progress.js style their OWN internals
   via injected <style>. These rules only give their mount points room to sit in
   the Game Center layout. */
.gc-prog-host{width:100%}
.gc-howto-host{width:100%;margin:14px 0 4px;text-align:left;max-height:min(56vh,520px);overflow:auto}
.gc-howto-compact{margin:10px 0 2px}
.gc-overlay-card:has(.gc-howto-host){max-width:min(680px,94vw)}
.gc-card{position:relative}
.gc-card-help{position:absolute;top:8px;right:8px;width:22px;height:22px;border-radius:50%;
  border:1px solid var(--border);background:rgba(255,255,255,.06);color:var(--muted);
  font:700 11px var(--ui);cursor:pointer;line-height:1;padding:0;opacity:0;transition:.15s;z-index:2}
.gc-card:hover .gc-card-help,.gc-card-help:focus{opacity:1}
.gc-card-help:hover{background:var(--accent);border-color:var(--accent);color:var(--bg);opacity:1}
@media (hover:none){.gc-card-help{opacity:.75}}

/* ══ v9.10.639 — overlay containment, reach, and size ══════════════════════
   MEASURED on a 1440x900 viewport with the Connect Four start card open:
     overlay  y=132 h=468 bottom=600
     card     y=30  h=692 bottom=722   <-- 224px taller than its own container
     Play     y=662                    <-- 62px BELOW the overlay box
   The card outgrew the overlay, .gc-frame{overflow:hidden} clipped the result,
   and the buttons ended up outside the box they belong to. The overlay must
   SCROLL and the card must be BOUNDED by it — an overlay that can overflow is
   an overlay whose buttons can become unreachable. */
.gc-overlay{overflow:auto;padding:18px;-webkit-overflow-scrolling:touch}
.gc-overlay-card{
  width:min(760px,94%);max-width:min(760px,94%);
  max-height:100%;display:flex;flex-direction:column;margin:auto;
  /* the card itself never scrolls — only its guide region does, so the action
     buttons stay pinned and visible no matter how long the content is */
  overflow:visible;
}
.gc-overlay-card>.gc-howto-host{flex:1 1 auto;min-height:0;max-height:none}
.gc-overlay-btns{flex:0 0 auto;margin-top:auto;padding-top:12px}

/* POINTER-EVENTS SAFETY NET. The blocker above was a parent left at
   pointer-events:none. Re-asserting it on the interactive descendants means a
   future regression up the tree can make the card look wrong but can never
   again make it impossible to press Play. */
.gc-overlay.on,.gc-overlay.on .gc-overlay-card,.gc-overlay.on .gc-btn,
.gc-overlay.on .gc-howto-host{pointer-events:auto}

/* The guide grid was collapsing to one word per line inside a 370px card. */
.gc-howto-host{max-height:none}
.gc-howto-compact{max-height:min(46vh,420px);overflow:auto}

/* ══ Bigger boards. The owner: "the size of the boxs are to small". ══════ */
@media (min-width:900px){
  .gc-2048-b{width:min(520px,60vh)}
  .gc-g-t3{width:min(420px,52vh)}
  .gc-g-c4{width:min(620px,64vh)}
  .gc-g-ov{width:min(600px,64vh)}
  .gc-g-gm{width:min(660px,68vh)}
  .gc-g-ms{width:min(720px,70vh)}
  .gc-g-lo{width:min(440px,52vh)}
  .gc-g-sl{width:min(460px,54vh)}
  .gc-g-mem{width:min(620px,62vh)}
  .gc-canvas{max-height:66vh;width:auto}
}

/* ══ v9.10.639 — .gc-frame CONTRAST ═══════════════════════════════════════
   The owner, twice: "they dont have a theme background to hold the Stuff as
   its floating in the ecosystem" and "i still dont see a container".
   MEASURED: the frame was NOT missing — it had a border, a 16px radius and a
   shadow. Its FILL was var(--panel) at 0.72 alpha sitting on a near-black page,
   so computed backgroundColor came back rgba(0,0,0,0) with only a faint
   gradient behind it. A container you cannot see is not a container.
   Fill it opaquely and let the accent glow ride on top. --panel-solid is a real
   token in every theme (#0a0f1b default, #140500 on the red theme), so this
   stays theme-correct. */
.gc-frame{
  background:
    radial-gradient(130% 90% at 50% -25%, var(--accent-glow), transparent 62%),
    linear-gradient(180deg, var(--panel-solid), var(--panel-solid));
  border:1px solid rgba(255,255,255,.13);
  box-shadow:0 28px 70px -30px rgba(0,0,0,.9), 0 2px 10px -5px rgba(0,0,0,.7),
             inset 0 1px 0 rgba(255,255,255,.05);
}
/* Head and foot become readable bands so the frame reads as a real panel with
   structure, instead of one flat rectangle. */
.gc-frame-head{background:linear-gradient(180deg,rgba(255,255,255,.05),transparent);
  border-bottom:1px solid var(--border)}
.gc-frame-foot{background:rgba(0,0,0,.26);border-top:1px solid var(--border)}
.gc-frame-body{background:rgba(0,0,0,.16)}

/* ══ v9.10.640 — SPECIFICITY CORRECTION ═══════════════════════════════════
   The frame element carries BOTH classes: <div class="gc-stage gc-frame">.
   An earlier block defines a fallback for a stage with no frame:
       .gc-stage:not(:has(.gc-frame)) { ... }
   but :has() tests DESCENDANTS, and the frame is the element itself, not a
   child of itself — so :not(:has(.gc-frame)) is TRUE on the very element that
   IS the frame. At 0,2,0 it outranks a plain .gc-frame (0,1,0), so the
   "no container" styling won every time and the real frame styling never
   applied. That is why the owner kept saying he could not see a container:
   the container rules were being beaten by the rules for not having one.
   Matching .gc-frame.gc-frame ties the specificity and wins on order.
   MEASURED before/after via getComputedStyle, not by eye. */
.gc-frame.gc-frame{
  background:
    radial-gradient(130% 90% at 50% -25%, var(--accent-glow), transparent 62%),
    linear-gradient(180deg, var(--panel-solid), var(--panel-solid));
  border:1px solid rgba(255,255,255,.14);
  border-radius:16px;
  box-shadow:0 28px 70px -30px rgba(0,0,0,.9), 0 2px 10px -5px rgba(0,0,0,.7),
             inset 0 1px 0 rgba(255,255,255,.06);
  overflow:hidden;
}
.gc-frame.gc-frame > .gc-frame-head,.gc-frame.gc-frame > .gc-stage-head{
  background:linear-gradient(180deg,rgba(255,255,255,.06),transparent);
  border-bottom:1px solid var(--border)}
.gc-frame.gc-frame > .gc-frame-foot,.gc-frame.gc-frame > .gc-stage-foot{
  background:rgba(0,0,0,.28);border-top:1px solid var(--border)}
.gc-frame.gc-frame > .gc-frame-body,.gc-frame.gc-frame > .gc-stage-body{
  background:rgba(0,0,0,.18)}

/* ══ v9.10.642 — USE THE SCREEN, AND SHOW LEGAL MOVES ═════════════════════
   Owner: "the screen for the games are way to small look how much room there
   could be" and "this game center should look more like a game system area
   ... like how xbox looks". MEASURED: the frame was capped at 940px inside a
   ~1430px content column on a 1901px display — roughly a third of the usable
   width thrown away. */
.gc-frame.gc-frame{max-width:min(1500px,97%)}
.gc-stage{max-width:none}
.gc-frame.gc-frame > .gc-frame-body{min-height:clamp(420px,64vh,860px);padding:clamp(18px,2.2vw,34px)}

/* Legal-move affordance. Othello already glowed its legal squares; nothing
   else did, so every other board silently swallowed illegal clicks. */
.gc-gm-ok{background:rgba(74,222,128,.14);box-shadow:inset 0 0 0 1px rgba(74,222,128,.42)}
.gc-gm-ok:hover{background:rgba(74,222,128,.28)}

/* Leaderboard inside the game menu */
.gc-board-host{max-height:min(48vh,420px);overflow:auto;text-align:left}
.gc-board-me{font:600 12px var(--ui);color:var(--accent);padding:6px 11px;margin-bottom:8px;
  background:var(--accent-glow);border-radius:7px}
.gc-board-r b{width:26px;font-size:13px}

/* ══ CONSOLE-STYLE LIBRARY ════════════════════════════════════════════════
   Bigger tiles, a large hero row, and art built from the accent colour so it
   reads as a game system shelf rather than a list of links. No image assets —
   the CSP forbids them — so the "art" is gradients keyed to each game accent. */
.gc-wrap{max-width:min(1600px,97%)}
.gc-grid{grid-template-columns:repeat(auto-fill,minmax(clamp(200px,17vw,268px),1fr));gap:16px}
.gc-card{flex-direction:column;align-items:stretch;gap:0;padding:0;overflow:hidden;min-height:186px}
.gc-card-ico{width:100%;height:104px;display:flex;align-items:center;justify-content:center;
  font-size:46px;background:
    radial-gradient(120% 130% at 50% 0%, var(--gc-accent,var(--accent)), transparent 68%),
    linear-gradient(180deg, rgba(255,255,255,.05), rgba(0,0,0,.35));
  filter:saturate(.9);text-shadow:0 4px 18px rgba(0,0,0,.55);transition:.22s}
.gc-card:hover .gc-card-ico{height:112px;filter:saturate(1.15) brightness(1.08)}
.gc-card-b{padding:12px 14px 14px}
.gc-card-n{font-size:14.5px}
.gc-card-d{-webkit-line-clamp:2;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden}
.gc-card-s{position:absolute;top:8px;left:10px;background:rgba(0,0,0,.55);border-radius:6px;
  padding:3px 7px;font-size:10px;backdrop-filter:blur(3px)}
.gc-card::before{width:100%;height:3px;inset:auto 0 0 0;opacity:.9}
@media (max-width:900px){
  .gc-card{min-height:150px}
  .gc-card-ico{height:76px;font-size:34px}
  .gc-frame.gc-frame{max-width:100%}
}

/* ══ v9.10.643 — playability affordances ══════════════════════════════════ */
/* Fifteen: only the tiles that can actually slide are live, and they show it. */
.gc-sl-c:disabled{opacity:.45}
.gc-sl-ok{box-shadow:inset 0 0 0 1px rgba(34,217,230,.45);background:rgba(34,217,230,.10)}
.gc-sl-ok:hover{background:rgba(34,217,230,.22)}

/* Memory Match: the peek, the size picker, and a board that uses the room. */
.gc-mem-sizes{display:flex;gap:6px;flex-wrap:wrap;justify-content:center;margin-bottom:4px}
.gc-mem-peek{color:var(--warn)!important;font-weight:700}
.gc-mem-peeking{animation:none!important}
.gc-g-mem{width:min(860px,88vw)}
@media (min-width:900px){.gc-g-mem{width:min(900px,72vh)}}
.gc-mem-c{font-size:clamp(20px,2.4vw,34px)}

/* Anagram Rush: real buttons so it is playable without a keyboard. */
.gc-an-bar{display:flex;gap:8px;justify-content:center;margin-top:4px}

/* ══ v9.10.644 — MORE ROWS, NOT BIGGER TILES; AND FIT THE FRAME ═══════════
   Owner: "i never said make them bigger i said make more rows and its also
   to large from the bottom being past the area with no padding".
   v9.10.643 scaled the BOARD up, which inflated every tile instead of adding
   rows, and the taller board then ran past the frame with nothing to scroll
   and no breathing room at the bottom. Cap the TILE and let the row count grow
   from the pair count; give the body real scroll and real padding. */
.gc-frame.gc-frame > .gc-frame-body{
  overflow:auto;
  padding:clamp(16px,2vw,28px) clamp(16px,2vw,28px) clamp(28px,3vw,44px);
  align-items:flex-start;
}
/* --cols is set by the game so the board width follows the COLUMN COUNT at a
   fixed tile size, instead of stretching a fixed width across the columns. */
.gc-g-mem{
  width:min(calc(var(--cols,6) * 76px), 94%);
  max-width:100%;
  gap:6px;
}
.gc-mem-c{font-size:clamp(15px,1.6vw,26px);border-radius:7px}
@media (min-width:900px){
  .gc-g-mem{width:min(calc(var(--cols,6) * 78px), 92%)}
}
@media (max-width:900px){
  .gc-g-mem{width:min(calc(var(--cols,6) * 52px), 96%);gap:4px}
  .gc-mem-c{font-size:clamp(13px,4vw,20px)}
}

/* CARD FLIP. Cards used to blink into existence; this turns them over. The
   half-turn scale keeps it readable without needing 3D perspective on a grid. */
@keyframes gcFlip{
  0%{transform:rotateY(-90deg) scale(.94);opacity:.35}
  55%{transform:rotateY(12deg) scale(1.04);opacity:1}
  100%{transform:rotateY(0) scale(1);opacity:1}
}
.gc-flip{animation:gcFlip .34s cubic-bezier(.3,1.3,.5,1) both;backface-visibility:hidden}
/* The opening peek turns the whole board over, staggered by column so it reads
   as a deal rather than one flat flash. */
@keyframes gcPeekIn{from{transform:rotateY(-80deg);opacity:0}to{transform:rotateY(0);opacity:1}}
.gc-mem-peeking{animation:gcPeekIn .30s ease-out both}
.gc-g-mem .gc-mem-peeking:nth-child(3n+2){animation-delay:.05s}
.gc-g-mem .gc-mem-peeking:nth-child(3n+3){animation-delay:.1s}
@media (prefers-reduced-motion:reduce){
  .gc-flip,.gc-mem-peeking{animation:none!important}
}

/* ══ v9.10.645 — the game WRAPPER was the constraint, not the board ═══════
   Two rounds of widening the board did nothing because .gc-frame-body is a
   flex row and its child wrappers shrink-wrap to content — so the board width
   min(444px, 96%) was resolving 96% against a ~365px parent, not the 1300px
   frame. Percentages are only as wide as what they are a percentage OF.
   Stretch the wrappers and centre their contents. */
.gc-frame.gc-frame > .gc-frame-body{justify-content:center}
.gc-frame.gc-frame > .gc-frame-body > *{width:100%;max-width:100%}
.gc-mem,.gc-2048,.gc-ms,.gc-lo,.gc-sl,.gc-si,.gc-rx,.gc-w5,.gc-an,.gc-turn,.gc-arcade{
  width:100%;display:flex;flex-direction:column;align-items:center}
.gc-g,.gc-turn-board,.gc-2048-b,.gc-w5-b{margin-left:auto;margin-right:auto}

/* ══ v9.10.648 — CONSOLE DASHBOARD: hero + shelf ══════════════════════════
   A console leads with one big thing you can start instantly and a shelf of
   what you were last playing. A flat A-Z grid makes you re-decide from
   scratch every visit. All art is gradient — the CSP blocks image files. */
.gc-hero{position:relative;display:flex;gap:clamp(16px,2.4vw,34px);align-items:stretch;
  border:1px solid rgba(255,255,255,.12);border-radius:16px;overflow:hidden;
  background:linear-gradient(120deg, var(--panel-solid), var(--panel-2));
  min-height:clamp(190px,23vw,260px)}
.gc-hero::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(90% 140% at 8% 0%, var(--gc-accent,var(--accent)), transparent 58%);
  opacity:.30}
.gc-hero-art{position:relative;z-index:1;flex:0 0 clamp(150px,20vw,290px);display:flex;
  align-items:center;justify-content:center;
  background:radial-gradient(80% 90% at 50% 40%, var(--gc-accent,var(--accent)), transparent 70%);
  border-right:1px solid rgba(255,255,255,.08)}
.gc-hero-art span{font-size:clamp(52px,7vw,104px);filter:drop-shadow(0 10px 26px rgba(0,0,0,.6))}
.gc-hero-b{position:relative;z-index:1;flex:1;min-width:0;display:flex;flex-direction:column;
  justify-content:center;gap:8px;padding:clamp(16px,2vw,28px) clamp(16px,2vw,30px) clamp(16px,2vw,28px) 0}
.gc-hero-k{font:700 10px var(--ui);letter-spacing:1.6px;text-transform:uppercase;color:var(--accent)}
.gc-hero-n{font:700 clamp(22px,2.8vw,38px) var(--ui);color:var(--text);line-height:1.1}
.gc-hero-d{font:400 13.5px var(--ui);color:var(--muted);max-width:62ch}
.gc-hero-m{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.gc-hero-s{font:500 11px var(--mono);color:var(--muted-2);margin-left:4px}
.gc-hero-btns{display:flex;gap:9px;margin-top:6px;flex-wrap:wrap}
.gc-hero-play{font-size:14px;padding:11px 26px}

.gc-shelf{margin-top:4px}
.gc-shelf-h{font:700 10.5px var(--ui);letter-spacing:1.4px;text-transform:uppercase;
  color:var(--muted);margin-bottom:9px}
.gc-shelf-r{display:flex;gap:10px;overflow-x:auto;padding-bottom:6px;scrollbar-width:thin}
.gc-shelf-c{flex:0 0 auto;width:112px;display:flex;flex-direction:column;align-items:center;
  gap:7px;padding:12px 8px;border-radius:12px;cursor:pointer;color:var(--text);
  border:1px solid var(--border);background:var(--c-card-bg);transition:.16s}
.gc-shelf-c:hover{border-color:var(--gc-accent,var(--accent));transform:translateY(-3px);
  background:var(--c-card-hover)}
.gc-shelf-i{font-size:30px;line-height:1}
.gc-shelf-n{font:600 11px var(--ui);text-align:center;line-height:1.25}

@media (max-width:900px){
  .gc-hero{flex-direction:column;min-height:0}
  .gc-hero-art{flex:0 0 110px;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}
  .gc-hero-b{padding:16px}
  .gc-shelf-c{width:92px}
}

/* ══ v9.10.649 — resume affordances ═══════════════════════════════════════ */
.gc-hero-r{font:600 11.5px var(--ui);color:var(--good);display:flex;align-items:center;gap:6px}
.gc-hero-r::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--good);
  box-shadow:0 0 9px var(--good)}
.gc-resume-note{color:var(--good)!important;font-weight:600}
.gc-shelf-t{font:500 9.5px var(--mono);color:var(--muted-2);text-align:center}
.gc-shelf-res{border-color:rgba(74,222,128,.34)}
.gc-shelf-res .gc-shelf-t{color:var(--good)}
.gc-shelf-res::after{content:"";position:absolute;top:7px;right:7px;width:6px;height:6px;
  border-radius:50%;background:var(--good);box-shadow:0 0 8px var(--good)}
.gc-shelf-c{position:relative}

/* ══ v9.10.650 — Achievements + Daily challenge panels ════════════════════ */
.gc-head-acts{display:flex;gap:7px;margin-left:auto}
.gc-headbtn{display:flex;align-items:center;gap:6px;background:rgba(255,255,255,.05);
  border:1px solid var(--border);color:var(--text);border-radius:9px;padding:7px 13px;
  font:600 11.5px var(--ui);cursor:pointer;transition:.15s;white-space:nowrap}
.gc-headbtn:hover{background:rgba(255,255,255,.1);border-color:var(--accent)}
.gc-headbtn b{font:700 10.5px var(--mono);color:var(--accent)}
.gc-headbtn-done{border-color:rgba(74,222,128,.45)}
.gc-headbtn-done span{color:var(--good)}

.gc-modal{position:fixed;inset:0;z-index:120;display:flex;align-items:center;
  justify-content:center;padding:22px;background:rgba(4,7,13,.72);backdrop-filter:blur(5px)}
.gc-modal-card{width:min(760px,96%);max-height:88vh;display:flex;flex-direction:column;
  background:var(--panel-solid);border:1px solid rgba(255,255,255,.14);border-radius:16px;
  box-shadow:0 30px 80px -30px rgba(0,0,0,.95);overflow:hidden}
.gc-modal-head{display:flex;align-items:center;gap:12px;padding:15px 18px;
  border-bottom:1px solid var(--border);background:linear-gradient(180deg,rgba(255,255,255,.05),transparent)}
.gc-modal-t{font:700 16px var(--ui);color:var(--text);flex:1}
.gc-modal-t span{font:500 11.5px var(--mono);color:var(--muted);margin-left:9px}
.gc-modal-b{padding:16px 18px 22px;overflow:auto}

.gc-ach-top{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.gc-ach-bar{flex:1;height:8px;border-radius:99px;background:rgba(255,255,255,.07);overflow:hidden}
.gc-ach-bar i{display:block;height:100%;border-radius:99px;
  background:linear-gradient(90deg,var(--accent-2),var(--accent))}
.gc-ach-pct{font:700 13px var(--mono);color:var(--accent);min-width:42px;text-align:right}
.gc-ach-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:9px}
.gc-ach{display:flex;gap:11px;align-items:flex-start;padding:11px 13px;border-radius:11px;
  background:rgba(255,255,255,.03);border:1px solid var(--border-2)}
.gc-ach.earned{background:rgba(74,222,128,.08);border-color:rgba(74,222,128,.28)}
.gc-ach-i{font-size:22px;line-height:1;flex:none;width:28px;text-align:center;opacity:.55}
.gc-ach.earned .gc-ach-i{opacity:1}
.gc-ach-b{flex:1;min-width:0}
.gc-ach-t{font:600 12.5px var(--ui);color:var(--text)}
.gc-ach-d{font:400 11px var(--ui);color:var(--muted);margin-top:2px;line-height:1.4}
.gc-ach-p{height:5px;border-radius:99px;background:rgba(255,255,255,.07);overflow:hidden;margin-top:7px}
.gc-ach-p i{display:block;height:100%;border-radius:99px;background:var(--accent);min-width:2px}
.gc-ach-n{font:500 9.5px var(--mono);color:var(--muted-2);margin-top:3px}
.gc-ach-ok{color:var(--good);font-size:15px;font-weight:700;flex:none}

.gc-daily{display:flex;gap:14px;align-items:flex-start;padding:16px;border-radius:13px;
  background:radial-gradient(120% 140% at 0% 0%, var(--accent-glow), transparent 62%), rgba(255,255,255,.03);
  border:1px solid var(--border)}
.gc-daily.done{border-color:rgba(74,222,128,.4)}
.gc-daily-i{font-size:38px;line-height:1;flex:none}
.gc-daily-b{flex:1;min-width:0}
.gc-daily-t{font:600 15px var(--ui);color:var(--text)}
.gc-daily-x{font:700 11px var(--mono);color:var(--accent);margin:4px 0 9px}
.gc-daily.done .gc-daily-x{color:var(--good)}
.gc-daily-go{margin-top:14px;width:100%;padding:12px}
.gc-daily-meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px;margin-top:14px}
.gc-daily-m{padding:11px 13px;border-radius:10px;background:rgba(255,255,255,.03);
  border:1px solid var(--border-2);display:flex;flex-direction:column;gap:3px}
.gc-daily-m b{font:700 13px var(--ui);color:var(--text)}
.gc-daily-m span{font:400 10.5px var(--ui);color:var(--muted)}
.gc-daily-note{margin-top:14px;font-size:11px;line-height:1.6}
@media (max-width:900px){
  .gc-head-acts{margin-left:0;width:100%}
  .gc-headbtn span{display:none}
  .gc-ach-grid{grid-template-columns:1fr}
}

/* ══ v9.10.651 — audio controls in the library menu ═══════════════════════ */
.gc-audio-set{display:flex;align-items:center;gap:6px;padding-left:6px;
  margin-left:2px;border-left:1px solid var(--border)}
.gc-audio-b.gc-audio-off{opacity:.55;border-color:var(--border-2)}
.gc-audio-b.gc-audio-off span{color:var(--muted-2)}
.gc-vol{width:84px;height:4px;-webkit-appearance:none;appearance:none;cursor:pointer;
  background:rgba(255,255,255,.12);border-radius:99px;outline:none}
.gc-vol::-webkit-slider-thumb{-webkit-appearance:none;width:13px;height:13px;border-radius:50%;
  background:var(--accent);cursor:pointer;box-shadow:0 0 8px var(--accent-glow)}
.gc-vol::-moz-range-thumb{width:13px;height:13px;border:none;border-radius:50%;
  background:var(--accent);cursor:pointer}
.gc-vol:disabled{opacity:.35;cursor:default}
.gc-vol:disabled::-webkit-slider-thumb{background:var(--muted-2);box-shadow:none}
@media (max-width:900px){
  .gc-audio-set{border-left:none;padding-left:0;width:100%;justify-content:flex-start}
  .gc-vol{width:70px}
}

/* ══════════════════════════════════════════════════════════════════════════
   GAME CENTER — SETTINGS PANEL + MEMORY MATCH CAMPAIGN   (v9.10.652)
   APPEND-ONLY. Nothing above this line was edited.
   ──────────────────────────────────────────────────────────────────────────
   WHY THIS BLOCK EXISTS
   The owner asked for two things the Game Center had no surface for:

     1. "add a settings panel for the game center" — sound/music/volume,
        AI difficulty, hints, timers, the Memory Match peek length, and the
        destructive rows (clear saves / reset progress). Until now the only
        audio controls were the three cramped widgets in the library header
        (.gc-audio-set, v9.10.651); everything else was unreachable.
     2. A Memory Match CAMPAIGN — a peek countdown, a running game timer that
        feeds the score, Candy-Crush-style perks, and a stage ladder with
        1-3 stars per stage.

   Two other units are writing the JS for those, blind to this file, so every
   class named in the shared contract is implemented here and no others are
   invented. Where the DOM shape is genuinely unknowable (is .gc-set-help a
   sibling of .gc-set-lab or a child of a wrapper? is the switch <button>
   empty or does it hold a label?) the rules are written to be correct EITHER
   WAY rather than betting on one shape — see the notes at each such rule.

   THE THEME TRAP, and why some rules below carry !important.
   Line ~6252 and the per-theme blocks (~211 for Dragon's Breath, the owner's
   red theme) style EVERY `button.gc-btn` with a gradient background and a
   fixed text colour, using !important. Any new control that also carries
   .gc-btn — a segmented option, a perk, a switch — would be repainted as a
   solid primary button and its selected/unselected states would become
   indistinguishable. The neutraliser at the end of this block outranks those
   rules on specificity (0,4,1 vs 0,2,2) and hands the on-state back.

   Tokens only. --bg/--accent/--good/--bad/--warn/--star all move with the
   theme; a hardcoded hex would fight the red palette on every screen.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. SETTINGS PANEL ───────────────────────────────────────────────────── */
/* Lives inside the existing .gc-modal-card > .gc-modal-b, which already owns
   the padding and the scroll. This is only the rhythm inside it. */
.gc-set{display:flex;flex-direction:column;gap:14px;width:100%;text-align:left}

.gc-set-g{
  background:linear-gradient(180deg,rgba(255,255,255,.035),rgba(0,0,0,.14));
  border:1px solid var(--border);border-radius:13px;
  padding:2px 15px 6px;
}
.gc-set-gh{
  padding:12px 0 9px;margin-bottom:2px;
  border-bottom:1px solid var(--border-2);
  font:700 10px var(--ui);letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);
}

.gc-set-row{
  display:flex;align-items:center;justify-content:space-between;
  gap:10px 16px;flex-wrap:wrap;
  padding:12px 0;border-bottom:1px solid var(--border-2);
}
.gc-set-row:last-child{border-bottom:none}
/* The label side takes the slack; it shrinks to a 150px basis before wrapping. */
.gc-set-row>:first-child{flex:1 1 150px;min-width:0}
/* The control side is whichever of these it turns out to be, so the row is
   right-aligned whether the settings unit emits a switch, a segmented control,
   a bare <button>, a <select> or an <input>. */
.gc-set-row>.gc-switch,
.gc-set-row>.gc-set-seg,
.gc-set-row>.gc-set-confirm,
.gc-set-row>button,
.gc-set-row>select,
.gc-set-row>input{flex:0 0 auto;margin-left:auto}

.gc-set-lab{font:600 13px var(--ui);color:var(--text);line-height:1.35}
/* Two shapes supported. As a BLOCK under the label (wrapped in a div with it)
   the margin-top does the work; as a direct FLEX CHILD of the row it takes a
   full-width basis and is ordered last, so it lands on its own line beneath
   the label+control pair instead of squeezing between them. */
.gc-set-help{font:400 11px var(--ui);color:var(--muted);line-height:1.5;margin-top:4px;max-width:60ch}
/* max-width MUST be released here. MEASURED: with `max-width:60ch` still in
   force the flex algorithm clamps the item's hypothetical main size to ~432px
   BEFORE it decides line breaks, so `flex-basis:100%` never overflows the line
   and the help text sat between the label and the switch instead of under
   them (label x=322 w=178, switch x=516, help x=580 — all on one row). A
   flex-basis of 100% only breaks the line if nothing shrinks it first. */
.gc-set-row>.gc-set-help{flex:1 0 100%;max-width:100%;order:9;margin-top:2px}

/* ── segmented control ───────────────────────────────────────────────────── */
.gc-set-seg{
  display:inline-flex;align-items:center;gap:3px;padding:3px;
  border-radius:11px;background:rgba(255,255,255,.05);border:1px solid var(--border);
  max-width:100%;flex-wrap:wrap;
}
.gc-set-seg button{
  -webkit-appearance:none;appearance:none;border:1px solid transparent;background:transparent;
  color:var(--muted);font:600 11.5px var(--ui);letter-spacing:.2px;white-space:nowrap;
  padding:7px 13px;min-height:34px;border-radius:9px;cursor:pointer;
  transition:background .15s ease,color .15s ease,box-shadow .15s ease;
}
.gc-set-seg button:hover:not(.on):not(:disabled){background:rgba(255,255,255,.08);color:var(--text)}
.gc-set-seg button.on{
  background:var(--accent);color:var(--bg);border-color:var(--accent);
  box-shadow:0 5px 16px -9px var(--accent);
}
.gc-set-seg button:disabled{opacity:.4;cursor:default}
.gc-set-seg button:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-glow)}

/* ── switch ──────────────────────────────────────────────────────────────── */
/* Built from a <button role="switch">. The knob is ::after so an EMPTY button
   still renders one; if the unit instead nests an element to act as the knob,
   that child is visually hidden (not display:none) so it stays in the
   accessibility tree and the ::after knob is the single source of truth. Any
   bare text node inside collapses to nothing via font-size:0. */
.gc-switch{
  position:relative;flex:none;-webkit-appearance:none;appearance:none;
  width:48px;height:27px;padding:0;border-radius:99px;cursor:pointer;
  border:1px solid var(--border);background:rgba(255,255,255,.09);
  font-size:0;line-height:0;color:transparent;overflow:hidden;
  transition:background .18s ease,border-color .18s ease,box-shadow .18s ease;
}
.gc-switch::after{
  content:"";position:absolute;top:50%;left:3px;
  /* 99px, not 50%: the press state below widens the knob to 23px against a
     fixed 19px height, and a 50% radius on a 23x19 box draws an ellipse.
     A large px radius keeps it a circle at rest and a pill while pressed. */
  width:19px;height:19px;border-radius:99px;transform:translateY(-50%);
  background:var(--muted);box-shadow:0 2px 6px rgba(0,0,0,.55);
  transition:left .22s cubic-bezier(.3,1.5,.5,1),right .22s cubic-bezier(.3,1.5,.5,1),
             background .18s ease,width .12s ease;
}
.gc-switch.on{background:var(--accent);border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}
.gc-switch.on::after{left:auto;right:3px;background:var(--bg);box-shadow:0 2px 7px rgba(0,0,0,.45)}
.gc-switch:active:not(:disabled)::after{width:23px}
.gc-switch:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-glow)}
.gc-switch:disabled{opacity:.4;cursor:default}
.gc-switch>*{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;
  overflow:hidden;white-space:nowrap;clip-path:inset(50%);
}

/* ── destructive rows ────────────────────────────────────────────────────── */
/* A block of its own inside the group card rather than a tinted table row, so
   it cannot be mistaken for the setting above it. */
.gc-set-row.gc-set-danger,
.gc-set-danger{
  margin:9px 0;padding:12px 13px;border-radius:11px;
  background:linear-gradient(90deg,rgba(248,113,113,.10),transparent 72%);
  border:1px solid rgba(248,113,113,.28);
}
.gc-set-danger .gc-set-lab{color:var(--bad)}
.gc-set-danger>button{
  border:1px solid rgba(248,113,113,.45);background:rgba(248,113,113,.12);
  color:var(--bad);font:600 11.5px var(--ui);border-radius:9px;padding:8px 14px;
  min-height:34px;cursor:pointer;transition:background .15s ease,border-color .15s ease;
}
.gc-set-danger>button:hover:not(:disabled){background:rgba(248,113,113,.24);border-color:var(--bad)}
.gc-set-danger>button:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(248,113,113,.3)}

/* The "are you sure" state, which replaces the button in place. Every button
   inside reads as destructive-outline, and whichever one the unit marks
   .gc-btn-primary becomes the solid commit — so this is correct regardless of
   whether the confirm or the cancel is emitted first. */
@keyframes gcSetConfirmIn{from{opacity:0;transform:translateX(6px)}to{opacity:1;transform:none}}
.gc-set-confirm{
  display:inline-flex;align-items:center;gap:7px;flex-wrap:wrap;
  padding:5px 6px 5px 12px;border-radius:11px;
  background:rgba(248,113,113,.13);border:1px solid rgba(248,113,113,.42);
  font:700 11px var(--ui);letter-spacing:.3px;color:var(--bad);
  animation:gcSetConfirmIn .18s ease-out both;
}
.gc-set-confirm button{
  -webkit-appearance:none;appearance:none;
  border:1px solid rgba(248,113,113,.45);background:rgba(0,0,0,.22);color:var(--bad);
  font:600 11px var(--ui);border-radius:8px;padding:6px 11px;min-height:30px;cursor:pointer;
  transition:background .14s ease,color .14s ease;
}
.gc-set-confirm button:hover{background:rgba(248,113,113,.26)}
.gc-set-confirm button:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(248,113,113,.32)}
.gc-set-confirm .gc-btn-primary{background:var(--bad);border-color:var(--bad);color:var(--bg)}
.gc-set-confirm .gc-btn-primary:hover{background:var(--bad);filter:brightness(1.1)}

/* ── 2. MEMORY MATCH CAMPAIGN ────────────────────────────────────────────── */
/* .gc-mem is a centred flex column (see v9.10.645), so anything that should
   span the play area has to say width:100% for itself. */

/* HUD — the peek countdown before the board, the game timer after it. */
.gc-mem-hud{
  display:flex;align-items:center;justify-content:center;gap:8px 20px;flex-wrap:wrap;
  width:100%;max-width:560px;margin:0 auto;padding:10px 18px;
  border-radius:12px;background:var(--panel-2);border:1px solid var(--border-2);
  font:600 11px var(--ui);letter-spacing:.9px;text-transform:uppercase;color:var(--muted);
  text-align:center;min-height:52px;
}

/* The big peek number. The pulse is a one-per-second heartbeat so the count
   reads as ticking even though CSS cannot see the text change. */
@keyframes gcMemCount{0%{transform:scale(1.14);opacity:1}45%{transform:scale(1);opacity:1}100%{transform:scale(1);opacity:.82}}
.gc-mem-count{
  font:700 clamp(34px,7vw,60px) var(--mono);line-height:1;
  color:var(--accent);font-variant-numeric:tabular-nums;letter-spacing:1px;
  text-transform:none;
  filter:drop-shadow(0 0 18px var(--accent-glow));
  animation:gcMemCount 1s ease-out infinite;
}

@keyframes gcMemLow{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.05)}}
.gc-mem-timer{
  font:700 clamp(17px,2.1vw,23px) var(--mono);line-height:1;color:var(--text);
  font-variant-numeric:tabular-nums;letter-spacing:.6px;text-transform:none;
  transition:color .25s ease;
}
.gc-mem-timer.low{color:var(--warn);animation:gcMemLow 1s ease-in-out infinite}

/* PERKS — the Candy-Crush-style bar. */
.gc-mem-perks{
  display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap;
  width:100%;max-width:660px;margin:2px auto 0;
}
.gc-mem-perk{
  position:relative;display:inline-flex;align-items:center;gap:8px;
  min-height:42px;padding:8px 13px;border-radius:12px;cursor:pointer;
  border:1px solid var(--border);color:var(--text);
  background:linear-gradient(180deg,rgba(255,255,255,.07),rgba(0,0,0,.2));
  font:600 11.5px var(--ui);letter-spacing:.2px;white-space:nowrap;
  transition:background .16s ease,border-color .16s ease,box-shadow .16s ease,transform .12s ease;
}
.gc-mem-perk:hover:not(:disabled){
  border-color:var(--accent);background:var(--accent-glow);transform:translateY(-2px);
  box-shadow:0 10px 22px -14px var(--accent);
}
.gc-mem-perk:active:not(:disabled){transform:translateY(0)}
.gc-mem-perk:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-glow)}
/* the remaining-charges pill */
.gc-mem-perk b{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:20px;height:20px;padding:0 6px;border-radius:99px;
  background:var(--accent);color:var(--bg);
  font:700 10.5px var(--mono);line-height:1;font-variant-numeric:tabular-nums;
}
.gc-mem-perk:disabled{opacity:.42;cursor:default;filter:grayscale(.8)}
.gc-mem-perk:disabled b{background:var(--muted-2);color:var(--text)}
/* armed / selected, without inventing a class name */
.gc-mem-perk[aria-pressed="true"]{
  border-color:var(--accent);background:var(--accent-glow);
  box-shadow:0 0 0 2px var(--accent-glow),0 10px 22px -14px var(--accent);
}

/* STAGES — the ladder. auto-fill keeps 3 tiles per row at 375px and grows to
   7-8 on a desktop frame without ever needing a breakpoint per width. */
.gc-mem-stages{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(clamp(78px,20vw,116px),1fr));
  gap:10px;width:100%;max-width:920px;margin:0 auto;
}
.gc-mem-stage{
  position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:6px;aspect-ratio:1/1;min-height:78px;padding:9px 6px;
  border-radius:14px;cursor:pointer;overflow:hidden;
  border:1px solid var(--border);color:var(--text);
  background:linear-gradient(180deg,rgba(255,255,255,.06),rgba(0,0,0,.26));
  font:700 clamp(15px,2.2vw,21px) var(--mono);line-height:1.1;text-align:center;
  transition:border-color .16s ease,background .16s ease,box-shadow .16s ease,transform .12s ease;
}
.gc-mem-stage:hover:not(.locked){
  border-color:var(--accent);transform:translateY(-3px);
  box-shadow:0 14px 28px -18px var(--accent);
}
.gc-mem-stage:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-glow)}
.gc-mem-stage.locked{
  opacity:.42;cursor:default;color:var(--muted-2);border-color:var(--border-2);
  background:rgba(255,255,255,.02);
}
.gc-mem-stage.locked:hover{transform:none;box-shadow:none}
@keyframes gcMemCurrent{0%,100%{box-shadow:0 0 0 2px var(--accent-glow)}50%{box-shadow:0 0 0 5px var(--accent-glow)}}
.gc-mem-stage.current{
  border-color:var(--accent);color:var(--text);
  background:radial-gradient(120% 110% at 50% 0%,var(--accent-glow),transparent 66%),
             linear-gradient(180deg,rgba(255,255,255,.07),rgba(0,0,0,.26));
  animation:gcMemCurrent 2.2s ease-in-out infinite;
}
.gc-mem-stage.cleared{
  border-color:rgba(74,222,128,.36);
  background:linear-gradient(180deg,rgba(74,222,128,.12),rgba(0,0,0,.24));
}
.gc-mem-stage.cleared::after{
  content:"";position:absolute;top:0;right:0;width:0;height:0;
  border-top:16px solid var(--good);border-left:16px solid transparent;opacity:.85;
}

/* STARS. The :empty fallback means the row still shows three stars even if the
   unit emits bare <i> elements with no glyph in them. */
.gc-mem-stars{display:inline-flex;align-items:center;gap:2px;line-height:1}
.gc-mem-stars i{
  font-style:normal;font-size:clamp(10px,1.3vw,13px);line-height:1;
  color:var(--muted-2);opacity:.6;transition:color .2s ease,opacity .2s ease,filter .2s ease;
}
.gc-mem-stars i:empty::before{content:"\2605"}
.gc-mem-stars i.on{color:var(--star);opacity:1;filter:drop-shadow(0 0 5px var(--star))}

/* SCORE BREAKDOWN — the owner asked that the remaining time add points, so the
   card has to show WHERE every point came from. A total with no derivation
   teaches the player nothing about how to score higher next board. */
.gc-mem-score{
  width:100%;max-width:440px;margin:6px auto 0;padding:14px 16px 15px;
  border-radius:13px;text-align:left;
  background:linear-gradient(180deg,rgba(255,255,255,.04),rgba(0,0,0,.2));
  border:1px solid var(--border);
}
.gc-mem-score-r{
  display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:7px 0;border-bottom:1px dashed var(--border-2);
  font:500 12px var(--ui);color:var(--muted);
}
.gc-mem-score-r:last-child{border-bottom:none}
.gc-mem-score-r>b,
.gc-mem-score-r>*:last-child:not(:first-child){
  font:700 12.5px var(--mono);color:var(--text);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.gc-mem-score-r.total{
  margin-top:6px;padding-top:11px;
  border-top:1px solid var(--border);border-bottom:none;
  font:700 13.5px var(--ui);color:var(--text);
}
.gc-mem-score-r.total>b,
.gc-mem-score-r.total>*:last-child:not(:first-child){
  font:700 clamp(20px,2.4vw,26px) var(--mono);color:var(--accent);
  filter:drop-shadow(0 0 12px var(--accent-glow));
}

/* ── 3. THEME NEUTRALISER ────────────────────────────────────────────────── */
/* See the banner. If any of these controls also carries .gc-btn, the theme
   layer's !important gradient would flatten selected and unselected into the
   same solid button. These selectors outrank it (0,4,1 / 0,4,0 against the
   theme rules' 0,2,2) and then the on-states are handed back explicitly. */
[class*="theme-"] .gc-set-seg button.gc-btn:not(.on),
[class*="theme-"] .gc-mem-perk.gc-btn:not([aria-pressed="true"]),
[class*="theme-"] .gc-mem-stage.gc-btn:not(.current):not(.cleared){
  background:linear-gradient(180deg,rgba(255,255,255,.06),rgba(0,0,0,.2))!important;
  color:var(--text)!important;border:1px solid var(--border)!important;box-shadow:none!important;
}
[class*="theme-"] .gc-set-seg button.gc-btn.on{
  background:var(--accent)!important;color:var(--bg)!important;border:1px solid var(--accent)!important;
}
/* The armed perk and the current/cleared stage are EXCLUDED from the
   neutraliser above so they can keep their accent — but excluding them is not
   enough on its own. The theme layer also declares
   `border:1px solid transparent!important`, which beats a plain
   `border-color:var(--accent)` from the base rules. MEASURED under
   theme-dragons-breath: borderTopColor came back rgba(0,0,0,0) — the armed
   perk and the current stage lost their outline completely. They need their
   own !important border, not just an exemption. */
[class*="theme-"] .gc-mem-perk.gc-btn[aria-pressed="true"]{
  background:var(--accent-glow)!important;color:var(--text)!important;
  border:1px solid var(--accent)!important;
  box-shadow:0 0 0 2px var(--accent-glow)!important;
}
[class*="theme-"] .gc-mem-stage.gc-btn.current{
  background:radial-gradient(120% 110% at 50% 0%,var(--accent-glow),transparent 66%),
             linear-gradient(180deg,rgba(255,255,255,.07),rgba(0,0,0,.26))!important;
  color:var(--text)!important;border:1px solid var(--accent)!important;box-shadow:none!important;
}
[class*="theme-"] .gc-mem-stage.gc-btn.cleared{
  background:linear-gradient(180deg,rgba(74,222,128,.12),rgba(0,0,0,.24))!important;
  color:var(--text)!important;border:1px solid rgba(74,222,128,.36)!important;box-shadow:none!important;
}
[class*="theme-"] .gc-switch.gc-btn{
  background:rgba(255,255,255,.09)!important;border:1px solid var(--border)!important;box-shadow:none!important;
}
[class*="theme-"] .gc-switch.gc-btn.on{
  background:var(--accent)!important;border-color:var(--accent)!important;
  box-shadow:0 0 0 3px var(--accent-glow)!important;
}
[class*="theme-"] .gc-set-danger>button.gc-btn,
[class*="theme-"] .gc-set-confirm button.gc-btn:not(.gc-btn-primary){
  background:rgba(248,113,113,.14)!important;color:var(--bad)!important;
  border:1px solid rgba(248,113,113,.45)!important;box-shadow:none!important;
}
[class*="theme-"] .gc-set-confirm button.gc-btn-primary{
  background:var(--bad)!important;color:var(--bg)!important;
  border:1px solid var(--bad)!important;box-shadow:none!important;
}

/* ── 4. MOBILE (must be usable at 375px) ─────────────────────────────────── */
@media (max-width:430px){
  .gc-set{gap:11px}
  .gc-set-g{padding:2px 12px 5px;border-radius:12px}
  /* Stack the row: label, then its explanation, then the control. The explicit
     order values put them in that sequence no matter which order the settings
     unit emits the help text and the control in. */
  .gc-set-row{flex-direction:column;align-items:stretch;gap:9px;padding:11px 0}
  /* MUST reset the first child's flex. `.gc-set-row>:first-child{flex:1 1 150px}`
     above is a WIDTH basis while the row is a row — but flex-basis follows the
     MAIN axis, so the moment this query turns the row into a column that 150px
     becomes a HEIGHT basis. MEASURED at 375px before this reset: the label box
     was 150px tall with its text at the top, i.e. a ~130px dead gap in every
     settings row on a phone. */
  .gc-set-row>:first-child{flex:0 0 auto}
  .gc-set-row>.gc-set-help{order:5;flex:0 0 auto;margin-top:0}
  .gc-set-row>.gc-switch,
  .gc-set-row>.gc-set-seg,
  .gc-set-row>.gc-set-confirm,
  .gc-set-row>button,
  .gc-set-row>select,
  .gc-set-row>input{order:9;margin-left:0;align-self:flex-start}
  /* full-width segments give real thumb targets instead of 40px slivers */
  .gc-set-row>.gc-set-seg{align-self:stretch;justify-content:stretch}
  .gc-set-seg button{flex:1 1 0;min-width:0;padding:8px 6px;text-align:center}
  .gc-switch{width:52px;height:30px}
  .gc-switch::after{width:22px;height:22px}
  .gc-switch.on::after{right:3px}
  .gc-set-row.gc-set-danger,.gc-set-danger{padding:11px 12px}
  .gc-set-danger>button{width:100%}
  .gc-set-confirm{width:100%;justify-content:space-between}
  .gc-set-confirm button{flex:1 1 0}

  .gc-mem-hud{padding:9px 12px;gap:6px 12px;min-height:46px;border-radius:11px}
  .gc-mem-perks{gap:6px}
  .gc-mem-perk{padding:7px 10px;min-height:38px;font-size:11px;gap:6px}
  .gc-mem-stages{grid-template-columns:repeat(auto-fill,minmax(78px,1fr));gap:8px}
  .gc-mem-stage{min-height:72px;border-radius:12px}
  .gc-mem-score{padding:12px 13px 13px}
  .gc-mem-score-r{font-size:11.5px;gap:8px}
}

/* ── 5. REDUCED MOTION ───────────────────────────────────────────────────── */
/* Both routes do the same job: the OS-level preference, and .gc-reduce-motion
   which the settings panel puts on #view-games-body for people who set it in
   the panel instead. gcModal() appends its backdrop INTO #view-games-body
   (oracle-games.js ~1081), so the class reaches the settings modal too.

   Near-zero durations, NOT animation:none. GC.anim self-clears its class on
   `animationend`; killing the animation outright would mean that event never
   fires and stale gc-flip/gc-pop classes would pile up on recycled tiles. A
   0.001ms animation still ends, so the cleanup still runs. */
.gc-reduce-motion,
.gc-reduce-motion *,
.gc-reduce-motion *::before,
.gc-reduce-motion *::after{
  animation-duration:.001ms!important;
  animation-iteration-count:1!important;
  animation-delay:0s!important;
  transition-duration:.001ms!important;
  transition-delay:0s!important;
  scroll-behavior:auto!important;
}
/* the loading spinner is the one exemption — a frozen spinner communicates
   nothing at all, so it keeps turning, just slowly and without the snap */
.gc-reduce-motion .gc-spin{animation-duration:2.4s!important;animation-iteration-count:infinite!important}
/* hover/press displacement is motion too */
.gc-reduce-motion .gc-card:hover,
.gc-reduce-motion .gc-shelf-c:hover,
.gc-reduce-motion .gc-btn:hover:not(:disabled),
.gc-reduce-motion .gc-btn:active:not(:disabled),
.gc-reduce-motion .gc-icon-btn:active:not(:disabled),
.gc-reduce-motion .gc-nim-s:hover:not(:disabled),
.gc-reduce-motion .gc-mem-perk:hover:not(:disabled),
.gc-reduce-motion .gc-mem-stage:hover:not(.locked){transform:none}
.gc-reduce-motion .gc-mem-timer.low{animation:none!important;color:var(--warn)}
.gc-reduce-motion .gc-mem-count{animation:none!important}
.gc-reduce-motion .gc-mem-stage.current{animation:none!important;box-shadow:0 0 0 3px var(--accent-glow)}

@media (prefers-reduced-motion:reduce){
  .gc-set-confirm{animation:none}
  .gc-switch,.gc-switch::after,.gc-set-seg button,.gc-mem-perk,.gc-mem-stage,
  .gc-mem-timer,.gc-mem-stars i{transition-duration:.001ms}
  .gc-mem-count{animation:none}
  .gc-mem-timer.low{animation:none;color:var(--warn)}
  .gc-mem-stage.current{animation:none;box-shadow:0 0 0 3px var(--accent-glow)}
  .gc-mem-perk:hover:not(:disabled),.gc-mem-stage:hover:not(.locked){transform:none}
}


/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.653 — GAME CENTER: CROSS-UNIT CLASS RECONCILIATION

   The settings unit, the Memory Match unit and the stylesheet unit were written
   in parallel and could not see each other. Auditing the result, every class the
   settings panel emits (.gc-set-*, .gc-switch, .gc-vol) was already styled — but
   sixteen classes emitted by Memory Match were not. Fourteen of them survive
   today only because the game also writes an inline `style.cssText`, and two
   (.gc-mem-play, .gc-mem-hint) had no styling from either side.

   Inline styles win over a stylesheet, so these rules do NOT change what the
   player sees today; they mirror the inline values so the class names stop being
   phantoms and the game keeps its layout the moment those inline fallbacks are
   dropped. .gc-mem-play and .gc-mem-hint are the two that take effect now.
   ══════════════════════════════════════════════════════════════════════════════ */

/* The play surface: HUD, clock bar, perk bar, board and footer. .gc-mem is a
   centred flex column, so a child that should span has to say so itself. */
.gc-mem-play{width:100%;display:flex;flex-direction:column;align-items:center}

/* THE HINT PERK'S ONLY OUTPUT. Hint marks the partner of the card you just
   turned; if that mark does not render, the perk silently costs points and does
   nothing. The game also sets this ring inline — belt and braces, on purpose,
   because a perk that appears to do nothing reads as a bug, not as a miss. */
@keyframes gcMemHint{0%,100%{box-shadow:0 0 0 2px var(--warn),0 0 20px var(--accent-glow)}
                     50%{box-shadow:0 0 0 3px var(--warn),0 0 28px var(--accent-glow)}}
.gc-mem-c.gc-mem-hint{
  border-color:var(--warn);
  box-shadow:0 0 0 2px var(--warn),0 0 20px var(--accent-glow);
  animation:gcMemHint 1.1s ease-in-out infinite;
}
.gc-reduce-motion .gc-mem-c.gc-mem-hint{animation:none}

/* ── mirrors of the game's inline fallbacks ────────────────────────────────── */
.gc-mem-top{display:flex;flex-wrap:wrap;gap:6px;align-items:center;justify-content:center;margin-bottom:6px}
.gc-mem-tabs{display:flex;gap:6px}
.gc-mem-line{font:400 12px var(--ui);color:var(--muted);align-self:center}
.gc-mem-bar{height:6px;border-radius:4px;background:rgba(255,255,255,.08);overflow:hidden;
  margin:0 auto 8px;width:min(520px,92%)}
.gc-mem-fill{display:block;height:100%;width:100%;background:var(--accent);
  transition:width .2s linear,background .25s ease}
.gc-reduce-motion .gc-mem-fill{transition:none}
.gc-mem-foot{margin-top:10px;display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
.gc-mem-panel{max-width:560px;margin:0 auto;padding:18px 18px 16px;text-align:center;
  background:linear-gradient(180deg,var(--panel-2),var(--panel-solid));
  border:1px solid var(--border);border-radius:14px}
.gc-mem-h{font:700 19px var(--ui);color:var(--text);margin-bottom:4px}
.gc-mem-sub{font:400 12.5px var(--ui);color:var(--muted);margin-bottom:10px}
.gc-mem-row{display:flex;align-items:baseline;gap:10px;padding:6px 2px;
  border-top:1px solid var(--border-2);font:400 13px var(--ui);text-align:left}
.gc-mem-total{display:flex;align-items:baseline;gap:10px;padding:10px 2px 2px;
  border-top:1px solid var(--border);font:700 16px var(--ui);text-align:left}
.gc-mem-rewards{font:600 13px var(--ui);color:var(--good);margin-top:10px}
.gc-mem-btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin-top:14px}

/* THIRTY STAGE TILES DO NOT FIT IN A 560px PANEL. The stylesheet unit sized the
   ladder for a full-width surface; it actually renders inside .gc-mem-panel, so
   without a scroll container the panel grows past the viewport and the ladder
   pushes the Play button off screen. The game inlines this cap today — this is
   the same cap, so the CSS-only path behaves identically. */
.gc-mem-stages{max-height:min(48vh,360px);overflow:auto}

/* ══ v9.10.654 — the peek countdown is the PRIMARY element ════════════════
   .gc-mem-count and .gc-mem-timer were written by the CSS unit but never
   emitted by the game, which rendered the countdown as 11px HUD text. Now the
   JS uses them, so the HUD has to make room — a 60px number dropped into a row
   built for 11px labels would blow the strip apart. Warn colour, because the
   peek is a deadline you are being asked to beat, not a neutral readout. */
.gc-hud:has(.gc-mem-count){gap:12px;min-height:64px;align-items:center}
.gc-mem-count{color:var(--warn);filter:drop-shadow(0 0 18px rgba(251,191,36,.35))}
.gc-hud .gc-mem-count{margin:0 2px}
.gc-reduce-motion .gc-mem-count,.gc-reduce-motion .gc-mem-timer.low{animation:none!important}

/* ══ v9.10.655 — SPECIFICITY, AGAIN ══════════════════════════════════════
   .gc-mem-count rendered at 17px instead of its 34-60px clamp because
   .gc-hud b (0,1,1) outranks .gc-mem-count (0,1,0) no matter which comes
   last. Exactly the trap that made the game frame invisible in v9.10.640:
   appending a rule does not help when the losing side loses on WEIGHT.
   Match the element AND the class. */
.gc-hud b.gc-mem-count{
  font:700 clamp(34px,7vw,60px) var(--mono);line-height:1;
  color:var(--warn);letter-spacing:1px;font-variant-numeric:tabular-nums;
  filter:drop-shadow(0 0 18px rgba(251,191,36,.35));
}
.gc-hud b.gc-mem-timer{font:700 clamp(17px,2.1vw,23px) var(--mono);font-variant-numeric:tabular-nums}

/* ══ v9.10.656 — stage tile inner text ════════════════════════════════════
   The tiles now carry state CLASSES instead of inline style, so the
   stylesheet .locked/.current/.cleared treatments finally apply. Their two
   inner spans were also inline-styled and need real rules. */
.gc-mem-stage .gc-mem-stn{font:700 clamp(15px,2.2vw,20px) var(--ui);color:var(--text);line-height:1}
.gc-mem-stage.locked .gc-mem-stn{color:var(--muted);font-size:15px}
.gc-mem-stage .gc-mem-stt{font:400 clamp(9px,1.1vw,10.5px) var(--ui);color:var(--muted);
  line-height:1.2;max-width:100%;overflow:hidden;text-overflow:ellipsis;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.gc-mem-stage.locked .gc-mem-stt{color:var(--muted-2)}
.gc-mem-stage.cleared .gc-mem-stn{color:var(--good)}
@media (prefers-reduced-motion:reduce){.gc-mem-stage.current{animation:none}}
.gc-reduce-motion .gc-mem-stage.current{animation:none}


/* ══════════════════════════════════════════════════════════════════════════
   GAME CENTER — MOBILE-FIRST            (v9.10.657)         APPEND-ONLY
   ──────────────────────────────────────────────────────────────────────────
   WHY THIS BLOCK EXISTS

   The owner, verbatim: "mobile version is not using the full screen for the
   Setup for each game ... extended lead boards is in a different area than the
   other buttons and its all to un-mobile friendly. the games also are not
   mobile friendly."

   MEASURED on a real 375x812 phone viewport, BEFORE this block:

       start card    317 x 484   =  84% of the screen width, 60% of its height
       overlay       373 x 520
       buttons       33-34px tall  ->  54 CONTROLS UNDER THE 44px MINIMUM
       Connect Four  board 340 x 293, cell 40px
       Leaderboard   in .gc-frame-foot, 526px from the tools in .gc-frame-head

   Those five numbers ARE the brief.

   * 84% of the width is not "full screen". A 317px card on a 375px phone
     throws away 58px of horizontal room, and it is 317px because
     `.gc-overlay{padding:18px}` + `.gc-overlay-card{width:min(760px,94%)}`
     multiply out to 94% of 337. Below 700px the overlay goes full-bleed: 6px
     insets, square corners, the card owns the scroll, and the action buttons
     are `position:sticky` at the bottom in a full-width stack so a thumb can
     always reach Play without scrolling to find it.
   * 33-34px is 10px under the floor every platform agrees on (iOS HIG 44pt,
     Material 48dp, WCAG 2.5.8). The single biggest source of that number is
     `.gc-frame-head .gc-back,.gc-mode,.gc-sel{height:34px}` and
     `.gc-icon-btn{width:34px;height:34px}`.
   * a 40px Connect Four cell inside a 340px board is the same failure in the
     play surface: the board is sized `min(94vw, clamp(340px,50vw,620px))` and
     on a 375px screen the clamp FLOOR wins, so the board froze at 340px
     instead of using the ~360px it had. Boards go to ~96vw here.
   * the leaderboard being 526px away from the other tools is not a spacing
     problem, it is a GROUPING problem. The framework unit moves the button
     into `.gc-frame-tools`; this block makes that container read as one
     cluster — a tinted, wrapping strip on its own row under the title.

   THE BREAKPOINT IS 700px, NOT 900px, ON PURPOSE.
   Everything above uses 900px, which is a TABLET boundary, and those rules are
   tablet-correct. Stacking a phone layer at 700px leaves the tablet untouched
   and still wins at 375px, because equal-specificity rules are resolved by
   source order and this block is last in the file.

   SPECIFICITY — the trap this file has already been bitten by three times
   (v9.10.640, .655, .656): appending a rule does not help when the losing side
   loses on WEIGHT. The four live hazards, and what they force:

     1. the frame element carries BOTH classes: <div class="gc-stage gc-frame">.
        `.gc-stage:not(:has(.gc-frame))` (0,2,0) MATCHES it, because an element
        is not its own descendant. Any frame override must therefore be written
        `.gc-frame.gc-frame` (0,2,0) or heavier — a plain `.gc-frame` (0,1,0)
        loses silently, which is exactly the v9.10.640 bug.
     2. `.gc-frame-head .gc-back` (0,2,0) pins the header controls at 34px, so
        a bare `.gc-back{min-height:44px}` (0,1,0) cannot lift them.
     3. `.gc-hud b` (0,1,1) outranks a bare `.gc-lives`/`.gc-level` (0,1,0), so
        the new HUD classes are also declared element-qualified.
     4. the theme layer paints every `button.gc-btn` with an !important
        gradient (line ~6252, and one block per theme). Anything new that also
        carries .gc-btn needs a HEAVIER selector, not a later one — see the
        neutraliser for .gc-tools-more at the end.

   TOUCH TARGETS are grown with min-height / padding / invisible hit-area
   pseudo-elements — never with font-size. A 44px button whose label ballooned
   to 20px is a different, worse bug. Where the painted element must stay small
   (the card's "?" badge, the settings switch, a Nim stick) a transparent
   ::before/::after extends the finger target while the paint stays put.

   Tokens only. The owner runs the red Dragon's Breath theme and a hardcoded
   hex here would fight it on every screen.
   ══════════════════════════════════════════════════════════════════════════ */


/* ══ 1. NEW CLASSES — LIVES, LEVEL, CONTINUE, OVERFLOW TOOLS, FLOPPY KAI ══
   All widths, not just phones. The owner's other complaint is that a game
   "doesnt have levels its just game over! like they did something bad and no
   continue". These are the readouts that make a run feel survivable: how much
   life is left, how far you got, and the offer to keep going. The games unit
   emits them; this is the only place they are painted. */

/* ── lives ──────────────────────────────────────────────────────────────── */
.gc-lives{display:inline-flex;align-items:center;gap:5px;line-height:1;vertical-align:middle}
/* .gc-hud b (0,1,1) would otherwise win the font/colour on a <b class="gc-lives"> */
.gc-hud b.gc-lives,.gc-hud span.gc-lives,.gc-hud i.gc-lives{
  display:inline-flex;align-items:center;gap:5px;font:inherit;color:inherit;line-height:1;
}
.gc-life{
  display:inline-block;flex:none;width:15px;height:15px;
  font:400 14px/1 var(--ui);font-style:normal;text-align:center;
  color:var(--bad);filter:drop-shadow(0 0 6px rgba(248,113,113,.5));
  transition:color .2s ease,opacity .2s ease,filter .2s ease,transform .2s ease;
}
/* an empty pip still renders — the same defence .gc-mem-stars i uses, because
   the games unit may emit bare <i class="gc-life"></i> with no glyph in it */
.gc-life:empty::before{content:"\2665"}
.gc-life.lost{color:var(--muted-2);opacity:.4;filter:none;transform:scale(.84)}
/* deliberately NO animation on .lost: the arcade HUD is repainted from
   innerHTML on every score change, so an entry animation would re-fire on
   every frame and strobe. */

/* ── level / wave badge ─────────────────────────────────────────────────── */
.gc-level{
  display:inline-flex;align-items:center;gap:5px;
  padding:3px 9px;border-radius:99px;white-space:nowrap;
  background:var(--accent-glow);border:1px solid var(--accent);
  font:700 10.5px/1.5 var(--mono);letter-spacing:1.1px;text-transform:uppercase;
  color:var(--accent);font-variant-numeric:tabular-nums;
}
.gc-hud b.gc-level,.gc-hud span.gc-level,.gc-hud i.gc-level{
  font:700 11px/1.5 var(--mono);letter-spacing:1.1px;color:var(--accent);
  text-transform:uppercase;
}
.gc-level b,.gc-level strong{font:inherit;color:inherit;font-size:1.15em}

/* ── the Continue? panel ────────────────────────────────────────────────── */
/* Shown INSTEAD of an instant game-over, so it has to read as an offer, not an
   epitaph: accent-lit, centred, and its buttons are the widest thing on it.
   It renders either on its own in the frame body or inside .gc-overlay-card —
   both shapes are handled, the second by flattening the panel chrome so there
   is not a card inside a card. */
@keyframes gcContinueGlow{
  0%,100%{box-shadow:0 22px 50px -26px rgba(0,0,0,.9),0 0 0 1px var(--accent-glow)}
  50%    {box-shadow:0 22px 50px -26px rgba(0,0,0,.9),0 0 0 5px var(--accent-glow)}
}
.gc-continue{
  width:min(430px,100%);margin:0 auto;padding:20px 18px 18px;
  display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;
  border-radius:14px;border:1px solid var(--accent);
  background:radial-gradient(120% 120% at 50% 0%,var(--accent-glow),transparent 66%),
             linear-gradient(180deg,var(--panel-2),var(--panel-solid));
  animation:gcContinueGlow 2.2s ease-in-out infinite;
}
.gc-overlay-card .gc-continue,.gc-modal-b .gc-continue{
  width:100%;padding:0;border:none;background:none;animation:none;box-shadow:none;
}
.gc-continue-t{
  font:700 clamp(19px,3.4vw,25px) var(--ui);color:var(--text);letter-spacing:.2px;line-height:1.2;
}
.gc-continue-d{font:400 13px/1.6 var(--ui);color:var(--muted);max-width:46ch}
/* the seconds-left / lives-left number the panel counts down */
.gc-continue-d b{color:var(--warn);font-weight:700;font-variant-numeric:tabular-nums}
.gc-continue-btns{
  display:flex;gap:9px;justify-content:center;flex-wrap:wrap;width:100%;margin-top:6px;
}
.gc-continue-btns>*{min-height:44px}

/* ── overflow tool menu ─────────────────────────────────────────────────── */
/* The "⋯" that reveals the tools that will not fit on a narrow head. Written
   to be correct WHETHER the framework unit emits it as the button itself or as
   a wrapper holding a trigger plus a popup — betting on one shape is how a
   cross-unit class becomes a phantom (see the v9.10.653 banner). */
button.gc-tools-more,.gc-tools-more>button:first-child{
  width:38px;height:38px;flex:none;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.05);border:1px solid var(--border);border-radius:10px;
  color:var(--muted);font:700 16px/1 var(--ui);cursor:pointer;
  transition:background .14s,border-color .14s,color .14s;
}
button.gc-tools-more:hover,.gc-tools-more>button:first-child:hover{
  background:var(--accent-glow);border-color:var(--accent);color:var(--text);
}
button.gc-tools-more.on,button.gc-tools-more[aria-expanded="true"],
.gc-tools-more.on>button:first-child{
  background:var(--accent-glow);border-color:var(--accent);color:var(--accent);
}
button.gc-tools-more:focus-visible,.gc-tools-more>button:first-child:focus-visible{
  outline:none;box-shadow:0 0 0 3px var(--accent-glow);
}
.gc-tools-more:not(button){position:relative;display:inline-flex;align-items:center;flex:none}
/* the popup, when the wrapper shape is used: whatever follows the trigger */
.gc-tools-more:not(button)>:last-child:not(:first-child){
  position:absolute;top:calc(100% + 8px);right:0;z-index:60;
  display:flex;flex-direction:column;gap:6px;min-width:196px;padding:8px;
  background:var(--panel-solid);border:1px solid var(--border);border-radius:13px;
  box-shadow:0 24px 60px -26px rgba(0,0,0,.95);
}
.gc-tools-more:not(button)>:last-child:not(:first-child) button{
  display:flex;align-items:center;justify-content:flex-start;gap:9px;
  width:100%;min-height:44px;text-align:left;
}

/* ── Floppy KAI HUD ─────────────────────────────────────────────────────── */
/* Kept OUT of the canvas bitmap on purpose: text painted into a 400x640 canvas
   that is then scaled to fit a phone is blurry text, and it cannot be selected,
   themed or read by a screen reader. */
.gc-fk-hud{
  display:flex;align-items:center;justify-content:center;gap:8px 18px;flex-wrap:wrap;
  width:min(560px,100%);margin:0 auto;padding:9px 16px;min-height:48px;
  border-radius:12px;background:var(--panel-2);border:1px solid var(--border-2);
  font:600 10.5px var(--ui);letter-spacing:1px;text-transform:uppercase;color:var(--muted);
  text-align:center;
}
.gc-fk-hud b{
  font:700 clamp(18px,2.4vw,24px) var(--mono);color:var(--text);
  letter-spacing:.5px;text-transform:none;font-variant-numeric:tabular-nums;
}
.gc-fk-hud .gc-level,.gc-fk-hud .gc-lives{text-transform:none;letter-spacing:.4px}
.gc-fk-hud em{font-style:normal;color:var(--star);text-transform:none}


/* ══ 2. THE PHONE LAYER ═══════════════════════════════════════════════════ */
@media (max-width:700px){

  /* ── 2.1 THE FRAME IS THE SCREEN ─────────────────────────────────────── */
  /* Edge-to-edge: on a 375px screen a 16px radius and a side border cost 34px
     of play surface to draw a rounded rectangle nobody asked for. The bottom
     margin clears the mobile taskbar; it never drops below the 90px the
     tablet layer already reserved. */
  .gc-wrap{
    max-width:100%;gap:12px;
    padding:12px 10px max(90px,calc(66px + env(safe-area-inset-bottom,0px)));
  }
  .gc-frame.gc-frame{
    width:100%;max-width:100%;min-height:0;
    margin:0 0 max(90px,calc(66px + env(safe-area-inset-bottom,0px)));
    border-radius:0;border-left:none;border-right:none;
  }

  /* HEAD: title truncates, tools become one cluster on their own row. */
  .gc-frame.gc-frame>.gc-frame-head,
  .gc-frame.gc-frame>.gc-stage-head{
    padding:9px 10px;min-height:0;gap:8px;align-items:center;
  }
  /* display:block, not flex — text-overflow cannot ellipsis an ANONYMOUS flex
     item, and the title is an icon <span> followed by a bare text node. As a
     block the whole line truncates and the icon rides along inline. */
  /* flex-basis 0, NOT auto. MEASURED with `flex:1 1 auto`: a long game name
     ("Connect Four Deluxe Championship") reports its full nowrap width as its
     hypothetical main size, flexbox breaks the LINE before it ever shrinks
     anything, and the title dropped onto a row of its own — head 205px tall on
     an 812px screen. A basis of 0 contributes nothing to the line-breaking
     decision, so the title always shares row one with ← Games and truncates
     into whatever is left. Head 205px -> 175px. */
  .gc-frame-head .gc-frame-title,.gc-frame-head .gc-stage-t{
    display:block;flex:1 1 0;min-width:0;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    font-size:15px;line-height:1.35;
  }
  .gc-frame-head .gc-frame-title .gc-stage-ico{
    display:inline-block;vertical-align:-3px;margin-right:6px;font-size:19px;
  }

  /* THE ONE CLUSTER. Mode buttons, difficulty, pause, music, sound and the
     leaderboard the framework unit is moving up here all live in this strip. */
  .gc-frame-head .gc-frame-tools{
    flex:1 0 100%;order:9;width:100%;margin-left:0;
    display:flex;align-items:center;justify-content:flex-start;gap:6px;flex-wrap:wrap;
    padding:6px;border-radius:12px;
    background:rgba(255,255,255,.04);border:1px solid var(--border-2);
  }
  /* width:auto is load-bearing. The 900px tablet block sets
     `.gc-modes{margin-left:0;width:100%}`, which was written when .gc-modes was
     a direct child of the head. Inside the tools cluster it makes two 54px mode
     buttons claim the ENTIRE 343px row (MEASURED: gc-modes w=343), pushing the
     difficulty select and all four icon tools onto a second line for nothing. */
  .gc-frame-head .gc-frame-tools>.gc-modes{
    margin-left:0;width:auto;flex:0 1 auto;
    display:flex;gap:5px;flex-wrap:wrap;min-width:0;
  }
  .gc-frame-head .gc-frame-tools .gc-sel{flex:0 1 auto;min-width:0;max-width:44vw}
  .gc-frame-head .gc-modes+.gc-frame-tools{margin-left:0}

  /* BODY: absorbs every remaining pixel, so the overlay that covers it (and
     therefore the Setup card) is as tall as the screen allows. The floor stops
     it collapsing if the flex chain above ever loses its definite height. */
  .gc-frame.gc-frame>.gc-frame-body{
    flex:1 1 auto;min-height:min(58vh,420px);
    padding:10px 7px calc(14px + env(safe-area-inset-bottom,0px));
    gap:10px;align-items:center;
    justify-content:flex-start;
    justify-content:safe center;
    overscroll-behavior:contain;
  }
  /* v9.10.644 set flex-start, NOT center, and the reason was correct: this
     element is a scroll container, and centring OVERFLOWING content in a scroll
     container puts the top of that content above the scroll origin, where the
     scrollbar cannot reach it.
     v9.10.7xx: `safe center` is the exact remedy for that and nothing else - it
     centres while the content fits and falls back to flex-start the moment it
     would overflow, so the unreachable-top failure cannot occur. The plain
     flex-start above it is the fallback for engines that do not parse `safe`.
     WHY IT CHANGED: pinned to the top, every game sat directly under the top
     bar, fouling the menu buttons and wasting the bottom half of the screen. */

  .gc-frame.gc-frame>.gc-frame-foot,
  .gc-frame.gc-frame>.gc-stage-foot{
    padding:9px 10px calc(9px + env(safe-area-inset-bottom,0px));min-height:0;gap:8px;
  }
  .gc-foot-s{flex:1 1 100%;font-size:11.5px;line-height:1.5}

  /* ── 2.2 THE SETUP SCREEN GOES FULL-BLEED ────────────────────────────── */
  /* MEASURED 317x484 inside a 375x812 screen. Now: 6px insets, the card owns
     the scroll, and the actions are sticky at the bottom in a stack. */
  .gc-overlay{
    display:flex;align-items:stretch;justify-content:flex-start;
    padding:6px;border-radius:0;overflow:hidden;
  }
  .gc-overlay-card{
    width:100%;max-width:100%;height:100%;max-height:100%;min-height:0;margin:0;
    padding:16px 14px 0;border-radius:6px;
    display:flex;flex-direction:column;
    overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
    -webkit-overflow-scrolling:touch;
  }
  /* ONE scroll surface. The guide had its own overflow:auto, which on a phone
     means a scroll box inside a scroll box — the classic "it won't scroll"
     report. The card is the only scroller now. */
  .gc-overlay-card>.gc-howto-host,
  .gc-overlay-card .gc-howto-compact{flex:0 0 auto;max-height:none;overflow:visible}
  .gc-overlay-card:has(.gc-howto-host){max-width:100%}
  .gc-overlay-t{font-size:20px;margin-bottom:6px}
  .gc-overlay-d{font-size:13px;margin-bottom:12px}
  /* PINNED ACTIONS. margin-top:auto parks them at the bottom when the content
     is short; position:sticky keeps them on screen when it is long. The
     safe-area padding lives INSIDE the bar (and the card's own bottom padding
     is 0) so the buttons sit above the home indicator without a dead gap. */
  .gc-overlay-btns{
    position:sticky;bottom:0;z-index:2;
    display:flex;flex-direction:column;align-items:stretch;gap:8px;
    width:100%;margin-top:auto;
    padding:12px 0 calc(12px + env(safe-area-inset-bottom,0px));
    background:linear-gradient(180deg,transparent,var(--panel-solid) 24%);
  }
  .gc-overlay-btns>*{width:100%;min-height:48px}
  /* (0,2,0): `.gc-btn{min-height:44px}` in 2.3 below is (0,1,0) but comes
     LATER in the file, so `.gc-overlay-btns>*` (0,1,0) lost the tie and the
     Play button measured 44px instead of 48px. Qualify it. */
  .gc-overlay-btns>.gc-btn{min-height:48px}
  /* while the Setup card is up the board behind it must not scroll away from
     under it — an absolutely positioned overlay inside a scroll container is
     pinned to the CONTENT, not to the scrollport. */
  .gc-frame-body:has(>.gc-overlay.on){overflow:hidden}

  /* ── 2.3 44px MINIMUM TOUCH TARGET ───────────────────────────────────── */
  /* MEASURED: 54 controls at 33-34px. Every one of them is listed here.
     Padding and min-height only — the type sizes stay where they are. */
  .gc-btn{
    min-height:44px;padding:11px 16px;font-size:13px;
    display:inline-flex;align-items:center;justify-content:center;gap:7px;
  }
  .gc-back{min-height:44px;padding:11px 14px;font-size:12.5px;
    display:inline-flex;align-items:center;flex:none}
  /* (0,2,0) — has to match `.gc-frame-head .gc-back{height:34px}` to beat it */
  .gc-frame-head .gc-back,.gc-frame-head .gc-mode,.gc-frame-head .gc-sel,
  .gc-frame-tools .gc-back,.gc-frame-tools .gc-mode,.gc-frame-tools .gc-sel{
    height:auto;min-height:44px;display:inline-flex;align-items:center;
  }
  .gc-icon-btn{width:44px;height:44px;font-size:17px;border-radius:11px}
  /* (0,1,1) to match its own base rule, which is element-qualified */
  button.gc-tools-more,.gc-tools-more>button:first-child{
    width:44px;height:44px;font-size:18px;border-radius:11px;
  }
  .gc-headbtn{min-height:44px;padding:11px 14px;font-size:12px}
  .gc-chip{min-height:44px;padding:11px 15px;font-size:12.5px;
    display:inline-flex;align-items:center}
  .gc-mode{min-height:44px;padding:11px 15px;font-size:12px;
    display:inline-flex;align-items:center}
  .gc-sel{min-height:44px;padding:10px 11px;font-size:12.5px}
  .gc-search{min-height:44px;padding:12px 14px;font-size:14px}
  .gc-room{min-height:44px;padding:11px 13px}
  .gc-shelf-c{min-height:44px;padding:12px 8px}
  .gc-mem-perk{min-height:44px;padding:11px 13px;font-size:11.5px}
  .gc-set-seg button{min-height:44px}
  .gc-set-danger>button{min-height:44px;padding:11px 14px}
  .gc-set-confirm button{min-height:44px;padding:10px 13px}
  .gc-hero-play,.gc-daily-go{min-height:48px}
  .gc-an-bar>*,.gc-mem-btns>*,.gc-mem-foot>*,.gc-turn-bar>*{min-height:44px}

  /* Hit area grown WITHOUT growing the paint. The "?" badge stays a 30px
     circle in the corner of a card; the transparent ::after gives the finger
     the 44px it needs. Both stay inside .gc-card's overflow:hidden, so the
     expanded region is still hit-testable. */
  .gc-card-help{width:30px;height:30px;font-size:13px;opacity:.8;top:7px;right:7px}
  .gc-card-help::after{content:"";position:absolute;inset:-7px;border-radius:50%}

  /* Same technique on the switch: a 34px track reads correctly at this size,
     and ::before adds the last 10px of reach. overflow has to be released for
     that (font-size:0 + color:transparent already hide any stray label, and
     .gc-switch>* is clip-path hidden, so nothing leaks). */
  .gc-switch{width:58px;height:34px;overflow:visible}
  .gc-switch::after{width:26px;height:26px}
  .gc-switch.on::after{right:3px}
  .gc-switch::before{content:"";position:absolute;inset:-5px -2px;border-radius:99px}
  .gc-switch:active:not(:disabled)::after{width:30px}

  /* The volume slider was a 4px-tall line — a 4px finger target. The track
     becomes a pseudo-element so the INPUT can be 30px tall while the painted
     line stays thin. WebKit and Gecko pseudo-elements must stay in separate
     rules: one unknown pseudo invalidates a whole selector list. */
  .gc-vol{width:130px;height:30px;background:transparent;border-radius:0}
  .gc-vol::-webkit-slider-runnable-track{height:5px;border-radius:99px;background:rgba(255,255,255,.14)}
  .gc-vol::-webkit-slider-thumb{width:19px;height:19px;margin-top:-7px}
  .gc-vol::-moz-range-track{height:5px;border-radius:99px;background:rgba(255,255,255,.14)}
  .gc-vol::-moz-range-thumb{width:19px;height:19px}

  /* ── 2.4 BOARDS USE THE WIDTH THEY HAVE ──────────────────────────────── */
  /* min(96vw,100%): the vw term keeps the board off the screen edges, the 100%
     term keeps it inside the frame body when the OS runs the Game Center in a
     narrower pane — where vw would lie. Neither can produce a horizontal
     scrollbar, which is the whole point. */
  .gc-g-t3{width:min(96vw,100%)}
  .gc-g-c4{width:min(96vw,100%);gap:5px;padding:6px;border-radius:12px}
  .gc-g-ov{width:min(97vw,100%);gap:2px;padding:4px;border-radius:10px}
  .gc-g-gm{width:min(97vw,100%);gap:1px;padding:3px}
  .gc-g-ms{width:min(97vw,100%);gap:2px}
  .gc-g-lo{width:min(92vw,100%);gap:7px}
  .gc-g-sl{width:min(94vw,100%);gap:6px}
  .gc-g-si{width:min(84vw,100%);gap:9px}
  .gc-2048-b{width:min(96vw,100%);gap:7px;padding:7px;border-radius:12px}
  .gc-g-mem{width:min(calc(var(--cols,6) * 60px),100%);gap:5px}
  .gc-rx-p{width:min(96vw,100%);height:clamp(150px,24vh,220px);font-size:16px}
  .gc-an-i{width:min(96vw,100%);font-size:16px}
  .gc-an-q{font-size:clamp(28px,9vw,40px);letter-spacing:6px;padding:10px 4px}
  .gc-nim{padding:4px;gap:12px;width:100%}
  .gc-db{padding:6px;width:100%;align-items:center}
  .gc-turn{gap:10px;width:100%}
  .gc-turn-board{width:100%}

  /* 44px cells on the COARSE grids only. Forcing it on Othello (8x8), Gomoku
     (15x15) or Minesweeper (up to 16 wide) would break aspect-ratio:1 and turn
     round discs into ovals while making the board taller than the phone — a
     4-in-a-row board you have to scroll is worse than a 42px cell. Those grids
     get their width back instead, above. */
  .gc-g-t3 .gc-c,.gc-g-c4 .gc-c,.gc-g-lo .gc-c,.gc-g-sl .gc-c,
  .gc-g-mem .gc-c,.gc-g-si .gc-si-p,.gc-2048-t{min-height:44px}
  .gc-sl-c{font-size:clamp(20px,7vw,30px)}
  .gc-mem-c{font-size:clamp(16px,6vw,26px)}
  .gc-2048-t{font-size:clamp(20px,6.5vw,30px)}
  .gc-2048-t.v128,.gc-2048-t.v256,.gc-2048-t.v512{font-size:clamp(18px,5.6vw,26px)}
  .gc-2048-t.v1024,.gc-2048-t.v2048,.gc-2048-t.v4096{font-size:clamp(14px,4.6vw,21px)}

  /* Wordle: a real phone keyboard. The keys FLEX instead of carrying a fixed
     min-width, so ten of them share the row exactly rather than overflowing it,
     and every one is 46px tall. Width per key is whatever 10-across allows —
     the 44px rule is a rule about the TARGET, and a key you cannot miss
     vertically in a row of ten is the same trade every phone keyboard makes. */
  .gc-w5-c{width:clamp(38px,11.4vw,52px);height:clamp(38px,11.4vw,52px);
    font-size:clamp(18px,5vw,24px);border-radius:7px}
  .gc-w5-kb{width:100%;max-width:min(100%,480px);align-items:stretch;gap:6px}
  .gc-w5-kr{display:flex;gap:4px;width:100%}
  .gc-w5-k{flex:1 1 0;min-width:0;height:46px;padding:0 2px;font-size:13px;border-radius:6px}
  .gc-w5-k.wide{flex:1.7 1 0;font-size:11px}

  /* Nim sticks: 13px wide was a 13px target. 22px of paint plus a transparent
     reach ring, kept deliberately narrower than the 8px gap so two neighbours
     can never claim the same tap — an overlapping hit area on a game where you
     choose HOW MANY to take is worse than a small one. */
  .gc-nim-r{gap:8px;flex-wrap:wrap;justify-content:center;min-height:56px}
  .gc-nim-s{position:relative;width:22px;height:56px;border-radius:5px}
  .gc-nim-s::after{content:"";position:absolute;inset:-6px -3px}

  /* Dots & Boxes: the 10px edges were unhittable. The PAINTED size is left
     alone on purpose — .gc-db-h is 44x10 and .gc-db-v is 10x44, and the row /
     vrow columns only line up because those two 10s match the 10px dot. Growing
     .gc-db-v to 14px would shift every column by 4px and the grid would shear.
     So the reach is added with a transparent ::after instead: 10 + 2x17 = 44 on
     the axis that was short, and ~2px on the axis that was already fine.
     They cannot steal each other's taps — an h-edge spans a BOX column and a
     v-edge spans a DOT column, so the expansions never share x AND y. */
  .gc-db-h,.gc-db-v{position:relative}
  .gc-db-h::after{content:"";position:absolute;inset:-17px -2px}
  .gc-db-v::after{content:"";position:absolute;inset:-2px -17px}

  /* ── 2.5 ARCADE: THE D-PAD MUST BE ON SCREEN ─────────────────────────── */
  /* A d-pad you have to scroll to is not a d-pad. The canvas is capped so the
     canvas + HUD + pad fit one screen; the max() floor keeps it playable on a
     short phone, and the plain 52vh above it is the fallback for engines
     without dvh (an invalid dvh declaration is dropped, the vh one survives). */
  .gc-arcade{gap:8px;width:100%}
  .gc-canvas{
    width:auto;max-width:100%;border-radius:10px;
    max-height:52vh;
    max-height:max(180px,min(46dvh,calc(100dvh - 430px)));
  }
  .gc-hud{padding:7px 11px;gap:5px 10px;font-size:11px;border-radius:10px}
  .gc-hud b{font-size:15px}
  .gc-pause{font-size:13px;border-radius:10px}

  .gc-pad{
    display:flex;gap:8px;margin-top:8px;justify-content:center;flex-wrap:wrap;
    padding-bottom:calc(4px + env(safe-area-inset-bottom,0px));
  }
  .gc-pad-b{
    width:56px;height:56px;border-radius:14px;font-size:19px;flex:none;
    background:rgba(255,255,255,.09);
  }
  .gc-pad-b:active{background:var(--accent-glow);border-color:var(--accent)}
  /* A ROW of five arrows is not a d-pad — your thumb has to travel the whole
     width to go from left to up. When the framework emits exactly the five
     buttons it emits today (◀ ▲ ▼ ▶ ●) lay them out as a real cross with the
     action key under the right thumb. Any other count falls straight back to
     the row above, and so does any engine without :has(). */
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6))){
    display:grid;width:max-content;max-width:100%;
    grid-template-columns:repeat(4,56px);grid-template-rows:repeat(2,56px);
    gap:8px;justify-content:center;align-content:center;
  }
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6)))>:nth-child(1){grid-area:1/1/3/2;height:auto}
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6)))>:nth-child(2){grid-area:1/2/2/3}
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6)))>:nth-child(3){grid-area:2/2/3/3}
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6)))>:nth-child(4){grid-area:1/3/3/4;height:auto}
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6)))>:nth-child(5){
    grid-area:1/4/3/5;height:auto;border-radius:18px;font-size:22px;
  }

  /* ── 2.6 MODALS (settings, achievements, daily, leaderboard) ─────────── */
  /* Same complaint, same answer: a 96%-wide card with 22px of backdrop padding
     is not "full screen" on a phone. These are fixed-position, so they clear
     the OS chrome themselves and take both safe-area insets. */
  .gc-modal{padding:0;align-items:stretch;justify-content:flex-start}
  .gc-modal-card{
    width:100%;max-width:100%;height:100%;max-height:100%;border-radius:0;border:none;
  }
  .gc-modal-head{padding:12px;padding-top:max(12px,env(safe-area-inset-top,0px));gap:9px}
  .gc-modal-t{font-size:15px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .gc-modal-b{padding:14px 12px calc(26px + env(safe-area-inset-bottom,0px))}
  .gc-board-host{max-height:none}

  /* ── 2.7 SETTINGS ROWS STACK FROM 700px, NOT 430px ───────────────────── */
  /* The stacked layout below already existed at 430px; between 431 and 700 a
     label, a help line and a control were still fighting for one row. Same
     rules, same explicit order values, one breakpoint earlier. */
  .gc-set{gap:12px}
  .gc-set-g{padding:2px 12px 5px;border-radius:12px}
  .gc-set-row{flex-direction:column;align-items:stretch;gap:9px;padding:12px 0}
  /* flex-basis follows the MAIN axis: `>:first-child{flex:1 1 150px}` becomes a
     150px HEIGHT the moment the row turns into a column. Reset it or every row
     opens with a ~130px dead gap (measured, v9.10.652). */
  .gc-set-row>:first-child{flex:0 0 auto}
  .gc-set-row>.gc-set-help{order:5;flex:0 0 auto;margin-top:0;max-width:100%}
  .gc-set-row>.gc-switch,
  .gc-set-row>.gc-set-seg,
  .gc-set-row>.gc-set-confirm,
  .gc-set-row>button,
  .gc-set-row>select,
  .gc-set-row>input{order:9;margin-left:0;align-self:flex-start}
  .gc-set-row>.gc-set-seg{align-self:stretch;justify-content:stretch;width:100%}
  .gc-set-seg button{flex:1 1 0;min-width:0;padding:11px 8px;text-align:center}
  .gc-set-danger>button{width:100%}
  .gc-set-confirm{width:100%;justify-content:space-between}
  .gc-set-confirm button{flex:1 1 0}

  /* ── 2.8 THE LIBRARY ─────────────────────────────────────────────────── */
  /* The console shelf re-declared .gc-grid OUTSIDE a media query and after the
     900px rules, so its `minmax(clamp(200px,17vw,268px),1fr)` won on a phone
     too: 200px against a 351px column is ONE card per row. Two, explicitly. */
  .gc-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .gc-card{min-height:0}
  .gc-card-ico{height:70px;font-size:32px}
  .gc-card:hover .gc-card-ico{height:70px}
  .gc-card-b{padding:10px 11px 12px}
  .gc-card-n{font-size:13px}
  .gc-card-d{font-size:11px;margin-bottom:6px}
  .gc-head{gap:9px}
  .gc-title{font-size:17px;flex:1 1 100%}
  .gc-search{flex:1 1 100%;max-width:none}
  .gc-count{margin-left:0}
  /* The filter chips become a swipe rail. Wrapping them at 44px tall would push
     the whole shelf below the fold. */
  .gc-chips{
    flex-wrap:nowrap;overflow-x:auto;gap:6px;padding-bottom:4px;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .gc-chips::-webkit-scrollbar{display:none}
  .gc-chip{flex:0 0 auto}
  /* the spacer separates the CATEGORY chips from the MODE chips. As a
     flex:1 gap it would be a metre wide inside a nowrap scroller and push the
     mode filters past the end of the rail, so it becomes a hairline divider —
     the grouping it was there to express, in the space a rail can afford. */
  .gc-chip-sp{flex:0 0 1px;min-width:1px;align-self:stretch;
    background:var(--border);margin:5px 4px}
  .gc-head-acts{gap:6px;flex-wrap:wrap}
  .gc-headbtn{flex:1 1 auto;justify-content:center}
  .gc-hero{border-radius:14px}
  .gc-hero-art{flex:0 0 96px}
  .gc-hero-n{font-size:22px}
  .gc-hero-d{font-size:12.5px}
  .gc-hero-btns{width:100%}
  .gc-hero-btns>*{flex:1 1 auto}
  .gc-shelf-r{
    gap:9px;scroll-snap-type:x proximity;scroll-padding-left:2px;
    -webkit-overflow-scrolling:touch;
  }
  .gc-shelf-c{width:96px;scroll-snap-align:start}
  .gc-lobby{padding:11px 12px}
  .gc-lobby-l{gap:7px}

  /* ── 2.9 THE NEW CLASSES ON A PHONE ──────────────────────────────────── */
  .gc-continue{width:100%;padding:18px 14px 16px;border-radius:14px}
  .gc-continue-btns{flex-direction:column;align-items:stretch;gap:8px}
  .gc-continue-btns>*{width:100%;min-height:48px}
  .gc-fk-hud{padding:8px 12px;min-height:46px;gap:6px 14px;font-size:10px}
  .gc-fk-hud b{font-size:19px}
  .gc-life{width:14px;height:14px;font-size:13px}
  .gc-mem-hud{padding:9px 12px;gap:6px 12px;min-height:46px;border-radius:11px}
  .gc-mem-perks{gap:6px}
  .gc-mem-stages{grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:8px;
    max-height:min(46vh,340px)}
  .gc-mem-panel{padding:16px 13px 14px;max-width:100%}
  .gc-mem-score{padding:12px 13px 13px;max-width:100%}
}


/* ══ 3. VERY NARROW (<=380px) ═════════════════════════════════════════════
   iPhone SE / mini territory. Only the things that genuinely stop fitting. */
@media (max-width:380px){
  .gc-grid{gap:8px}
  .gc-card-ico{height:62px;font-size:28px}
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6))){
    grid-template-columns:repeat(4,50px);grid-template-rows:repeat(2,50px);gap:7px;
  }
  .gc-pad-b{width:50px;height:50px;font-size:17px}
  .gc-frame-head .gc-frame-tools{padding:5px;gap:5px}
  .gc-frame-head .gc-frame-tools .gc-sel{max-width:38vw}
  .gc-w5-k{font-size:12px}
  .gc-w5-k.wide{font-size:10px}
  .gc-overlay-t{font-size:18px}
  .gc-shelf-c{width:88px}
}


/* ══ 4. LANDSCAPE PHONES ══════════════════════════════════════════════════
   A 375x812 phone turned sideways is 812x375, and 812 IS WIDER THAN THE 700px
   phone breakpoint — a landscape phone gets the desktop layer, not the phone
   one. That is why this query is height-driven (max-height:520px) instead, and
   why it comes in TWO parts: 4a is safe for anything up to a small landscape
   tablet, 4b refines what section 2 already changed and must therefore stay
   inside 700px or it would half-apply a layout that is not there. */

/* ── 4a. any short landscape screen up to 900px ──────────────────────────── */
@media (max-width:900px) and (orientation:landscape) and (max-height:520px){
  /* flex + a FLOOR, never min-height:0. MEASURED at 812x375 with a bare
     `min-height:0`: the frame body collapsed to 14px and took the start card
     with it, because outside the 700px layer nothing else gives the body a
     height. The floor is the smaller of 62vh and 280px so it can never demand
     more room than a 375px-tall screen has. */
  .gc-frame.gc-frame>.gc-frame-body{
    flex:1 1 auto;min-height:min(62vh,280px);padding:8px 8px 10px;gap:8px;
  }
  .gc-frame.gc-frame>.gc-frame-head,
  .gc-frame.gc-frame>.gc-stage-head{padding:6px 10px}
  .gc-canvas{
    max-height:62vh;
    max-height:max(150px,min(74dvh,calc(100dvh - 160px)));
  }
  .gc-pad{margin-top:4px;padding-bottom:calc(2px + env(safe-area-inset-bottom,0px))}
  .gc-pad:has(>:nth-child(5)):not(:has(>:nth-child(6))){
    grid-template-columns:repeat(4,46px);grid-template-rows:repeat(2,46px);gap:6px;
  }
  .gc-pad-b{width:46px;height:46px;font-size:16px}
  .gc-mem-stages{max-height:40vh}
  /* A finger does not get smaller when the phone is turned sideways, but the
     700px WIDTH gate in section 2 stops firing at 812px, so a landscape phone
     would drop straight back to the 33-34px controls this whole block exists to
     kill. The size rules — and only the size rules — are repeated here. */
  .gc-btn{min-height:44px;padding:10px 15px;display:inline-flex;
    align-items:center;justify-content:center;gap:7px}
  .gc-frame-head .gc-back,.gc-frame-head .gc-mode,.gc-frame-head .gc-sel,
  .gc-frame-tools .gc-back,.gc-frame-tools .gc-mode,.gc-frame-tools .gc-sel{
    height:auto;min-height:44px;display:inline-flex;align-items:center;
  }
  .gc-back,.gc-mode,.gc-chip,.gc-headbtn,.gc-sel,.gc-set-seg button,
  .gc-mem-perk,.gc-set-danger>button,.gc-set-confirm button{min-height:44px}
  .gc-icon-btn{width:44px;height:44px;font-size:17px;border-radius:11px}
  button.gc-tools-more,.gc-tools-more>button:first-child{width:44px;height:44px}
  .gc-switch{width:58px;height:34px;overflow:visible}
  .gc-switch::after{width:26px;height:26px}
  .gc-switch.on::after{right:3px}
  .gc-switch::before{content:"";position:absolute;inset:-5px -2px;border-radius:99px}
  .gc-card-help{width:30px;height:30px;font-size:13px;opacity:.8;top:7px;right:7px}
  .gc-card-help::after{content:"";position:absolute;inset:-7px;border-radius:50%}
  /* the 900px tablet layer pins the Wordle keys at height:40px */
  .gc-w5-k{height:46px}
}

/* ── 4b. only where the full-bleed phone card from section 2 is in force ── */
@media (max-width:700px) and (orientation:landscape) and (max-height:520px){
  .gc-overlay-card{padding:12px 14px 0}
  /* a column of full-width buttons in a 375px-tall window is the whole card;
     side by side they cost one row */
  .gc-overlay-btns{flex-direction:row;flex-wrap:wrap}
  .gc-overlay-btns>*{width:auto;flex:1 1 auto;min-width:140px}
}


/* ══ 5. THEME NEUTRALISER FOR THE NEW CONTROLS ════════════════════════════
   See hazard 4 in the banner. `[class*="theme-"] button.gc-btn` (0,2,1) repaints
   any button carrying .gc-btn with an !important accent gradient. If the
   framework unit gives .gc-tools-more that class the "⋯" would arrive as a
   solid primary button sitting next to three ghost icon buttons. These
   selectors are (0,3,1)/(0,4,1) and hand the icon-button look back. */
[class*="theme-"] button.gc-tools-more.gc-btn,
[class*="theme-"] .gc-tools-more>button.gc-btn:first-child{
  background:rgba(255,255,255,.05)!important;color:var(--muted)!important;
  border:1px solid var(--border)!important;box-shadow:none!important;
}
[class*="theme-"] button.gc-tools-more.gc-btn.on,
[class*="theme-"] button.gc-tools-more.gc-btn[aria-expanded="true"]{
  background:var(--accent-glow)!important;color:var(--accent)!important;
  border:1px solid var(--accent)!important;
}


/* ══ 6. REDUCED MOTION FOR THE NEW BITS ═══════════════════════════════════
   Both routes, as everywhere else in the Game Center: the OS preference and
   the .gc-reduce-motion class the settings panel puts on #view-games-body. */
.gc-reduce-motion .gc-continue{animation:none!important}
.gc-reduce-motion .gc-life{transition:none}
.gc-reduce-motion .gc-pad-b:active{background:rgba(255,255,255,.09)}
@media (prefers-reduced-motion:reduce){
  .gc-continue{animation:none}
  .gc-life{transition:none}
}
/* ══ end v9.10.657 ═══════════════════════════════════════════════════════ */


/* ══ v9.10.657 VERIFY PASS — cross-unit repairs ═══════════════════════════
   Two defects the parallel units could not see, because each was half of a
   contract the other half never met. Found by mounting the Game Center in a
   375x812 DOM and resolving the real cascade against each control's real
   ancestor chain (see the verify harness), not by reading either file alone. */

/* ── 1. THE OVERFLOW TOOL MENU WAS NEVER STYLED ──────────────────────────
   The CSS unit hedged between two possible shapes and styled the WRAPPER one:
     .gc-tools-more:not(button) > :last-child:not(:first-child)
   The framework unit shipped the SIBLING one — `<button class="gc-icon-btn
   gc-tools-more">` with a separate `<div class="gc-tools-menu">` appended
   alongside it in .gc-frame-tools. So `.gc-tools-menu` and
   .gc-tools-menu-row carried NO rule at all: opening ⋯ on a phone dropped a
   bare in-flow div into the middle of a wrapping flex row, shoving the tools
   it was meant to tidy off the head. Both the wrapper rules above and these
   stay — whichever shape is on screen, one of them applies.

   It has to be OUT OF FLOW for a second reason: layoutTools() folds tools
   until `tools.scrollWidth <= tools.clientWidth`, and an in-flow menu adds its
   own width to that measurement — so the row reads as overflowing however much
   is folded, and every control vanishes into a menu that is itself what does
   not fit. The JS closes the menu before measuring precisely because it
   expects this rule to exist. */
.gc-frame-tools{position:relative}
.gc-tools-menu{
  position:absolute;top:calc(100% + 8px);right:0;z-index:60;
  flex-direction:column;gap:6px;min-width:216px;max-width:min(280px,86vw);padding:8px;
  background:var(--panel-solid);border:1px solid var(--border);border-radius:13px;
  box-shadow:0 24px 60px -26px rgba(0,0,0,.95);
}
/* display lives here, not inline: the JS toggles style.display between 'none'
   and '' — the empty string falls back to whatever the sheet says, so this is
   the rule that decides what "open" looks like. */
.gc-tools-menu{display:flex}
.gc-tools-menu-row{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  min-height:44px;padding:0 4px;font:600 12.5px/1.35 var(--ui);color:var(--muted);
}
.gc-tools-menu-row+.gc-tools-menu-row{border-top:1px solid var(--border)}
.gc-tools-menu-row>span{flex:1 1 auto;min-width:0}
/* The tool itself was sized for a tight header row; in the menu it has room,
   and it is the thing being tapped. */
.gc-tools-menu-row>button,
.gc-tools-menu-row>select{flex:0 0 auto;min-height:44px;margin-left:0}
.gc-tools-menu-row>select{min-width:112px}

/* ── 2. THE VOLUME SLIDER STOPPED SHORT OF 44px ──────────────────────────
   The mobile pass took it from a 4px line to a 30px box — the right idea, one
   step short of the bar every other control in the head now clears. The track
   is already a pseudo-element, so the input can own the full 44px while the
   painted line stays 5px; nothing about the look changes. */
@media (max-width:700px){
  .gc-vol{height:44px}
}
/* ══ end v9.10.657 verify pass ═══════════════════════════════════════════ */

/* ── 3. THE FRAME SAID EDGE-TO-EDGE; THE STAGE STILL INSET IT ────────────
   The <=700px pass makes the frame explicitly full-bleed —
     .gc-frame.gc-frame{border-radius:0;border-left:none;border-right:none}
   — a border-radius of 0 and no side borders mean only one thing: it is meant
   to touch both edges of the phone. But `.gc-stage{padding:10px 10px 14px}`
   from the <=900px block still holds it 10px off each side, so the frame is
   full-bleed styling on a box that is not full-bleed. That 20px is also the
   last of the owner's "not using the full screen for the Setup": the start
   card is width:100% of an overlay that fills the frame, so every pixel the
   stage keeps is a pixel the card never sees.

   Measured at 375px: start card 317px (84.5%) before this pass, 343px (91.5%)
   after the card/overlay work, 363px (96.8%) with this. Vertical padding is
   left alone — that is spacing from the head and the tab bar, not wasted
   width — and .gc-frame-body keeps its own 7px so nothing touches glass. */
@media (max-width:700px){
  .gc-stage{padding-left:0;padding-right:0}
}
/* ══ end v9.10.657 verify pass ═══════════════════════════════════════════ */


/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.659 — GAME CENTER: THE MOTION LAYER

   VISUAL DIRECTION. Oracle OS is a dark sci-fi LATTICE: thin geometry, accent
   glow, depth from shadow and blur. Never flat cartoon. Five laws, and every
   rule below obeys them:

     1. EASING, NOT LINEAR.  Things accelerate and settle. The only constant
        speed anywhere in this block is a fall under gravity.
     2. GLOW, NOT OUTLINE.   Emphasis is light bleeding out of a shape, not a
        stroke drawn around it.
     3. WEIGHT AND FOLLOW-THROUGH. A dropped disc squashes on the LANDING frame
        and rebounds twice. A revealed tile overshoots and settles.
     4. SMALL SHAKE, REAL IMPACT ONLY. There is exactly one shake in the whole
        Game Center — a mine going off — and it travels 3px.
     5. KILLABLE. Both reduced-motion routes neutralise all of it (section 7).
        Nothing here carries meaning: take the motion away and every board still
        reads correctly.

   PERFORMANCE. Only transform / opacity / filter / box-shadow are animated —
   never width, height, top, left or margin — so nothing in this block can
   trigger layout. `will-change` appears ONLY on the transient GC.anim classes,
   which the framework strips on animationend: no element is left holding a
   compositor layer it is not currently using. On the owner's phone that is the
   difference between one promoted layer per ANIMATING tile and one per tile,
   forever.

   NO LAYOUT SHIFT. Where a rule needs stacking (a falling disc in front of the
   empty holes it passes, a sliding tile over the one it crosses) it uses
   position:relative on a grid item, which changes paint order and nothing else.

   ── THE CONTRACT, AS THE JS UNITS ACTUALLY SHIPPED IT ────────────────────────
   Read from oracle-games.js rather than assumed. `GC.anim(node,kind)` maps kind
   to a class and strips it on animationend, with a per-class cleanup timer:

     kind       class         ANIM_MS   this sheet's worst case (delay+run)
     'drop'     .gc-drop        560ms    500ms
     'flipx'    .gc-flipx       640ms    600ms  (200ms stagger cap + 400ms run)
     'slide'    .gc-slide       520ms    320ms
     'ripple'   .gc-ripple      720ms    700ms  (400ms cap + 300ms run)
     'bloom'    .gc-bloom       820ms    780ms  (340ms cap + 440ms run)
     'stagger'  .gc-stagger     700ms    280ms  (delay is inline, from GC.stagger)

   Every duration here is chosen to finish INSIDE its cleanup timer. If a
   duration below is ever lengthened, ANIM_MS has to move with it — a class
   stripped mid-animation cancels it and the element snaps.

   `.gc-stagger` is a PER-NODE class, not a container class: GC.stagger walks a
   list, writes `style.animationDelay` on each node and adds the class. Inline
   delay beats this sheet, which is what makes one rule serve every wave.

   Four custom properties steer the rest. Set them INLINE from JS
   (`node.style.setProperty('--gc-i', 3)`) — inline is what makes them
   per-element:

     --gc-i          stagger index; multiplied by --gc-step to make the delay.
                     Feed it a COLUMN for Word Five, the DISTANCE FROM THE TAP
                     for a Minesweeper flood, the POSITION ALONG THE LINE for a
                     Reversi cascade. Every use is clamped, per the table above.
     --gc-dx/--gc-dy where a .gc-slide travels FROM, relative to where it already
                     is. A 2048 tile that moved three columns left sets
                     `--gc-dx:246px` (positive = it came from the right).
     --gc-drop-from  how far above a .gc-drop starts. Default -46px suits the
                     panels and cards that call 'drop' today; board cells get a
                     long fall from the rule below, and Connect Four should pass
                     `calc(row * -100% - 100%)` so a disc entering the bottom row
                     falls further than one landing on top — which is the entire
                     point of a drop.

   ── WHAT NEEDS A JS HANDSHAKE AND WHAT DOES NOT ─────────────────────────────
   Section 3 (backdrop, continue panel, tools menu, buttons, focus, hover) needs
   nothing from anybody: those elements are built fresh when shown or toggled
   through display:none, and both restart a CSS animation on their own.

   The per-piece game motion does need the handshake, and it needs it because
   the boards re-render WHOLESALE on every move. An unconditional animation on
   `.gc-lo-c.on` would re-pulse every lit cell on every click; on `.gc-ms-c.open`
   it would re-reveal the entire cleared field every time you clear one more
   square. Exactly one game state is safe to animate directly — `.gc-ms-c.boom`,
   which appears once and then the board stops repainting forever (section 4).

   ── WHAT THIS BLOCK DELIBERATELY DOES NOT TOUCH ─────────────────────────────
   `.gc-overlay-card`, `.gc-modal-card`, `.gc-frame` and `.gc-hero` are all
   driven by GC.anim / GC.stagger now. An element has ONE `animation` property,
   so a rule here would silently cancel theirs. Checked in oracle-games.js, not
   assumed: overlay cards at :2453 (`o.enter || 'drop'`), modal card at :1794,
   frame at :2371, hero in the chrome wave at :1455.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── 1. MOTION TOKENS ─────────────────────────────────────────────────────────
   On :root so the vocabulary resolves for anything the Game Center portals out
   of its own subtree. Every name is --gc- prefixed and none collides with the
   one that already existed (--gc-accent, set per-tile by the library). */
:root{
  /* the house curve — leaves fast, arrives slow, no bounce */
  --gc-ease:cubic-bezier(.2,.8,.3,1);
  /* arrival only: things already moving when you first see them */
  --gc-ease-out:cubic-bezier(.16,.9,.28,1);
  /* departure only: gravity, and anything that should feel heavy */
  --gc-ease-in:cubic-bezier(.45,0,.85,.5);
  /* one small overshoot — for reveals and presses, never for travel */
  --gc-spring:cubic-bezier(.18,.9,.28,1.28);
  --gc-t-fast:.16s;
  --gc-t:.28s;
  --gc-t-slow:.4s;
  /* the gap between one staggered element and the next */
  --gc-step:38ms;
}

/* ── 2. THE ANIMATION VOCABULARY ────────────────────────────────────────────── */

/* DROP — Connect Four discs, and every panel that arrives over the library.
   The squash is on the LANDING frame, never during the fall: things deform when
   they hit something, not while they are in the air. The squash amounts are
   variables so one keyframe can serve both callers — a 6px disc wants a real
   splat, a 700px settings panel wants a hint of one. */
@keyframes gcDrop{
  0%  {transform:translate3d(0,var(--gc-drop-from,-46px),0);opacity:0;
       animation-timing-function:var(--gc-ease-in)}
  9%  {opacity:1;animation-timing-function:var(--gc-ease-in)}
  54% {transform:translate3d(0,0,0) scale3d(var(--gc-squash-x,1.03),var(--gc-squash-y,.96),1);
       animation-timing-function:var(--gc-ease-out)}
  68% {transform:translate3d(0,-14%,0) scale3d(1,1.02,1)}
  82% {transform:translate3d(0,0,0) scale3d(var(--gc-squash-x,1.03),var(--gc-squash-y,.96),1)}
  92% {transform:translate3d(0,-4%,0)}
  100%{transform:translate3d(0,0,0)}
}
.gc-drop{
  animation:gcDrop .5s linear both;
  position:relative;z-index:2;will-change:transform,opacity;
}
/* A BOARD CELL falls the height of a board, not 46px, and lands like a checker.
   Scoped to .gc-c so the panels that also use 'drop' keep the gentle default.
   An inline --gc-drop-from from the game still beats this. */
.gc-c.gc-drop{--gc-drop-from:-320%;--gc-squash-x:1.11;--gc-squash-y:.86}

/* FLIP — Reversi captures, Word Five reveals, Memory Match cards.
   Hinged at the top edge, because that is what every flip-to-reveal anyone has
   played does. The brightness spike at the halfway point is the edge catching
   the light: without it a flat-coloured disc passing through 90° simply seems
   to vanish for a frame, which reads as a dropped frame rather than a flip.
   Stagger with --gc-i and a capture line cascades outward from the stone that
   took it; a Word Five row reveals left to right. .gc-flipy is the same motion
   about the vertical axis for anything that reads better spinning sideways. */
@keyframes gcFlipX{
  0%  {transform:perspective(560px) rotateX(-180deg) scale(.92);filter:brightness(.5)}
  48% {transform:perspective(560px) rotateX(-96deg)  scale(1.06);filter:brightness(1.65)}
  76% {transform:perspective(560px) rotateX(12deg)   scale(1.02);filter:brightness(1.08)}
  100%{transform:perspective(560px) rotateX(0deg)    scale(1);filter:none}
}
@keyframes gcFlipY{
  0%  {transform:perspective(560px) rotateY(-180deg) scale(.92);filter:brightness(.5)}
  48% {transform:perspective(560px) rotateY(-96deg)  scale(1.06);filter:brightness(1.65)}
  76% {transform:perspective(560px) rotateY(12deg)   scale(1.02);filter:brightness(1.08)}
  100%{transform:perspective(560px) rotateY(0deg)    scale(1);filter:none}
}
.gc-flipx,
.gc-flipy{
  animation-duration:.4s;
  animation-timing-function:var(--gc-ease);
  animation-fill-mode:both;
  /* capped at 200ms so delay + run stays inside ANIM_MS['gc-flipx'] = 640ms.
     At the 38ms default step that is five tiles apart — exactly a Word Five
     row — and a longer Reversi cascade simply tightens up rather than
     overrunning its own cleanup. */
  animation-delay:min(calc(var(--gc-i,0) * var(--gc-step)),200ms);
  position:relative;z-index:1;will-change:transform,filter;
  backface-visibility:visible;
}
.gc-flipx{animation-name:gcFlipX}
.gc-flipy{animation-name:gcFlipY}

/* SLIDE — 2048 and Fifteen tiles, and the play frame arriving over the library.
   The tile is PAINTED WHERE IT ENDS and animated back to where it started, so
   the DOM is correct on the very first frame and a dropped animation can never
   leave a tile lying about its own position. Flat-out and short: the player
   already knows where the tile is going, so this is the one motion that should
   feel instant. z-index:3 so a tile crossing the board passes over the ones it
   slides past instead of under them. */
@keyframes gcSlide{
  from{transform:translate3d(var(--gc-dx,4%),var(--gc-dy,0),0)}
  to  {transform:translate3d(0,0,0)}
}
.gc-slide{
  animation:gcSlide var(--gc-t-fast) cubic-bezier(.25,.86,.36,1) both;
  position:relative;z-index:3;will-change:transform;
}
/* The frame is not a tile: opening a game is a navigation, so it comes in from
   the side AND fades, over a longer beat. Two animations on one element is
   fine — they are both declared here, so neither can silently cancel the
   other. Still inside ANIM_MS['gc-slide'] = 520ms. */
.gc-frame.gc-slide{
  --gc-dx:5%;
  animation:gcSlide .32s var(--gc-ease-out) both,gcFadeIn .26s ease both;
}

/* RIPPLE — the Minesweeper flood, the Lights Out plus-shape.
   Fill-mode `both` plus a distance-scaled delay is the whole trick: the cell
   sits at opacity 0 for its share of the delay, so a cleared region washes
   outward from the tap instead of arriving in one slab. Feed --gc-i the
   Chebyshev distance from the clicked cell for Minesweeper — a square flood
   front, which is how the flood actually spreads — and 0 for the centre / 1 for
   the four arms in Lights Out, so the plus resolves in two beats.
   Worst case 400ms + 300ms = 700ms, inside ANIM_MS['gc-ripple'] = 720ms. */
@keyframes gcRipple{
  0%  {opacity:0;transform:scale(.55)}
  42% {opacity:1;transform:scale(1.07)}
  100%{opacity:1;transform:scale(1)}
}
.gc-ripple{
  animation:gcRipple .3s var(--gc-ease) both;
  animation-delay:min(calc(var(--gc-i,0) * 30ms),400ms);
  will-change:transform,opacity;
}

/* BLOOM — Echo's pads, the level banner, the big result card.
   A pad does not switch on, it floods. The glow colour is a variable rather
   than currentColor: Echo sets its pads' identity colour as a `background`, so
   currentColor there is the inherited TEXT colour and would have glowed white.
   --gc-glow lets the pack pass the pad's real colour; everything else glows
   with the theme accent, which on the owner's RED theme means red.
   Worst case 340ms + 440ms = 780ms, inside ANIM_MS['gc-bloom'] = 820ms. */
@keyframes gcBloom{
  0%  {transform:scale(1);filter:brightness(1) saturate(1);
       box-shadow:0 0 0 0 transparent}
  26% {transform:scale(1.06);filter:brightness(1.7) saturate(1.2);
       box-shadow:0 0 40px 9px var(--gc-glow,var(--accent))}
  62% {filter:brightness(1.18) saturate(1.05);
       box-shadow:0 0 22px 4px var(--gc-glow,var(--accent))}
  100%{transform:scale(1);filter:brightness(1) saturate(1);
       box-shadow:0 0 0 0 transparent}
}
.gc-bloom{
  animation:gcBloom var(--gc-t-slow) var(--gc-ease) both;
  animation-delay:min(calc(var(--gc-i,0) * var(--gc-step)),340ms);
  will-change:transform,filter;
}

/* STAGGER — the entrance wave. One rule, because GC.stagger writes the delay
   inline on every node it touches and inline beats this sheet.
   The travel is UPWARD-TO-REST (starts 10px above, settles down) and never
   downward, which is not a style choice: #view-games-body scrolls, .gc-shelf-r
   is overflow-x:auto so its overflow-y computes to auto too, and in both a
   child translated DOWN extends the scrollable region and flashes a scrollbar
   for the length of the animation. Translating up cannot — the scrollable area
   never grows above the top edge. Same look, no scrollbar flash. */
@keyframes gcRise{
  from{opacity:0;transform:translate3d(0,-10px,0) scale(.985)}
  to  {opacity:1;transform:none}
}
.gc-stagger{animation:gcRise var(--gc-t) var(--gc-ease) both}

/* LEAVING — a matched Memory pair, a taken Nim stick, a cleared row. Not
   registered in ANIM, so it comes through GC.anim's `'gc-' + kind` fallback and
   its 900ms timer; 340 + 300 is well inside that. Things that go away should go
   away — snapping to opacity:.4 reads as a bug, not as a rule. */
@keyframes gcOut{
  0%  {opacity:1;transform:scale(1)}
  35% {opacity:1;transform:scale(1.09);filter:brightness(1.4)}
  100%{opacity:0;transform:scale(.72);filter:brightness(1)}
}
.gc-out{
  animation:gcOut .3s var(--gc-ease-in) both;
  animation-delay:min(calc(var(--gc-i,0) * var(--gc-step)),340ms);
  will-change:transform,opacity;pointer-events:none;
}

/* ── 3. THE SHELL: MOTION THAT NEEDS NO JS UNIT ───────────────────────────────
   Everything here is created fresh when it appears or toggled through
   display:none, and going from display:none to displayed restarts a CSS
   animation. So these run today, without waiting on anyone — and none of them
   is an element GC.anim already owns. */

@keyframes gcFadeIn{from{opacity:0}to{opacity:1}}

/* THE MODAL BACKDROP. gcModal() builds it per open and appends it into
   #view-games-body. The CARD is GC.anim's ('drop', oracle-games.js:1794) — this
   is only the dim behind it, so the panel does not arrive over a hard cut. */
.gc-modal{animation:gcFadeIn .18s ease both}

/* THE CONTINUE PANEL — the one screen in the arcade that has to read as an
   offer rather than an obituary. showContinue() builds it fresh and reveals it
   by dropping the inline display, so this fires once per death and never on the
   countdown that ticks inside it. Its CHILDREN are GC.stagger's (:1224); only
   the panel itself is mine.
   The existing infinite accent breath is kept and pushed behind the entrance so
   the two never run over each other. */
@keyframes gcContinueIn{
  0%  {opacity:0;transform:translate3d(0,20px,0) scale(.94)}
  60% {opacity:1}
  100%{opacity:1;transform:none}
}
.gc-continue{
  animation:gcContinueIn .34s var(--gc-spring) both,
            gcContinueGlow 2.2s ease-in-out .34s infinite;
  will-change:transform,opacity;
}
/* Flattened inside an overlay or a modal, the panel is not a card any more —
   its parent already did the arriving, so it only fades. The older rule set
   `animation:none` here, which ALSO out-specifies .gc-stagger and would silently
   swallow the wave if the panel is ever a direct child of .gc-modal-b (which
   GC.stagger walks at :1795). Both shapes are answered. */
.gc-overlay-card .gc-continue,
.gc-modal-b .gc-continue{animation:gcFadeIn .2s ease both}
.gc-overlay-card .gc-continue.gc-stagger,
.gc-modal-b .gc-continue.gc-stagger{animation:gcRise var(--gc-t) var(--gc-ease) both}

/* THE OVERFLOW TOOL MENU. The JS toggles style.display between 'none' and '',
   so it re-animates on every open. It grows out of the ⋯ that opened it. */
@keyframes gcMenuIn{
  from{opacity:0;transform:translate3d(0,-8px,0) scale(.94)}
  to  {opacity:1;transform:none}
}
.gc-tools-menu{
  animation:gcMenuIn .16s var(--gc-ease-out) both;
  transform-origin:top right;
}
.gc-tools-menu-row{animation:gcFadeIn .2s ease both}
.gc-tools-menu-row:nth-child(2){animation-delay:.03s}
.gc-tools-menu-row:nth-child(3){animation-delay:.06s}
.gc-tools-menu-row:nth-child(4){animation-delay:.09s}
.gc-tools-menu-row:nth-child(5){animation-delay:.12s}

/* BUTTONS — real depth on press.
   ENHANCEMENT ONLY: no background and no colour, because the theme layer owns
   those with !important and has to keep winning. What changes is the shadow
   underneath and how far the button travels, which is the whole difference
   between a press that feels like a press and a 1px jump. */
.gc-btn{
  transition:transform .12s var(--gc-ease),box-shadow .16s var(--gc-ease),
             border-color .14s,background .14s;
}
.gc-btn:hover:not(:disabled){
  transform:translateY(-1px);
  box-shadow:0 10px 22px -14px rgba(0,0,0,.95),0 0 0 1px var(--accent-glow);
}
.gc-btn:active:not(:disabled){
  transform:translateY(1px) scale(.985);
  box-shadow:inset 0 2px 6px rgba(0,0,0,.5);
  transition-duration:.06s;                 /* a press must never lag the finger */
}
.gc-btn-primary:hover:not(:disabled){
  box-shadow:0 12px 26px -12px var(--accent),0 0 0 1px var(--accent-glow);
}
.gc-icon-btn{
  transition:transform .12s var(--gc-ease),background .14s,border-color .14s,
             color .14s,box-shadow .16s;
}
.gc-icon-btn:active:not(:disabled){transform:translateY(1px) scale(.94);transition-duration:.06s}

/* FOCUS — visible, and part of the aesthetic rather than an apology for it.
   Two rings: a dark one to separate the control from whatever is behind it,
   then the accent. Scoped to the Game Center so it cannot leak into the rest of
   the OS, and pitched above the older .gc-btn / .gc-icon-btn focus rules so
   every focusable thing in the view gets the SAME ring. That is the actual fix:
   a board cell used to get the browser default while a button got a faint glow,
   and keyboard play looked broken as a result. */
#view-games-body button:focus-visible,
#view-games-body select:focus-visible,
#view-games-body input:focus-visible,
#view-games-body textarea:focus-visible,
#view-games-body a:focus-visible,
#view-games-body [tabindex]:focus-visible{
  outline:2px solid transparent;   /* forced-colors mode still draws a real ring */
  outline-offset:2px;
  box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--accent),0 0 18px 0 var(--accent-glow);
  z-index:5;
}
/* A focused board cell sits in a tight grid: the ring has to paint over its
   neighbours or the cell beside it clips it into an L. */
#view-games-body .gc-c:focus-visible,
#view-games-body .gc-si-p:focus-visible,
#view-games-body .gc-ms-c:focus-visible{position:relative}

/* HOVER ON THE LIBRARY — same displacement as before, better curve, and a
   shadow so the tile lifts off the page instead of just moving up it. */
.gc-card,
.gc-shelf-c{
  transition:transform .18s var(--gc-ease),border-color .16s,
             background .16s,box-shadow .18s var(--gc-ease);
}
.gc-card:hover{box-shadow:0 18px 34px -22px rgba(0,0,0,.95)}
.gc-shelf-c:hover{box-shadow:0 14px 26px -18px rgba(0,0,0,.9)}
/* the accent bar down the edge of a card lights up rather than sitting there */
.gc-card::before{transition:opacity .18s var(--gc-ease)}
.gc-card:hover::before{opacity:1}
/* A phone has no hover — but it DOES fire :hover on tap and then leave it stuck
   on the tile you just left. Killing the displacement there is a bug fix. */
@media (hover:none){
  .gc-card:hover,
  .gc-shelf-c:hover{transform:none}
}

/* ── 4. THE ONE PIECE OF GAME MOTION THAT NEEDS NO JS ──────────────────────────
   A mine is the single state in the pack that appears exactly once and then
   freezes — the board stops re-rendering the moment you hit it — so animating
   the state class directly is safe here and nowhere else.
   Red flash, then a shake that travels 3px. That is the entire shake budget for
   the Game Center, spent on the only real impact in it. --bad is the token,
   mixed down for the glow so the owner's RED theme drives the colour. */
@keyframes gcBoom{
  0%  {transform:scale(1) translate3d(0,0,0);filter:brightness(1);
       box-shadow:0 0 0 0 transparent}
  10% {transform:scale(1.22) translate3d(-3px,0,0);filter:brightness(2);
       box-shadow:0 0 36px 10px color-mix(in srgb,var(--bad) 80%,transparent)}
  24% {transform:scale(1.06) translate3d(3px,0,0);filter:brightness(1.4)}
  38% {transform:scale(1.12) translate3d(-2px,0,0);
       box-shadow:0 0 24px 5px color-mix(in srgb,var(--bad) 55%,transparent)}
  54% {transform:scale(1) translate3d(2px,0,0)}
  70% {transform:scale(1.03) translate3d(-1px,0,0)}
  100%{transform:scale(1) translate3d(0,0,0);filter:brightness(1);
       box-shadow:0 0 0 0 transparent}
}
.gc-ms-c.boom{
  animation:gcBoom .62s var(--gc-ease-out) both;
  position:relative;z-index:4;
}

/* ── 5. ECHO'S PADS: BLOOM INSTEAD OF A SWITCH ────────────────────────────────
   The pads are built ONCE and only `.lit` is toggled, so unlike every board in
   the pack they can be driven by a transition — and a transition is the right
   tool here, because a pad has to fade back down while the NEXT pad is already
   coming up, which two competing one-shot animations cannot do.
   No transform: the game already calls GC.anim(pad,'pop'), and two owners of
   `transform` on one element is a double bump on every press. The scale belongs
   to the pop; the light belongs here. */
.gc-si-p{
  transition:opacity .12s var(--gc-ease),filter .16s var(--gc-ease),
             box-shadow .22s var(--gc-ease);
}
.gc-si-p.lit{
  opacity:1;
  filter:brightness(1.35) saturate(1.15);
  box-shadow:0 0 38px 8px var(--gc-glow,currentColor),
             inset 0 0 0 2px rgba(255,255,255,.4);
}

/* ── 6. DEPTH ON THE BOARDS ───────────────────────────────────────────────────
   Not motion, but the same brief: the boards read as flat swatches next to the
   rest of the OS. Everything here is a SHADOW — no hue is touched anywhere, so
   every piece-identity colour (Connect Four red/yellow, Reversi black/white)
   survives exactly as it was, which is the point of those being hardcoded. */

/* the board sits IN the panel rather than on top of it */
.gc-g-c4,
.gc-g-ov,
.gc-g-gm,
.gc-2048-b{
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),
             inset 0 0 30px rgba(0,0,0,.35),
             0 18px 40px -30px rgba(0,0,0,.95);
}
/* an empty Connect Four slot is a hole punched through the board */
.gc-c4{box-shadow:inset 0 3px 7px rgba(0,0,0,.7),inset 0 -1px 0 rgba(255,255,255,.05)}
/* a disc is a sphere: lit from above, dark underneath, sitting on the board */
.gc-c4-R,
.gc-c4-Y{
  box-shadow:inset 0 4px 9px rgba(255,255,255,.32),
             inset 0 -5px 11px rgba(0,0,0,.38),
             0 2px 6px rgba(0,0,0,.45);
}
.gc-ov-B{box-shadow:inset 0 3px 8px rgba(255,255,255,.16),inset 0 -4px 9px rgba(0,0,0,.6),0 2px 5px rgba(0,0,0,.5)}
.gc-ov-W{box-shadow:inset 0 3px 8px rgba(255,255,255,.75),inset 0 -4px 9px rgba(0,0,0,.24),0 2px 5px rgba(0,0,0,.5)}
/* the legal-move hint answers the pointer instead of sitting there as a square */
.gc-ov-hint{transition:box-shadow .18s var(--gc-ease),background .18s var(--gc-ease)}
.gc-ov-hint:hover:not(:disabled){box-shadow:inset 0 0 0 1px var(--good),0 0 16px -2px var(--good)}

/* ── 7. REDUCED MOTION — BOTH ROUTES, ALL OF IT ───────────────────────────────
   Three layers of defence, because each one has a hole the others cover:

   (a) GC.anim and GC.stagger now refuse to add a class at all when the SETTINGS
       toggle is on (oracle-games.js:464). That covers everything routed through
       them — but it reads GC.settings().reducedMotion only, so it knows nothing
       about the OS preference.
   (b) The `.gc-reduce-motion` blanket earlier in this sheet already matches `*`
       inside the games view, so it covers every rule in this block that is NOT
       routed through GC.anim: the hover transitions, the continue panel, the
       tools menu, the pads.
   (c) The OS-preference route had NO blanket — only a hand-listed set of Memory
       Match rules — so it gets one here, scoped to the Game Center so it cannot
       reach across the rest of the OS.

   NEAR-ZERO DURATIONS, NOT `animation:none`. GC.anim removes its class on
   animationend; killing the animation outright means that event never fires and
   stale gc-flipx / gc-drop classes pile up on recycled cells. A .001ms animation
   still ends, so the cleanup still runs — and because every animation above uses
   fill-mode `both`, ending instantly lands the element on its FINAL frame:
   opacity 1, transform none, fully legible. Turning the motion off can never
   leave anything invisible. */
@media (prefers-reduced-motion:reduce){
  #view-games-body,
  #view-games-body *,
  #view-games-body *::before,
  #view-games-body *::after,
  .gc-drop,.gc-flipx,.gc-flipy,.gc-slide,.gc-ripple,.gc-bloom,.gc-out,.gc-stagger{
    animation-duration:.001ms!important;
    animation-delay:0s!important;
    animation-iteration-count:1!important;
    transition-duration:.001ms!important;
    transition-delay:0s!important;
  }
  /* the loading spinner is the one exemption, exactly as on the class route: a
     frozen spinner communicates nothing at all */
  #view-games-body .gc-spin{animation-duration:2.4s!important;animation-iteration-count:infinite!important}
  /* displacement is motion too */
  #view-games-body .gc-card:hover,
  #view-games-body .gc-shelf-c:hover,
  #view-games-body .gc-btn:hover:not(:disabled),
  #view-games-body .gc-btn:active:not(:disabled),
  #view-games-body .gc-icon-btn:active:not(:disabled){transform:none}
  /* the continue panel's breathing ring becomes a STATIC ring — the panel still
     has to stand out, it just stops moving. Without this the infinite glow ends
     on its own last frame, which is no shadow at all.
     MEASURED, not assumed: v9.10.657 already put `animation:none!important` on
     .gc-continue for BOTH routes (oracle.css:8959 and :8963), so under reduced
     motion the panel really does end up with no animation and therefore no
     shadow at all — Chrome reports animation-name:none on it. This static ring
     is what the player actually sees, and without it the panel would be a flat
     rectangle exactly when it most needs to stand out. */
  .gc-continue{box-shadow:0 22px 50px -26px rgba(0,0,0,.9),0 0 0 3px var(--accent-glow)}
  /* the mine is a state class, not a GC.anim class — nothing is listening for
     its animationend, so this one may be switched off outright */
  .gc-ms-c.boom{animation:none!important;box-shadow:0 0 0 2px var(--bad)}
}
/* The class route already has its blanket; it needs only the same two endings
   the media route spells out above. */
.gc-reduce-motion .gc-continue{
  box-shadow:0 22px 50px -26px rgba(0,0,0,.9),0 0 0 3px var(--accent-glow);
}
.gc-reduce-motion .gc-ms-c.boom{animation:none!important;box-shadow:0 0 0 2px var(--bad)}
/* ══ end v9.10.659 — Game Center motion layer ═══════════════════════════════ */

/* ══ v9.10.660 — CANVAS RESERVE WAS TOO GENEROUS ═════════════════════════
   Owner: the game is "super small" and should use the screen. MEASURED on a
   real 375x812 phone: Floppy KAI is a 420x640 portrait game rendering at
   246x374 — 66% of the width and 46% of the height — while its own container
   had 428px of room.
   The cap was  max(180px, min(46dvh, calc(100dvh - 430px)))  = 373px. That
   430px reserve for head + HUD + d-pad + foot is ~167px more than the chrome
   actually measures (head 66 + hud 40 + pad 111 + foot 46 = 263). The d-pad
   sat at bottom=683 on an 812px screen with 129px of unused slack below it.
   Reserve what the chrome COSTS, not a round number, and keep a margin so a
   short phone still shows the pad. This is the interim fix — the real answer
   is the aspect-driven fullscreen in GAME-CENTER-ARCADE-GOAL.md Phase A. */
@media (max-width:700px){
  .gc-canvas{
    max-height:55vh;
    max-height:max(200px,min(55dvh,calc(100dvh - 300px)));
  }
}
/* Desktop was the original complaint: a 1349px window showing a 360px game. */
@media (min-width:901px){
  .gc-canvas{width:auto;height:clamp(460px,74vh,940px);max-width:100%;object-fit:contain}
}

/* ══ v9.10.661 — max-height IS THE CAP, height is only a request ══════════
   The v9.10.660 desktop rule set  height: clamp(460px,74vh,940px)  and the
   canvas stayed at 552px, because an earlier  .gc-canvas{max-height:66vh}
   still capped it — 66vh of 837 = 552 exactly. Setting height cannot beat a
   max-height, the same way appending a rule cannot beat higher specificity.
   Raise the CAP as well as the request. */
@media (min-width:901px){
  .gc-canvas{
    max-height:min(78vh,940px);
    height:clamp(460px,78vh,940px);
    width:auto;max-width:100%;object-fit:contain;
  }
}

/* ══ v9.10.662 — multiplayer server browser ══════════════════════════════
   Two friends both pressed Online, both became hosts, and each sat in a room
   of one being told everything was fine. A waiting room with no way to SEE
   who else is out there is why multiplayer felt broken. */
.gc-mp-browser{width:min(560px,94%);margin:18px auto 0;text-align:left}
.gc-mp-h{font:700 10.5px var(--ui);letter-spacing:1.4px;text-transform:uppercase;
  color:var(--muted);margin-bottom:9px;display:flex;align-items:center;gap:8px}
.gc-mp-h span{font:600 10px var(--mono);color:var(--good);letter-spacing:0;
  background:rgba(74,222,128,.14);padding:2px 7px;border-radius:99px}
.gc-mp-none{padding:12px 14px;background:rgba(255,255,255,.03);border-radius:10px;
  border:1px dashed var(--border);line-height:1.55}
.gc-mp-list{display:flex;flex-direction:column;gap:7px}
.gc-mp-row{display:flex;align-items:center;gap:11px;width:100%;min-height:52px;
  padding:9px 13px;border-radius:11px;cursor:pointer;text-align:left;
  border:1px solid var(--border);background:var(--c-card-bg);color:var(--text);transition:.15s}
.gc-mp-row:hover{border-color:var(--accent);background:var(--accent-glow);transform:translateX(2px)}
.gc-mp-row.same{border-color:rgba(74,222,128,.42)}
.gc-mp-i{font-size:22px;line-height:1;flex:none}
.gc-mp-n{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.gc-mp-n b{font:600 13px var(--ui)}
.gc-mp-n i{font:400 11px var(--ui);color:var(--muted);font-style:normal}
.gc-mp-c{font:700 12px var(--mono);color:var(--accent);flex:none}
@media (max-width:700px){
  .gc-mp-browser{width:100%}
  .gc-mp-row{min-height:56px}
}

/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.663 — ORACLE ARCADE: CONSOLE BOOT → IMMERSIVE SHELL → FULLSCREEN PLAY

   THE INTENT (owner): tapping the Games icon should feel like powering on a
   console — the Oracle mark boots up with a chime, then an Arcade OS shell
   appears the way Workspace does, you pick a game, and the game plays FULL
   SCREEN inside Oracle OS. Mobile is the primary target, not a port.

   THREE PARTS, THREE CONTRACTS with the JS unit:
     1  .oa-boot            transient full-bleed console warm-up. Children:
                            .oa-boot-mark (drawn logo — inline SVG/canvas; there
                            is no image asset and the CSP would block one),
                            .oa-boot-sweep (lattice + scanline field),
                            .oa-boot-title, .oa-boot-bar, .oa-boot-skip.
                            Fade out by adding .oa-out, remove on transitionend.
     2  body.os-arcade-immersive + .oa-shell / .oa-shell-top / .oa-shell-body /
                            .oa-exit. The body class MIRRORS os-workspace-immersive
                            (oracle.css:500-517) selector for selector — same
                            chrome hidden, same fixed .shell/.col-center, same
                            z-index band — because two different mechanisms for
                            "the OS gets out of the way" is how one of them rots.
                            Leaving is the JS unit's leave hook, not CSS.
     3  body.os-arcade-play + .oa-stage (alias .oa-play) for the game itself.
                            .oa-exit is styled for BOTH placements: in flow when
                            it sits inside .oa-shell-top, floating and fixed when
                            it stands alone or a game is running. If you call
                            requestFullscreen, call it on .oa-stage and keep
                            .oa-exit INSIDE it — the top layer does not render
                            elements from outside the fullscreen subtree. Real
                            fullscreen is refused outright on iOS Safari for
                            non-video elements, so body.os-arcade-play alone
                            produces the identical in-app result without it.

   WHY THE CLASS-SCOPE DISCIPLINE. Everything below is either .oa-* or scoped
   under body.os-arcade-*. Not one bare .gc-* rule is added, because the phone
   suite (games_mobile_test.js) resolves the real cascade at 375x812 and asserts
   0 controls under 44px, a start card >= 92% of the screen and no horizontal
   overflow. A bare .gc-canvas or .gc-pad-b rule here would silently win over
   those and take the suite red. The existing non-fullscreen canvas caps
   (v9.10.660/661) are deliberately left untouched — fullscreen overrides them
   only while body.os-arcade-play is set.

   Design tokens only. dvh with a vh fallback everywhere the viewport is
   measured, because the mobile URL bar makes vh lie. env(safe-area-inset-*) on
   every edge-anchored control. Reduced motion is honoured on all three routes
   the OS actually uses: @media (prefers-reduced-motion:reduce), body.reduce-motion
   (kai.os.reduceMotion, oracle.css:5633) and .gc-reduce-motion (GC settings).
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE CONSOLE BOOT ──────────────────────────────────────────────────────
   A CRT warm-up: a hairline flash blooms open, the mark settles under a lattice
   sweep, the title resolves, a thin bar runs. No bounce, nothing overshoots.
   z-index sits above every app modal (200060) and toast (99999) but BELOW the
   scope-boot curtain at 2147483000, which is a security guard (oracle.css:1391)
   and must never be painted over. */
.oa-boot{
  position:fixed;inset:0;z-index:2147482000;
  box-sizing:border-box;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:max(20px,env(safe-area-inset-top,0px)) 20px calc(max(18px,env(safe-area-inset-bottom,0px)) + 64px);
  background:
    radial-gradient(120% 82% at 50% 44%,var(--accent-glow),transparent 58%),
    radial-gradient(150% 120% at 50% 118%,var(--bg-2),transparent 68%),
    var(--bg);
  color:var(--text);
  overflow:hidden;                 /* the title resolves in from a wide letter-spacing;
                                      this is what stops that becoming a scrollbar */
  cursor:pointer;
  touch-action:manipulation;
  -webkit-user-select:none;user-select:none;
  -webkit-tap-highlight-color:transparent;
  opacity:1;
  transition:opacity .34s ease;
}
.oa-boot.oa-out{opacity:0;pointer-events:none}
.oa-boot[hidden]{display:none !important}
/* stacking: sweep behind, content above it, vignette above that, skip on top,
   the CRT flash over everything (it fades out and stops mattering) */
.oa-boot>*{position:relative;z-index:2}

/* the power-on hairline: a bright line that blooms to full field and dies */
.oa-boot::before{
  content:'';position:absolute;left:0;right:0;top:50%;height:2px;margin-top:-1px;
  z-index:5;pointer-events:none;
  background:rgba(255,255,255,.92);
  box-shadow:0 0 34px 8px var(--accent-glow);
  animation:oaCrt .66s cubic-bezier(.3,.9,.3,1) both;
}
/* vignette — a tube has dark corners */
.oa-boot::after{
  content:'';position:absolute;inset:0;z-index:3;pointer-events:none;
  background:radial-gradient(122% 100% at 50% 50%,transparent 40%,rgba(0,0,0,.58));
}

/* the lattice + scanline field, with a band sweeping down it */
.oa-boot-sweep{
  position:absolute;inset:0;z-index:1;pointer-events:none;overflow:hidden;
  background:
    repeating-linear-gradient(to bottom,rgba(255,255,255,.05) 0 1px,transparent 1px 3px),
    repeating-linear-gradient(to right,var(--accent-glow) 0 1px,transparent 1px 46px),
    repeating-linear-gradient(to bottom,var(--accent-glow) 0 1px,transparent 1px 46px);
  opacity:.42;
}
.oa-boot-sweep::after{
  content:'';position:absolute;left:-12%;right:-12%;top:-44%;height:40%;
  background:linear-gradient(180deg,transparent,var(--accent-glow) 42%,rgba(255,255,255,.13) 50%,var(--accent-glow) 58%,transparent);
  animation:oaSweep 2.3s cubic-bezier(.4,0,.2,1) infinite;
}

/* the mark. The logo itself is DRAWN by the JS (inline SVG or canvas) — no image
   file exists and the CSP would block one anyway — so this styles the frame, the
   bloom and the boot ring around whatever it draws. */
.oa-boot-mark{
  position:relative;flex:none;
  width:clamp(94px,32vw,164px);height:clamp(94px,32vw,164px);
  display:grid;place-items:center;
  color:var(--accent);
  filter:drop-shadow(0 0 20px var(--accent-glow)) drop-shadow(0 0 4px var(--accent-glow));
  animation:oaMarkIn 1s cubic-bezier(.2,.8,.3,1) both;
}
.oa-boot-mark>svg,.oa-boot-mark>canvas{width:100%;height:100%;display:block;overflow:visible}
/* the bloom behind the mark */
.oa-boot-mark::before{
  content:'';position:absolute;inset:-40%;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle at 50% 50%,var(--accent-glow),transparent 64%);
  animation:oaHalo 2.6s ease-in-out .45s infinite;
}
/* the boot ring — a console spinning up */
.oa-boot-mark::after{
  content:'';position:absolute;inset:-11%;border-radius:50%;pointer-events:none;
  border:1px solid var(--border);border-top-color:var(--accent);
  opacity:.75;
  animation:oaRing 1.9s linear infinite;
}

/* the title resolves out of a blur and a wide letter-spacing */
.oa-boot-title{
  margin:24px 0 0;max-width:100%;
  font:700 clamp(15px,4.4vw,22px) var(--ui);
  letter-spacing:.32em;padding-left:.32em;   /* padding balances the trailing space */
  text-transform:uppercase;text-align:center;color:var(--text);
  animation:oaTitleIn .95s cubic-bezier(.2,.8,.3,1) .3s both;
}
.oa-boot-title small,.oa-boot-title span{
  display:block;margin-top:10px;
  font:400 11.5px var(--mono);letter-spacing:.16em;
  text-transform:none;color:var(--muted);
}

/* the progress bar. Indeterminate shimmer by default; if the JS drops a child in
   and drives its width, that child is the real fill and the shimmer stands down
   (:has route automatic, .oa-det route explicit for browsers without :has). */
.oa-boot-bar{
  position:relative;flex:none;
  width:min(260px,62vw);height:3px;margin-top:26px;
  border-radius:99px;background:rgba(255,255,255,.10);overflow:hidden;
}
.oa-boot-bar::after{
  content:'';position:absolute;top:0;bottom:0;left:0;width:36%;border-radius:inherit;
  background:linear-gradient(90deg,transparent,var(--accent),transparent);
  animation:oaBar 1.5s cubic-bezier(.5,0,.5,1) infinite;
}
.oa-boot-bar>*{
  position:absolute;left:0;top:0;bottom:0;width:0;border-radius:inherit;z-index:1;
  background:linear-gradient(90deg,var(--accent-glow),var(--accent));
  box-shadow:0 0 12px var(--accent-glow);
  transition:width .2s linear;
}
/* TWO RULES, NOT ONE LIST. An unknown selector invalidates the WHOLE list it
   sits in, so pairing the :has() route with the .oa-det route would have taken
   the explicit fallback down on precisely the engines that lack :has() and
   therefore need it. */
.oa-boot-bar:has(>*)::after{display:none}
.oa-boot-bar.oa-det::after{display:none}

/* SKIP. A cinematic you cannot skip is a tax you pay every time you want to play
   Pong. 44px minimum, clear of the home indicator, and discreet enough that it
   does not compete with the mark. The whole field is also a skip target — that
   is the JS unit's listener; this is the affordance that says so. */
.oa-boot-skip{
  position:absolute;left:50%;transform:translateX(-50%);
  bottom:max(16px,env(safe-area-inset-bottom,0px));
  z-index:4;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:44px;min-width:140px;padding:0 20px;
  border-radius:99px;border:1px solid var(--border);
  background:rgba(255,255,255,.04);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  color:var(--muted);font:600 11.5px var(--ui);letter-spacing:.15em;text-transform:uppercase;
  cursor:pointer;touch-action:manipulation;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;
  transition:color .16s ease,border-color .16s ease,background .16s ease;
  animation:oaSkipIn .45s ease 1s both;
}
.oa-boot-skip:hover{color:var(--text);border-color:var(--accent);background:var(--accent-glow)}
.oa-boot-skip:active{transform:translateX(-50%) scale(.97)}

@keyframes oaCrt{
  0%  {transform:scaleX(.02) scaleY(1);opacity:0}
  12% {transform:scaleX(1) scaleY(1);opacity:1}
  44% {transform:scaleX(1) scaleY(1);opacity:.9}
  100%{transform:scaleX(1) scaleY(460);opacity:0}
}
@keyframes oaMarkIn{
  0%  {opacity:0;transform:scale(.86);filter:brightness(2.4) blur(7px)}
  55% {opacity:1;filter:brightness(1.25) blur(0)}
  100%{opacity:1;transform:scale(1);filter:brightness(1) blur(0)}
}
@keyframes oaHalo{0%,100%{opacity:.55}50%{opacity:1}}
@keyframes oaRing{to{transform:rotate(360deg)}}
@keyframes oaSweep{0%{top:-44%}100%{top:104%}}
@keyframes oaTitleIn{
  0%  {opacity:0;letter-spacing:.62em;filter:blur(6px)}
  58% {opacity:1;filter:blur(0)}
  100%{opacity:1;letter-spacing:.32em;filter:blur(0)}
}
@keyframes oaBar{0%{left:-38%}100%{left:100%}}
@keyframes oaSkipIn{from{opacity:0}to{opacity:1}}

/* ── 2. THE IMMERSIVE SHELL ───────────────────────────────────────────────────
   Selector-for-selector mirror of body.os-workspace-immersive (oracle.css:500).
   Same chrome hidden, same fixed .shell / .col-center, same z-index band — the
   only differences are the view id and the class name. #view-games carries an
   INLINE display/flex/min-height (oracle.html:1054), so every one of these needs
   !important exactly like the workspace block does. */
body.os-arcade-immersive .topbar,
body.os-arcade-immersive .rail,
body.os-arcade-immersive .m-tabbar,
body.os-arcade-immersive .m-appbar,
body.os-arcade-immersive #col-left,
body.os-arcade-immersive #col-right,
body.os-arcade-immersive .tab-strip,
body.os-arcade-immersive #gshort-fab,
body.os-arcade-immersive .cmd-bar,
body.os-arcade-immersive #cmd-bar{display:none !important}
body.os-arcade-immersive .shell{position:fixed !important;inset:0 !important;padding:0 !important;margin:0 !important;max-width:none !important;height:100% !important;z-index:40;display:flex !important}
body.os-arcade-immersive .col-center{position:fixed !important;inset:0 !important;padding:0 !important;margin:0 !important;height:100% !important;max-height:none !important;width:100% !important;max-width:none !important;z-index:41;display:flex !important;flex-direction:column !important;overflow:hidden !important}
body.os-arcade-immersive #view-games{position:fixed !important;inset:0 !important;z-index:42;display:flex !important;flex-direction:column !important;width:100% !important;height:100% !important;max-height:none !important;flex:1 !important;background:var(--bg)}
/* the games body stops being the scroller — .oa-shell-body takes that job, so the
   shell chrome stays pinned while the library scrolls under it */
body.os-arcade-immersive #view-games-body{
  flex:1 1 auto !important;min-height:0 !important;
  height:100% !important;max-height:none !important;
  padding:0 !important;overflow:hidden !important;
}
/* nothing in the arcade may push the page sideways */
body.os-arcade-immersive{overflow-x:hidden}

.oa-shell{
  position:relative;z-index:1;
  display:flex;flex-direction:column;
  flex:1 1 auto;min-height:0;width:100%;max-width:none;
  margin:0;padding:0;
  overflow:hidden;
  color:var(--text);
  background:
    radial-gradient(122% 76% at 50% -16%,var(--accent-glow),transparent 60%),
    linear-gradient(180deg,var(--bg-2),var(--bg));
  animation:oaShellIn .42s cubic-bezier(.2,.8,.3,1) both;
}
body.os-arcade-immersive .oa-shell{
  position:fixed;inset:0;z-index:43;
  height:100vh;height:100dvh;
}

.oa-shell-top{
  position:relative;z-index:3;flex:none;
  display:flex;align-items:center;gap:10px;
  min-height:56px;
  padding:10px max(14px,env(safe-area-inset-right,0px)) 10px max(14px,env(safe-area-inset-left,0px));
  padding-top:max(10px,env(safe-area-inset-top,0px));
  border-bottom:1px solid var(--border);
  background:linear-gradient(180deg,rgba(255,255,255,.045),transparent);
  -webkit-backdrop-filter:blur(12px) saturate(1.05);backdrop-filter:blur(12px) saturate(1.05);
}
.oa-shell-top b{font:700 15px var(--ui);letter-spacing:.06em;color:var(--text);min-width:0}
.oa-shell-top small{font:400 11px var(--mono);letter-spacing:.1em;color:var(--muted)}
.oa-shell-top .oa-shell-sp{flex:1 1 auto;min-width:0}

.oa-shell-body{
  flex:1 1 auto;min-height:0;width:100%;
  display:flex;flex-direction:column;
  padding:0;                       /* full-bleed on phones — the start card IS the screen */
  overflow:auto;-webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;
}
@media (min-width:901px){
  .oa-shell-body{padding:0 clamp(12px,2.4vw,32px)}
}

/* EXIT. Always visible, always clear of the safe areas, and correct in both
   placements: in flow when the JS puts it inside .oa-shell-top, floating when it
   stands alone or when a game has taken the screen. */
.oa-exit{
  position:fixed;z-index:60;
  top:max(10px,env(safe-area-inset-top,0px));
  right:max(10px,env(safe-area-inset-right,0px));
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  min-height:44px;min-width:44px;padding:0 15px;
  border-radius:99px;border:1px solid var(--border);
  background:rgba(4,7,13,.74);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  color:var(--text);font:600 12px var(--ui);letter-spacing:.05em;
  box-shadow:0 12px 28px -16px rgba(0,0,0,.92);
  cursor:pointer;touch-action:manipulation;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;
  transition:border-color .16s ease,background .16s ease,transform .12s ease;
}
.oa-shell-top .oa-exit{position:static;margin-left:auto;box-shadow:none;background:rgba(255,255,255,.05)}
/* while a game owns the screen the exit always floats, wherever it was authored */
body.os-arcade-play .oa-exit{
  position:fixed;
  top:max(10px,env(safe-area-inset-top,0px));
  right:max(10px,env(safe-area-inset-right,0px));
  margin-left:0;background:rgba(4,7,13,.74);
  box-shadow:0 12px 28px -16px rgba(0,0,0,.92);
}
.oa-exit:hover{border-color:var(--accent);background:var(--accent-glow)}
.oa-exit:active{transform:scale(.96)}
@keyframes oaShellIn{from{opacity:0;transform:scale(.994)}to{opacity:1;transform:none}}

/* ── 3. FULLSCREEN PLAY ───────────────────────────────────────────────────────
   The stage fills the viewport, the canvas grows into whatever is left after the
   chrome and letterboxes inside it (object-fit:contain keeps the aspect ratio),
   and the d-pad keeps its own row below — it is flex:none, so the canvas gives up
   space first and the pad is never the thing squeezed off screen.

   Every rule is gated on body.os-arcade-play (or :fullscreen). Nothing here can
   reach ordinary in-page play, so the v9.10.660/661 canvas caps stand. */
.oa-stage,.oa-play{
  position:relative;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  flex:1 1 auto;min-height:0;width:100%;
  gap:8px;padding:0;margin:0;
  background:#04070d;
  overflow:hidden;
}
body.os-arcade-play .oa-stage,
body.os-arcade-play .oa-play{
  position:fixed;inset:0;z-index:70;
  width:100vw;
  height:100vh;height:100dvh;   /* the URL bar makes vh lie; dvh wins where it exists */
}
/* THE NATIVE-FULLSCREEN VARIANTS GET THEIR OWN RULES, for the same reason as the
   progress bar above and with a sharper edge: :fullscreen is not understood by
   Safari before 16.4 — i.e. by a large share of the iPhones this runs on — and
   an unknown selector invalidates the entire list it appears in. Sharing a list
   with the body.os-arcade-play rule would therefore have killed IN-APP
   fullscreen on exactly the devices that can never have the real thing, since
   iOS Safari refuses requestFullscreen on non-video elements anyway. */
.oa-stage:fullscreen,.oa-play:fullscreen,.oa-shell:fullscreen{
  position:fixed;inset:0;z-index:70;width:100vw;
  height:100vh;height:100dvh;background:#04070d;
}
.oa-stage:-webkit-full-screen,.oa-play:-webkit-full-screen,.oa-shell:-webkit-full-screen{
  position:fixed;inset:0;z-index:70;width:100vw;height:100vh;background:#04070d;
}
.oa-stage::backdrop,.oa-play::backdrop,.oa-shell::backdrop{background:#04070d}

/* the game panel stops being a card and becomes the screen */
body.os-arcade-play .gc-frame{
  width:100% !important;max-width:none !important;
  height:100% !important;margin:0 !important;
  border:0 !important;border-radius:0 !important;
  box-shadow:none !important;background:transparent !important;
}
body.os-arcade-play .gc-frame::before{display:none}
body.os-arcade-play .gc-frame-head{
  flex:none;min-height:48px;
  padding:6px max(58px,env(safe-area-inset-right,0px)) 6px max(10px,env(safe-area-inset-left,0px));
  padding-top:max(6px,env(safe-area-inset-top,0px));
}
body.os-arcade-play .gc-frame-body{
  flex:1 1 auto;min-height:0 !important;
  justify-content:flex-start;
  gap:8px;padding:8px 0 0 !important;
}
body.os-arcade-play .gc-frame-foot{
  flex:none;min-height:0;padding:6px 12px;
  padding-bottom:max(6px,env(safe-area-inset-bottom,0px));
}
body.os-arcade-play .gc-arcade{
  flex:1 1 auto;min-height:0;width:100%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
}
body.os-arcade-play .gc-hud{flex:none}
/* THE CANVAS. flex:1 1 auto + min-height:0 lets it take the leftover box;
   object-fit:contain letterboxes the bitmap inside that box, so a 420x640 game
   stays 420x640-shaped however tall the phone is. */
body.os-arcade-play .gc-canvas{
  flex:1 1 auto;min-height:0;align-self:stretch;
  width:100% !important;max-width:100% !important;
  height:auto !important;max-height:none !important;
  object-fit:contain;
  border:0 !important;border-radius:0 !important;background:transparent !important;
}
/* the pad holds its ground and clears the home indicator */
body.os-arcade-play .gc-pad{
  flex:none;
  margin-bottom:max(4px,env(safe-area-inset-bottom,0px));
}
/* landscape phone: the chrome is the enemy, the canvas is the point */
@media (max-width:900px) and (orientation:landscape) and (max-height:560px){
  body.os-arcade-play .oa-shell-top{display:none}
  body.os-arcade-play .gc-frame-head{min-height:40px;padding-top:max(4px,env(safe-area-inset-top,0px))}
  body.os-arcade-play .gc-frame-foot{display:none}
  body.os-arcade-play .gc-frame-body{padding-top:4px !important;gap:4px}
}

/* ── 4. REDUCED MOTION — ALL THREE ROUTES ─────────────────────────────────────
   A boot cinematic is exactly the thing someone with vestibular sensitivity
   needs to opt out of, and .oa-boot mounts OUTSIDE #view-games-body — so the
   existing .gc-reduce-motion blanket cannot reach it and it needs its own.
   Near-zero durations rather than animation:none, matching the convention the
   rest of this sheet relies on: the animation still ENDS, so any animationend
   cleanup still fires, and every animation here uses fill-mode `both`, so ending
   instantly lands on the FINAL frame — opacity 1, transform none, fully legible.
   Turning the motion off can never hide anything.
   The three genuinely vestibular effects (the CRT bloom, the sweeping band, the
   spinning ring) are switched off outright; nothing listens for their end. */
@media (prefers-reduced-motion:reduce){
  .oa-boot,.oa-boot *,.oa-boot *::before,.oa-boot *::after,
  .oa-shell,.oa-shell *,.oa-shell *::before,.oa-shell *::after,
  .oa-stage,.oa-play,.oa-exit{
    animation-duration:.001ms !important;
    animation-delay:0s !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    transition-delay:0s !important;
    scroll-behavior:auto !important;
  }
  .oa-boot::before{display:none !important}
  .oa-boot-sweep::after{display:none !important}
  .oa-boot-mark::after{animation:none !important;border-top-color:var(--accent);opacity:.5}
  .oa-boot-mark::before{animation:none !important;opacity:.8}
  .oa-boot-bar::after{animation:none !important;width:100%;background:var(--accent-glow)}
  .oa-boot-title{letter-spacing:.32em;filter:none}
  .oa-exit:active{transform:none}
  .oa-boot-skip:active{transform:translateX(-50%)}
}
body.reduce-motion .oa-boot::before,
.gc-reduce-motion .oa-boot::before,
body.reduce-motion .oa-boot-sweep::after,
.gc-reduce-motion .oa-boot-sweep::after{display:none !important}
body.reduce-motion .oa-boot-mark::after,
.gc-reduce-motion .oa-boot-mark::after{animation:none !important;border-top-color:var(--accent);opacity:.5}
body.reduce-motion .oa-boot-mark::before,
.gc-reduce-motion .oa-boot-mark::before{animation:none !important;opacity:.8}
body.reduce-motion .oa-boot-bar::after,
.gc-reduce-motion .oa-boot-bar::after{animation:none !important;width:100%;background:var(--accent-glow)}
body.reduce-motion .oa-boot-title,
.gc-reduce-motion .oa-boot-title{letter-spacing:.32em;filter:none}
body.reduce-motion .oa-shell,
.gc-reduce-motion .oa-shell{animation:none}
body.reduce-motion .oa-boot-skip:active,
.gc-reduce-motion .oa-boot-skip:active{transform:translateX(-50%)}
/* ══ end v9.10.663 — Oracle Arcade boot / shell / fullscreen ════════════════ */

/* ══ v9.10.665 — console browse: sliding shelves, rank badges, category rows ═══════════
   The owner asked for the library to read like a console, not a list:
     "see Popular or trending in the Sliding category ... similar to how the
      radio browse shows the sounds in the organized structure but more game
      like and console like that i slight to or click on"
   Touch already slid (overflow-x + scroll-snap). A MOUSE did not — a desktop
   user got a hairline scrollbar and a row of twenty games that looked like six.
   .gc-shelf-nav is the console arrow; it only appears once the row actually
   overflows (JS adds .gc-shelf-over after measuring), so a short row stays
   clean. ═══════════════════════════════════════════════════════════════════ */
.gc-shelf{position:relative}

/* The arrows sit OVER the row's edges rather than beside it, so adding them
   never steals width from the cards themselves. */
.gc-shelf-nav{
  position:absolute;top:calc(50% + 9px);transform:translateY(-50%);
  z-index:3;width:34px;height:52px;padding:0;
  display:none;align-items:center;justify-content:center;
  font:400 22px/1 var(--ui);color:var(--fg);
  background:linear-gradient(90deg,rgba(0,0,0,.02),var(--panel) 55%);
  border:1px solid var(--line);border-radius:10px;cursor:pointer;
  box-shadow:0 4px 18px rgba(0,0,0,.28);
  transition:opacity .16s ease,transform .16s ease,border-color .16s ease;
}
.gc-shelf-prev{left:-6px}
.gc-shelf-next{right:-6px}
.gc-shelf-over .gc-shelf-nav{display:flex}
.gc-shelf-nav:hover{border-color:var(--accent);color:var(--accent)}
.gc-shelf-nav:active{transform:translateY(-50%) scale(.94)}
/* Disabled means "there is nothing more that way" — it must READ as unavailable
   but must not vanish, or the row appears to gain and lose controls as you
   scroll, which is worse than a dim arrow. */
.gc-shelf-nav:disabled{opacity:.26;cursor:default;box-shadow:none}
.gc-shelf-nav:disabled:hover{border-color:var(--line);color:var(--fg)}

/* Pointer-only. On a touch screen the finger IS the control, and a pair of
   floating arrows over a 96px card would cover the artwork. */
@media (hover:none),(pointer:coarse){
  .gc-shelf-over .gc-shelf-nav{display:none}
}

/* Rank badge — Popular/Trending are ordered lists, and a console says so. */
.gc-shelf-rk{
  position:absolute;top:6px;left:6px;z-index:2;
  min-width:17px;height:17px;padding:0 4px;
  display:inline-flex;align-items:center;justify-content:center;
  font:800 10px/1 var(--mono);letter-spacing:.02em;
  color:var(--bg);background:var(--gc-accent,var(--accent));
  border-radius:5px;box-shadow:0 1px 5px rgba(0,0,0,.35);
}
/* The top three earn the accent glow; the rest are quiet numerals. */
.gc-shelf-c:nth-child(-n+3) .gc-shelf-rk{box-shadow:0 0 0 1px rgba(255,255,255,.14),0 2px 9px rgba(0,0,0,.45)}

/* Async host for the server-fed shelves. Zero-height until it has content, so
   an offline server costs no layout at all. */
.gc-shelf-async{display:contents}

/* ══ end v9.10.665 ═════════════════════════════════════════════════════════ */

/* ══ v9.10.666 — VERIFY PASS: two tokens that do not exist ══════════════════
   .gc-shelf-nav (the console browse arrows, shipped one version earlier) asks
   for var(--fg) and var(--line). Neither is defined anywhere in this project —
   not in oracle.css, not in oracle.html, not in any other sheet — and neither
   usage carried a fallback. Measured, not guessed: 4 usages, 0 definitions.

   The consequence is not "slightly wrong colour". `color:var(--fg)` is invalid
   at computed-value time, and for an inherited property that means `inherit`,
   which happens to look fine. `border:1px solid var(--line)` makes the whole
   SHORTHAND invalid, which resolves to `unset` -> `medium none currentcolor`:
   the arrow loses its border entirely and reads as a floating glyph.

   Repaired here rather than in place because this sheet is append-only. Same
   specificity, later in the cascade, so these win. --text and --border are the
   real tokens the rest of the file uses for exactly this pair. ══════════════ */
.gc-shelf-nav{color:var(--text);border:1px solid var(--border)}
.gc-shelf-nav:disabled:hover{border-color:var(--border);color:var(--text)}


/* ═══ v9.10.666 — THE ARCADE SHELL NOW HOLDS THE LIBRARY ══════════════════
   THE BUG. `.oa-shell` is appended to document.body, so it is a SIBLING of
   `.shell`. body.os-arcade-immersive gives .shell position:fixed + z-index:40,
   which makes it a stacking context; #view-games (z-index:42) and everything the
   Game Center paints are sealed INSIDE it. .oa-shell is z-index:43 in the ROOT
   context with an opaque background, so the contest is 40 vs 43 and the library
   loses it however high we number the library. From v9.10.665 the shell was
   raised for the LIBRARY too, not just for a running game, and the Game Center
   became a blank purple field — 21 cards, every node opacity 1, all of it under
   a flat sheet. The purple in the owner's screenshot IS .oa-shell's own
   background gradient.

   THE FIX is the one this module always documented: ARCADE.adopt() moves
   #view-games-body INTO .oa-shell-body (oracle-arcade.js), so the library is a
   CHILD of the shell rather than a rival to it. Stacking stops being the
   question. The ELEMENT moves, not the paint target, so every
   getElementById('view-games-body') and every `#view-games-body …` rule in this
   sheet keeps resolving.

   WHAT THIS BLOCK IS FOR. body.os-arcade-immersive #view-games-body is
   height:100% + overflow:hidden !important, which was correct when it lived in a
   fixed full-screen #view-games and is exactly wrong inside a scroller: it would
   clip thousands of px of library to one screen, and there is NO other scrolling
   ancestor on desktop (.view-pane{overflow:hidden}; the overflow-y:auto is inside
   @media(max-width:900px)). Given its natural height instead, .oa-shell-body's
   existing overflow:auto becomes the scroller the arcade never had.

   Specificity: `body.os-arcade-immersive .oa-shell-body > #view-games-body` is
   (1,2,1) and beats the (1,1,1) rule near line 9882; the inline `flex:1` on
   oracle.html:1055 is beaten by !important. Append-only, as this sheet requires.

   NOT NEEDED, and deliberately absent: any z-index. Raising #view-games or
   .gc-wrap cannot work — they are trapped in .shell's stacking context, so the
   number is resolved locally and never competes with .oa-shell at all. Parentage
   was the only knob that existed.
   ══════════════════════════════════════════════════════════════════════════ */
body.os-arcade-immersive .oa-shell-body > #view-games-body{
  /* content height, not container height — the shell body does the scrolling */
  flex:0 0 auto !important;
  height:auto !important;
  min-height:0 !important;
  max-height:none !important;
  overflow:visible !important;
  width:100% !important;
  padding:0 !important;
}
/* The shell is pointer-events:none (oracle-arcade.js's fallback sheet is the only
   declaration for it in the whole cascade). A borrowed library needs its clicks
   back — and only when it is actually there. An EMPTY .oa-shell-body must stay
   transparent to input so it can never swallow a tap meant for something
   underneath it, which is why this is keyed to the adoption marker rather than
   set on .oa-shell-body outright. The JS sets it inline too; this is the belt to
   that pair of braces. */
body.os-arcade-immersive .oa-shell-body > #view-games-body[data-oa-adopted]{
  pointer-events:auto !important;
}


/* ══ v9.10.668 — THE TWO DEFECTS IN THE SCREENSHOT ════════════════════════
   The owner sent a photograph of the Meteor Run start card with two red marks
   on it: one under the "3 played · best 851" foot with a long arrow pointing
   down into a large empty black region, and his words —

     "the bottom part has to much padding ... plus the bottom has so much space
      being padded that it makes things load smaller on the users screen"
     "the screen when loosing shows up on the bottom of the screen luckyly we
      can press continue but it should be in the middle"

   Everything below answers one of those two sentences. Every number in these
   comments was MEASURED in real Chromium at 375x812 and 1920x1080, offscreen,
   with fullscreen refused the way iOS Safari refuses it — not estimated.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE CONTINUE PANEL IS A MODAL, SO IT IS POSITIONED LIKE ONE ────────
   MEASURED, as shipped: the "You lost a life / Continue / Give up" panel sat at
   top=625.6 bot=833.4 on an 812px screen — 21px of it off the bottom edge, and
   only reachable at all because .gc-frame-body had become a scroller
   (scrollHeight 726 vs clientHeight 672). Painted midpoint 703 against a
   viewport midpoint of 406.

   The cause was source order, not this stylesheet: oracle-games.js appended the
   panel LAST into .gc-arcade's flex column, after a 444px canvas and a 111px
   d-pad. It is now wrapped in .gc-continue-layer, and THE LAYER does the
   centring. That indirection is not decoration — .gc-continue carries
   'gcContinueIn' + 'gcContinueGlow' (line ~9338) and a CSS animation out-ranks
   normal declarations, so a 'transform:translate(-50%,-50%)' written on the
   panel itself is discarded by the animation's own 'transform:none' keyframe.
   Measured when tried: the panel did not move (left stayed 188.1 of 375).
   A parent cannot be overridden by its child's animation.

   z-index 26 is BELOW .gc-overlay's 30 on purpose: the two are mutually
   exclusive (endRun() calls hideContinue() before the result card), and if that
   ever stopped being true the result card must be the one you can see. */
.gc-continue-layer{
  position:fixed;left:0;top:0;right:0;bottom:0;z-index:26;
  display:none;align-items:center;justify-content:center;
  padding:max(14px,env(safe-area-inset-top,0px)) 14px max(14px,env(safe-area-inset-bottom,0px));
  background:rgba(4,7,13,.62);
  -webkit-backdrop-filter:blur(5px) saturate(.85);backdrop-filter:blur(5px) saturate(.85);
  overflow:auto;overscroll-behavior:contain;
}
.gc-continue-layer.on{display:flex}
/* Belt to the JS braces. A full-viewport scrim left up with nothing lit inside
   it would swallow every tap meant for the game behind it, so the layer proves
   it has a live panel before it is allowed to exist. (0,3,0) — :not() takes the
   specificity of its argument — so it outranks .gc-continue-layer.on and the
   inline display the JS writes still outranks both. */
.gc-continue-layer:not(:has(> .gc-continue.on)){display:none}
.gc-continue-layer>.gc-continue{margin:0;flex:0 0 auto;max-height:100%}

/* ── 2. THE RESULT CARD STOPS BEING A BOTTOM SHEET ON A PHONE ──────────────
   MEASURED, as shipped, at 375x812: the card's BOX straddled the centre
   (112.5..773) while everything readable in it did not — headline bottom 150.5,
   buttons top 644, i.e. 493.5px of nothing in between, and computed
   'margin-top: 454.7px' on .gc-overlay-btns. A box-centred assertion passes on
   that; the pixel band does not (ink 133..770 = 637px of an 812px screen).

   Three rules compose into it, all in the @media(max-width:700px) block at
   ~8546: '.gc-overlay{align-items:stretch;justify-content:flex-start}',
   '.gc-overlay-card{height:100%;margin:0}' and '.gc-overlay-btns{margin-top:auto;
   position:sticky;bottom:0}'. They are RIGHT for the start card — a long
   scrollable how-to whose Play button must stay pinned — and wrong for a result
   card with ~210px of content. The data-kind attribute added in v9.10.654 exists
   to tell those two apart and was, until now, read by nothing in the cascade.

   Specificity: .gc-overlay-card is (0,1,0), so the doubled class + attribute is
   (0,3,0) and wins inside the same media query. The goal doc records two prior
   losses in this exact selector family; source order alone is not enough. */
@media (max-width:700px){
  .gc-overlay.gc-overlay[data-kind="result"]{
    align-items:center;justify-content:center;padding:12px;overflow:auto;
  }
  .gc-overlay-card.gc-overlay-card[data-kind="result"]{
    height:auto;max-height:100%;min-height:0;margin:auto;
    padding:20px 16px calc(16px + env(safe-area-inset-bottom,0px));
    border-radius:14px;
  }
  .gc-overlay-card[data-kind="result"]>.gc-overlay-btns{
    position:static;margin-top:16px;padding:0;background:none;
  }
}

/* ── 3. THE FRAME GETS ITS DEFINITE HEIGHT BACK ────────────────────────────
   THE OWNER'S ARROW. MEASURED at 375x812: .gc-frame ended at y=650.3 and the
   161.8px below it — 19.9% of the phone screen — carried NOTHING. Proven by
   edge density, not by eye: 0.00 edges per 1000px in that band against 88.94 in
   a control band inside the card (the control is the same probe, so a blinded
   probe fails the control instead of passing the claim).

   The cause is the v9.10.666 adoption rule 40 lines above this one. It gives
   #view-games-body 'flex:0 0 auto; height:auto' so a 6500px LIBRARY can scroll
   inside .oa-shell-body — correct for the library, and it also removed the
   definite height that .gc-frame (flex:1 1 0%) needs to stretch into. With
   nothing to stretch into the frame collapses to its content, which is then
   pinned by '.gc-frame-body{min-height:min(58vh,420px)}' at ~8528. The fix that
   made the library scrollable is the same rule that stopped a one-screen game
   frame filling the screen.

   :has(>.gc-frame) discriminates the two cases exactly — a frame is present for
   the start card and for a running game, and absent for the library — so the
   library keeps its scroll and the frame gets its height. (1,3,1) beats the
   (1,2,1) rule above, which is what an append needs to win here.

   ISOLATED, one variable at a time: '.gc-frame{margin-bottom:0}' ALONE left the
   dead band at 161.8px (the frame stopped at 650.3 either way — the margin only
   relocated the void). The height chain is the cause; the margin is a separate
   90px reserved for .m-tabbar, which measures display:none under
   os-arcade-immersive, so it is reserving space for something that is not there. */
body.os-arcade-immersive .oa-shell-body>#view-games-body:has(>.gc-frame){
  flex:1 1 auto !important;
  height:auto !important;
  min-height:100% !important;
  max-height:100% !important;
  overflow:hidden !important;
}
body.os-arcade-immersive .gc-frame.gc-frame{margin-bottom:0}
body.os-arcade-immersive .gc-wrap{padding-bottom:max(16px,env(safe-area-inset-bottom,0px))}

/* ── 4. THE PLAY SURFACE TAKES THE SPACE THE PADDING WAS HOLDING ───────────
   Scoped to .gc-immersive, which oracle-games.js puts on the frame in
   stageEnter() and takes off in stageRelease() — so none of this touches the
   start card, and none of it touches the library.

   DO NOT ADD 'position:fixed' TO A .gc-immersive RULE. cssOwnsImmersive()
   (oracle-games.js ~1737) asks the browser whether the computed position is
   already fixed and, if it is, SKIPS the entire inline fallback — the body
   overflow lock, the frame-body flex chain and the canvas sizing all stop being
   applied. These rules deliberately set no position at all.

   PHONE — the canvas is WIDTH-bound, not height-bound. Meteor Run is a 520x640
   bitmap in a 361px-wide box: 361 x 640/520 = 444.3, and it measured 443.8. So
   vertical padding was never the constraint; the 7px side padding and the 1px
   rounded border were. 14px of width is 17px of height on this aspect ratio.

   DESKTOP — the canvas is HEIGHT-bound and was not being driven at all. The
   inline styles stageEnter() writes are 'width:auto;height:auto;max-*:100%',
   and max-* can only ever SHRINK a replaced element, so at 1920x1080 the game
   rendered at its raw bitmap size — 522x642 in a 1920x1080 window, 16.2% of the
   screen, with 329px of dead space under it. Driving HEIGHT with width:auto is
   what grows it, and it is also what keeps the element box EXACTLY the painted
   bitmap: 'width:100% + object-fit:contain' would have grown it too, but it
   letterboxes inside a wider box, and every pointer-mapped game in the pack
   converts client coordinates with '(clientX - rect.left) * (W / rect.width)'
   against that box — Breakout's paddle and Floppy KAI's tap would both have
   started reading the wrong place. Raising the CAP as well as the request is
   the v9.10.661 lesson: 'max-height' is the cap, 'height' is only a request. */
body.os-arcade-immersive .gc-frame.gc-immersive>.gc-frame-body{
  padding-left:0;padding-right:0;padding-top:6px;
  padding-bottom:max(0px,env(safe-area-inset-bottom,0px));
  gap:0;justify-content:center;
}
body.os-arcade-immersive .gc-frame.gc-immersive .gc-stage-body{
  flex:1 1 auto;min-height:0;width:100%;
}
body.os-arcade-immersive .gc-frame.gc-immersive .gc-arcade{
  flex:1 1 auto;min-height:0;justify-content:center;
}
@media (max-width:700px){
  body.os-arcade-immersive .gc-frame.gc-immersive .gc-arcade>.gc-canvas{
    border-left:0;border-right:0;border-radius:0;
  }
}
@media (min-width:901px){
  body.os-arcade-immersive .gc-frame.gc-immersive .gc-arcade>.gc-canvas{
    height:100% !important;width:auto !important;
    max-height:100% !important;max-width:100% !important;
    min-height:0;flex:0 1 auto;object-fit:contain;
  }
}
/* ══ end v9.10.668 ═════════════════════════════════════════════════════════ */

/* ══ v9.10.668b — MEASURED, THEN CORRECTED ════════════════════════════════
   Section 4 above gave .gc-arcade  flex:1 1 auto  and the canvas  height:100%,
   and the canvas did not grow by a single pixel. THE BOX TREE SAYS WHY:

     .gc-stage-body   display:flex  flex-direction:ROW  align-items:flex-start

   In a ROW container `flex:1 1 auto` grows the item along the MAIN axis, which
   is width — measured, .gc-arcade duly became 1920px wide and stayed 642px
   tall. Height in a row container is the CROSS axis and is decided by
   align-items, which is flex-start on desktop and center on a phone. And with
   .gc-arcade sized by its own content, the canvas asking for `height:100%` is a
   circular reference the spec resolves as auto — so the request was not merely
   losing to a cap, it was never definite in the first place.

   align-items:stretch is the one declaration that makes the whole chain
   definite. Then, and only then, height:100% on the canvas resolves.
   MEASURED after: 522x642 -> 784x965 at 1920x1080.

   align-self on .gc-arcade as well as align-items on the parent: the pack has
   game wrappers other than .gc-arcade in that same slot, and stretching them
   all from the parent alone would be a wider change than this unit measured. */
body.os-arcade-immersive .gc-frame.gc-immersive .gc-stage-body{align-items:stretch}
body.os-arcade-immersive .gc-frame.gc-immersive .gc-arcade{align-self:stretch}

/* THE RESULT CARD IS CENTRED ON THE SCREEN, NOT ON WHAT IS LEFT OF IT.
   .gc-overlay is position:absolute inside .gc-frame-body, so with section 2
   applied it centred perfectly — inside a box that starts 127px down, under the
   head. MEASURED: ink midpoint 454 against a viewport midpoint of 406, i.e. the
   card sat exactly half the head-height low. The continue panel (section 1) is
   viewport-centred, so the two surfaces that answer the same moment in a game
   were landing 48px apart.
   Only for the RESULT kind, and only while a run is actually staged: the frame
   is position:fixed and full-viewport for the whole of that, so fixed here
   cannot escape anywhere it should not be. The start card keeps its
   frame-relative overlay, because that one is a full-bleed sheet by design. */
body.os-arcade-immersive .gc-frame.gc-immersive>.gc-frame-body>.gc-overlay[data-kind="result"]{
  position:fixed;left:0;top:0;right:0;bottom:0;border-radius:0;
}
/* ══ end v9.10.668b ════════════════════════════════════════════════════════ */

/* ══ v9.10.668c — THE LAST 18px ═══════════════════════════════════════════
   With 668b in place the desktop canvas measured 953px against a largest-that-
   fits of 971. The missing 18 is  .gc-stage-body{padding:6px 0}  (base sheet,
   ~6874) plus the 6px padding-top section 4 left on .gc-frame-body. Breathing
   room around a card in a page; a letterbox bar around a game on a screen the
   player asked to be filled. Zeroed for a STAGED RUN ONLY — the start card and
   the library keep every pixel of their padding.
   MEASURED after: canvas 774.7x953 -> 782x971, dead space 18px -> 0px. */
body.os-arcade-immersive .gc-frame.gc-immersive .gc-stage-body{padding-top:0;padding-bottom:0}
body.os-arcade-immersive .gc-frame.gc-immersive>.gc-frame-body{padding-top:0}
/* ══ end v9.10.668c ════════════════════════════════════════════════════════ */

/* ══ v9.10.669 — PHASE A4 (STRIP THE PLAY SCREEN) + A5 (KILL THE D-PAD) ════
   The owner, for the third time, and this time with no room left to interpret:

     "games need to be full screen on the mobile screen to the device so only
      thing shown when in the game is the how to play and the buttons and than
      the game not the buttons and stuff around it outside the game view the
      game view is full screen and the menu is on top left for menu so the
      users can go back and select another game or go change into another mode
      like solo to ai to online from the menu or continue to un-pause and or
      restart or exit to game hub."

   Every number in these comments was MEASURED in real Chromium at 375x812 and
   1920x1080, offscreen, with requestFullscreen stubbed out the way iOS Safari
   refuses it — the phone path, which is the one he is looking at.

   WHY body.os-arcade-play IS STILL NOT SET, having audited it as asked.
   oracle.css ~10001-10049 holds a complete, finished, never-executed fullscreen
   play layer (21 occurrences of the class in this sheet, ZERO in any .js). It
   was authored for a play screen that still had a head, a foot and a d-pad, and
   five of its eleven rules now describe furniture that no longer exists:
     .gc-frame-head{min-height:48px;padding:...}   the head is gone
     .gc-frame-foot{...} and the landscape display:none   the foot is gone
     .gc-pad{margin-bottom:...}                    the pad is DELETED
     .oa-exit{position:fixed;top;right}            a SECOND floating control,
       top-right, competing with the one top-left control the brief allows
     .gc-canvas{width:100% !important;object-fit:contain}
       — this one is actively harmful now: it makes the ELEMENT box wider than
       the painted bitmap, and every pointer-mapped game converts coordinates
       with (clientX - rect.left) * (W / rect.width) against that box. Breakout's
       paddle, Floppy KAI's tap and the whole A5 gesture engine would all read
       the wrong place. The v9.10.668 approach — width:auto/height:auto under
       max-*:100%, so the box IS the bitmap — is the one the pointer maths needs.
   Switching the class on would therefore mean overriding five rules to use six.
   The class stays unset; this block is the play-screen layer, scoped to the
   signature that is actually live (body.os-arcade-immersive + .gc-immersive,
   verified at runtime in v9.10.668c).
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE HEAD AND THE FOOT COME OFF ─────────────────────────────────────
   MEASURED at 375x812 before this rule: .gc-frame-head 127px (three rows —
   "← Games" 44, title 21, the tools cluster 56, plus 18 of padding) and
   .gc-frame-foot 36.3px, i.e. 163px = 20% of the phone screen spent on chrome
   the owner struck through in his own screenshot. On Pong the head measures
   176px, because .gc-frame-tools is flex-wrap:wrap and the row does not
   overflow — it grows.

   BOTH SCREENS, not just the running game. The head is struck through on the
   START CARD photograph too, and everything it carried now lives in the menu:
   the back button becomes "Back to Game Hub", the mode pills become the Mode
   row, difficulty / leaderboard / music / sound go under Options, and pause
   becomes the glyph itself.

   Gated on os-arcade-immersive, which is set for the library AND for a game.
   With the arcade shell absent — oracle-arcade.js is optional by contract —
   the class is never set, the head returns, and the Game Center degrades to
   exactly the surface it had before this version. */
body.os-arcade-immersive .gc-frame>.gc-frame-head,
body.os-arcade-immersive .gc-frame>.gc-frame-foot{display:none !important}

/* ── 2. THE ONE CONTROL THAT OVERLAYS THE GAME ─────────────────────────────
   "the menu is on top left". Top left, >=44px (48 here), inside the notch and
   the rounded corner via env(safe-area-inset-*), and nothing else is over the
   game at all.

   z-index 2, and the 2 is load-bearing. .gc-frame>* is z-index:1 (~7102), so
   .gc-frame-body is a stacking context at 1 and the overlay's z-index:30 is
   resolved INSIDE it — 30 never competes with anything out here. At z-index:2
   the menu is above the body and therefore above the overlay, which is what
   lets the panel open over the start card. Whether the GLYPH shows over a card
   is then a decision, not an accident: .gc-ov-on (set by ovShow for every kind
   except 'start') takes it away.

   position:absolute has to out-specify .gc-frame>*{position:relative}, which is
   (0,1,0) — hence the child selector, (0,2,0). */
.gc-frame>.gc-gamemenu{
  position:absolute;left:0;top:0;z-index:2;
  padding:max(10px,env(safe-area-inset-top,0px)) 0 0 max(10px,env(safe-area-inset-left,0px));
  pointer-events:none;                 /* only the glyph and the panel take taps */
}
.gc-frame.gc-ov-on>.gc-gamemenu{display:none}
.gc-menu-btn{
  pointer-events:auto;
  display:inline-flex;align-items:center;justify-content:center;
  width:48px;height:48px;min-width:48px;min-height:48px;padding:0;
  border-radius:14px;border:1px solid var(--border);
  background:rgba(4,7,13,.72);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  color:var(--text);font:600 20px/1 var(--ui);
  box-shadow:0 12px 28px -16px rgba(0,0,0,.92);
  cursor:pointer;touch-action:manipulation;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;
  transition:border-color .16s ease,background .16s ease,transform .12s ease;
}
.gc-menu-btn:hover{border-color:var(--accent);background:var(--accent-glow)}
.gc-menu-btn:active{transform:scale(.94)}
.gc-menu-btn.on{border-color:var(--accent);background:var(--accent-glow)}
/* The scrim exists so a tap anywhere else is "resume", and so the game behind
   the menu is legibly stopped rather than merely frozen. */
.gc-gamemenu-scrim{
  position:fixed;left:0;top:0;right:0;bottom:0;display:none;
  background:rgba(4,7,13,.58);
  -webkit-backdrop-filter:blur(6px) saturate(.85);backdrop-filter:blur(6px) saturate(.85);
}
.gc-gamemenu.open .gc-gamemenu-scrim{display:block;pointer-events:auto}

/* ── 3. THE PANEL ──────────────────────────────────────────────────────────
   It reuses .gc-tools-menu — the SAME node applyTools() has always folded the
   live controls into, so Music/Sound/Difficulty/Mode/Leaderboard have exactly
   one instance each and cannot drift. Only the anchoring changes: the base rule
   (~8993) pins it top:calc(100%+8px);right:0 under a header cluster on the
   RIGHT, and it now hangs under a glyph on the LEFT. Doubled class = (0,2,0),
   which beats the base and does not depend on source order alone. */
.gc-tools-menu.gc-gamemenu-panel{
  pointer-events:auto;
  position:absolute;left:max(10px,env(safe-area-inset-left,0px));right:auto;
  top:calc(max(10px,env(safe-area-inset-top,0px)) + 56px);
  min-width:min(300px,86vw);max-width:min(340px,90vw);
  max-height:calc(100vh - max(10px,env(safe-area-inset-top,0px)) - 76px);
  max-height:calc(100dvh - max(10px,env(safe-area-inset-top,0px)) - 76px);
  overflow:auto;overscroll-behavior:contain;
  padding:10px;gap:4px;
}
.gc-menu-head{
  display:flex;align-items:center;gap:8px;
  padding:2px 6px 8px;margin-bottom:2px;
  border-bottom:1px solid var(--border);
  font:700 14px var(--ui);color:var(--text);letter-spacing:.2px;
}
.gc-menu-head .gc-stage-ico{font-size:18px;line-height:1}
.gc-menu-sep{
  padding:10px 6px 4px;margin-top:4px;border-top:1px solid var(--border);
  font:700 10.5px var(--ui);letter-spacing:.13em;text-transform:uppercase;color:var(--muted-2);
}
.gc-menu-item{
  display:flex;align-items:center;gap:10px;width:100%;
  min-height:46px;padding:0 12px;
  border-radius:10px;border:1px solid transparent;background:transparent;
  color:var(--text);font:600 14px var(--ui);text-align:left;
  cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;
  transition:background .14s ease,border-color .14s ease;
}
.gc-menu-item:hover,.gc-menu-item:focus-visible{background:var(--accent-glow);border-color:var(--border)}
.gc-menu-item.gc-menu-primary{background:var(--accent-glow);border-color:var(--accent);color:var(--text)}
.gc-menu-item.gc-menu-quiet{color:var(--muted)}
/* The Mode pills get the whole width in here; in the old head they were a
   right-aligned cluster and they inherited that squeeze. */
.gc-gamemenu-panel .gc-tools-menu-row{padding:0 6px}
.gc-gamemenu-panel .gc-modes{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}
.gc-gamemenu-panel .gc-modes .gc-mode{min-height:38px}

/* ── 4. THE D-PAD IS GONE (Phase A5) ───────────────────────────────────────
   oracle-games.js no longer builds .gc-pad at all — the five buttons and their
   keys['arrowleft']=true handlers are deleted, not hidden behind a setting.
   This sheet is APPEND-ONLY, so the six existing .gc-pad rule blocks (~6958,
   8731, 8861, 8898, 8961, 10039) cannot be removed; this is the belt that
   stops any of them resurrecting a row that nothing populates. Both halves —
   the JS build site and the display — or the row comes back the next time
   somebody appends a .gc-pad rule. */
.gc-pad,.gc-pad-b{display:none !important}

/* ── 5. WITH THE CHROME GONE, THE GAME TAKES THE SCREEN ────────────────────
   MEASURED at 375x812 as shipped in v9.10.668: canvas 375x444 inside a body
   that started 127px down and stopped 36px short — 54.7% of the screen was the
   game. Deleting the head (127), the foot (36) and the d-pad (111) hands the
   body all 812px. That alone is NOT enough, and this is the part that is easy
   to get wrong: a 520x640 bitmap letterboxed into 375x812 is still 375x461,
   because it is WIDTH-bound. 43% of the screen would have moved from "chrome"
   to "black bars" and the owner would have been looking at the same complaint.

   So the buffer takes the viewport's aspect inside limits each game declares
   (oracle-games.js fitH(), spec.fit) and the canvas keeps the v9.10.668 sizing
   that makes its box exactly the painted bitmap. These two rules only remove
   what is left: the body's own centring gap and the bottom inset, which now
   have nothing to separate. */
body.os-arcade-immersive .gc-frame.gc-immersive>.gc-frame-body{
  padding-bottom:0;gap:0;
}
body.os-arcade-immersive .gc-frame.gc-immersive .gc-arcade{gap:0}
/* ══ end v9.10.669 ═════════════════════════════════════════════════════════ */

/* ══ v9.10.670 — STEAM BIG PICTURE (goal doc §8) ═══════════════════════════
   The owner asked four separate times for the Game Hub to look — and OPERATE —
   like the Steam Big Picture screen he sent. §8.1 lists the six things that
   make that screen read as a console; this block is those six, in order:

     1  PORTRAIT BOX ART, 2:3, per game            .gcbp-art
     2  exactly ONE focused item, everything
        else reading FROM it                       .gcbp-on / .gcbp-meta-on / #gcbp-wash
     3  rows BLEEDING off the right edge           .gcbp .gc-shelf-r negative margin
     4  metadata UNDER the row, not on the tile    .gcbp-meta
     5  a persistent bottom bar                    #gcbp-bar
     6  status cluster top-right, icons only       .gcbp-status

   SCOPE. Almost every rule is prefixed `.gcbp`, a class only the Game Center's
   own wrap carries, so nothing here can reach the player frame, the modals, or
   any other view. The handful that are not (#gcbp-bar, #gcbp-wash,
   .gcbp-status) are id- or class-unique nodes this version introduces.

   APPEND-ONLY, as this sheet requires: not one byte above this line changed.
   Where a base rule had to lose, it loses on WEIGHT and not on source order —
   `.gcbp .gc-card-help` is (0,2,0) against the base (0,1,0), `button.gcp-d-go`
   is (0,1,1) against a (0,1,0) rule injected by oracle-games-progress.js into
   a <style> that comes AFTER this file. Goal doc lesson 2 cost this project two
   versions to exactly that mistake.                                          */

/* ── the wash: the background IS the focused game (§8.1 item 7) ──────────────
   The focused poster, blown up, blurred and faded down into black, so moving
   focus repaints the whole screen rather than a ring on one tile.
   PAINT ORDER, because this is the trap: #gcbp-wash is a positioned child of
   .oa-shell, and .oa-shell-body is NOT positioned — so a positioned z-index:0
   sibling would paint ABOVE the entire library (positioned boxes come after
   in-flow ones, whatever their DOM order). Giving .oa-shell-body a z-index of
   its own is what puts the library back in front of its own background. */
#gcbp-wash{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background-position:50% 0;background-size:cover;background-repeat:no-repeat;
  filter:blur(46px) saturate(1.3);
  transform:scale(1.22);transform-origin:50% 0;
  opacity:.40;
  transition:opacity .45s ease;
  -webkit-mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.62) 34%,transparent 72%);
  mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.62) 34%,transparent 72%);
}
#gcbp-wash::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(120% 80% at 50% 0%,var(--gcbp-w,var(--accent)),transparent 62%);
  opacity:.22;
}
body.os-arcade-immersive .oa-shell-body{position:relative;z-index:1}
@media (max-width:700px){#gcbp-wash{filter:blur(30px) saturate(1.2);opacity:.34}}
.gc-reduce-motion #gcbp-wash,body.reduce-motion #gcbp-wash{transition:none}

/* ── the wrap ─────────────────────────────────────────────────────────────
   --gcbp-pad is the page gutter, exported as a custom property so the rows
   below can cancel exactly as much of it as they need in order to bleed. The
   bottom padding is the bottom bar's height: the bar overlays the scroller, so
   without this the last row would sit permanently underneath it. */
.gc-wrap.gcbp{
  --gcbp-pad:clamp(14px,2.6vw,40px);
  max-width:none;width:100%;
  gap:clamp(13px,1.8vw,22px);
  padding:clamp(12px,1.6vw,20px) var(--gcbp-pad) calc(78px + env(safe-area-inset-bottom,0px));
}
.gcbp .gc-title{font-size:13px;letter-spacing:.14em;text-transform:uppercase;opacity:.7}
.gcbp .gc-title span{display:none}
.gcbp .gc-head{gap:10px;align-items:center}

/* ── §8.1 item 2 — ONE hero row: wide landscape tile + portrait covers ───── */
.gcbp .gcbp-top{display:flex;gap:clamp(14px,1.8vw,26px);align-items:stretch;min-width:0}
.gcbp .gcbp-top>.gc-hero{flex:0 0 44%;min-width:0}
/* NO negative margin here. The scroller INSIDE the rail already cancels the
   page gutter; doing it on both stacks two -14px margins and pushes the row 14px
   PAST the viewport, which measured as `.gc-shelf-r` right = 383 on a 375px
   screen — real horizontal overflow, hidden only by the overflow-x:clip at the
   foot of this block. One cancellation, at the scroller. */
.gcbp .gcbp-rail{
  flex:1 1 auto;min-width:0;
  display:flex;flex-direction:column;justify-content:flex-end;
}
.gcbp .gcbp-rail>.gc-shelf{margin-top:0}
@media (max-width:900px){
  .gcbp .gcbp-top{flex-direction:column;gap:12px}
  .gcbp .gcbp-top>.gc-hero{flex:0 0 auto}
}

/* The hero wears the 16:9 cut of the SAME seeded artwork its poster uses — one
   game, one picture. The emoji span stays in the DOM as the degraded rendering
   and is hidden here, because the art already draws its own glyph. */
.gcbp .gc-hero{border-radius:14px;min-height:clamp(190px,24vw,290px)}
.gcbp .gc-hero-art{
  flex:0 0 46%;
  background-size:cover;background-position:50% 46%;background-repeat:no-repeat;
  border-right:1px solid rgba(255,255,255,.10);
}
.gcbp .gc-hero-art span{display:none}
.gcbp .gc-hero::after{opacity:.16}
@media (max-width:900px){
  .gcbp .gc-hero-art{flex:0 0 132px;border-right:none;border-bottom:1px solid rgba(255,255,255,.10)}
}

/* ── §8.1 item 1 — PORTRAIT BOX ART. This is most of the effect. ───────────
   background-color is the accent, deliberately: if a data: URI ever failed to
   decode, a tile degrades to a coloured plate rather than to a hole. */
.gcbp .gcbp-art{
  display:block;width:100%;aspect-ratio:2/3;
  border-radius:10px;
  background-color:var(--gc-accent,var(--accent));
  background-size:cover;background-position:50% 50%;background-repeat:no-repeat;
  box-shadow:0 10px 26px -16px rgba(0,0,0,.96);
  outline:1px solid rgba(255,255,255,.10);outline-offset:-1px;
  transition:transform .17s cubic-bezier(.2,.8,.3,1),box-shadow .17s ease,outline-color .17s ease;
}
/* aspect-ratio is recent enough to be worth a floor for anything without it. */
@supports not (aspect-ratio:2/3){.gcbp .gcbp-art{height:0;padding-bottom:150%}}

/* ── §8.1 item 3 — rows that BLEED off the right edge ─────────────────────
   The scroller cancels the page gutter on its right so its viewport reaches
   the screen edge and the next poster is visibly sliced; padding-right puts
   the gutter back INSIDE the scroll region so the final card still clears the
   edge once you have scrolled to the end. Vertical padding is not decoration:
   overflow-x:auto makes overflow-y auto too, and the focused tile scales up. */
.gcbp .gc-shelf{margin-top:0}
.gcbp .gc-shelf-r{
  gap:clamp(9px,1vw,14px);
  padding:10px var(--gcbp-pad) 14px 0;
  margin-right:calc(-1 * var(--gcbp-pad));
  scroll-padding-left:2px;
  scrollbar-width:none;
}
.gcbp .gc-shelf-r::-webkit-scrollbar{display:none}
.gcbp .gcbp-rail .gc-shelf-r{padding-top:10px}
/* A ROW CAN ONLY CANCEL THE GUTTER IT KNOWS ABOUT. Measured at 1920x1080: the
   rows stopped at x=1882 against a usable edge of 1914 — 32px short, and the
   32px was `.oa-shell-body{padding:0 clamp(12px,2.4vw,32px)}` (line ~9929),
   which is a PARENT's padding and therefore invisible to any negative margin
   further down. The hub supplies its own gutter with --gcbp-pad, so while the
   shell is holding the adopted library that outer padding is redundant as well
   as in the way. Scoped by :has() to the adoption marker so an .oa-shell-body
   holding anything else keeps it. */
@media (min-width:901px){
  body.os-arcade-immersive .oa-shell-body:has(> #view-games-body[data-oa-adopted]){
    padding-left:0;padding-right:0;
  }
}
.gcbp .gc-shelf-c{
  width:clamp(102px,10.4vw,152px);
  flex:0 0 auto;display:block;
  padding:0;border:0;border-radius:10px;background:transparent;
  transition:none;
}
.gcbp .gc-shelf-c:hover{background:transparent;border-color:transparent;transform:none}
.gcbp .gc-shelf-c .gc-shelf-i,
.gcbp .gc-shelf-c .gc-shelf-n,
.gcbp .gc-shelf-c .gc-shelf-t{display:none}
.gcbp .gc-shelf-c:hover .gcbp-art{transform:translateY(-3px)}
/* the resume dot has to clear the poster's rounded corner */
.gcbp .gc-shelf-res::after{top:9px;right:9px;z-index:3}
.gcbp .gc-shelf-rk{top:9px;left:9px;z-index:3}

/* ── §8.1 item 5 — eyebrow over each row (NEWS / MAJOR UPDATE) ───────────── */
.gcbp .gc-shelf-h{
  display:flex;align-items:center;gap:9px;
  font:800 10px var(--ui);letter-spacing:.22em;text-transform:uppercase;
  color:var(--muted-2);margin-bottom:2px;
}
.gcbp .gc-shelf-h i{flex:none;width:16px;height:2px;border-radius:2px;background:var(--accent);opacity:.85}

/* ── §8.1 item 4 — the metadata line UNDER the row ────────────────────────
   Steam's `MECCHA CHAMELEON / ↻ PLAYTIME: 2.9 HRS`. This is where the
   "N played · best X" that the owner had us take off the play screen went. It
   describes the FOCUSED tile and changes as focus moves; a row that does not
   hold focus keeps its line but dims it, so nothing jumps as focus travels. */
.gcbp .gcbp-meta{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 14px;
  min-height:38px;padding-top:2px;
  opacity:.34;transition:opacity .22s ease;
}
.gcbp .gcbp-meta.gcbp-meta-on{opacity:1}
.gcbp .gcbp-meta b{
  font:800 clamp(15px,1.5vw,21px) var(--ui);letter-spacing:.02em;
  color:var(--text);text-transform:uppercase;line-height:1.15;
}
.gcbp .gcbp-meta span{font:600 10.5px var(--mono);letter-spacing:.16em;color:var(--muted)}

/* ── §8.1 item 2 — THE FOCUS RING. Exactly one of these exists at a time. ── */
.gcbp .gcbp-on .gcbp-art{
  transform:scale(1.055);
  outline:2px solid #fff;outline-offset:2px;
  box-shadow:0 22px 46px -18px rgba(0,0,0,.98),0 0 30px -6px var(--gc-accent,var(--accent));
}
.gcbp .gcbp-tile:focus{outline:none}
.gcbp .gcbp-tile:focus-visible .gcbp-art{outline:2px solid #fff;outline-offset:2px}
.gc-reduce-motion .gcbp .gcbp-on .gcbp-art,
body.reduce-motion .gcbp .gcbp-on .gcbp-art{transform:none}
.gc-reduce-motion .gcbp .gcbp-art,
body.reduce-motion .gcbp .gcbp-art{transition:none}

/* ── §8.1 item 4 (tabs) — the CENTRED PILL TAB STRIP ─────────────────────── */
.gcbp .gcbp-tabs{
  justify-content:center;align-items:center;gap:7px;flex-wrap:wrap;
  padding:9px 0;margin-top:2px;
  border-top:1px solid var(--border);border-bottom:1px solid var(--border);
}
.gcbp .gcbp-tabs .gc-chip{
  display:inline-flex;align-items:center;gap:8px;
  min-height:44px;padding:0 17px;border-radius:999px;
  background:transparent;border:1px solid transparent;color:var(--muted);
  font:700 11.5px var(--ui);letter-spacing:.1em;text-transform:uppercase;
}
.gcbp .gcbp-tabs .gc-chip:hover{background:rgba(255,255,255,.07);color:var(--text)}
.gcbp .gcbp-tabs .gc-chip b{
  font:700 10px var(--mono);letter-spacing:.04em;
  background:rgba(255,255,255,.11);color:var(--text);
  border-radius:999px;padding:2px 7px;
}
.gcbp .gcbp-tabs .gc-chip.on{background:var(--accent);border-color:var(--accent);color:#04070d}
.gcbp .gcbp-tabs .gc-chip.on b{background:rgba(4,7,13,.22);color:#04070d}
.gcbp .gcbp-tabs .gc-chip-sp{
  flex:0 0 1px;min-width:1px;width:1px;align-self:stretch;
  margin:0 7px;background:var(--border);
}

/* ── the results grid is box art too ─────────────────────────────────────
   It was the one surface still pairing a square emoji with a paragraph of
   blurb. The blurb and the mode pills are not lost: they moved into the grid's
   own .gcbp-meta line, which is where §8.1 item 4 puts them. */
.gcbp .gc-grid{
  grid-template-columns:repeat(auto-fill,minmax(clamp(102px,10.4vw,152px),1fr));
  gap:clamp(11px,1.3vw,18px);
  padding:10px 0 4px;
}
.gcbp .gc-card{
  display:block;position:relative;
  min-height:0;padding:0;border:0;border-radius:10px;
  background:transparent;overflow:visible;transition:none;
}
.gcbp .gc-card::before{display:none}
.gcbp .gc-card:hover{background:transparent;border-color:transparent;transform:none}
.gcbp .gc-card:hover .gcbp-art{transform:translateY(-3px)}
.gcbp .gc-card .gc-card-ico,
.gcbp .gc-card .gc-card-b,
.gcbp .gc-card .gc-card-s{display:none}

/* 44px, and the circle still looks like a 26px circle. The button box IS the
   target — expanding only the hit area with a pseudo-element would leave a
   30x30 box for any audit that measures getBoundingClientRect, which is the
   measurement that flagged this control 21 times. */
.gcbp .gc-card-help{
  top:0;right:0;
  width:44px;height:44px;min-width:44px;min-height:44px;
  padding:0;border:0;background:transparent;border-radius:0;
  display:flex;align-items:center;justify-content:center;
  color:transparent;font-size:0;line-height:0;z-index:4;
  transition:opacity .15s ease;
}
.gcbp .gc-card-help::before{
  content:"?";
  display:flex;align-items:center;justify-content:center;
  width:26px;height:26px;border-radius:50%;
  border:1px solid rgba(255,255,255,.3);background:rgba(4,7,13,.78);
  color:var(--text);font:700 13px var(--ui);
  transition:background .15s ease,border-color .15s ease,color .15s ease;
}
.gcbp .gc-card-help:hover{background:transparent}
.gcbp .gc-card-help:hover::before{background:var(--accent);border-color:var(--accent);color:#04070d}
/* Quiet by default and loud on approach. Twenty-one "?" badges at full opacity
   over twenty-one posters is a rash on the artwork; the 44px HIT BOX does not
   change, only how much of it you can see until you reach for it. Written AFTER
   the block above on purpose — both are (0,2,0), so an `opacity:1` sitting up
   there would have won on source order and this would have done nothing.
   Coarse pointers keep it visible: there is no hover to reveal it with. */
.gcbp .gc-card-help{opacity:.32}
.gcbp .gc-card:hover .gc-card-help,
.gcbp .gc-card.gcbp-on .gc-card-help,
.gcbp .gc-card-help:focus,
.gcbp .gc-card-help:focus-visible{opacity:1}
@media (hover:none),(pointer:coarse){.gcbp .gc-card-help{opacity:.85}}

/* ── §8.1 item 6 — THE PERSISTENT BOTTOM BAR ──────────────────────────────
   Parked inside #oa-shell, which is the arcade's stacking context: that puts
   it above the library and below .gc-modal (z 120) without either of them
   needing to know it exists. z-index 30 is under the modal and over the rows. */
#gcbp-bar{
  position:absolute;left:0;right:0;bottom:0;z-index:30;
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  min-height:56px;
  padding:0 max(14px,env(safe-area-inset-right,0px))
          max(0px,env(safe-area-inset-bottom,0px))
          max(14px,env(safe-area-inset-left,0px));
  border-top:1px solid var(--border);
  background:linear-gradient(180deg,rgba(4,7,13,.68),rgba(4,7,13,.95));
  -webkit-backdrop-filter:blur(14px) saturate(1.1);backdrop-filter:blur(14px) saturate(1.1);
  pointer-events:auto;
}
#gcbp-bar.gcbp-bar-flow{position:sticky;bottom:0;z-index:5}
.gcbp-brand{display:flex;align-items:center;gap:11px;min-width:0}
.gcbp-brand b{font:800 13px var(--ui);letter-spacing:.24em;color:var(--text);white-space:nowrap}
.gcbp-brand em{font-style:normal;color:var(--muted-2);opacity:.55}
.gcbp-menu{
  min-height:44px;padding:0 17px;border-radius:9px;
  border:1px solid var(--border);background:rgba(255,255,255,.05);color:var(--text);
  font:800 12px var(--ui);letter-spacing:.2em;cursor:pointer;white-space:nowrap;
  touch-action:manipulation;transition:border-color .15s ease,background .15s ease;
}
.gcbp-menu:hover{border-color:var(--accent);background:var(--accent-glow)}
.gcbp-hints{display:flex;align-items:center;gap:clamp(9px,1.6vw,22px);min-width:0;overflow:hidden}
.gcbp-hints span{
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  font:700 10.5px var(--ui);letter-spacing:.18em;color:var(--muted);
}
.gcbp-hints i{
  font-style:normal;display:inline-flex;align-items:center;justify-content:center;
  min-width:23px;height:23px;padding:0 6px;border-radius:6px;
  border:1px solid var(--border);background:rgba(255,255,255,.08);
  font:700 11px var(--mono);color:var(--text);
}
@media (max-width:560px){
  .gcbp-brand b{display:none}
  .gcbp-hints span:first-child{display:none}
  .gcbp-hints{gap:11px}
}

/* ── §8.1 item 1 (status) — top-right cluster, ICONS ONLY, no labels ──────
   It goes into the arcade's own top bar rather than a second header of our
   own: two stacked bars on a 375px phone is exactly the padding v9.10.669 was
   asked to delete. .oa-exit already carries `margin-left:auto`; giving the
   cluster the auto margin instead lets Exit sit flush beside it. */
.gcbp-status{display:flex;align-items:center;gap:3px;margin-left:auto;min-width:0}
.gcbp-st{
  display:inline-flex;align-items:center;justify-content:center;gap:4px;
  min-width:40px;height:40px;padding:0 8px;
  border:1px solid transparent;border-radius:9px;background:transparent;
  color:var(--muted);font:600 13px var(--ui);line-height:1;
}
.gcbp-st b{font:700 11px var(--mono);color:var(--text)}
.gcbp-st-b{
  min-width:44px;height:44px;cursor:pointer;touch-action:manipulation;
  transition:border-color .15s ease,background .15s ease;
}
.gcbp-st-b:hover{border-color:var(--accent);background:var(--accent-glow);color:var(--text)}
.gcbp-st-c{font:700 12px var(--mono);color:var(--text);letter-spacing:.05em;padding:0 6px}
.gcbp-st-a{
  width:32px;min-width:32px;height:32px;padding:0;border-radius:50%;
  background:linear-gradient(140deg,var(--accent),var(--accent-2));
  color:#04070d;font:800 13px var(--ui);
}
@media (max-width:560px){
  .gcbp-st-b,.gcbp-st-n{display:none}
  .gcbp-status{gap:2px}
}

/* ── the MENU panel the bottom bar opens ─────────────────────────────────── */
.gcbp-menu-l{display:flex;flex-direction:column;gap:8px}
.gcbp-menu-r{
  display:flex;align-items:center;gap:14px;width:100%;
  min-height:58px;padding:11px 14px;text-align:left;
  border:1px solid var(--border-2);border-radius:12px;
  background:rgba(255,255,255,.03);color:var(--text);cursor:pointer;
  transition:border-color .15s ease,background .15s ease;
}
.gcbp-menu-r:hover{border-color:var(--accent);background:var(--accent-glow)}
.gcbp-menu-i{flex:none;width:30px;text-align:center;font-size:20px;line-height:1}
.gcbp-menu-b{display:flex;flex-direction:column;gap:2px;min-width:0}
.gcbp-menu-b b{font:700 14px var(--ui);color:var(--text)}
.gcbp-menu-b i{font:400 11.5px var(--ui);font-style:normal;color:var(--muted)}

/* ── THE 44px SWEEP ───────────────────────────────────────────────────────
   Verification found 22 controls under 44px at 375x812 and 29 at 812x375. All
   pre-existing. The blanket is scoped to .gcbp so it cannot reach the player
   frame or the modals, and the tiles are excluded because a poster is already
   far larger than 44px and a min-height would fight its aspect-ratio. */
.gcbp button:not(.gcbp-tile):not(.gc-card):not(.gc-card-help),
.gcbp .gc-headbtn,
.gcbp .gc-search{min-height:44px}
/* min-WIDTH too, and it is not redundant: measured at 812x375 four .gc-headbtn
   came back 37-38px wide. Under 900px the header hides each button's <span>,
   so what is left is one emoji inside 26px of padding — 44px tall and a third
   of a target wide. A 44px rule that only constrains one axis passes an audit
   that only looks at one axis. */
.gcbp button:not(.gcbp-tile):not(.gc-card):not(.gc-card-help),
.gcbp .gc-headbtn{min-width:44px}
/* The browse arrows are positioned `top:calc(50% + 9px)` against .gc-shelf, and
   .gc-shelf just grew a metadata line at its foot — so 50% is no longer the
   middle of the ARTWORK, which is the only thing the arrow is pointing at. The
   posters, their row padding and the meta line put the art's centre at ~45% of
   the shelf at every breakpoint measured, so that is the anchor. */
.gcbp .gc-shelf-nav{min-width:44px;width:44px;height:56px;top:45%}
.gcbp .gc-audio-set{align-items:center}

/* The volume slider measured 70x4 in landscape — a 4px tall control is not a
   control. The track keeps its 5px line; the INPUT grows to 44px so the thumb
   is reachable. -webkit-appearance:none is already on the base rule, which is
   what makes the runnable-track pseudo the thing that draws the line. */
input.gc-vol{
  height:44px;min-width:110px;width:132px;
  background:transparent;border-radius:0;padding:0;
}
input.gc-vol::-webkit-slider-runnable-track{
  height:5px;border-radius:99px;background:rgba(255,255,255,.16);
}
input.gc-vol::-webkit-slider-thumb{width:19px;height:19px;margin-top:-7px}
input.gc-vol::-moz-range-track{height:5px;border-radius:99px;background:rgba(255,255,255,.16)}
input.gc-vol::-moz-range-thumb{width:19px;height:19px}

/* oracle-games-progress.js injects its styles into a <style> that lands AFTER
   this file, so source order cannot win here — `button.gcp-d-go` is (0,1,1)
   against its (0,1,0) and wins on weight wherever it is written. */
button.gcp-d-go,button.gcp-d-done{min-height:44px}

/* ── phone ────────────────────────────────────────────────────────────────
   The posters get smaller, not the layout different: a console screen that
   turns into a list on a phone is not the thing he asked for. */
@media (max-width:700px){
  .gc-wrap.gcbp{--gcbp-pad:14px;padding-bottom:calc(74px + env(safe-area-inset-bottom,0px))}
  .gcbp .gc-shelf-c{width:clamp(96px,29vw,124px)}
  .gcbp .gc-grid{grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:10px}
  .gcbp .gcbp-meta{min-height:34px}
  .gcbp .gcbp-meta b{font-size:15px}
  .gcbp .gcbp-meta span{font-size:9.5px;letter-spacing:.13em}
  .gcbp .gcbp-tabs{
    justify-content:flex-start;flex-wrap:nowrap;overflow-x:auto;
    scrollbar-width:none;margin-right:calc(-1 * var(--gcbp-pad));padding-right:var(--gcbp-pad);
  }
  .gcbp .gcbp-tabs::-webkit-scrollbar{display:none}
  .gcbp .gcbp-tabs .gc-chip{flex:0 0 auto;padding:0 14px;font-size:11px}
  .gcbp .gc-hero{min-height:0}
  #gcbp-bar{min-height:54px}
  /* The header was three wrapped rows of chrome — title, search, then five
     buttons and a slider — sitting above the first poster on a 375px screen.
     The title says GAME CENTER directly under a bar that says ORACLE ARCADE,
     and the count is now a badge inside every tab; the action row scrolls
     sideways instead of wrapping. ~55px of vertical chrome back. */
  .gcbp .gc-title{display:none}
  .gcbp .gc-count{display:none}
  .gcbp .gc-head-acts{
    flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    width:100%;margin-left:0;
    margin-right:calc(-1 * var(--gcbp-pad));padding-right:var(--gcbp-pad);
  }
  .gcbp .gc-head-acts::-webkit-scrollbar{display:none}
  .gcbp .gc-audio-set{flex:0 0 auto;width:auto}
  .gcbp .gc-hero-art{flex:0 0 108px}
}
/* The arcade's own brand text is 'Oracle Arcade' beside a chip glyph, and with
   the status cluster now sharing that bar it clipped to "ORACLE ARCAD" on a
   phone. The glyph carries an explicit 18px width so it survives font-size:0.
   Scoped by :has() to bars that actually hold the cluster. */
@media (max-width:560px){
  .oa-shell-top:has(.gcbp-status)>span{font-size:0;flex:0 0 auto}
}
/* nothing in the hub may push the page sideways */
.gcbp{overflow-x:clip;max-width:100%}
/* ══ end v9.10.670 ═════════════════════════════════════════════════════════ */


/* ══ v9.10.671 — PHASE A4: THE ONLY EXIT WAS UNREACHABLE ═══════════════════
   Every number here was MEASURED in real Chromium at 375x812, offscreen, over
   file:// against this sheet, with requestFullscreen refused the way iOS Safari
   refuses it. Hit testing was driven with real CDP touch and real CDP mouse —
   a dispatched PointerEvent proves a listener exists, not that a thumb reaches
   it.

   WHAT WAS WRONG. v9.10.669 put ONE control on the play screen: a 48px glyph,
   top-left, that opens the pause menu. v9.10.670 then added, for the Big
   Picture library:

       body.os-arcade-immersive .oa-shell-body{position:relative;z-index:1}

   (this file, ~10689) so the library would paint above #gcbp-wash. That line is
   correct about the wash and fatal for the game. It makes .oa-shell-body a
   STACKING CONTEXT at z-index 1, and .gc-frame.gc-immersive — position:fixed,
   inline z-index 2147483000 — is a DESCENDANT of it. Two thousand million
   resolves INSIDE that context and the whole subtree is flattened to 1.
   .oa-shell-top is position:relative; z-index:3 (~9907) and a SIBLING under
   #oa-shell, so 3 beat 1 and 65px of blurred brand bar sat on top of the game.

   MEASURED, as shipped: .gc-frame at 0..812 fixed z=2147483000, yet
   document.elementsFromPoint(34,34) returned
     [span (inside .oa-shell-top), div.oa-shell-top z=3, button.gc-menu-btn, ...]
   — the glyph THIRD. 36 of 36 sampled points in the top 65px belonged to
   .oa-shell-top. A real touch tap on the glyph did nothing. A real mouse click
   did nothing. Esc still worked, which is exactly why this survived: every
   desktop test passes and the phone has no exit at all.

   IT IS THE SAME LESSON §9.5 RECORDS FROM v9.10.666 — a z-index only competes
   inside its own stacking context — reintroduced by the Big Picture pass, and
   this time it killed the only way out on touch.

   WHY THE PIXEL TEST DID NOT CATCH IT. The covering span has no background, so
   the glyph's pixel differential is 0.335: it IS painted. Only hit testing was
   broken. That is the mirror image of the v9.10.665 failure, where DOM probes
   said healthy and the pixels were absent. Neither test alone finds both; the
   pair does. Keep running both.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. UNCAP THE RUNNING GAME ─────────────────────────────────────────────
   Raise the library's own context ABOVE the brand bar instead of below it, so
   a fixed descendant is no longer beaten by a sibling of its ancestor.

   WHY NOT JUST DELETE THE 10689 LINE. Deleting it puts #gcbp-wash (absolute,
   z-index:0, a positioned child of .oa-shell) back on top of the whole library
   — positioned boxes paint after in-flow ones whatever their DOM order, which
   is the bug that line was added to fix. .oa-shell-body has to stay a stacking
   context; it just has to be a stacking context that WINS.

   WHY 4. It has to beat .oa-shell-top (3) and must not disturb the two boxes
   that already sit above the library on purpose: #gcbp-bar is z-index:30 and
   .gc-modal is 120, both children of #oa-shell, both still above 4. In the
   LIBRARY state nothing changes visually at all — .oa-shell-top and
   .oa-shell-body are consecutive rows of the same flex column and do not
   overlap, so their paint order is unobservable there. It is observable only
   for the one box that leaves the flow: the fixed game frame.

   APPEND-ONLY, so this overrides on SOURCE ORDER at equal specificity (0,2,1)
   and touches nothing but z-index — the position:relative from 10689 stands. */
body.os-arcade-immersive .oa-shell-body{z-index:4}

/* ── 2. NOTHING ON THE PLAY SCREEN EXCEPT THE GAME ─────────────────────────
   "the game view is full screen ... not the buttons and stuff around it outside
   the game view". §9.2 says the same: nothing on the play screen except the
   game. Rule 1 already puts the opaque frame over the bar, so this is not what
   restores the exit — it removes a 65px backdrop-filter:blur(12px) saturate()
   layer that would otherwise keep compositing, every frame, underneath an
   opaque cover, and it removes .oa-exit as a stray hit target over the game.

   .gc-immersive IS THE RIGHT SIGNAL, and it is checked rather than assumed:
   stageEnter() is called from exactly one place (oracle-games.js ~4897, inside
   run()), so the class is on the frame for a RUNNING GAME and off for the start
   card. Measured: start card frame immClass=false with the glyph at top=76
   (65px bar + 10px pad); running frame immClass=true with the glyph at top=10.
   The start card therefore keeps the bar, which is right — the owner struck
   through .gc-frame-head in his photograph, not the arcade's own brand bar, and
   the start card is the surface where leaving is meant to be easy.

   IF :has() IS UNSUPPORTED this rule is dropped and rule 1 alone still holds
   the exit open. That ordering is deliberate: the fix that matters does not
   depend on the newer selector. */
body.os-arcade-immersive .oa-shell:has(.gc-frame.gc-immersive)>.oa-shell-top{display:none}
/* ══ end v9.10.671 ═════════════════════════════════════════════════════════ */

/* ══ v9.10.672 — THE OFFLINE BANNER WAS EATING THE ONLY EXIT ════════════════
   Phase A4 leaves exactly ONE visible way out of a running game: the 48px
   .gc-menu-btn glyph at the top-left. oracle-core.js setLive(false) — raised
   any time the /health poll fails, which for a phone is every tunnel, lift and
   dropped bar — prepends #offline-banner to <body> with an INLINE
   position:fixed; top:0; z-index:9000 and default pointer-events.

   MEASURED at 375x812 in real Chromium: the banner is 44px tall, the glyph
   occupies y=10..58, and sweeping the glyph's centre column every 4px returned
   DIV#offline-banner for 9 of 12 rows — a 14px live sliver at the bottom of a
   48px control. A REAL CDP touch at the glyph's centre did nothing at all; a
   touch at y=55 opened the menu. The same collision kills the arcade's hub
   .oa-exit, whose centre (y=32) sits under the banner's 44px bottom edge at
   phone width and clears it by 2px at 812x375 and 1920x1080 — so the defect
   only bites the viewport the owner is complaining about.

   1. POINTER-EVENTS IS THE FIX THAT MATTERS, and it is deliberately global and
      unconditional. The banner is a sentence. It has no link, no button and no
      dismiss — nothing in it was ever meant to be clicked, so nothing is lost
      by making it stop absorbing taps, and NO control anywhere in the OS can
      be killed by it again. It does not depend on :has(), on a body class, or
      on the arcade being involved at all.
   2. Hiding it outright on the play screen is §9.2 ("nothing on the play
      screen except the game") and is the same predicate v9.10.671 uses for
      .oa-shell-top. It is the cosmetic half: with rule 1 in place the glyph is
      already reachable in every browser, including one with no :has() support.
      A player who dropped offline still sees the banner the moment they are
      back in the library. */
#offline-banner{pointer-events:none !important}
body.os-arcade-immersive:has(.gc-frame.gc-immersive) #offline-banner{display:none}

/* ── The insertion marker the Big Picture tab strip is placed before. It never
   paints and never occupies a flex/grid slot; it exists only so the strip can
   land at §8.1 position 4 without reordering the code that builds it. ── */
.gcbp-tabs-anchor{display:none}
/* ══ end v9.10.672 ═════════════════════════════════════════════════════════ */


/* ══ v9.10.673 — TURN-GAME BOARDS SIT AT THE TOP OF A FULL-HEIGHT PLAY AREA ═══
   The owner: "some games arent centered and they are top like tiktac to".

   MEASURED in real Chromium, a 300px board in the 739px play area the A4
   fullscreen work now hands every game:
       gap above the board   37px
       gap below the board  404px
   Not a rounding error — the board is pinned to the top with more than half the
   screen empty underneath it.

   IT IS A LATENT BUG THAT A4 EXPOSED, NOT ONE A4 INTRODUCED. Two declarations
   compose into it:
     .gc-stage-body{align-items:flex-start}   (base rule)
     .gc-turn{...}                            with no justify-content, so it
                                              defaults to flex-start
   Before the play screen went full height the stage body was only as tall as its
   content, so neither had anything to push against and both looked correct. Give
   the container 739px and the same two declarations park a 3x3 grid against the
   ceiling. Every small-boarded turn game is affected — tictactoe worst, because
   its board is the smallest.

   WHY align-self AND NOT A FIX ON .gc-stage-body. The container is shared with
   the canvas games, whose .gc-canvas is sized by JS against the box it is given;
   changing the container's align-items would resize every arcade game as a side
   effect of centring a noughts-and-crosses grid. Scoping to the child changes
   the turn games and nothing else — verified live: .gc-arcade still computes
   align-self:auto with this rule active.

   VERIFIED BOTH WAYS, live, at 1440x900 with the container forced to 760px:
       300px board  ->  222 above / 219 below   CENTRED
       560px board  ->   93 above /  90 below   CENTRED
   Also re-checked at 375x812, where the mobile rule already set
   align-items:center and this is a harmless no-op. ══════════════════════════ */
.gc-stage-body > .gc-turn{align-self:stretch;justify-content:center}
/* ══ end v9.10.673 ═════════════════════════════════════════════════════════ */

/* ══ v9.10.675 — GAME CENTER: batch "turn-puzzle" ═══════════════════════════
   Mancala · Nine Men's Morris · Hex · Sudoku · Nonogram · Block Escape.

   APPENDED, never edited in place — this file is append-only and every rule
   below is a NEW selector, so nothing above can change meaning because of it.

   THREE THINGS EVERY BOARD HERE DOES:
   · it sizes with min(px, vw, ...) AND caps its height, because the play
     surface is now full-bleed and a board that only knows about width becomes
     a letterboxed stamp the moment the phone turns sideways;
   · it uses design tokens for every colour, so the owner's red theme drives
     these the same way it drives the rest of the OS. The only literals are the
     two Hex player colours and the Block Escape car — those exist so you can
     tell the pieces apart, exactly like the Blocks tetrominoes;
   · nothing interactive is under 44px unless the grid itself forbids it
     (Nonogram at 15x15 and Sudoku at 9x9 are the two, same as Gomoku).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── shared: the small chip strip the three solitaires use ─────────────────
   EVERY RULE HERE IS SCOPED BEHIND .gc-chiprow, and that is not tidiness.
   `.gc-chip` already exists in this file (~line 6826) and is worn by the
   library's category filter, the mode filter, Memory's track and stage chips
   and the Big Picture tab strip. A BARE `.gc-chip` appended down here has the
   same specificity as the original and wins on source order — so the first cut
   of this block was silently restyling all of them, deleting their hover
   background, and beating the base's 44px phone rule (also 0,1,0) to shrink
   them to 34px on a phone. Caught by diffing the class names this block
   declares against the class names the base declares, not by looking at it.  */
.gc-chiprow{display:flex;gap:6px;flex-wrap:wrap;justify-content:center}
.gc-chiprow .gc-chip{background:rgba(255,255,255,.05);border-radius:999px;padding:7px 14px;
  min-height:36px;font:600 12px var(--ui);
  transition:background .14s,border-color .14s,color .14s}
.gc-chiprow .gc-chip:hover{background:rgba(255,255,255,.09);border-color:var(--accent);color:var(--text)}
.gc-chiprow .gc-chip.on{background:var(--accent);border-color:var(--accent);color:#04070d}
@media (max-width:900px){
  .gc-chiprow .gc-chip{min-height:44px;padding:11px 15px;display:inline-flex;align-items:center}
}

/* ── Mancala ─────────────────────────────────────────────────────────────── */
.gc-mc{display:flex;align-items:stretch;gap:clamp(6px,1.6vw,12px);
  width:min(600px,96vw);padding:clamp(8px,2vw,14px);
  background:linear-gradient(180deg,rgba(140,96,52,.16),rgba(90,60,32,.10));
  border:1px solid var(--border);border-radius:16px}
.gc-mc-mid{flex:1 1 auto;display:flex;flex-direction:column;gap:clamp(6px,1.6vw,12px);min-width:0}
.gc-mc-row{display:grid;grid-template-columns:repeat(6,1fr);gap:clamp(4px,1.2vw,10px)}
.gc-mc-pit{position:relative;aspect-ratio:1;max-height:16vh;border-radius:50%;padding:0;
  background:radial-gradient(circle at 50% 38%,rgba(0,0,0,.42),rgba(255,255,255,.05));
  border:1px solid var(--border-2,var(--border));color:var(--text);cursor:default;
  display:flex;align-items:flex-end;justify-content:center;transition:.13s}
.gc-mc-pit b{position:relative;z-index:2;font:700 clamp(11px,2.4vw,15px) var(--mono);
  padding-bottom:6%;text-shadow:0 1px 3px rgba(0,0,0,.7)}
.gc-mc-pit.empty b{color:var(--muted-2,var(--muted))}
.gc-mc-pit.ok{cursor:pointer;border-color:var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent),0 0 12px -4px var(--accent)}
.gc-mc-pit.ok:hover{background:radial-gradient(circle at 50% 38%,rgba(0,0,0,.3),var(--accent-glow,rgba(34,217,230,.2)))}
.gc-mc-pit.cur{outline:2px solid var(--accent);outline-offset:2px}
.gc-mc-seeds{position:absolute;inset:0;pointer-events:none}
.gc-mc-seeds i{position:absolute;width:13%;height:13%;margin:-6.5% 0 0 -6.5%;border-radius:50%;
  background:linear-gradient(160deg,#e6c894,#a97c46);box-shadow:0 1px 2px rgba(0,0,0,.55)}
.gc-mc-store{flex:0 0 clamp(46px,11vw,78px);border-radius:999px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:4px;
  background:radial-gradient(ellipse at 50% 30%,rgba(0,0,0,.4),rgba(255,255,255,.05));
  border:1px solid var(--border-2,var(--border))}
.gc-mc-store b{font:700 clamp(16px,3.6vw,26px) var(--mono);color:var(--text)}
.gc-mc-lab{font:600 8.5px var(--ui);letter-spacing:1.1px;text-transform:uppercase;color:var(--muted-2,var(--muted))}
@media (max-width:520px){.gc-mc-pit{max-height:12vh}}

/* ── Nine Men's Morris ───────────────────────────────────────────────────── */
.gc-mor{display:flex;flex-direction:column;align-items:center;gap:10px}
.gc-mor-grid{position:relative;width:min(430px,86vw);aspect-ratio:1;max-height:62vh;
  padding:0;margin:22px;background:rgba(255,255,255,.02);border-radius:10px}
.gc-mor-sq{position:absolute;border:2px solid var(--border-2,var(--border));border-radius:3px;pointer-events:none}
.gc-mor-ln{position:absolute;border-top:2px solid var(--border-2,var(--border));
  border-left:2px solid var(--border-2,var(--border));pointer-events:none;
  transform:translate(-1px,-1px)}
.gc-mor-p{position:absolute;width:min(44px,11%);height:min(44px,11%);
  transform:translate(-50%,-50%);border-radius:50%;padding:0;cursor:default;
  background:var(--panel);border:1px solid var(--border-2,var(--border));transition:.13s}
.gc-mor-p.land{cursor:pointer;background:var(--accent-glow,rgba(34,217,230,.18));
  border-color:var(--accent);box-shadow:0 0 0 3px rgba(0,0,0,.25)}
.gc-mor-p.pick{cursor:pointer}
.gc-mor-p.take{cursor:pointer;box-shadow:0 0 0 3px var(--bad),0 0 14px -2px var(--bad)}
.gc-mor-p.sel{outline:2px solid var(--accent);outline-offset:3px}
.gc-mor-p.kb{outline:2px dashed var(--accent);outline-offset:4px}
.gc-mor-W{background:linear-gradient(160deg,#f4f7fc,#c3ccda);border-color:#aab4c4}
.gc-mor-B{background:linear-gradient(160deg,#2b3241,#10141d);border-color:#000}
.gc-mor-p.mill{box-shadow:0 0 0 2px var(--good),0 0 12px -3px var(--good)}
.gc-mor-p.take.mill{box-shadow:0 0 0 3px var(--bad),0 0 14px -2px var(--bad)}
.gc-mor-say{font:600 12.5px var(--ui);color:var(--accent);text-align:center;min-height:17px}

/* ── Hex ─────────────────────────────────────────────────────────────────── */
.gc-hx{display:flex;justify-content:center;padding:10px 4px}
.gc-hx-w{position:relative;width:min(480px,94vw);aspect-ratio:1.574;max-height:60vh}
.gc-hx-c{position:absolute;padding:0;border:none;background:transparent;cursor:default;
  clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);transition:.12s}
.gc-hx-c::after{content:"";position:absolute;inset:6%;
  clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
  background:rgba(255,255,255,.06);transition:.12s}
.gc-hx-c:not(:disabled){cursor:pointer}
.gc-hx-c:not(:disabled):hover::after{background:var(--accent-glow,rgba(34,217,230,.28))}
.gc-hx-R::after{background:linear-gradient(160deg,#fb7185,#be123c)}
.gc-hx-B::after{background:linear-gradient(160deg,#60a5fa,#1d4ed8)}
.gc-hx-c.path::after{box-shadow:inset 0 0 0 3px var(--text);filter:brightness(1.25)}
.gc-hx-c.kb::after{box-shadow:inset 0 0 0 2px var(--accent)}
.gc-hx-edge{position:absolute;pointer-events:none;border-radius:3px}
.gc-hx-et,.gc-hx-eb{left:0;right:0;height:4px;background:linear-gradient(90deg,#fb7185,#be123c)}
.gc-hx-et{top:-8px}
.gc-hx-eb{bottom:-8px}
.gc-hx-el,.gc-hx-er{top:0;bottom:0;width:4px;background:linear-gradient(180deg,#60a5fa,#1d4ed8)}
.gc-hx-el{left:-9px}
.gc-hx-er{right:-9px}

/* ── Sudoku ──────────────────────────────────────────────────────────────── */
.gc-sd{display:flex;flex-direction:column;align-items:center;gap:10px;width:100%}
.gc-sd-b{display:grid;grid-template-columns:repeat(9,1fr);width:min(470px,94vw);
  max-height:56vh;aspect-ratio:1;gap:1px;padding:3px;background:var(--border);
  border:2px solid var(--border-2,var(--border));border-radius:10px}
.gc-sd-c{position:relative;padding:0;aspect-ratio:1;background:var(--panel);border:none;
  color:var(--accent);font:600 clamp(15px,3.6vw,24px) var(--mono);cursor:pointer;
  display:flex;align-items:center;justify-content:center;transition:background .1s}
.gc-sd-c.rt{margin-right:-1px;border-right:2px solid var(--border-2,var(--border))}
.gc-sd-c.bt{margin-bottom:-1px;border-bottom:2px solid var(--border-2,var(--border))}
.gc-sd-c.fix{color:var(--text);background:var(--panel-2,var(--panel));cursor:default}
.gc-sd-c.peer{background:rgba(255,255,255,.055)}
.gc-sd-c.fix.peer{background:rgba(255,255,255,.09)}
.gc-sd-c.same{background:var(--accent-glow,rgba(34,217,230,.16))}
.gc-sd-c.sel{background:var(--accent);color:var(--bg)}
.gc-sd-c.bad{color:var(--bad)}
.gc-sd-c.sel.bad{background:var(--bad);color:var(--bg)}
.gc-sd-n{position:absolute;inset:2px;display:grid;grid-template-columns:repeat(3,1fr);
  grid-template-rows:repeat(3,1fr);pointer-events:none}
.gc-sd-n i{font:500 clamp(6px,1.5vw,10px)/1 var(--mono);color:var(--muted);
  display:flex;align-items:center;justify-content:center;font-style:normal}
.gc-sd-pad{display:grid;grid-template-columns:repeat(11,1fr);gap:5px;width:min(470px,94vw)}
.gc-sd-k{position:relative;min-height:44px;padding:0;background:rgba(255,255,255,.05);
  border:1px solid var(--border);border-radius:9px;color:var(--text);
  font:600 clamp(14px,3.4vw,19px) var(--mono);cursor:pointer;transition:.12s}
.gc-sd-k:hover{border-color:var(--accent);background:var(--accent-glow,rgba(34,217,230,.14))}
.gc-sd-k i{position:absolute;right:3px;bottom:1px;font:500 8px var(--mono);
  color:var(--muted-2,var(--muted));font-style:normal}
.gc-sd-k.out{opacity:.4}
.gc-sd-k.on{background:var(--accent);border-color:var(--accent);color:var(--bg)}
.gc-sd-era,.gc-sd-note{font-size:15px}
.gc-sd-bar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:center}
.gc-sd-msg{flex:1 0 100%;text-align:center;font:500 12px var(--ui);color:var(--muted);min-height:16px}
@media (max-width:430px){.gc-sd-pad{grid-template-columns:repeat(6,1fr)}}

/* ── Nonogram ────────────────────────────────────────────────────────────── */
.gc-ng{display:flex;flex-direction:column;align-items:center;gap:10px;width:100%}
.gc-ng-b{display:grid;grid-template-columns:auto minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);
  width:min(470px,95vw);max-height:60vh}
.gc-ng-corner{grid-area:1/1}
.gc-ng-ch{grid-area:1/2;display:grid;grid-template-columns:repeat(var(--ngn),1fr);gap:1px}
.gc-ng-cl{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:0;
  padding-bottom:3px;min-height:calc(var(--ngc) * 1.25em)}
.gc-ng-rh{grid-area:2/1;display:grid;grid-template-rows:repeat(var(--ngn),1fr);gap:1px}
.gc-ng-rl{display:flex;align-items:center;justify-content:flex-end;gap:.35em;padding-right:5px;
  min-width:calc(var(--ngr) * 1.15em)}
.gc-ng-cl i,.gc-ng-rl i{font:600 clamp(8px,1.9vw,13px)/1.25 var(--mono);color:var(--muted);font-style:normal}
.gc-ng-cl.ok i,.gc-ng-rl.ok i{color:var(--good);opacity:.55}
.gc-ng-f{grid-area:2/2;display:grid;grid-template-columns:repeat(var(--ngn),1fr);
  aspect-ratio:1;gap:1px;background:var(--border);border:2px solid var(--border-2,var(--border));
  border-radius:6px;padding:1px}
.gc-ng-c{position:relative;padding:0;aspect-ratio:1;background:var(--panel);border:none;
  cursor:pointer;transition:background .09s}
.gc-ng-c:hover{background:rgba(255,255,255,.12)}
.gc-ng-c.on{background:var(--accent)}
.gc-ng-c.no::after{content:"";position:absolute;inset:26%;
  background:linear-gradient(45deg,transparent 43%,var(--muted) 43%,var(--muted) 57%,transparent 57%),
             linear-gradient(-45deg,transparent 43%,var(--muted) 43%,var(--muted) 57%,transparent 57%)}
.gc-ng-c.kb{box-shadow:inset 0 0 0 2px var(--accent-2,var(--accent))}
.gc-ng-c.rt{border-right:2px solid var(--border-2,var(--border))}
.gc-ng-c.bt{border-bottom:2px solid var(--border-2,var(--border))}
.gc-ng-bar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:center}
.gc-ng-mode.on{background:var(--accent);border-color:var(--accent);color:var(--bg)}
.gc-ng-b.tight .gc-ng-cl i,.gc-ng-b.tight .gc-ng-rl i{font-size:clamp(7px,1.5vw,10px)}

/* ── Block Escape ────────────────────────────────────────────────────────── */
.gc-be{display:flex;flex-direction:column;align-items:center;gap:10px}
.gc-be-b{position:relative;width:min(430px,90vw);aspect-ratio:1;max-height:58vh;
  background:var(--panel);border:3px solid var(--border-2,var(--border));border-radius:12px;
  overflow:visible}
.gc-be-grid{position:absolute;inset:0;display:grid;grid-template-columns:repeat(6,1fr);
  grid-template-rows:repeat(6,1fr)}
.gc-be-cell{border-right:1px solid rgba(255,255,255,.05);border-bottom:1px solid rgba(255,255,255,.05)}
.gc-be-exit{position:absolute;right:-3px;width:9px;display:flex;align-items:center;justify-content:center}
.gc-be-exit i{display:block;width:5px;height:76%;border-radius:3px;background:var(--good);
  box-shadow:0 0 12px -1px var(--good)}
.gc-be-blk{position:absolute;border-radius:9px;cursor:grab;touch-action:none;
  background:linear-gradient(160deg,rgba(150,165,190,.95),rgba(88,100,124,.95));
  border:1px solid rgba(0,0,0,.45);box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 2px 5px rgba(0,0,0,.4);
  transition:left .13s ease-out,top .13s ease-out}
.gc-be-blk::after{content:"";position:absolute;border-radius:3px;background:rgba(0,0,0,.22)}
.gc-be-blk.h::after{left:12%;right:12%;top:42%;height:16%}
.gc-be-blk.v::after{top:12%;bottom:12%;left:42%;width:16%}
.gc-be-blk.x{background:linear-gradient(160deg,#fb7185,#be123c);border-color:#7f1d1d;z-index:3}
.gc-be-blk.sel{box-shadow:inset 0 0 0 2px var(--accent),0 2px 8px rgba(0,0,0,.5)}
.gc-be-blk.grab{cursor:grabbing;transition:none;filter:brightness(1.12)}
.gc-be-blk.out{left:105% !important;opacity:0;transition:left .5s cubic-bezier(.4,0,.9,.4),opacity .5s .15s}
.gc-be-bar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:center}

/* Reduced motion: the boards still say everything they said, they just stop
   sliding to say it. Honours the media query AND the OS class, per the contract
   in oracle-games.js. */
@media (prefers-reduced-motion:reduce){
  .gc-be-blk,.gc-mc-pit,.gc-mor-p,.gc-hx-c,.gc-sd-c,.gc-ng-c{transition:none !important}
}
.gc-reduce-motion .gc-be-blk,.gc-reduce-motion .gc-mc-pit,.gc-reduce-motion .gc-mor-p,
.gc-reduce-motion .gc-hx-c,.gc-reduce-motion .gc-sd-c,.gc-reduce-motion .gc-ng-c{transition:none !important}
/* ══ end v9.10.675 ═════════════════════════════════════════════════════════ */

/* ══ v9.10.675b — turn-puzzle: phone tap targets ════════════════════════════
   MEASURED, at 375x812, in real Chromium: Mancala's pits came out 34px and the
   Morris points 35px. Both are the same shape of problem — a fixed number of
   cells across a fixed width — and both have room to give, so this takes it:
   the Mancala stores and the board padding shrink on a narrow screen (nothing
   about the stores needs to be wide, they hold a number), and the Morris points
   grow from 11% of the board to 13%, which still leaves 11px of clear lattice
   between neighbouring points.

   NOT changed, and named rather than quietly left: Hex's cells are 35x41 and a
   Sudoku square is 38px on a phone. Those two are the grid itself — 7 hexes and
   9 squares across 350px cannot be 44px each — and widening them would mean a
   smaller board, which is worse. Both are comfortably larger than Gomoku's
   23px, which has shipped since v9.10.636. Sudoku's REPEATED control is the
   number pad, and that is 44px by construction.                              */
@media (max-width:430px){
  .gc-mc{padding:4px;gap:4px}
  .gc-mc-mid{gap:4px}
  .gc-mc-row{gap:4px}
  .gc-mc-store{flex:0 0 30px;border-radius:15px}
  .gc-mc-store b{font-size:15px}
  .gc-mc-lab{font-size:7px;letter-spacing:.5px}
  .gc-mc-pit b{font-size:12px}
  .gc-mor-p{width:min(44px,13%);height:min(44px,13%)}
}
/* ══ end v9.10.675b ════════════════════════════════════════════════════════ */

/* ══ v9.10.676 — EVERY GAME GETS ITS OWN TABLE ═══════════════════════════════
   The player surface was one flat near-black panel for all 38 titles, so a
   board game and an arcade game looked like the same empty rectangle. These are
   pure generated gradients (the CSP blocks image assets), scoped by the
   data-game / data-cat attributes the frame now carries, and they only paint
   BEHIND the game — no game's own canvas or tiles are touched.               */
.gc-frame[data-cat]{background-image:radial-gradient(120% 80% at 50% 0%,rgba(255,255,255,.05),transparent 60%)}
.gc-frame[data-cat="board"]   {background-color:#2a1d12;background-image:radial-gradient(120% 85% at 50% 0%,#4a3520 0%,#2f2114 45%,#1a1109 100%)}
.gc-frame[data-cat="arcade"]  {background-color:#070a18;background-image:radial-gradient(110% 80% at 50% 0%,#1b2352 0%,#0d1130 46%,#05070f 100%)}
.gc-frame[data-cat="puzzle"]  {background-color:#0a1420;background-image:radial-gradient(115% 85% at 50% 0%,#143a4d 0%,#0d2333 44%,#050d15 100%)}
.gc-frame[data-cat="word"]    {background-color:#141021;background-image:radial-gradient(115% 85% at 50% 0%,#3a2456 0%,#221439 46%,#0c0716 100%)}
.gc-frame[data-cat="card"]    {background-color:#0b1c14;background-image:radial-gradient(115% 85% at 50% 0%,#175039 0%,#0e3325 45%,#04160f 100%)}
.gc-frame[data-cat="skill"]   {background-color:#1a0a12;background-image:radial-gradient(115% 85% at 50% 0%,#5a1233 0%,#330b1e 46%,#14040c 100%)}
/* a few titles earn their own table rather than their category's */
.gc-frame[data-game="mahjong"]{background-color:#082b21;background-image:radial-gradient(120% 90% at 50% 0%,#1f6b52 0%,#14503d 42%,#082b21 100%)}
.gc-frame[data-game="snake"]  {background-color:#04140a;background-image:radial-gradient(110% 80% at 50% 0%,#0f3d1c 0%,#082612 46%,#031007 100%)}
.gc-frame[data-game="asteroid"]{background-color:#04060d;background-image:radial-gradient(120% 90% at 50% 10%,#141a33 0%,#080b1a 50%,#020307 100%)}
.gc-frame[data-game="sudoku"] {background-color:#0d1017;background-image:radial-gradient(110% 80% at 50% 0%,#232c3d 0%,#131924 48%,#080b11 100%)}

/* ══ v9.10.677 — THE RESULT CARD, STYLED ═════════════════════════════════════
   The card's JS has always built a score with a count-up, three stars and a row
   of stat chips — and NOT ONE .gc-result-* rule existed in this stylesheet, so
   all of it rendered as unstyled inline text at body size. That is why the win
   screen read "Score580" and "Best 5843W · 0L · 0D3 played": the chips had no
   box, no padding and no gap, so they ran together into one string. Styling
   them is the whole fix — no JS change was needed to make the card legible.  */
.gc-overlay-card:has(.gc-result){max-width:min(460px,94vw)}
.gc-result{display:flex;flex-direction:column;align-items:center;gap:14px;margin:6px 0 4px}

/* SCORE — the number is the headline, the word is a quiet label above it */
.gc-result-score{display:flex;flex-direction:column;align-items:center;gap:2px;line-height:1}
.gc-result-k{font:700 10px var(--ui,sans-serif);letter-spacing:1.6px;text-transform:uppercase;color:var(--muted-2,#6b7a90)}
.gc-result-n{font:800 46px var(--mono,monospace);color:var(--text,#e9eef7);letter-spacing:-1px;
  text-shadow:0 2px 18px rgba(34,217,230,.35)}

/* STARS — the reward. Big, gold, and they land one at a time (GC.stagger). */
.gc-result-stars{display:flex;gap:10px;align-items:center;justify-content:center}
.gc-result-star{font-style:normal;font-size:40px;line-height:1;color:rgba(255,255,255,.16);
  filter:none;transition:color .2s}
.gc-result-star.on{color:#f5c944;text-shadow:0 0 16px rgba(245,201,68,.75),0 0 34px rgba(245,201,68,.35)}

/* CHIPS — one fact per pill, so they can never run together again */
.gc-result-chips{display:flex;flex-wrap:wrap;gap:7px;justify-content:center;max-width:100%}
.gc-result-chip{display:inline-flex;align-items:center;gap:5px;background:rgba(255,255,255,.06);
  border:1px solid var(--border,rgba(255,255,255,.12));border-radius:999px;padding:6px 13px;
  font:500 12px var(--ui,sans-serif);color:var(--muted,#8b9bb0);white-space:nowrap}
.gc-result-chip b{font:700 12.5px var(--mono,monospace);color:var(--text,#e9eef7)}
.gc-result-chip.gc-result-new{background:rgba(245,201,68,.14);border-color:rgba(245,201,68,.5);color:#f5c944;font-weight:700}
.gc-result-chip.gc-result-ach{background:rgba(167,139,250,.15);border-color:rgba(167,139,250,.45);color:#c4b5fd}

@media (max-width:900px){
  .gc-result-n{font-size:40px}
  .gc-result-star{font-size:34px}
}

/* ══ v9.10.678 — LEVEL PICKER ════════════════════════════════════════════════ */
.gc-levels-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(52px,1fr));gap:8px;
  margin:12px 0 4px;max-height:46vh;overflow-y:auto;padding:2px}
.gc-lvl-cell{aspect-ratio:1;border:1px solid var(--border,rgba(255,255,255,.14));
  background:rgba(255,255,255,.05);border-radius:11px;color:var(--text,#e9eef7);
  font:700 15px var(--ui,sans-serif);cursor:pointer;transition:.14s;display:flex;
  align-items:center;justify-content:center}
.gc-lvl-cell:hover:not(.locked){border-color:var(--accent,#22d9e6);background:rgba(34,217,230,.14);transform:translateY(-1px)}
.gc-lvl-cell.on{border-color:#f5c944;background:rgba(245,201,68,.16);color:#f5c944;
  box-shadow:0 0 0 1px rgba(245,201,68,.4)}
.gc-lvl-cell.locked{opacity:.32;cursor:default;font-weight:500}

/* ══ v9.10.679 — DIFFICULTY TRACKS IN THE LEVEL PICKER ══════════════════════ */
.gc-track-tabs{display:flex;gap:6px;justify-content:center;background:rgba(0,0,0,.3);
  border:1px solid var(--border,rgba(255,255,255,.12));border-radius:12px;padding:4px;margin:10px 0 8px}
.gc-track-tab{flex:1;border:none;background:transparent;color:var(--muted,#8b9bb0);padding:8px 10px;
  border-radius:9px;font:700 11px var(--ui,sans-serif);letter-spacing:.7px;text-transform:uppercase;cursor:pointer}
.gc-track-tab.on{background:var(--accent,#22d9e6);color:#04070d}
.gc-track-tab.done i{font-style:normal;color:#4ade80;margin-left:3px}
.gc-track-tab.on.done i{color:#04070d}
.gc-track-note{text-align:center;font:400 12px var(--ui,sans-serif);color:var(--muted,#8b9bb0);margin-bottom:4px}
.gc-track-note b{color:var(--text,#e9eef7)}


/* ══ v9.10.682 — FIVE EMITTED CLASSES THAT HAD NO RULE AT ALL ═══════════════
   games_mobile_test asserts "no emitted gc- class is unstyled" and named five:
   gc-diffbadge, gc-mc-n, gc-mc-nst, gc-mc-s, gc-mc-sst. All five are MODIFIERS
   on bases that ARE styled (.gc-mc-store has 4 rules, .gc-mc-pit has 10), so
   nothing rendered broken — but nothing distinguished the two sides either.

   That matters in Mancala specifically: the whole game is "my pits and my
   store versus yours", and with both stores painted identically you have to
   remember which end is yours. A board you have to remember the orientation of
   is a board that reads wrong. South is the human seat, so South gets the
   accent and North gets a cool neutral.

   Appended, not edited in place — this sheet is append-only. These are all
   single-class selectors (0,1,0), same as the base rules they refine, so they
   win on source order alone and no !important is needed. ══════════════════ */

/* SOUTH = the player. Accent ring + a warm inner light. */
.gc-mc-sst{
  border-color:var(--accent,#7c3aed);
  box-shadow:inset 0 0 18px -6px var(--accent,#7c3aed),0 2px 10px -6px rgba(0,0,0,.8);
}
.gc-mc-sst b{color:var(--accent,#7c3aed)}

/* NORTH = the opponent. Deliberately cooler and quieter, so the eye lands on
   your own side first. */
.gc-mc-nst{
  border-color:var(--border,rgba(255,255,255,.16));
  box-shadow:inset 0 0 14px -8px rgba(255,255,255,.35),0 2px 10px -6px rgba(0,0,0,.8);
}
.gc-mc-nst b{color:var(--muted,#8b9bb0)}

/* The pit rows get the same two-sided cue, kept much softer than the stores so
   the stores stay the loudest thing on the board. */
.gc-mc-s{border-color:color-mix(in srgb,var(--accent,#7c3aed) 42%,transparent)}
.gc-mc-n{border-color:var(--border,rgba(255,255,255,.14))}

/* The difficulty badge rides on .gc-chiprow, which is already laid out; this
   only stops it inheriting the full-width chip-row spacing in a HUD context. */
.gc-diffbadge{gap:6px;margin:0;flex:0 0 auto;justify-content:center}

/* ══ end v9.10.682 ═════════════════════════════════════════════════════════ */


/* ══ v9.10.683 — TWO TAIL CORRECTIONS FOUND BY THE PHONE SUITE ═════════════
   APPEND-ONLY, as always. Nothing above this line is edited.

   1. THE MODE PILLS WERE 6px UNDER THE TOUCH FLOOR, AT EVERY WIDTH.
      Phase A4 moved Mode out of .gc-frame-head and into the pause menu, and
      the panel rule that restyled the pills there —
      `.gc-gamemenu-panel .gc-modes .gc-mode{min-height:38px}` — is (0,3,0)
      and carries NO media query, so it beats the (0,1,0) phone rule
      `@media(max-width:700px){.gc-mode{min-height:44px}}` everywhere: 38px on
      a 375px phone and 38px at 1280 too. Every other control in the same panel
      is fine (gc-icon-btn 44, gc-sel 44, gc-menu-item 46, gc-menu-btn 48), so
      this was the one control the move took below the floor.

      It went unseen for fourteen versions because the phone suite's mount loop
      never OPENED the menu, so .gc-mode was never emitted and the assertion
      failed as "never emitted — the suite cannot vouch for it". A reachability
      failure hid a real one. Same specificity as the rule it corrects, later in
      source, so it wins on order and needs no !important.

   2. A DOC-COMMENT DRIFT, corrected here rather than in place because this
      sheet is append-only: the prose at ~line 9031 still quotes the <=900px
      stage padding as `.gc-stage{padding:10px 10px 14px}`. The live value is
      `padding:10px 10px 20px` — the bottom was retuned and the comment (and
      the suite's hardcoded 14) were left behind. The mechanism the comment
      describes is unchanged and still correct: the <=700px `padding-left:0`
      longhand beats the <=900px shorthand at equal specificity by source
      order, which is why the start card is 100% of 375px and not 96.8%.
      ═══════════════════════════════════════════════════════════════════════ */
.gc-gamemenu-panel .gc-modes .gc-mode{min-height:44px}

/* ══ end v9.10.683 ═════════════════════════════════════════════════════════ */


/* ══ v9.10.684 — THE `body.os-arcade-play` TRAP, DISARMED ══════════════════
   APPEND-ONLY, as always. Nothing above this line is edited.

   WHAT THIS IS. `body.os-arcade-play` is a complete, finished, NEVER-EXECUTED
   fullscreen play layer living at roughly oracle.css:9954-10051. Enumerated
   programmatically from this file (comments stripped, braces balanced):
   **15 rule blocks / 16 selectors**, plus 6 prose-only mentions in comments
   (~9666, 9674, 9684, 9971, 9991, 10478) — **22** textual occurrences in
   total. That is where the "21 rules" figure in the older note at ~10478
   came from, and it is wrong twice over: it counted occurrences rather than
   rules, and it counted 21 where there are 22. It is not 21 rules and it is
   not eleven; it is 15 blocks:

     9954  .oa-exit           9981  .oa-stage / .oa-play      10004 .gc-frame
     10010 .gc-frame::before  10011 .gc-frame-head            10016 .gc-frame-body
     10021 .gc-frame-foot     10025 .gc-arcade                10029 .gc-hud
     10033 .gc-canvas         10041 .gc-pad
     — and inside @media(max-width:900px) and (orientation:landscape)
       and (max-height:560px) opening at 10046 —
     10047 .oa-shell-top      10048 .gc-frame-head            10049 .gc-frame-foot
     10050 .gc-frame-body

   **ZERO JAVASCRIPT REFERENCES.** Re-confirmed at v9.10.684 two ways: a
   per-file grep over every top-level *.js, oracle-os/shell/*.js and
   oracle.html returned 0 hits, and a repo-wide search matched exactly two
   files — this stylesheet and GAME-CENTER-ARCADE-GOAL.md. Nothing has ever
   set the class, in any version.

   WHY IT STAYS UNSET — the decision, unchanged, and the reason restated here
   because the reason is the load-bearing part:

     body.os-arcade-play .gc-canvas{ width:100% !important; object-fit:contain }

   makes the ELEMENT BOX wider than the painted bitmap. Every pointer-mapped
   game converts a touch with (clientX - rect.left) * (W / rect.width) against
   that box, so a contained bitmap inside an over-wide box reads the wrong
   place by exactly the letterbox: Breakout's paddle, Floppy KAI's tap, Pong's
   bat and the whole Phase A5 gesture engine (dodge/breakout dragX, snake
   swipe, blocks tetris, 2048's Pointer Events) all mis-map. The v9.10.668
   approach — width:auto / height:auto under max-*:100%, so the box IS the
   bitmap — is the one the pointer maths needs, and it is what ships.
   Four more of the 15 blocks describe furniture that no longer exists at all
   (.gc-frame-head, .gc-frame-foot ×2, .gc-pad); .oa-exit adds a SECOND
   floating control top-right, competing with the one top-left control the
   Phase A4 brief allows. See the full audit at ~10478.

   WHY A COMMENT ALONE WAS NOT ENOUGH, AND WHAT THIS BLOCK ADDS.
   The audit at ~10478 has recorded this decision since v9.10.669 and it did
   not stop the class reading, to every fresh session, like a feature waiting
   for its `classList.add`. A comment cannot survive contact with one line of
   JavaScript. So the hazard is LATCHED instead: the rule below cancels the
   six geometry declarations of the .gc-canvas block whenever os-arcade-play
   is set WITHOUT a second, explicitly-named class. Enabling the fullscreen
   layer is now two deliberate acts, and the second one is called
   `os-arcade-play-unsafe-canvas` — you cannot turn the pointer-breaking
   behaviour on without typing the words that say so.

   This changes NOTHING that ships. The selector requires os-arcade-play,
   which nothing sets, so it matches no element in any state of the product
   today; it exists entirely for the accident that has not happened yet.
   Deleting the offending block outright is not available — this sheet is
   append-only, 798KB, and cutting ~100 lines out of the middle of it is the
   exact operation the project rule exists to prevent.

   Specificity, since that is what decides this: the latch is
   (0,3,1) — body + .os-arcade-play + :not(.os-arcade-play-unsafe-canvas)
   + .gc-canvas — against (0,2,1) for the block it cancels, and both sides
   carry !important, so weight decides and the latch wins. It stays BELOW the
   (0,5,1) `body.os-arcade-immersive .gc-frame.gc-immersive .gc-arcade >
   .gc-canvas` desktop rule that actually ships, so the live sizing is
   untouched either way.
   ═══════════════════════════════════════════════════════════════════════════ */
body.os-arcade-play:not(.os-arcade-play-unsafe-canvas) .gc-canvas{
  flex:0 0 auto !important;
  align-self:center !important;
  width:auto !important;
  max-width:100% !important;
  height:auto !important;
  object-fit:fill !important;
}

/* ══ end v9.10.684 ═════════════════════════════════════════════════════════ */


/* ══ v9.10.685 — A CORRECTION TO THE v9.10.684 NOTE ABOVE ════════════════
   APPEND-ONLY, as always. Nothing above this line is edited — including the
   block being corrected, which is why this is a note and not an edit.

   The v9.10.684 write-up (Codex masthead, history row and CHANGELOG) said the
   latched state of `.gc-canvas` was "identical to the shipped no-class state".
   IT IS NOT. Re-measured with the suites' own cascade engine, over the real
   play-screen chain (body.os-arcade-immersive > .gc-stage.gc-frame.gc-immersive
   > .gc-frame-body > .gc-arcade > canvas.gc-canvas):

     375x812   shipped        width:auto  max-width:100%  object-fit:—
                              align-self:—
               +os-arcade-play width:auto  max-width:100%  object-fit:fill
                              align-self:center
               +unsafe-canvas  width:100%  max-width:100%  object-fit:contain
                              align-self:stretch

     1280x900  shipped        width:auto  max-width:100%  object-fit:contain
                              align-self:—
               +os-arcade-play width:auto  max-width:100%  object-fit:fill
                              align-self:center
               +unsafe-canvas  width:auto  max-width:100%  object-fit:contain
                              align-self:stretch

   WHY THE LATCH IS STILL CORRECT, WHICH IS THE PART WORTH KEEPING. The hazard
   was never `object-fit`. It is `width:100%`, which makes the ELEMENT BOX wider
   than the painted bitmap, so `(clientX - rect.left) * (W / rect.width)` lands
   off by exactly the letterbox. The latch restores `width:auto` under
   `max-width:100%` — the box IS the bitmap — and once that holds there is
   nothing for `object-fit` or `align-self` to act on: `fill` and `contain`
   paint the same pixels when the box already matches the source aspect. The
   residual difference is inert. The fix was right; the sentence claiming
   identity was not, and overstating a measurement is how a checked fact turns
   back into a belief.

   It is no longer prose. games_mobile_test.js section (f) resolves all three
   states at both viewports and asserts them, including the negative that
   matters most — that no state reachable without the second, explicitly-named
   class puts `width:100%` on the canvas.
   ═════════════════════════════════════════════════════════════════════════════ */
/* ══ end v9.10.685 ══════════════════════════════════════════════════ */

/* ══ v9.10.688 — GAP 1: the shell is not a scroller ═════════════════════════
   THE 210px PAN, ROOT-CAUSED. BIGPICTURE-GAP.md §1b measured the damage
   exactly right (hero x 40 -> -170, bottom bar x 0 -> -210, pinned there) but
   named the wrong cause. It blamed the rail's 14 tiles overflowing through
   `.gcbp-rail { overflow-x: visible }`. They do not reach the shell: they are
   clipped one level lower by `.gcbp .gc-shelf-r`, which is `overflow-x:auto`
   (line ~7584 / ~10765) and is a scroll container in its own right.

   Surveyed at 1907x1075 — every descendant of `.oa-shell` with an unbroken
   chain of `overflow-x: visible` ancestors, measured in shell-content
   coordinates — there is exactly ONE box past `clientWidth`, and it is this
   file's own decoration:

     div#gcbp-wash   x -209.77   w 2326.54   right 2116.77   over +209.77

   `#gcbp-wash` is `position:absolute; inset:0` (so 1907 wide) carrying
   `transform: scale(1.22)` with `transform-origin: 50% 0` (line ~10680).
   1907 x 1.22 = 2326.54, which hangs 209.77px off EACH side. The left hang is
   negative scroll and Chromium discards it; the right hang is scrollable
   overflow, so scrollWidth = 1907 + 210 = 2117 — the measured number, to the
   pixel. Then `bpFocus`'s `scrollIntoView({inline:'center'})` finds the
   nearest horizontal scroll container, which `overflow:hidden` makes the SHELL
   itself, and drags the entire console sideways to the 210px clamp.

   A blurred, `pointer-events:none` background wash must never be able to move
   the screen. Two ways to make that true: stop the decoration overflowing, or
   stop the shell being a scroller. The first is not free — the 1.22 scale is
   what pushes `blur(46px)`'s transparent falloff off-screen, and shrinking the
   box to compensate re-crops a `background-size:cover` image, i.e. it changes
   how the wash LOOKS. `overflow: clip` costs nothing: it clips at the padding
   box byte-for-byte the way `hidden` does, and it does not create a scroll
   container at all, so there is no scrollLeft to set, no scroll port for
   `scrollIntoView` to choose, and no third mechanism to maintain.

   scrollIntoView IS NOT DISABLED. It still runs on every focus move; with the
   shell out of the running it resolves to the containers that should own the
   job — `.gcbp .gc-shelf-r` horizontally (the rail translates, exactly as it
   already does on mobile) and `.oa-shell-body` vertically. The focus model in
   §1a is untouched.

   Why mobile "did not have this bug": it has the same one, 41px wide.
   375 x 1.22 = 457.5, +41.25 per side; scrollWidth 416 vs clientWidth 375. The
   focused tile already sits near the middle at that width so `inline:'center'`
   only ever asked for ~1px of it. This rule removes both.

   NOT `!important`, and no new selector weight: the base is the bare
   `.oa-shell` at line ~9892 (0,1,0); this is (0,1,0) at the foot of the sheet
   and wins on source order, which is what append-only means here. The base
   rule is preserved verbatim — a browser too old for `overflow: clip` drops
   this declaration and lands back on `hidden`, i.e. today's behaviour.        */
.oa-shell{
  overflow:clip;
  overflow-clip-margin:0px;
}
/* ══ end v9.10.688 ══════════════════════════════════════════════════ */

/* ══ v9.10.689 — GAPS 2,3,4,6,7,8,12: THE ROW, THE PAGE, THE CAPSULE ═══════
   Fourth attempt, and the first one measured before and after against the same
   instrument. Every "ours" figure below is a live reading at 1907x1075 (the
   owner's own screenshot size); every "reference" figure is either that same
   reading taken off the Big Picture screenshot or a Valve-published capsule
   ratio. BIGPICTURE-GAP.md §6 is the ranked list this block answers.

   APPEND-ONLY, as this sheet requires: not one byte above this line changed
   (the base is byte-identical to HEAD, sha1 5efee05f…). Everything here either
   introduces a NEW selector or repeats an existing one at equal specificity and
   wins on SOURCE ORDER, which is the only override this file permits.

   THE ONE GAP THAT CANNOT BE CLOSED, STATED PLAINLY: Big Picture gets its
   character from real painted key art, one image per game. The CSP is
   default-src 'self' with no external hosts and this project ships zero image
   files, so every cover here is an inline SVG data-URI drawn in code and always
   will be. Layout, density, page shape, composition, mask, desaturation and
   motion are all reachable and are all done below. Painted artwork is not.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the two numbers the whole screen is built from ───────────────────────────
   ONE poster width, exported so the hero, the rail, the grid and the metadata
   band all derive from it instead of four independent clamps drifting apart.

     ours (before)   152.00 x 228.00 = 21.21vh, pitch 166, 6.01 across the rail
     reference       248    x 375    = 34.88vh, pitch 258, 4.10 across

   23.25vh x 1.5 = 34.875vh, i.e. 249.9 x 374.9 at 1075 — the reference height
   to two decimal places, at the reference aspect the covers already had.
   The `min(...,38vw)` arm exists for the phone only: 23.25vh on an 812px screen
   is a 189px poster, which leaves 1.8 of them across a 375px band. That is not
   a row, it is a slideshow. §3 of the gap doc already establishes that the
   reference row geometry is arithmetically impossible at 375px and has to be an
   explicit decision; this is the decision, and it is reported as a miss rather
   than rounded into a win. */
.gc-wrap.gcbp{
  --gcbp-tilew:clamp(120px,min(23.25vh,38vw),300px);
  --gcbp-tileh:calc(var(--gcbp-tilew) * 1.5);
  --gcbp-metah:52px;
}

/* ── GAP 3 — A CONSOLE SCREEN IS ONE SCREEN ──────────────────────────────────
   ours 3860 / 1010 = 3.82 screens (mobile 6.58). Reference 1.00.

   The console chrome was scrolling with the content: at `.oa-shell-body`
   scrollTop 2850 the hero, the tab strip and the focused metadata line were all
   off the top of the screen and what remained was a web page. Big Picture never
   does that — the frame is fixed and the ROWS move inside it.

   So the document stops being the scroller and the library becomes one:
   `.oa-shell-body` clips, `#view-games-body` is given the container's height
   back, and `.gc-wrap.gcbp` scrolls its own rows. scrollIntoView() is NOT
   disabled — with the shell body out of the running it resolves to the wrap
   vertically and to `.gcbp .gc-shelf-r` horizontally, which is exactly where
   the focus model wants it. The rows below the fold are still reachable, still
   by the same ↓ key; what changed is that the screen they scroll under stays
   still. TOTAL ROW CONTENT IS STILL TALLER THAN ONE SCREEN and that is the
   honest reading of this — the PAGE is one screen, the row stack is not.

   Specificity: `#view-games-body:has(> .gc-wrap.gcbp)` is (1,4,1) against the
   (1,2,1) of the v9.10.666 rule at ~10216, so it wins on weight as well as
   order, and both carry !important. Keyed to the Big Picture wrap, so a shell
   body holding a running game or anything else is untouched. */
body.os-arcade-immersive .oa-shell-body:has(> #view-games-body > .gc-wrap.gcbp){
  overflow:hidden;
}
body.os-arcade-immersive .oa-shell-body > #view-games-body:has(> .gc-wrap.gcbp){
  flex:1 1 auto !important;
  height:100% !important;
  min-height:0 !important;
  overflow:hidden !important;
  display:flex !important;
  flex-direction:column !important;
}
.gc-wrap.gcbp{
  flex:1 1 auto;min-height:0;
  overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  scrollbar-width:none;
}
.gc-wrap.gcbp::-webkit-scrollbar{width:0;height:0}

/* ── GAP 12 + GAP 5 — three sections behind three tabs ────────────────────── */
.gcbp .gcbp-sec{display:flex;flex-direction:column;gap:clamp(13px,1.8vw,22px);min-width:0}
.gcbp .gcbp-sec[hidden]{display:none}
/* The strip is the same centred pill row it already was; it is the CONTENTS
   that changed, from ten filters to three destinations. Bigger, because three
   pills carrying the whole navigation should not read as six filters did. */
.gcbp .gcbp-tabs .gc-chip{min-height:46px;padding:0 27px;font-size:13px;letter-spacing:.12em}
.gcbp .gcbp-tabs .gc-chip.gcbp-tab b{font-size:10.5px}
/* The category + mode filters, in their new home above the grid they filter.
   Quieter than the tab strip on purpose: a filter is not a destination. */
.gcbp .gcbp-filters{
  display:flex;justify-content:flex-start;align-items:center;gap:7px;flex-wrap:wrap;
  padding:2px 0 4px;
}
.gcbp .gcbp-filters .gc-chip{
  display:inline-flex;align-items:center;gap:8px;
  min-height:40px;padding:0 15px;border-radius:999px;
  background:rgba(255,255,255,.04);border:1px solid var(--border);color:var(--muted);
  font:700 11px var(--ui);letter-spacing:.08em;text-transform:uppercase;
}
.gcbp .gcbp-filters .gc-chip:hover{background:rgba(255,255,255,.08);color:var(--text)}
.gcbp .gcbp-filters .gc-chip b{
  font:700 10px var(--mono);letter-spacing:.04em;
  background:rgba(255,255,255,.11);color:var(--text);border-radius:999px;padding:2px 7px;
}
.gcbp .gcbp-filters .gc-chip.on{background:var(--accent);border-color:var(--accent);color:#04070d}
.gcbp .gcbp-filters .gc-chip.on b{background:rgba(4,7,13,.22);color:#04070d}
.gcbp .gcbp-filters .gc-chip-sp{
  flex:0 0 1px;min-width:1px;width:1px;height:24px;align-self:center;
  margin:0 7px;background:var(--border);
}

/* ── GAP 2 — THE ROW ─────────────────────────────────────────────────────── */
.gcbp .gc-shelf-c{width:var(--gcbp-tilew)}
.gcbp .gc-shelf-r{gap:10px}                    /* reference 10px; ours was 14 */
/* THE FOCUSED POSTER GREW WITH THE ROW, AND SO DID WHAT IT OVERHANGS. The
   focus treatment is `transform: scale(1.055)` on the art (§5 item 7, measured
   good, not touched), which at 152px hung 4.2px past the tile box and at 249.94
   hangs 6.9px — into a scroller whose padding-left was 0, so the FIRST tile in
   every row had the left edge of its artwork sliced the moment it took focus.
   9px of scroll padding, cancelled by an equal negative margin: the row's
   CONTENT still starts on the same pixel (the 40px gutter of §5 item 2 is
   untouched, and the rail's first tile stays at 863.8), it just has somewhere
   to grow into. scroll-padding-left follows it so scrollIntoView cannot tuck a
   focused tile back under that edge. */
.gcbp .gc-shelf-r{padding-left:9px;margin-left:-9px;scroll-padding-left:9px}
/* auto-fill at gap 10 gives 7 columns of 252.43 against a 249.94 poster — the
   grid and the rows are one size. At the 14px gap it was 6 columns of 292.83,
   i.e. the same library drawn at two different scales on two tabs. */
.gcbp .gc-grid{grid-template-columns:repeat(auto-fill,minmax(var(--gcbp-tilew),1fr));gap:10px}

/* ── GAP 4 — THE LANDSCAPE TILE IS A CAPSULE ─────────────────────────────────
     ours       803.88 x 306, art 368.86 x 304 = 1.213:1 filling 45.9% of it,
                104 characters of text printed on the tile
     reference  2.128:1, ZERO characters, art edge to edge

   Two panels became one picture. The width is derived from the poster height so
   the capsule is exactly 2.128:1 (374.9 x 2.128 = 797.8 wide at 1075), and the
   bottom margin — one metadata band plus the row's own bottom padding — lands
   its lower edge on the SAME line as the posters beside it, which is also what
   puts it in the same bpRows() bucket for arrow-key navigation.

   The 102 characters are not deleted. They are the focused item's line under
   the row (`heroSub` in oracle-games.js), shared with every cover, which is
   where the reference puts a tile's name and metadata. The two remaining
   actions are 44px badges drawn by ::before below — those glyphs are pseudo
   content, so the tile still measures 0 characters of text. */
.gcbp .gcbp-top{align-items:flex-end}
.gcbp .gcbp-top>.gc-hero{
  flex:0 0 auto;
  width:min(calc(var(--gcbp-tileh) * 2.128),46%);
  height:var(--gcbp-tileh);min-height:0;
  margin-bottom:calc(var(--gcbp-metah) + 14px);
  /* border -> outline, the same swap the posters use: a 1px border would make
     the art 2px narrower than the box and cost the "100% of the tile" outright */
  border:0;outline:1px solid rgba(255,255,255,.10);outline-offset:-1px;
  border-radius:10px;cursor:pointer;
  background-color:var(--gc-accent,var(--accent));
  transition:outline-color .17s ease,box-shadow .17s ease;
}
.gcbp .gc-hero-art{
  flex:1 1 auto;width:100%;height:100%;
  border-right:0;
  background-color:var(--gc-accent,var(--accent));
  background-position:50% 50%;
}
.gcbp .gc-hero::after{opacity:.12}
/* the hero is a focus target now, and it has no .gcbp-art to put the ring on */
.gcbp .gc-hero.gcbp-on{
  outline:2px solid #fff;outline-offset:2px;z-index:2;
  box-shadow:0 22px 46px -18px rgba(0,0,0,.98),0 0 30px -6px var(--gc-accent,var(--accent));
}
.gcbp .gc-hero:focus{outline:1px solid rgba(255,255,255,.10);outline-offset:-1px}
.gcbp .gc-hero:focus-visible{outline:2px solid #fff;outline-offset:2px}
/* THE TWO BADGES. v9.10.689 shipped these as `el('button','gcbp-hbtn…','')` on
   the stated assumption that CSS drew the glyph — and the CSS was never
   written, so what rendered was a 44x304 UA-default white slab in the middle of
   the hero with no label at all. This is that missing half. */
.gcbp .gcbp-hbtn{
  position:absolute;z-index:3;bottom:12px;
  width:44px;height:44px;padding:0;
  display:flex;align-items:center;justify-content:center;
  border:1px solid rgba(255,255,255,.30);border-radius:50%;
  background:rgba(4,7,13,.74);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  color:var(--text);font:700 18px var(--ui);line-height:1;
  cursor:pointer;opacity:.42;
  transition:opacity .15s ease,background .15s ease,border-color .15s ease,color .15s ease;
}
.gcbp .gcbp-hbtn::before{display:block}
.gcbp .gcbp-hbtn-how{right:12px}
.gcbp .gcbp-hbtn-how::before{content:"?"}
.gcbp .gcbp-hbtn-new{right:64px}
.gcbp .gcbp-hbtn-new::before{content:"↺"}
.gcbp .gc-hero:hover .gcbp-hbtn,
.gcbp .gc-hero.gcbp-on .gcbp-hbtn,
.gcbp .gcbp-hbtn:hover,
.gcbp .gcbp-hbtn:focus,
.gcbp .gcbp-hbtn:focus-visible{opacity:1}
.gcbp .gcbp-hbtn:hover{background:var(--accent);border-color:var(--accent);color:#04070d}
@media (hover:none),(pointer:coarse){.gcbp .gcbp-hbtn{opacity:.9}}

/* ── GAPS 8, 9, 15 — the focused title and its metadata, STACKED ─────────────
     ours       side by side, span 165.42px to the right, 10px lower
     reference  stacked, metadata ~27px below the title
   Title 21px -> clamp to 30px (gap 9), metadata 10.5px -> 12px (gap 15).
   The rail's line is given a definite height because the hero's bottom margin
   is measured against it; every other shelf keeps a min-height so a long blurb
   can still take a second line without being clipped. */
.gcbp .gcbp-meta{
  flex-direction:column;align-items:flex-start;flex-wrap:nowrap;gap:0;
  min-height:var(--gcbp-metah);
}
.gcbp .gcbp-meta b{font:800 clamp(19px,2.05vw,30px) var(--ui);line-height:.98;letter-spacing:.01em}
.gcbp .gcbp-meta span{font:600 12px var(--mono);letter-spacing:.14em;line-height:1.5;color:var(--muted)}
.gcbp .gcbp-rail .gcbp-meta{height:var(--gcbp-metah);overflow:hidden}

/* ── GAP 7 — the section heading ─────────────────────────────────────────────
     ours 13px, uppercase, ls 1.82px, opacity .7   reference ~28px, sentence case
   The 40px left gutter is NOT touched: it measured 2.098% against the
   reference's own 40px and is one of the nine things §5 says are already right. */
.gcbp .gc-title{
  font:700 28px var(--ui);letter-spacing:0;text-transform:none;
  opacity:1;color:var(--text);line-height:1.15;
}

/* ── GAP 6 — THE WASH ────────────────────────────────────────────────────────
     ours       blur(46px) saturate(1.3), linear 180deg mask, accent tint @ .22,
                animation: none
     reference  grayscale(1) contrast(1), radial 75% 83% at 50% 18%, no tint,
                25s slow zoom

   Four measured differences, four lines. We saturated where Steam desaturates;
   our mask faded downward only, so colour ran hard into the left and right
   edges where Steam's radial ellipse lets the whole perimeter go black; we
   added an accent tint Steam does not have; and it never moved.

   The zoom is bounded 1.22 -> 1.34 and the shell is `overflow:clip` (v9.10.688),
   so a wider decoration cannot become scrollable overflow and pan the screen —
   that was GAP 1 and it stays fixed. Reduced motion suppresses it in all three
   dialects this OS uses: the media query, the .gc-reduce-motion class the
   settings panel sets, and body.reduce-motion. */
@keyframes gcbpWashZoom{from{transform:scale(1.22)}to{transform:scale(1.34)}}
#gcbp-wash{
  filter:grayscale(1) contrast(1) blur(46px);
  opacity:.46;
  -webkit-mask-image:radial-gradient(75% 83% at 50% 18%,#000 0%,rgba(0,0,0,.72) 45%,transparent 100%);
  mask-image:radial-gradient(75% 83% at 50% 18%,#000 0%,rgba(0,0,0,.72) 45%,transparent 100%);
  animation:gcbpWashZoom 25s ease 0s infinite alternate;
}
#gcbp-wash::after{content:none}
@media (max-width:700px){#gcbp-wash{filter:grayscale(1) contrast(1) blur(30px);opacity:.4}}
@media (prefers-reduced-motion:reduce){#gcbp-wash{animation:none;transform:scale(1.22)}}
.gc-reduce-motion #gcbp-wash,
body.reduce-motion #gcbp-wash{animation:none;transform:scale(1.22)}

/* ── the phone ───────────────────────────────────────────────────────────────
   Written last so it beats the v9.10.670 phone block on source order at equal
   specificity, which is what that block itself relies on. The layout does not
   become a list: the posters get smaller and the capsule goes full width. */
@media (max-width:700px){
  .gc-wrap.gcbp{--gcbp-metah:44px}
  .gcbp .gc-shelf-c{width:var(--gcbp-tilew)}
  .gcbp .gc-grid{grid-template-columns:repeat(auto-fill,minmax(var(--gcbp-tilew),1fr));gap:10px}
  .gcbp .gcbp-meta{min-height:var(--gcbp-metah)}
  .gcbp .gcbp-meta b{font-size:19px}
  .gcbp .gcbp-meta span{font-size:11px;letter-spacing:.12em}
  .gcbp .gcbp-tabs{justify-content:center;flex-wrap:nowrap;overflow:visible;margin-right:0;padding-right:0}
  .gcbp .gcbp-tabs .gc-chip{flex:0 0 auto;min-height:44px;padding:0 16px;font-size:12px}
  .gcbp .gcbp-filters{
    flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    margin-right:calc(-1 * var(--gcbp-pad));padding-right:var(--gcbp-pad);
  }
  .gcbp .gcbp-filters::-webkit-scrollbar{display:none}
  .gcbp .gcbp-filters .gc-chip{flex:0 0 auto}
}
@media (max-width:900px){
  /* the capsule spans the column; the rail follows underneath it */
  .gcbp .gcbp-top{align-items:stretch}
  .gcbp .gcbp-top>.gc-hero{
    width:100%;height:auto;aspect-ratio:2.128;margin-bottom:0;
  }
  .gcbp .gc-hero-art{flex:1 1 auto;height:auto;border-bottom:0}
}
/* ══ end v9.10.689 ══════════════════════════════════════════════════ */

/* ══ v9.10.693 — PANDA COINS readout (oracle-coins.js) ═════════════════════
   Project tokens only: --accent/--star/--panel-2/--border/--text/--muted/--good
   /--bad/--ui/--mono. No image files, no font files, no external hosts — the
   coin is a CSS gradient disc, which is also why it costs nothing to draw one
   in a header that repaints on every keystroke. */
.pc-chip{position:relative;font-variant-numeric:tabular-nums}
.pc-chip .pc-val{font:700 12px var(--mono);color:var(--star);letter-spacing:.02em}
.pc-chip:hover{border-color:var(--star)}
.pc-chip.pc-stale{opacity:.55}
.pc-chip.pc-stale .pc-val{color:var(--muted)}
.pc-coin{
  width:13px;height:13px;border-radius:50%;flex:0 0 auto;display:inline-block;
  background:radial-gradient(circle at 34% 30%,#fde68a 0%,var(--star) 46%,#b7791f 100%);
  box-shadow:0 0 0 1px rgba(0,0,0,.35) inset,0 0 6px rgba(251,191,36,.35);
  position:relative;
}
.pc-coin::after{
  content:'';position:absolute;inset:3.5px;border-radius:50%;
  border:1.5px solid rgba(60,35,0,.55);
}
.pc-chip.pc-pop{animation:pcPop .42s cubic-bezier(.2,1.5,.4,1)}
@keyframes pcPop{0%{transform:scale(1)}35%{transform:scale(1.12)}100%{transform:scale(1)}}
.pc-delta{
  position:absolute;right:8px;top:-2px;font:700 11px var(--mono);pointer-events:none;
  opacity:0;animation:pcFly 1.5s ease-out forwards;
}
.pc-delta.pc-up{color:var(--good)}
.pc-delta.pc-down{color:var(--bad)}
@keyframes pcFly{0%{opacity:0;transform:translateY(4px)}18%{opacity:1}70%{opacity:1}100%{opacity:0;transform:translateY(-16px)}}
@media (prefers-reduced-motion:reduce){
  .pc-chip.pc-pop{animation:none}
  .pc-delta{animation:none;opacity:1}
}

/* ── the statement sheet ─────────────────────────────────────────────────── */
.pc-back{
  position:fixed;inset:0;z-index:9400;background:rgba(2,4,9,.72);
  display:flex;align-items:center;justify-content:center;padding:20px;
  backdrop-filter:blur(3px);
}
.pc-sheet{
  width:min(460px,100%);max-height:min(80vh,640px);display:flex;flex-direction:column;
  background:var(--panel-solid);border:1px solid var(--border);border-radius:14px;
  box-shadow:0 24px 60px rgba(0,0,0,.55);overflow:hidden;
}
.pc-sheet-h{display:flex;align-items:center;gap:9px;padding:14px 16px;border-bottom:1px solid var(--border)}
.pc-sheet-h b{font:600 14px var(--ui);color:var(--text);flex:1}
.pc-x{background:none;border:0;color:var(--muted);font-size:15px;cursor:pointer;padding:2px 6px;border-radius:6px}
.pc-x:hover{color:var(--text);background:rgba(255,255,255,.07)}
.pc-bal{display:flex;align-items:baseline;gap:8px;padding:16px 16px 4px}
.pc-bal-n{font:700 32px var(--mono);color:var(--star);letter-spacing:-.5px}
.pc-bal-s{font:500 11px var(--ui);color:var(--muted);text-transform:uppercase;letter-spacing:.14em}
.pc-note{padding:0 16px 12px;font:400 11.5px var(--ui);color:var(--muted)}
.pc-cap{padding:0 16px 14px}
.pc-cap-l{font:500 11px var(--ui);color:var(--muted);margin-bottom:6px}
.pc-cap-l b{color:var(--text)}
.pc-cap-bar{height:5px;border-radius:3px;background:rgba(255,255,255,.07);overflow:hidden}
.pc-cap-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--star),#f59e0b);border-radius:3px}
.pc-rows{overflow:auto;border-top:1px solid var(--border);padding:6px 8px 12px;flex:1;min-height:60px}
.pc-row{display:flex;align-items:center;gap:10px;padding:8px 8px;border-radius:8px}
.pc-row:hover{background:rgba(255,255,255,.04)}
.pc-row-m{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.pc-row-m b{font:500 12.5px var(--ui);color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pc-row-m span{font:400 10.5px var(--ui);color:var(--muted-2)}
.pc-row-a{font:700 13px var(--mono);flex:0 0 auto}
.pc-row-a.pc-up{color:var(--good)}
.pc-row-a.pc-down{color:var(--bad)}
.pc-dim{color:var(--muted);font:400 12px var(--ui);padding:10px 8px}
@media (max-width:560px){
  .pc-sheet{width:100%;max-height:88vh}
  .pc-bal-n{font-size:28px}
}
/* ══ end v9.10.693 ══════════════════════════════════════════════════ */

/* ══ PANDA COINS — earning, the daily wheel and quests (v9.10.694) ══════════
   Appended, never inserted. Every colour is a design token so the owner's theme
   drives all of it; the hex after each var() is only the pre-token first paint.
   No image files, no icon fonts, no external anything — the wheel is inline SVG
   and the pointer is a CSS triangle. ══════════════════════════════════════ */
:root{
  --pa-w1:rgba(255,255,255,.07);
  --pa-w2:rgba(255,255,255,.14);
  --pa-line:rgba(0,0,0,.35);
  --pa-rim:var(--accent,#22d9e6);
}

/* ── the header button ─────────────────────────────────────────────────── */
.pa-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;
  color:var(--text,#e9eef7)}
.pa-btn .pa-ico{display:inline-flex;line-height:0;transition:transform .5s cubic-bezier(.2,.9,.2,1)}
.pa-btn:hover .pa-ico{transform:rotate(90deg)}
.pa-btn.pa-ready{color:var(--accent,#22d9e6)}
.pa-btn.pa-ready::after{content:'';position:absolute;inset:-2px;border-radius:inherit;
  border:1px solid var(--accent,#22d9e6);opacity:.55;animation:pa-halo 2.2s ease-in-out infinite}
@keyframes pa-halo{0%,100%{opacity:.18;transform:scale(1)}50%{opacity:.6;transform:scale(1.06)}}
.pa-badge{position:absolute;top:-5px;right:-5px;min-width:15px;height:15px;padding:0 3px;
  border-radius:8px;background:var(--accent,#22d9e6);color:#04121a;font:700 10px/15px var(--ui,inherit);
  text-align:center;box-shadow:0 0 0 2px var(--panel,#12161d)}

/* ── the sheet + tabs ──────────────────────────────────────────────────── */
.pa-sheet{width:min(430px,96vw)}
.pa-tabs{display:flex;gap:6px;padding:0 14px 10px}
.pa-tab{flex:1;padding:7px 10px;border-radius:9px;cursor:pointer;
  border:1px solid var(--border,rgba(255,255,255,.10));background:transparent;
  color:var(--dim,#9aa6b8);font:600 12px/1 var(--ui,inherit)}
.pa-tab.on{color:var(--text,#e9eef7);border-color:var(--accent,#22d9e6);
  background:color-mix(in srgb,var(--accent,#22d9e6) 12%,transparent)}
.pa-pane{padding:0 14px 16px}

/* ── the wheel ─────────────────────────────────────────────────────────── */
.pa-wheel-wrap{position:relative;display:flex;justify-content:center;padding:6px 0 4px}
.pa-wheel-svg{max-width:100%;height:auto;filter:drop-shadow(0 6px 18px rgba(0,0,0,.45))}
.pa-wheel-rot{transform-origin:140px 140px}
.pa-wlabel{fill:var(--text,#e9eef7);font:700 12px/1 var(--ui,sans-serif);text-anchor:middle;
  dominant-baseline:middle;pointer-events:none}
.pa-wjack{fill:#1a1305}
.pa-hub{fill:var(--accent,#22d9e6);font:700 11px/1 var(--ui,sans-serif);text-anchor:middle;letter-spacing:.08em}
.pa-ptr{position:absolute;top:-2px;left:50%;transform:translateX(-50%);z-index:2;
  width:0;height:0;border-left:11px solid transparent;border-right:11px solid transparent;
  border-top:20px solid var(--accent,#22d9e6);filter:drop-shadow(0 2px 3px rgba(0,0,0,.6))}

.pa-result{min-height:24px;text-align:center;font:600 14px/24px var(--ui,inherit);
  color:var(--text,#e9eef7);margin:4px 0 8px}
.pa-win{color:var(--good,#35d07f)}
.pa-jack{color:var(--accent2,#ffcf5a);font-weight:800;letter-spacing:.06em}
.pa-spin-btn{width:100%;padding:12px;border-radius:12px;cursor:pointer;
  border:1px solid var(--border,rgba(255,255,255,.10));background:var(--panel2,rgba(255,255,255,.05));
  color:var(--dim,#9aa6b8);font:700 14px/1 var(--ui,inherit)}
.pa-spin-btn.pa-ready{color:#04121a;background:var(--accent,#22d9e6);border-color:transparent}
.pa-spin-btn:disabled{cursor:default;opacity:.75}
.pa-reset{text-align:center;font:500 11px/1.6 var(--ui,inherit);color:var(--dim,#9aa6b8);padding:8px 0 2px}

.pa-odds{margin-top:8px;border-top:1px solid var(--border,rgba(255,255,255,.10));padding-top:8px}
.pa-odds summary{cursor:pointer;font:600 11px/1.5 var(--ui,inherit);color:var(--dim,#9aa6b8)}
.pa-odds-list{display:flex;flex-direction:column;gap:3px;padding:8px 0 2px}
.pa-odd{display:grid;grid-template-columns:10px 1fr auto;gap:8px;align-items:center;
  font:500 11px/1.7 var(--ui,inherit);color:var(--text,#e9eef7)}
.pa-odd i{width:10px;height:10px;border-radius:3px;display:block}
.pa-odd em{color:var(--dim,#9aa6b8);font-style:normal}
.pa-odd b{color:var(--dim,#9aa6b8);font-weight:600;font-variant-numeric:tabular-nums}
.pa-fine{font:400 10.5px/1.6 var(--ui,inherit);color:var(--dim,#9aa6b8);margin:8px 0 0}

/* ── quests ────────────────────────────────────────────────────────────── */
.pa-q-top{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:2px 0 12px}
.pa-q-cell{background:var(--panel2,rgba(255,255,255,.05));border:1px solid var(--border,rgba(255,255,255,.10));
  border-radius:11px;padding:10px 8px;text-align:center}
.pa-q-cell b{display:block;font:700 19px/1.15 var(--ui,inherit);color:var(--text,#e9eef7);font-variant-numeric:tabular-nums}
.pa-q-cell span{display:block;font:500 10.5px/1.5 var(--ui,inherit);color:var(--dim,#9aa6b8)}
.pa-q-cell em{display:block;font:400 9.5px/1.5 var(--ui,inherit);color:var(--dim,#9aa6b8);opacity:.75;font-style:normal}

.pa-daily{background:var(--panel2,rgba(255,255,255,.05));border:1px solid var(--border,rgba(255,255,255,.10));
  border-radius:12px;padding:12px;margin-bottom:14px}
.pa-d-h{display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.pa-d-h b{font:700 12.5px/1.4 var(--ui,inherit);color:var(--text,#e9eef7)}
.pa-d-h span{font:600 11px/1.4 var(--ui,inherit);color:var(--accent,#22d9e6)}
.pa-d-d{font:500 12px/1.5 var(--ui,inherit);color:var(--text,#e9eef7);opacity:.9;padding:5px 0 8px}
.pa-d-bar{height:6px;border-radius:4px;background:rgba(255,255,255,.09);overflow:hidden}
.pa-d-bar i{display:block;height:100%;border-radius:4px;background:var(--accent,#22d9e6);transition:width .4s ease}
.pa-d-f{font:500 10.5px/1.6 var(--ui,inherit);color:var(--dim,#9aa6b8);padding-top:6px}

.pa-ms-h{font:700 11px/1 var(--ui,inherit);letter-spacing:.08em;text-transform:uppercase;
  color:var(--dim,#9aa6b8);padding:2px 0 8px}
.pa-ms{display:grid;grid-template-columns:1fr auto;grid-template-areas:'t r' 'b r';
  gap:2px 10px;align-items:center;padding:8px 0;border-bottom:1px solid var(--border,rgba(255,255,255,.07))}
.pa-ms-t{grid-area:t;min-width:0}
.pa-ms-t b{display:block;font:600 12px/1.4 var(--ui,inherit);color:var(--text,#e9eef7)}
.pa-ms-t span{display:block;font:400 10.5px/1.4 var(--ui,inherit);color:var(--dim,#9aa6b8)}
.pa-ms-b{grid-area:b;height:4px;border-radius:3px;background:rgba(255,255,255,.09);overflow:hidden}
.pa-ms-b i{display:block;height:100%;border-radius:3px;background:var(--dim,#9aa6b8);transition:width .4s ease}
.pa-ms-r{grid-area:r;text-align:right;font:600 11px/1.4 var(--ui,inherit);
  color:var(--dim,#9aa6b8);font-variant-numeric:tabular-nums}
.pa-ms-r em{display:block;font:500 10px/1.4 var(--ui,inherit);color:var(--accent,#22d9e6);font-style:normal}
.pa-ms.on .pa-ms-b i{background:var(--good,#35d07f)}
.pa-ms.on .pa-ms-r{color:var(--good,#35d07f)}
.pa-ms.on .pa-ms-t b{color:var(--good,#35d07f)}

/* ── the earn toast ────────────────────────────────────────────────────── */
.pa-toast{position:fixed;right:16px;bottom:16px;z-index:9600;min-width:190px;max-width:260px;
  background:var(--panel,#12161d);border:1px solid var(--border,rgba(255,255,255,.12));
  border-radius:13px;padding:10px 12px;box-shadow:0 10px 30px rgba(0,0,0,.5);
  animation:pa-in .32s cubic-bezier(.2,.9,.2,1)}
.pa-toast.pa-toast-warn{border-color:color-mix(in srgb,var(--warn,#e6a23c) 55%,transparent)}
.pa-toast.pa-out{animation:pa-fade .7s ease forwards}
@keyframes pa-in{from{opacity:0;transform:translateY(10px) scale(.97)}to{opacity:1;transform:none}}
@keyframes pa-fade{to{opacity:0;transform:translateY(-6px)}}
.pa-t-head{display:flex;align-items:center;gap:7px;font:700 15px/1.2 var(--ui,inherit);
  color:var(--good,#35d07f);padding-bottom:6px}
.pa-toast-warn .pa-t-head{color:var(--warn,#e6a23c)}
.pa-t-body{display:flex;flex-direction:column;gap:2px}
.pa-t-row{display:flex;justify-content:space-between;gap:10px;font:500 11px/1.5 var(--ui,inherit);
  color:var(--dim,#9aa6b8)}
.pa-t-row b{color:var(--text,#e9eef7);font-weight:600;font-variant-numeric:tabular-nums}
.pa-t-ms span{color:var(--accent2,#ffcf5a)}
.pa-t-foot{font:500 10px/1.5 var(--ui,inherit);color:var(--dim,#9aa6b8);padding-top:6px;
  border-top:1px solid var(--border,rgba(255,255,255,.08));margin-top:6px}

@media (max-width:560px){
  .pa-sheet{width:100%}
  .pa-wheel-svg{width:250px;height:250px}
  .pa-toast{left:12px;right:12px;bottom:12px;max-width:none}
  .pa-q-cell b{font-size:17px}
}
@media (prefers-reduced-motion:reduce){
  .pa-wheel-rot{transition-duration:.9s !important}
  .pa-btn.pa-ready::after{animation:none}
  .pa-toast{animation:none}
}
/* ══ end v9.10.694 ══════════════════════════════════════════════════════ */


/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.695 — THE SHOP AND THE CASINO

   Three blocks, and the first one is the important one.

   1. THE COSMETICS THE SHOP SELLS. Every rule here hangs off an application
      point that ALREADY WORKS: `body[data-avframe]` and `body[data-nametag]`
      have been set by applyAppearanceSettings since v9.10.545, and this version
      adds `body[data-arcadeskin]` beside them (one line, oracle-core.js:19503).
      Nothing is sold whose effect exists nowhere.

      Note that every selector is PAIRED WITH ITS PREVIEW CLASS — the `.psf-`,
      `.psn-` and `.psk-` swatches on the shop card are painted by the same
      declaration that will paint the real thing. A preview drawn separately is a
      preview that can drift, and a shop whose pictures lie is worse than one
      with no pictures.

      Shop values are all prefixed `pc-` so they cannot collide with the values
      the existing level-gated pickers offer. That is what lets the server-side
      ownership check refuse an unowned SHOP value while leaving every existing
      choice alone.

   2. THE SHOP SHEET (.ps-*).
   3. THE FOUR CASINO TABLES (.cs-*). All art is CSS: the CSP forbids image and
      audio files outright, so a deck of 52 card faces is 52 requests this page
      cannot make. Cards are drawn from two text nodes and a border.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── 1a. avatar frames (appearance.avatarFrame) ───────────────────────────── */
body[data-avframe="pc-bamboo"] .me-av, .psf-pc-bamboo {
  box-shadow:0 0 0 3px #6aa84f,0 0 0 5px rgba(106,168,79,.25)!important; }
body[data-avframe="pc-koi"] .me-av, .psf-pc-koi {
  box-shadow:0 0 0 3px #f08a3c,0 0 12px rgba(240,138,60,.4),0 0 0 6px rgba(255,255,255,.06)!important;
  animation:avframe-pulse 3.6s ease-in-out infinite; }
body[data-avframe="pc-jade"] .me-av, .psf-pc-jade {
  box-shadow:0 0 0 3px #35d6a4,0 0 16px rgba(53,214,164,.45),inset 0 0 10px rgba(53,214,164,.25)!important; }
body[data-avframe="pc-circuit"] .me-av, .psf-pc-circuit {
  box-shadow:0 0 0 2px #1b3a2f,0 0 0 4px #3ee08a,0 0 14px rgba(62,224,138,.35)!important;
  animation:avframe-pulse 1.1s steps(2,end) infinite; }
body[data-avframe="pc-frost"] .me-av, .psf-pc-frost {
  box-shadow:0 0 0 3px #a8e6ff,0 0 18px rgba(168,230,255,.55),0 0 34px rgba(120,190,255,.18)!important; }
/* Conic ring behind the avatar — a box-shadow cannot make a rotating gradient.
   Re-uses the avframe-spin keyframes the shipped frames already declare. */
body[data-avframe="pc-gold"] .me-av::before,
body[data-avframe="pc-eclipse"] .me-av::before {
  content:""; position:absolute; inset:-4px; border-radius:inherit; z-index:-1;
  animation:avframe-spin 8s linear infinite; }
body[data-avframe="pc-gold"] .me-av::before, .psf-pc-gold {
  background:conic-gradient(from 0deg,#7a5c14,#f2d16b,#fffbe6,#f2d16b,#a8791f,#7a5c14); }
body[data-avframe="pc-eclipse"] .me-av::before, .psf-pc-eclipse {
  background:conic-gradient(from 0deg,#000,#3a1f5c,#b28cff,#fff,#b28cff,#3a1f5c,#000);
  animation:avframe-spin 14s linear infinite; }
.psf-pc-gold, .psf-pc-eclipse { animation:avframe-spin 8s linear infinite; }

/* ── 1b. name effects (appearance.nameTagEffect) ──────────────────────────── */
body[data-nametag="pc-mint"] .me-name, .psn-pc-mint {
  color:#7ff0c2!important; text-shadow:0 0 8px rgba(127,240,194,.35)!important; }
body[data-nametag="pc-ember"] .me-name, .psn-pc-ember {
  background:linear-gradient(90deg,#f59e0b,#ef4444,#f59e0b)!important; background-size:220% 100%!important;
  -webkit-background-clip:text!important; background-clip:text!important; color:transparent!important;
  animation:pc-slide 4s linear infinite; }
body[data-nametag="pc-neon"] .me-name, .psn-pc-neon {
  background:linear-gradient(90deg,#22d9e6 0 50%,#ec4899 50% 100%)!important;
  -webkit-background-clip:text!important; background-clip:text!important; color:transparent!important;
  text-shadow:0 0 10px rgba(236,72,153,.25)!important; }
body[data-nametag="pc-holo"] .me-name, .psn-pc-holo {
  background:linear-gradient(100deg,#ff6ec7,#7af0ff,#c4ff6e,#ffd76e,#ff6ec7)!important; background-size:300% 100%!important;
  -webkit-background-clip:text!important; background-clip:text!important; color:transparent!important;
  animation:pc-slide 5.5s linear infinite; }
body[data-nametag="pc-gilded"] .me-name, .psn-pc-gilded {
  background:linear-gradient(180deg,#fff3c4,#e0b64a 55%,#8a6412)!important;
  -webkit-background-clip:text!important; background-clip:text!important; color:transparent!important;
  -webkit-text-stroke:.4px rgba(0,0,0,.55)!important; }
body[data-nametag="pc-void"] .me-name, .psn-pc-void {
  color:#c3a6ff!important;
  text-shadow:0 -1px 6px rgba(147,102,255,.75),0 -4px 14px rgba(90,40,180,.45),0 1px 0 rgba(0,0,0,.6)!important; }
@keyframes pc-slide { to { background-position:220% 0 } }

/* ── 1c. arcade skins (appearance.arcadeSkin) ─────────────────────────────────
   Scoped to the Game Center subtree. A skin is a repaint of the room you play
   in, NOT a global theme — the collectible themes already own that job, and two
   systems fighting over the same surfaces is how a UI stops being legible. */
body[data-arcadeskin] #view-games-body .gc-wrap { background:var(--pcsk-bg,transparent); }
body[data-arcadeskin] #view-games-body .gc-card,
body[data-arcadeskin] #view-games-body .gc-shelf-c,
body[data-arcadeskin] #view-games-body .gc-hero {
  background:var(--pcsk-card,rgba(255,255,255,.02))!important;
  border-color:var(--pcsk-line,rgba(255,255,255,.08))!important; }
body[data-arcadeskin] #view-games-body .gc-frame,
body[data-arcadeskin] #view-games-body .gc-stage { background:var(--pcsk-felt,transparent)!important; }
body[data-arcadeskin] #view-games-body .gc-h,
body[data-arcadeskin] #view-games-body .gc-shelf-h,
body[data-arcadeskin] #view-games-body .gc-card-n { color:var(--pcsk-ink,inherit); }
body[data-arcadeskin] #view-games-body .gc-btn-primary,
body[data-arcadeskin] #view-games-body .gc-hero-play {
  background:var(--pcsk-acc,var(--accent))!important; border-color:var(--pcsk-acc,var(--accent))!important; }

body[data-arcadeskin="midnight"], .psk-midnight {
  --pcsk-bg:linear-gradient(180deg,#050b1a,#0a1430); --pcsk-card:rgba(30,58,110,.22);
  --pcsk-line:rgba(96,140,220,.28); --pcsk-felt:#060d20; --pcsk-ink:#cfe0ff; --pcsk-acc:#4f7fe0; }
body[data-arcadeskin="sakura"], .psk-sakura {
  --pcsk-bg:linear-gradient(180deg,#2a1420,#3d1c2c); --pcsk-card:rgba(255,190,214,.10);
  --pcsk-line:rgba(255,175,205,.32); --pcsk-felt:#2a1420; --pcsk-ink:#ffd7e6; --pcsk-acc:#f27ba6; }
body[data-arcadeskin="crt"], .psk-crt {
  --pcsk-bg:repeating-linear-gradient(180deg,#00140a,#00140a 2px,#001a0d 2px,#001a0d 4px);
  --pcsk-card:rgba(0,255,120,.07); --pcsk-line:rgba(0,255,120,.35); --pcsk-felt:#00140a;
  --pcsk-ink:#7dffb0; --pcsk-acc:#00e070; }
body[data-arcadeskin="crt"] #view-games-body .gc-card-n,
.psk-crt { font-family:'JetBrains Mono',ui-monospace,monospace; }
body[data-arcadeskin="vapor"], .psk-vapor {
  --pcsk-bg:linear-gradient(180deg,#2b0a3d,#5a1470 55%,#c04a8a); --pcsk-card:rgba(255,120,220,.12);
  --pcsk-line:rgba(120,240,255,.4); --pcsk-felt:#20083a; --pcsk-ink:#ffe1ff; --pcsk-acc:#ff62c8; }
body[data-arcadeskin="grove"], .psk-grove {
  --pcsk-bg:linear-gradient(180deg,#07160e,#0d2718); --pcsk-card:rgba(80,200,130,.10);
  --pcsk-line:rgba(140,200,110,.35); --pcsk-felt:#061109; --pcsk-ink:#d6f5cf; --pcsk-acc:#5fbf5f; }
body[data-arcadeskin="obsidian"], .psk-obsidian {
  --pcsk-bg:linear-gradient(180deg,#000,#0b0b0d); --pcsk-card:rgba(255,255,255,.035);
  --pcsk-line:rgba(214,178,90,.45); --pcsk-felt:#000; --pcsk-ink:#f0e6cf; --pcsk-acc:#d6b25a; }

/* ══ 2. THE SHOP SHEET ═════════════════════════════════════════════════════ */
.ps-chip { display:inline-flex; align-items:center; gap:6px; padding:6px 11px; border-radius:999px;
  border:1px solid rgba(255,255,255,.14); background:rgba(255,255,255,.05); color:#e6edf7;
  font:600 12px Outfit,sans-serif; cursor:pointer; white-space:nowrap; }
.ps-chip:hover { background:rgba(255,255,255,.10); border-color:rgba(255,255,255,.26); }
.ps-chip-i { font-size:14px; line-height:1; }

.ps-sheet { position:fixed; inset:0; z-index:99000; opacity:0; transition:opacity .16s ease; }
.ps-sheet.on { opacity:1; }
.ps-scrim { position:absolute; inset:0; background:rgba(3,6,14,.72); backdrop-filter:blur(3px); }
.ps-panel { position:absolute; left:50%; top:50%; transform:translate(-50%,-48%) scale(.98);
  width:min(940px,94vw); max-height:88vh; display:flex; flex-direction:column;
  background:#0b1120; border:1px solid rgba(255,255,255,.12); border-radius:16px;
  box-shadow:0 30px 80px rgba(0,0,0,.6); overflow:hidden; transition:transform .18s ease; }
.ps-sheet.on .ps-panel { transform:translate(-50%,-50%) scale(1); }
.ps-bar { display:flex; align-items:center; justify-content:space-between; padding:12px 16px;
  border-bottom:1px solid rgba(255,255,255,.08); font:700 15px Outfit,sans-serif; color:#e9f0fb; }
.ps-x { background:none; border:0; color:#8fa0bb; font-size:22px; line-height:1; cursor:pointer; padding:0 4px; }
.ps-x:hover { color:#fff; }
.ps-body { overflow:auto; padding:14px 16px 22px; }

.ps-head { display:grid; grid-template-columns:repeat(4,1fr); gap:8px; margin-bottom:12px; }
.ps-h-cell { background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.07);
  border-radius:11px; padding:9px 10px; text-align:center; }
.ps-h-cell b { display:block; font:700 17px Outfit,sans-serif; color:#f4d97a; }
.ps-h-cell span { display:block; font-size:10.5px; color:#8fa0bb; margin-top:1px; }

.ps-tabs { display:flex; gap:6px; margin-bottom:10px; flex-wrap:wrap; }
.ps-tab { padding:6px 13px; border-radius:999px; border:1px solid rgba(255,255,255,.12);
  background:transparent; color:#b6c4da; font:600 12px Outfit,sans-serif; cursor:pointer; }
.ps-tab.on { background:rgba(244,217,122,.14); border-color:rgba(244,217,122,.5); color:#f4d97a; }

.ps-msg { min-height:16px; font-size:12px; color:#9fd6b4; margin:2px 0 8px; }
.ps-msg.bad { color:#fda4af; }

.ps-grp-h { font:700 13px Outfit,sans-serif; color:#e9f0fb; margin:16px 0 8px; }
.ps-grp-h span { display:block; font:400 11px Inter,sans-serif; color:#8092ad; margin-top:2px; }
.ps-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(268px,1fr)); gap:9px; }

.ps-card { display:flex; align-items:center; gap:10px; padding:10px;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.08); border-radius:12px; }
.ps-card.owned { border-color:rgba(90,200,140,.35); background:rgba(90,200,140,.06); }
.ps-card.locked { opacity:.62; }
.ps-common    { box-shadow:inset 3px 0 0 #7f8ea3; }
.ps-uncommon  { box-shadow:inset 3px 0 0 #55c07a; }
.ps-rare      { box-shadow:inset 3px 0 0 #4f9ce0; }
.ps-epic      { box-shadow:inset 3px 0 0 #a86ee0; }
.ps-legendary { box-shadow:inset 3px 0 0 #e0a63c; }
.ps-sw { width:46px; height:46px; flex:0 0 46px; display:flex; align-items:center; justify-content:center;
  border-radius:10px; background:rgba(255,255,255,.05); position:relative; overflow:visible; }
.ps-sw i { display:block; }
.ps-av { width:28px; height:28px; border-radius:50%; background:#26334a; }
.ps-nm { font:800 13px Outfit,sans-serif; color:#e6edf7; }
.ps-nm::after { content:"Name"; }
.ps-sk { width:34px; height:24px; border-radius:5px; background:var(--pcsk-bg,#26334a);
  border:1px solid var(--pcsk-line,rgba(255,255,255,.2)); }
.ps-ti::after  { content:"\1F3F7"; font-size:20px; }
.ps-crate::after { content:"\1F381"; font-size:22px; }
.ps-boost::after { content:"\26A1"; font-size:20px; }
.ps-c-b { flex:1 1 auto; min-width:0; }
.ps-c-n { font:700 13px Outfit,sans-serif; color:#eef4ff; display:flex; align-items:baseline; gap:6px; }
.ps-c-n em { font:600 9.5px Outfit,sans-serif; color:#8fa0bb; text-transform:uppercase; letter-spacing:.4px; font-style:normal; }
.ps-c-d { font-size:11px; color:#8fa0bb; margin-top:2px; line-height:1.35; }
.ps-c-lock { font-size:10.5px; color:#e0a63c; margin-top:3px; }
.ps-c-a { flex:0 0 auto; text-align:right; display:flex; flex-direction:column; align-items:flex-end; gap:5px; }
.ps-price { font:700 13px Outfit,sans-serif; color:#f4d97a; }
.ps-price.dim { color:#6e7d94; }
.ps-have { font:600 11px Outfit,sans-serif; color:#7fd6a2; }
.ps-btn { padding:5px 12px; border-radius:8px; border:1px solid rgba(255,255,255,.16);
  background:rgba(255,255,255,.05); color:#dbe6f5; font:600 11.5px Outfit,sans-serif; cursor:pointer; }
.ps-btn:hover:not(:disabled) { background:rgba(255,255,255,.11); }
.ps-btn:disabled { opacity:.45; cursor:not-allowed; }
.ps-btn.ps-primary { background:#f4d97a; border-color:#f4d97a; color:#1a1405; }
.ps-btn.ps-primary:hover:not(:disabled) { background:#ffe89a; }
.ps-btn.ps-on { background:rgba(90,200,140,.18); border-color:rgba(90,200,140,.55); color:#8fe4b4; }
.ps-empty { padding:24px; text-align:center; color:#7e8ea6; font-size:12.5px; }
.ps-fine { margin-top:16px; font-size:11px; color:#7382a0; line-height:1.5; }

.ps-gifts { margin-bottom:6px; }
.ps-gift-box { display:flex; align-items:center; gap:12px; padding:14px;
  background:linear-gradient(120deg,rgba(244,217,122,.10),rgba(168,110,224,.10));
  border:1px solid rgba(244,217,122,.28); border-radius:13px; }
.ps-gift-ic { font-size:32px; }
.ps-gift-t { flex:1 1 auto; }
.ps-gift-t b { display:block; font:700 14px Outfit,sans-serif; color:#f6e6b0; }
.ps-gift-t span { display:block; font-size:11px; color:#9aa8c2; margin-top:3px; line-height:1.4; }

.ps-reveal { text-align:center; padding:34px 20px; opacity:0; transform:scale(.94);
  transition:opacity .28s ease,transform .28s ease; }
.ps-reveal.open { opacity:1; transform:scale(1); }
.ps-r-crate { font-size:56px; }
.ps-r-name { font:800 20px Outfit,sans-serif; color:#f4d97a; margin-top:8px; }
.ps-r-rar { font:600 10.5px Outfit,sans-serif; text-transform:uppercase; letter-spacing:1.2px; color:#9aa8c2; margin-top:2px; }
.ps-r-desc { font-size:12px; color:#9fb0c9; margin:10px auto 0; max-width:420px; line-height:1.5; }
.ps-r-extra { font:600 12.5px Outfit,sans-serif; color:#8fe4b4; margin-top:12px; }
.ps-r-ok { margin-top:18px; }
.ps-r-legendary .ps-r-name { color:#ffd76e; text-shadow:0 0 22px rgba(255,215,110,.5); }
.ps-r-epic .ps-r-name { color:#c79cff; }
.ps-r-rare .ps-r-name { color:#8ec6ff; }

@media (max-width:560px) {
  .ps-head { grid-template-columns:repeat(2,1fr); }
  .ps-grid { grid-template-columns:1fr; }
  .ps-panel { width:100vw; height:100vh; max-height:100vh; border-radius:0; top:0; left:0; transform:none; }
  .ps-sheet.on .ps-panel { transform:none; }
}

/* ══ 3. THE CASINO ═════════════════════════════════════════════════════════ */
.cs-wrap { display:flex; flex-direction:column; gap:10px; height:100%; min-height:0;
  padding:10px; color:#e6edf7; font-family:Outfit,sans-serif; }

.cs-bar { display:flex; align-items:center; gap:12px; padding:8px 12px; border-radius:11px;
  background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.08); flex:0 0 auto; }
.cs-bal b, .cs-day b { font:700 16px Outfit,sans-serif; color:#f4d97a; }
.cs-day b.cs-up { color:#7fd6a2; }
.cs-day b.cs-down { color:#fda4af; }
.cs-bal span, .cs-day span { font-size:10px; color:#8fa0bb; margin-left:4px; }
.cs-lim { flex:1 1 auto; display:flex; flex-direction:column; gap:3px; min-width:70px; }
.cs-lim i { display:block; height:4px; border-radius:3px; background:#fda4af; width:0; transition:width .3s ease; }
.cs-lim i.cs-lim-win { background:#7fd6a2; }
.cs-fair-btn { padding:4px 10px; border-radius:7px; border:1px solid rgba(255,255,255,.16);
  background:transparent; color:#9fb0c9; font:600 11px Outfit,sans-serif; cursor:pointer; }
.cs-fair-btn:hover { color:#fff; border-color:rgba(255,255,255,.32); }

.cs-felt { flex:1 1 auto; min-height:0; overflow:auto; display:flex; flex-direction:column;
  align-items:center; justify-content:flex-start; gap:12px; padding:12px;
  border-radius:14px; border:1px solid rgba(255,255,255,.07);
  background:radial-gradient(ellipse at 50% 0%,rgba(40,110,80,.28),rgba(8,26,20,.85) 70%),#07130f; }
.cs-msg { flex:0 0 auto; min-height:18px; text-align:center; font-size:12.5px; color:#b8c8de; }
.cs-msg.cs-win { color:#8fe4b4; font-weight:700; }
.cs-msg.cs-lose { color:#fda4af; }
.cs-msg.cs-warn { color:#f4c95a; }
.cs-ctrl { flex:0 0 auto; }

.cs-fair { flex:0 0 auto; padding:10px 12px; border-radius:11px; font-size:11px; line-height:1.5;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.08); color:#93a4bd; }
.cs-fair-h { font:700 12px Outfit,sans-serif; color:#dbe6f5; margin-bottom:4px; }
.cs-fair p { margin:0 0 7px; }
.cs-fair-r { display:flex; gap:8px; align-items:baseline; margin-top:3px; }
.cs-fair-r span { flex:0 0 56px; color:#7382a0; }
.cs-fair-r code { flex:1 1 auto; font:400 10px 'JetBrains Mono',monospace; color:#8fc6d6;
  word-break:break-all; }
.cs-fair-n { margin-top:7px!important; color:#7382a0; }

.cs-deal-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; justify-content:center; }
.cs-lbl { font:600 11px Outfit,sans-serif; color:#8fa0bb; }
.cs-chips { display:flex; gap:5px; flex-wrap:wrap; }
.cs-chip { min-width:44px; padding:6px 9px; border-radius:999px; cursor:pointer;
  border:1px solid rgba(255,255,255,.16); background:rgba(255,255,255,.05);
  color:#dbe6f5; font:700 11.5px Outfit,sans-serif; }
.cs-chip.on { background:#f4d97a; border-color:#f4d97a; color:#1a1405; }
.cs-btn { padding:8px 18px; border-radius:9px; cursor:pointer; border:1px solid rgba(255,255,255,.18);
  background:rgba(255,255,255,.06); color:#e6edf7; font:700 13px Outfit,sans-serif; }
.cs-btn:hover:not(:disabled) { background:rgba(255,255,255,.13); }
.cs-btn:disabled { opacity:.4; cursor:not-allowed; }
.cs-btn.cs-primary { background:#3ec98a; border-color:#3ec98a; color:#04180f; }
.cs-btn.cs-primary:hover:not(:disabled) { background:#57e0a0; }
.cs-btn.cs-alt { background:transparent; color:#9fb0c9; }
.cs-acts { display:flex; gap:8px; flex-wrap:wrap; justify-content:center; }
.cs-hint { font-size:11px; color:#8fa0bb; text-align:center; margin-bottom:6px; }

/* cards — two text nodes and a border, because the CSP has no room for images */
.cs-card { position:relative; width:46px; height:66px; border-radius:6px; background:#f4f7fc;
  border:1px solid #9aa6b8; box-shadow:0 2px 6px rgba(0,0,0,.35); color:#16233a;
  font-family:Outfit,sans-serif; flex:0 0 auto; }
.cs-card.cs-red { color:#c22a3c; }
.cs-card .cs-r { position:absolute; top:3px; left:5px; font:700 13px Outfit,sans-serif; }
.cs-card .cs-s { position:absolute; bottom:2px; right:5px; font-size:15px; }
.cs-card .cs-r2 { position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font:700 15px Outfit,sans-serif; opacity:.16; }
.cs-card.cs-back { background:linear-gradient(135deg,#1c2f52,#0d1b33); border-color:#31456b;
  display:flex; align-items:center; justify-content:center; }
.cs-card.cs-back .cs-bk { font-size:22px; opacity:.75; }
.cs-hand { display:flex; gap:5px; flex-wrap:wrap; justify-content:center; min-height:66px; }

/* blackjack */
.cs-bj { display:flex; flex-direction:column; gap:16px; align-items:center; width:100%; }
.cs-side { text-align:center; }
.cs-side-h { font:600 11px Outfit,sans-serif; color:#9fb0c9; margin-bottom:5px; }
.cs-side-h em { font-style:normal; color:#f4d97a; font-weight:700; margin-left:5px; }
.cs-seats { display:flex; gap:12px; flex-wrap:wrap; justify-content:center; }
.cs-seat { padding:6px; border-radius:9px; border:1px solid transparent; }
.cs-seat.on { border-color:#3ec98a; background:rgba(62,201,138,.08); }
.cs-seat.cs-r-win, .cs-seat.cs-r-blackjack { border-color:rgba(127,214,162,.6); }
.cs-seat.cs-r-loss, .cs-seat.cs-r-bust { border-color:rgba(253,164,175,.45); opacity:.7; }
.cs-seat-f { display:flex; gap:8px; justify-content:center; align-items:baseline; margin-top:5px;
  font-size:11px; color:#9fb0c9; }
.cs-seat-f b { color:#f4d97a; }
.cs-seat-f i { font-style:normal; color:#8fe4b4; }

/* video poker */
.cs-paytable { width:min(420px,100%); border-radius:10px; overflow:hidden;
  border:1px solid rgba(255,255,255,.10); background:rgba(0,0,0,.25); }
.cs-pt-h { display:flex; justify-content:space-between; gap:8px; padding:6px 10px;
  background:rgba(255,255,255,.06); font:700 11.5px Outfit,sans-serif; color:#e6edf7; }
.cs-pt-h em { font:400 10.5px Inter,sans-serif; font-style:normal; color:#8fe4b4; }
.cs-pt-r { display:flex; justify-content:space-between; padding:3px 10px; font-size:11.5px; color:#a9b9d0; }
.cs-pt-r b { color:#f4d97a; }
.cs-pt-r.on { background:rgba(244,217,122,.16); color:#fff; }
.cs-fine { padding:7px 10px 9px; margin:0; font-size:10.5px; color:#7382a0; line-height:1.45; }
.cs-vp-hand { display:flex; gap:8px; justify-content:center; flex-wrap:wrap; }
.cs-vp-slot { position:relative; cursor:pointer; padding-top:14px; }
.cs-vp-slot .cs-hold { position:absolute; top:0; left:50%; transform:translateX(-50%);
  font:700 9px Outfit,sans-serif; letter-spacing:1px; color:#3ec98a; opacity:0; }
.cs-vp-slot.held .cs-hold { opacity:1; }
.cs-vp-slot.held .cs-card { outline:2px solid #3ec98a; outline-offset:2px; }

/* roulette */
.cs-wheel { position:relative; width:132px; height:132px; border-radius:50%; flex:0 0 auto;
  border:3px solid rgba(255,255,255,.18);
  background:conic-gradient(#1b2233 0 9deg,#8c2230 9deg 18deg); }
.cs-wheel.spinning { animation:avframe-spin 1.1s linear infinite; }
.cs-pocket { position:absolute; inset:22%; border-radius:50%; display:flex; align-items:center;
  justify-content:center; font:800 30px Outfit,sans-serif; background:#0a1220; color:#e6edf7; }
.cs-pocket.cs-p-red { background:#8c2230; }
.cs-pocket.cs-p-black { background:#12161f; }
.cs-pocket.cs-p-green { background:#1d6b46; }
.cs-ball { position:absolute; top:4px; left:50%; width:8px; height:8px; margin-left:-4px;
  border-radius:50%; background:#fff; box-shadow:0 0 6px rgba(255,255,255,.8); }
.cs-board { width:100%; max-width:620px; }
.cs-grid { display:grid; grid-template-columns:repeat(12,1fr) 42px; gap:2px; margin-top:2px; }
.cs-n { padding:6px 0; border-radius:4px; border:1px solid rgba(255,255,255,.14);
  font:700 11px Outfit,sans-serif; color:#fff; cursor:pointer; background:#1a1f2b; }
.cs-n.cs-rd { background:#8c2230; }
.cs-n.cs-bk { background:#12161f; }
.cs-n.cs-zero { width:100%; background:#1d6b46; margin-bottom:2px; padding:5px 0; }
.cs-n.hi { outline:2px solid #f4d97a; outline-offset:-2px; }
.cs-out { padding:6px 8px; border-radius:5px; cursor:pointer; background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.14); color:#dbe6f5; font:600 10.5px Outfit,sans-serif; }
.cs-out:hover { background:rgba(255,255,255,.12); }
.cs-o-red { background:rgba(140,34,48,.55); }
.cs-o-black { background:rgba(18,22,31,.85); }
.cs-outs { display:flex; gap:3px; flex-wrap:wrap; margin-top:5px; }
.cs-inside { display:flex; gap:3px; flex-wrap:wrap; align-items:center; margin-top:6px; }
.cs-modes { display:flex; gap:4px; }
.cs-mode { padding:5px 10px; border-radius:7px; cursor:pointer; background:transparent;
  border:1px solid rgba(255,255,255,.16); color:#9fb0c9; font:600 11px Outfit,sans-serif; }
.cs-mode.on { background:rgba(244,217,122,.16); border-color:#f4d97a; color:#f4d97a; }
.cs-slip { display:flex; gap:5px; flex-wrap:wrap; align-items:center; justify-content:center;
  min-height:26px; width:100%; max-width:620px; }
.cs-bet { padding:3px 8px; border-radius:999px; cursor:pointer; background:rgba(244,217,122,.14);
  border:1px solid rgba(244,217,122,.4); color:#f4d97a; font:600 10.5px Outfit,sans-serif; }
.cs-bet i { font-style:normal; margin-left:5px; opacity:.6; }
.cs-total { font:700 12px Outfit,sans-serif; color:#e6edf7; margin-left:6px; }
.cs-dim { font-size:11px; color:#7e8ea6; }

/* slots */
.cs-slot { position:relative; padding:14px 18px; border-radius:14px;
  background:linear-gradient(180deg,#1a1224,#0d0812); border:2px solid rgba(196,138,230,.35); }
.cs-slot.cs-jackpot { animation:avframe-pulse 0.5s ease-in-out 6; border-color:#f4d97a; }
.cs-reels { display:flex; gap:8px; }
.cs-reel { width:66px; height:80px; display:flex; align-items:center; justify-content:center;
  font-size:38px; border-radius:9px; background:#f4f7fc; border:1px solid #9aa6b8; }
.cs-reel.rolling { filter:blur(1.5px); opacity:.85; }
.cs-payline { height:2px; background:rgba(224,90,90,.6); margin-top:-42px; position:relative; z-index:1; }
.cs-sl-pt { margin-top:12px; }

@media (max-width:560px) {
  .cs-card { width:38px; height:55px; }
  .cs-card .cs-r { font-size:11px; }
  .cs-reel { width:52px; height:64px; font-size:30px; }
  .cs-grid { grid-template-columns:repeat(6,1fr); }
  .cs-grid .cs-col { grid-column:span 6; }
  .cs-wheel { width:104px; height:104px; }
  .cs-pocket { font-size:24px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   CHIP-8  (v9.10.696, oracle-chip8.js)                          APPEND-ONLY
   ───────────────────────────────────────────────────────────────────────────
   Every pixel here is generated: gradients, borders and one <canvas>. There is
   not an image file in the arcade and this does not introduce the first one —
   the ROM tiles are the programs themselves, booted and blitted.
   The screen is a 64x32 canvas scaled by CSS with `image-rendering: pixelated`,
   so a CHIP-8 pixel lands on an exact block of device pixels and the display
   stays crisp at any size. Smoothing it would be a lie about the hardware.
   ═══════════════════════════════════════════════════════════════════════════ */
.c8-wrap { display:flex; flex-direction:column; width:100%; flex:1; min-height:0; gap:10px; }

/* ── the library ──────────────────────────────────────────────────────────── */
.c8-lib { display:flex; flex-direction:column; gap:14px; width:100%; flex:1; min-height:0; overflow-y:auto; padding:2px; }
.c8-libhead { text-align:center; padding:6px 8px 0; }
.c8-libt { font:800 22px/1.1 var(--display,var(--ui,sans-serif)); letter-spacing:2px; color:#ffb030;
  text-shadow:0 0 18px rgba(255,176,48,.35); }
.c8-libs { margin-top:6px; font:400 12.5px/1.5 var(--ui,sans-serif); color:var(--muted,rgba(255,255,255,.6));
  max-width:60ch; margin-left:auto; margin-right:auto; }

.c8-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(230px,1fr)); gap:12px; }
.c8-card { display:flex; flex-direction:column; gap:0; padding:0; overflow:hidden; text-align:left;
  background:var(--card,rgba(255,255,255,.04)); border:1px solid var(--line,rgba(255,255,255,.12));
  border-radius:14px; cursor:pointer; color:inherit; font:inherit;
  transition:transform .12s ease, border-color .12s ease, box-shadow .12s ease; }
.c8-card:hover { transform:translateY(-2px); border-color:rgba(255,176,48,.55);
  box-shadow:0 10px 26px rgba(0,0,0,.35), 0 0 0 1px rgba(255,176,48,.18) inset; }
.c8-card:focus-visible { outline:2px solid #ffb030; outline-offset:2px; }
.c8-cardscr { position:relative; background:#120c04; border-bottom:1px solid var(--line,rgba(255,255,255,.1)); }
.c8-cardscr::after { content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(180deg,rgba(255,255,255,.07),transparent 40%),
             radial-gradient(120% 80% at 50% 120%,rgba(0,0,0,.5),transparent 60%); }
.c8-cardcv { display:block; width:100%; aspect-ratio:2/1; image-rendering:pixelated; image-rendering:crisp-edges; }
.c8-cardmeta { padding:10px 12px 12px; display:flex; flex-direction:column; gap:5px; }
.c8-cardt { font:700 14px var(--ui,sans-serif); color:var(--fg,#fff); }
.c8-cardb { font:400 12px/1.45 var(--ui,sans-serif); color:var(--muted,rgba(255,255,255,.6)); }
.c8-cardtags { display:flex; flex-wrap:wrap; gap:6px; margin-top:2px; }
.c8-tag { font:600 9.5px var(--mono,monospace); letter-spacing:.6px; text-transform:uppercase;
  padding:3px 7px; border-radius:999px; background:rgba(255,176,48,.12); color:#ffc36a;
  border:1px solid rgba(255,176,48,.22); }
.c8-tag-demo { background:rgba(255,255,255,.08); color:var(--muted,rgba(255,255,255,.65));
  border-color:rgba(255,255,255,.16); }

.c8-own { border:1px dashed var(--line,rgba(255,255,255,.18)); border-radius:14px; padding:14px;
  display:flex; flex-direction:column; gap:8px; align-items:flex-start; }
.c8-ownt { font:700 13px var(--ui,sans-serif); color:var(--fg,#fff); }
.c8-ownb { font:400 12px/1.5 var(--ui,sans-serif); color:var(--muted,rgba(255,255,255,.6)); max-width:66ch; }
.c8-ownb code { font:600 11px var(--mono,monospace); padding:1px 5px; border-radius:5px;
  background:rgba(255,255,255,.08); }
.c8-ownbtn { font:600 12px var(--ui,sans-serif); padding:8px 14px; border-radius:9px; cursor:pointer;
  background:rgba(255,176,48,.14); color:#ffc36a; border:1px solid rgba(255,176,48,.3); }
.c8-ownbtn:hover { background:rgba(255,176,48,.22); }
.c8-file { display:none; }
.c8-note { font:500 12px var(--ui,sans-serif); color:#ffb4a0; background:rgba(255,90,60,.1);
  border:1px solid rgba(255,90,60,.28); border-radius:9px; padding:8px 11px; }

/* ── the machine ──────────────────────────────────────────────────────────── */
.c8-box { display:flex; flex-direction:column; width:100%; flex:1; min-height:0; gap:9px; }
.c8-head { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.c8-title { font:700 14px var(--ui,sans-serif); color:var(--fg,#fff); flex:1; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.c8-readout { font:700 13px var(--mono,monospace); letter-spacing:1px; color:#ffb030;
  background:rgba(255,176,48,.1); border:1px solid rgba(255,176,48,.22);
  border-radius:999px; padding:4px 11px; white-space:nowrap; }
.c8-btn { font:600 11.5px var(--ui,sans-serif); padding:7px 12px; border-radius:9px; cursor:pointer;
  background:var(--card,rgba(255,255,255,.06)); color:var(--fg,#fff);
  border:1px solid var(--line,rgba(255,255,255,.14)); white-space:nowrap; }
.c8-btn:hover { background:rgba(255,255,255,.12); }
.c8-btn:focus-visible { outline:2px solid #ffb030; outline-offset:2px; }
.c8-btn-p { background:rgba(255,176,48,.18); color:#ffc36a; border-color:rgba(255,176,48,.35); }

/* THE TUBE. A 2:1 box that never grows past the height available, so the keypad
   below it is always reachable without scrolling — on a phone that is the whole
   difference between a playable emulator and a demo of one. */
.c8-stage { position:relative; width:100%; display:flex; align-items:center; justify-content:center;
  background:#0a0803; border:1px solid var(--line,rgba(255,255,255,.14)); border-radius:12px;
  overflow:hidden; flex:0 1 auto; min-height:0; }
.c8-screen { display:block; width:100%; height:auto; max-height:100%; aspect-ratio:2/1;
  image-rendering:pixelated; image-rendering:crisp-edges; }
/* Bloom and a scanline wash, both painted by CSS over the canvas rather than
   into it: the framebuffer stays exactly what the ROM drew, which is what makes
   the pixel readout trustworthy. */
.c8-glow { position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(72% 60% at 50% 45%,rgba(255,176,48,.09),transparent 72%),
             radial-gradient(130% 100% at 50% 110%,rgba(0,0,0,.55),transparent 60%);
  mix-blend-mode:screen; }
.c8-glow::after { content:""; position:absolute; inset:0;
  background:repeating-linear-gradient(180deg,rgba(0,0,0,.16) 0 1px,transparent 1px 3px); opacity:.5; }

.c8-over { position:absolute; inset:0; display:none; align-items:center; justify-content:center;
  background:rgba(6,5,2,.82); backdrop-filter:blur(2px); }
.c8-over.on { display:flex; }
.c8-overcard { display:flex; flex-direction:column; align-items:center; gap:8px; padding:16px 22px; text-align:center; }
.c8-overt { font:700 15px var(--ui,sans-serif); color:var(--fg,#fff); }
.c8-overs { font:800 34px/1 var(--mono,monospace); color:#ffb030; text-shadow:0 0 22px rgba(255,176,48,.45); }
.c8-overb { font:500 11.5px var(--mono,monospace); color:#ffb4a0; }

.c8-bar { display:flex; gap:7px; flex-wrap:wrap; justify-content:center; }

/* ── the hex keypad ───────────────────────────────────────────────────────
   Sixteen keys in the COSMAC VIP's own 4x4 arrangement, which is why 2/4/6/8
   read as a d-pad. `touch-action:none` is load-bearing: without it a fast tap
   is swallowed by the browser's scroll/zoom gesture recogniser and the game
   simply does not respond, which reads as a broken emulator rather than a
   broken gesture. `user-select:none` stops a held key selecting its own label. */
.c8-pad { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; width:100%;
  max-width:340px; margin:0 auto; touch-action:none; user-select:none; -webkit-user-select:none; }
.c8-key { position:relative; aspect-ratio:1/1; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:1px; cursor:pointer;
  background:linear-gradient(180deg,rgba(255,255,255,.1),rgba(255,255,255,.03));
  border:1px solid var(--line,rgba(255,255,255,.16)); border-radius:10px; color:var(--fg,#fff);
  font:inherit; padding:0; -webkit-tap-highlight-color:transparent;
  transition:transform .06s ease, background .1s ease, box-shadow .1s ease; }
.c8-key .c8-kh { font:800 17px/1 var(--mono,monospace); letter-spacing:1px; }
.c8-key .c8-kl { font:600 8px var(--ui,sans-serif); letter-spacing:.5px; text-transform:uppercase; color:#ffc36a; }
.c8-key .c8-kb { font:600 8px var(--mono,monospace); color:var(--muted,rgba(255,255,255,.38)); }
/* The keys this program never reads stay VISIBLE but recede — hiding them would
   stop the pad looking like the machine it is, and treating all sixteen alike
   makes it unusable with a thumb. */
.c8-key-dim { opacity:.34; }
.c8-key:not(.c8-key-dim) { border-color:rgba(255,176,48,.4);
  background:linear-gradient(180deg,rgba(255,176,48,.16),rgba(255,176,48,.05)); }
.c8-key.on { transform:translateY(2px) scale(.97); background:rgba(255,176,48,.42); color:#1a1000;
  box-shadow:0 0 16px rgba(255,176,48,.5) inset; opacity:1; }
.c8-key.on .c8-kl, .c8-key.on .c8-kb { color:rgba(26,16,0,.7); }
.c8-key:focus-visible { outline:2px solid #ffb030; outline-offset:2px; }

.c8-hint { text-align:center; font:400 10.5px var(--ui,sans-serif); color:var(--muted,rgba(255,255,255,.45)); }
.c8-hint b { font:600 10.5px var(--mono,monospace); color:var(--muted,rgba(255,255,255,.66)); }

/* ── the how-to diagram ───────────────────────────────────────────────────── */
.c8-diag { display:flex; flex-direction:column; align-items:center; gap:8px; padding:6px 0; }
.c8-diaggrid { display:grid; grid-template-columns:repeat(4,44px); gap:5px; }
.c8-diagk { aspect-ratio:1/1; display:flex; flex-direction:column; align-items:center; justify-content:center;
  border:1px solid rgba(255,176,48,.3); border-radius:8px; background:rgba(255,176,48,.07); }
.c8-diagk b { font:800 14px/1 var(--mono,monospace); color:#ffb030; }
.c8-diagk i { font:600 8.5px var(--mono,monospace); font-style:normal; color:var(--muted,rgba(255,255,255,.5)); }
.c8-diagcap { font:400 11px var(--ui,sans-serif); color:var(--muted,rgba(255,255,255,.55)); text-align:center; }

/* The pad gets bigger on a phone, not smaller: it is the only control there is.
   The tube is capped so the pad is always on screen beneath it. */
@media (max-width:560px) {
  .c8-grid { grid-template-columns:1fr; }
  .c8-libt { font-size:19px; }
  .c8-stage { max-height:38vh; }
  .c8-pad { max-width:100%; gap:8px; }
  .c8-key .c8-kh { font-size:20px; }
  .c8-key .c8-kl, .c8-key .c8-kb { font-size:9px; }
  .c8-hint { display:none; }
  .c8-readout { font-size:12px; padding:3px 9px; }
  .c8-diaggrid { grid-template-columns:repeat(4,38px); }
}
/* Reduced motion: the hover lift is the only transform that is not gameplay. */
@media (prefers-reduced-motion:reduce) {
  .c8-card, .c8-key { transition:none; }
  .c8-card:hover { transform:none; }
}
.gc-reduce-motion .c8-card, .gc-reduce-motion .c8-key { transition:none; }
.gc-reduce-motion .c8-card:hover { transform:none; }

/* ═══════════════════════════════════════════════════════════════════════════
   v9.10.697 — TOUCH TARGETS IN THE COIN, SHOP, WHEEL AND CASINO SHEETS

   The Game Center owned ZERO sub-44px controls before the coin layers landed;
   those four sheets added forty-odd. Measured at 375x812 in real Chromium
   against the real payloads: .ps-x 21x22, .pc-x 24x24, .ps-btn 48x24 with 29
   of them stacked down the shop list, .ps-tab 28 tall, .pa-tab 28 tall, and
   .pa-spin-btn — the primary SPIN control — 40 tall. The sharpest edge was a
   21x22 dismiss sitting directly above a column of 24px SPEND buttons.

   Scoped to coarse pointers and narrow viewports ON PURPOSE. The defect was
   measured on a phone, and inflating every button to thumb size on a 27"
   monitor would just be a different regression. A mouse can hit 24px; a thumb
   cannot, and the thumb is the one being asked to spend coins.

   Appended at the tail. Nothing above this line is modified.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (pointer:coarse), (max-width:720px) {

  /* Dismiss buttons. These carry a single glyph, so the box grows around the
     glyph rather than the glyph growing - the icon stays the size it was. */
  .pc-x, .ps-x {
    min-width:44px; min-height:44px;
    display:inline-flex; align-items:center; justify-content:center;
  }

  /* Anything that spends, equips or switches a view. */
  .ps-btn, .ps-tab, .pa-tab {
    min-height:44px;
    display:inline-flex; align-items:center; justify-content:center;
  }

  /* The shop's Buy button sits at the end of a row; keep it from being the
     narrow half of a 44px-tall row. */
  .ps-btn { min-width:72px; }

  /* The primary action on the wheel gets more than the minimum, because it is
     the one control on that sheet a player actually aims at. */
  .pa-spin-btn { min-height:52px; }

  /* The casino's chip rail and action buttons are hit under time pressure with
     a stake already on the table, which is the worst moment to miss. */
  .cs-chip, .cs-act, .cs-btn, .cs-hold {
    min-height:44px;
    display:inline-flex; align-items:center; justify-content:center;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   v9.10.698 — THE CASINO IS ITS OWN ROOM
   ═══════════════════════════════════════════════════════════════════════════
   The owner: "the casino part isnt or should be a part of the normal games it
   should be in its own section". Everything below draws the two halves of that
   — the DOOR at the top of Home, and the ROOM you walk into — plus the one
   rule without which the JS cannot hide the hub's chrome.

   Deliberately a different palette from the rest of the arcade: felt green and
   gold instead of the hub's accent, so a player can tell at a glance that the
   screen changed rooms rather than tabs. Appended at the tail per the
   append-only rule; nothing above this line is touched.                     */

/* ── THE ONE LOAD-BEARING RULE ────────────────────────────────────────────
   showSection() sets `hidden` on the header, the hero row and the tab strip
   when the casino opens. That alone does NOTHING: `.gc-head{display:flex}`
   (line ~6817) and `.gcbp .gcbp-top{display:flex}` (~10711) are author rules
   and they beat the UA sheet's `[hidden]{display:none}`. These three
   selectors carry an extra attribute of specificity so the attribute wins. */
.gcbp .gc-head[hidden],
.gcbp .gcbp-top[hidden],
.gcbp .gcbp-tabs[hidden]{display:none}

/* ── THE DOOR ─────────────────────────────────────────────────────────────
   First thing in the Home section, under the tab strip. One wide plate: what
   it is on the left, the three numbers that decide whether you want to go in
   on the right. */
.gc-casdoor{
  position:relative; display:flex; align-items:center; gap:clamp(12px,2vw,26px);
  flex-wrap:wrap; padding:clamp(13px,1.7vw,20px) clamp(15px,2vw,24px);
  border-radius:16px; cursor:pointer; min-height:76px;
  border:1px solid rgba(230,193,90,.34);
  background:
    radial-gradient(120% 180% at 8% 0%, rgba(230,193,90,.16), transparent 62%),
    linear-gradient(135deg, #0d2a1e 0%, #081a13 52%, #0a1410 100%);
  box-shadow:0 10px 30px rgba(0,0,0,.34), inset 0 1px 0 rgba(255,255,255,.06);
  transition:transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.gc-casdoor::after{
  /* felt weave, so the plate does not read as another dark card */
  content:''; position:absolute; inset:0; border-radius:16px; pointer-events:none;
  background:repeating-linear-gradient(45deg, rgba(255,255,255,.026) 0 2px, transparent 2px 6px);
}
.gc-casdoor:hover, .gc-casdoor.gcbp-on{
  border-color:rgba(230,193,90,.72);
  box-shadow:0 14px 40px rgba(0,0,0,.46), 0 0 0 2px rgba(230,193,90,.4), inset 0 1px 0 rgba(255,255,255,.08);
  transform:translateY(-2px);
}
.gc-casdoor:focus-visible{outline:3px solid #e6c15a; outline-offset:3px}
.gc-casdoor-m{display:flex; align-items:center; gap:12px; min-width:0; flex:1 1 260px}
.gc-casdoor-i{font-size:30px; line-height:1; filter:drop-shadow(0 2px 6px rgba(0,0,0,.5))}
.gc-casdoor-t{min-width:0}
.gc-casdoor-t b{
  display:block; font-size:clamp(17px,2vw,23px); font-weight:800; letter-spacing:.02em;
  color:#f4e3ae; text-shadow:0 1px 0 rgba(0,0,0,.5);
}
.gc-casdoor-t i{
  display:block; font-style:normal; font-size:12px; margin-top:3px;
  color:rgba(244,227,174,.68); line-height:1.35;
}
.gc-casdoor-n{display:flex; gap:clamp(10px,1.6vw,22px); flex-wrap:wrap}
.gc-casdoor-f{display:flex; flex-direction:column; gap:2px; min-width:74px}
.gc-casdoor-f b{
  font-size:clamp(14px,1.5vw,18px); font-weight:800; color:#e6c15a;
  font-variant-numeric:tabular-nums; letter-spacing:.01em;
}
.gc-casdoor-f i{font-style:normal; font-size:10px; letter-spacing:.09em; text-transform:uppercase; color:rgba(244,227,174,.5)}
.gc-casdoor-go{
  display:inline-flex; align-items:center; gap:8px; margin-left:auto;
  padding:0 18px; min-height:44px; border-radius:999px;
  background:linear-gradient(180deg,#e6c15a,#c79f36); color:#0a1410;
  font-weight:800; font-size:13px; letter-spacing:.06em; text-transform:uppercase;
  white-space:nowrap;
}
.gc-casdoor-go em{font-style:normal; font-size:15px}
/* Closed for the day: still enterable (the room explains why), but it stops
   advertising itself as an invitation. */
.gc-casdoor-shut{border-color:rgba(224,90,90,.5)}
.gc-casdoor-shut .gc-cas-loss{color:#e8867f}

/* ── THE SEARCH BRIDGE ────────────────────────────────────────────────────
   "coins" used to return the four tables and nothing else. Now it returns an
   empty grid, so this says where they went. */
.gc-cas-hint{
  display:flex; align-items:center; gap:13px; width:100%; text-align:left;
  padding:12px 16px; min-height:56px; border-radius:13px; cursor:pointer;
  border:1px dashed rgba(230,193,90,.42);
  background:linear-gradient(135deg, rgba(13,42,30,.85), rgba(10,20,16,.7));
  color:#f4e3ae; font:inherit;
}
.gc-cas-hint:hover{border-style:solid; border-color:rgba(230,193,90,.8)}
.gc-cas-hint:focus-visible{outline:3px solid #e6c15a; outline-offset:2px}
.gc-cas-hint-i{font-size:22px; line-height:1}
.gc-cas-hint-t{min-width:0}
.gc-cas-hint-t b{display:block; font-size:13.5px; font-weight:700}
.gc-cas-hint-t i{display:block; font-style:normal; font-size:11.5px; margin-top:2px; color:rgba(244,227,174,.6)}
.gc-cas-hint-go{
  margin-left:auto; white-space:nowrap; font-size:12px; font-weight:800;
  letter-spacing:.05em; text-transform:uppercase; color:#e6c15a;
}
.gc-cas-hint[hidden]{display:none}

/* ── THE ROOM ─────────────────────────────────────────────────────────────
   Its own top bar (the way out, the name, your balance), then the house rules,
   then the tables. The numbers come first on purpose: the owner asked that the
   published edge and the daily loss limit be legible BEFORE a player sits
   down, and everything here is read from /api/casino rather than restated. */
.gc-cas{
  display:flex; flex-direction:column; gap:clamp(13px,1.7vw,20px);
  padding:clamp(14px,1.8vw,22px); border-radius:18px;
  border:1px solid rgba(230,193,90,.24);
  background:
    radial-gradient(140% 120% at 50% -10%, rgba(230,193,90,.1), transparent 58%),
    linear-gradient(180deg, #0c2419 0%, #071410 60%, #050d0a 100%);
}
.gc-cas-top{display:flex; align-items:center; gap:clamp(10px,1.6vw,18px); flex-wrap:wrap}
.gc-cas-back{
  display:inline-flex; align-items:center; gap:8px; min-height:44px; padding:0 17px;
  border-radius:999px; cursor:pointer; font:inherit; font-size:13px; font-weight:700;
  letter-spacing:.04em; color:#f4e3ae; background:rgba(255,255,255,.06);
  border:1px solid rgba(244,227,174,.28);
}
.gc-cas-back:hover{background:rgba(255,255,255,.12); border-color:rgba(244,227,174,.55)}
.gc-cas-back:focus-visible{outline:3px solid #e6c15a; outline-offset:2px}
.gc-cas-back em{font-style:normal; font-size:15px}
.gc-cas-id{display:flex; align-items:baseline; gap:9px; flex-wrap:wrap; min-width:0}
.gc-cas-id span{font-size:22px; line-height:1}
.gc-cas-id b{font-size:clamp(18px,2.2vw,26px); font-weight:800; color:#f4e3ae; letter-spacing:.02em}
.gc-cas-id i{font-style:normal; font-size:12px; color:rgba(244,227,174,.6)}
.gc-cas-wallet{margin-left:auto; text-align:right; line-height:1.15}
.gc-cas-wallet b{display:block; font-size:clamp(18px,2.2vw,26px); font-weight:800; color:#e6c15a; font-variant-numeric:tabular-nums}
.gc-cas-wallet i{font-style:normal; font-size:10.5px; letter-spacing:.09em; text-transform:uppercase; color:rgba(244,227,174,.5)}

.gc-cas-facts{display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:clamp(9px,1.2vw,14px)}
.gc-cas-fact{
  display:flex; flex-direction:column; gap:4px; padding:12px 14px; border-radius:12px;
  background:rgba(0,0,0,.3); border:1px solid rgba(244,227,174,.14);
}
.gc-cas-fact i{font-style:normal; font-size:10.5px; letter-spacing:.1em; text-transform:uppercase; color:rgba(244,227,174,.52)}
.gc-cas-fact b{font-size:15px; font-weight:800; color:#f4e3ae; font-variant-numeric:tabular-nums}
.gc-cas-fact span{font-size:11px; color:rgba(244,227,174,.55); line-height:1.35}
.gc-cas-fact u{display:block; height:5px; border-radius:99px; background:rgba(255,255,255,.09); overflow:hidden; text-decoration:none; margin-top:3px}
.gc-cas-fact u s{display:block; height:100%; width:0; text-decoration:none; border-radius:99px; transition:width .3s ease}
.gc-cas-fact-loss u s{background:linear-gradient(90deg,#c97a4a,#e05a5a)}
.gc-cas-fact-win u s{background:linear-gradient(90deg,#5ad1e6,#6ee0a8)}
.gc-cas-up{color:#6ee0a8}
.gc-cas-down{color:#e8867f}
.gc-cas-note{font-size:12px; line-height:1.5; color:rgba(244,227,174,.62)}
.gc-cas-note b{color:#f4e3ae}
.gc-cas-shut .gc-cas-fact-loss{border-color:rgba(224,90,90,.5)}

/* THE TABLES — presented as tables, not as library tiles. A library cover is a
   2:3 poster with a name; these lead with the number that decides whether you
   want to sit down. */
.gc-cas-tables{display:grid; grid-template-columns:repeat(auto-fit,minmax(310px,1fr)); gap:clamp(11px,1.4vw,17px)}
.gc-cas-t{
  position:relative; display:flex; flex-direction:column; overflow:hidden;
  border-radius:15px; cursor:pointer; min-height:190px;
  border:1px solid rgba(244,227,174,.18); background:rgba(0,0,0,.36);
  transition:transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.gc-cas-t:hover, .gc-cas-t.gcbp-on{
  transform:translateY(-3px); border-color:var(--gc-accent,#e6c15a);
  box-shadow:0 16px 38px rgba(0,0,0,.5), 0 0 0 2px var(--gc-accent,#e6c15a);
}
.gc-cas-t:focus-visible{outline:3px solid var(--gc-accent,#e6c15a); outline-offset:2px}
.gc-cas-t-art{
  display:block; height:88px; background-size:cover; background-position:center 38%;
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 42%,transparent 100%);
          mask-image:linear-gradient(180deg,#000 0%,#000 42%,transparent 100%);
}
.gc-cas-t-b{display:flex; flex-direction:column; gap:7px; padding:0 15px 14px; margin-top:-26px; position:relative; flex:1 1 auto}
.gc-cas-t-h{display:flex; align-items:center; gap:9px; flex-wrap:wrap}
.gc-cas-t-i{font-size:23px; line-height:1}
.gc-cas-t-h b{font-size:17px; font-weight:800; color:#f8f3e2; text-shadow:0 1px 3px rgba(0,0,0,.7)}
.gc-cas-t-edge{
  margin-left:auto; text-align:right; line-height:1.1;
  padding:4px 10px; border-radius:9px; background:rgba(0,0,0,.5);
  border:1px solid rgba(244,227,174,.2);
}
.gc-cas-t-edge em{display:block; font-style:normal; font-size:15px; font-weight:800; color:var(--gc-accent,#e6c15a); font-variant-numeric:tabular-nums}
.gc-cas-t-edge i{display:block; font-style:normal; font-size:9px; letter-spacing:.08em; text-transform:uppercase; color:rgba(244,227,174,.5)}
.gc-cas-t-r{font-size:11.5px; line-height:1.45; color:rgba(244,227,174,.66)}
.gc-cas-t-f{display:flex; gap:10px; flex-wrap:wrap; align-items:baseline; margin-top:auto}
.gc-cas-t-stakes, .gc-cas-t-you{font-size:10.5px; letter-spacing:.06em; text-transform:uppercase; color:rgba(244,227,174,.44)}
.gc-cas-t-you{margin-left:auto}
.gc-cas-t-go{
  margin:0 15px 15px; padding:0 16px; min-height:44px;
  display:flex; align-items:center; justify-content:center; border-radius:11px;
  background:linear-gradient(180deg,#e6c15a,#c79f36); color:#0a1410;
  font-weight:800; font-size:12.5px; letter-spacing:.08em; text-transform:uppercase;
}
.gc-cas-t-q{
  position:absolute; top:9px; right:9px; width:44px; height:44px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  background:rgba(4,10,8,.7); border:1px solid rgba(244,227,174,.32);
  color:#f4e3ae; font:inherit; font-size:16px; font-weight:800; line-height:1;
}
.gc-cas-t-q:hover{background:#e6c15a; color:#0a1410; border-color:#e6c15a}
.gc-cas-t-q:focus-visible{outline:3px solid #e6c15a; outline-offset:2px}

/* ── PHONE ────────────────────────────────────────────────────────────────
   Measured at 375x812 the tables used to sit 7.8 screens down a 5,521px grid.
   The door is now the first thing under the tab strip; these rules keep it one
   tap tall rather than four, and keep every control at 44px. */
@media (max-width:640px){
  .gc-casdoor{gap:11px; padding:13px 14px; border-radius:14px}
  .gc-casdoor-i{font-size:26px}
  .gc-casdoor-n{width:100%; justify-content:space-between; gap:8px}
  .gc-casdoor-f{min-width:0; flex:1 1 0}
  .gc-casdoor-f b{font-size:14px}
  .gc-casdoor-go{margin-left:0; width:100%; justify-content:center}
  .gc-cas{padding:12px; border-radius:14px}
  .gc-cas-top{gap:9px}
  .gc-cas-back{flex:0 0 auto}
  .gc-cas-id{flex:1 1 100%; order:3}
  .gc-cas-wallet{text-align:right}
  .gc-cas-facts{grid-template-columns:1fr}
  .gc-cas-tables{grid-template-columns:1fr}
  .gc-cas-t{min-height:0}
  .gc-cas-hint{padding:11px 13px}
  .gc-cas-hint-go{display:none}
}


/* ══════════════════════════════════════════════════════════════════════════
   GAME BOARD SIZING ON PHONES  (v9.10.7xx)
   Two complaints, one cause: boards were sized against WIDTH only, so in
   portrait they never grew into the vertical space the `safe center` change
   just freed up, and in landscape - where width is plentiful and height is
   the scarce axis - they overflowed instead of shrinking to fit.
   Everything below is opt-in by shape: only boards that are actually square
   get the square treatment.
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- PORTRAIT PHONE: let a square board use the height it now has -------- */
@media (max-width:820px) and (orientation:portrait){
  .gc-g,.gc-turn-board,.gc-cc-b{
    width:min(100%, calc(100dvh - 300px));
    max-width:100%;
    margin-left:auto;margin-right:auto;
  }
  /* Chess, draughts and the other 8x8-and-up boards were the smallest of the
     lot because their cells divide the width into many parts. Give them the
     larger of the two budgets rather than the width budget alone. */
  .gc-turn-board{width:min(100%, max(62vw, calc(100dvh - 280px)))}
}

/* ---- LANDSCAPE PHONE: height is the scarce axis, so size against it ------ */
@media (max-height:560px) and (orientation:landscape){
  .gc-frame.gc-frame>.gc-frame-body{
    min-height:0;
    padding:6px 8px calc(8px + env(safe-area-inset-bottom,0px));
    gap:6px;
  }
  .gc-frame.gc-frame>.gc-stage-head{padding:4px 10px}
  .gc-frame.gc-frame>.gc-stage-foot{padding:5px 10px calc(5px + env(safe-area-inset-bottom,0px))}
  /* A square board in landscape is bounded by height, never by width. */
  .gc-g,.gc-turn-board,.gc-cc-b{
    width:auto;
    height:min(86dvh, 96vw);
    aspect-ratio:1/1;
    max-width:96vw;
    margin-left:auto;margin-right:auto;
  }
  .gc-canvas{
    max-height:min(88dvh,100%);
    height:auto;width:auto;max-width:96vw;object-fit:contain;
  }
}


/* ══ CASCADE ═══════════════════════════════════════════════════════════════
   Match-three with a level campaign. The board is square and is registered in
   the phone sizing rules above alongside the other square boards.
   ═════════════════════════════════════════════════════════════════════════ */
.gc-cc{display:flex;flex-direction:column;align-items:center;gap:10px;width:100%;position:relative}

/* ---- level select ------------------------------------------------------- */
.gc-cc-maphead{display:flex;align-items:baseline;gap:12px;width:min(100%,560px);justify-content:space-between}
.gc-cc-mapt{font:700 18px/1 var(--ui);color:var(--text)}
.gc-cc-maps{font:600 13px/1 var(--ui);color:#ffd93d}
.gc-cc-map{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));
  gap:8px;width:min(100%,560px);
}
.gc-cc-lv{
  all:unset;display:flex;flex-direction:column;gap:3px;
  padding:9px 10px;border-radius:11px;cursor:pointer;
  background:linear-gradient(180deg,var(--panel-2),var(--panel));
  border:1px solid var(--border);
  transition:transform .12s ease,border-color .12s ease;
  -webkit-tap-highlight-color:transparent;
}
.gc-cc-lv:hover{transform:translateY(-2px);border-color:var(--accent)}
.gc-cc-lv b{font:800 17px/1 var(--ui);color:var(--text)}
.gc-cc-lv i{font:500 10.5px/1.35 var(--ui);color:var(--muted);font-style:normal}
.gc-cc-lv u{font-size:11px;text-decoration:none;color:#ffd93d;letter-spacing:1px}
.gc-cc-lv.done{border-color:color-mix(in srgb,#ffd93d 45%,var(--border))}
.gc-cc-lv.lock{opacity:.4;cursor:default}
.gc-cc-lv.lock:hover{transform:none;border-color:var(--border)}

/* ---- in level ----------------------------------------------------------- */
.gc-cc-top{display:flex;align-items:center;gap:10px;width:min(100%,560px);justify-content:space-between}
.gc-cc-hud{display:flex;align-items:center;gap:7px}
.gc-cc-moves{font:800 22px/1 var(--ui);color:var(--accent)}
.gc-cc-mlab{font:500 11px/1 var(--ui);color:var(--muted);margin-right:6px}
.gc-cc-goal{width:min(100%,560px);display:flex;flex-direction:column;gap:5px}
.gc-cc-gt{font:600 12.5px/1.4 var(--ui);color:var(--text)}
.gc-cc-bar{height:6px;border-radius:3px;background:var(--border-2);overflow:hidden}
.gc-cc-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),#ffd93d);transition:width .25s ease}
.gc-cc-need{display:flex;gap:6px;flex-wrap:wrap}
.gc-cc-nchip{
  display:inline-flex;align-items:center;gap:4px;
  padding:3px 8px;border-radius:20px;font:600 11.5px/1 var(--ui);
  background:color-mix(in srgb,var(--c) 16%,transparent);
  border:1px solid color-mix(in srgb,var(--c) 45%,transparent);color:var(--text);
}
.gc-cc-nchip b{color:var(--c);font-size:13px}
.gc-cc-nchip.ok{opacity:.5}

.gc-cc-b{
  display:grid;grid-template-columns:repeat(8,1fr);grid-template-rows:repeat(8,1fr);
  aspect-ratio:1/1;width:min(100%,480px);gap:3px;
  padding:4px;border-radius:12px;
  background:
    radial-gradient(120% 100% at 50% 0%,rgba(167,139,250,.14),transparent 70%),
    radial-gradient(90% 70% at 50% 108%,rgba(56,189,248,.10),transparent 70%),
    var(--panel-2);
  border:1px solid var(--border);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 10px 30px -18px rgba(0,0,0,.8);
  /* v9.10.707 - none, NOT manipulation. `manipulation` still hands vertical
     drags to the page scroller, so a downward swipe on a phone scrolled the
     board out from under the finger instead of moving a piece. There is
     nothing to scroll on a square board; the gesture is the game. */
  touch-action:none;
}
.gc-cc-c{
  display:flex;align-items:center;justify-content:center;
  border-radius:8px;min-width:0;min-height:0;
  font-size:clamp(13px,3.4vw,24px);line-height:1;
  user-select:none;-webkit-tap-highlight-color:transparent;
}
.gc-cc-c.hole{background:transparent}
.gc-cc-c.stone{background:linear-gradient(180deg,#4b5563,#374151);color:#9ca3af;border:1px solid #1f2937}
.gc-cc-c.p{
  cursor:pointer;
  background:none;box-shadow:none;border:0;
  padding:6%;
  transition:transform .1s ease;
}
.gc-cc-c.p:active{transform:scale(.9)}
/* v9.10.707 - the selection used to be a hard white outline that just sat
   there. A slow breath reads as "held", which is what a selection is. */
.gc-cc-c.sel{
  outline:3px solid #fff;outline-offset:-3px;border-radius:9px;
  animation:gcCcHeld .9s ease-in-out infinite;
}
@keyframes gcCcHeld{0%,100%{transform:scale(.9)}50%{transform:scale(.83)}}
.gc-cc-c.hint{animation:gcCcHint 1s ease-in-out infinite}
@keyframes gcCcHint{0%,100%{transform:scale(1)}50%{transform:scale(.84)}}

/* THE CLEAR. v9.10.708.
   Until now the pop class was added to cells that paint() destroyed in the same
   tick, so this has never been seen. It gets a real beat: a swell, then the
   piece collapses and spins out while a ring pushes past where it stood. The
   ring is a pseudo-element so it costs no extra node in a grid of 64. */
.gc-cc-c.clearing{
  animation:gcCcBurst .30s cubic-bezier(.22,.8,.3,1) both;
  position:relative;z-index:2;pointer-events:none;
}
@keyframes gcCcBurst{
  0%{transform:scale(1);opacity:1}
  30%{transform:scale(1.24) rotate(-4deg);opacity:1}
  100%{transform:scale(.12) rotate(16deg);opacity:0}
}
.gc-cc-c.clearing::after{
  content:'';position:absolute;inset:12%;border-radius:50%;
  border:2px solid var(--c,#fff);
  animation:gcCcRing .34s cubic-bezier(.15,.7,.3,1) both;
}
@keyframes gcCcRing{
  0%{transform:scale(.35);opacity:.85;border-width:3px}
  100%{transform:scale(2.1);opacity:0;border-width:1px}
}


/* THE PIECE ITSELF.
   .ccp-body takes the piece colour from the cell via currentColor; .ccp-dark is
   the same silhouette drawn as a heavy inset rim, which is what gives the shape
   an edge without a second path to keep in sync. The drop shadow sits the piece
   on the board instead of printing it on the board. */
.gc-cc-c .ccp{
  width:100%;height:100%;display:block;overflow:visible;
  /* v9.10.708 - NO FILTER. drop-shadow() rasterises the SVG into a CSS-pixel
     bitmap, so on any high-DPR screen the piece was being upscaled from a
     low-resolution render. That is the whole reason these looked soft. The
     shadow is drawn inside the SVG as a translated copy of the path instead,
     which stays vector and stays sharp at any density. */
  shape-rendering:geometricPrecision;
}
.gc-cc-c .ccp-body{fill:currentColor}
.gc-cc-c .ccp-dark{fill:none;stroke:rgba(0,0,0,.42);stroke-width:7;stroke-linejoin:round}
/* the special's halo is drawn as concentric strokes inside the SVG - see
   ccPieceSVG. Two stacked drop-shadows here used to rasterise it twice over. */

/* jelly sits UNDER the piece, so it has to read around it */
.gc-cc-c.j1{background:rgba(56,189,248,.20);box-shadow:inset 0 0 0 3px rgba(56,189,248,.55);border-radius:9px}
.gc-cc-c.j2{background:rgba(56,189,248,.34);box-shadow:inset 0 0 0 3px rgba(56,189,248,.95),inset 0 0 0 6px rgba(56,189,248,.45);border-radius:9px}
/* ice sits OVER it, and a frozen piece cannot be swapped - so it must look
   unavailable rather than merely decorated */
.gc-cc-c.ice{position:relative;cursor:not-allowed}
.gc-cc-c.ice::after{
  content:'';position:absolute;inset:0;border-radius:9px;
  background:linear-gradient(135deg,rgba(224,247,255,.62),rgba(160,220,255,.42));
  box-shadow:inset 0 0 0 2px rgba(255,255,255,.55);
  backdrop-filter:blur(1px);
}


@media (prefers-reduced-motion:reduce){
  .gc-cc-c,.gc-cc-lv{transition:none}
  .gc-cc-c.hint{animation:none;outline:2px dashed #fff;outline-offset:-2px}
  .gc-cc-c.sel{animation:none;transform:scale(.9)}
  .gc-cc-c.clearing{animation:none;opacity:0}
  .gc-cc-c.clearing::after{animation:none;display:none}
}


/* ══ PHASE 10 ══════════════════════════════════════════════════════════════ */
.gc-p10{display:flex;flex-direction:column;gap:10px;width:100%;max-width:640px;margin:0 auto;position:relative}
.gc-p10-opps{display:flex;gap:8px;flex-wrap:wrap}
.gc-p10-opp{
  flex:1 1 190px;padding:8px 10px;border-radius:11px;
  background:linear-gradient(180deg,var(--panel-2),var(--panel));
  border:1px solid var(--border);display:flex;flex-direction:column;gap:3px;
}
.gc-p10-opp.act{border-color:var(--c);box-shadow:0 0 0 1px var(--c),0 0 16px -6px var(--c)}
.gc-p10-name{font:700 13px/1 var(--ui);color:var(--c,var(--text))}
.gc-p10-meta{font:500 11px/1.4 var(--ui);color:var(--muted)}
.gc-p10-meta2{font:500 11px/1.4 var(--ui);color:var(--muted);opacity:.75}
.gc-p10-goal{font:600 11.5px/1.4 var(--ui);color:#eab308;margin-left:auto}

.gc-p10-mid{display:flex;gap:14px;justify-content:center;align-items:flex-start;padding:2px 0}
.gc-p10-pile{all:unset;display:flex;flex-direction:column;align-items:center;gap:4px;cursor:default}
.gc-p10-pile.live{cursor:pointer}
.gc-p10-pile.live:hover .gc-p10-card{transform:translateY(-4px)}
.gc-p10-plab{font:600 10.5px/1 var(--ui);color:var(--muted)}

.gc-p10-card{
  width:42px;height:60px;border-radius:7px;flex:0 0 auto;position:relative;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(160deg,#fff,#e8e8ee);
  border:1px solid rgba(0,0,0,.25);
  box-shadow:0 2px 5px -2px rgba(0,0,0,.6);
  transition:transform .12s ease,box-shadow .12s ease;
  user-select:none;
}
.gc-p10-card b{font:800 21px/1 var(--ui);color:var(--c,#111)}
.gc-p10-card i{
  position:absolute;right:4px;bottom:2px;font:700 9px/1 var(--ui);
  color:var(--c,#111);opacity:.65;font-style:normal;
}
.gc-p10-card.wild{background:conic-gradient(#ef4444,#eab308,#22c55e,#3b82f6,#a78bfa,#ef4444)}
.gc-p10-card.wild b{color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.75)}
.gc-p10-card.skip{background:linear-gradient(160deg,#1f2937,#111827)}
.gc-p10-card.skip b{color:#f87171}
.gc-p10-card.back{background:repeating-linear-gradient(45deg,#312e81 0 5px,#3730a3 5px 10px);border-color:#1e1b4b}
.gc-p10-card.empty{background:rgba(255,255,255,.05);border-style:dashed}
.gc-p10-card.sel{transform:translateY(-11px);box-shadow:0 0 0 2px var(--accent),0 8px 16px -6px #000}

.gc-p10-you{
  padding:9px 10px;border-radius:12px;
  background:linear-gradient(180deg,var(--panel-2),var(--panel));
  border:1px solid var(--border);display:flex;flex-direction:column;gap:7px;
}
.gc-p10-you.act{border-color:var(--accent)}
.gc-p10-yhead{display:flex;align-items:baseline;gap:9px;--c:#a78bfa}
.gc-p10-hand{display:flex;gap:4px;flex-wrap:wrap;justify-content:center;min-height:62px}
.gc-p10-hand .gc-p10-card{cursor:pointer}

.gc-p10-laid{display:flex;gap:8px;flex-wrap:wrap;margin-top:2px}
.gc-p10-grp{
  display:flex;gap:2px;padding:3px;border-radius:8px;cursor:pointer;
  background:rgba(255,255,255,.05);border:1px dashed var(--border);
}
.gc-p10-grp:hover{border-color:var(--accent)}
.gc-p10-grp .gc-p10-card{width:26px;height:37px}
.gc-p10-grp .gc-p10-card b{font-size:13px}
.gc-p10-grp .gc-p10-card i{display:none}

.gc-p10-acts,.gc-p10-ask{display:flex;gap:7px;flex-wrap:wrap;align-items:center;justify-content:center}
.gc-p10-ask{padding:7px;border-radius:9px;background:rgba(234,179,8,.12);border:1px solid rgba(234,179,8,.4);font:600 12px/1 var(--ui)}
.gc-p10-msg{font:500 12px/1.5 var(--ui);color:var(--muted);text-align:center;min-height:18px}

.gc-p10-over{
  position:absolute;inset:0;z-index:6;display:flex;align-items:center;justify-content:center;
  background:rgba(6,8,14,.8);backdrop-filter:blur(3px);border-radius:12px;
}
.gc-p10-ocard{
  display:flex;flex-direction:column;gap:9px;padding:18px 20px;border-radius:14px;text-align:center;
  background:linear-gradient(180deg,var(--panel-2),var(--panel));
  border:1px solid var(--border);box-shadow:0 24px 60px -24px #000;max-width:94%;
}
.gc-p10-ocard>b{font:700 16px/1.3 var(--ui);color:var(--text)}
.gc-p10-tbl{display:flex;flex-direction:column;gap:4px}
.gc-p10-row{display:grid;grid-template-columns:auto auto 1fr auto;gap:9px;align-items:baseline;font:500 12px/1.4 var(--ui)}
.gc-p10-rn{font-weight:700;color:var(--c)}
.gc-p10-rp{color:#f87171}
.gc-p10-rt{color:var(--text);text-align:left}
.gc-p10-ra{color:var(--muted);font-size:11px}
.gc-p10-ra.ok{color:#4ade80}
.gc-p10-win{font:600 13px/1.4 var(--ui);color:#eab308}

@media (max-width:560px){
  .gc-p10-card{width:34px;height:49px}
  .gc-p10-card b{font-size:17px}
  .gc-p10-grp .gc-p10-card{width:22px;height:31px}
  .gc-p10-grp .gc-p10-card b{font-size:11px}
}
@media (prefers-reduced-motion:reduce){ .gc-p10-card{transition:none} }


/* ══ GAME VERTICAL PLACEMENT ON PHONES  (v9.10.7xx, 2nd pass) ══════════════
   FIRST ATTEMPT MISSED, and the reason is worth recording. It padded
   `.gc-stage-head` and, as a fallback, the body of any frame that had no head -
   but the frames DO have a head, so the fallback never matched, and the games
   that draw their own top row (Cascade, Phase 10) were nudged by per-game rules
   that Skip-Bo never got at all. Three partial rules, none of them covering
   every game.

   Every game, without exception, renders inside `.gc-frame`. So the clearance
   goes there, once, as a margin - which moves the title bar, the body and the
   footer down together rather than pushing content around inside a card that
   is still jammed against the top of the screen.
   ═════════════════════════════════════════════════════════════════════════ */
:root{ --gc-top-clear:10px; --gc-menu-clear:68px; }

/* THIRD PASS, and this time measured on the live page rather than reasoned
   about. The floating menu is `.gc-gamemenu` - position:absolute, 58x58, in the
   TOP-LEFT CORNER OF THE GAME FRAME ITSELF. It is not app chrome sitting above
   the game; it is part of the game frame. So pushing the frame down moved the
   button down with it, by exactly the same amount, and the overlap never
   changed. Both were measured at top:84 with an 84px margin applied - the
   clearance was working perfectly and achieving nothing.

   The fix is INSIDE the frame: reserve a band at the top of the frame body that
   the button occupies, so game content starts below it. The frame's own margin
   drops back to a small breathing gap, because there is nothing above it that
   needed clearing in the first place. */
@media (max-width:820px){
  .gc-frame.gc-frame{ margin-top:var(--gc-top-clear) !important; }
  .gc-stage:not(:has(.gc-frame)){ margin-top:var(--gc-top-clear) !important; }
  /* the band the menu button lives in - only the frame's DIRECT body child, or
     the padding compounds down the nested stage/frame body chain */
  .gc-frame.gc-frame>.gc-frame-body{ padding-top:var(--gc-menu-clear) !important; }
  .gc-frame.gc-frame>.gc-stage-head{ padding-top:var(--gc-menu-clear) !important; }
}

/* Landscape: the control is still there but height is the scarce axis, so the
   clearance shrinks to a token gap rather than eating the board. */
@media (max-height:560px) and (orientation:landscape){
  :root{ --gc-top-clear:6px; --gc-menu-clear:60px; }
}

/* I ADDED A CARVE-OUT HERE AND IT WAS WRONG. The reasoning was that immersive
   full-bleed hides the surrounding chrome so nothing needs clearing - but
   `os-arcade-immersive` is on <body> PERMANENTLY, not only during full-bleed
   play. Checked on the live page: the class is present sitting on the game
   library. So the carve-out was zeroing the clearance everywhere, and would
   have kept doing so even once the browser finally loaded the new stylesheet.
   Removed rather than narrowed: the owner wants games lower in every state,
   including in a game, so there is no state this exception should apply to. */

/* ══ SKIP-BO ═══════════════════════════════════════════════════════════════
   Colour is the identity here and the numeral is confirmation, per the owner:
   the question this game asks over and over is "does this fit on that", four
   piles at a time, and a colour answers it without a lookup.
   ═════════════════════════════════════════════════════════════════════════ */
.gc-sb{display:flex;flex-direction:column;gap:9px;width:100%;max-width:640px;margin:0 auto;position:relative}
.gc-sb-opps{display:flex;flex-direction:column;gap:6px}
.gc-sb-opp{padding:7px 9px;border-radius:11px;background:linear-gradient(180deg,var(--panel-2),var(--panel));border:1px solid var(--border)}
.gc-sb-opp.act{border-color:var(--c);box-shadow:0 0 0 1px var(--c),0 0 16px -7px var(--c)}
.gc-sb-ohead{display:flex;gap:9px;align-items:baseline;margin-bottom:4px}
.gc-sb-name{font:700 12.5px/1 var(--ui);color:var(--c,var(--text))}
.gc-sb-meta{font:500 10.5px/1 var(--ui);color:var(--muted)}
.gc-sb-orow{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.gc-sb-ohand{font-size:15px;letter-spacing:-3px;color:var(--muted);min-width:44px}
.gc-sb-odisc,.gc-sb-mydisc{display:flex;gap:4px}

.gc-sb-mid{display:flex;align-items:center;gap:12px;justify-content:center;flex-wrap:wrap;padding:3px 0}
.gc-sb-deck{display:flex;flex-direction:column;align-items:center;gap:3px}
.gc-sb-build{display:flex;gap:7px}
.gc-sb-slot{border-radius:9px;padding:2px;cursor:pointer;border:2px dashed transparent}
.gc-sb-slot.ok{border-color:#4ade80;box-shadow:0 0 12px -3px #4ade80}

.gc-sb-card{
  width:44px;height:62px;border-radius:7px;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  background:var(--c,#2a2a33);
  border:1px solid rgba(0,0,0,.35);
  box-shadow:0 2px 5px -2px rgba(0,0,0,.65),inset 0 -6px 12px -6px rgba(0,0,0,.5);
  transition:transform .12s ease,box-shadow .12s ease;
}
/* The numeral is present but secondary - dark on light colours, and small. */
.gc-sb-card b{font:800 15px/1 var(--ui);color:rgba(10,10,14,.72)}
.gc-sb-card.wild{background:conic-gradient(#ff5d5d,#ffd93d,#4ade80,#38bdf8,#a78bfa,#ff5d5d)}
.gc-sb-card.wild b{color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.8)}
.gc-sb-card.back{background:repeating-linear-gradient(45deg,#134e4a 0 5px,#115e59 5px 10px)}
.gc-sb-card.empty,.gc-sb-card.ghost{background:rgba(255,255,255,.05);border-style:dashed}
.gc-sb-card.empty b,.gc-sb-card.ghost b{color:rgba(255,255,255,.28)}
.gc-sb-card.sm{width:31px;height:44px}
.gc-sb-card.sm b{font-size:11px}
.gc-sb-card.stk{box-shadow:0 3px 9px -3px rgba(0,0,0,.8),0 0 0 2px rgba(255,255,255,.14)}
.gc-sb-card.sel{transform:translateY(-9px) scale(1.05);box-shadow:0 0 0 3px var(--accent),0 10px 18px -6px #000}
.gc-sb-card.drop{outline:2px dashed rgba(255,255,255,.35);outline-offset:2px}
.gc-sb-cnt{font:700 10px/1 var(--ui);color:var(--muted)}
.gc-sb-stkwrap,.gc-sb-dstack{display:flex;flex-direction:column;align-items:center;gap:3px}

.gc-sb-you{padding:8px 9px;border-radius:12px;background:linear-gradient(180deg,var(--panel-2),var(--panel));border:1px solid var(--border);display:flex;flex-direction:column;gap:8px}
.gc-sb-you.act{border-color:var(--accent)}
.gc-sb-yrow{display:flex;gap:14px;align-items:flex-start;flex-wrap:wrap}
.gc-sb-hand{display:flex;gap:5px;justify-content:center;flex-wrap:wrap;min-height:64px}
.gc-sb-hand .gc-sb-card{cursor:pointer}
.gc-sb-msg{font:500 12px/1.5 var(--ui);color:var(--muted);text-align:center;min-height:18px}

/* the flying clone */
.gc-sb-fly{position:absolute;z-index:20;pointer-events:none;will-change:transform}
.gc-sb-fly .gc-sb-card{width:100%;height:100%;box-shadow:0 12px 24px -8px #000}

.gc-sb-over{position:absolute;inset:0;z-index:30;display:flex;align-items:center;justify-content:center;background:rgba(6,8,14,.8);backdrop-filter:blur(3px);border-radius:12px}
.gc-sb-ocard{display:flex;flex-direction:column;gap:8px;padding:18px 20px;border-radius:14px;text-align:center;background:linear-gradient(180deg,var(--panel-2),var(--panel));border:1px solid var(--border);box-shadow:0 24px 60px -24px #000;max-width:94%}
.gc-sb-ocard>b{font:700 16px/1.3 var(--ui);color:var(--text)}
.gc-sb-row{display:flex;gap:10px;justify-content:space-between;font:500 12px/1.4 var(--ui)}
.gc-sb-rn{font-weight:700;color:var(--c)}
.gc-sb-rs{color:var(--muted)}
.gc-sb-acts{display:flex;gap:6px;flex-wrap:wrap;justify-content:center;margin-top:4px}

@media (max-width:560px){
  .gc-sb-card{width:36px;height:51px}
  .gc-sb-card b{font-size:13px}
  .gc-sb-card.sm{width:26px;height:37px}
  .gc-sb-card.sm b{font-size:9px}
}
@media (prefers-reduced-motion:reduce){
  .gc-sb-card{transition:none}
  .gc-sb-fly{display:none}
}


/* ══ GAME MOTION  (v9.10.7xx) ══════════════════════════════════════════════
   Owner: "both games need more animation work." The three that carry the most
   are here: pieces that fall instead of teleporting, points that appear where
   they were earned, and cards that arrive rather than materialise.
   ═════════════════════════════════════════════════════════════════════════ */

/* Cascade — the floating score, at the point of impact */
.gc-cc-pop{
  position:absolute;z-index:8;pointer-events:none;
  transform:translate(-50%,0);
  font:800 15px/1 var(--ui);color:#ffe14d;
  text-shadow:0 2px 6px rgba(0,0,0,.9),0 0 12px rgba(255,225,77,.5);
  animation:gcCcPop .85s cubic-bezier(.2,.7,.3,1) forwards;
}
@keyframes gcCcPop{
  0%{opacity:0;transform:translate(-50%,6px) scale(.7)}
  22%{opacity:1;transform:translate(-50%,-6px) scale(1.15)}
  60%{opacity:1;transform:translate(-50%,-22px) scale(1)}
  100%{opacity:0;transform:translate(-50%,-42px) scale(.92)}
}
/* the cell a piece is falling into must not clip the piece mid-flight */
.gc-cc-b{overflow:visible}

/* Phase 10 — cards arrive instead of appearing. The stagger is by index so a
   fresh hand deals left to right rather than all at once. */
.gc-p10-hand .gc-p10-card{animation:gcP10In .32s cubic-bezier(.2,.8,.3,1) backwards}
.gc-p10-hand .gc-p10-card:nth-child(1){animation-delay:.00s}
.gc-p10-hand .gc-p10-card:nth-child(2){animation-delay:.03s}
.gc-p10-hand .gc-p10-card:nth-child(3){animation-delay:.06s}
.gc-p10-hand .gc-p10-card:nth-child(4){animation-delay:.09s}
.gc-p10-hand .gc-p10-card:nth-child(5){animation-delay:.12s}
.gc-p10-hand .gc-p10-card:nth-child(6){animation-delay:.15s}
.gc-p10-hand .gc-p10-card:nth-child(7){animation-delay:.18s}
.gc-p10-hand .gc-p10-card:nth-child(8){animation-delay:.21s}
.gc-p10-hand .gc-p10-card:nth-child(9){animation-delay:.24s}
.gc-p10-hand .gc-p10-card:nth-child(n+10){animation-delay:.27s}
@keyframes gcP10In{
  from{opacity:0;transform:translateY(16px) rotate(-4deg) scale(.9)}
  to{opacity:1;transform:none}
}
/* a laid group lands with weight */
.gc-p10-grp{animation:gcP10Lay .34s cubic-bezier(.2,.9,.3,1) backwards}
@keyframes gcP10Lay{
  from{opacity:0;transform:scale(.82) translateY(-10px)}
  to{opacity:1;transform:none}
}

@media (prefers-reduced-motion:reduce){
  .gc-cc-pop{animation-duration:.01ms}
  .gc-p10-hand .gc-p10-card,.gc-p10-grp{animation:none}
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE BOTTOM SECTION WHEEL  (v9.10.727)  —  oracle-navwheel.js
   ───────────────────────────────────────────────────────────────────────────
   Two states. RESTING is a flat pill with back / home / forward and the name
   of the section you are in. OPEN raises the sections onto a bent arc you drag
   sideways; letting go snaps to the centre, opens it, and the arc lowers and
   dims back into the pill.

   `.m-tabbar` is NOT display:none'd while this is on. oracle-navwheel.js reads
   the computed display of each `.m-tab` to know which sections the current role
   is allowed — and a display:none ANCESTOR does not change a child's own
   computed display, so hiding the bar that way would keep working while
   hiding it any other way would not. It is collapsed to exactly the pill's
   height with its contents made invisible and inert instead, which also means
   every layout rule that already reserves space for the tab bar keeps
   reserving the right amount and nothing below had to be re-measured.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  --nw-h:54px;
  --nw-pad:max(6px,env(safe-area-inset-bottom,0px));
}
body.nw-on .m-tabbar{
  height:calc(var(--nw-h) + var(--nw-pad)) !important;
  min-height:0 !important;
  padding:0 !important;
  overflow:hidden !important;
  opacity:0 !important;
  pointer-events:none !important;
  border-top-color:transparent !important;
}

.nw{
  position:fixed;left:0;right:0;bottom:0;z-index:64;
  display:none;
  font-family:var(--ui,system-ui,sans-serif);
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;
  /* THE CONTAINER IS A HOLE, NOT A SURFACE. `.nw` spans the arc's height even
     when the arc is down, so leaving it hit-testable would swallow every scroll
     and tap that began in the bottom ~210px of the page - with nothing visible
     there to explain why. Only the pill takes events at rest; the wash and the
     arc take them while it is open. */
  pointer-events:none;
}
.nw-bar{pointer-events:auto;touch-action:none}
.nw.nw-open{pointer-events:auto}
body.nw-on .nw{display:block}
/* Wherever the tab bar gets out of the way, so does this. */
body.os-workspace-immersive .nw,
body.os-arcade-immersive .nw,
body.force-desktop .nw{display:none !important}
body.m-tabbar-hidden .nw .nw-wheel{opacity:0 !important;pointer-events:none !important}
body.m-tabbar-hidden .nw .nw-bar{transform:translateY(115%)}
:fullscreen .nw,:-webkit-full-screen .nw{display:none !important}

/* ── the scrim, only while the arc is up ───────────────────────────────── */
.nw-wash{
  position:fixed;left:0;right:0;bottom:0;height:340px;
  background:linear-gradient(to top,rgba(4,7,13,.93) 0%,rgba(4,7,13,.78) 38%,rgba(4,7,13,0) 100%);
  opacity:0;pointer-events:none;transition:opacity .3s ease;touch-action:none;
}
.nw.nw-open .nw-wash{opacity:1;pointer-events:auto}

/* ── the arc ───────────────────────────────────────────────────────────── */
.nw-wheel{
  position:relative;height:132px;margin-bottom:2px;touch-action:none;
  opacity:0;transform:translateY(30px) scale(.9);
  transform-origin:50% 100%;
  transition:opacity .24s ease,transform .36s cubic-bezier(.18,.9,.24,1);
  pointer-events:none;
}
/* ── will-change ONLY WHILE IT IS UP (v9.10.737) ──────────────────────────
   This was unconditional, on the wheel and on all ten items. `will-change`
   is a promise to the compositor that costs a real GPU layer for as long as
   it is set, and this control is down and invisible for almost the whole
   session - so it was eleven permanent layers, pinned to the bottom of every
   screen in the OS, next to a `perspective` 3D rendering context. On a phone
   GPU that is exactly the budget that produces half-rasterised tiles: content
   that simply is not painted, in rectangles, below the fold.
   Promising it at the moment the class lands is early enough - the open
   transition is 240ms and the compositor only needs the current frame. */
.nw.nw-open .nw-wheel{opacity:1;transform:none;pointer-events:auto;will-change:transform,opacity}
.nw.nw-open .nw-i{will-change:transform,opacity}
/* THE DRUM. `perspective` has to live on the PARENT of the transformed items -
   this is the whole reason the wheel reads as something turning rather than a
   row of icons getting smaller. 760px against a 300px cylinder radius is a
   ~2.5:1 ratio, which is close to what iOS uses: enough that the third item
   away is visibly rotated edge-on, not so much that the near items distort. */
.nw-arc{
  position:absolute;left:50%;top:62px;width:0;height:0;
  perspective:760px;
  -webkit-perspective:760px;
}
.nw-notch{
  position:absolute;left:50%;bottom:2px;width:64px;height:2px;margin-left:-32px;
  border-radius:2px;background:var(--accent,#22d9e6);opacity:.55;
}
.nw-i{
  position:absolute;left:0;top:0;width:76px;height:76px;margin:-38px 0 0 -38px;
  backface-visibility:hidden;-webkit-backface-visibility:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  background:transparent;border:0;padding:0;color:var(--muted,#8b93a8);
  cursor:pointer;transform-origin:50% 50%;
}
.nw-i-ico{
  position:relative;width:44px;height:44px;border-radius:15px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.05);border:1px solid var(--border,rgba(255,255,255,.12));
  transition:background .2s ease,border-color .2s ease,box-shadow .2s ease;
}
.nw-i-ico svg{width:21px;height:21px}
.nw-i-t{
  font-size:9px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;
  white-space:nowrap;
}
.nw-i-dot{
  display:none;position:absolute;top:2px;right:12px;width:8px;height:8px;border-radius:50%;
  background:#ff4d5e;box-shadow:0 0 0 2px rgba(4,7,13,.85);
}
.nw-i-dot.on{display:block}
.nw-i.nw-i-on{color:var(--accent,#22d9e6)}
.nw-i.nw-i-on .nw-i-ico{
  background:rgba(34,217,230,.18);
  background:color-mix(in srgb,var(--accent,#22d9e6) 18%,transparent);
  border-color:var(--accent,#22d9e6);
  box-shadow:0 0 0 1px var(--accent,#22d9e6),0 8px 26px rgba(0,0,0,.5);
}

/* ── the resting pill ──────────────────────────────────────────────────── */
.nw-bar{
  position:relative;display:flex;align-items:center;gap:6px;
  height:var(--nw-h);margin:0 auto calc(var(--nw-pad)) auto;max-width:280px;padding:0 8px;
  border-radius:16px;
  background:var(--panel-2,rgba(14,19,30,.94));
  border:1px solid var(--border,rgba(255,255,255,.12));
  box-shadow:0 10px 30px rgba(0,0,0,.45);
  transition:transform .3s cubic-bezier(.2,.9,.25,1),box-shadow .3s ease,border-color .3s ease;
}
.nw-bar.nw-bar-land{
  animation:nw-land .42s cubic-bezier(.2,.9,.25,1);
}
@keyframes nw-land{
  0%{transform:scale(1.035);box-shadow:0 14px 40px rgba(0,0,0,.6)}
  60%{transform:scale(.996)}
  100%{transform:scale(1)}
}
/* ── v9.10.729 — THREE BUTTONS, CENTRED ──────────────────────────────────
   The section chip and the grab handle are gone. Back and Forward sit either
   side of Home because that is where the thumb that just held Home already is,
   and while the wheel is up those two are what turn it. */
.nw-nav{display:flex;align-items:center;justify-content:center;gap:10px;flex:1}
.nw-b{
  position:relative;width:46px;height:42px;
  display:flex;align-items:center;justify-content:center;
  background:transparent;border:0;border-radius:13px;color:var(--muted,#8b93a8);cursor:pointer;
  transition:color .16s ease,background .16s ease,opacity .16s ease;
  touch-action:none;
}
.nw-b>svg:not(.nw-ring){width:21px;height:21px}
.nw-b:active{background:rgba(255,255,255,.07);color:var(--accent,#22d9e6)}
.nw-b.nw-off{opacity:.28;pointer-events:none}
.nw-b-home{width:52px}
.nw-b-home .nw-b-i{width:22px;height:22px}
/* While the wheel is up the arrows are turning it, not walking history. */
.nw.nw-turning .nw-b{color:var(--accent,#22d9e6)}
.nw.nw-turning .nw-b-home{color:var(--muted,#8b93a8)}
.nw-b-home.nw-holding{background:rgba(255,255,255,.07)}
/* Primed: half a second is up, the wheel is one slide away. It has to look
   different from "being pressed" or there is no moment that says go. */
.nw-b-home.nw-primed{background:rgba(34,217,230,.16);color:var(--accent,#22d9e6)}
.nw-b-home.nw-primed .nw-b-i{transform:translateY(-2px)}
.nw-b-home .nw-b-i{transition:transform .18s cubic-bezier(.2,.9,.25,1)}

/* THE "SLIDE UP" HINT. Half a second of holding with nothing on screen is a
   button that appears not to work, and "now slide up" is not something anyone
   guesses. It rides above the bar, pointing the way the thumb has to go. */
.nw-lift{
  position:absolute;left:0;right:0;bottom:calc(var(--nw-h) + var(--nw-pad) + 6px);
  display:flex;flex-direction:column;align-items:center;gap:2px;
  opacity:0;transform:translateY(6px);pointer-events:none;
  transition:opacity .18s ease,transform .24s cubic-bezier(.2,.9,.25,1);
  color:var(--accent,#22d9e6);
}
.nw.nw-hint .nw-lift{opacity:1;transform:none}
.nw-lift svg{width:18px;height:18px;animation:nw-bob 1.1s ease-in-out infinite}
.nw-lift span{font:800 9px var(--ui);letter-spacing:.16em;text-transform:uppercase;opacity:.8}
@keyframes nw-bob{0%,100%{transform:translateY(2px)}50%{transform:translateY(-3px)}}

/* THE "SLIDE DOWN" INSTRUCTION, on the wheel itself, for the same reason. */
.nw-go{
  position:absolute;left:0;right:0;bottom:-4px;
  display:flex;align-items:center;justify-content:center;gap:6px;
  color:var(--muted,#8b93a8);opacity:.55;
  transition:opacity .2s ease,color .2s ease,transform .2s ease;
}
.nw-go svg{width:14px;height:14px}
.nw-go span{font:800 9px var(--ui);letter-spacing:.16em;text-transform:uppercase}
/* Pulling down lights it, so the gesture shows its own progress rather than
   firing out of nowhere. */
.nw.nw-pulling .nw-go{opacity:1;color:var(--accent,#22d9e6);transform:translateY(3px)}
.nw.nw-pulling .nw-notch{opacity:1;height:3px}

/* ── THE PROGRESS RINGS ─────────────────────────────────────────────────────
   Two long waits in this control - a three-second press to open it and a
   two-second dwell before it acts - and a long wait with no feedback is
   indistinguishable from a dead button. Both draw the same ring: a rounded
   rect stroked round its own perimeter, whose length is MEASURED with
   getTotalLength() rather than hardcoded, so changing the corner radius cannot
   silently desynchronise the fill from the clock. */
.nw-ring{
  position:absolute;left:50%;top:50%;width:42px;height:42px;margin:-21px 0 0 -21px;
  pointer-events:none;overflow:visible;
}
.nw-ring rect{
  fill:none;stroke:var(--accent,#22d9e6);stroke-width:2.5;
  stroke-dashoffset:1000;
  transform-origin:50% 50%;transform:rotate(-90deg);
}
.nw.nw-open .nw-bar{border-color:rgba(34,217,230,.45);border-color:color-mix(in srgb,var(--accent,#22d9e6) 45%,transparent)}

@media (prefers-reduced-motion:reduce){
  .nw-wheel,.nw-bar,.nw-wash,.nw-lift,.nw-go{transition:none !important}
  .nw-lift svg{animation:none !important}
  .nw-bar.nw-bar-land{animation:none !important}
}

/* ═══════════════════════════════════════════════════════════════════════════
   GAME CENTER — CATEGORY OR ALL, AND HOW YOU WANT TO PLAY  (v9.10.727)
   ───────────────────────────────────────────────────────────────────────────
   The owner: "it should be structured with category of games or all games...
   when I select to filter to online or solo or ai it should when clicked be on
   that option so I don't have to go in the menu."

   The six per-category shelves on Home are gone (they were the same games the
   grid already lists), so the chips ARE the categories now. And the play-mode
   chips are pulled out of that same strip into their own labelled row, because
   they answer a different question: the category row asks WHAT, this one asks
   HOW, and ten identical pills in one line made them look like one control.
   ═══════════════════════════════════════════════════════════════════════════ */
.gcbp .gcbp-modes{
  display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  padding:2px 0 8px;
}
.gcbp .gcbp-modes .gc-chips-lbl{
  font:800 10px var(--ui);letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);opacity:.75;margin-right:4px;
}
.gcbp .gcbp-modes .gc-chip{
  display:inline-flex;align-items:center;
  min-height:36px;padding:0 14px;border-radius:999px;
  background:transparent;border:1px solid var(--border);color:var(--muted);
  font:700 11px var(--ui);letter-spacing:.08em;text-transform:uppercase;cursor:pointer;
}
.gcbp .gcbp-modes .gc-chip:hover{background:rgba(255,255,255,.06);color:var(--text)}
/* The active play mode is outlined rather than filled: it is a standing choice
   that stays on across visits, and a solid accent pill reads as "you just
   pressed this". */
.gcbp .gcbp-modes .gc-chip.on{
  background:rgba(34,217,230,.13);
  background:color-mix(in srgb,var(--accent) 13%,transparent);
  border-color:var(--accent);color:var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent);
}

/* THE FILTER SAYS WHAT IT IS ABOUT TO DO. A play mode that survives a week and
   then changes how a game opens needs to admit that on the surface it changes,
   not only as a lit chip somewhere above the fold. */
.gc-mode-note{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin:0 0 10px;padding:9px 13px;border-radius:11px;
  background:rgba(34,217,230,.08);
  background:color-mix(in srgb,var(--accent) 8%,transparent);
  border:1px solid var(--border);
  border-left:3px solid var(--accent);
}
.gc-mode-note[hidden]{display:none !important}
.gc-mode-note b{font:800 11.5px var(--ui);letter-spacing:.06em;color:var(--text);text-transform:uppercase}
.gc-mode-note span{flex:1;min-width:150px;font:500 11.5px var(--ui);color:var(--muted)}
.gc-mode-note em{
  font:800 10.5px var(--ui);letter-spacing:.12em;text-transform:uppercase;font-style:normal;
  color:var(--accent);cursor:pointer;padding:7px 11px;border-radius:8px;
  border:1px solid var(--border);
}
.gc-mode-note em:hover{background:rgba(255,255,255,.06)}
@media (max-width:900px){
  .gcbp .gcbp-modes{
    flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;
    scrollbar-width:none;padding-bottom:10px;
  }
  .gcbp .gcbp-modes::-webkit-scrollbar{height:0}
  .gcbp .gcbp-modes .gc-chip{flex:0 0 auto;min-height:42px;padding:0 16px;font-size:12px}
  .gcbp .gcbp-modes .gc-chips-lbl{flex:0 0 auto}
  .gc-mode-note em{min-height:40px;display:inline-flex;align-items:center}
}

/* ═══════════════════════════════════════════════════════════════════════════
   GAME CENTER — THE FOCUSED GAME'S NAME, WHERE YOU CAN SEE IT  (v9.10.732)
   ───────────────────────────────────────────────────────────────────────────
   "when slecting or Viewing a Game the name and description is on the bottom
   of the games list and also not viewable."

   Two separate causes, both measurable.

   1. The grid's metadata line sat AFTER the grid. That is right for a shelf,
      which is one row; it is wrong for an auto-fill grid holding the whole
      library, where it lands thirteen rows of covers below the fold. It is
      above the grid now (see oracle-games.js) and sticky, so it holds while
      you scroll.

   2. On a phone the covers were 102-112px wide. The name is drawn INTO the
      poster at 25px on a 300px-wide artboard, so at that tile size it renders
      at about 9px - present, and unreadable. Under 900px the grid now gives
      each cover roughly half the width of the screen and the name is set as
      real text underneath it, at a real size, instead of being a decoration
      inside a scaled-down picture.
   ═══════════════════════════════════════════════════════════════════════════ */
.gcbp .gcbp-meta.gcbp-meta-grid{
  position:sticky;top:0;z-index:4;
  margin:0 0 4px;padding:9px 12px;
  border-radius:11px;
  /* Opaque, NOT a backdrop-filter. A blur on a `position:sticky` element is one
     of the reliable ways to corrupt rasterisation in a Chromium WebView: the
     sticky box is promoted to its own layer, the filter forces a readback of
     whatever is behind it every frame, and what fails is the painting of the
     content BELOW - which is what a black band under the fold looks like.
     Nothing behind this line is meant to be legible through it anyway. */
  background:#080b14;
  border:1px solid var(--border);
  /* seeded at build time, so it is never an empty band waiting for a hover */
  opacity:1;
}
.gcbp .gcbp-meta.gcbp-meta-grid b{font-size:clamp(14px,1.3vw,18px)}
.gcbp .gcbp-meta.gcbp-meta-grid span{opacity:.8}

@media (max-width:900px){
  /* ── v9.10.734 — THE SIZE WAS THE WRONG LEVER ────────────────────────────
     "why are the games so big like 1 game can fit on the screeen".

     v9.10.732 read "the name is 9px" as "the covers are too small" and went to
     a 44vw floor - two columns, a 2:3 poster ~265px tall, so roughly ONE ROW
     on screen at a time. Measured against what it replaced (102px covers, three
     columns, three or four rows) that is nine or twelve games traded for two.

     The name being 9px was never a size problem. It is 25px drawn INTO a 300px
     artboard, so it scales with the picture and is unreadable at any tile size
     a phone can afford. The fix was the text label underneath, which is real
     type at a real size and does not care how wide the cover is. That stays;
     the covers go back to roughly the density they had.

     MEASURED, per viewport, columns then cover width:
       320px  2 / 143   360px  3 / 105   390px  3 / 115   430px  3 / 129
       480px  4 / 109   600px  5 / 105   768px  6 / 115
     which is the same column count the 102px floor produced at every one of
     them. The only thing the label costs is 29px of row height. */
  .gcbp .gc-grid{
    grid-template-columns:repeat(auto-fill,minmax(clamp(96px,25vw,104px),1fr));
    gap:10px;
  }
  /* AND THE NAME IS SET AS TEXT, NOT DRAWN INTO THE PICTURE. A touch screen has
     no hover, so the focus line above can never describe what your thumb is
     over - by the time a tap registers, the game is already opening. The label
     is the only thing that tells you what a cover is before you commit to it. */
  .gcbp .gc-card .gc-card-b{
    display:block;padding:6px 1px 0;background:transparent;
  }
  /* Exactly two lines tall whether the name needs one or two, so the grid rows
     stay level. A ragged bottom edge across three columns reads as broken
     layout, and the alternative - truncating to one line - turns "Mahjong
     Solitaire" into "Mahjong Solit...". */
  .gcbp .gc-card .gc-card-n{
    font:700 11.5px var(--ui);color:var(--text);letter-spacing:.01em;
    line-height:1.24;margin:0;height:2.48em;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  }
  /* The blurb stays off the tile on purpose: two lines of it under every cover
     turns a wall of art into a wall of paragraphs, and the "?" on each cover
     already opens the real guide. */
  /* Neither the blurb nor the mode pills go under the cover. Both were costing
     ~22px of row height each for something already on the sticky line above the
     grid, on the start card, and behind the "?" - and height is exactly what
     was in short supply. */
  .gcbp .gc-card .gc-card-d,
  .gcbp .gc-card .gc-card-m{display:none}
  /* Same for the shelves — a row of unlabelled thumbnails is the same problem
     one row at a time. */
  /* A shelf scrolls sideways, so its tiles were never the thing eating the
     screen - but they were the same 102px as the grid and had the same 9px
     name. Nudged up a little and labelled; one line with an ellipsis is right
     here, because a row you are swiping through wants a level bottom edge more
     than it wants the last two characters of a long title. */
  .gcbp .gc-shelf-c{width:clamp(104px,27vw,140px)}
  .gcbp .gc-shelf-c .gc-shelf-n{
    display:block;padding:6px 1px 0;
    font:700 11.5px var(--ui);color:var(--text);line-height:1.25;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  .gcbp .gc-shelf-c .gc-shelf-t{
    display:block;padding:1px 1px 0;
    font:600 9px var(--mono);letter-spacing:.08em;text-transform:uppercase;
    color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  .gcbp .gcbp-meta.gcbp-meta-grid{padding:8px 11px}
  .gcbp .gcbp-meta.gcbp-meta-grid b{font-size:14px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   GAME CENTER — CONTROLS ARE DRAWN, NOT TYPED  (v9.10.736)
   ───────────────────────────────────────────────────────────────────────────
   "I see invisible icons."

   Under 900px `.gc-headbtn span{display:none}`, so each of those controls is
   its glyph and nothing else. Four of them were characters with no guaranteed
   font behind them: `⚙` U+2699, `♫` U+266B, `⏸` U+23F8 and `✕` U+2715 are
   TEXT-presentation symbols, drawn from the UI font rather than the emoji font,
   and a WebView whose stack does not carry them renders nothing at all. The
   emoji ones survived - which is exactly what the screenshot showed: three
   buttons with pictures and three empty boxes.

   They are inline SVG now. This is the styling that makes an icon-only button
   look deliberate rather than like a label that failed to load.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ── SIZED AGAINST THE BOX, NOT AGAINST THE VIEWBOX (v9.10.738) ───────────
   "icon images are way to big for the box their in". They were 19px inside a
   44px button, which is 43% - a ratio that is fine for an icon with its own
   internal margin and wrong for these, because every path here runs edge to
   edge of its 24x24 artboard. A 19px render of a glyph that fills its own
   viewBox is a 19px glyph; a 19px render of a typical icon is about 15px of
   ink with 4px of air. So the drawn weight was a third larger than the number
   suggested. 15-16px against 44px lands at ~35%, which is where a control-row
   icon normally sits. */
.gc-bi{
  width:15px;height:15px;flex:none;display:block;
  stroke:currentColor;fill:none;
}
.gc-headbtn .gc-bi{width:15px;height:15px}
.gc-icon-btn .gc-bi{width:16px;height:16px}
.gc-headbtn:hover .gc-bi,
.gc-icon-btn:hover .gc-bi{color:var(--accent)}
/* The "off" states were carried by a different glyph (🔇 for 🔊). The icon
   changes too, but colour is what reads at 16px, so it says it twice. */
.gc-audio-b.gc-audio-off .gc-bi{color:var(--muted-2);opacity:.75}

@media (max-width:900px){
  /* With the label hidden the button was a wide pill wrapped around a 16px
     picture, which is why an empty one read as a blank box rather than as a
     control that had lost its icon. Square, and sized for a thumb. */
  .gc-headbtn{
    min-width:44px;min-height:44px;padding:0 12px;
    justify-content:center;
  }
  .gc-headbtn .gc-bi{width:16px;height:16px}
  /* A count still earns its place next to the icon — "24/70" is the reason to
     press the trophy — so those buttons keep their width. */
  .gc-headbtn:has(b){padding:0 13px;gap:7px}
  .gc-head-acts{
    display:flex;flex-wrap:nowrap;overflow-x:auto;gap:8px;
    -webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:2px;
  }
  .gc-head-acts::-webkit-scrollbar{height:0}
  .gc-audio-set{width:auto;flex:none}
  /* The volume track was `background:transparent` with only the 19px thumb
     painted, so on a dark panel it read as a lone floating circle — the third
     "invisible icon" in the screenshot. The runnable-track rule below it does
     paint a line, but Android's WebView needs the base element to declare one
     too before it will honour the pseudo-element. */
  .gc-vol{background:rgba(255,255,255,.10);border-radius:99px;height:22px}
  .gc-vol::-webkit-slider-runnable-track{height:6px;border-radius:99px;background:rgba(255,255,255,.16)}
  .gc-vol::-webkit-slider-thumb{margin-top:-6.5px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE COINS ROW IN THE GAME CENTER HEADER  (v9.10.737)
   ───────────────────────────────────────────────────────────────────────────
   "I still don't see two icons next to the daily spin the wheel."

   The wheel is drawn by oracle-coins-arcade.js as an inline SVG, which is why
   it was the one of the three that showed. Its neighbours were not:

     · the SHOP used `\1F6CD` SHOPPING BAGS, a DEFAULT-TEXT-PRESENTATION
       codepoint - asked of the UI font, not the emoji font, and absent from
       this device's. With `.ps-chip{border-radius:999px}` and the 44px minimum
       a phone gives these buttons, an empty one is a perfect circle. Now SVG.
     · the BALANCE chip is a 13px CSS coin next to a value that is an em-dash
       until the first fetch lands - unreadable beside 19px line icons. Sized up
       here to match its neighbours.

   And the three of them mount INDEPENDENTLY, each watching for the header
   rather than being called by it, so which one lands first is a race and the
   row could come out in any order. `order` fixes the reading order in CSS,
   where it does not depend on who won.
   ═══════════════════════════════════════════════════════════════════════════ */
.gc-head-acts > *{order:5}
.gc-head-acts > .pc-chip{order:1}
.gc-head-acts > .pa-btn{order:2}
.gc-head-acts > .ps-chip{order:3}
.gc-head-acts > .gc-audio-set{order:9}

.ps-chip-i{display:inline-flex;align-items:center;justify-content:center;font-size:0}
.ps-chip-i svg{width:15px;height:15px;display:block}

@media (max-width:900px){
  /* ── AND HERE IS WHAT WAS ACTUALLY EMPTYING THEM ────────────────────────
     `.gc-headbtn span{display:none}` (line ~7670) exists to drop the text
     LABEL from these buttons on a phone. It is written as "every span", and
     the three coin controls are not built by oracle-games.js - they are
     mounted by oracle-coins.js, oracle-coins-arcade.js and
     oracle-coins-shop.js, which put their ICONS in spans too. So the rule hid
     the icon along with the label:

       .pa-ico     survived only by accident - `.pa-btn .pa-ico` is (0,2,0)
                   against the rule's (0,1,1), so it out-specified it. That is
                   why the wheel was the one of the three that showed.
       .pc-coin    (0,1,0). Hidden.
       .pc-val     styled by `.pc-chip .pc-val`, which sets font and colour and
                   never sets `display` - and specificity is decided PER
                   PROPERTY, so the balance was hidden by a rule it otherwise
                   beats.
       .ps-chip-i  no display of its own. Hidden.

     Two buttons with nothing inside them, in a row of buttons that work. */
  .gc-headbtn .pa-ico,
  .gc-headbtn .ps-chip-i{display:inline-flex !important}
  .gc-headbtn .pc-coin{display:inline-block !important}
  .gc-headbtn .pc-val{display:inline !important}
  .gc-headbtn .pa-badge:not([hidden]){display:flex !important}
  .gc-headbtn .ps-chip-t{display:none}

  /* Same square footprint as every other icon-only control in this row, so a
     pill among rounded squares does not read as a different kind of thing —
     and an EMPTY pill at 44px is a perfect circle, which is what the owner was
     looking at. */
  .gc-head-acts > .ps-chip{border-radius:12px;padding:0 12px}
  .ps-chip-i svg{width:16px;height:16px}
  /* The balance is the one chip whose CONTENT is the point, so it keeps its
     number — a coin with no number is a decoration. */
  .gc-head-acts > .pc-chip{padding:0 12px;gap:7px}
  .gc-head-acts > .pc-chip .pc-val{font-size:13px}
  .pc-coin{width:15px;height:15px}
  .pc-coin::after{inset:4px}
}

/* ══ CONTRACTS / ASSIGNMENTS / QUESTS (v9.10.740) ═══════════════════════════
   Scoped under #view-contracts-body so nothing here can reach another view. */
#view-contracts-body{overflow-y:auto;padding:0}
/* v9.10.753 - THE TAB BAR WAS BEING CRUSHED, NOT HIDDEN.
   `#view-contracts-body` is a COLUMN FLEX CONTAINER (inline style, oracle.html
   :1068) and this bar is one of its two flex items, with the initial
   `flex-shrink:1`. On a long page the other item wins the space and the browser
   squeezes the bar - MEASURED at 25px against its natural 61px, which slices
   23px off 36px-tall pills and leaves the sliver of rounded tops the owner
   photographed. It looked correct on My work for the only reason it ever could:
   that page was short enough that nothing needed shrinking. `flex:none` is the
   whole fix, on the bar and on the body that was stealing from it.

   backdrop-filter dropped at the same time, per this sheet's own finding at
   ~line 13953: a blur on a `position:sticky` element promotes it to its own
   layer and forces a per-frame readback of what is behind it, which is a
   reliable way to corrupt the painting of the content below it in a Chromium
   WebView. Nothing behind this bar is meant to be legible through it. */
#view-contracts-body .ct-tabs{position:sticky;top:0;z-index:5;flex:none;display:flex;gap:7px;padding:12px 14px;
 background:#080b14;border-bottom:1px solid rgba(255,255,255,.09);overflow-x:auto}
#view-contracts-body .ct-body{flex:0 0 auto}
#view-contracts-body .ct-sheet > .ct-shead{flex:none}
#view-contracts-body .ct-sheet > .ct-sbody{flex:0 0 auto}
#view-contracts-body .ct-tabs button{flex:none;height:36px;padding:0 15px;border-radius:99px;background:transparent;
 border:1px solid rgba(255,255,255,.09);color:#93a0b8;font:700 11.5px ui-sans-serif;cursor:pointer;white-space:nowrap}
#view-contracts-body .ct-tabs button.on{background:rgba(34,217,230,.13);border-color:#22d9e6;color:#22d9e6}
#view-contracts-body .ct-body{padding:14px 14px 90px;max-width:820px;margin:0 auto}
#view-contracts-body .ct-head{margin-bottom:14px}
#view-contracts-body .ct-h1{font:800 21px ui-sans-serif;letter-spacing:-.02em;color:#eef2f9}
#view-contracts-body .ct-sub{color:#93a0b8;font-size:12.5px;margin-top:3px}
#view-contracts-body .ct-h4{font:700 11px ui-sans-serif;letter-spacing:.12em;text-transform:uppercase;color:#93a0b8;margin:22px 0 9px}
#view-contracts-body .ct-gh{font:700 11px ui-sans-serif;letter-spacing:.1em;text-transform:uppercase;color:#66738c;margin:16px 0 8px}
#view-contracts-body .ct-gh span{text-transform:none;letter-spacing:0;font-weight:400;font-size:11.5px;color:#66738c}
#view-contracts-body .ct-hint{color:#66738c;font-size:11.5px;line-height:1.5;margin:7px 0 0}
#view-contracts-body .ct-empty{text-align:center;color:#66738c;font-size:13px;padding:40px 14px;line-height:1.7}
#view-contracts-body .ct-note{border-left:3px solid #22d9e6;background:rgba(34,217,230,.06);padding:11px 13px;
 border-radius:0 11px 11px 0;font-size:12.5px;line-height:1.55;color:#93a0b8;margin:0 0 13px}
#view-contracts-body .ct-note b{color:#22d9e6}
#view-contracts-body .ct-note.ct-warn{border-left-color:#fbbf24;background:rgba(251,191,36,.07)}
#view-contracts-body .ct-note.ct-warn b{color:#fbbf24}
#view-contracts-body .ct-card{display:block;width:100%;text-align:left;background:#0e1524;border:1px solid rgba(255,255,255,.09);
 border-radius:15px;padding:14px;margin-bottom:10px;cursor:pointer;color:#eef2f9;font-family:inherit}
#view-contracts-body .ct-card:hover{border-color:rgba(255,255,255,.17)}
#view-contracts-body .ct-card.ct-blocked{opacity:.6}
#view-contracts-body .ct-c1{display:flex;align-items:center;gap:9px;margin-bottom:8px}
#view-contracts-body .ct-kind{font:800 9.5px ui-monospace;letter-spacing:.13em;text-transform:uppercase;
 padding:4px 8px;border-radius:6px;background:rgba(125,211,252,.15);color:#7dd3fc}
#view-contracts-body .ct-k-quest{background:rgba(167,139,250,.15);color:#a78bfa}
#view-contracts-body .ct-k-mission{background:rgba(251,146,60,.15);color:#fb923c}
#view-contracts-body .ct-k-adventure{background:rgba(74,222,128,.15);color:#4ade80}
#view-contracts-body .ct-k-job{background:rgba(244,114,182,.15);color:#f472b6}
#view-contracts-body .ct-when,#view-contracts-body .ct-state{margin-left:auto;color:#66738c;font-size:11.5px;white-space:nowrap}
#view-contracts-body .ct-title{font-weight:700;font-size:16px;line-height:1.3;margin-bottom:8px}
#view-contracts-body .ct-meta{display:flex;gap:14px;flex-wrap:wrap;color:#93a0b8;font-size:12px}
#view-contracts-body .ct-meta span{display:flex;align-items:center;gap:5px}
#view-contracts-body .ct-meta svg{width:13px;height:13px;opacity:.7}
#view-contracts-body .ct-why{color:#22d9e6;font-size:11.5px;margin-top:9px}
#view-contracts-body .ct-gate{display:flex;align-items:center;gap:6px;color:#fbbf24;font-size:11.5px;margin-top:9px}
#view-contracts-body .ct-gate svg{width:13px;height:13px}
#view-contracts-body .ct-panel{background:#0e1524;border:1px solid rgba(255,255,255,.09);border-radius:15px;padding:14px}
#view-contracts-body .ct-wbar{display:flex;align-items:center;gap:10px;margin-bottom:9px}
#view-contracts-body .ct-wl{width:150px;flex:none;font-size:12.5px;color:#93a0b8}
#view-contracts-body .ct-wt{flex:1;height:8px;border-radius:99px;background:rgba(255,255,255,.08);overflow:hidden}
#view-contracts-body .ct-wt i{display:block;height:100%;background:#22d9e6;border-radius:99px}
#view-contracts-body .ct-wv{width:38px;text-align:right;font:700 12px ui-sans-serif;color:#eef2f9}
#view-contracts-body .ct-fg{margin-bottom:15px}
#view-contracts-body .ct-fg > label{display:block;font:700 11px ui-sans-serif;letter-spacing:.1em;
 text-transform:uppercase;color:#93a0b8;margin:0 0 7px}
#view-contracts-body .ct-fg input,#view-contracts-body .ct-fg select,#view-contracts-body .ct-fg textarea{
 width:100%;background:#0e1524;border:1px solid rgba(255,255,255,.09);color:#eef2f9;border-radius:11px;
 padding:0 13px;height:46px;font-size:14px;font-family:inherit}
#view-contracts-body .ct-fg textarea{min-height:96px;padding:12px 13px;resize:vertical;line-height:1.5}
#view-contracts-body .ct-fg input:focus,#view-contracts-body .ct-fg select:focus,#view-contracts-body .ct-fg textarea:focus{outline:0;border-color:#22d9e6}
#view-contracts-body .ct-kinds{display:grid;grid-template-columns:1fr;gap:8px}
@media(min-width:620px){#view-contracts-body .ct-kinds{grid-template-columns:1fr 1fr}}
#view-contracts-body .ct-kp{background:#0e1524;border:1px solid rgba(255,255,255,.09);border-radius:12px;padding:12px 13px;
 cursor:pointer;text-align:left;color:#eef2f9;font-family:inherit}
#view-contracts-body .ct-kp.on{border-color:#22d9e6;background:rgba(34,217,230,.07)}
#view-contracts-body .ct-kp b{display:block;font-size:14px;margin-bottom:3px}
#view-contracts-body .ct-kp span{color:#93a0b8;font-size:11.5px;line-height:1.4}
#view-contracts-body .ct-seg{display:flex;gap:5px;background:#0e1524;border:1px solid rgba(255,255,255,.09);border-radius:13px;padding:4px}
#view-contracts-body .ct-seg button{flex:1;height:38px;border:0;background:transparent;color:#93a0b8;border-radius:10px;
 font:700 12.5px ui-sans-serif;cursor:pointer}
#view-contracts-body .ct-seg button.on{background:#22d9e6;color:#04070d}
#view-contracts-body .ct-cond{background:#0e1524;border:1px solid rgba(255,255,255,.09);border-radius:14px;padding:13px;margin-bottom:9px}
#view-contracts-body .ct-cond.yes{border-color:rgba(34,217,230,.35)}
#view-contracts-body .ct-cond.no{border-color:rgba(251,113,133,.3)}
#view-contracts-body .ct-cn{font-size:14px;font-weight:700;line-height:1.3;margin-bottom:4px;color:#eef2f9}
#view-contracts-body .ct-cx{color:#93a0b8;font-size:12.5px;line-height:1.5;margin-bottom:11px}
#view-contracts-body .ct-onet{color:#66738c;font-size:10.5px;font-family:ui-monospace,monospace;margin-top:9px}
#view-contracts-body .ct-pref{display:flex;gap:6px}
#view-contracts-body .ct-pref button{flex:1;min-height:44px;border:1px solid rgba(255,255,255,.09);background:transparent;
 color:#93a0b8;border-radius:11px;font:700 11.5px ui-sans-serif;cursor:pointer;padding:6px 5px;line-height:1.3}
#view-contracts-body .ct-pref button.on{background:rgba(34,217,230,.14);border-color:#22d9e6;color:#22d9e6}
#view-contracts-body .ct-pref button.ct-no.on{background:rgba(251,113,133,.13);border-color:#fb7185;color:#fb7185}
#view-contracts-body .ct-pills{display:flex;flex-wrap:wrap;gap:7px}
#view-contracts-body .ct-pills button,#view-contracts-body .ct-pills span{border:1px solid rgba(255,255,255,.09);
 background:#0e1524;color:#93a0b8;border-radius:99px;padding:8px 13px;font:600 12px ui-sans-serif;cursor:pointer}
#view-contracts-body .ct-pills button.on{background:rgba(34,217,230,.12);border-color:#22d9e6;color:#22d9e6}
#view-contracts-body .ct-pills.read span{cursor:default;font-size:11.5px}
#view-contracts-body .ct-pills.read span.ok{border-color:rgba(74,222,128,.35);color:#4ade80}
#view-contracts-body .ct-pills.read span.clash{border-color:rgba(251,113,133,.3);color:#fb7185}
#view-contracts-body .ct-actions{display:flex;gap:8px;flex-wrap:wrap;margin:16px 0}
#view-contracts-body .ct-btn{flex:1;min-width:150px;background:#22d9e6;border:0;color:#04070d;border-radius:12px;
 height:50px;font:800 14px ui-sans-serif;cursor:pointer}
#view-contracts-body .ct-btn.sm{flex:none;min-width:0;height:38px;padding:0 16px;font-size:12px}
#view-contracts-body .ct-btn.ghost{background:transparent;border:1px solid rgba(255,255,255,.17);color:#eef2f9;text-transform:capitalize}
#view-contracts-body .ct-btn:disabled{opacity:.4;cursor:not-allowed}
#view-contracts-body .ct-sheet{display:flex;flex-direction:column;flex:1;min-height:0}
#view-contracts-body .ct-shead{position:sticky;top:0;z-index:5;flex:none;display:flex;align-items:center;gap:10px;padding:11px 14px;
 background:#080b14;border-bottom:1px solid rgba(255,255,255,.09);color:#eef2f9}
#view-contracts-body .ct-icon{width:38px;height:38px;flex:none;border-radius:11px;background:#0e1524;
 border:1px solid rgba(255,255,255,.09);color:#93a0b8;display:flex;align-items:center;justify-content:center;cursor:pointer}
#view-contracts-body .ct-icon svg{width:17px;height:17px}
#view-contracts-body .ct-sbody{padding:16px 14px 90px;max-width:820px;margin:0 auto;width:100%}
#view-contracts-body .ct-dt{font:800 22px/1.25 ui-sans-serif;letter-spacing:-.3px;margin:6px 0 12px;color:#eef2f9}
#view-contracts-body .ct-locbox{background:#0e1524;border:1px solid rgba(255,255,255,.09);border-radius:13px;
 padding:12px 13px;font-size:14px;font-weight:700;display:flex;flex-wrap:wrap;align-items:center;gap:7px;color:#eef2f9}
#view-contracts-body .ct-locbox svg{width:15px;height:15px;color:#93a0b8}
#view-contracts-body .ct-locbox .ct-hint{width:100%;font-weight:400}
#view-contracts-body .ct-prose{color:#eef2f9;font-size:14px;line-height:1.65;opacity:.92;white-space:pre-wrap}
#view-contracts-body .ct-facts{background:#0e1524;border:1px solid rgba(255,255,255,.09);border-radius:14px;overflow:hidden}
#view-contracts-body .ct-fact{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;
 border-bottom:1px solid rgba(255,255,255,.09);font-size:13.5px}
#view-contracts-body .ct-fact:last-child{border-bottom:0}
#view-contracts-body .ct-fact span{color:#93a0b8}
#view-contracts-body .ct-fact b{text-align:right;color:#eef2f9}
#view-contracts-body .ct-appl{display:flex;align-items:center;gap:11px;background:#0e1524;
 border:1px solid rgba(255,255,255,.09);border-radius:13px;padding:12px;margin-bottom:9px;color:#eef2f9}
#view-contracts-body .ct-appl > div{flex:1;min-width:0}

/* ══ v9.10.752 — A PLATFORM WITH NOTHING ON IT IS STILL A PLATFORM ═══════════
   Two complaints, one root: the board was a 820px column of sentences in the
   middle of a black screen, and with no postings it said "Nothing open yet" and
   stopped. A person cannot judge a place that shows them nothing, so the empty
   state now carries the template - example cards, the anatomy of a posting, and
   the lifecycle - and the board itself widens into a grid instead of stacking
   one card per screen-width. */
#view-contracts-body .ct-body{max-width:1180px}
#view-contracts-body .ct-sbody{max-width:920px}
#view-contracts-body .ct-grid{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:760px){#view-contracts-body .ct-grid{grid-template-columns:1fr 1fr}}
@media(min-width:1120px){#view-contracts-body .ct-grid{grid-template-columns:1fr 1fr 1fr}}
#view-contracts-body .ct-grid .ct-card{margin:0;height:100%}
#view-contracts-body .ct-blank{background:linear-gradient(180deg,rgba(34,217,230,.07),rgba(34,217,230,0));
 border:1px solid rgba(34,217,230,.22);border-radius:18px;padding:22px 20px;margin-bottom:6px}
#view-contracts-body .ct-blank-h{font:800 19px/1.3 ui-sans-serif;letter-spacing:-.2px;color:#eef2f9;margin-bottom:9px}
#view-contracts-body .ct-blank-p{color:#93a0b8;font-size:13.5px;line-height:1.7;margin:0;max-width:70ch}
#view-contracts-body .ct-demo{opacity:.72;cursor:default;border-style:dashed}
#view-contracts-body .ct-demo:hover{border-color:rgba(255,255,255,.09)}
#view-contracts-body .ct-tagx{font:700 9.5px ui-monospace,monospace;letter-spacing:.14em;text-transform:uppercase;
 color:#fbbf24;border:1px solid rgba(251,191,36,.4);border-radius:99px;padding:3px 8px}
#view-contracts-body .ct-anat{background:#0e1524;border:1px solid rgba(255,255,255,.09);border-radius:15px;overflow:hidden}
#view-contracts-body .ct-anat-row{display:grid;grid-template-columns:1fr;gap:3px;padding:13px 15px;
 border-bottom:1px solid rgba(255,255,255,.07)}
@media(min-width:700px){#view-contracts-body .ct-anat-row{grid-template-columns:210px 1fr;gap:16px;align-items:baseline}}
#view-contracts-body .ct-anat-row:last-child{border-bottom:0}
#view-contracts-body .ct-anat-row b{color:#22d9e6;font-size:13px}
#view-contracts-body .ct-anat-row span{color:#93a0b8;font-size:12.5px;line-height:1.6}
#view-contracts-body .ct-flow{display:grid;grid-template-columns:1fr;gap:8px;margin:16px 0 4px}
@media(min-width:640px){#view-contracts-body .ct-flow{grid-template-columns:1fr 1fr}}
@media(min-width:1000px){#view-contracts-body .ct-flow{grid-template-columns:repeat(4,1fr)}}
#view-contracts-body .ct-flow-s{background:rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.08);
 border-radius:12px;padding:11px 12px}
#view-contracts-body .ct-flow-s i{display:inline-flex;align-items:center;justify-content:center;width:19px;height:19px;
 border-radius:50%;background:rgba(34,217,230,.15);color:#22d9e6;font:800 10.5px ui-monospace,monospace;
 font-style:normal;margin-bottom:6px}
#view-contracts-body .ct-flow-s b{display:block;font-size:13px;color:#eef2f9;margin-bottom:2px}
#view-contracts-body .ct-flow-s span{color:#66738c;font-size:11.5px;line-height:1.5}
#view-contracts-body .ct-chips{display:flex;flex-wrap:wrap;gap:7px;margin-top:9px}
#view-contracts-body .ct-chips button{border:1px solid #22d9e6;background:rgba(34,217,230,.12);color:#22d9e6;
 border-radius:99px;padding:8px 13px;font:600 12px ui-sans-serif;cursor:pointer}
#view-contracts-body .ct-chips button:hover{background:rgba(251,113,133,.14);border-color:#fb7185;color:#fb7185}
#view-contracts-body .ct-addrow{margin-top:9px}
#view-contracts-body .ct-addrow input,#view-contracts-body .ct-row input{flex:1;min-width:0;background:#0e1524;
 border:1px solid rgba(255,255,255,.09);color:#eef2f9;border-radius:11px;padding:0 13px;height:46px;
 font-size:14px;font-family:inherit}
#view-contracts-body .ct-addrow input:focus{outline:0;border-color:#22d9e6}
#view-contracts-body .ct-btn.ct-ghost{flex:0 0 auto;min-width:0;padding:0 18px;height:46px;background:transparent;
 border:1px solid rgba(255,255,255,.17);color:#eef2f9;font-size:13px}
#view-contracts-body .ct-btn.ct-ghost:hover{border-color:#22d9e6;color:#22d9e6}
#view-contracts-body .ct-blank .ct-actions .ct-btn{flex:0 0 auto;min-width:0;padding:0 24px;height:48px}
#view-contracts-body .ct-blank .ct-actions .ct-btn.ct-ghost{height:48px}
/* An input the width of the page reads as "write an essay here". It takes a
   trade name and a card name; size it like one. */
#view-contracts-body .ct-addrow{max-width:540px}

/* ══ THE DOOR — Hash Hangman + hiding Contracts until it is found (v9.10.741) ═
   The nav entries are hidden rather than removed, so the moment the server says
   the door is open they appear without a reload. */
body:not(.ct-unlocked) .rail-btn[data-view="contracts"],
body:not(.ct-unlocked) .nav-item[data-view="contracts"],
body:not(.ct-unlocked) .m-tab[data-view="contracts"]{display:none !important}
.hh-wrap{position:fixed;inset:0;z-index:9000;display:flex;align-items:center;justify-content:center;
 padding:18px;background:rgba(4,7,13,.86);backdrop-filter:blur(10px);animation:hhIn .22s ease}
@keyframes hhIn{from{opacity:0}to{opacity:1}}
.hh-card{width:100%;max-width:520px;max-height:92vh;overflow-y:auto;background:#0e1524;
 border:1px solid rgba(255,255,255,.17);border-radius:20px;padding:22px 20px;
 box-shadow:0 30px 80px rgba(0,0,0,.6);color:#eef2f9;text-align:center}
.hh-lead{font:700 10.5px ui-monospace;letter-spacing:.16em;text-transform:uppercase;color:#fbbf24;margin-bottom:12px}
.hh-title{font:800 25px ui-sans-serif;letter-spacing:-.5px;margin-bottom:8px}
.hh-sub{color:#93a0b8;font-size:13px;line-height:1.6;margin-bottom:16px}
.hh-sub b{color:#22d9e6}
.hh-hash{font-family:ui-monospace,monospace;font-size:11px;line-height:1.7;color:#66738c;word-break:break-all;
 background:rgba(0,0,0,.35);border:1px solid rgba(255,255,255,.09);border-radius:11px;padding:10px 12px;margin-bottom:18px}
.hh-mask{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-bottom:16px}
.hh-slot{width:30px;height:38px;border-bottom:3px solid rgba(255,255,255,.22);display:flex;align-items:center;
 justify-content:center;font:800 20px ui-sans-serif;color:#eef2f9}
.hh-slot.on{border-bottom-color:#22d9e6;color:#22d9e6}
.hh-lives{display:flex;align-items:center;gap:6px;justify-content:center;margin-bottom:16px}
.hh-lives i{width:9px;height:9px;border-radius:50%;background:rgba(255,255,255,.15);display:block}
.hh-lives i.on{background:#fb7185}
.hh-lives span{color:#66738c;font-size:11.5px;margin-left:7px}
.hh-keys{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;margin-bottom:16px}
@media(max-width:420px){.hh-keys{grid-template-columns:repeat(6,1fr)}}
.hh-keys button{height:42px;border-radius:10px;border:1px solid rgba(255,255,255,.12);background:#131c30;
 color:#eef2f9;font:700 14px ui-sans-serif;cursor:pointer}
.hh-keys button:hover:not(:disabled){border-color:#22d9e6}
.hh-keys button.hit{background:rgba(34,217,230,.16);border-color:#22d9e6;color:#22d9e6}
.hh-keys button.miss{opacity:.3}
.hh-keys button:disabled{cursor:default}
.hh-foot{display:flex;justify-content:center}
.hh-foot2{display:flex;gap:9px;margin-top:18px}
.hh-x{background:transparent;border:1px solid rgba(255,255,255,.17);color:#93a0b8;border-radius:11px;
 height:44px;padding:0 18px;font:700 12.5px ui-sans-serif;cursor:pointer}
.hh-go{flex:1;background:#22d9e6;border:0;color:#04070d;border-radius:11px;height:44px;
 font:800 13.5px ui-sans-serif;cursor:pointer}
.hh-word{font:800 30px ui-monospace;letter-spacing:.16em;color:#22d9e6;margin:6px 0 14px}
.hh-verify{font-family:ui-monospace,monospace;font-size:11px;color:#66738c;line-height:1.7;margin-top:12px;
 background:rgba(0,0,0,.3);border-radius:10px;padding:9px 11px;word-break:break-all}
.hh-load{color:#93a0b8;font-size:13px;padding:26px 0}
.hh-won .hh-title{color:#4ade80}
.hh-lost .hh-title{color:#fb7185}

/* v9.10.751 - the puzzle explains itself. Everything below exists because a
   first-timer could not tell what the hash, the blanks or the dots were for. */
.hh-stake{color:#c8d2e4;font-size:13.5px;line-height:1.6;margin-bottom:14px}
.hh-how{text-align:left;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.09);
 border-radius:13px;padding:12px 14px 12px 4px;margin-bottom:16px}
.hh-how-t{font:700 10px ui-monospace,monospace;letter-spacing:.16em;text-transform:uppercase;
 color:#22d9e6;margin:0 0 8px 14px}
.hh-how ol{margin:0;padding-left:30px;color:#93a0b8;font-size:12.5px;line-height:1.6}
.hh-how li{margin-bottom:5px;padding-left:2px}
.hh-how li:last-child{margin-bottom:0}
.hh-tip{color:#66738c;font-size:11.5px;line-height:1.6;margin-bottom:14px}
.hh-cap{color:#66738c;font-size:11.5px;margin:-9px 0 15px}
.hh-theme{color:#93a0b8;font-size:12.5px;line-height:1.6;margin-bottom:16px}
.hh-theme b{color:#fbbf24}
.hh-slot.given{border-bottom-style:dashed}
.hh-why{text-align:left;margin-bottom:4px}
.hh-hash-lab{font:700 10px ui-monospace,monospace;letter-spacing:.16em;text-transform:uppercase;
 color:#66738c;margin-bottom:7px}
.hh-why .hh-hash{margin-bottom:8px;text-align:center}
.hh-note{color:#66738c;font-size:11.5px;line-height:1.6}
.hh-lost .hh-word{color:#fb7185}

/* v9.10.744 — post-form rows added during the pre-flight pass */
#view-contracts-body .ct-two{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media(max-width:520px){#view-contracts-body .ct-two{grid-template-columns:1fr}}
#view-contracts-body .ct-row{display:flex;gap:8px}
#view-contracts-body .ct-row input{flex:1;min-width:0}
#view-contracts-body .ct-row select{flex:0 0 108px}
#view-contracts-body .ct-unit{align-self:center;color:#93a0b8;font-size:13px}

/* v9.10.750 — Hash Hangman OWNER-ONLY quick-launch button (mobile tap entry).
   Hidden for everyone by default; shown only for the OWNER (server-driven
   body.scope-owner, set by applyScope() from me.role==='owner') while the Game
   Center is open. Non-owners never receive scope-owner, so this never renders
   for them and the Easter egg stays fully intact. */
#hh-owner-fab{display:none;position:fixed;right:16px;bottom:18px;z-index:8800;
 flex-direction:column;align-items:flex-start;gap:2px;cursor:pointer;
 padding:9px 14px;border-radius:14px;background:#0e1524;border:1px solid #22d9e6;
 box-shadow:0 10px 30px rgba(0,0,0,.5);color:#eef2f9;user-select:none;
 -webkit-tap-highlight-color:transparent}
body.scope-owner[data-view="games"] #hh-owner-fab{display:inline-flex}
#hh-owner-fab:active{transform:translateY(1px)}
#hh-owner-fab .hhf-top{font:800 13px ui-sans-serif;letter-spacing:-.2px;color:#22d9e6}
#hh-owner-fab .hhf-sub{font:600 10.5px ui-monospace;letter-spacing:.02em;color:#93a0b8}
/* mobile: lift above the bottom tab/nav bar (both twins kept in sync) */
@media(max-width:900px){ #hh-owner-fab{right:12px;bottom:74px} }
body.force-mobile #hh-owner-fab{right:12px;bottom:74px}

/* ══ v9.10.755 — THE POST ACTION ROW NEVER WENT MOBILE ══════════════════════
   "its also hard for Users to post and view posts likes comments and the
   others ... on mobile also is bugged."

   `@media(max-width:900px)` at line 3012 has always said the right thing for a
   phone: `font-size:0` so the row is icons, `gap:0`, `padding:12px 10px`,
   `min-height:44px;min-width:44px` so every control is a real touch target.
   None of it has ever applied. Three hundred lines LATER, at line 6331 and
   again at 6491, `.gpost-acts button` is declared at TOP LEVEL with
   `font-size:12px !important` and `padding:0 10px !important`. `!important`
   beats a media query at any width, so on a 390px phone the row renders six
   labelled controls - Like, Comment, Repost, Share and two icon buttons - in
   344px of card. MEASURED: computed font-size 12px at 390px, 430px and 1400px
   alike, widest button 64px, the labels colliding with the next icon.

   THIS ALSO CORRECTS A DIAGNOSIS IN THE CODEBASE. The note at
   oracle-core.js:12128 reasons from the same symptom - "the post actions still
   showing their TEXT labels - and `.gpost-acts button{font-size:0}` only
   applies under 900px" - to the conclusion that the layout viewport must have
   been wider than 900 CSS px, and `_vmFitGuard()` was built on that inference.
   The labels show at EVERY width. No viewport anomaly was ever required.
   _vmFitGuard is left alone: it is a reasonable guard on its own terms, it only
   ever moves in the safe direction, and it is not what this bug was.

   Appended rather than edited in place, as this sheet requires. Same
   specificity as the rules it corrects, both !important, and LAST in the file -
   so it wins on order, which is the only lever left once everything is
   !important. Deliberately unprefixed: there is no `#app` in oracle.html (the
   wrapper is `.shell`), and a prefix that does not match is a fix that silently
   does nothing. */
@media (max-width:900px){
  .gpost-acts, body.force-mobile .gpost-acts{
    gap:6px !important; padding:6px 0 2px !important;
    display:flex !important; flex-wrap:nowrap !important; align-items:center !important;
  }
  /* Icons only. `font-size:0` hides the label visually and keeps it in the
     accessibility tree, which is why it is the right tool here and `display:none`
     on the text would not be. */
  .gpost-acts button, body.force-mobile .gpost-acts button{
    font-size:0 !important; gap:0 !important;
    height:auto !important; min-height:44px !important; min-width:44px !important;
    padding:0 !important; border-radius:10px !important;
    flex:1 1 0 !important;
  }
  .gpost-acts button svg, body.force-mobile .gpost-acts button svg{
    width:21px !important; height:21px !important;
  }
  /* The two utility buttons are a fixed pair, not part of the four-way split. */
  .gpost-acts .gpa-util, body.force-mobile .gpost-acts .gpa-util{
    display:flex !important; gap:2px !important; flex:0 0 auto !important;
  }
  .gpost-acts .gpa-util button, body.force-mobile .gpost-acts .gpa-util button{
    flex:0 0 44px !important; min-width:44px !important;
  }
  .gpost-acts .gpx-wrap, body.force-mobile .gpost-acts .gpx-wrap{
    flex:1 1 0 !important; display:flex !important;
  }
  .gpost-acts .gpx-wrap > button, body.force-mobile .gpost-acts .gpx-wrap > button{
    flex:1 1 auto !important;
  }
}

/* The same override buried eleven other deliberate mobile choices. A sheet-wide
   scan (parse every declaration, note its @media context and !important flag,
   then look for a mobile rule beaten by a LATER top-level !important of the same
   selector and property) found twelve pairs. Most were no-ops - the same value
   declared twice - and the action row above was the one that broke a feature.
   These four are the rest of the ones that change anything: a phone was meant to
   get larger, looser post text and a tighter card, and has been getting the
   desktop values since the !important block landed. */
@media (max-width:900px){
  .gpost, body.force-mobile .gpost{
    padding:14px 14px !important; margin-bottom:8px !important;
  }
  .gpost-text, body.force-mobile .gpost-text{
    font-size:15px !important; line-height:1.6 !important;
  }
}

/* ══ v9.10.756 — POSTING SHOULD NOT BE AN EXAM ══════════════════════════════
   "the questions in post work area is weird and also very long questions for
   trying to post a thing."

   The questions were never long - 42 characters on average. There were 24 of
   them, each drawn as a card with three 44px buttons, then thirty credential
   pills, and only THEN the button that posts. The essentials now end with
   Create, and everything that only improves the match folds shut beneath it. */
#view-contracts-body .ct-kindrow{display:flex;flex-wrap:wrap;gap:6px}
#view-contracts-body .ct-kindrow button{flex:1 1 auto;min-width:92px;min-height:42px;padding:0 14px;
 border-radius:11px;border:1px solid rgba(255,255,255,.12);background:#0e1524;color:#93a0b8;
 font:700 12.5px ui-sans-serif;cursor:pointer}
#view-contracts-body .ct-kindrow button.on{background:rgba(34,217,230,.13);border-color:#22d9e6;color:#22d9e6}
#view-contracts-body .ct-fold{border:1px solid rgba(255,255,255,.09);border-radius:14px;margin-bottom:10px;
 background:rgba(255,255,255,.02);overflow:hidden}
#view-contracts-body .ct-fold-h{width:100%;display:flex;align-items:center;gap:10px;padding:14px 15px;
 background:transparent;border:0;color:#eef2f9;cursor:pointer;text-align:left;font-family:inherit;min-height:52px}
#view-contracts-body .ct-fold-h b{font:700 13.5px ui-sans-serif}
#view-contracts-body .ct-fold-h span{color:#66738c;font-size:11.5px;margin-left:auto}
#view-contracts-body .ct-fold-h i{font:700 16px ui-monospace,monospace;font-style:normal;color:#66738c;
 width:22px;height:22px;display:flex;align-items:center;justify-content:center;flex:none}
#view-contracts-body .ct-fold.open .ct-fold-h i{color:#22d9e6}
#view-contracts-body .ct-fold-b{padding:0 15px 15px}
/* One line per question. `min-height:44px` on the buttons keeps the touch
   target honest even though the row is half the height of the old card. */
#view-contracts-body .ct-crow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
 padding:9px 0;border-bottom:1px solid rgba(255,255,255,.06)}
#view-contracts-body .ct-crow:last-of-type{border-bottom:0}
#view-contracts-body .ct-crow-q{flex:1 1 190px;min-width:0;font-size:13px;line-height:1.45;color:#eef2f9}
#view-contracts-body .ct-crow-b{display:flex;gap:5px;flex:0 0 auto}
#view-contracts-body .ct-crow-b button{min-width:52px;min-height:38px;padding:0 10px;border-radius:9px;
 border:1px solid rgba(255,255,255,.1);background:transparent;color:#93a0b8;font:700 12px ui-sans-serif;cursor:pointer}
#view-contracts-body .ct-crow-b button.on{background:rgba(34,217,230,.14);border-color:#22d9e6;color:#22d9e6}
#view-contracts-body .ct-crow-b button.ct-no.on{background:rgba(251,113,133,.13);border-color:#fb7185;color:#fb7185}
@media (max-width:900px){
  #view-contracts-body .ct-crow-b button{min-height:44px;min-width:56px}
}

/* v9.10.757 — "Doesn't matter" is a longer word than "—" and needs the room.
   It replaces a middle button that said "Not really" while the matcher treated
   it as no answer at all. */
#view-contracts-body .ct-crow-b button.ct-skip{min-width:104px;color:#66738c}
#view-contracts-body .ct-crow-b button.ct-skip.on{background:rgba(255,255,255,.07);
 border-color:rgba(255,255,255,.28);color:#c8d2e4}
@media (max-width:900px){
  #view-contracts-body .ct-crow{gap:6px}
  #view-contracts-body .ct-crow-q{flex:1 1 100%}
  #view-contracts-body .ct-crow-b{width:100%}
  #view-contracts-body .ct-crow-b button{flex:1 1 auto}
  #view-contracts-body .ct-crow-b button.ct-skip{min-width:0;flex:1.6 1 auto}
}

/* ══ v9.10.762 — THE MOBILE INTENT, PUT BACK ════════════════════════════════
   `tools/audit/audit.mjs` check 3 found 26 declarations inside
   `@media(max-width:900px)` that a LATER top-level rule silently overrides at
   every width. Same disease as the post-action row (v9.10.755): the mobile
   block says one thing, a polish block appended three thousand lines later says
   another, and later-at-equal-specificity wins everywhere.

   Each was judged rather than bulk-reverted. Restored below are the ones where
   the phone was deliberately given tighter spacing and lost it. NOT restored,
   and recorded as reviewed in the audit's ACCEPTED list: the call self-PIP
   (`min(42vw,220px)` is a better rule than a fixed 100px), `.gc-card` padding
   and `.gc-pad` (a later redesign that meant it), and the 2px story-card
   height. Reverting those would undo real improvements. */
@media (max-width:900px){
  /* `.ghome-tabs{display:none}` is NOT restored, and this is the one I got
     wrong on the first pass. It looks like lost mobile intent and it is a stale
     rule: v9.10.374 relocated that strip INTO the topbar (see
     `#topbar-tabs-mount .ghome-tabs` around line 1752), and the later
     `display:flex` at ~1760 is what makes it work there. Restoring the hide
     would have blanked the tabs on every phone. Checked before shipping because
     "the mobile block said so" is not on its own a reason. */
  .gpost-stats{gap:8px !important;padding:8px 0 !important}
  .gcomposer-opt{padding:6px 10px !important}
  .gpost-composer{border-radius:12px !important;margin-bottom:0 !important;padding:12px 14px !important}
  .gcomp-text{min-height:40px !important}
  .gcomp-post-btn{padding:8px 20px !important}

  .gstories-row{gap:8px !important;padding:6px 4px 12px !important}
  .gstory-create-top{height:96px !important}
  .gstory-ring-av{width:30px !important;height:30px !important}

  /* the tab row has to fit five labels across ~360px */
  .gfeed-tabs{margin-bottom:0 !important}
  .gfeed-tabs button{padding:10px 8px !important}

  /* a square board on a phone is bounded by HEIGHT, not width */
  .gc-cc-b{width:min(100%, calc(100dvh - 300px)) !important}
}

/* ── the loading skeleton was a different size from the card ──────────────
   Not a mobile bug at all - this one is wrong at every width, and the audit
   found it while looking for something else. `.gstory-card` is pinned to
   92x148 with !important at line 6370; `.gstory-skel` was left on the original
   105x170, so every story row visibly jumps as it finishes loading. A skeleton
   whose only job is to hold the shape of the thing it stands in for must be
   the same size as that thing. */
.gstory-skel{ width:92px !important; height:148px !important; border-radius:12px !important; }

/* ── v9.10.762 — every top-pinned sticky bar holds its own height ─────────
   The Contracts tab bar was measured at 25px against its natural 61px because
   it was a flex item in a column flex container carrying the default
   `flex-shrink:1`, and a long page took the space (v9.10.753). These six are
   the same shape: full-width bars pinned to the top of a scroller, none of
   which should ever grow or shrink. `flex` is ignored entirely outside a flex
   container, so this is inert where the parent is not one and load-bearing
   where it is. */
.ghome-tabs,
.gprof-tabs,
.pf-tabs,
.gfeed-newbar,
#gfeed-ptr,
.gcbp .gcbp-meta.gcbp-meta-grid{ flex:none; }


/* ══════════════════════════════════════════════════════════════════════════════
   v9.10.872 — PHONE POWER BUDGET
   ══════════════════════════════════════════════════════════════════════════════
   MEASURED: Oracle OS burned ~0.31% of a phone battery per minute of screen
   time across two separate sessions (Aug 28: 21.6% / 68m. Aug 31: 27.1% / 90m).
   A comparable app on the same handset, same days, same dark theme, measured
   0.096 and 0.108. Three times the cost per minute, twice, independently.

   THE LARGEST ALWAYS-ON TERM WAS THIS FILE, not the JavaScript.

   `body[class*="theme-"]::after` is position:fixed, inset:0, height:200%, and
   every one of the ~18 themes hangs an `infinite` animation on it — th-rise,
   th-fall, th-drift, th-spin, th-breathe, th-sheen, th-flicker. That is a
   full-viewport layer animating at the display refresh rate, on every view,
   for the entire time the app is open, whether the user is reading a book or
   playing a game or looking at a static settings page.

   There are twenty-four `prefers-reduced-motion` blocks in this file. Not one
   of them covers that rule. It is the biggest animation in the app and it is
   the only one nobody gated — because it is a background, and backgrounds do
   not look like they cost anything.

   Three of the themes (gold, obsidian, prismatic) animate `background-position`,
   which is not compositor-accelerated: those repaint a full-screen fixed layer
   on every frame rather than just re-transforming it.

   WHAT THIS BLOCK DOES: on a real touch device — `(hover:none) and
   (pointer:coarse)`, which a desktop in force-mobile LAYOUT does not match —
   the theme keeps its colour, its gradient, its identity, and loses only the
   drift. At phone size the motion was several pixels a second across a
   two-screen-tall layer; it is close to invisible and it was never free.

   Desktop is deliberately untouched. So is every other animation in the file.
   ══════════════════════════════════════════════════════════════════════════════ */

@media (hover:none) and (pointer:coarse){
  body[class*="theme-"]::after{
    animation:none !important;
  }
  /* The parallax background stack is three fixed full-screen layers. On a touch
     device there is no pointer to parallax against, so `will-change:transform`
     is pinning a full-screen GPU texture for a transform that never runs, and
     `filter:blur()` forces an offscreen render pass to produce it. The photo
     and the vignette stay; only the machinery that cannot do anything here goes. */
  #app-bg{
    will-change:auto !important;
    filter:saturate(.92) !important;
    transition:none !important;
  }
  #app-bg-mid{
    will-change:auto !important;
    transition:none !important;
  }
}

/* Everyone, on every device, when the OS or the in-app switch asks for less
   motion. This is the gate the rule should have had from the day it was written. */
@media (prefers-reduced-motion:reduce){
  body[class*="theme-"]::after{ animation:none !important; }
}
body.reduce-motion[class*="theme-"]::after{ animation:none !important; }
