A copy-and-build guide: create the widgets, paste the CSS, add three variables, add two timers, and paste the scripts.

1. What you are building
- 32 animated panels arranged in a 4 × 8 grid.
- Terminal-style loading text and boot log.
- Heartbeat system status indicator.
- Animated progress bar and percentage.
- 42-frame sequence driven by Timer_1.
- Final state: DASHBOARD READY, SYSTEM ONLINE, and the closing message.
How it works
Timer_2 resets the loader. Timer_1 advances RainStep from 0 to 41. Each RainStep swaps CSS classes on the panels and text widgets. The CSS provides the glow, flash, trace, powered and final visual states.
2. Create these SAC objects
| Type | Exact ID | Purpose |
| Panel | Panel_1 to Panel_32 | 4 × 8 animated grid |
| Panel | Panel_ProgressTrack | Progress bar track |
| Panel | Panel_ProgressFill | Animated progress fill |
| Text | Text_Loading | Main loading message |
| Text | Text_Progress | Percentage value |
| Text | Text_Status | Heartbeat / online status |
| Text | Text_BootLog | Boot sequence messages |
| Text | Text_Remember | Final message |
| Timer | Timer_1 | Animation engine |
| Timer | Timer_2 | Reset/start timer |
Use the IDs exactly as shown. The scripts reference them directly.



3. Build the layout
- Place Panel_1 to Panel_32 in a 4-row × 8-column grid.
- Keep all 32 panels the same size with even spacing.
- Place Text_Loading below the grid and centre it.
- Create Panel_ProgressTrack below Text_Loading.
- Place Panel_ProgressFill inside/over the progress track, aligned left.
- Place Text_Progress over or beside the progress bar.
- Place Text_Status and Text_BootLog in the boot-log area.
- Place Text_Remember where the final message should appear. It will be hidden during boot.

4. Create the script variables
| ID | Type | Default | Array |
| BootLog | string | “” | No |
| RainRunning | boolean | false | No |
| RainStep | integer | 0 | No |
Do not expose any of these as URL parameters.


5. Add the CSS
Open the story/application CSS editor and paste the complete CSS below. These classes are the visual engine for the animation.
| /* ===================================================== */ /* BOOT SEQUENCE LOG */ /* ===================================================== */ .boot-log .sap-custom-text-widget { background-color: transparent; border: none; opacity: 1; } .boot-log .sap-custom-text { color: rgba(80, 205, 180, 0.72); font-family: monospace; font-size: 14px; font-weight: normal; } /* Final completed boot log */ .boot-log-ready .sap-custom-text-widget { background-color: transparent; border: none; opacity: 1; } .boot-log-ready .sap-custom-text { color: rgba(120, 255, 210, 0.88); font-family: monospace; font-size: 14px; font-weight: normal; } .remember-message .sap-custom-text-widget { border: none; } .remember-message .sap-custom-text { color: rgba(120,255,210,0.95); font-size: 22px; font-weight: 700; } /* ===================================================== */ /* PROGRESS BAR */ /* ===================================================== */ .progress-track .sap-custom-panel-widget { background-color: rgba(2, 22, 25, 0.96); border: 1px solid rgba(0, 175, 150, 0.45); opacity: 1; border-radius: 6px; box-shadow: inset 0px 0px 12px rgba(0, 0, 0, 0.65), 0px 0px 10px rgba(0, 180, 155, 0.20); } .progress-fill .sap-custom-panel-widget { background-color: rgba(0, 220, 185, 1); border: 1px solid rgba(210, 255, 242, 1); opacity: 1; border-radius: 5px; box-shadow: |
| inset 0px 0px 10px rgba(255, 255, 255, 0.30), 0px 0px 12px rgba(0, 255, 215, 0.95), 0px 0px 28px rgba(0, 220, 190, 0.65); } .progress-fill-flash .sap-custom-panel-widget { background-color: rgba(220, 255, 245, 1); border: 1px solid rgba(255, 255, 255, 1); opacity: 1; border-radius: 5px; box-shadow: 0px 0px 15px rgba(255, 255, 255, 1), 0px 0px 36px rgba(0, 255, 215, 1); } .progress-fill-ready .sap-custom-panel-widget { background-color: rgba(60, 235, 180, 1); border: 1px solid rgba(220, 255, 240, 1); opacity: 1; border-radius: 5px; box-shadow: inset 0px 0px 8px rgba(255, 255, 255, 0.25), 0px 0px 14px rgba(0, 255, 190, 0.85); } /* ===================================================== */ /* HEARTBEAT STATUS */ /* ===================================================== */ .heartbeat-on .sap-custom-text { color: rgba(120,255,210,1); font-family: monospace; font-size: 13px; font-weight: bold; } .heartbeat-on .sap-custom-text-widget { background-color: transparent; opacity: 1; } .heartbeat-off .sap-custom-text { color: rgba(40,120,105,0.45); font-family: monospace; font-size: 13px; font-weight: bold; } .heartbeat-off .sap-custom-text-widget { background-color: transparent; opacity: 1; } /* ===================================================== */ /* DASHBOARD LOADING TEXT */ /* ===================================================== */ /* —————————————————– */ /* Idle */ |
| /* —————————————————– */ .loading-text-idle .sap-custom-text-widget { background-color: rgba(3, 28, 30, 0.92); border: 1px solid rgba(0, 175, 150, 0.55); opacity: 0.85; border-radius: 8px; box-shadow: inset 0px 0px 18px rgba(0, 125, 110, 0.18), 0px 0px 10px rgba(0, 180, 155, 0.25); } .loading-text-idle .sap-custom-text { color: rgba(80, 210, 185, 0.75); font-family: monospace; font-size: 18px; font-weight: bold; } /* —————————————————– */ /* Active */ /* —————————————————– */ .loading-text-active .sap-custom-text-widget { background-color: rgba(0, 65, 60, 0.96); border: 2px solid rgba(120, 255, 220, 0.9); opacity: 1; border-radius: 8px; box-shadow: inset 0px 0px 20px rgba(160, 255, 230, 0.18), 0px 0px 14px rgba(0, 255, 210, 0.75), 0px 0px 32px rgba(0, 220, 185, 0.38); } .loading-text-active .sap-custom-text { color: rgba(205, 255, 240, 1); font-family: monospace; font-size: 18px; font-weight: bold; } /* —————————————————– */ /* Flash */ /* —————————————————– */ .loading-text-flash .sap-custom-text-widget { background-color: rgba(180, 255, 230, 1); border: 2px solid rgba(255, 255, 255, 1); opacity: 1; border-radius: 8px; box-shadow: 0px 0px 16px rgba(255, 255, 255, 1), 0px 0px 40px rgba(0, 255, 215, 0.95); } .loading-text-flash .sap-custom-text { color: rgba(0, 55, 48, 1); font-family: monospace; font-size: 18px; font-weight: bold; } /* —————————————————– */ /* Ready */ |
| /* —————————————————– */ .loading-text-ready .sap-custom-text-widget { background-color: rgba(5, 78, 66, 0.98); border: 2px solid rgba(145, 255, 215, 1); opacity: 1; border-radius: 8px; box-shadow: inset 0px 0px 16px rgba(150, 255, 225, 0.2), 0px 0px 18px rgba(0, 255, 200, 0.7); } .loading-text-ready .sap-custom-text { color: rgba(225, 255, 245, 1); font-family: monospace; font-size: 18px; font-weight: bold; } /* ===================================================== */ /* DIGITAL RAIN — PANEL STATES */ /* ===================================================== */ /* —————————————————– */ /* Amber processing state */ /* —————————————————– */ .rain-process .sap-custom-panel-widget { background-color: rgba(185, 110, 0, 0.96); border: 2px solid rgba(255, 220, 145, 1); opacity: 1; box-shadow: inset 0px 0px 20px rgba(255, 245, 205, 0.35), 0px 0px 12px rgba(255, 185, 60, 0.9), 0px 0px 30px rgba(255, 145, 0, 0.55); } /* —————————————————– */ /* Deliberate digital glitch */ /* —————————————————– */ .rain-glitch .sap-custom-panel-widget { background-color: rgba(0, 210, 185, 0.95); border-top: 3px solid rgba(255, 255, 255, 1); border-right: 2px dashed rgba(0, 255, 220, 0.9); border-bottom: 3px dotted rgba(0, 100, 90, 0.9); border-left: 2px solid rgba(255, 255, 255, 0.8); opacity: 0.78; box-shadow: inset 8px 0px 0px rgba(255, 255, 255, 0.25), -5px 0px 0px rgba(0, 255, 215, 0.35), 5px 0px 0px rgba(255, 180, 0, 0.25); } /* —————————————————– */ /* Dormant panel */ /* —————————————————– */ .rain-dormant .sap-custom-panel-widget { background-color: rgba(5, 18, 24, 0.92); border: 1px solid rgba(50, 95, 105, 0.35); |
| opacity: 0.82; box-shadow: inset 3px 3px 8px rgba(0, 0, 0, 0.55), inset -3px -3px 8px rgba(70, 140, 150, 0.08); } /* —————————————————– */ /* Previously activated panel */ /* —————————————————– */ .rain-trace .sap-custom-panel-widget { background-color: rgba(4, 45, 50, 0.92); border: 1px solid rgba(45, 180, 165, 0.48); opacity: 0.92; box-shadow: inset 0px 0px 18px rgba(0, 160, 145, 0.18), 0px 0px 8px rgba(0, 180, 160, 0.28); } /* —————————————————– */ /* Bright active panel */ /* —————————————————– */ .rain-active .sap-custom-panel-widget { background-color: rgba(0, 180, 155, 0.96); border: 2px solid rgba(195, 255, 235, 1); opacity: 1; box-shadow: inset 0px 0px 22px rgba(230, 255, 248, 0.42), 0px 0px 12px rgba(0, 255, 210, 0.95), 0px 0px 30px rgba(0, 220, 190, 0.70); } /* —————————————————– */ /* White-hot flash */ /* —————————————————– */ .rain-flash .sap-custom-panel-widget { background-color: rgba(220, 255, 245, 1); border: 3px solid rgba(255, 255, 255, 1); opacity: 1; box-shadow: inset 0px 0px 18px rgba(255, 255, 255, 0.9), 0px 0px 16px rgba(255, 255, 255, 1), 0px 0px 42px rgba(0, 255, 215, 1); } /* —————————————————– */ /* Fully powered panel */ /* —————————————————– */ .rain-powered .sap-custom-panel-widget { background-color: rgba(8, 72, 78, 0.96); border: 1px solid rgba(75, 230, 210, 0.72); opacity: 1; box-shadow: inset 3px 3px 10px rgba(0, 0, 0, 0.35), inset -3px -3px 10px rgba(130, 255, 230, 0.14), 0px 0px 12px rgba(0, 210, 185, 0.35); } |
/* —————————————————– */ /* Final polished dashboard card */ /* —————————————————– */ .rain-final .sap-custom-panel-widget { background-color: rgba(242, 249, 248, 0.98); border: 1px solid rgba(0, 120, 120, 0.28); opacity: 1; box-shadow: inset 0px 4px 0px rgba(0, 175, 155, 0.75), 4px 6px 14px rgba(0, 35, 40, 0.16); } /* ===================================================== */ /* CENTRAL CORE */ /* ===================================================== */ /* —————————————————– */ /* Core idle */ /* —————————————————– */ .rain-core-idle .sap-custom-shape-widget { background-color: rgba(4, 18, 24, 1); border: 2px solid rgba(0, 140, 135, 0.55); box-shadow: inset 0px 0px 18px rgba(0, 100, 100, 0.3), 0px 0px 12px rgba(0, 150, 145, 0.32); } /* —————————————————– */ /* Core active */ /* —————————————————– */ .rain-core-active .sap-custom-shape-widget { background-color: rgba(0, 190, 165, 1); border: 3px solid rgba(215, 255, 245, 1); box-shadow: inset 0px 0px 20px rgba(255, 255, 255, 0.45), 0px 0px 18px rgba(255, 255, 255, 0.85), 0px 0px 50px rgba(0, 255, 215, 0.95); } /* —————————————————– */ /* Core flash */ /* —————————————————– */ .rain-core-flash .sap-custom-shape-widget { background-color: rgba(245, 255, 252, 1); border: 4px solid rgba(255, 255, 255, 1); box-shadow: 0px 0px 25px rgba(255, 255, 255, 1), 0px 0px 65px rgba(0, 255, 220, 1); } |
6. Page_1 — onInitialization
Add this single line to Page_1 → onInitialization:
| Timer_2.start(1); |

7. Timer_2 — reset and start
Paste the following into Timer_2. This resets every visual state and then starts Timer_1.
| Timer_1.stop(); RainStep = 0; RainRunning = true; Text_Loading.setVisible(true); Text_Loading.applyText(“DASHBOARD LOADING”); Text_Loading.setCssClass(“loading-text-idle”); Text_Remember.setVisible(false); Text_Remember.applyText(“”); // Initialise system status Text_Status.setVisible(true); Text_Status.applyText(“● SYSTEM BOOTING”); Text_Status.setCssClass(“heartbeat-on”); // Initialise boot sequence BootLog = “”; Text_BootLog.setVisible(true); Text_BootLog.applyText(“”); Text_BootLog.setCssClass(“boot-log”); // Make all panels visible Panel_1.setVisible(true); Panel_2.setVisible(true); Panel_3.setVisible(true); Panel_4.setVisible(true); Panel_5.setVisible(true); Panel_6.setVisible(true); Panel_7.setVisible(true); Panel_8.setVisible(true); Panel_9.setVisible(true); Panel_10.setVisible(true); Panel_11.setVisible(true); Panel_12.setVisible(true); Panel_13.setVisible(true); Panel_14.setVisible(true); Panel_15.setVisible(true); Panel_16.setVisible(true); Panel_17.setVisible(true); Panel_18.setVisible(true); Panel_19.setVisible(true); Panel_20.setVisible(true); Panel_21.setVisible(true); Panel_22.setVisible(true); Panel_23.setVisible(true); Panel_24.setVisible(true); Panel_25.setVisible(true); Panel_26.setVisible(true); Panel_27.setVisible(true); Panel_28.setVisible(true); Panel_29.setVisible(true); Panel_30.setVisible(true); Panel_31.setVisible(true); Panel_32.setVisible(true); // Reset all panels to dormant Panel_1.setCssClass(“rain-dormant”); Panel_2.setCssClass(“rain-dormant”); Panel_3.setCssClass(“rain-dormant”); Panel_4.setCssClass(“rain-dormant”); Panel_5.setCssClass(“rain-dormant”); Panel_6.setCssClass(“rain-dormant”); Panel_7.setCssClass(“rain-dormant”); Panel_8.setCssClass(“rain-dormant”); Panel_9.setCssClass(“rain-dormant”); Panel_10.setCssClass(“rain-dormant”); Panel_11.setCssClass(“rain-dormant”); Panel_12.setCssClass(“rain-dormant”); Panel_13.setCssClass(“rain-dormant”); Panel_14.setCssClass(“rain-dormant”); Panel_15.setCssClass(“rain-dormant”); Panel_16.setCssClass(“rain-dormant”); Panel_17.setCssClass(“rain-dormant”); Panel_18.setCssClass(“rain-dormant”); |
| Panel_19.setCssClass(“rain-dormant”); Panel_20.setCssClass(“rain-dormant”); Panel_21.setCssClass(“rain-dormant”); Panel_22.setCssClass(“rain-dormant”); Panel_23.setCssClass(“rain-dormant”); Panel_24.setCssClass(“rain-dormant”); Panel_25.setCssClass(“rain-dormant”); Panel_26.setCssClass(“rain-dormant”); Panel_27.setCssClass(“rain-dormant”); Panel_28.setCssClass(“rain-dormant”); Panel_29.setCssClass(“rain-dormant”); Panel_30.setCssClass(“rain-dormant”); Panel_31.setCssClass(“rain-dormant”); Panel_32.setCssClass(“rain-dormant”); // Reset progress bar Panel_ProgressTrack.setVisible(true); Panel_ProgressFill.setVisible(true); Panel_ProgressTrack.setCssClass(“progress-track”); Panel_ProgressFill.setCssClass(“progress-fill”); Panel_ProgressFill.getLayout().setWidth(4); // Start the animation Timer_1.start(0.18); |
8. Timer_1 — animation script
Paste the complete script below into Timer_1. Timer_1 restarts itself every 0.18 seconds until RainStep reaches 41.
| // ========================================================= // 32-PANEL DIGITAL RAIN ANIMATION // 4 rows × 8 columns // Includes Text_Loading status display // ========================================================= // ——————————————————— // Boot cursor state // ——————————————————— var cursor = “”; if ((RainStep % 4) < 2) { cursor = “_”; } // ——————————————————— // PHASE 1 — random digital rain // Frames 0–11 // ——————————————————— if (RainStep === 0) { Text_Loading.setVisible(true); Text_Progress.setVisible(true); Text_Loading.applyText(“DASHBOARD LOADING”+ cursor); Text_Loading.setCssClass(“loading-text-active”); Panel_3.setCssClass(“rain-active”); Panel_14.setCssClass(“rain-flash”); Panel_27.setCssClass(“rain-active”); } if (RainStep === 1) { Text_Loading.applyText(“DASHBOARD LOADING.”+ cursor); Panel_3.setCssClass(“rain-trace”); Panel_14.setCssClass(“rain-trace”); Panel_27.setCssClass(“rain-trace”); Panel_7.setCssClass(“rain-active”); Panel_18.setCssClass(“rain-process”); Panel_30.setCssClass(“rain-flash”); } if (RainStep === 2) { Text_Loading.applyText(“DASHBOARD LOADING..”+ cursor); Panel_7.setCssClass(“rain-trace”); Panel_18.setCssClass(“rain-trace”); Panel_30.setCssClass(“rain-trace”); Panel_1.setCssClass(“rain-glitch”); Panel_11.setCssClass(“rain-active”); Panel_24.setCssClass(“rain-flash”); } if (RainStep === 3) { Text_Loading.applyText(“DASHBOARD LOADING…”+ cursor); Panel_1.setCssClass(“rain-trace”); Panel_11.setCssClass(“rain-trace”); Panel_24.setCssClass(“rain-trace”); Panel_6.setCssClass(“rain-active”); Panel_20.setCssClass(“rain-active”); Panel_32.setCssClass(“rain-flash”); } if (RainStep === 4) { Text_Loading.applyText(“INITIALISING COMPONENTS”+ cursor); Panel_6.setCssClass(“rain-trace”); Panel_20.setCssClass(“rain-trace”); |
| Panel_32.setCssClass(“rain-trace”); Panel_9.setCssClass(“rain-flash”); Panel_16.setCssClass(“rain-active”); Panel_22.setCssClass(“rain-process”); } if (RainStep === 5) { Text_Loading.applyText(“CONNECTING DATA SOURCES”+ cursor); Text_Loading.setCssClass(“loading-text-active”); Panel_9.setCssClass(“rain-trace”); Panel_16.setCssClass(“rain-trace”); Panel_22.setCssClass(“rain-trace”); Panel_4.setCssClass(“rain-active”); Panel_13.setCssClass(“rain-glitch”); Panel_29.setCssClass(“rain-flash”); } if (RainStep === 6) { Text_Loading.applyText(“CONNECTING DATA SOURCES.”+ cursor); Panel_4.setCssClass(“rain-trace”); Panel_13.setCssClass(“rain-trace”); Panel_29.setCssClass(“rain-trace”); Panel_8.setCssClass(“rain-flash”); Panel_17.setCssClass(“rain-active”); Panel_26.setCssClass(“rain-active”); } if (RainStep === 7) { Text_Loading.applyText(“CONNECTING DATA SOURCES..”+ cursor); Panel_8.setCssClass(“rain-trace”); Panel_17.setCssClass(“rain-trace”); Panel_26.setCssClass(“rain-trace”); Panel_2.setCssClass(“rain-active”); Panel_15.setCssClass(“rain-flash”); Panel_31.setCssClass(“rain-process”); } if (RainStep === 8) { Text_Loading.applyText(“CONNECTING DATA SOURCES…”+ cursor); Panel_2.setCssClass(“rain-trace”); Panel_15.setCssClass(“rain-trace”); Panel_31.setCssClass(“rain-trace”); Panel_5.setCssClass(“rain-glitch”); Panel_19.setCssClass(“rain-active”); Panel_25.setCssClass(“rain-flash”); } if (RainStep === 9) { Text_Loading.applyText(“DATA CONNECTION ESTABLISHED”+ cursor); Panel_5.setCssClass(“rain-trace”); Panel_19.setCssClass(“rain-trace”); Panel_25.setCssClass(“rain-trace”); Panel_10.setCssClass(“rain-active”); Panel_21.setCssClass(“rain-flash”); Panel_28.setCssClass(“rain-active”); } if (RainStep === 10) { Text_Loading.applyText(“PREPARING ANALYTIC ENGINE”+ cursor); Panel_10.setCssClass(“rain-trace”); Panel_21.setCssClass(“rain-trace”); |
| Panel_28.setCssClass(“rain-trace”); Panel_12.setCssClass(“rain-flash”); Panel_23.setCssClass(“rain-active”); Panel_30.setCssClass(“rain-glitch”); } if (RainStep === 11) { Text_Loading.applyText(“PREPARING ANALYTIC ENGINE…”+ cursor); Panel_12.setCssClass(“rain-trace”); Panel_23.setCssClass(“rain-trace”); Panel_30.setCssClass(“rain-trace”); Panel_3.setCssClass(“rain-active”); Panel_18.setCssClass(“rain-flash”); Panel_27.setCssClass(“rain-process”); } // ——————————————————— // PHASE 2 — serpentine energy pulse // Frames 12–27 // ——————————————————— if (RainStep === 12) { Text_Loading.applyText(“LOADING ANALYTIC MODELS”+ cursor); Text_Loading.setCssClass(“loading-text-active”); Panel_3.setCssClass(“rain-trace”); Panel_18.setCssClass(“rain-trace”); Panel_27.setCssClass(“rain-trace”); Panel_1.setCssClass(“rain-flash”); Panel_2.setCssClass(“rain-active”); } if (RainStep === 13) { Text_Loading.applyText(“LOADING ANALYTIC MODELS.”+ cursor); Panel_1.setCssClass(“rain-powered”); Panel_2.setCssClass(“rain-flash”); Panel_3.setCssClass(“rain-active”); } if (RainStep === 14) { Text_Loading.applyText(“LOADING ANALYTIC MODELS..”+ cursor); Panel_2.setCssClass(“rain-powered”); Panel_3.setCssClass(“rain-flash”); Panel_4.setCssClass(“rain-active”); } if (RainStep === 15) { Text_Loading.applyText(“LOADING ANALYTIC MODELS…”+ cursor); Panel_3.setCssClass(“rain-powered”); Panel_4.setCssClass(“rain-flash”); Panel_5.setCssClass(“rain-active”); } if (RainStep === 16) { Text_Loading.applyText(“MODEL 01 INITIALISED”+ cursor); Panel_4.setCssClass(“rain-powered”); Panel_5.setCssClass(“rain-flash”); Panel_6.setCssClass(“rain-active”); } if (RainStep === 17) { Text_Loading.applyText(“MODEL 02 INITIALISED”+ cursor); |
| Panel_5.setCssClass(“rain-powered”); Panel_6.setCssClass(“rain-flash”); Panel_7.setCssClass(“rain-active”); } if (RainStep === 18) { Text_Loading.applyText(“MODEL 03 INITIALISED”+ cursor); Panel_6.setCssClass(“rain-powered”); Panel_7.setCssClass(“rain-flash”); Panel_8.setCssClass(“rain-active”); } if (RainStep === 19) { Text_Loading.applyText(“ACTIVATING CALCULATION LAYER”+ cursor); Panel_7.setCssClass(“rain-powered”); Panel_8.setCssClass(“rain-flash”); Panel_16.setCssClass(“rain-active”); } if (RainStep === 20) { Text_Loading.applyText(“ACTIVATING CALCULATION LAYER.”+ cursor); Panel_8.setCssClass(“rain-powered”); Panel_16.setCssClass(“rain-flash”); Panel_15.setCssClass(“rain-active”); } if (RainStep === 21) { Text_Loading.applyText(“ACTIVATING CALCULATION LAYER..”+ cursor); Panel_16.setCssClass(“rain-powered”); Panel_15.setCssClass(“rain-flash”); Panel_14.setCssClass(“rain-active”); } if (RainStep === 22) { Text_Loading.applyText(“ACTIVATING CALCULATION LAYER…”+ cursor); Panel_15.setCssClass(“rain-powered”); Panel_14.setCssClass(“rain-flash”); Panel_13.setCssClass(“rain-active”); } if (RainStep === 23) { Text_Loading.applyText(“CALCULATIONS ONLINE”+ cursor); Panel_14.setCssClass(“rain-powered”); Panel_13.setCssClass(“rain-flash”); Panel_12.setCssClass(“rain-active”); } if (RainStep === 24) { Text_Loading.applyText(“APPLYING BUSINESS LOGIC”+ cursor); Panel_13.setCssClass(“rain-powered”); Panel_12.setCssClass(“rain-flash”); Panel_11.setCssClass(“rain-active”); } if (RainStep === 25) { Text_Loading.applyText(“APPLYING BUSINESS LOGIC.”+ cursor); Panel_12.setCssClass(“rain-powered”); Panel_11.setCssClass(“rain-flash”); Panel_10.setCssClass(“rain-active”); } |
if (RainStep === 26) { Text_Loading.applyText(“APPLYING BUSINESS LOGIC..”+ cursor); Panel_11.setCssClass(“rain-powered”); Panel_10.setCssClass(“rain-flash”); Panel_9.setCssClass(“rain-active”); } if (RainStep === 27) { Text_Loading.applyText(“BUSINESS LOGIC VALIDATED”+ cursor); Panel_10.setCssClass(“rain-powered”); Panel_9.setCssClass(“rain-flash”); Panel_17.setCssClass(“rain-active”); Panel_18.setCssClass(“rain-active”); Panel_19.setCssClass(“rain-active”); Panel_20.setCssClass(“rain-active”); Panel_21.setCssClass(“rain-active”); Panel_22.setCssClass(“rain-active”); Panel_23.setCssClass(“rain-active”); Panel_24.setCssClass(“rain-active”); } // ——————————————————— // PHASE 3 — row ignition // Frames 28–31 // ——————————————————— if (RainStep === 28) { Text_Loading.applyText(“VALIDATING DASHBOARD COMPONENTS”+ cursor); Text_Loading.setCssClass(“loading-text-active”); Panel_9.setCssClass(“rain-powered”); Panel_17.setCssClass(“rain-flash”); Panel_18.setCssClass(“rain-flash”); Panel_19.setCssClass(“rain-flash”); Panel_20.setCssClass(“rain-flash”); Panel_21.setCssClass(“rain-flash”); Panel_22.setCssClass(“rain-flash”); Panel_23.setCssClass(“rain-flash”); Panel_24.setCssClass(“rain-flash”); } if (RainStep === 29) { Text_Loading.applyText(“VALIDATING DASHBOARD COMPONENTS.”+ cursor); Panel_17.setCssClass(“rain-powered”); Panel_18.setCssClass(“rain-powered”); Panel_19.setCssClass(“rain-powered”); Panel_20.setCssClass(“rain-powered”); Panel_21.setCssClass(“rain-powered”); Panel_22.setCssClass(“rain-powered”); Panel_23.setCssClass(“rain-powered”); Panel_24.setCssClass(“rain-powered”); Panel_25.setCssClass(“rain-active”); Panel_26.setCssClass(“rain-active”); Panel_27.setCssClass(“rain-active”); Panel_28.setCssClass(“rain-active”); Panel_29.setCssClass(“rain-active”); Panel_30.setCssClass(“rain-active”); Panel_31.setCssClass(“rain-active”); Panel_32.setCssClass(“rain-active”); } if (RainStep === 30) { Text_Loading.applyText(“VALIDATING DASHBOARD COMPONENTS..”+ cursor); Panel_25.setCssClass(“rain-flash”); Panel_26.setCssClass(“rain-flash”); Panel_27.setCssClass(“rain-flash”); Panel_28.setCssClass(“rain-flash”); Panel_29.setCssClass(“rain-flash”); |
| Panel_30.setCssClass(“rain-flash”); Panel_31.setCssClass(“rain-flash”); Panel_32.setCssClass(“rain-flash”); } if (RainStep === 31) { Text_Loading.applyText(“COMPONENT VALIDATION COMPLETE”+ cursor); Panel_25.setCssClass(“rain-powered”); Panel_26.setCssClass(“rain-powered”); Panel_27.setCssClass(“rain-powered”); Panel_28.setCssClass(“rain-powered”); Panel_29.setCssClass(“rain-powered”); Panel_30.setCssClass(“rain-powered”); Panel_31.setCssClass(“rain-powered”); Panel_32.setCssClass(“rain-powered”); } // ——————————————————— // PHASE 4 — vertical scanner sweep // Frames 32–39 // ——————————————————— if (RainStep === 32) { Text_Loading.applyText(“ACTIVATING VISUAL LAYER”+ cursor); Text_Loading.setCssClass(“loading-text-active”); Panel_1.setCssClass(“rain-flash”); Panel_9.setCssClass(“rain-flash”); Panel_17.setCssClass(“rain-flash”); Panel_25.setCssClass(“rain-flash”); } if (RainStep === 33) { Text_Loading.applyText(“ACTIVATING VISUAL LAYER.”+ cursor); Panel_1.setCssClass(“rain-powered”); Panel_9.setCssClass(“rain-powered”); Panel_17.setCssClass(“rain-powered”); Panel_25.setCssClass(“rain-powered”); Panel_2.setCssClass(“rain-flash”); Panel_10.setCssClass(“rain-flash”); Panel_18.setCssClass(“rain-flash”); Panel_26.setCssClass(“rain-flash”); } if (RainStep === 34) { Text_Loading.applyText(“ACTIVATING VISUAL LAYER..”+ cursor); Panel_2.setCssClass(“rain-powered”); Panel_10.setCssClass(“rain-powered”); Panel_18.setCssClass(“rain-powered”); Panel_26.setCssClass(“rain-powered”); Panel_3.setCssClass(“rain-flash”); Panel_11.setCssClass(“rain-flash”); Panel_19.setCssClass(“rain-flash”); Panel_27.setCssClass(“rain-flash”); } if (RainStep === 35) { Text_Loading.applyText(“ACTIVATING VISUAL LAYER…”+ cursor); Panel_3.setCssClass(“rain-powered”); Panel_11.setCssClass(“rain-powered”); Panel_19.setCssClass(“rain-powered”); Panel_27.setCssClass(“rain-powered”); Panel_4.setCssClass(“rain-flash”); Panel_12.setCssClass(“rain-flash”); Panel_20.setCssClass(“rain-flash”); Panel_28.setCssClass(“rain-flash”); } |
if (RainStep === 36) { Text_Loading.applyText(“RENDERING DASHBOARD”+ cursor); Panel_4.setCssClass(“rain-powered”); Panel_12.setCssClass(“rain-powered”); Panel_20.setCssClass(“rain-powered”); Panel_28.setCssClass(“rain-powered”); Panel_5.setCssClass(“rain-flash”); Panel_13.setCssClass(“rain-flash”); Panel_21.setCssClass(“rain-flash”); Panel_29.setCssClass(“rain-flash”); } if (RainStep === 37) { Text_Loading.applyText(“RENDERING DASHBOARD.”+ cursor); Panel_5.setCssClass(“rain-powered”); Panel_13.setCssClass(“rain-powered”); Panel_21.setCssClass(“rain-powered”); Panel_29.setCssClass(“rain-powered”); Panel_6.setCssClass(“rain-flash”); Panel_14.setCssClass(“rain-flash”); Panel_22.setCssClass(“rain-flash”); Panel_30.setCssClass(“rain-flash”); } if (RainStep === 38) { Text_Loading.applyText(“RENDERING DASHBOARD..”+ cursor); Panel_6.setCssClass(“rain-powered”); Panel_14.setCssClass(“rain-powered”); Panel_22.setCssClass(“rain-powered”); Panel_30.setCssClass(“rain-powered”); Panel_7.setCssClass(“rain-flash”); Panel_15.setCssClass(“rain-flash”); Panel_23.setCssClass(“rain-flash”); Panel_31.setCssClass(“rain-flash”); } if (RainStep === 39) { Text_Loading.applyText(“RENDERING DASHBOARD…”+ cursor); Panel_7.setCssClass(“rain-powered”); Panel_15.setCssClass(“rain-powered”); Panel_23.setCssClass(“rain-powered”); Panel_31.setCssClass(“rain-powered”); Panel_8.setCssClass(“rain-flash”); Panel_16.setCssClass(“rain-flash”); Panel_24.setCssClass(“rain-flash”); Panel_32.setCssClass(“rain-flash”); } // ——————————————————— // PHASE 5 — full system flash // Frame 40 // ——————————————————— if (RainStep === 40) { Text_Loading.applyText(“FINALISING” + cursor); Text_Loading.setCssClass(“loading-text-flash”); Panel_1.setCssClass(“rain-flash”); Panel_2.setCssClass(“rain-flash”); Panel_3.setCssClass(“rain-flash”); Panel_4.setCssClass(“rain-flash”); Panel_5.setCssClass(“rain-flash”); Panel_6.setCssClass(“rain-flash”); Panel_7.setCssClass(“rain-flash”); Panel_8.setCssClass(“rain-flash”); Panel_9.setCssClass(“rain-flash”); |
| Panel_10.setCssClass(“rain-flash”); Panel_11.setCssClass(“rain-flash”); Panel_12.setCssClass(“rain-flash”); Panel_13.setCssClass(“rain-flash”); Panel_14.setCssClass(“rain-flash”); Panel_15.setCssClass(“rain-flash”); Panel_16.setCssClass(“rain-flash”); Panel_17.setCssClass(“rain-flash”); Panel_18.setCssClass(“rain-flash”); Panel_19.setCssClass(“rain-flash”); Panel_20.setCssClass(“rain-flash”); Panel_21.setCssClass(“rain-flash”); Panel_22.setCssClass(“rain-flash”); Panel_23.setCssClass(“rain-flash”); Panel_24.setCssClass(“rain-flash”); Panel_25.setCssClass(“rain-flash”); Panel_26.setCssClass(“rain-flash”); Panel_27.setCssClass(“rain-flash”); Panel_28.setCssClass(“rain-flash”); Panel_29.setCssClass(“rain-flash”); Panel_30.setCssClass(“rain-flash”); Panel_31.setCssClass(“rain-flash”); Panel_32.setCssClass(“rain-flash”); } // ——————————————————— // PHASE 6 — final state // Frame 41 // ——————————————————— if (RainStep === 41) { Text_Loading.applyText(“DASHBOARD READY”); Text_Loading.setCssClass(“loading-text-ready”); Panel_1.setCssClass(“rain-final”); Panel_2.setCssClass(“rain-final”); Panel_3.setCssClass(“rain-final”); Panel_4.setCssClass(“rain-final”); Panel_5.setCssClass(“rain-final”); Panel_6.setCssClass(“rain-final”); Panel_7.setCssClass(“rain-final”); Panel_8.setCssClass(“rain-final”); Panel_9.setCssClass(“rain-final”); Panel_10.setCssClass(“rain-final”); Panel_11.setCssClass(“rain-final”); Panel_12.setCssClass(“rain-final”); Panel_13.setCssClass(“rain-final”); Panel_14.setCssClass(“rain-final”); Panel_15.setCssClass(“rain-final”); Panel_16.setCssClass(“rain-final”); Panel_17.setCssClass(“rain-final”); Panel_18.setCssClass(“rain-final”); Panel_19.setCssClass(“rain-final”); Panel_20.setCssClass(“rain-final”); Panel_21.setCssClass(“rain-final”); Panel_22.setCssClass(“rain-final”); Panel_23.setCssClass(“rain-final”); Panel_24.setCssClass(“rain-final”); Panel_25.setCssClass(“rain-final”); Panel_26.setCssClass(“rain-final”); Panel_27.setCssClass(“rain-final”); Panel_28.setCssClass(“rain-final”); Panel_29.setCssClass(“rain-final”); Panel_30.setCssClass(“rain-final”); Panel_31.setCssClass(“rain-final”); Panel_32.setCssClass(“rain-final”); // Show final message Text_Remember.setVisible(true); Text_Remember.applyText(“Remember…\n\nSORT YOUR DATA FIRST.”); Text_Remember.setCssClass(“remember-message”); Timer_1.stop(); RainRunning = false; } |
// ——————————————————— // Progress bar // 440px track with a small internal margin // ——————————————————— var progressWidth = 4; if (RainStep === 0) { progressWidth = 4; } if (RainStep === 1) { progressWidth = 14; } if (RainStep === 2) { progressWidth = 25; } if (RainStep === 3) { progressWidth = 35; } if (RainStep === 4) { progressWidth = 46; } if (RainStep === 5) { progressWidth = 56; } if (RainStep === 6) { progressWidth = 67; } if (RainStep === 7) { progressWidth = 77; } if (RainStep === 8) { progressWidth = 88; } if (RainStep === 9) { progressWidth = 98; } if (RainStep === 10) { progressWidth = 109; } if (RainStep === 11) { progressWidth = 119; } if (RainStep === 12) { progressWidth = 130; } if (RainStep === 13) { progressWidth = 140; } if (RainStep === 14) { progressWidth = 151; } if (RainStep === 15) { |
| progressWidth = 161; } if (RainStep === 16) { progressWidth = 172; } if (RainStep === 17) { progressWidth = 182; } if (RainStep === 18) { progressWidth = 193; } if (RainStep === 19) { progressWidth = 203; } if (RainStep === 20) { progressWidth = 214; } if (RainStep === 21) { progressWidth = 224; } if (RainStep === 22) { progressWidth = 235; } if (RainStep === 23) { progressWidth = 245; } if (RainStep === 24) { progressWidth = 256; } if (RainStep === 25) { progressWidth = 266; } if (RainStep === 26) { progressWidth = 277; } if (RainStep === 27) { progressWidth = 287; } if (RainStep === 28) { progressWidth = 298; } if (RainStep === 29) { progressWidth = 308; } if (RainStep === 30) { progressWidth = 319; } if (RainStep === 31) { progressWidth = 329; } if (RainStep === 32) { |
| progressWidth = 340; } if (RainStep === 33) { progressWidth = 350; } if (RainStep === 34) { progressWidth = 361; } if (RainStep === 35) { progressWidth = 371; } if (RainStep === 36) { progressWidth = 382; } if (RainStep === 37) { progressWidth = 392; } if (RainStep === 38) { progressWidth = 403; } if (RainStep === 39) { progressWidth = 413; } if (RainStep === 40) { progressWidth = 424; Panel_ProgressFill.setCssClass(“progress-fill-flash”); } if (RainStep === 41) { progressWidth = 436; Panel_ProgressFill.setCssClass(“progress-fill-ready”); } Panel_ProgressFill.getLayout().setWidth(progressWidth); // ——————————————————— // Tongue-in-cheek boot sequence // Safe version: tied directly to existing RainStep frames // ——————————————————— if (RainStep === 0) { BootLog = “> Initialising analytics kernel……… OK”; Text_BootLog.applyText(BootLog); } if (RainStep === 2) { BootLog = BootLog + “\n> Loading semantic layer…………… OK”; Text_BootLog.applyText(BootLog); } if (RainStep === 4) { BootLog = BootLog + “\n> Unified semantic layer…………… We remember Universes.”; Text_BootLog.applyText(BootLog); } if (RainStep === 6) |
| { BootLog = BootLog + “\n> Connecting BW Live………………. OK”; Text_BootLog.applyText(BootLog); } if (RainStep === 8) { BootLog = BootLog + “\n> Loading CDS Views……………….. OK”; Text_BootLog.applyText(BootLog); } if (RainStep === 10) { BootLog = BootLog + “\n> Loading Data Products……………. Still defining them.”; Text_BootLog.applyText(BootLog); } if (RainStep === 12) { BootLog = BootLog + “\n> Validating KPI definitions……….. Debate continues.”; Text_BootLog.applyText(BootLog); } if (RainStep === 14) { BootLog = BootLog + “\n> Loading tabular reporting………… BOBJ sends its regards.”; Text_BootLog.applyText(BootLog); } if (RainStep === 16) { BootLog = BootLog + “\n> Building single source of truth…… Version 14.”; Text_BootLog.applyText(BootLog); } if (RainStep === 18) { BootLog = BootLog + “\n> Initialising AI assistant………… Buzzwords detected.”; Text_BootLog.applyText(BootLog); } if (RainStep === 20) { BootLog = BootLog + “\n> Measuring AI hype……………….. 97%”; Text_BootLog.applyText(BootLog); } if (RainStep === 22) { BootLog = BootLog + “\n> Measuring production value……….. Still loading.”; Text_BootLog.applyText(BootLog); } if (RainStep === 24) { BootLog = BootLog + “\n> Generating executive summary……… \”AI-first\” inserted.”; Text_BootLog.applyText(BootLog); } if (RainStep === 26) { BootLog = BootLog + “\n> Validating AI predictions………… Human judgement retained.”; Text_BootLog.applyText(BootLog); } if (RainStep === 28) { BootLog = BootLog + “\n> Trusting AI completely…………… Negative.”; Text_BootLog.applyText(BootLog); } if (RainStep === 30) { BootLog = BootLog + “\n> Loading AI assistant…………….. Trust starts with clean data.”; Text_BootLog.applyText(BootLog); } if (RainStep === 32) { BootLog = BootLog + “\n> Preparing executive dashboard…….. More green requested.”; Text_BootLog.applyText(BootLog); } if (RainStep === 34) { |
| BootLog = BootLog + “\n> Enabling self-service……………. Excel standing by.”; Text_BootLog.applyText(BootLog); } if (RainStep === 36) { BootLog = BootLog + “\n> Initialising dashboard scripts……. console.log() enabled.”; Text_BootLog.applyText(BootLog); } if (RainStep === 37) { BootLog = BootLog + “\n> Detecting spreadsheet exports…….. Inevitable.”; Text_BootLog.applyText(BootLog); } if (RainStep === 38) { BootLog = BootLog + “\n> Refreshing cache…………………. CTRL+F5 not required.”; Text_BootLog.applyText(BootLog); } if (RainStep === 40) { BootLog = BootLog + “\n> Finalising dashboard…………….. COMPLETE”; Text_BootLog.applyText(BootLog); } if (RainStep === 41) { Text_BootLog.setCssClass(“boot-log-ready”); } // ——————————————————— // Slow heartbeat status indicator // Bright for 6 frames, dim for 6 frames // ——————————————————— // ——————————————————— // Status LED // ——————————————————— if (RainStep < 41) { if ((RainStep % 8) < 2) { Text_Status.applyText(“● SYSTEM BOOTING”); Text_Status.setCssClass(“heartbeat-on”); } else { Text_Status.applyText(“○ SYSTEM BOOTING”); Text_Status.setCssClass(“heartbeat-off”); } } else { Text_Status.applyText(“● SYSTEM ONLINE”); Text_Status.setCssClass(“heartbeat-on”); } // ——————————————————— // Continue animation // ——————————————————— |
if (RainStep < 41) { RainStep = RainStep + 1; var percent = ConvertUtils.numberToString(Math.round((RainStep / 41) * 100)); Text_Progress.applyText(percent + “%”); Timer_1.start(0.18); } |
9. Expected result
| Frames | Stage | What you should see |
| 0–11 | Digital rain | Random cells activate, flash, glitch and leave traces. |
| 12–27 | Energy pulse | The animation moves through the grid in a controlled sequence. |
| 28–31 | Row ignition | Whole rows transition into powered states. |
| 32–39 | Scanner sweep | Columns flash across the grid. |
| 40 | Final flash | All 32 panels flash together. |
| 41 | Ready | Panels become final cards; DASHBOARD READY and SYSTEM ONLINE appear. |
10. Quick checks if it does not work
| Problem | Check |
| Nothing happens | Page_1 onInitialization contains Timer_2.start(1); |
| Panels stay plain | CSS is present and the panel IDs exactly match Panel_1 to Panel_32. |
| Timer error | Timer_1 and Timer_2 exist and scripts are pasted into the correct timer events. |
| Progress does not move | Panel_ProgressFill exists and its width can be controlled by getLayout().setWidth(). |
| Percentage errors | Text_Progress exists with the exact ID. |
| Boot log stays empty | BootLog is a string variable and Text_BootLog exists. |
| Final state never appears | RainStep is an integer, starts at 0, and Timer_1 is allowed to reach frame 41. |
11. CSS class reference
Main classes used by the scripts:
- Panels: rain-dormant, rain-trace, rain-active, rain-process, rain-glitch, rain-flash, rain-powered, rain-final.
- Loading text: loading-text-idle, loading-text-active, loading-text-flash, loading-text-ready.
- Progress: progress-track, progress-fill, progress-fill-flash, progress-fill-ready.
- Status/log: heartbeat-on, heartbeat-off, boot-log, boot-log-ready, remember-message.
- The supplied CSS also contains rain-core-idle, rain-core-active and rain-core-flash for a shape-based central core. The current Timer_1 script does not reference these classes.
12. Build checklist
- 32 panels created and named correctly.
- Five text widgets created and named correctly.
- Progress track and fill created.
- BootLog, RainRunning and RainStep variables created.
- Timer_1 and Timer_2 created.
- CSS pasted.
- Timer_2.start(1); added to Page_1 onInitialization.
- Timer_2 script pasted.
- Timer_1 script pasted.
- Run the application and confirm the loader reaches DASHBOARD READY.


