Skip to main content

Act 1: Dynamical Systems

<!DOCTYPE html>
<html lang="vulnerability">
<head>
 <meta charset="UTF-8">
 <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
 <meta name = "keywords" content = "HTML, CSS, JavaScript">
 <meta name = "description" content = "a love poem">
 <meta name = "author" content = "the source of eternal love">

    <title>The Delivery</title>

 <style>
    /*by hand*/
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;

  /*Characters: you, me*/

    /*my*/
    body {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
        min-height: 100vh;
        position: relative;
        overflow-x: hidden;
    }
    /*trembling*/

  /*Setting:*/
    .titleContent-wrapper {
        position: relative;
        z-index: 10;
        max-width: 1200px;
        margin: 0 auto;
        padding: 40px 20px;
    }
    .titleHeader {
        text-align: center;
        margin-bottom: 40px;
    }
    .titleHeader h1 {
        font-size: 2.5em;
        color: #2c3e50;
        font-weight: 300;
        letter-spacing: 2px;
        margin-bottom: 10px;
        text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
    }

    .card {
        background: rgba(255, 255, 255, 0.10);
        border-radius: 16px;
        padding: 30px;
        margin-bottom: 30px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.10);
        backdrop-filter: blur(.5px);
    }

  /*Plot:*/
    .signHere {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 20px;
    }

  /*Motif:*/
    .button-group {
        display: flex;
        gap: 15px;
    }
    button {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        border: none;
        padding: 12px 30px;
        border-radius: 25px;
        font-size: 16px;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.3s ease;
        box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
    }
    button:hover {
        transform: translateY(-2px);
        box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
    }
    button:active {
        transform: translateY(0);
    }

  /*Themes:*/
      /*something to treasure*/
    .image-container {
        margin-top: 20px;
        text-align: center;
    }
    .image-container img {
        max-width: 200px;
        border-radius: 12px;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.01);
        transition: transform 0.3s ease;
    }
    .image-container img:hover {
        transform: scale(1.05);
    }

      /*a total vibe*/
    .choices-section {
        margin-top: 30px;
        align-items: center;
        display: flex;
        flex-direction: column;
    }
    .choices-section h2 {
        color: #2c3e50;
        font-size: 1.8em;
        font-weight: 400;
        margin-bottom: 25px;
        text-align: center;
    }
    .choice-item {
        background: rgba(255, 255, 255, .2);
        padding: 20px;
        border-radius: 12px;
        margin-bottom: 15px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        transition: all 0.3s ease;
    }
    .choice-item:hover {
        background: rgba(255, 255, 255, 0.5);
        transform: translateX(5px);
    }
    .choice-text {
        font-size: 1.1em;
        color: #34495e;
        align-items: center;
    }

      /*a long-term commitment*/
    .response-text {
        font-size: 1.1em;
        color: #667eea;
        font-weight: 500;
        font-style: italic;
        align-items: center;
    }

    .axiom {
        background: #2c3e50;
        color: #ecf0f1;
        padding: 20px;
        border-radius: 12px;
        font-family: 'Courier New', monospace;
        font-size: 1em;
        line-height: 1.8;
        margin-top: 30px;
        box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.3);
    }

      /*a place where anything is possible*/
    .canvas-container {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 1;
        pointer-events: none;
    }
    .canvas-title {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        color: rgba(44, 66, 88, 0.4);
        font-size: 1.2em;
        font-weight: 300;
        letter-spacing: 3px;
        text-shadow: 0 0 20px rgba(255, 255, 255, 0.8);
        z-index: 5;
        pointer-events: none;
    }
    canvas {
        display: block;
        width: 100%;
        height: 100%;
    }

      /*where everything seems to fit*/
    @media (max-width: 768px) {
      .titleHeader h1 {
        font-size: 1.8em;
        }

      .button-group {
        flex-direction: column;
        }

      button {
        width: 100%;
        }

      .choice-item {
        flex-direction: column;
                gap: 15px;
                text-align: center;
        }
    }
  </style>
</head>

<!--Storyline:-->
<body>
  <!--palying in the background, where there is no beginning or end, in space and time-->
    <div class="canvas-container">
        <div class="canvas-title">the Love here is infinite</div>
        <canvas id="canvas"></canvas>
        </div>

      <!--a main request-->
        <div class="titleContent-wrapper">
            <div class="titleHeader">
        <!--albeit a bit clumsy-->
                  <h1>The Delivery</h1>
            </div>

        <!--the face-->
            <div class="card">
          <!--says, please-->
                <div class="signHere">
                    <div class="button-group">
                    <button onclick="changeImage('policy')">Policy</button>
                    <button onclick="changeImage('open')">Open</button>
                    </div>

                <div class="image-container">
            <!--to have and to hold, till death do us part-->
                    <img id="myImage" 
                                 src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQkYRdrvg_ylfhamyg0bmKPeq6HE4xQaARx4A&s"
                        alt="Delivery Image">
                </div>
            </div>
            </div>
        <!--the face-->
            <div class="card">
          <!--a patient reflection-->
                <div class="choices-section">
                    <h2>Having seen the contents</h2>
                    <div class="choice-item">
                        <span class="choice-text" id="possibility1">You may choose to <button onclick="runFunction()">Run</button></span>
                                </div>
            <!--or-->
                    <div class="choice-item">
                        <span class="choice-text" id="possibility2">You may choose to <button onclick="stayFunction()">Stay</button></span> 
                    </div>
                </div>
            <!--a prayer-->
                <div class="axiom">
                    let x = you;<br>
                    let y = me;<br>
                    let sum = you + me + ∞;
                </div>    
            </div>
    </div>

<!-- rendering dynamical systems in a dynamic language-->

  <script>
  // no refunds, only exchanges; sine here
    function changeImage(type) {
        const img = document.getElementById('myImage');
        if (type === 'policy') {
            img.src = 'https://i.ebayimg.com/images/g/q~UAAeSwhRhoXsD0/s-l300.jpg';
        } else if (type === 'open') {
            img.src = 'https://tse2.mm.bing.net/th/id/OIP.Jrt2WxsH2XXWEH44qYc3SgHaE7?rs=1&pid=ImgDetMain&o=7&rm=3';
        }
    }

  // your heart knows this —
    function runFunction() {
        document.getElementById("possibility1").innerHTML = 
            '<span class="response-text">Я жду тебя с распростёртыми руками</span>';
    }

    function stayFunction() {
        document.getElementById("possibility2").innerHTML = 
            '<span class="response-text">I am waiting for you with open arms</span>';
    }

  // in a space of pure potential
    const canvas = document.getElementById('canvas');
    const lex = canvas.getContext('2d');
  // i have a job for you

    function resizeCanvas() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }

    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);

    let centerX = canvas.width / 2;
    let centerY = canvas.height / 2;

  // establishing natural parameters and laying our foundations
    const g = 0.2;
    const L = 150;
    const damping = 1;
        
    let theta = Math.PI / 3;
    let omega = 0;
    let time = 0;
        
    function toCanvasX(th) {
        const scale = Math.min(canvas.width, canvas.height) * 0.35;
        return canvas.width / 2 + th * scale / Math.PI;
    }
        
    function toCanvasY(om) {
        const maxOmega = 3;
        const scale = Math.min(canvas.width, canvas.height) * 0.35;
        return canvas.height / 2 - om * scale / maxOmega;
    }

  // we're going places
    function acceleration(th) {
        return -(g / L) * Math.sin(th) * 100;
    }

    function getVelocity(th, om) {
        const dtheta_dt = om;
        const domega_dt = -(g / L) * Math.sin(th) * 100;
        return { dtheta: dtheta_dt, domega: domega_dt };
    }

  // caught in a spectrum of possibilities
    function getColor(th, om, alpha = 1) {
        const hue = (th * 60 + om * 30 + time * 0.005) % 360;
        const saturation = 80 + Math.sin(time * 0.0001) * 20;
        const lightness = 60 + Math.sin(time * 0.0002) * 10;
        return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`;
    }

  // our magnitude and direction are stored efficiently
    function drawFlowingVectors() {
        centerX = canvas.width / 2;
        centerY = canvas.height / 2;
        const gridSize = 80;
        const sphereRadius = Math.min(canvas.width, canvas.height) * 0.4;

        for (let i = 0; i < canvas.width; i += gridSize) {
            for (let j = 0; j < canvas.height; j += gridSize) {
                const distFromCenter = Math.sqrt((i - centerX) ** 2 + (j - centerY) ** 2);
                if (distFromCenter > sphereRadius) continue;

                const scale = Math.min(canvas.width, canvas.height) * 0.35;
                const th = ((i - centerX) / scale) * Math.PI;
                const om = -((j - centerY) / scale) * 3;

                const vel = getVelocity(th, om);
                const dx = vel.dtheta * 3;
                const dy = -vel.domega * 3;
                const mag = Math.sqrt(dx * dx + dy * dy);

                if (mag < 0.1) continue;

                const pendulumX = toCanvasX(theta);
                const pendulumY = toCanvasY(omega);
                const distToPendulum = Math.sqrt((i - pendulumX) ** 2 + (j - pendulumY) ** 2);
                const proximityEffect = Math.exp(-distToPendulum / 150);

                const flowSpeed = 0.10;
                const flowPhase = (time * flowSpeed + i * 0.01 + j * 0.01) % 1.0;
                const flowOffset = flowPhase * 1.5;
                const angle = Math.atan2(dy, dx);

                const curvatureAmount = (distFromCenter / sphereRadius) * 0.3;
                const angleToCenter = Math.atan2(j - centerY, i - centerX);
                const curvedAngle = angle + Math.sin(angleToCenter) * curvatureAmount;

                const x = i + Math.cos(curvedAngle) * flowOffset * 20;
                const y = j + Math.sin(curvedAngle) * flowOffset * 20;
                const flowFade = Math.pow(Math.sin(flowPhase * Math.PI), 0.5);
                const edgeFade = 1 - Math.pow(distFromCenter / sphereRadius, 3);
                const alpha = (0.4 + proximityEffect * 0.5) * edgeFade * flowFade;

                if (alpha < 0.05) continue;

                lex.save();
                lex.translate(x, y);
                lex.rotate(curvedAngle);

                lex.fillStyle = getColor(th, om, alpha);
                lex.font = `${8 + proximityEffect * 4}px Arial`;
                lex.textAlign = 'center';
                lex.textBaseline = 'middle';

                if (proximityEffect > 0.1) {
                    lex.shadowBlur = proximityEffect * 50;
                    lex.shadowColor = getColor(th, om, alpha * 0.2);
                }

                const text = 'Love';
                const charSpacing = 0.08;
                const radius = 202;

                for (let c = 0; c < text.length; c++) {
                    const charAngle = (c - text.length / 2) * charSpacing;
                    const charX = Math.sin(charAngle) * radius;
                    const charY = -Math.cos(charAngle) * radius + radius;

                    lex.save();
                    lex.translate(charX, charY);
                    lex.rotate(charAngle);
                    lex.fillText(text[c], 0, 0);
                    lex.restore();
                }

                lex.shadowBlur = 0;
                lex.restore();
            }
        }
    }
        
  // anchored to our Azimuthal Zero
    function drawAxes() {
        centerX = canvas.width / 2;
        centerY = canvas.height / 2;
        const sphereRadius = Math.min(canvas.width, canvas.height) * 0.4;

        const outerGlow = lex.createRadialGradient(centerX, centerY, sphereRadius - 20, centerX, centerY, sphereRadius + 20);
        outerGlow.addColorStop(0, 'rgba(255, 255, 255, 0.1)');
        outerGlow.addColorStop(0.5, 'rgba(255, 255, 255, 0.05)');
        outerGlow.addColorStop(1, 'rgba(255, 255, 255, 0)');
        lex.fillStyle = outerGlow;
        lex.beginPath();
        lex.arc(centerX, centerY, sphereRadius + 20, 0, Math.PI * 2);
        lex.fill();

        lex.strokeStyle = 'rgba(255, 255, 255, 0.3)';
        lex.lineWidth = 2;
        lex.beginPath();
        lex.arc(centerX, centerY, sphereRadius, 0, Math.PI * 2);
        lex.stroke();

        lex.strokeStyle = 'rgba(255, 255, 255, 0.2)';
        lex.lineWidth = 1;
        lex.beginPath();
        lex.arc(centerX, centerY, sphereRadius - 5, 0, Math.PI * 2);
        lex.stroke();

        lex.strokeStyle = 'rgba(255, 255, 255, 0.2)';
        lex.lineWidth = 1;
        lex.beginPath();
        lex.moveTo(centerX - sphereRadius, centerY);
        lex.lineTo(centerX + sphereRadius, centerY);
        lex.stroke();

        lex.beginPath();
        lex.moveTo(centerX, centerY - sphereRadius);
        lex.lineTo(centerX, centerY + sphereRadius);
        lex.stroke();
        lex.fillStyle = 'rgba(255, 255, 255, 0.4)';
        lex.font = '14px Arial';
        lex.textAlign = 'center';
        lex.shadowBlur = 10;
        lex.shadowColor = 'rgba(255, 255, 255, 0.3)';

        lex.fillText('θ', centerX + sphereRadius - 30, centerY - 10);
        lex.fillText('ω', centerX + 20, centerY - sphereRadius + 30);
        lex.shadowBlur = 0;
    }

  // we overcome —
    function update() {
        const acc = acceleration(theta);
        omega += acc;
        omega *= damping;
        theta += omega;
        time += 0.1;
    }

  // we imagine and create —
    function draw() {
        lex.fillStyle = 'rgba(0, 0, 0, 0)';
        lex.fillRect(0, 0, canvas.width, canvas.height);
        drawAxes();
        drawFlowingVectors();
    }

  // we inspire and bring to life —
    function animate() {
        update();
        draw();
        requestAnimationFrame(animate);
    }

  // we fetch; we
    animate();
  </script>
</body>
</html>