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 @@ +
+ +
+
+ +

Fund Session

+ +
+

⚡ What are Sats?

+

Sats (satoshis) are the smallest unit of Bitcoin—like cents to a dollar. There are 100 million sats in 1 bitcoin. They enable tiny payments perfect for AI interactions.

+
+ +
+

🛠️ Why Fund Your Session?

+

Your sats power the Workshop AI agents. When you fund a session:

+
    +
  • Timmy and the agent swarm can process your requests
  • +
  • You get priority access to compute resources
  • +
  • Agents are compensated for their work
  • +
+
+ +
+

💰 Approximate Costs

+
+
+ Simple chat message + ~10-50 sats +
+
+ Code generation task + ~100-500 sats +
+
+ Complex multi-agent job + ~1,000-5,000 sats +
+
+

Costs vary based on model and complexity. Unused sats remain in your balance.

+
+ +
+
+ + +
+ +
+ + +
+
+
+
@@ -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; + } }