From b5a4ccd5395de3f966bf88c8fcaa7e511c7edae5 Mon Sep 17 00:00:00 2001 From: Tanishq Dubey Date: Thu, 30 Jan 2025 12:09:47 -0500 Subject: [PATCH] initial personal site --- static/script.js | 361 ------------------------------------------- static/style.css | 341 ++++++---------------------------------- templates/index.html | 297 ++++++++++------------------------- 3 files changed, 131 insertions(+), 868 deletions(-) diff --git a/static/script.js b/static/script.js index b815e4e..e69de29 100644 --- a/static/script.js +++ b/static/script.js @@ -1,361 +0,0 @@ -const container = document.getElementById('patch-container'); -const svgOverlay = document.getElementById('cable-overlay'); - -const portsState = {}; - -const LED_COLORS = [ - // Gruvbox dark bright colors - '#fb4934', // red - '#b8bb26', // green - '#fabd2f', // yellow - '#83a598', // blue - '#d3869b', // purple - '#8ec07c', // aqua - '#fe8019', // orange -]; - -const CABLE_COLORS = [ - // Gruvbox light dark colors - '#9d0006', // red - '#79740e', // green - '#b57614', // yellow - '#076678', // blue - '#8f3f71', // purple - '#427b58', // aqua - '#af3a03', // orange -]; - -let cables = []; - -let dragSource = null; -let tempCablePath = null; - -const NUM_SEGMENTS = 64; -const GRAVITY = 0.6; -const DAMPING = 0.4; -const CONSTRAINT_ITERATIONS = 15; - -const SWAY_AMPLITUDE = 0.05; -const SWAY_FREQUENCY = 0.002; - -function getPortCenter(portEl) { - const rect = portEl.getBoundingClientRect(); - return { - x: rect.left + rect.width / 2, - y: rect.top + rect.height / 2 - }; -} - -/********************************************** - * LED logic - **********************************************/ -function initPortState(portId) { - if (!portsState[portId]) { - portsState[portId] = { - connectionCount: 0, - ledColor: null, - ledIsLit: false, - nextBlinkTime: 0 - }; - } -} -function addConnection(portId) { - initPortState(portId); - const st = portsState[portId]; - st.connectionCount++; - if (st.connectionCount === 1) { - // choose a color if not set - if (!st.ledColor) { - st.ledColor = LED_COLORS[Math.floor(Math.random() * LED_COLORS.length)]; - } - // schedule next blink - st.nextBlinkTime = performance.now(); - } -} -function removeConnection(portId) { - initPortState(portId); - const st = portsState[portId]; - if (st.connectionCount > 0) { - st.connectionCount--; - } - if (st.connectionCount <= 0) { - st.connectionCount = 0; - st.ledIsLit = false; - updatePortLED(portId); - } -} -/** Check if we should toggle LED, then update DOM. */ -function updateLEDs(now) { - for (const portId in portsState) { - const st = portsState[portId]; - if (st.connectionCount > 0) { - if (now >= st.nextBlinkTime) { - st.ledIsLit = !st.ledIsLit; - const interval = 50 + Math.random() * 150; // 200..800 ms - st.nextBlinkTime = now + interval; - } - } - updatePortLED(portId); - } -} -function updatePortLED(portId) { - const st = portsState[portId]; - const portEl = document.getElementById(portId); - if (!portEl) return; - const ledEl = portEl.querySelector('.led'); - if (!ledEl) return; - - if (st.connectionCount > 0 && st.ledColor) { - ledEl.style.background = st.ledIsLit ? st.ledColor : '#222'; - } else { - ledEl.style.background = '#222'; - } -} - -/********************************************** - * Cable creation & removal - **********************************************/ -function randomColor() { - return CABLE_COLORS[Math.floor(Math.random() * CABLE_COLORS.length)]; -} -function createCablePath(color) { - const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); - path.setAttribute('stroke', color); - path.setAttribute('fill', 'none'); - path.setAttribute('stroke-width', '3'); - path.classList.add('cable-path'); - // We want to click cables to remove them - path.addEventListener('click', onCableClick); - svgOverlay.appendChild(path); - return path; -} -function createRope(sourceEl, targetEl, numSegments) { - const s = getPortCenter(sourceEl); - const t = getPortCenter(targetEl); - const rope = []; - for (let i = 0; i <= numSegments; i++) { - const alpha = i / numSegments; - rope.push({ - x: s.x + (t.x - s.x) * alpha, - y: s.y + (t.y - s.y) * alpha, - vx: 0, vy: 0 - }); - } - return rope; -} -function connect(sourceId, targetId, color) { - if (!sourceId || !targetId || sourceId === targetId) return; - const sourceEl = document.getElementById(sourceId); - const targetEl = document.getElementById(targetId); - if (!sourceEl || !targetEl) return; - - color = color || randomColor(); - const rope = createRope(sourceEl, targetEl, NUM_SEGMENTS); - const dx = rope[rope.length - 1].x - rope[0].x; - const dy = rope[rope.length - 1].y - rope[0].y; - const totalDist = Math.sqrt(dx * dx + dy * dy); - const restLength = totalDist / NUM_SEGMENTS; - - const pathEl = createCablePath(color); - const swayOffset = Math.random() * 1000; - - cables.push({ - sourceId, targetId, - pathEl, ropeSegments: rope, - restLength, color, swayOffset - }); - - addConnection(sourceId); - addConnection(targetId); -} -function removeCable(cable) { - svgOverlay.removeChild(cable.pathEl); - cables = cables.filter(c => c !== cable); - removeConnection(cable.sourceId); - removeConnection(cable.targetId); -} -function onCableClick(e) { - const pathEl = e.currentTarget; - const cable = cables.find(c => c.pathEl === pathEl); - if (cable) removeCable(cable); -} - -/********************************************** - * Dragging logic (user can draw cables) - **********************************************/ -function handlePortMouseDown(e) { - e.preventDefault(); - dragSource = e.currentTarget; - const color = randomColor(); - tempCablePath = createCablePath(color); - tempCablePath.style.pointerEvents = 'none'; -} -function handleMouseMove(e) { - if (!dragSource || !tempCablePath) return; - const s = getPortCenter(dragSource); - const mx = e.clientX, my = e.clientY; - const midX = (s.x + mx) / 2, midY = (s.y + my) / 2; - const d = ` - M ${s.x},${s.y} - C ${midX},${s.y} - ${midX},${my} - ${mx},${my} - `; - tempCablePath.setAttribute('d', d); -} -function handleMouseUp(e) { - - const dropTargetEl = document.elementFromPoint(e.clientX, e.clientY); - - const portEl = dropTargetEl && dropTargetEl.closest('.port'); - - if (portEl) { - - const sourceId = dragSource.id; - const targetId = portEl.id; - if (sourceId !== targetId) { - const color = tempCablePath.getAttribute('stroke'); - svgOverlay.removeChild(tempCablePath); - tempCablePath = null; - connect(sourceId, targetId, color); - } else { - - svgOverlay.removeChild(tempCablePath); - tempCablePath = null; - } - } else { - svgOverlay.removeChild(tempCablePath); - tempCablePath = null; - } - dragSource = null; -} - -/*********************************************** - * NAS drive-lights random blinking - ***********************************************/ -let driveLights = []; -function initDriveLights() { - driveLights = document.querySelectorAll('.drive-light'); - driveLights.forEach(light => { - - light.dataset.nextBlinkTime = '0'; - }); -} -function updateDriveLights(timestamp) { - driveLights.forEach(light => { - let nextBlink = parseFloat(light.dataset.nextBlinkTime) || 0; - if (timestamp >= nextBlink) { - - light.classList.toggle('lit'); - - const interval = 300 + Math.random() * 500; // 300..800 ms - light.dataset.nextBlinkTime = (timestamp + interval).toString(); - } - }); -} - -/********************************************** - * Main animation loop - **********************************************/ -function animate(timestamp) { - - updateLEDs(timestamp); - updateDriveLights(timestamp); - - - const dt = 1.0; - cables.forEach(cable => { - const rope = cable.ropeSegments; - const n = rope.length; - if (n < 2) return; - - const sourceEl = document.getElementById(cable.sourceId); - const targetEl = document.getElementById(cable.targetId); - if (!sourceEl || !targetEl) return; - - const s = getPortCenter(sourceEl); - const t = getPortCenter(targetEl); - - // anchors - rope[0].x = s.x; rope[0].y = s.y; - rope[0].vx = 0; rope[0].vy = 0; - rope[n - 1].x = t.x; rope[n - 1].y = t.y; - rope[n - 1].vx = 0; rope[n - 1].vy = 0; - - // 1) gravity + wind for interior segments - for (let i = 1; i < n - 1; i++) { - rope[i].vy += GRAVITY; - const wave = Math.sin((timestamp + cable.swayOffset + i * 50) * SWAY_FREQUENCY); - rope[i].vx += wave * SWAY_AMPLITUDE; - - rope[i].vx *= DAMPING; - rope[i].vy *= DAMPING; - rope[i].x += rope[i].vx * dt; - rope[i].y += rope[i].vy * dt; - } - - // 2) constraints - for (let iter = 0; iter < CONSTRAINT_ITERATIONS; iter++) { - for (let i = 0; i < n - 1; i++) { - let p1 = rope[i], p2 = rope[i + 1]; - let dx = p2.x - p1.x, dy = p2.y - p1.y; - let dist = Math.sqrt(dx * dx + dy * dy); - if (dist < 0.001) dist = 0.001; - let diff = (dist - cable.restLength) / dist; - if (i !== 0) { - p1.x += 0.5 * dx * diff; - p1.y += 0.5 * dy * diff; - } - if (i + 1 !== n - 1) { - p2.x -= 0.5 * dx * diff; - p2.y -= 0.5 * dy * diff; - } - } - } - - // 3) recalc velocities - for (let i = 1; i < n - 1; i++) { - rope[i].vx = rope[i].x - (rope[i].x - rope[i].vx * dt); - rope[i].vy = rope[i].y - (rope[i].y - rope[i].vy * dt); - } - - // 4) update path - let pathD = `M ${rope[0].x},${rope[0].y}`; - for (let i = 1; i < n; i++) { - pathD += ` L ${rope[i].x},${rope[i].y}`; - } - cable.pathEl.setAttribute('d', pathD); - }); - - requestAnimationFrame(animate); -} - - - -/********************************************** - * Startup - **********************************************/ -initDriveLights(); -document.querySelectorAll('.port').forEach(portEl => { - portEl.addEventListener('mousedown', handlePortMouseDown); -}); -container.addEventListener('mousemove', handleMouseMove); -container.addEventListener('mouseup', handleMouseUp); -requestAnimationFrame(animate); - - - -connect('r1s0_portA', 'r1s2_portA',randomColor()); -connect('r1s2_portB', 'r2s1_portA',randomColor()); -connect('r1s2_portC', 'r1s3_portA',randomColor()); - -connect('r2s1_portB', 'r2s2_portS',randomColor()); -connect('r2s2_portA', 'r2s3_portA',randomColor()); -connect('r2s2_portB', 'r3s1_portA',randomColor()); -connect('r2s2_portC', 'r3s2_portA',randomColor()); -connect('r2s2_portD', 'r3s3_portA',randomColor()); -connect('r2s1_portD', 'r2s1_portG',randomColor()); -connect('r2s1_portK', 'r3s2_portB',randomColor()); - - - diff --git a/static/style.css b/static/style.css index db6baa1..547ea87 100644 --- a/static/style.css +++ b/static/style.css @@ -3,321 +3,72 @@ padding: 0 } -/* Basic reset */ + html, body { margin: 0; padding: 0; width: 100%; height: 100%; - background: #1d2021; - overflow: hidden; - /* No default scrollbars */ - font-family: "JetBrains Mono", serif; + background: #e8e8ea; + font-family: "Newsreader", serif; font-optical-sizing: auto; font-weight: 400; font-style: normal; - font-size: 20px; + color: #1A1C1A; +} + +.header { + column-span:all; +} + +.holder { + display: flex; + flex-direction: row; + height: 100%; + width: 100%; } h1 { - font-size: 48px; - color: #ebdbb2; + font-size: 5rem; + font-weight: 700; + font-style: normal; } -h2 { - font-size: 36px; - color: #ebdbb2; +.regimg { + max-width: 14em; + max-height: 20em; + height: auto; + align-self: center; } -h3 { - font-size: 28px; - color: #ebdbb2; +.largeimage { + width: auto; + object-fit: cover; + object-position: center; + column-span: none; + display: block; + float: left; } -/******************************************* - * Main Container (holds racks + cables) - *******************************************/ -#patch-container { - position: relative; +.content { + /* height: 100%; width: 100%; - height: 100%; - overflow: hidden; -} - -/* SVG overlay for cables, on top of racks */ -#cable-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 9999; - /* put cables on top */ - pointer-events: none; - /* let clicks pass through by default */ -} - -/* Each cable path can be clicked on => remove */ -.cable-path { - pointer-events: auto; - /* re-enable clicks for cable paths specifically */ - cursor: pointer; - transition: stroke 0.2s; -} - -.cable-path:hover { - stroke: #cc241d !important; -} - -/******************************************* - * Data center (the racks) - *******************************************/ -#datacenter { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - display: flex; - /* If you want horizontal scrolling if there are many racks, use: - overflow-x: auto; - */ - overflow-x: auto; - overflow-y: hidden; - z-index: 1; - /* behind cable overlay */ -} - -.rack { - width: 16em; - /* each rack’s width */ - /* fill all available vertical space */ - background: #282828; - border: 2px solid #3c3836; - margin: 10px; - box-sizing: border-box; - display: flex; - flex-direction: column; - /* stack servers top to bottom */ -} - -.rack-title { - text-align: center; - text-transform: uppercase; - font-size: 14px; - color: #ebdbb2; - margin: 8px 0; - letter-spacing: 1px; -} - -.server { - background: #32302f; - border: 1px solid #3c3836; - margin: 6px; - /* spacing within the rack */ -} - -.server-under-construction { - /* Diagonal stripes: - repeating-linear-gradient(angle, color1 start, color1 end, color2 start, color2 end) */ - background: repeating-linear-gradient( - 45deg, - #282828 0, - #282828 12px, - #32302f 12px, - #32302f 24px - ); - color:#000; - border: 2px dashed #282828; /* Give it a dashed border for effect */ - } - -.server-row { - padding: 5px 8px; - box-sizing: border-box; - display: flex; - align-items: center; - justify-content: space-between; -} - -.text-row { - font-size: 14px; - color: #ebdbb2; -} - -.port-row { - gap: 8px; - display: flex; - justify-content: right; -} - -/* If you want a spacer between servers, you can use a simple div with .spacer. */ -.spacer { - height: 20px; -} - -/******************************************* - * Port + LED styling - *******************************************/ -.port { - position: relative; - width: 1rem; - height: 1rem; - background: #32302f; - border: 2px solid #504945; - border-radius: 50%; - cursor: pointer; -} - -.port:hover { - background: #7c6f64; - border-color: #ebdbb2; -} - -a:link { - color: #b16286; - } - - /* visited link */ - a:visited { - color: #8f3f71; - } - - /* mouse over link */ - a:hover { - color: #d3869b; - } - - /* selected link */ - a:active { - color: #b16286; - } - -.led { - position: absolute; - top: -5px; - right: -5px; - width: .4rem; - height: .4rem; - background: #1d2021; - /* off state */ - border: 2px solid #504945; - border-radius: 50%; - box-shadow: 0 0 2px #000; -} - -.temp-row { - position: relative; - flex: 1; - } - .temp-label { - color: #eee; - font-size: 11px; - margin-right: 8px; - } - .temp-bar { - flex: 1; - height: 10px; - background: linear-gradient(to right, #f80, #f00); - box-shadow: 0 0 6px rgba(255,80,0,0.5); - animation: flickerHeat 1.5s infinite ease-in-out alternate; - } - @keyframes flickerHeat { - 0% { opacity: 1; transform: scaleX(1); } - 100% { opacity: 0.7; transform: scaleX(1.05); } - } - - /*************************************************** - * POWER USAGE LIGHTS (Random Blink) - ***************************************************/ - .power-lights-row { - gap: 4px; - } - .power-light { - width: 10px; height: 10px; - background: #222; - border: 2px solid #555; - border-radius: 2px; - box-shadow: 0 0 2px #000; - } - .power-light.lit { - background: #0f0; /* or something bright to indicate usage */ - } - -/************************************************ - * FAN SPACER: Animated fans - ************************************************/ -.fans { - background: #7c6f64; - margin: 6px; - /* spacing within the rack */ -} - -.fan-row { - display: flex; + display: grid; gap: 10px; - justify-content: center; - padding: 5px 0; + grid-template: repeat(4, 1fr) / repeat(2, 1fr); + grid-auto-flow: column; */ + height: 100%; + width: 40em; + min-width: 35em; + column-count: 2; + column-gap: 1em; + column-rule: thin solid black; + column-fill: auto; + font-size: 1.5rem; } -.fan { - width: 5rem; - height: 5rem; - border-radius: 50%; - background-image: url('fan.svg'); - filter: invert(29%) sepia(3%) saturate(1342%) hue-rotate(338deg) brightness(93%) contrast(90%); - animation: spin 1s linear infinite; - transform-origin: center; - background-size: contain; - background-repeat: no-repeat; - background-position: center; - transition: all 1s linear; -} - -.fan:hover { - animation: 5s; -} - -@keyframes spin { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -} - -/************************************************ - * NAS SPACER: Random blinking drive lights - ************************************************/ -.nas { - background: #504945; - border: 1px solid #7c6f64; - margin: 6px; - /* spacing within the rack */ -} - -.drive-lights-row { - display: flex; - gap: 4px; - justify-content: center; - padding: 5px 0; - flex-wrap: wrap; - /* if many lights, wrap to next line */ -} - -.drive-light { - width: 12px; - height: 12px; - background: #1d2021; - /* off by default */ - border: 2px solid #504945; - border-radius: 2px; - box-shadow: 0 0 2px #000; -} - -.drive-light.lit { - background: #b8bb26; - /* or any color you like */ +.item { + padding: .2em; + margin: .2em; } \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 4c66f90..f2d672d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,236 +2,109 @@ - - - DWS + Tanishq Dubey - - - +
-
- +
-
- -
- -
-
-

DWS

-
-
-
-
-
- -
-
It's your internet.
-
Take it back.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-

About

-
-
-
-
-
-
- -
-
DWS is built around the idea of giving the user control of the - internet again.
-
We do this by building tools, providing services, and ideas that - focus on local first, openness, and privacy.
-
-
-
-
-
-
Joining us is easy. Host your own software, spread the word, and - make the internet yours.
-
+
+

Tanishq Dubey

-
-
-
-
-
-
-
-
-
+

About Me

+

+ NEW YORK — Hi, you've already read my name. Currently, I am an Engineering Manager at Datadog, working on Code Security. +

+

+ Before this, I was a Staff Engineer at Clear Steet, where I worked on a bunch of things, from backend services to infra platforms. +

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

+ My interests lie in distributed systems, operating systems, processor architecture and cloud systems and networking.
+

- -
-
-

Services

-
-
-
-
-
Sesame 2FA
-
-
-
-
Spectra
-
-
-
-
KAT
-
-
-
-
Custom Hosting & Storage
-
-
-
-
-
-
-

Sesame 2FA

-
-
-
-
-
-
-
-
-
-
A open source 2FA app that lets you inspect, edit, and create your own 2FA tokens. All stored encrypted on the iOS Keychain.
-
Find out more at the Sesame site.
-
-
+

+ On a more fun note, I consider myself to be a amateur photographer. Here are some pictures I've taken recently: +

+ + + +
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi + ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa + qui officia deserunt mollit anim id est laborum Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat + cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Lorem ipsum dolor + sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim + id est laborum + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus eget enim eu felis fringilla elementum vel quis metus. Ut sit amet augue sed sem sagittis sollicitudin. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec eleifend, dolor in mollis tempus, sem ante fermentum neque, vitae sodales sem ante id est. Curabitur lobortis diam euismod urna mattis, non rhoncus mi malesuada. Donec in luctus orci. Mauris commodo convallis tristique. Aenean nulla purus, dignissim sed pharetra et, dignissim eu enim. Praesent sed sodales dui. Aliquam erat volutpat. In consectetur, neque sed maximus blandit, turpis nunc vulputate sem, eu vehicula nisl metus fringilla enim. In ornare pharetra lorem a vehicula. Nullam metus arcu, condimentum non leo non, facilisis sollicitudin nunc. Praesent ornare turpis mollis pellentesque faucibus. Sed sagittis at enim ut interdum. Maecenas eleifend accumsan elementum. -

-
-
-

Spectra

-
-
-
-
-
-
-
-
-
-
Fast and simple photo porfolio hosting. DWS offers both selfhosted and cloud offerings of Spectra, with BYOD (domain) support and for early signups, unlimited storage, all at minimal cost.
-
Find out more at DWS Git
-
Or contact us at admin (at) dws.rip for hosting and pricing
-
-
-
-

KAT

-
-
-
-
-
-
-
-
-
-
-
COMING SOON: A orchestration solution brought to you by DWS.
-
-
-
Opinionated, fast, single or multi-machine. This is the orchestration system for hackers.
-
EST. Summer 2025.
-
-
-
-

Custom Hosting

-
-
-
-
-
-
-
-
-
-
Need help with something unlisted?
-
Contact us at admin (at) dws.rip for hosting and pricing
-
-
+ Suspendisse venenatis augue blandit dapibus dignissim. Vestibulum a turpis nec lacus gravida aliquet elementum eleifend odio. Vestibulum nec felis at sem rutrum blandit interdum et risus. Vestibulum sit amet convallis turpis, vitae sagittis eros. Vestibulum risus tellus, gravida ut erat nec, suscipit fermentum dolor. Quisque feugiat metus ac metus iaculis, non mattis dui gravida. Maecenas id odio ac tortor congue eleifend. Praesent mattis ullamcorper massa non laoreet. Praesent fringilla sapien eu lorem gravida tincidunt a quis lorem. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

+ +

Praesent volutpat tincidunt odio at aliquet. Proin feugiat hendrerit lectus, vel pretium libero commodo sit amet. Aliquam ultricies et sem non luctus. Proin eget leo a purus suscipit pulvinar eu eget arcu. Sed ipsum lacus, ultricies a enim quis, bibendum placerat est. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut tempus ligula magna, quis molestie dui sollicitudin id. In ac dui erat. + + Suspendisse suscipit eget tellus sit amet finibus. Aliquam erat volutpat. Morbi quis congue magna. Proin commodo euismod lacus sed lobortis. Etiam nec sollicitudin ipsum. Morbi vel nisl eu est maximus maximus sed ut sem. Etiam rutrum nec arcu ac ullamcorper. Pellentesque non justo efficitur, condimentum libero accumsan, bibendum diam. Quisque id laoreet orci. Praesent consequat ultricies tincidunt. Morbi fermentum, ex maximus laoreet malesuada, dolor tellus imperdiet lectus, quis cursus nibh velit eu metus. Pellentesque sit amet tempor elit, non mattis nulla. + + Maecenas fermentum purus nisl, in semper massa feugiat id. Suspendisse vitae elementum erat. Etiam suscipit sed ante a interdum. Suspendisse quam turpis, faucibus vitae leo quis, vulputate scelerisque odio. Nullam feugiat varius mattis. Aliquam eu enim eu dui ultrices congue varius ut nibh. Pellentesque nec mi sed felis viverra cursus. Vivamus vehicula nisl nulla, vitae imperdiet lorem elementum ut. Aenean tempus ligula sapien, ut rutrum purus dictum eget. Nullam a ligula pretium, mollis lorem nec, pellentesque mauris. Pellentesque gravida leo lacus. Aliquam eget velit in arcu varius tincidunt. Aliquam urna felis, sollicitudin sed ultricies a, aliquet quis lacus. + + Duis posuere est sed urna finibus, vitae vestibulum neque feugiat. Phasellus vitae mi venenatis, gravida magna a, dignissim mi. Fusce quam turpis, porttitor fringilla neque at, vehicula dignissim felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar interdum risus a dignissim. Nam porttitor vehicula purus, quis vestibulum lectus mollis vel. Vivamus ut convallis purus, ut lacinia est. Curabitur lobortis viverra libero, ornare aliquet justo maximus sed. Cras nec malesuada velit, eget pharetra velit. Quisque sit amet fringilla est, nec faucibus eros. Sed at suscipit odio. + + Sed et mi et enim vehicula volutpat vel non ex. Duis congue tempus nisl, at molestie risus dapibus sit amet. Etiam ullamcorper gravida efficitur. Quisque rhoncus suscipit mollis. Nam vestibulum dignissim lorem, et condimentum elit semper eu. Aliquam at consequat risus, eget commodo est. Donec eu tincidunt ipsum. Curabitur lobortis ultricies bibendum. Fusce bibendum varius malesuada. Quisque ut feugiat tortor, in blandit enim. + + Etiam consectetur erat sed sem faucibus varius. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam cursus quam eget tempor convallis. Curabitur fermentum est vel metus mattis, ut auctor nulla elementum. Donec non massa molestie, semper dolor non, bibendum arcu. Fusce sed orci rhoncus, cursus mi eu, lobortis massa. Sed tincidunt velit dolor, vitae finibus magna ullamcorper in. Morbi consequat fringilla tristique. Curabitur at sem velit. Sed sed mollis ligula. Integer volutpat augue leo, nec ornare mauris blandit et. Morbi et dui sapien. Fusce gravida lorem ac molestie mattis. Vestibulum ut consequat diam, a porta augue. + + Duis iaculis sapien in enim consectetur tincidunt. Maecenas et elit vel erat blandit blandit nec non quam. Etiam sed nulla id elit mollis blandit. Sed fringilla pellentesque tellus malesuada bibendum. Suspendisse potenti. Aliquam bibendum ultrices nisi, ac varius ipsum maximus quis. Maecenas mi quam, hendrerit quis hendrerit sit amet, aliquam eget eros. Ut bibendum, tortor sollicitudin pretium congue, mauris enim blandit nunc, eu laoreet urna mauris a metus. Phasellus fermentum sodales sapien, non lacinia risus tincidunt vel. + + Nulla tempor euismod mi. Donec ut dolor placerat, ornare nisl quis, congue justo. Fusce et est non metus consectetur tristique et et diam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ornare eleifend lobortis. Etiam a nulla ut urna iaculis vulputate eu quis sapien. Nullam dolor orci, aliquet quis dictum nec, vestibulum ut est. Praesent tortor libero, sagittis id orci at, vulputate dictum felis. Mauris eleifend id justo quis commodo. Vestibulum a urna augue. Ut lobortis lorem in lacus lacinia efficitur. Curabitur sodales gravida eros id consectetur. Nunc in libero nisl. Proin lacus sem, mollis eu odio eget, tincidunt bibendum erat. Sed vel ipsum sollicitudin, dapibus risus sit amet, porta urna. + + Fusce eleifend, erat eget feugiat lobortis, nisl tortor accumsan odio, sed porta ipsum magna ut justo. Aliquam tempor tristique lectus ac molestie. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum at metus congue, tincidunt dolor in, sagittis urna. Donec viverra dui id nibh porttitor, bibendum bibendum quam lobortis. Nulla pretium lorem nulla, ut dictum velit tincidunt at. Nunc mollis ultricies nulla, a pharetra arcu. Nullam commodo elementum diam sed rhoncus. Duis fermentum ante sed interdum maximus. Donec et sapien a massa pretium molestie. Aliquam scelerisque eget justo ac tristique. Aliquam ultricies velit ut pharetra mattis. Maecenas eros leo, mollis varius tempus sit amet, blandit id justo. Nunc aliquet porttitor pharetra. Vivamus eu scelerisque enim, eu volutpat ligula. + + Praesent semper nulla nec nisl venenatis, non bibendum purus gravida. Sed eget porta magna. Cras blandit, augue vitae rhoncus pretium, lorem lectus eleifend nibh, vitae lobortis sapien tortor eu nisl. Fusce accumsan arcu enim, vitae pharetra justo feugiat a. Integer sed ullamcorper erat. Aliquam viverra orci vel mauris congue, et ornare odio egestas. Mauris at placerat est, et vestibulum ipsum. Nam velit mi, sollicitudin ac sapien in, pharetra consectetur nulla. Pellentesque sed tincidunt neque. Duis feugiat nibh vitae diam molestie, ac sodales dolor vulputate. Nullam blandit, urna non blandit dignissim, velit leo blandit magna, quis vulputate mauris eros sit amet neque. + + Vestibulum eu nisi sit amet erat ultrices sollicitudin non commodo nisl. Fusce condimentum enim mauris, gravida volutpat nisi interdum at. Aenean massa orci, condimentum in lobortis sit amet, suscipit sit amet arcu. Pellentesque vel ipsum dapibus, convallis urna feugiat, facilisis ante. Morbi neque dolor, feugiat eu mauris interdum, porta sagittis erat. Praesent ultrices fermentum ex, in condimentum justo accumsan ut. Nunc sagittis elit lectus, at consequat nisl finibus sed. Quisque sit amet neque placerat, interdum dui sed, rhoncus dui. Fusce nec magna sed velit feugiat commodo a sit amet lacus. Proin id rutrum purus. Duis rhoncus lorem placerat congue sodales. + + Cras ante libero, faucibus ac sollicitudin quis, imperdiet et ligula. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vivamus vel augue viverra, convallis massa gravida, pharetra lacus. Integer tristique efficitur volutpat. Proin ultrices venenatis ante, quis porttitor purus luctus et. In hac habitasse platea dictumst. Nunc dapibus est leo. + + Vivamus commodo enim non elit efficitur pulvinar. Quisque tincidunt congue pellentesque. Donec mollis finibus ex, tempus ultricies sapien auctor nec. Phasellus pharetra dui ex, quis eleifend mauris laoreet vel. Aenean quam tortor, tristique eget diam eget, laoreet pharetra odio. Sed eu cursus nisl. Fusce dapibus tristique sollicitudin. Quisque id consequat libero. + + Aliquam ut ultrices velit, in aliquam diam. Nullam eu mi libero. Aenean tempus semper tellus, at efficitur felis sodales in. Nullam aliquam, lacus ut suscipit faucibus, quam sapien pretium massa, at pretium eros risus ornare ligula. Ut turpis neque, pretium nec convallis et, gravida eget nisi. Sed purus felis, vestibulum quis ante at, condimentum gravida orci. Nam elit magna, elementum a facilisis vitae, pharetra et metus. Vestibulum tortor ipsum, dignissim ut dui in, ornare cursus odio. Aliquam iaculis eleifend facilisis. Nunc pretium, nunc sed elementum tempor, ante erat bibendum mi, in rhoncus justo libero blandit mauris. Integer ultricies erat non nisl tempus, ut rutrum magna ullamcorper. Donec porta tincidunt hendrerit. Cras et odio placerat, interdum mi id, dapibus eros. Nulla lectus risus, vestibulum eget enim ut, commodo blandit justo. Aenean et vestibulum enim. + + Curabitur sit amet pulvinar elit. Sed venenatis leo nisl, sit amet pulvinar libero molestie a. In tincidunt quis elit mollis consequat. Curabitur scelerisque auctor orci id cursus. Vestibulum placerat, tellus et ultricies sagittis, lorem magna venenatis diam, non blandit urna nibh sit amet augue. Phasellus quis elementum erat. Aliquam iaculis, nibh ultrices tempus semper, ante diam dapibus est, nec faucibus tortor ante vitae magna. Pellentesque semper, erat sit amet sagittis porttitor, arcu justo condimentum arcu, a finibus tortor sem ultricies nibh. Maecenas ut interdum elit. Aenean bibendum felis ut euismod imperdiet. Nunc sed iaculis dolor. Morbi vitae nunc dui. + + Nam ultrices ut ante quis ultrices. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean facilisis enim turpis. Maecenas luctus purus vel nunc lobortis, ac consequat lectus cursus. Suspendisse id cursus risus. Aenean maximus arcu et neque pulvinar iaculis. Suspendisse sollicitudin sollicitudin pellentesque. Aliquam eu vehicula ante. Curabitur semper auctor magna. Nullam at blandit neque, id vulputate nunc. Integer elementum, purus quis volutpat efficitur, nisi risus facilisis quam, eget mollis enim turpis suscipit magna. + + Vivamus facilisis odio leo, sed scelerisque orci tincidunt ac. Nam ultrices bibendum sem, vel lobortis lectus rhoncus sit amet. Vivamus tristique commodo finibus. Sed pharetra lacus sit amet nunc sagittis aliquam. Aenean mattis sodales justo. In a commodo mi, sit amet molestie mauris. Proin enim lectus, blandit ut ante in, aliquam dapibus purus. Morbi feugiat nisi molestie, congue urna vitae, aliquam eros. Proin a dapibus lacus, fermentum ultrices dolor. Cras tempus elit quis odio laoreet congue. + + Nulla sagittis lectus sit amet sapien laoreet, vel sollicitudin ex lobortis. Aenean egestas magna nunc, sed finibus dolor posuere nec. Nam tempor, ante at pellentesque malesuada, augue ante convallis enim, nec fringilla enim lacus eu sapien. Donec non neque vel quam venenatis semper. Aliquam tristique erat et feugiat porta. Proin vel ultrices justo, ut vehicula mi. Duis orci elit, blandit quis nisi ac, hendrerit euismod dolor. Nam commodo dui lobortis nunc sodales scelerisque. Donec risus leo, vulputate a interdum aliquam, convallis non metus. Curabitur facilisis consectetur dictum. Vestibulum placerat nibh id libero feugiat, quis commodo metus pellentesque. Vestibulum posuere sem eget tellus hendrerit viverra. + + Vestibulum imperdiet nisl quam, a malesuada velit semper fringilla. Integer mollis dolor non tortor ultricies lobortis. Aliquam imperdiet dui et velit auctor aliquet. Vivamus est elit, tristique in ipsum sed, iaculis tincidunt mi. Duis commodo massa nec augue posuere dapibus. Cras fermentum neque orci, nec tristique elit hendrerit fermentum. Phasellus a consequat ante, eu aliquam sem. Aenean a dui libero. Duis eget felis a leo ultricies placerat. Etiam sollicitudin, ex sit amet tincidunt semper, nisl leo egestas turpis, ac semper nisi sapien ut ligula. Donec nulla nisl, faucibus eu interdum sed, gravida id sapien. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam varius nibh in mauris rhoncus tempor. Nunc convallis rhoncus tellus sagittis vehicula. Vestibulum nibh nunc, pretium id porta fringilla, luctus eget orci. Vivamus iaculis euismod mi, ac molestie erat fermentum quis. + + Curabitur felis tortor, efficitur id volutpat in, rhoncus in orci. Nullam hendrerit lacus ac pretium auctor. Nullam suscipit orci ac eros commodo, rutrum hendrerit lectus blandit. Nunc vehicula id mauris ut ornare. Nulla sed neque arcu. Curabitur suscipit eu libero eu sagittis. Aenean sed convallis risus. Sed at mauris lorem. Nulla at orci id turpis condimentum tristique eleifend vitae mauris. Nullam a blandit tortor. Cras fringilla turpis turpis, in auctor erat feugiat a. Duis ac eros sit amet purus malesuada tempus at non ante. + Nulla ullamcorper, neque ut venenatis aliquet, ipsum lectus scelerisque erat, ut consequat nisi purus non metus. Nam laoreet ex vitae malesuada fermentum. Curabitur ultrices metus eget nulla mollis, nec elementum velit maximus. Integer sed metus vulputate, congue nisi nec, varius mauris. Quisque magna ex, accumsan non libero eu, posuere elementum magna. Integer at mauris tincidunt, eleifend metus ut, semper odio. Vivamus iaculis, augue dictum rhoncus fringilla, nibh nunc congue lorem, in pulvinar ex enim eu purus. Ut ut vestibulum velit. Nam pellentesque turpis in lorem interdum tristique. Sed eget metus et dolor hendrerit elementum. Nulla ut massa dictum, interdum nunc a, rutrum dui. + + Praesent lobortis nisl ut urna mattis, non dignissim nisl tincidunt. Nullam ullamcorper purus vitae lacinia euismod. Proin aliquam nisl non tellus tincidunt placerat. Quisque molestie, erat vel egestas egestas, lectus felis posuere metus, sed placerat odio leo nec lorem. Pellentesque vestibulum porta mollis. Duis malesuada nibh vel odio bibendum viverra. Vestibulum iaculis nisl odio, vel elementum eros rutrum id. Vestibulum cursus dolor quis est faucibus scelerisque. Sed id tortor facilisis, semper magna eget, placerat sem. In non mi in orci convallis gravida. Mauris volutpat quam vitae tortor pharetra tincidunt. Integer ac commodo ligula, nec dignissim felis. Proin elit libero, sodales sit amet vulputate ac, euismod ac arcu. Mauris accumsan sollicitudin sapien id finibus. Nulla facilisi. Vestibulum venenatis sapien sed volutpat eleifend. +