diff --git a/panther.js b/panther.js
index 991a4bc6df6ffcdbb720250a6b454b179948e071..68ec8cc81854a3d61557053469cd27e606a05ebe 100644
--- a/panther.js
+++ b/panther.js
@@ -42,7 +42,8 @@
 	let cameraStarted = false;
 	const machineCaseSensitive = document.location.search.indexOf('machine=')>-1? document.location.search.split('machine=')[1].split('&')[0]: conf.default_machine;
 	const machine = machineCaseSensitive.toLowerCase();
-	const latticeFile = document.location.href.split('?')[0].split('/').slice(0,-1).join('/')+'/'+machine+'_lattice.json';
+	let latticeFile = document.location.href.split('?')[0].split('/').slice(0,-1).join('/')+'/'+machine+'_lattice.json';
+	if (machine.indexOf('simulator_')>-1) {latticeFile = document.location.href.split('?')[0].split('/').slice(0,-1).join('/')+'/'+'simulator.php?lattice&machine='+machine.split('simulator_')[1];}
 	window.names = [];
 	window.alias = [];
 	let lattice;
@@ -115,7 +116,7 @@
 
 	gui.addColor(params, 'backgroundColor').onChange(function() {toggleParam('backgroundColor');});
 	params.far = typeof conf.default_far[machine]!='undefined'? conf.default_far[machine]: conf.default_far.default;
-	gui.add(params, 'far', 50, 400).onChange(function() {setFar(params.far);});
+	gui.add(params, 'far', 50, 500).onChange(function() {setFar(params.far);});
 	const debugcamera = document.location.search.indexOf('debugcamera')>-1;
 	if (debugcamera) $('body').append('<div class="debug" style="top: 0; position: fixed;"> x: <input size="5" id="x"/>, y: <input size="5" id="y"/>, z: <input size="5" id="z"/>, cx: <input size="5" id="cx"/>, cy: <input size="5" id="cy"/>, cz: <input size="5" id="cz"/>');
 	const highlight = document.location.search.indexOf('highlight=')==-1? []: document.location.search.split('highlight=')[1].split('&')[0].split(',');
@@ -242,6 +243,15 @@
 		}
 		$('body').append('<div style="position: absolute; left: 5px; bottom: 5px;">'+index.join(' ')+'</div>');
 	}
+	function initShortcut(lattice) {
+		const index = [];
+		for (let l in lattice.conf.shortcut) {
+			const cmd = "document.location = document.location.pathname + '?"+lattice.conf.shortcut[l]+"';";
+			index.push('<button onclick="'+cmd+'" id="'+l.toLowerCase().split(' ').join('')+'">'+l+'</button>');
+		}
+		$('body').append('<div style="position: absolute; left: 5px; bottom: 5px;">'+index.join(' ')+'</div>');
+		if(document.location.search.indexOf('ps')>-1) $('#powersupplies').css('background-color', 'limegreen');
+	}
 	fetch(latticeFile).then((response) => {return response.json();}).then((flattice) => {
 		lattice = flattice;
 		const blmfacilities = [''];
@@ -298,7 +308,7 @@
 		params.gotoAdmin = function() {document.location = './admin.php';};
 		gui.add(params, 'gotoAdmin').name('Admin');
 		$('#ui-id-1').css('z-index', 10000000);
-		if (document.location.search.indexOf('highlight=')>-1) {$('<div><iframe style="width: 100%;height:250px;" src="../misc/gauge.html?dark&r2only=1&r=100&ringwidth=58&max=1&throttlingPeriod=50&apply=shrink&val='+params.highlightShrink+'"></iframe></div>').insertBefore('.function');}
+		if (document.location.search.indexOf('highlight=')>-1) {$('<div><iframe style="width: 100%;height:250px;" src="./spa/gauge.html?dark&r2only=1&r=100&ringwidth=58&max=1&throttlingPeriod=50&apply=shrink&val='+params.highlightShrink+'"></iframe></div>').insertBefore('.function');}
 		for (let i in lattice) {if (i!='conf') initLattice(lattice[i].sections, i);}
 		if (vlv) {
 			fetch(conf.vlvSrcUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
@@ -322,6 +332,7 @@
 		params.goto2D = function() {document.location = './panther2d.php?machine='+params.machine;};
 		gui.add(params, 'goto2D').name('2D');
 		if (document.location.search.indexOf('search=')>-1) findComponent(document.location.search.split('search=')[1].split('&')[0], false);
+		if (lattice.conf && lattice.conf.shortcut) initShortcut(lattice);
 		if (lattice.conf && lattice.conf.index) initIndex(lattice);
 		console.log(lattice, facilities);
 		if (ps) {
@@ -344,9 +355,9 @@
 	})
 	.catch(error => {console.log("Fetch error", error);});
 	function showStatus(i, stat) {
-			status[i].scale.x = 1;
-			status[i].scale.y = 1;
-			status[i].scale.z = 1;
+		status[i].scale.x = 1;
+		status[i].scale.y = 1;
+		status[i].scale.z = 1;
 		if (stat == 'null' || stat == '' || stat == 0 || (!fel1 && status[i].facility=='fel1') || (!fel2 && status[i].facility=='fel2')) {status[i].visible = false;}
 		else if (stat == 'ON' || stat == 'RUNNING') {
 			status[i].visible = true; 
@@ -364,7 +375,7 @@
 		}
 	}
 	let statVal;
-	const statScale = 0.3; 
+	const statScale = 0.07; 
 	function updateStatus() {
 		fetch(conf.stateUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
 			// console.log('updateStatus()', fel1, fel2, status);
@@ -455,12 +466,12 @@
 	}
 	// status
 	const normalMaterial = new THREE.MeshBasicMaterial({ color: 0xffff66});
-	const sphereGeometry = new THREE.SphereGeometry(300, 10, 10);
+	const sphereGeometry = new THREE.SphereGeometry(500, 10, 10);
 	const rot = {x: $('#rotx').val(), y: $('#roty').val(), z: $('#rotz').val()};
 	let gltfscene;
 
 	function pushComponent(facility, i, m, tang, direction, y=Ydefault) {
-		let magnet = lattice[facility].sections[i].components[m].type;
+		let magnet = m>-1? lattice[facility].sections[i].components[m].type: 'dipole';
 		if (typeof compBuffer[magnet] == 'undefined') compBuffer[magnet] = [];
 		compBuffer[magnet].push({facility: facility, i: i, m: m, tang: tang, direction: direction, y: y});
 	}
@@ -481,24 +492,24 @@
 			const tang = compBuffer[magnet][l].tang;
 			const direction = compBuffer[magnet][l].direction;
 			const y = compBuffer[magnet][l].y;
-			const myname = lattice[facility].sections[i].components[m].name;
-			console.log(facility, i, m, lattice[facility].sections[i].components[m]);
+			const myname = m==-1? lattice[facility].sections[i].bending.name: lattice[facility].sections[i].components[m].name;
+			console.log(facility, i, m, myname);
 			const id = extractId(myname);
-			const d = lattice[facility].sections[i].components[m].position;
+			const d = m==-1? 0: lattice[facility].sections[i].components[m].position;
 			const den = Math.sqrt(tang*tang+1) * direction;
-			const offset = lattice[facility].sections[i].components[m].offset3d? lattice[facility].sections[i].components[m].offset3d: [0, 0, 0];
+			const offset = m>-1 && lattice[facility].sections[i].components[m].offset3d? lattice[facility].sections[i].components[m].offset3d: [0, 0, 0];
 			mycomp.position.set(params.highlightScale*(lattice[facility].sections[i].start.x + tang*d / den) + offset[0], y + offset[1], params.highlightScale*(lattice[facility].sections[i].start.z + d / den + offset[2]));
 			if (mycomp.rotatedX) {mycomp.rotateZ(Math.atan(-tang));} else mycomp.rotateY(Math.atan(tang));
-			window.names.push(lattice[facility].sections[i].components[m].name);
-			if (lattice[facility].sections[i].components[m].embedded) {
+			window.names.push(myname);
+			if (m>-1 && lattice[facility].sections[i].components[m].embedded) {
 				// console.log('mycomp.embedded',lattice[facility].sections[i].components[m].embedded);
 				for (let j=0; j<lattice[facility].sections[i].components[m].embedded.length; j++)  {names.push(lattice[facility].sections[i].components[m].embedded[j]); alias.push([myname,lattice[facility].sections[i].components[m].embedded[j]]);}
 			}
 			if (id[1]) {window.names.push(id[1]); alias.push(id);}
 			mycomp.magnetType = magnet;
-			mycomp.name = lattice[facility].sections[i].components[m].name;
+			mycomp.name = myname;
 			compBuffer[magnet][l].name = mycomp.name;
-			if (lattice[facility].sections[i].components[m].href) mycomp.href = lattice[facility].sections[i].components[m].href;
+			if (m>-1 && lattice[facility].sections[i].components[m].href) mycomp.href = lattice[facility].sections[i].components[m].href;
 			if (highlight.length && !highlight.find(element => element == magnet)) {mycomp.scale.set(params.highlightShrink, params.highlightShrink, params.highlightShrink);}
 			facilities[facility].add(mycomp);
 			compBuffer[magnet][l].mycomp = mycomp;
@@ -544,12 +555,13 @@
 			if (magnet=='blm') {blmres.append(blm, facility, mycomp, direction);}
 			if (magnet=='vlv') {vlvs.push({'comp': mycomp, 'name': mycomp.name, 'type': magnet});}
 			if (magnet=='bst') {vlvs.push({'comp': mycomp, 'name': mycomp.name, 'type': magnet});}
-			if (Math.abs(den)>0.00001) {
-				if (mycomp.ps) {
-					for (let pi=0; pi<mycomp.ps.length; pi++) {
+			if (Math.abs(den)>0.00001 && document.location.search.indexOf('nops')==-1) {
+				if (mycomp.name.indexOf('CHV_S')>-1) console.log(mycomp, i, m, lattice[facility].sections[i].components[m]);
+				if (typeof lattice[facility].sections[i].components[m].ps == "object") {
+					for (let pi=0; pi<lattice[facility].sections[i].components[m].ps.length; pi++) {
 						const sphere = new THREE.Mesh(sphereGeometry,normalMaterial.clone());
-						sphere.position.set(params.highlightScale*(lattice[facility].sections[i].start.x + tang*d / den) - 50 + 50*pi, y+350, params.highlightScale*(lattice[facility].sections[i].start.z + d / den));
-						sphere.name = mycomp.ps[pi].replace('PS','') + '_status';
+						sphere.position.set(params.highlightScale*(lattice[facility].sections[i].start.x + tang*d / den) - 50 + 50*pi, y+500, params.highlightScale*(lattice[facility].sections[i].start.z + d / den));
+						sphere.name = lattice[facility].sections[i].components[m].ps[pi].replace('PS','') + '_status';
 						sphere.facility = facility;
 						sphere.visible = false;
 						status.push(sphere);
@@ -558,7 +570,7 @@
 				}
 				else {
 					const sphere = new THREE.Mesh(sphereGeometry,normalMaterial.clone());
-					sphere.position.set(params.highlightScale*(lattice[facility].sections[i].start.x + tang*d / den), y+350, params.highlightScale*(lattice[facility].sections[i].start.z + d / den));
+					sphere.position.set(params.highlightScale*(lattice[facility].sections[i].start.x + tang*d / den), y+500, params.highlightScale*(lattice[facility].sections[i].start.z + d / den));
 					sphere.name = mycomp.name+'_status';
 					sphere.facility = facility;
 					sphere.visible = false;
@@ -600,31 +612,36 @@
 			let bendingType = flattice[j].bending? flattice[j].bending.type: '';
 			if (componentCreator[bendingType+'fast'] && (fast==false || fast.indexOf(bendingType)>-1)) bendingType = bendingType+'fast';
 			if (componentCreator[bendingType+'premium'] && (premium==false || premium.indexOf(bendingType)>-1)) bendingType = bendingType+'premium';
+			const direction = (facility=='servicearea'? 1: 1)*((flattice[j].start.z<flattice[i].start.z /*!= flattice[j].start.x<=flattice[i].start.x*/)? -1: 1);
 			if (document.location.search.indexOf('components=hide')==-1 && flattice[j].bending && bendingType && typeof componentCreator[bendingType]!== 'undefined') {
-				component[dipoleNum] = flattice[j].bending.length? componentCreator[bendingType](flattice[j].bending.length): componentCreator[bendingType]();
-				component[dipoleNum].position.set(params.highlightScale*flattice[j].start.x, y-params.highlightScale*100, params.highlightScale*flattice[j].start.z);
-				component[dipoleNum].name = flattice[j].bending.name;
-				const a1 = Math.atan2((flattice[j].start.z-flattice[i].start.z), (flattice[j].start.x-flattice[i].start.x));
-				const a2 = Math.atan2((flattice[k].start.z-flattice[j].start.z),(flattice[k].start.x-flattice[j].start.x));
-				alpha = (a1 + a2)/2;
-				if (a1>0 && a2<0) alpha += Math.PI;
-				component[dipoleNum].rotateY(3*Math.PI/2-alpha);
-				if (highlight.length && !highlight.find(element => (element == 'bending' || element == bendingType))) {component[dipoleNum].scale.set(params.highlightShrink, params.highlightShrink, params.highlightShrink);}
-				component[dipoleNum].magnetType = bendingType;
-				facilities[facility].add(component[dipoleNum]);
-				if (1 || flattice[j].bending.label && flattice[j].bending.label=='show') {
-					const div = document.createElement('div');
+				if (real && typeof conf.real[bendingType] !== 'undefined') {
+					pushComponent(facility, i, -1, tang, direction, y);
+				}
+				else {
+					component[dipoleNum] = flattice[j].bending.length? componentCreator[bendingType](flattice[j].bending.length): componentCreator[bendingType]();
+					component[dipoleNum].position.set(params.highlightScale*flattice[j].start.x, y-params.highlightScale*100, params.highlightScale*flattice[j].start.z);
+					component[dipoleNum].name = flattice[j].bending.name;
+					const a1 = Math.atan2((flattice[j].start.z-flattice[i].start.z), (flattice[j].start.x-flattice[i].start.x));
+					const a2 = Math.atan2((flattice[k].start.z-flattice[j].start.z),(flattice[k].start.x-flattice[j].start.x));
+					alpha = (a1 + a2)/2;
+					if (a1>0 && a2<0) alpha += Math.PI;
+					component[dipoleNum].rotateY(3*Math.PI/2-alpha);
+					if (highlight.length && !highlight.find(element => (element == 'bending' || element == bendingType))) {component[dipoleNum].scale.set(params.highlightShrink, params.highlightShrink, params.highlightShrink);}
+					component[dipoleNum].magnetType = bendingType;
 					facilities[facility].add(component[dipoleNum]);
-					div.id = 'B' + dipoleNum; // 'B'+i; // flattice[j].bending.name; //
-					div.classList = [facility];
-					div.style.cssText = 'position: absolute; color: white;';
-					div.innerHTML = flattice[j].bending.name;
-					document.body.appendChild(div);
-					dipoleNum++;
+					if (1 || flattice[j].bending.label && flattice[j].bending.label=='show') {
+						const div = document.createElement('div');
+						facilities[facility].add(component[dipoleNum]);
+						div.id = 'B' + dipoleNum; // 'B'+i; // flattice[j].bending.name; //
+						div.classList = [facility];
+						div.style.cssText = 'position: absolute; color: white;';
+						div.innerHTML = flattice[j].bending.name;
+						document.body.appendChild(div);
+						dipoleNum++;
+					}
 				}
 				window.names.push(flattice[j].bending.name);
 			}
-			const direction = (facility=='servicearea'? 1: 1)*((flattice[j].start.z<flattice[i].start.z /*!= flattice[j].start.x<=flattice[i].start.x*/)? -1: 1);
 			if (document.location.search.indexOf('components=hide')==-1) if (flattice[i].components) for (let m=0; m<flattice[i].components.length; m++) {
 				// if (facility=='servicearea') console.log(facility, i, m, tang, direction);
 				const position = appendComponent(facility, i, m, tang, direction, y);
@@ -652,11 +669,11 @@
 			vlvVal[0] = vlvVal[0].split(':')[1];
 			// console.log(conf.vlvUrl, vlvVal, vlvs);
 			for (let i=0; i<vlvs.length; i++) {
-				if (vlvs[i].type=='vlv') componentCreator.vlvUpdate(vlvs[i].comp, vlvVal[vlvs[i].vlvindex]=='CLOSED'? 'yellow': (vlvVal[vlvs[i].vlvindex]=='OPENED'? 'limegreen': 'grey'));
+				if (vlvs[i].type=='vlv') componentCreator.vlvUpdate(vlvs[i].comp, vlvVal[vlvs[i].vlvindex]=='CLOSED'? 'red': (vlvVal[vlvs[i].vlvindex]=='OPENED'? 'limegreen': 'grey'));
 				if (vlvs[i].type=='bst') {
 					if (typeof vlvVal[vlvs[i].vlvindex] != 'string') continue;
 					const val = vlvVal[vlvs[i].vlvindex].split(',');
-					componentCreator.bstUpdate(vlvs[i].comp, val[0]=='true'? 'limegreen': (val[1]=='true'? 'yellow': 'grey'));
+					componentCreator.bstUpdate(vlvs[i].comp, val[0]=='true'? 'limegreen': (val[1]=='true'? 'red': 'grey'));
 				}
 			}
 		})