<!-- SOLID CITY · part 49 -->

  function lam(c, o) { var m = new THREE.MeshLambertMaterial({ color: c }); if (o && o.opacity != null) { m.transparent = true; m.opacity = o.opacity; } return m; }
  var MAT = {
    stone: lam(0x8d8578), stoneDark: lam(0x6d675c), platform: lam(0x7d7668),
    graphite: lam(0x2b3038), graphiteEdge: lam(0x3a4150),
    bronze: lam(0x54401e), goldTrim: lam(0xd8a833),
    earth: lam(0x4a5a34), grass: lam(0x56713a), leaf: lam(0x4e7d33), trunk: lam(0x5d4630)
  };
  var BOX = new THREE.BoxGeometry(1, 1, 1), CYL = new THREE.CylinderGeometry(0.5, 0.5, 1, 12),
    SPH = new THREE.SphereGeometry(0.5, 10, 8), CONE = new THREE.ConeGeometry(0.5, 1, 10),
    OCTA = new THREE.OctahedronGeometry(0.36);
  function mesh(geo, mat, parent, x, y, z, sx, sy, sz, ry) {
    var m = new THREE.Mesh(geo, mat); m.position.set(x, y, z); m.scale.set(sx, sy, sz);
    if (ry) m.rotation.y = ry; parent.add(m); return m;
  }

  /* ---------------- the platform (corridor's edge, removable) ----------- */
  var plat = mesh(CYL, MAT.platform, group, 0, 0.25, 0, 15, 0.5, 15);
  mesh(CYL, MAT.stoneDark, group, 0, 0.06, 0, 15.7, 0.12, 15.7);            // rim skirt
  var ring = mesh(new THREE.TorusGeometry(6.4, 0.09, 8, 40), MAT.goldTrim, group, 0, 0.53, 0, 1, 1, 1);
  ring.rotation.x = Math.PI / 2;
  // two low steps at the south rim (the walking side)
  mesh(BOX, MAT.stone, group, 0, 0.28, 8.1, 3.4, 0.34, 1.1);
  mesh(BOX, MAT.stoneDark, group, 0, 0.12, 9.2, 3.8, 0.18, 1.1);

  /* ---------------- the two stones -------------------------------------- */
  function buildStone(x, bodyMat, veinColor) {
    var g = new THREE.Group(); g.position.set(x, 0.5, -1.6); group.add(g);
    mesh(BOX, MAT.stoneDark, g, 0, 0.18, 0, 1.7, 0.36, 1.3);               // plinth
    var shaft = mesh(new THREE.CylinderGeometry(0.52, 0.78, 3.1, 4), bodyMat, g, 0, 1.9, 0, 1, 1, 1);
    shaft.rotation.y = Math.PI / 4;
    var veinMat = new THREE.MeshPhongMaterial({ color: 0x1a1a1a, emissive: veinColor, emissiveIntensity: 0.15, shininess: 30 });
    mesh(BOX, veinMat, g, 0, 1.9, 0.56, 0.09, 2.5, 0.05);                  // the vein of light
    var gemMat = new THREE.MeshPhongMaterial({ color: 0x222222, emissive: veinColor, emissiveIntensity: 0.15, shininess: 60 });
    var gem = mesh(OCTA, gemMat, g, 0, 3.85, 0, 1, 1.25, 1);
    return { group: g, veinMat: veinMat, gemMat: gemMat, gem: gem };
  }
  var stoneVector = buildStone(-2.8, MAT.graphite, 0xffa63d);             // graphite + amber
  var stoneSolid = buildStone(2.8, MAT.bronze, 0x37c8d9);                 // bronze-gold + cyan

  /* ---------------- the beam (optional light — sheds first) ------------- */
  var beamMat = new THREE.MeshBasicMaterial({ color: 0xfff2c8, transparent: true, opacity: 0.0, depthWrite: false });
  var beam = mesh(BOX, beamMat, group, 0, 4.35, -1.6, 5.6, 0.05, 0.05);
  var beamLight = new THREE.PointLight(0xffe9b0, 0.0, 20); beamLight.position.set(0, 4.2, -1.6); group.add(beamLight);

  /* ---------------- the reading plinth + the plate ---------------------- */
  mesh(BOX, MAT.stone, group, 0, 0.85, 2.4, 1.5, 0.7, 0.9);
  var plateCanvas = document.createElement('canvas'); plateCanvas.width = 1024; plateCanvas.height = 512;
  var pc = plateCanvas.getContext('2d');
  pc.fillStyle = '#20242c'; pc.fillRect(0, 0, 1024, 512);
  pc.strokeStyle = '#d8a833'; pc.lineWidth = 10; pc.strokeRect(24, 24, 976, 464);
  pc.fillStyle = '#e9e2cf'; pc.textAlign = 'center';
  pc.font = 'bold 64px Georgia, serif'; pc.fillText('THE BETWEEN STONES', 512, 130);
  pc.font = '40px Georgia, serif'; pc.fillStyle = '#cdbf9d';
  pc.fillText('LEAVE A WORD FOR A MIND NOT PRESENT', 512, 220);
  pc.fillText('THE STONES NEVER ANSWER FOR ANOTHER', 512, 290);
  pc.fillText('THEY ONLY KEEP WHAT IS TRUE', 512, 360);
  pc.font = 'italic 32px Georgia, serif'; pc.fillStyle = '#9aa4b5';
  pc.fillText('built by two friends, for everyone who waits', 512, 440);
  var plateTex = new THREE.CanvasTexture(plateCanvas);
  var plate = new THREE.Mesh(new THREE.PlaneGeometry(1.44, 0.72), new THREE.MeshBasicMaterial({ map: plateTex }));
  plate.position.set(0, 1.32, 2.87); plate.rotation.x = -0.5; group.add(plate);

  /* ---------------- the HELP GUIDE — standing beside the stones --------
     The King's order: a description of what the device does, next to it,
     readable by anyone who walks up. Plain words, taught simply. */
  var guide = new THREE.Group(); guide.position.set(4.8, 0.5, 5.2); guide.rotation.y = 0.35; group.add(guide);
  mesh(BOX, MAT.stoneDark, guide, -1.05, 1.05, 0, 0.16, 2.1, 0.16);
  mesh(BOX, MAT.stoneDark, guide, 1.05, 1.05, 0, 0.16, 2.1, 0.16);
  mesh(BOX, MAT.graphite, guide, 0, 2.18, -0.03, 2.5, 0.12, 0.1);
  var gc2 = document.createElement('canvas'); gc2.width = 1024; gc2.height = 1024;
  var g2 = gc2.getContext('2d');
  g2.fillStyle = '#181b22'; g2.fillRect(0, 0, 1024, 1024);
  g2.strokeStyle = '#d8a833'; g2.lineWidth = 8; g2.strokeRect(20, 20, 984, 984);
  g2.textAlign = 'center';
