diff --git a/static/world/index.html b/static/world/index.html
index d10f8663..9456d9dd 100644
--- a/static/world/index.html
+++ b/static/world/index.html
@@ -20,11 +20,76 @@
+
+
+
+
+
@@ -119,6 +184,50 @@
});
stateReader.connect();
+ // --- Fund Session Modal ---
+ const fundBtn = document.getElementById("fund-btn");
+ const fundModal = document.getElementById("fund-modal");
+ const fundClose = document.getElementById("fund-close");
+ const fundBackdrop = document.getElementById("fund-backdrop");
+ const fundSubmit = document.getElementById("fund-submit");
+ const fundAmount = document.getElementById("fund-amount");
+
+ function openFundModal() {
+ fundModal.classList.add("open");
+ document.body.style.overflow = "hidden";
+ // Focus the input when opening
+ setTimeout(() => fundAmount.focus(), 100);
+ }
+
+ function closeFundModal() {
+ fundModal.classList.remove("open");
+ document.body.style.overflow = "";
+ }
+
+ function handleFundSubmit() {
+ const amount = parseInt(fundAmount.value, 10);
+ if (!amount || amount < 100) {
+ alert("Please enter a valid amount (minimum 100 sats)");
+ return;
+ }
+ // TODO: Integrate with Lightning payment API
+ console.log("Funding session with", amount, "sats");
+ alert("Lightning payment integration coming soon! Amount: " + amount + " sats");
+ closeFundModal();
+ }
+
+ fundBtn.addEventListener("click", openFundModal);
+ fundClose.addEventListener("click", closeFundModal);
+ fundBackdrop.addEventListener("click", closeFundModal);
+ fundSubmit.addEventListener("click", handleFundSubmit);
+
+ // Allow Enter key to submit
+ fundAmount.addEventListener("keypress", (e) => {
+ if (e.key === "Enter") {
+ handleFundSubmit();
+ }
+ });
+
// --- About Panel ---
const infoBtn = document.getElementById("info-btn");
const aboutPanel = document.getElementById("about-panel");
@@ -141,8 +250,12 @@
// Close on Escape key
document.addEventListener("keydown", (e) => {
- if (e.key === "Escape" && aboutPanel.classList.contains("open")) {
- closeAboutPanel();
+ if (e.key === "Escape") {
+ if (fundModal.classList.contains("open")) {
+ closeFundModal();
+ } else if (aboutPanel.classList.contains("open")) {
+ closeAboutPanel();
+ }
}
});
diff --git a/static/world/style.css b/static/world/style.css
index 40626007..6e738604 100644
--- a/static/world/style.css
+++ b/static/world/style.css
@@ -92,7 +92,7 @@ canvas {
.info-button {
position: absolute;
top: 14px;
- right: 36px;
+ right: 70px;
width: 28px;
height: 28px;
padding: 0;
@@ -119,6 +119,286 @@ canvas {
height: 16px;
}
+/* Fund Session button */
+.fund-button {
+ position: absolute;
+ top: 14px;
+ right: 36px;
+ width: 28px;
+ height: 28px;
+ padding: 0;
+ background: rgba(10, 10, 20, 0.7);
+ border: 1px solid rgba(0, 180, 80, 0.4);
+ border-radius: 50%;
+ color: #00b450;
+ cursor: pointer;
+ pointer-events: auto;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.fund-button:hover {
+ background: rgba(0, 180, 80, 0.15);
+ border-color: rgba(0, 180, 80, 0.7);
+ transform: scale(1.05);
+}
+
+.fund-button svg {
+ width: 16px;
+ height: 16px;
+}
+
+/* Fund Session Modal */
+.fund-modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 100;
+ pointer-events: none;
+ visibility: hidden;
+ opacity: 0;
+ transition: opacity 0.3s ease, visibility 0.3s ease;
+}
+
+.fund-modal.open {
+ pointer-events: auto;
+ visibility: visible;
+ opacity: 1;
+}
+
+.fund-modal-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 420px;
+ max-width: 90%;
+ height: 100%;
+ background: rgba(10, 10, 20, 0.97);
+ border-left: 1px solid rgba(0, 180, 80, 0.3);
+ padding: 60px 24px 24px 24px;
+ overflow-y: auto;
+ transform: translateX(100%);
+ transition: transform 0.3s ease;
+ box-shadow: -4px 0 20px rgba(0, 0, 0, 0.5);
+}
+
+.fund-modal.open .fund-modal-content {
+ transform: translateX(0);
+}
+
+.fund-close {
+ position: absolute;
+ top: 16px;
+ right: 16px;
+ width: 32px;
+ height: 32px;
+ padding: 0;
+ background: transparent;
+ border: 1px solid rgba(160, 160, 160, 0.3);
+ border-radius: 50%;
+ color: #aaa;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.fund-close:hover {
+ background: rgba(255, 255, 255, 0.1);
+ border-color: rgba(0, 180, 80, 0.5);
+ color: #00b450;
+}
+
+.fund-close svg {
+ width: 18px;
+ height: 18px;
+}
+
+.fund-modal-content h2 {
+ font-size: 20px;
+ color: #00b450;
+ margin-bottom: 24px;
+ font-weight: 600;
+}
+
+.fund-info {
+ margin-bottom: 24px;
+}
+
+.fund-info h3 {
+ font-size: 14px;
+ color: #e0e0e0;
+ margin-bottom: 10px;
+ font-weight: 600;
+}
+
+.fund-info p {
+ font-size: 13px;
+ line-height: 1.6;
+ color: #aaa;
+ margin-bottom: 10px;
+}
+
+.fund-info ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.fund-info li {
+ font-size: 13px;
+ line-height: 1.6;
+ color: #aaa;
+ margin-bottom: 8px;
+ padding-left: 16px;
+ position: relative;
+}
+
+.fund-info li::before {
+ content: "•";
+ position: absolute;
+ left: 0;
+ color: #00b450;
+}
+
+.fund-info li strong {
+ color: #ccc;
+}
+
+/* Cost table */
+.cost-table {
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 180, 80, 0.2);
+ border-radius: 8px;
+ padding: 12px;
+ margin-bottom: 10px;
+}
+
+.cost-row {
+ display: flex;
+ justify-content: space-between;
+ padding: 8px 0;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ font-size: 13px;
+}
+
+.cost-row:last-child {
+ border-bottom: none;
+}
+
+.cost-row span:first-child {
+ color: #aaa;
+}
+
+.cost-value {
+ color: #00b450;
+ font-weight: 600;
+}
+
+.cost-note {
+ font-size: 12px;
+ color: #666;
+ font-style: italic;
+ margin-top: 8px;
+}
+
+/* Fund actions */
+.fund-actions {
+ margin-top: 32px;
+ padding: 20px;
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 180, 80, 0.2);
+ border-radius: 8px;
+}
+
+.fund-input-group {
+ margin-bottom: 16px;
+}
+
+.fund-input-group label {
+ display: block;
+ font-size: 13px;
+ color: #ccc;
+ margin-bottom: 6px;
+}
+
+.fund-input {
+ width: 100%;
+ padding: 10px 12px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(0, 180, 80, 0.3);
+ border-radius: 6px;
+ color: #e0e0e0;
+ font-family: "Courier New", monospace;
+ font-size: 16px;
+ transition: all 0.2s ease;
+}
+
+.fund-input:focus {
+ outline: none;
+ border-color: rgba(0, 180, 80, 0.6);
+ background: rgba(255, 255, 255, 0.08);
+}
+
+.fund-input::placeholder {
+ color: #666;
+}
+
+.fund-submit-btn {
+ width: 100%;
+ padding: 12px;
+ background: linear-gradient(135deg, rgba(0, 180, 80, 0.8), rgba(0, 140, 60, 0.9));
+ border: none;
+ border-radius: 6px;
+ color: #fff;
+ font-family: "Courier New", monospace;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.fund-submit-btn:hover {
+ background: linear-gradient(135deg, rgba(0, 200, 90, 0.9), rgba(0, 160, 70, 1));
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px rgba(0, 180, 80, 0.3);
+}
+
+.fund-submit-btn:active {
+ transform: translateY(0);
+}
+
+.fund-footer {
+ margin-top: 24px;
+ padding-top: 16px;
+ border-top: 1px solid rgba(160, 160, 160, 0.2);
+ font-size: 12px;
+ color: #666;
+ text-align: center;
+}
+
+.fund-backdrop {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.5);
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+
+.fund-modal.open .fund-backdrop {
+ opacity: 1;
+}
+
/* About Panel */
.about-panel {
position: fixed;
@@ -265,14 +545,15 @@ canvas {
/* Mobile adjustments */
@media (max-width: 480px) {
- .about-panel-content {
+ .about-panel-content,
+ .fund-modal-content {
width: 100%;
max-width: 100%;
padding: 56px 20px 20px 20px;
}
.info-button {
- right: 32px;
+ right: 66px;
width: 26px;
height: 26px;
}
@@ -281,4 +562,15 @@ canvas {
width: 14px;
height: 14px;
}
+
+ .fund-button {
+ right: 32px;
+ width: 26px;
+ height: 26px;
+ }
+
+ .fund-button svg {
+ width: 14px;
+ height: 14px;
+ }
}