|
Server : Apache/2.4.62 System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64 User : www ( 80) PHP Version : 8.3.8 Disable Function : NONE Directory : /domains/drsuper/CalculusMechanics/ |
Upload File : |
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Adventure 1 – Measuring the World by Slices and Sticks</title>
<style>
body {
font-size: 18px;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
margin: 0;
padding: 0;
background: #ffffff; /* remove outer blue page */
color: #222;
}
.wrap{
padding: 12px 18px 18px;
max-width: none;
margin: 0;
}
.nav-row{
display:flex;
flex-wrap:wrap;
gap:12px;
margin-bottom:0.8rem;
align-items:center;
}
.top-buttons{
display: flex;
gap: 10px;
margin-left: 12px; /* ← move right */
}
button {
background: #e9f0ff;
border: 2px solid #6b8cff;
border-radius: 0;
padding: 10px 18px;
font-size: 1rem;
cursor: pointer;
box-shadow: 0 3px 0 #4f6fe6;
transition: all 0.12s ease;
}
/* Hover */
button:hover {
background: #f3f7ff;
}
/* Pressed */
button:active {
background: #cddcff;
box-shadow: 0 1px 0 #4f6fe6;
transform: translateY(2px);
}
/* Optional: "checked" feeling after click */
button.checked {
background: #dff5e1;
border-color: #3a9b3a;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);
}
button.sampled {
background: #fff3d9;
border-color: #d9a441;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);
}
.card{
border:1px solid #dde3ff;
background:#f6f7ff;
border-radius:14px;
padding:1rem 1rem 0.95rem;
margin-top:12px;
}
.small{ font-size:0.95rem; color:#444; }
h1{ margin:0.2rem 0 0.25rem; font-size:2.1rem; }
h2{ margin-top:1.4rem; margin-bottom:0.4rem; font-size:1.55rem; }
p{ margin:0.35rem 0 0.7rem; line-height:1.55; }
.story-frame{
margin-top:1.4rem;
background:linear-gradient(180deg,#f9faff,#ffffff);
border:1px solid #dde3ff;
border-radius:18px;
padding:1.6rem 1.8rem 1.9rem;
box-shadow:0 10px 28px rgba(0,0,0,0.08);
}
.story-images{
display:grid;
grid-template-columns:repeat(3,1fr);
gap: 120px;
align-items:stretch;
}
.story-images img{
width:100%;
height: 300px;px;
object-fit: cover; /* fills box */
border-radius:14px;
border:1px solid #000;
display:block;
border: 5px solid #222;
.
}
@media (max-width:800px){
.story-images{ grid-template-columns:1fr; }
.story-images img{ height:240px; }
}
.topbar{
display:flex;
flex-wrap:wrap;
gap:10px;
align-items:center;
}
.topbar label{ margin-left:auto; }
.footer{
margin-top:2.2rem;
font-size:0.9rem;
color:#777;
text-align:left;
border-top:1px solid #eee;
padding-top:0.8rem;
}
.story-images figure {
margin: 0;
text-align: center;
}
.story-images figcaption {
margin-top: 0.6rem;
font-size: 0.95em;
color: #444;
}
</style>
</head>
<body>
<div class="wrap">
<div class="nav-row">
<a href="index.html"><button class="secondary">🧭 Hub</button></a>
<a href="adventure_1_home.html"><button class="secondary">🏠 Home</button></a>
<a href="adventure_1_activity_1_student.html"><button class="secondary">✅ Activity</button></a>
</div>
<div class="card">
<h2 style="margin-top:0">🔊 Listen to the story</h2>
<p class="small" style="margin-top:6px">Click <b>Read</b> to hear the story aloud. You can pause or stop at any time.</p>
<div class="topbar" style="margin:10px 0 0">
<button class="btn" id="readBtn" type="button">Read</button>
<button class="btn secondary" id="pauseBtn" type="button">Pause</button>
<button class="btn secondary" id="stopBtn" type="button">Stop</button>
<label class="small" style="display:flex;align-items:center;gap:8px">
Voice:
<select id="voiceSelect" style="padding:8px 10px;border-radius:10px;border:1px solid #bbb;font-size:1rem;min-width:220px">
<option value="">Loading voices…</option>
</select>
</label>
</div>
<div class="small" id="ttsMsg" style="margin-top:10px"></div>
</div>
<div class="story-frame">
<div class="story-images">
<figure>
<img src="images/adventure_1_story_image_1.png"
alt="Eratosthenes">
<figcaption><b>Eratosthenes teaching in Alexandria by Bernardo Strozzi (1635)</b>
</figcaption>
</figure>
<figure>
<img src="images/adventure_1_story_image_2.png"
alt="Grant Sanderson"
<figcaption>
<b>Measure of Earth's circumference, based on the approximation that Syene is on the Tropic of Cancer and on the same meridian as Alexandria</b>
</figcaption>
</figure>
<figure>
<img src="images/adventure_1_story_image_3.png"
alt="Eratosthenes’ Estimate of Earth’s Circumference">
<figcaption><b>Eratosthenes’ Estimate of Earth’s Circumference Student Worksheet</b>
</figcaption>
</figure>
</div>
<div id="storyText"><h1>Measuring the World by Slices and Sticks</h1>
<p>(Inspired by Bill Bryson’s chapter on early attempts to measure Earth)</p>
<p>Long before satellites and laser measuring tools, no one knew how big the Earth was. People guessed, argued, and made wildly different claims. Some thought the planet was enormous; others believed it was much smaller. What they all agreed on was this: the Earth was far too large to measure directly.
</p>
<p>Then came Eratosthenes. He lived more than two thousand years ago and worked in the Great Library of Alexandria — a place filled with scrolls, scholars, and a great deal of sunshine. Eratosthenes had learned something curious: in a southern city called Syene, the sun shone straight down a well on the summer solstice. At the very same moment in Alexandria, a vertical stick cast a small shadow.
</p>
<p>This tiny difference — the angle of a single shadow — was the clue.
</p>
<p>Eratosthenes realized he could “slice” the Earth using shadows the same way we slice area under a line: by taking a simple measurement and using it to understand something much bigger.
</p>
<p>He measured the angle of the shadow in Alexandria (about 7 degrees), knew the distance between the two cities, and reasoned: “If 7 degrees of curvature corresponds to this many miles, then the whole 360 degrees must correspond to… the entire Earth.”
</p>
<p>In other words, he used a small piece — one slice — to understand the whole curve of the planet.
</p>
<p>His method was astonishingly accurate, less than 2% error as compared to modern measurements.</p>
<div class="footer">Created by Dr. Super & Spark – Powered by ChatGPT</div>
</div>
<script>
(function(){
const readBtn = document.getElementById('readBtn');
const pauseBtn = document.getElementById('pauseBtn');
const stopBtn = document.getElementById('stopBtn');
const voiceSel = document.getElementById('voiceSelect');
const msgEl = document.getElementById('ttsMsg');
const storyEl = document.getElementById('storyText');
if(!('speechSynthesis' in window)){
msgEl.textContent = "Text-to-speech is not supported in this browser.";
readBtn.disabled = pauseBtn.disabled = stopBtn.disabled = true;
return;
}
let utter = null;
function pickThreeEnglish(voices){
const en = voices.filter(v => /^en(-|_)?/i.test(v.lang || "") || /english/i.test(v.name || ""));
en.sort((a,b) => (b.localService === true) - (a.localService === true));
const picked = [];
const seen = new Set();
for(const v of en){
const key = (v.name||"").toLowerCase();
if(seen.has(key)) continue;
picked.push(v); seen.add(key);
if(picked.length === 3) break;
}
return picked;
}
function loadVoices(){
const voices = window.speechSynthesis.getVoices();
const picked = pickThreeEnglish(voices);
voiceSel.innerHTML = "";
if(picked.length === 0){
voiceSel.innerHTML = "<option value=''>No English voices found</option>";
msgEl.textContent = "No English voices were found on this device. (Try Chrome or Edge.)";
return;
}
picked.forEach((v, idx) => {
const opt = document.createElement('option');
opt.value = v.name;
opt.textContent = `${v.name} (${v.lang})`;
voiceSel.appendChild(opt);
if(idx === 0) voiceSel.value = v.name;
});
msgEl.textContent = "";
}
loadVoices();
window.speechSynthesis.onvoiceschanged = loadVoices;
function buildUtterance(){
const text = (storyEl ? storyEl.innerText : '').trim();
if(!text){ msgEl.textContent = 'Could not find story text to read.'; return; }
utter = new SpeechSynthesisUtterance(text);
const voices = window.speechSynthesis.getVoices();
const chosenName = voiceSel.value;
const chosen = voices.find(v => v.name === chosenName);
if(chosen) utter.voice = chosen;
utter.rate = 1.0;
utter.pitch = 1.0;
utter.onend = () => {
readBtn.textContent = "Read";
};
utter.onerror = () => {
readBtn.textContent = "Read";
msgEl.textContent = "Could not play audio. Try another voice or refresh.";
};
}
function stop(){
window.speechSynthesis.cancel();
readBtn.textContent = "Read";
}
readBtn.addEventListener('click', () => {
msgEl.textContent = "";
stop();
buildUtterance();
window.speechSynthesis.speak(utter);
readBtn.textContent = "Reading…";
});
pauseBtn.addEventListener('click', () => {
if(window.speechSynthesis.speaking && !window.speechSynthesis.paused){
window.speechSynthesis.pause();
readBtn.textContent = "Read";
msgEl.textContent = "Paused. Click Pause again to resume.";
} else if(window.speechSynthesis.paused){
window.speechSynthesis.resume();
readBtn.textContent = "Reading…";
msgEl.textContent = "";
}
});
stopBtn.addEventListener('click', () => {
stop();
msgEl.textContent = "Stopped.";
});
voiceSel.addEventListener('change', () => {
if(window.speechSynthesis.speaking){
stop();
buildUtterance();
window.speechSynthesis.speak(utter);
readBtn.textContent = "Reading…";
msgEl.textContent = "";
}
});
})();
</script>
</body>
</html>