Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: blank.mjs — animated Why/What/How labels, updated prose and button text

- Add animated question labels (Why!?, What!?, How!?) above each
bottom-left link button
- Change description to "Receive a @jeffrey approved..."
- Buy button now reads "BUY LAPTOP $128"
- Drop "(PDF)" from paper and manual button text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+44 -17
+44 -17
system/public/aesthetic.computer/disks/blank.mjs
··· 54 54 const PAPER_URL = 55 55 "https://papers.aesthetic.computer/plorking-the-planet-26-arxiv-cards.pdf"; 56 56 const DESCRIPTION_PLAIN = 57 - "A @jeffrey approved, refurbished Thinkpad 11e Yoga Gen 6 pre-flashed with AC Native OS and Live USB recovery stick."; 57 + "Receive a @jeffrey approved, refurbished Thinkpad 11e Yoga Gen 6 pre-flashed with AC Native OS and Live USB recovery stick."; 58 58 const DESCRIPTION = 59 - "A \\255,100,255\\@jeffrey\\reset\\ approved, refurbished Thinkpad 11e Yoga Gen 6 pre-flashed with AC Native OS and Live USB recovery stick."; 59 + "Receive a \\255,100,255\\@jeffrey\\reset\\ approved, refurbished Thinkpad 11e Yoga Gen 6 pre-flashed with AC Native OS and Live USB recovery stick."; 60 60 const AUTH_TIMEOUT_MS = 1200; 61 61 62 62 async function getOptionalToken(api) { ··· 83 83 84 84 function getBuyText() { 85 85 if (buyPending) return "CHECKING OUT..."; 86 - return `BUY ${displayAmount(amount)}`; 86 + return `BUY LAPTOP ${displayAmount(amount)}`; 87 87 } 88 88 89 89 async function boot({ params, ui, screen, cursor, hud, api, handle }) { ··· 138 138 function setupButtons(ui, screen) { 139 139 buyBtn = new ui.TextButton(getBuyText(), { center: "x", bottom: 20, screen }); 140 140 osBtn = new ui.TextButton("AC Native OS", { x: 6, bottom: 20, screen }); 141 - paperBtn = new ui.TextButton("PLORK'ing the Planet (PDF)", { x: 6, bottom: 20, screen }); 142 - manualBtn = new ui.TextButton("ThinkPad 11e Yoga Manual (PDF)", { x: 6, bottom: 20 + (paperBtn.height || 14) + 4, screen }); 141 + paperBtn = new ui.TextButton("PLORK'ing the Planet", { x: 6, bottom: 20, screen }); 142 + manualBtn = new ui.TextButton("ThinkPad 11e Yoga Manual", { x: 6, bottom: 20 + (paperBtn.height || 14) + 4, screen }); 143 143 } 144 144 145 145 async function fetchCheckout(api) { ··· 800 800 $.needsPaint(); 801 801 } 802 802 803 - // Manual + Paper links (bottom left, vertically stacked, different colors) 804 - const manualScheme = isDark 805 - ? [[20, 20, 30], [100, 140, 200], [160, 190, 240]] 806 - : [[220, 225, 240], [50, 70, 140], [30, 50, 100]]; 807 - const manualHover = isDark 808 - ? [[30, 30, 45], [140, 180, 240], [200, 220, 255]] 809 - : [[210, 215, 235], [40, 60, 160], [20, 40, 120]]; 803 + // Bottom-left link stack with animated question labels 804 + const labelGap = 2; 805 + const labelH = charH + labelGap; 806 + const btnGap = 4; 807 + const t = frame * 0.04; 808 + 809 + // Animated label helper — cycling color shadow with wobble 810 + const paintLabel = (label, bottomY, phase) => { 811 + const lx = 6; 812 + const ly = h - bottomY - charH; 813 + const wobble = floor(sin(t + phase) * 1.5); 814 + ink(sr, sg, sb, shadowAlpha).write(label, { x: lx + shadowOff, y: ly + shadowOff + wobble, screen }); 815 + ink(fg).write(label, { x: lx, y: ly + wobble, screen }); 816 + }; 817 + 818 + // Stack from bottom: Why!? + paper, What!? + manual, How!? + os 819 + let stackY = 20; 820 + 821 + // --- Why!? + Paper --- 810 822 const paperScheme = isDark 811 823 ? [[25, 20, 20], [200, 140, 80], [240, 190, 130]] 812 824 : [[240, 230, 220], [140, 80, 30], [100, 55, 15]]; ··· 814 826 ? [[35, 28, 28], [240, 180, 100], [255, 210, 150]] 815 827 : [[235, 222, 210], [160, 100, 40], [120, 70, 20]]; 816 828 if (paperBtn) { 817 - paperBtn.reposition({ x: 6, bottom: 20, screen }, "PLORK'ing the Planet (PDF)"); 829 + paperBtn.reposition({ x: 6, bottom: stackY, screen }, "PLORK'ing the Planet"); 818 830 paperBtn.paint($btn, paperScheme, paperHover); 831 + stackY += paperBtn.height + btnGap; 819 832 } 833 + paintLabel("Why!?", stackY, 0); 834 + stackY += labelH; 835 + 836 + // --- What!? + Manual --- 837 + const manualScheme = isDark 838 + ? [[20, 20, 30], [100, 140, 200], [160, 190, 240]] 839 + : [[220, 225, 240], [50, 70, 140], [30, 50, 100]]; 840 + const manualHover = isDark 841 + ? [[30, 30, 45], [140, 180, 240], [200, 220, 255]] 842 + : [[210, 215, 235], [40, 60, 160], [20, 40, 120]]; 820 843 if (manualBtn) { 821 - const manualY = 20 + (paperBtn ? paperBtn.height + 4 : 0); 822 - manualBtn.reposition({ x: 6, bottom: manualY, screen }, "ThinkPad 11e Yoga Manual (PDF)"); 844 + manualBtn.reposition({ x: 6, bottom: stackY, screen }, "ThinkPad 11e Yoga Manual"); 823 845 manualBtn.paint($btn, manualScheme, manualHover); 846 + stackY += manualBtn.height + btnGap; 824 847 } 848 + paintLabel("What!?", stackY, PI * 0.66); 849 + stackY += labelH; 850 + 851 + // --- How!? + OS --- 825 852 const osScheme = isDark 826 853 ? [[20, 25, 20], [80, 200, 120], [140, 240, 170]] 827 854 : [[225, 240, 225], [30, 120, 50], [15, 90, 30]]; ··· 829 856 ? [[28, 35, 28], [120, 240, 150], [180, 255, 200]] 830 857 : [[215, 235, 215], [20, 140, 60], [10, 110, 40]]; 831 858 if (osBtn) { 832 - const osY = 20 + (paperBtn ? paperBtn.height + 4 : 0) + (manualBtn ? manualBtn.height + 4 : 0); 833 - osBtn.reposition({ x: 6, bottom: osY, screen }, "AC Native OS"); 859 + osBtn.reposition({ x: 6, bottom: stackY, screen }, "AC Native OS"); 834 860 osBtn.paint($btn, osScheme, osHover); 835 861 } 862 + paintLabel("How!?", stackY + (osBtn ? osBtn.height + btnGap : 0), PI * 1.33); 836 863 } 837 864 838 865 function act({ event: e, screen, jump, sound, ui, api }) {