This commit is contained in:
brookee 2024-01-29 20:46:10 -05:00
parent d73b9b27f7
commit 8bc6e2496b
3 changed files with 135 additions and 772 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,421 +1,111 @@
// <CRYPTO_DONATION>
(function () {
"use strict";
var donateButton = document.getElementById("donateButton");
var card = document.getElementById("card");
// braille
donateButton.addEventListener("click", function (event) {
event.stopPropagation();
if (card.classList.contains("card-out")) {
card.classList.remove("card-out");
card.classList.add("card-in");
} else {
card.classList.remove("card-in");
card.classList.add("card-out");
}
});
const enc = (x) =>
((x & 0x08) << 3) | ((x & 0x70) >> 1) | (x & 0x87) | 0x2800;
const row = (x) => String.fromCharCode(...Array.from(x, enc));
window.addEventListener("click", function (event) {
if (event.target === card || card.contains(event.target)) {
return;
}
const create = (width, height) =>
Array.from(Array(height >> 2), () => new Uint8Array(width >> 1));
if (card.classList.contains("card-in")) {
card.classList.remove("card-in");
card.classList.add("card-out");
}
});
const set = (table, x, y) =>
(table[y >> 2][x >> 1] |= 1 << ((y & 3) | ((x & 1) << 2)));
var cryptoWallets = [
{
symbol: "XMR",
name: "Monero",
address:
"49r2aeun8DtV5VqZpZSwRpS83WfUWEaLt4NG8HJwwVkbiT1vSsXTXrPFKkKTdc6MPX9iezbTidNPvhGZKCnM1338TfK6Hgi"
},
{
symbol: "LTC",
name: "Litecoin",
address: "LRAm7h5XENknfYEpbdVsvyGY8D6MiXGTDV"
},
{
symbol: "BTC",
name: "Bitcoin",
address: "bc1qkv97ajh7f0a72l9rsjd3fmmly5q5uywr06q3x0"
}
];
const render = (table) => table.map(row).join("\n");
var walletsContainer = document.getElementById("wallets");
var qrImage = document.getElementById("qrImage");
var donateTitle = document.getElementById("donateTitle");
var donateWarn = document.getElementById("donateWarn");
var walletAddress = document.getElementById("walletAddress");
var copyButton = document.getElementById("copyButton");
// util
function selectWallet(symbol) {
var wallet = cryptoWallets.find(function (w) {
return w.symbol === symbol;
});
if (!wallet) return;
const frame = () => new Promise((resolve) => requestAnimationFrame(resolve));
var buttons = Array.from(walletsContainer.children);
buttons.forEach(function (button) {
button.classList.remove("active");
if (button.textContent === symbol) {
button.classList.add("active");
}
});
const element = (name, options) =>
Object.assign(document.createElement(name), options);
qrImage.src =
"https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=" +
wallet.address;
donateTitle.textContent = "Donate " + wallet.name;
donateWarn.textContent =
"Send only " +
wallet.name +
" (" +
wallet.symbol +
") to this deposit address. Sending any other coin or token to this address may result in the loss of your donation. Thanks!";
walletAddress.value = wallet.address;
copyButton.textContent = "✚ Copy";
}
// bayer
function copyText() {
var input = document.createElement("input");
document.body.appendChild(input);
input.value = walletAddress.value;
input.select();
document.execCommand("copy");
document.body.removeChild(input);
copyButton.textContent = "✔ Copied";
}
cryptoWallets.forEach(function (wallet) {
var button = document.createElement("button");
button.textContent = wallet.symbol;
button.addEventListener("click", function () {
selectWallet(wallet.symbol);
});
walletsContainer.appendChild(button);
});
copyButton.addEventListener("click", copyText);
selectWallet(cryptoWallets[0].symbol);
// </CRYPTO_DONATION>
let globalUniforms = {
time: { value: 0 }
};
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
import {
CSS2DRenderer,
CSS2DObject
} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/renderers/CSS2DRenderer.js";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 2000);
camera.position.set(-5, 4, -0.8).setLength(14);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0x241917);
document.body.appendChild(renderer.domElement);
let labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = "absolute";
labelRenderer.domElement.style.top = "0px";
document.body.appendChild(labelRenderer.domElement);
window.addEventListener("resize", onWindowResize);
let controls = new OrbitControls(camera, labelRenderer.domElement);
controls.enablePan = false;
controls.minDistance = 10;
controls.maxDistance = 14;
controls.enableDamping = true;
controls.autoRotate = false;
// <GLOBE>
let counter = 40000;
let rad = 5;
let sph = new THREE.Spherical();
let r = 0;
let dlong = Math.PI * (3 - Math.sqrt(5));
let dz = 2 / counter;
let long = 0;
let z = 1 - dz / 2;
let pts = [];
let clr = [];
let c = new THREE.Color();
let uvs = [];
for (let i = 0; i < counter; i++) {
r = Math.sqrt(1 - z * z);
let p = new THREE.Vector3(
Math.cos(long) * r,
z,
-Math.sin(long) * r
).multiplyScalar(rad);
pts.push(p);
z = z - dz;
long = long + dlong;
c.setHSL(0.45, 0.5, Math.random() * 0.25 + 0.25);
c.toArray(clr, i * 3);
sph.setFromVector3(p);
uvs.push((sph.theta + Math.PI) / (Math.PI * 2), 1.0 - sph.phi / Math.PI);
}
let g = new THREE.BufferGeometry().setFromPoints(pts);
g.setAttribute("color", new THREE.Float32BufferAttribute(clr, 3));
g.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2));
let m = new THREE.PointsMaterial({
size: 0.17,
vertexColors: false,
color: new THREE.Color(0x743c2f),
onBeforeCompile: (shader) => {
shader.uniforms.globeTexture = {
value: new THREE.TextureLoader().load(imgData)
const bayer = (order, x, y) => {
let z = 0;
for (let i = order; i--; x >>= 1, y >>= 1)
z = ((((x & 1) ^ (y & 1)) | (z << 1)) << 1) | (y & 1);
return z;
};
shader.vertexShader = `
uniform sampler2D globeTexture;
varying float vVisibility;
varying vec3 vNormal;
varying vec3 vMvPosition;
${shader.vertexShader}
`.replace(
`gl_PointSize = size;`,
`
vVisibility = texture(globeTexture, uv).g;
gl_PointSize = size * (vVisibility < 0.5 ? 1. : 0.75);
vNormal = normalMatrix * normalize(position);
vMvPosition = -mvPosition.xyz;
gl_PointSize *= 0.4 + (dot(normalize(vMvPosition), vNormal) * 0.6);
`
);
shader.fragmentShader = `
varying float vVisibility;
varying vec3 vNormal;
varying vec3 vMvPosition;
${shader.fragmentShader}
`.replace(
`vec4 diffuseColor = vec4( diffuse, opacity );`,
`
bool circ = length(gl_PointCoord - 0.5) > 0.5;
bool vis = dot(vMvPosition, vNormal) < 0.;
if (circ || vis) discard;
vec3 col = diffuse + (vVisibility > 0.5 ? 0.5 : 0.);
const lut = (order) => {
const size = 1 << order,
area = size * size;
const lut = new Float32Array(area);
for (let y = 0; y < size; y++)
for (let x = 0; x < size; x++)
lut[x + y * size] = (bayer(order, x, y) + 0.5) / area;
return (x, y) => lut[(x % size) + (y % size) * size];
};
vec4 diffuseColor = vec4( col, opacity );`
);
// render
const simplex = new SimplexNoise();
const bayer4 = lut(4);
const fbm = (freq, amp, x, y, z) =>
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) +
simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2);
const texture = (u, v, w) => (2 * (0.5 + 0.5 * fbm(0.5, 1, u, v, w))) % 1;
const globe = (x, y, u, v, w) => {
const d = u * u + v * v;
if (d > 1) return false;
const f = 1 / ((1 - d ** 0.5) ** 0.5 + 1);
const t = texture(1e-1 * w + f * u, f * v, 1e-2 * w);
return t > bayer4(x, y);
};
// main
const main = async () => {
const fillerSize = 100;
const filler =
"\u28ff".repeat(fillerSize) + "\n\u28ff".repeat(fillerSize - 1);
const root = element("div", { className: "braille" });
const hidden = element("div", { className: "hidden", textContent: filler });
const visible = element("div", { className: "visible" });
root.appendChild(hidden);
root.appendChild(visible);
document.body.appendChild(root);
for (; ; await frame()) {
const hr = hidden.getBoundingClientRect();
const fontWidth = hr.width / fillerSize;
const fontHeight = hr.height / fillerSize;
const rr = root.getBoundingClientRect();
const ratio = rr.width / rr.height;
const width = (rr.width / fontWidth) << 2;
const height = (rr.height / fontHeight) << 3;
const pixels = create(width, height);
const time = 1e-3 * Date.now();
for (let y = 0; y < height; y++) {
const v = (2 * y) / height - 1;
for (let x = 0; x < width; x++) {
const u = ratio * ((2 * x) / width - 1);
if (globe(x, y, u, v, time)) set(pixels, x, y);
}
}
});
let globe = new THREE.Points(g, m);
scene.add(globe);
// </GLOBE>
// <LABEL>
visible.textContent = render(pixels);
}
};
const pinGeometryAtlanta = new THREE.SphereGeometry(0.05, 32, 32);
const pinMaterialAtlanta = new THREE.MeshBasicMaterial({ color: 0x31302c });
const pinMeshAtlanta = new THREE.Mesh(pinGeometryAtlanta, pinMaterialAtlanta);
const labelDivAtlanta = document.createElement("div");
labelDivAtlanta.className = "label-atl";
labelDivAtlanta.textContent = "Atlanta";
const labelObjectAtlanta = new CSS2DObject(labelDivAtlanta);
const pinLatitudeAtlanta = 33.7493266;
const pinLongitudeAtlanta = -95.39035664;
const sphericalAtlanta = new THREE.Spherical();
sphericalAtlanta.phi = (90 - pinLatitudeAtlanta) * (Math.PI / 180);
sphericalAtlanta.theta = (180 - pinLongitudeAtlanta) * (Math.PI / 180);
sphericalAtlanta.radius = 5;
const positionAtlanta = new THREE.Vector3();
positionAtlanta.setFromSpherical(sphericalAtlanta);
pinMeshAtlanta.position.copy(positionAtlanta);
labelObjectAtlanta.position.copy(positionAtlanta);
scene.add(pinMeshAtlanta);
scene.add(labelObjectAtlanta);
// San Jose
const pinGeometrySanJose = new THREE.SphereGeometry(0.05, 32, 32);
const pinMaterialSanJose = new THREE.MeshBasicMaterial({ color: 0x31302c });
const pinMeshSanJose = new THREE.Mesh(pinGeometrySanJose, pinMaterialSanJose);
const labelDivSanJose = document.createElement("div");
labelDivSanJose.className = "label-san";
labelDivSanJose.textContent = "San Jose";
const labelObjectSanJose = new CSS2DObject(labelDivSanJose);
const pinLatitudeSanJose = 38;
const pinLongitudeSanJose = -58;
const sphericalSanJose = new THREE.Spherical();
sphericalSanJose.phi = (90 - pinLatitudeSanJose) * (Math.PI / 180);
sphericalSanJose.theta = (180 - pinLongitudeSanJose) * (Math.PI / 180);
sphericalSanJose.radius = 5;
const positionSanJose = new THREE.Vector3();
positionSanJose.setFromSpherical(sphericalSanJose);
pinMeshSanJose.position.copy(positionSanJose);
labelObjectSanJose.position.copy(positionSanJose);
scene.add(pinMeshSanJose);
scene.add(labelObjectSanJose);
// Vint Hill
const pinGeometryVintHill = new THREE.SphereGeometry(0.05, 32, 32);
const pinMaterialVintHill = new THREE.MeshBasicMaterial({ color: 0x31302c });
const pinMeshVintHill = new THREE.Mesh(
pinGeometryVintHill,
pinMaterialVintHill
);
const labelDivVintHill = document.createElement("div");
labelDivVintHill.className = "label-vint";
labelDivVintHill.textContent = "Vint Hill";
const labelObjectVintHill = new CSS2DObject(labelDivVintHill);
const pinLatitudeVintHill = 38;
const pinLongitudeVintHill = -101;
const sphericalVintHill = new THREE.Spherical();
sphericalVintHill.phi = (90 - pinLatitudeVintHill) * (Math.PI / 180);
sphericalVintHill.theta = (180 - pinLongitudeVintHill) * (Math.PI / 180);
sphericalVintHill.radius = 5;
const positionVintHill = new THREE.Vector3();
positionVintHill.setFromSpherical(sphericalVintHill);
pinMeshVintHill.position.copy(positionVintHill);
labelObjectVintHill.position.copy(positionVintHill);
scene.add(pinMeshVintHill);
scene.add(labelObjectVintHill);
// Chicago
const pinGeometryChicago = new THREE.SphereGeometry(0.05, 32, 32);
const pinMaterialChicago = new THREE.MeshBasicMaterial({ color: 0x31302c });
const pinMeshChicago = new THREE.Mesh(pinGeometryChicago, pinMaterialChicago);
const labelDivChicago = document.createElement("div");
labelDivChicago.className = "label-cha";
labelDivChicago.textContent = "Chicago";
const labelObjectChicago = new CSS2DObject(labelDivChicago);
const pinLatitudeChicago = 42;
const pinLongitudeChicago = -92.5;
const sphericalChicago = new THREE.Spherical();
sphericalChicago.phi = (90 - pinLatitudeChicago) * (Math.PI / 180);
sphericalChicago.theta = (180 - pinLongitudeChicago) * (Math.PI / 180);
sphericalChicago.radius = 5;
const positionChicago = new THREE.Vector3();
positionChicago.setFromSpherical(sphericalChicago);
pinMeshChicago.position.copy(positionChicago);
labelObjectChicago.position.copy(positionChicago);
scene.add(pinMeshChicago);
scene.add(labelObjectChicago);
// New York
const pinGeometryNewYork = new THREE.SphereGeometry(0.05, 32, 32);
const pinMaterialNewYork = new THREE.MeshBasicMaterial({ color: 0x31302c });
const pinMeshNewYork = new THREE.Mesh(pinGeometryNewYork, pinMaterialNewYork);
const labelDivNewYork = document.createElement("div");
labelDivNewYork.className = "label-york";
labelDivNewYork.textContent = "New York";
const labelObjectNewYork = new CSS2DObject(labelDivNewYork);
const pinLatitudeNewYork = 40;
const pinLongitudeNewYork = -105;
const sphericalNewYork = new THREE.Spherical();
sphericalNewYork.phi = (90 - pinLatitudeNewYork) * (Math.PI / 180);
sphericalNewYork.theta = (180 - pinLongitudeNewYork) * (Math.PI / 180);
sphericalNewYork.radius = 5;
const positionNewYork = new THREE.Vector3();
positionNewYork.setFromSpherical(sphericalNewYork);
pinMeshNewYork.position.copy(positionNewYork);
labelObjectNewYork.position.copy(positionNewYork);
scene.add(pinMeshNewYork);
scene.add(labelObjectNewYork);
// ARCS
function renderArc(startPosition, endPosition) {
const curve = new THREE.QuadraticBezierCurve3(
startPosition,
new THREE.Vector3(
(startPosition.x + endPosition.x) / 1.8,
(startPosition.y + endPosition.y) / 1.8,
(startPosition.z + endPosition.z) / 2
),
endPosition
);
const points = curve.getPoints(50);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: 0xffffff });
const arc = new THREE.Line(geometry, material);
scene.add(arc);
}
renderArc(positionAtlanta, positionSanJose);
renderArc(positionAtlanta, positionNewYork);
renderArc(positionAtlanta, positionVintHill);
renderArc(positionAtlanta, positionChicago);
renderArc(positionSanJose, positionNewYork);
renderArc(positionSanJose, positionVintHill);
renderArc(positionSanJose, positionChicago);
renderArc(positionNewYork, positionVintHill);
renderArc(positionNewYork, positionChicago);
// </LABEL>
let clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
let t = clock.getElapsedTime();
globalUniforms.time.value = t;
controls.update();
renderer.render(scene, camera);
labelRenderer.render(scene, camera);
});
function onWindowResize() {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
labelRenderer.setSize(innerWidth, innerHeight);
}
main();
})();

View file

@ -1,322 +1,49 @@
@import url("//cdn.jsdelivr.net/gh/be5invis/Iosevka@ff81c66/fonts.css");
:root {
--size: calc(100vmin / 1.618033988749895);
}
html,
body {
overflow: hidden;
margin: 0;
font-family: "Open Sans", sans-serif;
}
.header-container {
color: white;
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
top: 1rem;
left: 1rem;
right: 1rem;
color: #fff;
z-index: 999;
background: rgba(255, 255, 255, 0.02);
backdrop-filter: blur(5px);
padding: 1rem;
padding-top: 0.5rem;
padding-bottom: 0.75rem;
border-radius: 1rem;
}
.header-container h1 {
display: inline-block;
font-family: "Open Sans", sans-serif;
margin: 0;
padding: 0;
}
.header-container nav ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.header-container nav ul li {
display: inline-block;
margin-left: 20px;
}
.header-container nav ul li a {
text-decoration: none;
color: white;
font-weight: 800;
position: relative;
}
.header-container nav ul li a::before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: white;
transform: scaleX(0);
transform-origin: bottom left;
transition: transform 0.3s ease;
height: 100vh;
overflow: hidden;
}
.header-container nav ul li a:hover::before {
transform: scaleX(1);
}
.card-button {
position: fixed;
z-index: 99;
right: 1.9rem;
bottom: 1.9rem;
padding: 5px 30px;
background-color: #232222;
color: #e3e3e3;
border-radius: 5px;
font-size: 22px;
font-weight: 800;
cursor: pointer;
transition: transform 0.3s;
}
.card-button:hover {
animation: wobble 2s ease-in-out infinite;
}
@keyframes wobble {
0% {
transform: translateX(0);
}
15% {
transform: translateX(-2px) rotate(-2deg);
}
30% {
transform: translateX(2px) rotate(2deg);
}
45% {
transform: translateX(-1px) rotate(-1deg);
}
60% {
transform: translateX(1px) rotate(1deg);
}
75% {
transform: translateX(-0.5px) rotate(-0.5deg);
}
100% {
transform: translateX(0);
}
}
.card-out {
z-index: 99;
position: fixed;
right: -520px;
bottom: 15px;
transition: right 0.5s ease-in-out;
}
.card-in {
z-index: 99;
position: fixed;
right: 15px;
bottom: 15px;
transition: right 0.5s ease-in-out;
}
*,
*:before,
*:after {
outline: 0;
body {
margin: 0;
padding: 0;
border: 0;
text-decoration: none;
box-sizing: border-box;
transition: color 300ms ease-out, background 300ms ease-out,
border 300ms ease-out, transform 300ms ease-out, opacity 300ms ease-out;
background: #241917;
color: #f3bbae;
}
input,
textarea,
select,
options,
button {
font-family: inherit;
font-size: inherit;
line-height: inherit;
font-weight: normal;
background: none;
color: #b4a477;
}
.card-wrap {
overflow: hidden;
margin: 0 auto;
max-width: 520px;
background-color: #232323;
border-radius: 9px;
box-shadow: 7px 7px 0 #743c2f;
}
.tabs-wrap {
position: relative;
}
.tabs-nav {
body,
.braille {
display: flex;
flex-direction: row;
align-items: center;
justify-content: stretch;
position: relative;
overflow: hidden;
background-color: #232222;
justify-content: center;
flex-flow: row;
}
.tabs-nav > button {
flex: 1;
display: block;
cursor: pointer;
text-align: center;
padding: 0.8em 0;
background-color: #232222;
font-weight: bold;
color: #733c2f;
.braille {
max-width: 100%;
max-height: 100%;
width: var(--size);
height: var(--size);
font: 11px/12px "Iosevka Web", monospace;
}
.tabs-nav > button:hover {
background-color: #733c2f;
color: #232222;
.braille > * {
white-space: pre;
}
.tabs-nav > button.active {
background-color: #733c2f;
border-color: #733c2f;
color: #232222;
.braille .hidden {
position: fixed;
bottom: 100%;
right: 100%;
}
.tabs-info {
min-height: 100px;
padding-top: 1em;
background-color: #232222;
font-weight: 700;
color: #733c2f;
.visible {
display: fixed !important;
left: 2;
}
.tabs-info .tabs-info-row {
display: flex;
flex-direction: row;
align-items: center;
justify-content: stretch;
margin-bottom: 1em;
padding: 0 1em;
}
.tabs-info .tabs-info-qr > img {
display: block;
border-radius: 10px;
background-color: white;
padding: 5px;
}
.tabs-info .tabs-info-input {
display: flex;
flex-direction: row;
align-items: center;
justify-content: stretch;
background-color: #232323;
padding: 0.75em 1em;
box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.4);
}
.tabs-info .tabs-info-input > span {
margin-right: 1em;
font-weight: bold;
color: #733c2f;
}
.tabs-info .tabs-info-input > input {
flex: 1;
margin-right: 1em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: bold;
color: #733c2f;
background-color: #232323;
border: none;
}
.tabs-info .tabs-info-input > button {
cursor: pointer;
font-weight: bold;
background-color: #232222;
color: #733c2f;
}
.tabs-info .tabs-info-details {
padding-left: 15px;
}
.tabs-info .tabs-info-title {
font-size: 2em;
}
.tabs-info .tabs-info-warn {
font-size: 1em;
}
.label-york,
.label-atl,
.label-cha,
.label-vint,
.label-san {
color: white;
background-color: rgba(0, 0, 0, 0.7);
padding: 4px;
border-radius: 4px;
font-size: 14px;
z-index: 99;
}
.ping1,
.ping2,
.ping3{position:absolute;z-index:88;left:50%;top:50%;display:block;content:"";-webkit-border-radius:116px;-moz-border-radius:116px;border-radius:116px;border:2px solid #ee4633;
transition:all 0.2s ease-in-out;
-webkit-transition:all 0.2s ease-in-out;
-moz-transition:all 0.2s ease-in-out;
-o-transition:all 0.2s ease-in-out;
width:0;
height:0;
margin-left:-2px;
margin-top:-2px;}
.dot:hover .ping1,
.dot:hover .ping2,
.dot:hover .ping3 {
transition:all 0.75s ease-out;
-webkit-transition:all 0.75s ease-out;
-moz-transition:all 0.75s ease-out;
-o-transition:all 0.75s ease-out;
}
.dot:hover .ping1 { width:116px;height:116px; margin-left:-60px;margin-top:-60px; }
.dot:hover .ping2{width:66px;height:66px;margin-left:-35px;margin-top:-35px;
-moz-transition-delay:0.2s;
-webkit-transition-delay:0.2s;
-o-transition-delay:0.2s;
transition-delay:0.2s;}
.dot:hover .ping3{width:40px;height:40px;margin-left:-22px;margin-top:-22px;
-moz-transition-delay:0.5s;
-webkit-transition-delay:0.5s;
-o-transition-delay:0.5s;
transition-delay:0.5s;}
.dot{position:absolute;z-index:99;width:14px;height:14px;background:#ee4633;-webkit-border-radius:12px;-moz-border-radius:12px;border-radius:12px;cursor:pointer;}
#map{position:relative;margin:5% auto;width:638px;}
#portland{left:33px;top:50px;}
#palo_alto{left:17px;top:181px;}
#scottsdale {left:115px;top:246px;}
#san_antonio{left:296px;top:311px;}