<!-- PLAYA 2.0'S WORLD · part 11 -->
a1) * R]);
      k.rod(M.red, 0.08, [Math.cos(a1) * R, y0, Math.sin(a1) * R], [Math.cos(a0) * R, y1, Math.sin(a0) * R]);
    }
    k.torus(M.glow, R, 0.08, 0, y1, 0);
  }
  k.cyl(M.red, 1.2, R, 2, 16, 0, 0.6 + h + 1, 0);
  k.cyl(M.glow, 0.3, 0.3, 4, 8, 0, 0.6 + h + 4, 0);
  k.build(); return place(scene, g, opts, { kind: 'land', hx: 4.3, hz: 4.3, pref: 17, cols: [[-4.3, 4.3, -4.3, 4.3, h + 6.6]] });
}
export default { createTwistingSpire, createRingedObelisk, createLatticeTower };


===== FILE: playa-world/world.css =====
:root{--red:#e01937;--red2:#ff2d4b;--bg:#000;--safe-b:env(safe-area-inset-bottom,0px);--safe-t:env(safe-area-inset-top,0px)}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;height:100%;overflow:hidden;background:var(--bg);color:#f2f2f2;font:600 14px/1.2 system-ui,-apple-system,"Segoe UI",sans-serif;touch-action:none;user-select:none;-webkit-user-select:none;overscroll-behavior:none}
#c{position:fixed;inset:0;width:100vw;height:100dvh;display:block;touch-action:none}
#hud{position:fixed;top:calc(10px + var(--safe-t));left:10px;right:10px;max-width:calc(100vw - 20px);display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px;padding:8px 12px;background:rgba(10,0,2,.72);border:1px solid rgba(224,25,55,.55);border-radius:12px;box-shadow:0 0 14px rgba(224,25,55,.35);pointer-events:none}
#hud h1{margin:0;font-size:17px;letter-spacing:.06em;text-transform:uppercase;color:var(--red2);text-shadow:0 0 10px rgba(255,45,75,.8)}
#hud h1 span{color:#fff;text-shadow:none}
#info{font-size:12px;color:#ccc;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
#joy{position:fixed;left:calc(18px + env(safe-area-inset-left,0px));bottom:calc(22px + var(--safe-b));width:132px;height:132px;border-radius:50%;background:radial-gradient(circle,rgba(224,25,55,.18),rgba(0,0,0,.55));border:2px solid rgba(224,25,55,.75);box-shadow:0 0 18px rgba(224,25,55,.45),inset 0 0 18px rgba(224,25,55,.25);touch-action:none}
#knob{position:absolute;left:50%;top:50%;width:56px;height:56px;margin:-28px 0 0 -28px;border-radius:50%;background:radial-gradient(circle at 40% 35%,#ff4a64,#8d0018);box-shadow:0 0 14px var(--red2);pointer-events:none}
#btns{position:fixed;right:calc(18px + env(safe-area-inset-right,0px));bottom:calc(22px + var(--safe-b));display:flex;flex-direction:column;gap:12px;align-items:flex-end}
#btns button{min-width:64px;min-height:64px;border-radius:50%;border:2px solid var(--red);background:rgba(12,0,3,.8);color:#fff;font:800 13px system-ui,sans-serif;letter-spacing:.05em;box-shadow:0 0 14px rgba(224,25,55,.5);touch-action:none;cursor:pointer}
#btns #cam{min-width:48px;min-height:48px;font-size:20px}
#btns button:active,#btns button.on{background:var(--red);box-shadow:0 0 22px var(--red2)}
@media (min-width:900px){#joy{opacity:.55}#hud{right:auto;max-width:520px}}


===== FILE: playa-world/world.js =====
// world.js — Playa 2.0's World: small walkable three.js world (red/black, night sky). JS only.
import { createTwistingSpire, createRingedObelisk, createLatticeTower } from './structures-20.js';
import { createSuspensionBridge, createArchBridge } from './bridges-20.js';
import { createCentralPlaza } from './plaza-20.js';
import { createFloatingIsland } from './floating-island.js';
import { createArchwayGate } from './archway-gate.js';
import { createSpiralTower } from './spiral-tower.js';
import { createMonorailLoop } from './monorail-loop.js';
import { createLanternPath } from './lantern-path.js';
import { createRingPortal } from './ring-portal.js';
import { createFireflies } from './fireflies.js';
const THREE = window.THREE;
const AV_H = 1.56, RAD = 0.32, STEP = 0.45, WORLD_R = 62, CH0 = 26, CH1 = 34; // channel z-range

const canvas = document.getElementById('c');
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, powerPreference: 'high-performance' });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
const scene = new THREE.Scene(); scene.background = new THREE.Color(0x000000); scene.fog = new THREE.FogExp2(0x050002, 0.012);
const camera = new THREE.PerspectiveCamera(62, 1, 0.1, 600);
scene.add(new THREE.HemisphereLight(0x553040, 0x080004, 0.9));
const moon = new THREE.DirectionalLight(0xffe0e6, 0.75); moon.position.set(-30, 50, 20); scene.add(moon);

// ---- sky: stars (1 draw call)
{ const n = 1500, p = new Float32Array(n * 3);
  for (let i = 0; i < n; i++) { const u = Math.random() * 2 - 1, t = Math.random() * Math.PI * 2, y = Math.abs(u) * 0.95 + 0.05, r = Math.sqrt(1 - y * y);
    p.set([Math.cos(t) * r * 400, y * 400, Math.sin(t) * r * 400], i * 3); }
  const g = new THREE.BufferGeometry(); g.setAttribute('position', new THREE.BufferAttribute(p, 3));
  scene.add(new THREE.Points(g, new THREE.PointsMaterial({ color: 0xffffff, size: 1.6, sizeAttenuation: false, fog: false }))); }

// ---- ground, perimeter glow, channel
const ground = new THREE.Mesh(new THREE.CircleGeo