Where ideas percolate and thoughts brew

The Romance Hierarchy

About This Sketch

A split-screen comparison of two approaches to human connection. On the left, a single person relies on one dominant romantic relationship while other connections fade. On the right, a network of equally-valued relationships provides distributed support. The visualization challenges the cultural assumption that romantic love should be elevated above all other forms of connection.

Algorithm

This visualization contrasts two models of human connection: the hierarchy model (left) where one romantic relationship dominates and all others fade into insignificance, versus the portfolio model (right) where multiple connections of equal importance support each other in a distributed network. The sketch uses visual weight (line thickness, node size, opacity) to represent the relative importance assigned to different relationships. In the hierarchy model, one connection pulses brightly while others remain faded and small. In the portfolio model, all connections maintain equal visual presence and interconnect to form a robust support network. This accompanies the blog post "The Romance Hierarchy" which argues that our cultural elevation of romantic love above all other forms of connection weakens both romantic relationships (by overburdening them) and all other relationships (by systematically devaluing them).

Pseudocode

SETUP:
  Create hierarchy person at left with:
    - One large romantic connection (pulsing, bright)
    - Six smaller secondary connections (faded, weak)
  Create portfolio people arranged in circle at right
  Initialize animation time

DRAW (every frame):
  Get current theme colors
  Clear background

  LEFT SIDE (Hierarchy):
    Draw label "Hierarchy"
    For each connection from central person:
      If romantic connection:
        Draw thick, bright, pulsing line
        Draw large endpoint
      Else:
        Draw thin, faded line
        Draw small endpoint
    Draw central person
    Display status: "One connection bears all weight"

  RIGHT SIDE (Portfolio):
    Draw label "Portfolio"
    For each person in network:
      Check distance to all other people
      If within connection threshold:
        Draw connecting line (strength based on distance)
    Draw all people as equal-sized nodes
    Display status: "Many connections share the load"

  Draw divider between models
  Display message: "Distribute your emotional investment"
  Increment time for animation

Source Code

let sketch = function(p) {
    let hierarchyPerson;
    let portfolioPeople;
    let time = 0;

    class HierarchyPerson {
        constructor() {
            this.x = 100;
            this.y = 150;
            this.connections = [];

            // Create connections of different "importance"
            // One large romantic connection
            this.connections.push({
                type: 'romantic',
                angle: -p.HALF_PI,
                distance: 60,
                size: 20,
                strength: 1.0,
                pulseSpeed: 0.05
            });

            // Several smaller, faded connections
            for (let i = 0; i < 6; i++) {
                let angle = p.TWO_PI * i / 6;
                this.connections.push({
                    type: 'other',
                    angle: angle,
                    distance: 45,
                    size: 8,
                    strength: 0.3,
                    pulseSpeed: 0.02
                });
            }
        }

        display(colors) {
            // Draw connections
            for (let conn of this.connections) {
                let endX = this.x + p.cos(conn.angle) * conn.distance;
                let endY = this.y + p.sin(conn.angle) * conn.distance;

                // Pulsing effect
                let pulse = p.sin(time * conn.pulseSpeed) * 0.2 + 0.8;

                if (conn.type === 'romantic') {
                    // Thick, bright line for romantic connection
                    p.stroke(...colors.accent2, 200 * pulse);
                    p.strokeWeight(3);
                    p.line(this.x, this.y, endX, endY);

                    // Large endpoint
                    p.noStroke();
                    p.fill(...colors.accent2, 220 * pulse);
                    p.circle(endX, endY, conn.size * pulse);
                } else {
                    // Thin, faded lines for other connections
                    p.stroke(...colors.accent3, 80 * conn.strength);
                    p.strokeWeight(1);
                    p.line(this.x, this.y, endX, endY);

                    // Small, faded endpoints
                    p.noStroke();
                    p.fill(...colors.accent3, 100 * conn.strength);
                    p.circle(endX, endY, conn.size);
                }
            }

            // Draw central person (stressed from supporting everything through one connection)
            p.noStroke();
            p.fill(...colors.accent2, 180);
            p.circle(this.x, this.y, 16);
        }
    }

    class PortfolioPerson {
        constructor(index, total) {
            let angle = p.TWO_PI * index / total;
            let radius = 45;
            this.x = 300 + p.cos(angle) * radius;
            this.y = 150 + p.sin(angle) * radius;
            this.connections = [];
            this.baseAngle = angle;
        }

        display(colors) {
            p.noStroke();
            p.fill(...colors.accent2, 200);
            p.circle(this.x, this.y, 14);
        }
    }

    p.setup = function() {
        p.createCanvas(400, 300);
        p.colorMode(p.RGB);

        hierarchyPerson = new HierarchyPerson();

        // Create network of portfolio people
        portfolioPeople = [];
        for (let i = 0; i < 7; i++) {
            portfolioPeople.push(new PortfolioPerson(i, 7));
        }
    };

    p.draw = function() {
        const colors = getThemeColors();
        p.background(...colors.bg);

        time++;

        // Left side - Hierarchy model
        p.noStroke();
        p.fill(...colors.accent1, 180);
        p.textAlign(p.CENTER);
        p.textSize(11);
        p.text('Hierarchy', 100, 35);

        hierarchyPerson.display(colors);

        p.textSize(9);
        p.fill(...colors.accent3, 150);
        p.text('One connection', 100, 270);
        p.text('bears all weight', 100, 282);

        // Right side - Portfolio model
        p.fill(...colors.accent1, 180);
        p.textSize(11);
        p.text('Portfolio', 300, 35);

        // Draw interconnected network
        // First pass: draw all connections
        for (let i = 0; i < portfolioPeople.length; i++) {
            let person = portfolioPeople[i];

            // Connect to neighbors
            for (let j = 0; j < portfolioPeople.length; j++) {
                if (i !== j) {
                    let other = portfolioPeople[j];
                    let distance = p.dist(person.x, person.y, other.x, other.y);

                    // Connect if close enough
                    if (distance < 80) {
                        let alpha = p.map(distance, 0, 80, 180, 60);
                        p.stroke(...colors.accent2, alpha);
                        p.strokeWeight(1.5);
                        p.line(person.x, person.y, other.x, other.y);
                    }
                }
            }
        }

        // Second pass: draw people on top
        for (let person of portfolioPeople) {
            person.display(colors);
        }

        p.noStroke();
        p.textSize(9);
        p.fill(...colors.accent3, 150);
        p.text('Many connections', 300, 270);
        p.text('share the load', 300, 282);

        // Divider
        p.stroke(...colors.accent1, 50);
        p.strokeWeight(1);
        p.line(200, 50, 200, 260);

        // Bottom message
        p.noStroke();
        p.fill(...colors.accent1, 140);
        p.textSize(9);
        p.textAlign(p.CENTER);
        p.text('Distribute your emotional investment', 200, 295);
    };
};