<!-- RUBY-BACKUP · part 362 -->
             'float lineMask = mix(0.0, 1.0, smoothstep(0.7, 0.2, shade));',
              'float crossMask = mix(0.0, 1.0, smoothstep(0.4, 0.0, shade));',
              'vec3 hatchCol = vec3(0.05, 0.02, 0.0);',
              'gl_FragColor.rgb = mix(gl_FragColor.rgb, hatchCol, (1.0-hatch1)*lineMask*0.55);',
              'gl_FragColor.rgb = mix(gl_FragColor.rgb, hatchCol, (1.0-hatch2)*crossMask*0.4);',
              '#include <dithering_fragment>'
            ].join('\n')
          );
        };
        o.material.needsUpdate = true;
        count++;
      }catch(e){}
    });
    codeStatus('true intaglio — ' + count + ' parts lined');
  }catch(e){ codeStatus('intaglio failed'); }
}
/* PRIMITIVES — Playa 2.0 specs, real 3D meshes */
/* Command stack for functional undo (Playa 2.0: Command Pattern) */
window._cmdStack = window._cmdStack || [];
window._cmdIndex = window._cmdIndex || -1;
function pushCommand(cmd){
  /* cmd = {name, execute, undo} */
  window._cmdStack = window._cmdStack.slice(0, window._cmdIndex+1);
  window._cmdStack.push(cmd);
  window._cmdIndex++;
  try{ cmd.execute(); }catch(e){}
}
function undoCommand(){
  if(window._cmdIndex < 0){ try{ codeStatus('nothing to undo'); }catch(e){} return; }
  var cmd = window._cmdStack[window._cmdIndex];
  try{ cmd.undo(); }catch(e){}
  window._cmdIndex--;
  try{ codeStatus('undid ' + cmd.name); }catch(e){}
}
function redoCommand(){
  if(window._cmdIndex >= window._cmdStack.length-1){ try{ codeStatus('nothing to redo'); }catch(e){} return; }
  window._cmdIndex++;
  var cmd = window._cmdStack[window._cmdIndex];
  try{ cmd.execute(); }catch(e){}
  try{ codeStatus('redid ' + cmd.name); }catch(e){}
}
function buildHourglass(){
  try{
    var g = new THREE.Group();
    var mat = new THREE.MeshStandardMaterial({color:0xd4a017, roughness:0.4, metalness:0.3});
    /* top cone (inverted) */
    var top = new THREE.Mesh(new THREE.ConeGeometry(1.2, 1.8, 4), mat);
    top.position.y = 0.9;
    top.rotation.x = Math.PI;
    top.name = 'vcore-top';
    g.add(top);
    /* bottom cone */
    var bot = new THREE.Mesh(new THREE.ConeGeometry(1.2, 1.8, 4), mat);
    bot.position.y = -0.9;
    bot.name = 'vcore-bottom';
    g.add(bot);
    /* core pin at the waist */
    var pin = new THREE.Mesh(new THREE.SphereGeometry(0.25, 12, 10), new THREE.MeshStandardMaterial({color:0x111111, roughness:0.3}));
    pin.name = 'vcore-pin';
    g.add(pin);
    /* gold caps */
    var capT = new THREE.Mesh(new THREE.BoxGeometry(2.6, 0.25, 2.6), new THREE.MeshStandardMaterial({color:0xffd700, metalness:0.8, roughness:0.2}));
    capT.position.y = 1.9;
    capT.name = 'vcore-cap-top';
    g.add(capT);
    var capB = capT.clone();
    capB.position.y = -1.9;
    capB.name = 'vcore-cap-bottom';
    g.add(capB);
    g.position.set(-20, 2.5, -20);
    /* twist/bend rigging (Playa 2.0 spec) */
    g.userData.twist = 0;
    g.userData.bend = 0;
    g.userData.applyRig = function(){
      top.rotation.y = g.userData.twist;
      bot.rotation.y = -g.userData.twist;
      g.rotation.z = g.userData.bend * 0.1;
    };
    window._hourglassRig = function(twist, bend){
      if(window._hourglass){
        window._hourglass.userData.twist = twist || 0;
        window._hourglass.userData.bend = bend || 0;
        window._hourglass.userData.applyRig();
      }
    };
    if(typeof scene!=='undefined') scene.add(g);
    window._hourglass = g;
    g.userData.isPrimitive = true;
    /* command for undo */
    var sceneRef = (typeof scene!=='undefined') ? scene : null;
    pushCommand({
      name: 'build hourglass',
      execute: function(){ if(sceneRef) sceneRef.add(g); },
      undo: function(){ if(sceneRef) sceneRef.remove(g); }
    });
    codeStatus('hourglass V-Core — real');
  }catch(e){ codeStatus('hourglass failed'); }
}
function buildPylon(){
  try{
    var g = new THREE.Group();
    var stoneMat = new THREE.MeshStandardMaterial({color:0x8a8a8a, roughness:0.8});
    var goldMat = new THREE.MeshStandardMaterial({color:0xffd700, metalness:0.8, roughness:0.2});
    /* base */
    var base = new THREE.Mesh(new THREE.BoxGeometry(1.6, 0.4, 1.6), stoneMat);
    base.position.y = 0.2;
    base.name = 'pylon-base';
    g.add(base);
    /* shaft — tapered with FLUTING (Playa 2.0 spec) */
    var shaft = new THREE.Mesh(new THREE.CylinderGeometry(0.45, 0.55, 4.5, 24), stoneMat);
    shaft.position.y = 2.65;
    shaft.name = 'pylon-shaft';
    g.add(shaft);
    /* fluting — 12 vertical grooves */
    for(var fl=0; fl<12; fl++){
      var angle = (fl/12) * Math.PI * 2;
      var groove = new THREE.Mesh(
        new THREE.BoxGeometry(0.08, 4.4, 0.12),
        new THREE.MeshStandardMaterial({color:0x6a6a6a, roughness:0.9})
      );
      var rx = Math.cos(angle) * 0.5;
      var rz = Math.sin(angle) * 0.5;
      groove.position.set(rx, 2.65, rz);
      groove.rotation.y = -angle;
      groove.name = 'pylon-flute';
      g.add(groove);
    }
    /* gold rings */
    for(var r=0; r<3; r