OK你是一名资深前端工程师。请帮我编写纯单文件 HTML 俄罗斯方块，双击即可运行，零依赖。

画布与视觉 300×600px，10×20 网格，单格 30px。深色背景+霓虹配色，居中布局。
7种标准方块，旋转矩阵必须基于原始形状克隆计算，禁止引用共享数组。
每块独立霓虹色，带 shadowBlur 辉光。
右侧 120×120 预览画布显示下一块。

核心机制（防BUG关键） 
方块出生时就完整显示在画布内,按经典速度开始下落.
旋转：使用独立二维数组表示每种方块的4个朝向，禁止运行时矩阵变换；Wall Kick 仅尝试左右各移1格。
消行：**严禁使用 splice/unshift 逐行操作（会导致索引偏移残留空行）。
正确做法：先标记所有满行索引，再遍历棋盘收集非满行按原顺序排列，顶部补空行，最后整体替换 board 数组。**同一帧内完成消除+上方行下移+计分，禁止分帧处理。多行满行必须同时消除干净才可放出下一方块。
碰撞：检测边界与已锁定网格，锁定方块存入二维数组 board[y][x]。


操作与流程 初始显示"开始"按钮，点击激活 AudioContext 并生成首块。
←→ 移动，↑ 旋转，↓ 软降（1.5倍速），空格硬降，ENTER 重置。
状态：IDLE/PLAYING/GAME_OVER，仅 PLAYING 响应按键。

音频（硬性约束） 仅 Web Audio API，自终止函数，零循环结构（for/while/setInterval/setTimeout/RAF）。
模板：创建 Osc+Gain → 设音量 → gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + dur) → osc.stop(ctx.currentTime + dur)，dur≤0.3s。
全局并发锁，最多4个音效，可利用不同顺序为不同场景产生音效，超限丢弃。
AudioContext 在首次点击时 resume()。 自终止计数必须使用 osc.onended 回调，禁止使用 setTimeout。

特效:消行时在对应行生成粒子爆炸；播放音效；1~4行分别显示 "NICE!"/"GREAT!X2"/"AMAZING!X3"/"TETRIS!X4"。时间依次增加1.15倍。
计分逻辑：在已消行数达到12的整数倍数时，速度分别加快15%，并在速度栏显示速度倍数（保留一位小数）

代码规范 IIFE/Class 封装，零全局污染。内联 <style> + <script>。
碰撞、旋转（含Wall Kick）、消行判定、粒子、音频触发处加中文注释。
禁止外部库、Base64音频、Web Worker。

输出 仅输出完整 HTML 代码块，零解释。文件名为 teris528-aa41.html 写完了之后再按需求，逐模块（或逐个代码块） 仔细审查代码，如果有问题要及时修复，确保90%功能OK了再交付给用户。