Earth and Space Science
  1. Unit 4: Climate Change
  2. 20  The Story of a Warming World
  • 1  Earth and Space Science
  • Unit 1: Discovering New Worlds
    • Unit 1: Discovering New Worlds
    • 2  Unit 1: Opening — Discovering New Worlds
    • 3  Unit 1: How the Sun Works
    • 4  Unit 1: Star Life Cycles
    • 5  Unit 1: Planets and Orbits
    • 6  Unit 1: Closing — Which Exoplanet Is Most Earth-Like?
  • Unit 2: Probability of Life Elsewhere
    • Unit 2: Probability of Life Elsewhere
    • 7  Unit 2: Opening — Are We Alone?
    • 8  Stability of the Solar System
    • 9  Coevolution of Earth and Life
    • 10  Origin of the Universe
    • 11  Asteroid Orbits & Planetary Defense
    • 12  Unit 2: Closing — The Probability of Life
  • Unit 3: Earthquakes, Volcanoes, & Tsunamis
    • 13  Unit 3: Earthquakes, Volcanoes & Tsunamis
    • 14  Unit 3: Opening — The Krakatoa Enigma
    • 15  Earth’s Interior
    • 16  Surface Features & Plate Boundaries
    • 17  Energy & Matter in Earth's Interior
    • 18  Performance Task: Natural Hazard Risk Assessment
  • Unit 4: Climate Change
    • Unit 4: Climate Change
    • 19  Unit 4: Climate Change - Unit Opening
    • 20  The Story of a Warming World
    • 21  Unit 4: Seasons (Optional 3E)
    • 22  Unit 4: Earth-Sun Dynamics 5E
    • 23  Unit 4: Climate Feedbacks 5E
    • 24  Unit 4: The Past and the Future 5E
    • 25  Unit 4: Climate Change - Unit Closing
  • Unit 5: More Hurricanes & Blizzards in NYC?
    • Unit 5: More Hurricanes & Blizzards in NYC?
    • 26  Unit 5: More Hurricanes & Blizzards in NYC? — Unit Opening
    • 27  Unit 5: Moon Phases
    • 28  Unit 5: Blizzards 5E
    • 29  Unit 5: Paths of Severe Storms 5E
    • 30  Unit 5: Hurricanes 5E
    • 31  Unit 5: Closing — Constructing Your Argument
  • Unit 6: Solutions for a Sustainable Future
    • Unit 6: Building a Sustainable Future
    • 32  Unit 6: Solutions for a Sustainable Future — Unit Opening
    • 33  Unit 6: Burning Fossil Fuels
    • 34  Unit 6: Land Use and Biodiversity
    • 35  Unit 6: Mining
    • 36  Unit 6: Closing — Your Solutions, Your Argument
  • References
  1. Unit 4: Climate Change
  2. 20  The Story of a Warming World

20  The Story of a Warming World

  • Show All Code
  • Hide All Code

  • View Source

20.1 Part 1: The Invisible Engine

Climate change begins with the atmosphere’s chemistry. To understand why the Earth is warming, we must first look at the “Keeling Curve,” the most famous graph in Earth Science.

In 1958, Charles Keeling began measuring CO2 at the Mauna Loa Observatory in Hawaii.

At the start of the record, CO2 levels were around 315 parts per million (ppm). This was already higher than the pre-industrial average, but the curve was just beginning its climb.

If you look closely at the line, you see a zig-zag pattern. This is the “breathing of the Earth.”

When the Northern Hemisphere tilts toward the sun (spring/summer), plants bloom and inhale CO2, dropping the levels. In the fall, leaves decay and release it back.

However, the “breathing” is overwhelmed by a much stronger force.

As we scroll to the present day, the trend accelerates upward. We have now passed 420 ppm, a level not seen on Earth for millions of years. This vertical ascent is the direct result of burning fossil fuels.

Code
// --- Collapsible quiz builder (file-scoped) ---
buildQuiz = function(id, title, questions) {
  const outer = html`<div id="${id}" style="margin:18px 0 24px 0;text-align:center;">
    <button style="
      display:inline-flex;align-items:center;gap:7px;
      background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
      color:#fff;border:none;padding:9px 22px;border-radius:50px;
      font-size:.95em;font-weight:700;cursor:pointer;
      box-shadow:0 3px 12px rgba(102,126,234,.45);
      transition:transform .15s,box-shadow .15s;"
      onmouseover="this.style.transform='scale(1.04)';this.style.boxShadow='0 5px 18px rgba(102,126,234,.55)'"
      onmouseout="this.style.transform='scale(1)';this.style.boxShadow='0 3px 12px rgba(102,126,234,.45)'"
    >
      <span style="font-size:1.1em;">📝</span> ${title}
      <span class="chevron" style="transition:transform .3s;">▼</span>
    </button>

    <div class="quiz-body" style="
      max-height:0;opacity:0;overflow:hidden;
      transition:max-height .5s cubic-bezier(.4,0,.2,1),opacity .4s ease,margin-top .3s ease;
      margin-top:0;text-align:left;">

      <button class="close-btn" style="
        display:block;margin:0 auto 10px auto;
        background:rgba(102,126,234,.12);color:#667eea;border:none;
        padding:5px 18px;border-radius:50px;font-size:.85em;
        font-weight:600;cursor:pointer;">Hide Quiz</button>
      <p style="text-align:center;color:#718096;font-style:italic;font-size:.9em;margin-bottom:12px;">
        Select an answer for each question.</p>
    </div>
  </div>`;

  const toggle = outer.querySelector("button");
  const chevron = toggle.querySelector(".chevron");
  const body   = outer.querySelector(".quiz-body");
  const closeBtn = body.querySelector(".close-btn");

  function expand(){  body.style.maxHeight="2000px";body.style.opacity="1";body.style.marginTop="14px";chevron.style.transform="rotate(180deg)"; }
  function collapse(){ body.style.maxHeight="0";body.style.opacity="0";body.style.marginTop="0";chevron.style.transform="rotate(0)"; }
  toggle.onclick = () => body.style.maxHeight === "0px" || body.style.maxHeight === "" ? expand() : collapse();
  closeBtn.onclick = collapse;

  questions.forEach((qq, qi) => {
    const card = document.createElement("div");
    card.style.cssText = "background:#fff;border-radius:12px;padding:16px 20px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.08);";
    card.innerHTML = `<p style="font-weight:700;margin:0 0 10px;">${qi+1}. ${qq.q}</p>`;
    qq.options.forEach((opt, oi) => {
      const btn = document.createElement("button");
      btn.textContent = opt;
      btn.style.cssText = "display:block;width:100%;text-align:left;padding:10px 14px;margin:6px 0;border:2px solid #e2e8f0;border-radius:8px;background:#fff;cursor:pointer;font-size:.95em;transition:border-color .2s,background .2s;";
      btn.onmouseover = () => { if(!card.dataset.answered){ btn.style.borderColor="#667eea";btn.style.background="#f0f0ff"; }};
      btn.onmouseout  = () => { if(!card.dataset.answered){ btn.style.borderColor="#e2e8f0";btn.style.background="#fff"; }};
      btn.onclick = () => {
        if(card.dataset.answered) return;
        card.dataset.answered = "true";
        card.querySelectorAll("button").forEach(b => { b.style.cursor="default"; b.onmouseover=null; b.onmouseout=null; });
        if(oi === qq.correct){
          btn.style.borderColor="#48bb78";btn.style.background="#f0fff4";
          fb.innerHTML = "✅ Correct! " + qq.explanation;
          fb.style.color="#276749";fb.style.background="#f0fff4";
        } else {
          btn.style.borderColor="#fc8181";btn.style.background="#fff5f5";
          card.querySelectorAll("button")[qq.correct].style.borderColor="#48bb78";
          card.querySelectorAll("button")[qq.correct].style.background="#f0fff4";
          fb.innerHTML = "❌ " + qq.explanation;
          fb.style.color="#9b2c2c";fb.style.background="#fff5f5";
        }
        fb.style.padding="10px 14px";fb.style.marginTop="8px";
      };
      card.appendChild(btn);
    });
    const fb = document.createElement("div");
    fb.style.cssText = "border-radius:8px;font-size:.9em;transition:all .3s;";
    card.appendChild(fb);
    body.appendChild(card);
  });
  return outer;
}
Code
buildQuiz("keeling-curve-quiz", "Check Your Understanding — The Keeling Curve", [
  {
    q: "What causes the zig-zag (seasonal oscillation) pattern visible in the Keeling Curve?",
    options: [
      "A) Measurement errors at the Mauna Loa observatory",
      "B) Volcanic eruptions releasing and absorbing CO₂",
      "C) Seasonal plant growth absorbing CO₂ in spring/summer and releasing it in fall/winter",
      "D) Changes in ocean temperature throughout the year"
    ],
    correct: 2,
    explanation: "The seasonal 'breathing' pattern comes from Northern Hemisphere vegetation: plants absorb CO₂ during the growing season (lowering levels) and release it during decomposition in fall/winter."
  },
  {
    q: "What is the approximate CO₂ level today, and how does it compare to pre-industrial levels (~280 ppm)?",
    options: [
      "A) About 315 ppm — only slightly higher than pre-industrial",
      "B) About 350 ppm — a moderate increase",
      "C) About 420 ppm — roughly 50% higher than pre-industrial",
      "D) About 600 ppm — more than double pre-industrial"
    ],
    correct: 2,
    explanation: "Current CO₂ levels have surpassed 420 ppm, about 50% higher than the pre-industrial baseline of ~280 ppm. This level has not been seen on Earth for millions of years."
  }
])

20.2 Part 2: The Consequence

Rising CO2 is not just a number; it traps heat. We can see the direct correlation when we look at global temperature anomalies over the last century.

This chart shows the global temperature deviation from the 20th-century average.

Between 1880 and 1940, years were often cooler than average (shown in blue). The climate fluctuated naturally, but remained relatively stable.

By the 1980s and 1990s, a shift occurs. The blue bars disappear, replaced almost entirely by red. The “greenhouse effect” predicted by physics is now visible in the data.

In the last 20 years, the warming has intensified.

The bars are not just red; they are growing taller. This shows that the rate of warming is increasing, driven by the CO2 accumulation we saw in the previous chart.

Code
buildQuiz("temp-anomaly-story-quiz", "Check Your Understanding — Temperature Anomalies", [
  {
    q: "According to the temperature anomaly chart, when did the shift from mostly blue (cool) bars to mostly red (warm) bars occur?",
    options: [
      "A) Around 1920",
      "B) Around 1950",
      "C) Around the 1980s",
      "D) Around 2010"
    ],
    correct: 2,
    explanation: "By the 1980s, cool years (blue bars) largely disappeared and were replaced by warm years (red bars), marking the emergence of a clear, sustained warming signal above natural variability."
  },
  {
    q: "How are the Keeling Curve (Part 1) and the Temperature Anomaly chart (Part 2) connected?",
    options: [
      "A) They are unrelated — CO₂ and temperature change independently",
      "B) Rising CO₂ traps more heat in the atmosphere, causing the temperature anomalies to grow",
      "C) Temperature increases cause CO₂ to rise, not the other way around",
      "D) Both are caused solely by changes in solar output"
    ],
    correct: 1,
    explanation: "The rising CO₂ from burning fossil fuels strengthens the greenhouse effect, trapping more heat and causing the temperature anomalies to grow larger over time. The physics of the greenhouse effect directly links these two datasets."
  }
])

])

🌍
19  Unit 4: Climate Change - Unit Opening
21  Unit 4: Seasons (Optional 3E)
Source Code
---
title: "The Story of a Warming World"
format:
  html:
    page-layout: full
    filters:
      - ../_extensions/qmd-lab/closeread/closeread.lua
    css:
      - ../styles.css
      - ../_extensions/qmd-lab/closeread/closeread.css
    cr-style:
      narrative-background-color-overlay: "#f0f0f0"
      section-background-color: "white"
---

```{python}
#| label: setup
#| include: false
import plotly.graph_objects as go
import numpy as np
import pandas as pd

# --- DATA GENERATION (Simulating Real Data for the Textbook) ---

# 1. Simulating the Keeling Curve (CO2)
years = np.arange(1958, 2025, 0.1)
trend = 315 + (years - 1958) * 1.6 + (years - 1958)**2 * 0.015 # The rising curve
seasonal = 3 * np.sin(2 * np.pi * years) # The seasonal "breath" of the forest
co2_levels = trend + seasonal
df_co2 = pd.DataFrame({'year': years, 'co2': co2_levels})

# 2. Simulating Temperature Anomalies (Global Warming)
years_temp = np.arange(1880, 2024)
# Random noise + exponential growth trend
anomalies = -0.2 + (np.random.rand(len(years_temp)) - 0.5) * 0.2 + ((years_temp - 1900) / 100)**3
df_temp = pd.DataFrame({'year': years_temp, 'anomaly': anomalies})
# Color logic: Blue for cold, Red for hot
df_temp['color'] = np.where(df_temp['anomaly'] < 0, 'rgb(100, 149, 237)', 'rgb(220, 20, 60)')

# --- FIGURE CONSTRUCTION ---

# Figure 1: The Keeling Curve
fig_co2 = go.Figure()
fig_co2.add_trace(go.Scatter(x=df_co2['year'], y=df_co2['co2'], 
                             mode='lines', name='CO2 ppm', line=dict(color='green', width=2)))
fig_co2.update_layout(title="Atmospheric CO2 at Mauna Loa", xaxis_title="Year", yaxis_title="CO2 (ppm)",
                      template="plotly_white", margin=dict(t=50, b=50))

# Figure 2: Temperature Anomalies
fig_temp = go.Figure()
fig_temp.add_trace(go.Bar(x=df_temp['year'], y=df_temp['anomaly'], 
                          marker_color=df_temp['color'], name='Anomaly'))
fig_temp.update_layout(title="Global Temperature Anomalies (1880-2024)", xaxis_title="Year", yaxis_title="Deviation (°C)",
                       template="plotly_white", margin=dict(t=50, b=50))
```

## Part 1: The Invisible Engine

Climate change begins with the atmosphere's chemistry. To understand why the Earth is warming, we must first look at the "Keeling Curve," the most famous graph in Earth Science.

::: {.cr-section}

In 1958, Charles Keeling began measuring CO2 at the Mauna Loa Observatory in Hawaii. @cr-keeling

At the start of the record, CO2 levels were around 315 parts per million (ppm). This was already higher than the pre-industrial average, but the curve was just beginning its climb. @cr-keeling

If you look closely at the line, you see a zig-zag pattern. This is the "breathing of the Earth." @cr-keeling

When the Northern Hemisphere tilts toward the sun (spring/summer), plants bloom and inhale CO2, dropping the levels. In the fall, leaves decay and release it back. @cr-keeling

However, the "breathing" is overwhelmed by a much stronger force. @cr-keeling

As we scroll to the present day, the trend accelerates upward. We have now passed 420 ppm, a level not seen on Earth for millions of years. This vertical ascent is the direct result of burning fossil fuels. @cr-keeling

::: {#cr-keeling}
```{python}
#| echo: false
fig_co2
```
:::

:::

```{ojs}
//| echo: false
// --- Collapsible quiz builder (file-scoped) ---
buildQuiz = function(id, title, questions) {
  const outer = html`<div id="${id}" style="margin:18px 0 24px 0;text-align:center;">
    <button style="
      display:inline-flex;align-items:center;gap:7px;
      background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
      color:#fff;border:none;padding:9px 22px;border-radius:50px;
      font-size:.95em;font-weight:700;cursor:pointer;
      box-shadow:0 3px 12px rgba(102,126,234,.45);
      transition:transform .15s,box-shadow .15s;"
      onmouseover="this.style.transform='scale(1.04)';this.style.boxShadow='0 5px 18px rgba(102,126,234,.55)'"
      onmouseout="this.style.transform='scale(1)';this.style.boxShadow='0 3px 12px rgba(102,126,234,.45)'"
    >
      <span style="font-size:1.1em;">📝</span> ${title}
      <span class="chevron" style="transition:transform .3s;">▼</span>
    </button>

    <div class="quiz-body" style="
      max-height:0;opacity:0;overflow:hidden;
      transition:max-height .5s cubic-bezier(.4,0,.2,1),opacity .4s ease,margin-top .3s ease;
      margin-top:0;text-align:left;">

      <button class="close-btn" style="
        display:block;margin:0 auto 10px auto;
        background:rgba(102,126,234,.12);color:#667eea;border:none;
        padding:5px 18px;border-radius:50px;font-size:.85em;
        font-weight:600;cursor:pointer;">Hide Quiz</button>
      <p style="text-align:center;color:#718096;font-style:italic;font-size:.9em;margin-bottom:12px;">
        Select an answer for each question.</p>
    </div>
  </div>`;

  const toggle = outer.querySelector("button");
  const chevron = toggle.querySelector(".chevron");
  const body   = outer.querySelector(".quiz-body");
  const closeBtn = body.querySelector(".close-btn");

  function expand(){  body.style.maxHeight="2000px";body.style.opacity="1";body.style.marginTop="14px";chevron.style.transform="rotate(180deg)"; }
  function collapse(){ body.style.maxHeight="0";body.style.opacity="0";body.style.marginTop="0";chevron.style.transform="rotate(0)"; }
  toggle.onclick = () => body.style.maxHeight === "0px" || body.style.maxHeight === "" ? expand() : collapse();
  closeBtn.onclick = collapse;

  questions.forEach((qq, qi) => {
    const card = document.createElement("div");
    card.style.cssText = "background:#fff;border-radius:12px;padding:16px 20px;margin-bottom:14px;box-shadow:0 2px 8px rgba(0,0,0,.08);";
    card.innerHTML = `<p style="font-weight:700;margin:0 0 10px;">${qi+1}. ${qq.q}</p>`;
    qq.options.forEach((opt, oi) => {
      const btn = document.createElement("button");
      btn.textContent = opt;
      btn.style.cssText = "display:block;width:100%;text-align:left;padding:10px 14px;margin:6px 0;border:2px solid #e2e8f0;border-radius:8px;background:#fff;cursor:pointer;font-size:.95em;transition:border-color .2s,background .2s;";
      btn.onmouseover = () => { if(!card.dataset.answered){ btn.style.borderColor="#667eea";btn.style.background="#f0f0ff"; }};
      btn.onmouseout  = () => { if(!card.dataset.answered){ btn.style.borderColor="#e2e8f0";btn.style.background="#fff"; }};
      btn.onclick = () => {
        if(card.dataset.answered) return;
        card.dataset.answered = "true";
        card.querySelectorAll("button").forEach(b => { b.style.cursor="default"; b.onmouseover=null; b.onmouseout=null; });
        if(oi === qq.correct){
          btn.style.borderColor="#48bb78";btn.style.background="#f0fff4";
          fb.innerHTML = "✅ Correct! " + qq.explanation;
          fb.style.color="#276749";fb.style.background="#f0fff4";
        } else {
          btn.style.borderColor="#fc8181";btn.style.background="#fff5f5";
          card.querySelectorAll("button")[qq.correct].style.borderColor="#48bb78";
          card.querySelectorAll("button")[qq.correct].style.background="#f0fff4";
          fb.innerHTML = "❌ " + qq.explanation;
          fb.style.color="#9b2c2c";fb.style.background="#fff5f5";
        }
        fb.style.padding="10px 14px";fb.style.marginTop="8px";
      };
      card.appendChild(btn);
    });
    const fb = document.createElement("div");
    fb.style.cssText = "border-radius:8px;font-size:.9em;transition:all .3s;";
    card.appendChild(fb);
    body.appendChild(card);
  });
  return outer;
}
```

```{ojs}
//| echo: false
buildQuiz("keeling-curve-quiz", "Check Your Understanding — The Keeling Curve", [
  {
    q: "What causes the zig-zag (seasonal oscillation) pattern visible in the Keeling Curve?",
    options: [
      "A) Measurement errors at the Mauna Loa observatory",
      "B) Volcanic eruptions releasing and absorbing CO₂",
      "C) Seasonal plant growth absorbing CO₂ in spring/summer and releasing it in fall/winter",
      "D) Changes in ocean temperature throughout the year"
    ],
    correct: 2,
    explanation: "The seasonal 'breathing' pattern comes from Northern Hemisphere vegetation: plants absorb CO₂ during the growing season (lowering levels) and release it during decomposition in fall/winter."
  },
  {
    q: "What is the approximate CO₂ level today, and how does it compare to pre-industrial levels (~280 ppm)?",
    options: [
      "A) About 315 ppm — only slightly higher than pre-industrial",
      "B) About 350 ppm — a moderate increase",
      "C) About 420 ppm — roughly 50% higher than pre-industrial",
      "D) About 600 ppm — more than double pre-industrial"
    ],
    correct: 2,
    explanation: "Current CO₂ levels have surpassed 420 ppm, about 50% higher than the pre-industrial baseline of ~280 ppm. This level has not been seen on Earth for millions of years."
  }
])
```

## Part 2: The Consequence

Rising CO2 is not just a number; it traps heat. We can see the direct correlation when we look at global temperature anomalies over the last century.

::: {.cr-section}

This chart shows the global temperature deviation from the 20th-century average. @cr-temp

Between 1880 and 1940, years were often cooler than average (shown in blue). The climate fluctuated naturally, but remained relatively stable. @cr-temp

By the 1980s and 1990s, a shift occurs. The blue bars disappear, replaced almost entirely by red. The "greenhouse effect" predicted by physics is now visible in the data. @cr-temp

In the last 20 years, the warming has intensified. @cr-temp

The bars are not just red; they are growing taller. This shows that the rate of warming is increasing, driven by the CO2 accumulation we saw in the previous chart. @cr-temp

::: {#cr-temp}
```{python}
#| echo: false
fig_temp
```
:::

:::

```{ojs}
//| echo: false
buildQuiz("temp-anomaly-story-quiz", "Check Your Understanding — Temperature Anomalies", [
  {
    q: "According to the temperature anomaly chart, when did the shift from mostly blue (cool) bars to mostly red (warm) bars occur?",
    options: [
      "A) Around 1920",
      "B) Around 1950",
      "C) Around the 1980s",
      "D) Around 2010"
    ],
    correct: 2,
    explanation: "By the 1980s, cool years (blue bars) largely disappeared and were replaced by warm years (red bars), marking the emergence of a clear, sustained warming signal above natural variability."
  },
  {
    q: "How are the Keeling Curve (Part 1) and the Temperature Anomaly chart (Part 2) connected?",
    options: [
      "A) They are unrelated — CO₂ and temperature change independently",
      "B) Rising CO₂ traps more heat in the atmosphere, causing the temperature anomalies to grow",
      "C) Temperature increases cause CO₂ to rise, not the other way around",
      "D) Both are caused solely by changes in solar output"
    ],
    correct: 1,
    explanation: "The rising CO₂ from burning fossil fuels strengthens the greenhouse effect, trapping more heat and causing the temperature anomalies to grow larger over time. The physics of the greenhouse effect directly links these two datasets."
  }
])
```
])