@@ -235,6 +239,9 @@ export function renderShell(opts: ShellOptions): string {
const infoPanel = document.getElementById('rapp-info-panel');
const infoBody = document.getElementById('rapp-info-body');
const infoClose = document.getElementById('rapp-info-close');
+ const infoOverlay = document.getElementById('rapp-info-overlay');
+ const infoIcon = document.getElementById('rapp-info-icon');
+ const infoTitle = document.getElementById('rapp-info-title');
if (!infoBtn || !infoPanel || !infoBody) return;
let infoPanelModuleId = '';
@@ -242,16 +249,20 @@ export function renderShell(opts: ShellOptions): string {
function showInfoPanel(moduleId) {
infoPanelModuleId = moduleId;
infoPanel.style.display = '';
+ if (infoOverlay) infoOverlay.style.display = '';
infoBtn.classList.add('rapp-info-btn--active');
// Lazy-load content
if (infoPanel.dataset.loadedModule !== moduleId) {
- infoBody.innerHTML = '
Loading…
';
+ infoBody.innerHTML = '
';
fetch('/api/modules/' + encodeURIComponent(moduleId) + '/landing')
.then(r => r.json())
.then(data => {
if (infoPanelModuleId !== moduleId) return; // stale
infoBody.innerHTML = data.html || '
No info available.
';
infoPanel.dataset.loadedModule = moduleId;
+ // Update header with module icon + name
+ if (infoIcon && data.icon) infoIcon.textContent = data.icon;
+ if (infoTitle && data.name) infoTitle.textContent = data.name;
})
.catch(() => { infoBody.innerHTML = '
Failed to load info.
'; });
}
@@ -259,9 +270,16 @@ export function renderShell(opts: ShellOptions): string {
function hideInfoPanel() {
infoPanel.style.display = 'none';
+ if (infoOverlay) infoOverlay.style.display = 'none';
infoBtn.classList.remove('rapp-info-btn--active');
}
+ // Click overlay to dismiss
+ if (infoOverlay) infoOverlay.addEventListener('click', hideInfoPanel);
+ document.addEventListener('keydown', (e) => {
+ if (e.key === 'Escape' && infoPanel.style.display !== 'none') hideInfoPanel();
+ });
+
infoBtn.addEventListener('click', () => {
if (infoPanel.style.display !== 'none') { hideInfoPanel(); return; }
// Resolve the currently active module from the tab bar
@@ -1096,6 +1114,7 @@ const WELCOME_CSS = `
`;
const INFO_PANEL_CSS = `
+/* ── Info button in tab bar ── */
.rapp-info-btn {
display: flex; align-items: center; justify-content: center;
width: 28px; height: 28px; padding: 0; margin-right: 2px;
@@ -1105,39 +1124,69 @@ const INFO_PANEL_CSS = `
}
.rapp-info-btn:hover { color: var(--rs-text-primary); background: var(--rs-bg-hover); border-color: var(--rs-border); }
.rapp-info-btn--active { color: var(--rs-primary); background: var(--rs-bg-hover); border-color: var(--rs-primary); }
+
+/* ── Backdrop overlay ── */
+.rapp-info-overlay {
+ position: fixed; inset: 0; z-index: 10000;
+ background: rgba(0,0,0,0.45);
+ backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
+ animation: rapp-overlay-in 0.2s ease-out;
+}
+@keyframes rapp-overlay-in { from { opacity: 0; } to { opacity: 1; } }
+
+/* ── Panel — centered modal ── */
.rapp-info-panel {
- position: fixed; top: 80px; right: 16px; z-index: 9000;
- width: min(480px, calc(100vw - 32px)); max-height: calc(100vh - 100px);
- background: var(--rs-bg-surface); border: 1px solid rgba(20,184,166,0.2);
- border-radius: 14px; box-shadow: 0 12px 48px rgba(0,0,0,0.5), 0 0 0 1px rgba(20,184,166,0.08);
+ position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
+ z-index: 10001;
+ width: min(520px, calc(100vw - 32px)); max-height: calc(100vh - 64px);
+ background: var(--rs-bg-surface);
+ border: 1px solid rgba(20,184,166,0.25);
+ border-radius: 16px;
+ box-shadow: 0 24px 80px rgba(0,0,0,0.6), 0 0 0 1px rgba(20,184,166,0.1), 0 0 60px rgba(20,184,166,0.06);
display: flex; flex-direction: column; overflow: hidden;
- animation: rapp-info-in 0.25s ease-out;
+ animation: rapp-info-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes rapp-info-in {
- from { opacity: 0; transform: translateY(-10px) scale(0.96); }
- to { opacity: 1; transform: translateY(0) scale(1); }
+ from { opacity: 0; transform: translate(-50%, -48%) scale(0.95); }
+ to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
+
+/* ── Header with icon + name ── */
.rapp-info-panel__header {
display: flex; align-items: center; justify-content: space-between;
- padding: 14px 18px;
- background: linear-gradient(135deg, rgba(20,184,166,0.1), rgba(79,70,229,0.08));
- border-bottom: 1px solid rgba(20,184,166,0.15);
+ padding: 16px 20px;
+ background: linear-gradient(135deg, rgba(20,184,166,0.12), rgba(79,70,229,0.08));
+ border-bottom: 1px solid rgba(20,184,166,0.18);
+}
+.rapp-info-panel__header-left {
+ display: flex; align-items: center; gap: 10px;
+}
+.rapp-info-panel__icon {
+ font-size: 1.5rem; line-height: 1;
}
.rapp-info-panel__title {
- font-size: 0.85rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
+ font-size: 1.05rem; font-weight: 700; letter-spacing: 0.01em;
background: linear-gradient(135deg, #14b8a6, #22d3ee);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
background-clip: text;
}
.rapp-info-panel__close {
- background: none; border: none; color: var(--rs-text-muted);
- font-size: 1.3rem; cursor: pointer; padding: 2px 6px; border-radius: 6px;
- line-height: 1; transition: color 0.15s, background 0.15s;
+ display: flex; align-items: center; justify-content: center;
+ width: 32px; height: 32px;
+ background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.08);
+ color: var(--rs-text-muted); font-size: 1.2rem; cursor: pointer;
+ border-radius: 8px; line-height: 1;
+ transition: color 0.15s, background 0.15s, border-color 0.15s;
}
-.rapp-info-panel__close:hover { color: var(--rs-text-primary); background: rgba(255,255,255,0.08); }
+.rapp-info-panel__close:hover {
+ color: var(--rs-text-primary); background: rgba(255,255,255,0.1);
+ border-color: rgba(255,255,255,0.15);
+}
+
+/* ── Body ── */
.rapp-info-panel__body {
padding: 0; overflow-y: auto; flex: 1;
- color: var(--rs-text-secondary); font-size: 0.88rem; line-height: 1.6;
+ color: var(--rs-text-secondary); font-size: 0.92rem; line-height: 1.65;
}
.rapp-info-panel__body h1, .rapp-info-panel__body h2, .rapp-info-panel__body h3 {
color: var(--rs-text-primary); margin: 0 0 8px;
@@ -1147,86 +1196,94 @@ const INFO_PANEL_CSS = `
.rapp-info-panel__body h3 { font-size: 0.95rem; }
.rapp-info-panel__body p { margin: 0 0 10px; }
.rapp-info-panel__body a { color: var(--rs-primary); }
+
+/* ── Loading state ── */
.rapp-info-panel__loading {
- display: flex; align-items: center; justify-content: center;
- padding: 32px; color: var(--rs-text-muted);
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
+ gap: 12px; padding: 48px 32px; color: var(--rs-text-muted);
}
+.rapp-info-panel__spinner {
+ width: 24px; height: 24px;
+ border: 2px solid rgba(20,184,166,0.2); border-top-color: #14b8a6;
+ border-radius: 50%; animation: rapp-spin 0.7s linear infinite;
+}
+@keyframes rapp-spin { to { transform: rotate(360deg); } }
/* ── Panel-scoped overrides for rich landing content ── */
-.rapp-info-panel__body .rl-hero {
- padding: 1.75rem 1.25rem 1.25rem; text-align: center;
-}
-.rapp-info-panel__body .rl-hero .rl-heading {
- font-size: 1.5rem !important;
-}
-.rapp-info-panel__body .rl-heading {
- font-size: 1.2rem; margin-bottom: 0.5rem;
-}
-.rapp-info-panel__body .rl-tagline {
- font-size: 0.6rem; padding: 0.25rem 0.75rem; margin-bottom: 1rem;
-}
-.rapp-info-panel__body .rl-subtitle {
- font-size: 1rem !important; margin-bottom: 0.75rem;
-}
-.rapp-info-panel__body .rl-subtext {
- font-size: 0.88rem !important; margin-bottom: 1.25rem;
-}
+.rapp-info-panel__body .rl-hero { padding: 1.75rem 1.5rem 1.25rem; text-align: center; }
+.rapp-info-panel__body .rl-hero .rl-heading { font-size: 1.5rem !important; }
+.rapp-info-panel__body .rl-heading { font-size: 1.2rem; margin-bottom: 0.5rem; }
+.rapp-info-panel__body .rl-tagline { font-size: 0.65rem; padding: 0.3rem 0.85rem; margin-bottom: 1rem; }
+.rapp-info-panel__body .rl-subtitle { font-size: 1rem !important; margin-bottom: 0.75rem; }
+.rapp-info-panel__body .rl-subtext { font-size: 0.9rem !important; margin-bottom: 1.25rem; line-height: 1.7; }
.rapp-info-panel__body .rl-hero .rl-subtext { font-size: 0.92rem !important; }
-.rapp-info-panel__body .rl-section {
- padding: 1.5rem 1.25rem; border-top: 1px solid var(--rs-border-subtle);
-}
-.rapp-info-panel__body .rl-section--alt {
- background: rgba(20,184,166,0.03);
-}
+.rapp-info-panel__body .rl-section { padding: 1.5rem 1.25rem; border-top: 1px solid var(--rs-border-subtle); }
+.rapp-info-panel__body .rl-section--alt { background: rgba(20,184,166,0.03); }
.rapp-info-panel__body .rl-container { max-width: 100%; }
/* Grids: max 2 columns in panel */
.rapp-info-panel__body .rl-grid-2,
.rapp-info-panel__body .rl-grid-3,
-.rapp-info-panel__body .rl-grid-4 {
- grid-template-columns: 1fr 1fr !important; gap: 0.75rem;
-}
+.rapp-info-panel__body .rl-grid-4 { grid-template-columns: 1fr 1fr !important; gap: 0.75rem; }
/* Cards */
-.rapp-info-panel__body .rl-card {
- padding: 1.15rem; border-radius: 0.75rem;
-}
-.rapp-info-panel__body .rl-card h3 { font-size: 0.85rem; margin-bottom: 0.35rem; }
-.rapp-info-panel__body .rl-card p { font-size: 0.8rem; line-height: 1.5; margin-bottom: 0; }
+.rapp-info-panel__body .rl-card { padding: 1.15rem; border-radius: 0.75rem; }
+.rapp-info-panel__body .rl-card h3 { font-size: 0.88rem; margin-bottom: 0.35rem; }
+.rapp-info-panel__body .rl-card p { font-size: 0.82rem; line-height: 1.55; margin-bottom: 0; }
/* Icon boxes */
-.rapp-info-panel__body .rl-icon-box {
- width: 2.25rem; height: 2.25rem; font-size: 1.15rem;
- border-radius: 0.5rem; margin-bottom: 0.65rem;
-}
+.rapp-info-panel__body .rl-icon-box { width: 2.5rem; height: 2.5rem; font-size: 1.25rem; border-radius: 0.6rem; margin-bottom: 0.65rem; }
.rapp-info-panel__body .rl-card--center .rl-icon-box { margin: 0 auto 0.65rem; }
/* Steps */
-.rapp-info-panel__body .rl-step__num {
- width: 2rem; height: 2rem; font-size: 0.7rem; margin-bottom: 0.5rem;
-}
-.rapp-info-panel__body .rl-step h3 { font-size: 0.85rem; }
-.rapp-info-panel__body .rl-step p { font-size: 0.78rem; }
+.rapp-info-panel__body .rl-step__num { width: 2.25rem; height: 2.25rem; font-size: 0.75rem; margin-bottom: 0.5rem; }
+.rapp-info-panel__body .rl-step h3 { font-size: 0.88rem; }
+.rapp-info-panel__body .rl-step p { font-size: 0.82rem; }
-/* CTAs */
-.rapp-info-panel__body .rl-cta-row { margin-top: 1.25rem; gap: 0.5rem; }
-.rapp-info-panel__body .rl-cta-primary,
+/* CTAs — bigger, bolder buttons */
+.rapp-info-panel__body .rl-cta-row { margin-top: 1.5rem; gap: 0.625rem; display: flex; flex-wrap: wrap; justify-content: center; }
+.rapp-info-panel__body .rl-cta-primary {
+ padding: 0.75rem 1.5rem; font-size: 0.92rem; font-weight: 600;
+ border-radius: 10px; text-decoration: none;
+ background: var(--rs-gradient-cta, linear-gradient(135deg, #14b8a6, #06b6d4));
+ color: #fff; box-shadow: 0 4px 16px rgba(20,184,166,0.3);
+ transition: transform 0.15s, box-shadow 0.15s;
+}
+.rapp-info-panel__body .rl-cta-primary:hover { transform: translateY(-1px); box-shadow: 0 6px 24px rgba(20,184,166,0.4); }
.rapp-info-panel__body .rl-cta-secondary {
- padding: 0.6rem 1.25rem; font-size: 0.85rem; border-radius: 0.5rem;
+ padding: 0.75rem 1.5rem; font-size: 0.92rem; font-weight: 600;
+ border-radius: 10px; text-decoration: none;
+ background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.12);
+ color: var(--rs-text-secondary); transition: transform 0.15s, border-color 0.15s, color 0.15s, background 0.15s;
+}
+.rapp-info-panel__body .rl-cta-secondary:hover { transform: translateY(-1px); border-color: rgba(20,184,166,0.4); color: var(--rs-text-primary); background: rgba(20,184,166,0.08); }
+
+/* Tour / guide links — promote to prominent buttons */
+.rapp-info-panel__body a[onclick*="startTour"],
+.rapp-info-panel__body a[href*="tour"] {
+ display: inline-flex; align-items: center; gap: 6px;
+ padding: 0.65rem 1.35rem; margin-top: 0.75rem;
+ font-size: 0.92rem; font-weight: 600; text-decoration: none;
+ background: linear-gradient(135deg, rgba(79,70,229,0.15), rgba(20,184,166,0.1));
+ border: 1px solid rgba(79,70,229,0.25); border-radius: 10px; color: #a78bfa;
+ transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.15s;
+}
+.rapp-info-panel__body a[onclick*="startTour"]:hover,
+.rapp-info-panel__body a[href*="tour"]:hover {
+ background: linear-gradient(135deg, rgba(79,70,229,0.25), rgba(20,184,166,0.15));
+ border-color: rgba(79,70,229,0.4); color: #c4b5fd; transform: translateY(-1px);
}
/* Badges */
-.rapp-info-panel__body .rl-badge { font-size: 0.6rem; padding: 0.12rem 0.45rem; }
+.rapp-info-panel__body .rl-badge { font-size: 0.65rem; padding: 0.15rem 0.5rem; }
/* Integration cards */
-.rapp-info-panel__body .rl-integration {
- padding: 1rem; border-radius: 0.75rem; gap: 0.75rem;
-}
-.rapp-info-panel__body .rl-integration h3 { font-size: 0.85rem; }
-.rapp-info-panel__body .rl-integration p { font-size: 0.8rem; }
+.rapp-info-panel__body .rl-integration { padding: 1rem; border-radius: 0.75rem; gap: 0.75rem; }
+.rapp-info-panel__body .rl-integration h3 { font-size: 0.88rem; }
+.rapp-info-panel__body .rl-integration p { font-size: 0.82rem; }
/* Check list */
-.rapp-info-panel__body .rl-check-list li { font-size: 0.8rem; padding: 0.25rem 0; }
+.rapp-info-panel__body .rl-check-list li { font-size: 0.82rem; padding: 0.3rem 0; }
/* Divider */
.rapp-info-panel__body .rl-divider { margin: 1rem 0; }
@@ -1234,23 +1291,27 @@ const INFO_PANEL_CSS = `
/* Back link */
.rapp-info-panel__body .rl-back { padding: 1.25rem 0 1.5rem; }
-.rapp-info-panel__body .rl-back a { font-size: 0.8rem; }
+.rapp-info-panel__body .rl-back a { font-size: 0.82rem; }
/* Scrollbar styling */
.rapp-info-panel__body::-webkit-scrollbar { width: 5px; }
.rapp-info-panel__body::-webkit-scrollbar-track { background: transparent; }
-.rapp-info-panel__body::-webkit-scrollbar-thumb {
- background: rgba(20,184,166,0.2); border-radius: 9999px;
-}
+.rapp-info-panel__body::-webkit-scrollbar-thumb { background: rgba(20,184,166,0.2); border-radius: 9999px; }
.rapp-info-panel__body::-webkit-scrollbar-thumb:hover { background: rgba(20,184,166,0.35); }
@media (max-width: 600px) {
- .rapp-info-panel { right: 8px; left: 8px; width: auto; top: 70px; }
+ .rapp-info-panel {
+ top: auto; left: 8px; right: 8px; bottom: 8px;
+ transform: none; width: auto; max-height: 85vh;
+ animation: rapp-info-in-mobile 0.3s cubic-bezier(0.16, 1, 0.3, 1);
+ }
+ @keyframes rapp-info-in-mobile {
+ from { opacity: 0; transform: translateY(20px); }
+ to { opacity: 1; transform: translateY(0); }
+ }
.rapp-info-panel__body .rl-grid-2,
.rapp-info-panel__body .rl-grid-3,
- .rapp-info-panel__body .rl-grid-4 {
- grid-template-columns: 1fr !important;
- }
+ .rapp-info-panel__body .rl-grid-4 { grid-template-columns: 1fr !important; }
}
`;
@@ -1260,7 +1321,7 @@ const SUBNAV_CSS = `
.rapp-subnav {
display: flex;
gap: 0.375rem;
- padding: 0.375rem 1rem;
+ padding: 0.5rem 1rem;
overflow-x: auto;
border-bottom: 1px solid var(--rs-border);
background: var(--rs-bg-surface);
@@ -1268,6 +1329,7 @@ const SUBNAV_CSS = `
position: sticky;
top: 92px;
z-index: 100;
+ margin-bottom: 4px;
}
.rapp-subnav::-webkit-scrollbar { display: none; }
@media (max-width: 640px) {