<!DOCTYPE html>
<html lang=”el”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>Μονάδες & Πυκνότητα — Διαδραστικό Εργαστήριο</title>
<link rel=”preconnect” href=”https://fonts.googleapis.com”>
<link rel=”preconnect” href=”https://fonts.gstatic.com” crossorigin>
<link href=”https://fonts.googleapis.com/css2?family=Alegreya:ital,wght@0,500;0,700;1,500;1,700&family=Commissioner:wght@400;500;600;700&display=swap” rel=”stylesheet”>
<style>
:root{
–paper:#f5f1e4; –paper2:#efe9d6; –card:#f9f6ec;
–ink:#28241a; –ink2:#6a6250;
–line:#d5ccb2; –red:#a63b2a; –teal:#2e6e62;
–ok:#2e7a4c; –bad:#b13a2c;
–mono:”SFMono-Regular”,Consolas,”Andale Mono”,Menlo,monospace;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:80px}
body{margin:0;background:var(–paper);color:var(–ink);font-family:’Commissioner’,sans-serif;font-size:16.5px;line-height:1.55}
.page{max-width:1120px;margin:0 auto;padding:0 26px 60px}
p{margin:.4em 0 1em}
strong{font-weight:700}
/* ———- κεφαλίδα ———- */
header.masthead{display:flex;justify-content:space-between;align-items:flex-start;gap:30px;padding:44px 0 0}
.kicker{font-size:12px;letter-spacing:.2em;text-transform:uppercase;font-weight:700;color:var(–red)}
h1{font-family:’Alegreya’,serif;font-weight:700;font-size:clamp(34px,5vw,50px);line-height:1.02;margin:8px 0 12px}
.sub{font-family:’Alegreya’,serif;font-style:italic;font-size:19px;color:var(–ink2);max-width:600px;margin:0}
.stampwrap{transform:rotate(-7deg);flex:0 0 auto}
.stamp{width:138px;height:138px;animation:spin 60s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
@media(max-width:700px){.stamp{width:92px;height:92px}}
/* ———- πλοήγηση ———- */
nav#topnav{position:sticky;top:0;z-index:40;display:flex;flex-wrap:wrap;gap:4px;padding:9px 0;margin-top:30px;
background:rgba(245,241,228,.95);backdrop-filter:blur(5px);border-top:1.5px solid var(–ink);border-bottom:1.5px solid var(–ink)}
nav#topnav a{display:inline-flex;align-items:center;gap:8px;text-decoration:none;color:var(–ink);font-size:13.5px;
font-weight:500;padding:5px 12px;border:1.5px solid transparent;border-radius:999px}
nav#topnav a .num{font-family:’Alegreya’,serif;font-weight:700;display:grid;place-items:center;width:24px;height:24px;
border:1.5px solid var(–ink);border-radius:50%;font-size:14px}
nav#topnav a:hover{border-color:var(–ink)}
nav#topnav a.current{background:var(–ink);color:var(–paper)}
nav#topnav a.current .num{border-color:var(–paper)}
/* ———- εισαγωγή ———- */
.intro{display:flex;gap:40px;align-items:center;justify-content:space-between;border-bottom:3px double var(–ink);padding:30px 0 26px;flex-wrap:wrap}
.intro-text{flex:1 1 420px;min-width:280px}
.big-formula{font-family:’Alegreya’,serif;font-style:italic;font-weight:700;font-size:46px;white-space:nowrap}
.frac{display:inline-flex;flex-direction:column;text-align:center;vertical-align:middle;line-height:1;margin:0 6px}
.frac>span:first-child{border-bottom:2.5px solid var(–ink);padding:0 10px 2px}
.frac>span:last-child{padding-top:2px}
.cap{font-size:13px;color:var(–ink2);letter-spacing:.05em;margin-top:6px}
/* ———- ενότητες ———- */
section{margin-top:62px;scroll-margin-top:86px}
.sec-head{display:flex;align-items:baseline;gap:16px;border-bottom:3px double var(–ink);padding-bottom:10px;margin-bottom:20px;flex-wrap:wrap}
.sec-num{font-family:’Alegreya’,serif;font-weight:700;font-size:34px;color:var(–red)}
.sec-title{font-family:’Alegreya’,serif;font-weight:700;font-size:25px}
.sec-lead{margin-left:auto;font-family:’Alegreya’,serif;font-style:italic;font-size:15px;color:var(–ink2);max-width:360px;text-align:right}
@media(max-width:860px){.sec-lead{display:none}}
.lead{font-family:’Alegreya’,serif;font-size:17.5px}
.split{display:flex;gap:34px;align-items:flex-start}
.split>.col{min-width:0}
.col.scene-col{flex:1.12}
.col.controls-col{flex:1}
@media(max-width:860px){.split{flex-direction:column}}
.scene{border:1.5px solid var(–ink);padding:8px;border-radius:4px;
background-color:var(–paper2);
background-image:linear-gradient(#e2dbc2 1px,transparent 1px),linear-gradient(90deg,#e2dbc2 1px,transparent 1px);
background-size:24px 24px}
.scene svg{width:100%;height:auto;display:block}
.caption{font-family:’Alegreya’,serif;font-style:italic;font-size:14px;color:var(–ink2);margin:8px 4px 0}
/* ———- κουμπιά / chips ———- */
.btn{font:inherit;font-weight:500;border:1.5px solid var(–ink);background:transparent;color:var(–ink);
padding:.52rem 1.1rem;border-radius:999px;cursor:pointer}
.btn:hover:not(:disabled){background:var(–ink);color:var(–paper)}
.btn:active:not(:disabled){transform:translateY(1px)}
.btn:disabled{opacity:.35;cursor:default}
.btn.small{padding:.35rem .8rem;font-size:14px}
.actions{display:flex;flex-wrap:wrap;gap:10px;margin:12px 0}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0 16px}
.chip{display:inline-flex;align-items:center;gap:8px;border:1.5px solid var(–ink);background:var(–card);
color:var(–ink);border-radius:8px;padding:6px 12px;cursor:pointer;font:inherit;font-size:14.5px}
.chip .sw{width:14px;height:14px;border:1.5px solid var(–ink);border-radius:3px;flex:0 0 auto}
.chip[aria-pressed=”true”]{background:var(–ink);color:var(–paper)}
.chip[aria-pressed=”true”] .sw{border-color:var(–paper)}
.chip.done{border-color:var(–ok);color:var(–ok);background:#eef3ea}
.msg{min-height:24px;margin:10px 0 0;font-size:15px;padding-left:12px;border-left:3px solid transparent}
.msg.ok{border-color:var(–ok);color:var(–ok)}
.msg.bad{border-color:var(–bad);color:var(–bad)}
/* ———- βήματα ———- */
.steps{display:flex;flex-wrap:wrap;gap:4px 8px;list-style:none;padding:0;margin:0 0 14px;font-size:14px;counter-reset:st}
.steps li{counter-increment:st;display:inline-flex;align-items:center}
.steps li::before{content:counter(st);font-family:’Alegreya’,serif;font-weight:700;color:var(–red);margin-right:6px;font-size:15px}
.steps li:not(:last-child)::after{content:’→’;margin:0 4px 0 10px;color:var(–ink2)}
/* ———- πίνακας τετραδίου ———- */
table.notebook{width:100%;border-collapse:collapse;font-size:14px;margin-top:16px}
table.notebook th{font-size:11.5px;letter-spacing:.05em;text-transform:uppercase;color:var(–ink2);text-align:left;
border-bottom:1.5px solid var(–ink);padding:6px 7px;font-weight:600}
table.notebook td{padding:7px;border-bottom:1px solid var(–line);font-family:var(–mono);font-size:13.5px;white-space:nowrap}
table.notebook td.name{font-family:’Commissioner’;font-weight:700}
table.notebook tr.active{background:#eee8d4}
#formulaLine{font-family:’Alegreya’,serif;font-size:18px;margin:14px 0 4px;min-height:26px}
/* ———- πεδία φόρμας ———- */
.field{margin:0 0 14px}
.field>label{display:block;font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;color:var(–ink2);font-weight:600;margin-bottom:5px}
select{font:inherit;padding:8px 10px;border:1.5px solid var(–ink);background:var(–card);border-radius:6px;width:100%}
select.ok{border-color:var(–ok);box-shadow:inset 0 0 0 1px var(–ok)}
select.bad{border-color:var(–bad);box-shadow:inset 0 0 0 1px var(–bad)}
.checks{display:flex;flex-direction:column;gap:1px}
.check{display:flex;align-items:center;gap:9px;padding:4px 6px;border-radius:5px;font-size:15px;cursor:pointer}
.check input{width:16px;height:16px;accent-color:var(–red);flex:0 0 auto}
.check.ok{color:var(–ok)} .check.bad{color:var(–bad)}
/* ———- σενάρια ———- */
.scenario{border:1.5px solid var(–ink);border-radius:10px;background:var(–card);padding:18px 22px;margin:14px 0}
.sc-name{font-family:’Alegreya’,serif;font-weight:700;font-size:19px;color:var(–red);margin-bottom:8px}
.sc-grid{display:grid;grid-template-columns:1.05fr 1fr;gap:26px}
.sc-text{font-family:’Alegreya’,serif;font-size:16.5px}
@media(max-width:860px){.sc-grid{grid-template-columns:1fr}}
.memo{border-left:3px solid var(–teal);padding:6px 18px;font-family:’Alegreya’,serif;font-size:16.5px;margin:14px 0 20px}
.memo span{font-weight:700;letter-spacing:.03em}
.progline{font-size:14px;color:var(–ink2);letter-spacing:.04em}
/* ———- διαγράμματα / θερμόμετρο ———- */
.chart{border:1.5px solid var(–ink);background:#faf7ec;padding:8px;border-radius:4px}
.chart svg{width:100%;height:auto;display:block}
.chart-cap{font-family:’Alegreya’,serif;font-style:italic;font-size:14px;color:var(–ink2);margin:8px 4px 14px}
.readouts{margin-top:14px}
.readouts .row{display:flex;justify-content:space-between;align-items:baseline;border-bottom:1px solid var(–line);padding:7px 2px}
.readouts .lbl{font-size:12px;letter-spacing:.07em;text-transform:uppercase;color:var(–ink2)}
.readouts .val{font-family:var(–mono);font-size:18px}
.sliderRow{display:flex;align-items:center;gap:12px;margin:16px 0 8px}
.sliderRow input[type=range]{flex:1;accent-color:var(–red)}
.sliderRow .tval{font-family:var(–mono);font-size:19px;min-width:78px;text-align:right}
.dashlist{list-style:none;padding:0;margin:6px 0 0;font-family:’Alegreya’,serif;font-size:16.5px}
.dashlist li{position:relative;padding:4px 0 4px 24px}
.dashlist li::before{content:”;position:absolute;left:0;top:1.05em;width:12px;height:2.5px;background:var(–red)}
/* ———- παρατηρήσεις δοχείου ———- */
#obsLog{list-style:none;padding:0;margin:10px 0 0;font-size:15px}
#obsLog li{display:flex;align-items:baseline;gap:9px;padding:6px 0;border-bottom:1px solid var(–line)}
#obsLog li .sw{width:13px;height:13px;border:1.5px solid var(–ink);border-radius:3px;flex:0 0 auto;align-self:center}
#obsLog li.empty{border:none;color:var(–ink2);font-style:italic;font-family:’Alegreya’,serif}
.rho{font-family:var(–mono);font-size:12.5px;color:var(–ink2)}
.concept{border:1.5px solid var(–teal);background:#e7efea;padding:14px 18px;border-radius:6px;
font-family:’Alegreya’,serif;font-size:16px;margin-top:18px}
.hint{font-family:’Alegreya’,serif;font-style:italic;font-size:15px;color:var(–ink2);margin-top:10px}
/* ———- quiz ———- */
.q{border:1.5px solid var(–ink);border-radius:10px;padding:16px 20px;margin:14px 0;background:var(–card)}
.q-head{display:flex;gap:12px;margin-bottom:8px}
.q-num{font-family:’Alegreya’,serif;font-weight:700;font-size:20px;color:var(–red)}
.q-text{font-family:’Alegreya’,serif;font-weight:700;font-size:17.5px}
.opts{display:flex;flex-direction:column;gap:2px;margin:4px 0 10px}
.opt{display:flex;gap:10px;align-items:baseline;padding:6px 8px;border-radius:6px;cursor:pointer;font-size:15.5px}
.opt:hover{background:#ede7d3}
.opt input{accent-color:var(–red);width:16px;height:16px;flex:0 0 auto;align-self:center}
.opt.mark-ok{background:#e2ecdf;color:var(–ok);font-weight:600}
.opt.mark-bad{background:#f0ddd6;color:var(–bad)}
.why{display:none;margin-top:10px;font-family:’Alegreya’,serif;font-style:italic;font-size:15.5px;color:var(–ink2);
border-left:3px solid var(–teal);padding-left:12px}
.q.done .why{display:block}
.scorebar{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
border-bottom:1.5px solid var(–ink);padding-bottom:10px;margin-bottom:6px}
#scoreTxt{font-family:var(–mono);font-size:16px}
.praise{border:2px solid var(–ok);color:var(–ok);border-radius:8px;padding:12px 16px;margin-top:12px;
font-family:’Alegreya’,serif;font-size:16.5px}
.praise[hidden]{display:none}
footer{margin-top:74px;border-top:3px double var(–ink);padding-top:16px;font-size:13.5px;color:var(–ink2)}
/* svg γενικά */
svg text{font-family:’Commissioner’,sans-serif}
svg .mono{font-family:var(–mono)}
</style>
</head>
<body>
<div class=”page”>
<header class=”masthead”>
<div>
<div class=”kicker”>Εργαστηριακό φύλλο · Διαδραστικό</div>
<h1>Μονάδες & Πυκνότητα</h1>
<p class=”sub”>Ζύγισε, μέτρησε, συμπέρανε — πέντε δραστηριότητες για την κατανόηση του κεφαλαίου, με ζυγό, κύλινδρο, θερμόμετρο και ένα δοχείο γεμάτο υγρά.</p>
</div>
<div class=”stampwrap” aria-hidden=”true”>
<svg class=”stamp” viewBox=”0 0 160 160″>
<defs><path id=”stc” d=”M80,80 m-57,0 a57,57 0 1,1 114,0 a57,57 0 1,1 -114,0″/></defs>
<circle cx=”80″ cy=”80″ r=”75″ fill=”none” stroke=”#a63b2a” stroke-width=”2.5″/>
<circle cx=”80″ cy=”80″ r=”46″ fill=”none” stroke=”#a63b2a” stroke-width=”1.2″/>
<text font-size=”11.5″ style=”letter-spacing:1.8px” fill=”#a63b2a” font-weight=”600″>
<textPath href=”#stc”>ΔΙΑΔΡΑΣΤΙΚΟ ΕΡΓΑΣΤΗΡΙΟ • ΧΗΜΕΙΑ Α΄ ΛΥΚΕΙΟΥ •</textPath>
</text>
<text x=”80″ y=”77″ text-anchor=”middle” font-family=”Alegreya,serif” font-style=”italic” font-weight=”700″ font-size=”22″ fill=”#a63b2a”>ρ = m/V</text>
<text x=”80″ y=”96″ text-anchor=”middle” font-size=”9.5″ style=”letter-spacing:1.5px” fill=”#a63b2a”>ΜΟΝΑΔΕΣ & ΠΥΚΝΟΤΗΤΑ</text>
</svg>
</div>
</header>
<nav id=”topnav” aria-label=”Ενοτήτες”>
<a href=”#method”><span class=”num”>Α</span>Η μέθοδος</a>
<a href=”#lab”><span class=”num”>Β</span>Εργαστήριο πυκνότητας</a>
<a href=”#temp”><span class=”num”>Γ</span>Θερμοκρασία</a>
<a href=”#float”><span class=”num”>Δ</span>Επιπλέει — βυθίζεται</a>
<a href=”#quiz”><span class=”num”>Ε</span>Αυτοέλεγχος</a>
</nav>
<div class=”intro”>
<div class=”intro-text”>
<p class=”lead”>Εδώ δεν διαβάζεις τη Χημεία — την <strong>κάνεις</strong>. Σχεδιάζεις πειράματα σαν ερευνητής και χειρίζεσαι τα σκεύη του εργαστηρίου, για να καταλάβεις τι ακριβώς μετράμε όταν μιλάμε για <em>μάζα</em>, <em>όγκο</em> και <em>πυκνότητα</em>. Στο τέλος, δοκιμάζεις τις γνώσεις σου σε ερωτήσεις του ίδιου του φύλλου.</p>
</div>
<div>
<div class=”big-formula”>ρ = <span class=”frac”><span>m</span><span>V</span></span></div>
<div class=”cap”>πυκνότητα = μάζα ÷ όγκο · μονάδες: g/mL, kg/m³</div>
</div>
</div>
<main>
<!– ============ Α΄ ΕΠΙΣΤΗΜΟΝΙΚΗ ΜΕΘΟΔΟΣ ============ –>
<section id=”method”>
<div class=”sec-head”>
<span class=”sec-num”>Α΄</span>
<span class=”sec-title”>Ποια μεταβλητή αλλάζω, ποια μετρώ;</span>
<span class=”sec-lead”>Πριν από κάθε πείραμα: ανεξάρτητη, εξαρτημένη, σταθερές.</span>
</div>
<div class=”memo”>
<div><span>Ανεξάρτητη</span> — η μεταβλητή που ο ερευνητής <em>αλλάζει σκόπιμα</em>.</div>
<div><span>Εξαρτημένη</span> — η μεταβλητή που <em>μετράμε</em>· «ακούει» την ανεξάρτητη.</div>
<div><span>Σταθερές</span> — ό,τι <em>κρατάμε αυτούσιο</em>, για να μη μπερδέψουμε τα αποτελέσματα.</div>
</div>
<p class=”progline” id=”scProg”>Λυμένα σενάρια: 0 / 3</p>
<div id=”scenBox”></div>
</section>
<!– ============ Β΄ ΕΡΓΑΣΤΗΡΙΟ ΠΥΚΝΟΤΗΤΑΣ ============ –>
<section id=”lab”>
<div class=”sec-head”>
<span class=”sec-num”>Β΄</span>
<span class=”sec-title”>Μέτρηση πυκνότητας στερεού στο εργαστήριο</span>
<span class=”sec-lead”>Ζυγός ακριβείας 0,01 g · ογκομετρικός κύλινδρος 100 mL.</span>
</div>
<p class=”lead”>Στον πάγκο υπάρχει ένας ηλεκτρονικός ζυγός και ένας ογκομετρικός κύλινδρος με <strong>50 mL νερού</strong>. Θα μετρήσεις μάζα και όγκο για πέντε άγνωστα δείγματα, θα υπολογίσεις <em>ρ = m/V</em> και θα τα ταυτοποιήσεις. Πρόσεξε: ένα από αυτά κρύβει έκπληξη…</p>
<div class=”chips” id=”sampleChips” aria-label=”Επιλογή δείγματος”></div>
<div class=”split”>
<div class=”col scene-col”>
<div class=”scene”>
<svg id=”benchSvg” viewBox=”0 0 660 440″ role=”img” aria-label=”Πάγκος εργαστηρίου με ζυγό και ογκομετρικό κύλινδρο”>
<!– τραπέζι –>
<rect x=”0″ y=”380″ width=”660″ height=”60″ fill=”#e3d9bd” stroke=”#28241a” stroke-width=”2″/>
<line x1=”0″ y1=”380″ x2=”660″ y2=”380″ stroke=”#28241a” stroke-width=”2.5″/>
<text x=”150″ y=”404″ text-anchor=”middle” font-size=”10″ style=”letter-spacing:1.5px” fill=”#6a6250″>ΗΛΕΚΤΡΟΝΙΚΟΣ ΖΥΓΟΣ</text>
<text x=”470″ y=”404″ text-anchor=”middle” font-size=”10″ style=”letter-spacing:1.5px” fill=”#6a6250″>ΟΓΚΟΜΕΤΡΙΚΟΣ ΚΥΛΙΝΔΡΟΣ · 100 mL</text>
<!– ζυγός –>
<rect x=”140″ y=”212″ width=”22″ height=”140″ fill=”#eae3cd” stroke=”#28241a” stroke-width=”2″/>
<polygon points=”112,214 190,214 176,200 126,200″ fill=”#eae3cd” stroke=”#28241a” stroke-width=”2″/>
<ellipse cx=”150″ cy=”198″ rx=”82″ ry=”9″ fill=”#f2ecd9″ stroke=”#28241a” stroke-width=”2.5″/>
<rect x=”70″ y=”352″ width=”180″ height=”28″ rx=”5″ fill=”#eae3cd” stroke=”#28241a” stroke-width=”2″/>
<rect x=”95″ y=”357″ width=”98″ height=”18″ rx=”2″ fill=”#232019″/>
<text id=”lcdTxt” class=”mono” x=”144″ y=”371″ text-anchor=”middle” font-size=”13″ fill=”#d7e4b9″ style=”letter-spacing:1px”>0,00 g</text>
<circle cx=”212″ cy=”366″ r=”4″ fill=”#a63b2a” stroke=”#28241a” stroke-width=”1.5″/>
<!– κύλινδρος –>
<rect x=”410″ y=”372″ width=”120″ height=”8″ fill=”#eae3cd” stroke=”#28241a” stroke-width=”2″/>
<path d=”M425,64 L425,372 L515,372 L515,64″ fill=”none” stroke=”#28241a” stroke-width=”2.5″/>
<g id=”cylTicks”></g>
<g id=”sampleG”></g>
<path id=”waterShape” d=”” fill=”#c9ddd6″ fill-opacity=”0.72″/>
<g id=”bubbles”></g>
<line id=”levelGuide” x1=”425″ x2=”515″ y1=”222″ y2=”222″ stroke=”#a63b2a” stroke-width=”1″ stroke-dasharray=”4 4″ opacity=”0.85″/>
<text id=”levelTag” class=”mono” x=”421″ y=”231″ text-anchor=”end” font-size=”12″ fill=”#a63b2a”>50,0</text>
</svg>
</div>
<p class=”caption”>Τη στάθμη τη διαβάζουμε στο <strong>χαμηλότερο σημείο του μενίσκου</strong> — εκεί δείχνει και η διακεκομμένη γραμμή.</p>
</div>
<div class=”col controls-col”>
<ol class=”steps”>
<li>Επίλεξε δείγμα</li><li>Ζύγισέ το</li><li>Βύθισέ το και διάβασε τη στάθμη</li><li>Υπολόγισε ρ = m/V</li><li>Ταυτοποίησέ το</li>
</ol>
<div class=”actions”>
<button class=”btn” id=”btnWeigh”>Ζύγισε το δείγμα</button>
<button class=”btn” id=”btnSub”>Βύθισε στον κύλινδρο</button>
<button class=”btn” id=”btnBench”>Επαναφορά στον πάγκο</button>
</div>
<div id=”formulaLine”></div>
<div class=”field”>
<label for=”matSel”>Τι υλικό είναι το δείγμα;</label>
<select id=”matSel”>
<option value=””>— διάλεξε υλικό —</option>
<option value=”0″>Αλουμίνιο (2,70 g/mL)</option>
<option value=”1″>Σίδηρος (7,87 g/mL)</option>
<option value=”2″>Χαλκός (8,96 g/mL)</option>
<option value=”3″>Χρυσός (19,3 g/mL)</option>
<option value=”4″>Άργυρος (10,5 g/mL)</option>
<option value=”5″>Καμία τιμή δεν ταιριάζει…</option>
</select>
</div>
<div class=”actions” style=”margin-top:0″>
<button class=”btn” id=”btnId”>Έλεγχος ταυτοποίησης</button>
<span class=”progline” id=”solvedTxt”>Ταυτοποιήθηκαν 0 / 5</span>
</div>
<div class=”msg” id=”labMsg” aria-live=”polite”></div>
<p class=”praise” id=”finalPraise” hidden>Συγχαρητήρια — και τα πέντε δείγματα λύθηκαν. Απέδειξες πειραματικά ότι η πυκνότητα είναι <strong>ιδιότητα του υλικού</strong> (ίδια όσο κι αν αλλάζει μάζα/όγκος) και ότι μια «περίεργη» τιμή μπορεί να μαρτυρά <strong>κοιλότητα</strong> μέσα στο σώμα.</p>
<table class=”notebook”>
<thead>
<tr><th>Δείγμα</th><th>m (g)</th><th>V<sub>αρχ.</sub> (mL)</th><th>V<sub>τελ.</sub> (mL)</th><th>V = V<sub>τελ.</sub>−V<sub>αρχ.</sub></th><th>ρ = m/V</th><th>Ταυτοποίηση</th></tr>
</thead>
<tbody id=”nbBody”>
<tr id=”nbRowΔ1″><td class=”name”>Δ1</td><td>—</td><td>50,0</td><td>—</td><td>—</td><td>—</td><td>—</td></tr>
<tr id=”nbRowΔ2″><td class=”name”>Δ2</td><td>—</td><td>50,0</td><td>—</td><td>—</td><td>—</td><td>—</td></tr>
<tr id=”nbRowΔ3″><td class=”name”>Δ3</td><td>—</td><td>50,0</td><td>—</td><td>—</td><td>—</td><td>—</td></tr>
<tr id=”nbRowΔ4″><td class=”name”>Δ4</td><td>—</td><td>50,0</td><td>—</td><td>—</td><td>—</td><td>—</td></tr>
<tr id=”nbRowΔ5″><td class=”name”>Δ5</td><td>—</td><td>50,0</td><td>—</td><td>—</td><td>—</td><td>—</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!– ============ Γ΄ ΘΕΡΜΟΚΡΑΣΙΑ ============ –>
<section id=”temp”>
<div class=”sec-head”>
<span class=”sec-num”>Γ΄</span>
<span class=”sec-title”>Πυκνότητα & θερμοκρασία: η ανωμαλία του νερού</span>
<span class=”sec-lead”>Όσο ζεσταίνεται ένα υγρό, «αδυνατίζει» — εκτός από το νερό, που χαλάει τον κανόνα.</span>
</div>
<div class=”split”>
<div class=”col” style=”flex:0 0 250px”>
<div class=”scene” style=”padding:10px”>
<svg id=”thermoSvg” viewBox=”0 0 130 330″ role=”img” aria-label=”Θερμόμετρο”>
<rect x=”55″ y=”24″ width=”18″ height=”256″ rx=”9″ fill=”#fdfaf1″ stroke=”#28241a” stroke-width=”2.5″/>
<circle cx=”64″ cy=”298″ r=”17″ fill=”#b13a2c” stroke=”#28241a” stroke-width=”2.5″/>
<rect id=”merc” x=”59″ y=”268″ width=”10″ height=”28″ fill=”#b13a2c”/>
<g id=”thermoTicks”></g>
<text x=”64″ y=”14″ text-anchor=”middle” font-size=”11″ fill=”#6a6250″>°C</text>
</svg>
</div>
<div class=”sliderRow”>
<label for=”tSlider” style=”font-size:20px”>θ</label>
<input type=”range” id=”tSlider” min=”0″ max=”30″ step=”0.5″ value=”15″>
<span class=”tval” id=”tVal”>15,0 °C</span>
</div>
<button class=”btn” id=”sweepBtn” style=”width:100%”>Σάρωση 0 → 30 °C</button>
<div class=”readouts”>
<div class=”row”><span class=”lbl”>Θερμοκρασία θ</span><span class=”val” id=”rTheta”>—</span></div>
<div class=”row”><span class=”lbl”>ρ νερού</span><span class=”val” id=”rRhoW”>—</span></div>
<div class=”row”><span class=”lbl”>Όγκος 1 kg νερού</span><span class=”val” id=”rVolW”>—</span></div>
<div class=”row”><span class=”lbl”>ρ οινοπνεύματος</span><span class=”val” id=”rRhoE”>—</span></div>
<div class=”row”><span class=”lbl”>Όγκος 1 kg οινοπνεύματος</span><span class=”val” id=”rVolE”>—</span></div>
</div>
</div>
<div class=”col”>
<div class=”chart”><svg id=”chartWide” viewBox=”0 0 470 330″></svg></div>
<p class=”chart-cap”>Πυκνότητα νερού και οινοπνεύματος σε συνάρτηση με τη θερμοκρασία (0–30 °C, 1 atm).</p>
<div class=”chart”><svg id=”chartZoom” viewBox=”0 0 330 250″></svg></div>
<p class=”chart-cap”>Σε μεγέθυνση (0–12 °C): η «ανωμαλία» του νερού — η πυκνότητα κορυφώνεται περίπου στους 4 °C.</p>
<ul class=”dashlist”>
<li>Σε σταθερή πίεση, όταν η θερμοκρασία ανεβαίνει τα υγρά <strong>διαστέλλονται</strong>, άρα η πυκνότητά τους <strong>ελαττώνεται</strong> — βλέπεις την ευθεία του οινοπνεύματος.</li>
<li>Το νερό από 0 έως 4 °C συνεχίζει να <strong>συστέλλεται</strong>: ο όγκος μικραίνει, η πυκνότητα μεγαλώνει και φτάνει μέγιστη τιμή στους ≈4 °C. Έπειτα συμπεριφέρεται «κανονικά».</li>
<li>Γι’ αυτό ο πάγος (ρ ≈ 0,92 g/mL) είναι ελαφρύτερος από το υγρό νερό και επιπλέει — και οι λίμνες παγώνουν από την επιφάνεια.</li>
<li>Στα <strong>αέρια</strong> η πυκνότητα εξαρτάται και από την <strong>πίεση</strong>· στα υγρά και τα στερεά η πίεση σχεδόν δεν τις αλλάζει.</li>
</ul>
</div>
</div>
</section>
<!– ============ Δ΄ ΕΠΙΠΛΕΕΙ — ΒΥΘΙΖΕΤΑΙ ============ –>
<section id=”float”>
<div class=”sec-head”>
<span class=”sec-num”>Δ΄</span>
<span class=”sec-title”>Επιπλέει ή βυθίζεται; Στρωμάτωση υγρών</span>
<span class=”sec-lead”>Κάθε υγρό ψάχνει τη θέση του· κάθε σώμα, το πρώτο υγρό πυκνότερό του.</span>
</div>
<div class=”split”>
<div class=”col scene-col”>
<div class=”scene”>
<svg id=”beakerSvg” viewBox=”0 0 470 458″ role=”img” aria-label=”Δοχείο με στρώματα υγρών και σώματα”>
<defs><clipPath id=”bkClip”><path d=”M74,40 L74,412 Q74,424 86,424 L284,424 Q296,424 296,412 L296,40 Z”/></clipPath></defs>
<rect x=”0″ y=”428″ width=”470″ height=”30″ fill=”#e3d9bd” stroke=”#28241a” stroke-width=”2″/>
<g id=”strata” clip-path=”url(#bkClip)”></g>
<g id=”bodyG”></g>
<g id=”strataLabels”></g>
<path d=”M70,36 L70,412 Q70,428 86,428 L284,428 Q300,428 300,412 L300,36″ fill=”none” stroke=”#28241a” stroke-width=”3″/>
<path d=”M70,36 L58,24″ fill=”none” stroke=”#28241a” stroke-width=”3″/>
<text id=”emptyHint” x=”185″ y=”238″ text-anchor=”middle” font-size=”14.5″ fill=”#6a6250″ style=”font-style:italic”>πρόσθεσε υγρά…</text>
</svg>
</div>
</div>
<div class=”col controls-col”>
<div class=”field”><label>Υγρά — πρόσθεσέ τα ή αφαίρεσέ τα</label><div class=”chips” id=”liqChips”></div></div>
<div class=”field”><label>Σώματα — ρίξε τα στο δοχείο</label><div class=”chips” id=”bodBtns”></div></div>
<div class=”actions”><button class=”btn” id=”btnEmpty”>Άδειασμα δοχείου</button></div>
<div class=”msg” id=”beakerMsg” aria-live=”polite”></div>
<ul id=”obsLog”></ul>
<div class=”concept”>Ο κανόνας: αν <strong>ρ<sub>σώματος</sub> < ρ<sub>υγρού</sub></strong> το σώμα επιπλέει· αν είναι μεγαλύτερη βυθίζεται· αν είναι ίση, αιωρείται. Στο δοχείο τα υ格拉οτά τακτοποιούνται με την πυκνότητα (πυκνότερα πάντα κάτω), και κάθε σώμα βουτά μέχρι να συναντήσει το πρώτο υγρό πυκνότερο από το ίδιο.</div>
<p class=”hint”>Ιδέα πειράματος: βάλε ηλιέλαιο + νερό και ρίξε πάγο — πού θα σταματήσει; Μετά πρόσθεσε μέλι και ξαναδώ τι θα αλλάξει…</p>
</div>
</div>
</section>
<!– ============ Ε΄ ΑΥΤΟΕΛΕΓΧΟΣ ============ –>
<section id=”quiz”>
<div class=”sec-head”>
<span class=”sec-num”>Ε΄</span>
<span class=”sec-title”>Αυτοέλεγχος: ερωτήσεις από το φύλλο</span>
<span class=”sec-lead”>Ό,τι εξασκήθηκες, τώρα το αποδεικνύεις.</span>
</div>
<div class=”scorebar”>
<span id=”scoreTxt”>Σωστές απαντήσεις: 0 / 8</span>
<button class=”btn small” id=”btnQuizReset”>Ξαναξεκίνα</button>
</div>
<div id=”quizBox”></div>
</section>
</main>
<footer>
Συνοδευτικό διδακτικό υλικό για το κεφάλαιο «Μονάδες — Πυκνότητα» (Χημεία Α΄ Λυκείου). Όλες οι προσομοιώσεις εκτελούνται τοπικά στον φυλλομετρητή — κανένα δεδομένο δεν αποστέλλεται πουθενά.
</footer>
</div>
<script>
(function(){
‘use strict’;
/* ———- helpers ———- */
const $ = s => document.querySelector(s);
const fmt = (x,d=2) => x.toFixed(d).replace(‘.’,’,’);
const wait = ms => new Promise(r=>setTimeout(r,ms));
const el = (t,c,h) => { const e=document.createElement(t); if(c) e.className=c; if(h!=null) e.innerHTML=h; return e; };
const SVGNS = ‘http://www.w3.org/2000/svg’;
function svgEl(tag, attrs, parent){ const e=document.createElementNS(SVGNS,tag); for(const k in attrs) e.setAttribute(k,attrs[k]); if(parent) parent.appendChild(e); return e; }
function tween(dur, step, done, ease){
let cancelled=false; const t0=performance.now(); const ez = ease || (k=>1-Math.pow(1-k,3));
function f(now){ if(cancelled) return; const k=Math.min(1,(now-t0)/dur); step(ez(k)); if(k<1) requestAnimationFrame(f); else if(done) done(); }
requestAnimationFrame(f); return { cancel(){ cancelled=true; } };
}
const ICHECK='<svg viewBox=”0 0 16 16″ width=”12″ height=”12″ aria-hidden=”true” style=”vertical-align:-1px”><path d=”M2.5 8.5 6.2 12.2 13.5 4.2″ fill=”none” stroke=”currentColor” stroke-width=”2.6″ stroke-linecap=”round” stroke-linejoin=”round”/></svg>’;
const IARROW='<svg viewBox=”0 0 16 16″ width=”11″ height=”11″ aria-hidden=”true” style=”vertical-align:-1px;margin-right:2px”><path d=”M8 2v9M4.5 8 8 11.5 11.5 8″ fill=”none” stroke=”currentColor” stroke-width=”2″ stroke-linecap=”round” stroke-linejoin=”round”/></svg>’;
/* =========================================================
Α΄ — Σενάρια επιστημονικής μεθόδου
========================================================= */
const SCEN = [
{ name:’Σενάριο 1 · Η ζάχαρη’,
text:’Ο Γιάννης και η Ελπίδα θέλουν να μάθουν αν η θερμοκρασία του νερού επηρεάζει την ποσότητα της ζάχαρης που διαλύεται σε αυτό. Χρησιμοποιούν τέσσερα πανομοιότυπα ποτήρια με 50 mL νερό, σε θερμοκρασίες 2, 25, 50 και 75 °C, με σταθερό ρυθμό ανάδευσης, και μετρούν πόση ζάχαρη διαλύεται πλήρως σε κάθε ποτήρι.’,
indOpts:[‘Η θερμοκρασία του νερού’,’Η ποσότητα του νερού (50 mL)’,’Η ποσότητα της ζάχαρης που διαλύεται’,’Ο αριθμός των ποτηριών’], ind:0,
depOpts:[‘Η ποσότητα του νερού’,’Η ποσότητα της ζάχαρης που διαλύεται’,’Η θερμοκρασία του νερού’,’Ο ρυθμός ανάδευσης’], dep:1,
consts:[‘Η ποσότητα του νερού (50 mL)’,’Ο ρυθμός της ανάδευσης’,’Η θερμοκρασία του νερού’,’Η ποσότητα της ζάχαρης’], constsOk:[1,1,0,0],
why:’Η θερμοκρασία είναι αυτή που αλλάζει σκόπιμα ο ερευνητής (ανεξάρτητη), η διαλυμένη ζάχαρη αυτή που μετριέται (εξαρτημένη), ενώ το νερό των 50 mL και η ανάδευση κρατιούνται ίδια (σταθερές).’ },
{ name:’Σενάριο 2 · Το λίπασμα’,
text:’Ένας χημικός δοκιμάζει την αποτελεσματικότητα ενός νέου υγρού λιπάσματος. Πέντε χωράφια με το ίδιο χώμα, το ίδιο μέγεθος και την ίδια ηλιακή ακτινοβολία λαμβάνουν διαφορετική ποσότητα λιπάσματος. Έναν μήνα αργότερα μετριέται το μέσο ύψος του γρασιδιού σε κάθε χωράφι.’,
indOpts:[‘Η ποσότητα του λιπάσματος’,’Το μέσο ύψος του γρασιδιού’,’Το είδος του χώματος’,’Η ηλιακή ακτινοβολία’], ind:0,
depOpts:[‘Η ποσότητα του λιπάσματος’,’Το είδος του χώματος’,’Το μέσο ύψος του γρασιδιού’,’Ο αριθμός των χωραφιών’], dep:2,
consts:[‘Το είδος του χώματος’,’Το μέγεθος των χωραφιών’,’Η ηλιακή ακτινοβολία’,’Η ποσότητα του λιπάσματος’,’Το μέσο ύψος του γρασιδιού’], constsOk:[1,1,1,0,0],
why:’Η ποσότητα λιπάσματος μεταβάλλεται σκόπιμα (ανεξάρτητη), το ύψος του γρασιδιού μετριέται (εξαρτημένη), ενώ χώμα, μέγεθος και ήλιος μένουν σταθερά.’ },
{ name:’Σενάριο 3 · Το χλωρίδιο του αμμωνίου’,
text:’Θέλουμε να ελέγξουμε την υπόθεση ότι «όσο περισσότερο στερεό NH₄Cl διαλύεται στο νερό, τόσο περισσότερο μειώνεται η θερμοκρασία του υγρού». Σε πανομοιότυπα ποτήρια με την ίδια ποσότητα νερού διαλύονται διαφορετικές ποσότητες NH₄Cl, με την ίδια ταχύτητα ανάδευσης, και μετράμε τη θερμοκρασία πριν και μετά τη διάλυση.’,
indOpts:[‘Η ποσότητα του NH₄Cl που διαλύεται’,’Η μεταβολή της θερμοκρασίας’,’Η ποσότητα του νερού’,’Η ταχύτητα της ανάδευσης’], ind:0,
depOpts:[‘Η αρχική θερμοκρασία του νερού’,’Η ποσότητα του NH₄Cl’,’Η μεταβολή της θερμοκρασίας του υγρού’,’Ο όγκος του νερού’], dep:2,
consts:[‘Η ποσότητα του νερού’,’Η ταχύτητα της ανάδευσης’,’Η αρχική θερμοκρασία του νερού’,’Η ποσότητα του NH₄Cl’], constsOk:[1,1,1,0],
why:’Προσθέτουμε σκόπιμα περισσότερο NH₄Cl (ανεξάρτητη) και παρακολουθούμε τη μεταβολή της θερμοκρασίας (εξαρτημένη)· νερό, ανάδευση και αρχική θερμοκρασία μένουν ίδιες.’ },
];
const scSolved = new Set();
SCEN.forEach((sc,i)=>{
const box = el(‘div’,’scenario’);
box.innerHTML = `
<div class=”sc-name”>${sc.name}</div>
<div class=”sc-grid”>
<div class=”sc-text”>${sc.text}</div>
<div class=”sc-fields”>
<div class=”field”><label>Ανεξάρτητη — αυτή που αλλάζω σκόπιμα</label>
<select class=”indSel”>${sc.indOpts.map((o,j)=>`<option value=”${j}”>${o}</option>`).join(”)}</select></div>
<div class=”field”><label>Εξαρτημένη — αυτή που μετράω</label>
<select class=”depSel”>${sc.depOpts.map((o,j)=>`<option value=”${j}”>${o}</option>`).join(”)}</select></div>
<div class=”field”><label>Σταθερές — όσες πρέπει να μείνουν ίδιες (διάλεξε όλες όσες πιστεύεις)</label>
<div class=”checks”>${sc.consts.map((c,j)=>`<label class=”check”><input type=”checkbox” data-j=”${j}”><span>${c}</span></label>`).join(”)}</div></div>
<div class=”actions” style=”margin-top:4px”><button class=”btn small”>Έλεγχος σεναρίου</button></div>
<div class=”msg” aria-live=”polite”></div>
</div>
</div>`;
$(‘#scenBox’).appendChild(box);
const indSel=box.querySelector(‘.indSel’), depSel=box.querySelector(‘.depSel’),
checks=[…box.querySelectorAll(‘.check input’)], msg=box.querySelector(‘.msg’);
[indSel,depSel,…checks].forEach(x=>x.addEventListener(‘change’,()=>{
indSel.classList.remove(‘ok’,’bad’); depSel.classList.remove(‘ok’,’bad’);
checks.forEach(c=>c.closest(‘.check’).classList.remove(‘ok’,’bad’));
msg.className=’msg’; msg.textContent=”;
}));
box.querySelector(‘button’).addEventListener(‘click’,()=>{
let all = true;
const mark=(sel,good)=>{ sel.classList.toggle(‘ok’,good); sel.classList.toggle(‘bad’,!good); if(!good) all=false; };
mark(indSel, +indSel.value===sc.ind);
mark(depSel, +depSel.value===sc.dep);
checks.forEach(cb=>{
const j=+cb.dataset.j, good = (cb.checked === !!sc.constsOk[j]);
cb.closest(‘.check’).classList.toggle(‘ok’, good);
cb.closest(‘.check’).classList.toggle(‘bad’, !good);
if(!good) all=false;
});
if(all){
scSolved.add(i);
msg.className=’msg ok’; msg.innerHTML='<strong>Σωστά!</strong> ‘+sc.why;
$(‘#scProg’).textContent = `Λυμένα σενάρια: ${scSolved.size} / 3`;
} else {
msg.className=’msg bad’; msg.textContent=’Υπάρχει τουλάχιστον ένα λάθος — κοίτα τις επισημάνσεις και δοκίμα ξανά.’;
}
});
});
/* =========================================================
Β΄ — Εικονικό εργαστήριο: ζυγός + ογκομετρικός κύλινδρος
========================================================= */
const SAMPLES=[
{id:’Δ1′, m:32.40, V:12.0, size:36, color:’#c9ced5′, truth:0, ans:’Αλουμίνιο’,
okMsg:’Σωστά! 32,40 g ÷ 12,0 mL = <strong>2,70 g/mL</strong> ⇒ αλουμίνιο.’},
{id:’Δ2′, m:78.70, V:10.0, size:32, color:’#4a4f57′, dark:true, truth:1, ans:’Σίδηρος’,
okMsg:’Σωστά! 78,70 g ÷ 10,0 mL = <strong>7,87 g/mL</strong> ⇒ σίδηρος.’},
{id:’Δ3′, m:89.60, V:10.0, size:32, color:’#bd7554′, truth:2, ans:’Χαλκός’,
okMsg:’Σωστά! 89,60 g ÷ 10,0 mL = <strong>8,96 g/mL</strong> ⇒ χαλκός. Πρόσεξε: <em>ίδιος όγκος</em> με το Δ2, αλλά πολύ μεγαλύτερη μάζα!’},
{id:’Δ4′, m:77.20, V:4.0, size:24, color:’#cfa233′, truth:3, ans:’Χρυσός’,
okMsg:’Σωστά! 77,20 g ÷ 4,0 mL = <strong>19,30 g/mL</strong> ⇒ χρυσός. Μικρός όγκος, μεγάλη μάζα — αυτό σημαίνει μεγάλη πυκνότητα.’},
{id:’Δ5′, m:32.40, V:20.0, size:44, color:’#c9ced5′, truth:5, ans:’Αλουμίνιο, με κοιλότητα’, cav:true,
okMsg:’Σωστά! 32,40 g ÷ 20,0 mL = <strong>1,62 g/mL</strong>: καμία καθαρή ουσία της λίστας δεν ταιριάζει. Το δείγμα είναι αλουμίνιο με <strong>κοιλότητα αέρα</strong> — λιγότερη μάζα για τον ίδιο εξωτερικό όγκο.’},
];
let cur=null, pos=’bench’, busy=false, waterM=50, sXY={x:0,y:0};
const solved = new Set();
/* βαθμονόμηση κυλίνδρου */
(function(){
const g=$(‘#cylTicks’);
for(let m=0;m<=100;m+=5){
const y=372-3*m, major=(m%10===0);
svgEl(‘line’,{x1:major?502:507,y1:y,x2:514,y2:y,stroke:’#28241a’,’stroke-width’:major?1.3:0.9,opacity:major?0.9:0.55},g);
if(major){ const t=svgEl(‘text’,{x:518,y:y+3.5,’font-size’:9,fill:’#6a6250′},g); t.textContent=m; }
}
})();
function drawWater(m){
waterM=m; const y=372-3*m;
$(‘#waterShape’).setAttribute(‘d’,`M427,${y} Q470,${y+9} 513,${y} L513,371 L427,371 Z`);
const g=$(‘#levelGuide’); g.setAttribute(‘y1’,y+5); g.setAttribute(‘y2’,y+5);
const t=$(‘#levelTag’); t.setAttribute(‘y’,y+9); t.textContent=fmt(m,1);
}
function animWater(target,dur=500){
return new Promise(res=>{ const from=waterM; tween(dur,k=>drawWater(from+(target-from)*k),res); });
}
function setLCD(t){ $(‘#lcdTxt’).textContent=t; }
function lcdFlicker(v){
return new Promise(res=>{
let n=0; const iv=setInterval(()=>{
n++;
if(n>=9){ clearInterval(iv); setLCD(fmt(v,2)+’ g’); res(); }
else setLCD(fmt(v*(0.4+Math.random()*1.1),1)+’ g’);
},65);
});
}
function posFor(p){
const z=cur.size;
if(p===’scale’) return {x:150-z/2, y:194-z};
if(p===’cyl’) return {x:470-z/2, y:372-z};
return {x:322-z/2, y:378-z};
}
function buildSample(){
const g=$(‘#sampleG’), s=cur, z=s.size;
let h=`<rect x=”0″ y=”0″ width=”${z}” height=”${z}” rx=”3″ fill=”${s.color}” stroke=”#28241a” stroke-width=”2″/>
<rect x=”4.5″ y=”4.5″ width=”${z-9}” height=”7″ rx=”2.5″ fill=”#ffffff” opacity=”0.33″/>
<text x=”${z/2}” y=”${z/2+4.5}” text-anchor=”middle” font-size=”11″ font-weight=”700″ fill=”${s.dark?’#f5f1e4′:’#28241a’}” style=”letter-spacing:1.5px”>${s.id}</text>`;
if(s.cav && solved.has(s.id))
h+=`<ellipse cx=”${z/2}” cy=”${z/2+7}” rx=”${z*0.21}” ry=”${z*0.19}” fill=”#f5f1e4″ stroke=”#28241a” stroke-dasharray=”4 3″ stroke-width=”1.5″/>`;
g.innerHTML=h;
}
function placeSample(p){ sXY=posFor(p); $(‘#sampleG’).setAttribute(‘transform’,`translate(${sXY.x},${sXY.y})`); }
function glideTo(p,dur=520){
return new Promise(res=>{
const seq=[];
if(pos===’cyl’||p===’cyl’) seq.push({x:(p===’cyl’? 470-cur.size/2 : sXY.x), y:26});
seq.push(posFor(p));
const from={…sXY}; pos=p; let i=0;
(function seg(){
const a=(i===0? from : seq[i-1]), b=seq[i], d=dur/seq.length;
tween(d,k=>{
sXY={x:a.x+(b.x-a.x)*k, y:a.y+(b.y-a.y)*k};
$(‘#sampleG’).setAttribute(‘transform’,`translate(${sXY.x},${sXY.y})`);
},()=>{ i++; if(i<seq.length) seg(); else res(); });
})();
});
}
function spawnBubbles(){
for(let i=0;i<4;i++){
const c=svgEl(‘circle’,{cx:470+(Math.random()*44-22),cy:366,r:1.5+Math.random()*2.2,fill:’#ffffff’,opacity:.85},$(‘#bubbles’));
const dy=30+Math.random()*50;
c.animate([{transform:’translateY(0)’,opacity:.85},{transform:`translateY(-${dy}px)`,opacity:0}],
{duration:600+Math.random()*500,easing:’ease-out’}).finished.then(()=>c.remove());
}
}
function nbUpdate(){
if(!cur) return;
const row=$(`#nbRow${cur.id}`);
row.children[1].textContent = cur.mM ? fmt(cur.m,2) : ‘—’;
row.children[3].textContent = cur.vM ? fmt(50+cur.V,1) : ‘—’;
row.children[4].textContent = cur.vM ? fmt(cur.V,1) : ‘—’;
row.children[5].textContent = (cur.mM&&cur.vM) ? fmt(cur.m/cur.V,2)+’ g/mL’ : ‘—’;
$(‘#formulaLine’).innerHTML = (cur.mM&&cur.vM)
? `ρ<sub>${cur.id}</sub> = ${fmt(cur.m,2)} g ÷ ${fmt(cur.V,1)} mL = <strong>${fmt(cur.m/cur.V,2)} g/mL</strong>`
: `Μέτρησε πρώτα μάζα και όγκο για το ${cur.id}…`;
}
function labMsg(kind,html){ const m=$(‘#labMsg’); m.className=’msg’+(kind?’ ‘+kind:”); m.innerHTML=html; }
function updBtns(){
$(‘#btnWeigh’).disabled = busy || !cur || pos===’scale’;
$(‘#btnSub’).disabled = busy || !cur || pos===’cyl’;
$(‘#btnBench’).disabled = busy || !cur || pos===’bench’;
}
function selectSample(s){
if(busy||cur===s) return;
if(cur && pos===’cyl’) animWater(50,280);
cur=s; pos=’bench’; setLCD(‘0,00 g’);
buildSample(); placeSample(‘bench’);
$(‘#matSel’).value=”; labMsg(”,”);
$(‘#finalPraise’).hidden = solved.size<5;
document.querySelectorAll(‘#nbBody tr’).forEach(r=>r.classList.remove(‘active’));
$(`#nbRow${s.id}`).classList.add(‘active’);
nbUpdate(); updBtns();
}
SAMPLES.forEach(s=>{
const b=el(‘button’,’chip’); b.id=’chip’+s.id; b.title=’Δείγμα ‘+s.id;
b.innerHTML=`<span class=”sw” style=”background:${s.color}”></span>${s.id}`;
b.addEventListener(‘click’,()=>selectSample(s));
$(‘#sampleChips’).appendChild(b);
});
$(‘#btnWeigh’).addEventListener(‘click’,async()=>{
if(busy||!cur) return; busy=true; updBtns();
let wP=Promise.resolve();
if(pos===’cyl’) wP=animWater(50,420);
if(pos!==’scale’) await glideTo(‘scale’);
setLCD(‘0,00 g’);
await lcdFlicker(cur.m);
cur.mM=true; nbUpdate();
await wP; busy=false; updBtns();
});
$(‘#btnSub’).addEventListener(‘click’,async()=>{
if(busy||!cur) return; busy=true; updBtns();
setLCD(‘0,00 g’);
const wP=(async()=>{ await wait(300); spawnBubbles(); await animWater(50+cur.V,560); cur.vM=true; nbUpdate(); })();
await glideTo(‘cyl’,640); await wP; busy=false; updBtns();
});
$(‘#btnBench’).addEventListener(‘click’,async()=>{
if(busy||!cur||pos===’bench’) return; busy=true; updBtns(); setLCD(‘0,00 g’);
let wP=Promise.resolve(); if(pos===’cyl’) wP=animWater(50,380);
await glideTo(‘bench’,520); await wP; busy=false; updBtns();
});
$(‘#btnId’).addEventListener(‘click’,()=>{
if(!cur) return;
const v=$(‘#matSel’).value;
if(v===”){ labMsg(‘bad’,’Διάλεξε πρώτα ένα υλικό από τη λίστα.’); return; }
if(+v===cur.truth){
solved.add(cur.id);
const chip=$(‘#chip’+cur.id); chip.classList.add(‘done’); chip.insertAdjacentHTML(‘beforeend’,’ ‘+ICHECK);
$(`#nbRow${cur.id}`).children[6].innerHTML=`${cur.ans} ${ICHECK}`;
labMsg(‘ok’,cur.okMsg);
$(‘#solvedTxt’).textContent=`Ταυτοποιήθηκαν ${solved.size} / 5`;
buildSample();
if(solved.size===5) $(‘#finalPraise’).hidden=false;
} else {
labMsg(‘bad’,`Δεν ταιριάζει. Διάβασε ξανά μάζα και όγκο του ${cur.id} από το τετράδιο, κάνε τη διαίρεση m ÷ V και σύγκρισε με τις πυκνότητες. (Το Δ5 κρύβει κάτι ξεχωριστό…)`);
}
});
drawWater(50);
selectSample(SAMPLES[0]);
/* =========================================================
Γ΄ — Θερμοκρασία & πυκνότητα
========================================================= */
function rhoWater(t){
const num=999.83952+16.945177*t-7.9870401e-3*t*t-4.6170461e-5*Math.pow(t,3)
+1.0556302e-7*Math.pow(t,4)-2.8054253e-10*Math.pow(t,5);
return num/(1+0.01687985*t)/1000;
}
function rhoEth(t){ return 0.80625-0.000845*t; }
let wDot,eDot,tLine,zDot;
(function buildCharts(){
const W=$(‘#chartWide’), Z=$(‘#chartZoom’);
const line=(p,x1,y1,x2,y2,st,w)=>svgEl(‘line’,{x1,y1,x2,y2,stroke:st,’stroke-width’:w},p);
const txt=(p,x,y,s,size,fill,anchor,weight)=>{const t=svgEl(‘text’,{x,y,’font-size’:size,fill,’text-anchor’:anchor||’start’},p); if(weight)t.setAttribute(‘font-weight’,weight); t.textContent=s; return t;};
const X=t=>64+13*t, Yw=r=>288-(r-0.74)*818.75;
[0.8,0.9,1.0].forEach(r=>{ line(W,64,Yw(r),454,Yw(r),’#ddd5bc’,1); txt(W,56,Yw(r)+3.5,fmt(r,1),10,’#6a6250′,’end’); });
[10,20,30].forEach(t=>{ line(W,X(t),28,X(t),288,’#ddd5bc’,1); txt(W,X(t),302,String(t),10,’#6a6250′,’middle’); });
svgEl(‘path’,{d:’M64,28 L64,288 L454,288′,fill:’none’,stroke:’#28241a’,’stroke-width’:1.6},W);
txt(W,64,16,’ρ (g/mL)’,11,’#6a6250′,’start’,600);
txt(W,258,322,’θ (°C)’,11,’#6a6250′,’middle’,600);
let d=”; for(let t=0;t<=30.01;t+=0.25) d+=(d?’ L’:’M’)+X(t).toFixed(1)+’,’+Yw(rhoWater(t)).toFixed(1);
svgEl(‘path’,{d,fill:’none’,stroke:’#2e6e62′,’stroke-width’:3,’stroke-linejoin’:’round’},W);
let de=”; for(let t=0;t<=30.01;t+=0.5) de+=(de?’ L’:’M’)+X(t).toFixed(1)+’,’+Yw(rhoEth(t)).toFixed(1);
svgEl(‘path’,{d:de,fill:’none’,stroke:’#96662c’,’stroke-width’:2.5},W);
txt(W,452,Yw(rhoWater(30))-9,’νερό’,12.5,’#2e6e62′,’end’,700);
txt(W,452,Yw(rhoEth(30))+17,’οινόπνευμα’,12.5,’#96662c’,’end’,700);
tLine=svgEl(‘line’,{x1:X(15),x2:X(15),y1:28,y2:288,stroke:’#a63b2a’,’stroke-width’:1,’stroke-dasharray’:’4 4′,opacity:.55},W);
wDot=svgEl(‘circle’,{r:5.5,fill:’#2e6e62′,stroke:’#28241a’,’stroke-width’:1.5},W);
eDot=svgEl(‘circle’,{r:5,fill:’#96662c’,stroke:’#28241a’,’stroke-width’:1.5},W);
const X2=t=>56+21.6667*t, Y2=r=>210-(r-0.9994)*320000;
[0.9994,0.9996,0.9998,1.0].forEach(r=>{ line(Z,56,Y2(r),316,Y2(r),’#ddd5bc’,1); txt(Z,50,Y2(r)+3.5,fmt(r,4),9.5,’#6a6250′,’end’); });
[0,4,8,12].forEach(t=>{ line(Z,X2(t),18,X2(t),210,’#ddd5bc’,1); txt(Z,X2(t),224,String(t),10,’#6a6250′,’middle’); });
svgEl(‘path’,{d:’M56,18 L56,210 L316,210′,fill:’none’,stroke:’#28241a’,’stroke-width’:1.4},Z);
txt(Z,56,10,’ρ (g/mL)’,10.5,’#6a6250′,’start’,600);
txt(Z,186,238,’θ (°C)’,10.5,’#6a6250′,’middle’,600);
let dz=”; for(let t=0;t<=12.001;t+=0.1) dz+=(dz?’ L’:’M’)+X2(t).toFixed(1)+’,’+Y2(rhoWater(t)).toFixed(1);
svgEl(‘path’,{d:dz,fill:’none’,stroke:’#2e6e62′,’stroke-width’:3},Z);
svgEl(‘line’,{x1:X2(4),x2:X2(4),y1:18,y2:210,stroke:’#a63b2a’,’stroke-dasharray’:’4 4′,’stroke-width’:1.2,opacity:.7},Z);
txt(Z,X2(4),14,’≈4 °C’,10,’#a63b2a’,’middle’,700);
svgEl(‘line’,{x1:56,x2:316,y1:Y2(rhoWater(3.98)),y2:Y2(rhoWater(3.98)),stroke:’#a63b2a’,’stroke-dasharray’:’2 3′,’stroke-width’:1,opacity:.5},Z);
zDot=svgEl(‘circle’,{r:4.5,fill:’#2e6e62′,stroke:’#28241a’,’stroke-width’:1.5},Z);
})();
(function thermoTicks(){
const g=$(‘#thermoTicks’);
for(let t=0;t<=30;t+=5){
const y=268-7.33333*t, major=(t%10===0);
svgEl(‘line’,{x1:major?46:49,y1:y,x2:54,y2:y,stroke:’#28241a’,’stroke-width’:major?1.4:1,opacity:major?.95:.6},g);
if(major){ const tx=svgEl(‘text’,{x:42,y:y+3.5,’font-size’:10,fill:’#6a6250′,’text-anchor’:’end’},g); tx.textContent=t; }
}
})();
function updateTemp(t){
const rw=rhoWater(t), re=rhoEth(t);
$(‘#tVal’).textContent=fmt(t,1)+’ °C’;
$(‘#rTheta’).textContent=fmt(t,1)+’ °C’;
$(‘#rRhoW’).textContent=fmt(rw,5)+’ g/mL’;
$(‘#rVolW’).textContent=fmt(1000/rw,1)+’ mL’;
$(‘#rRhoE’).textContent=fmt(re,4)+’ g/mL’;
$(‘#rVolE’).textContent=fmt(1000/re,1)+’ mL’;
const y=268-7.33333*t, m=$(‘#merc’);
m.setAttribute(‘y’,y); m.setAttribute(‘height’,296-y);
const X=t=>64+13*t, Yw=r=>288-(r-0.74)*818.75;
wDot.setAttribute(‘cx’,X(t)); wDot.setAttribute(‘cy’,Yw(rw));
eDot.setAttribute(‘cx’,X(t)); eDot.setAttribute(‘cy’,Yw(re));
tLine.setAttribute(‘x1’,X(t)); tLine.setAttribute(‘x2’,X(t));
if(t<=12){ zDot.setAttribute(‘opacity’,1); zDot.setAttribute(‘cx’,56+21.6667*t); zDot.setAttribute(‘cy’,210-(rw-0.9994)*320000); }
else zDot.setAttribute(‘opacity’,0);
}
let sweep=null;
const sweepBtn=$(‘#sweepBtn’);
function stopSweep(){ if(sweep){ sweep.cancel(); sweep=null; } sweepBtn.textContent=’Σάρωση 0 → 30 °C’; }
sweepBtn.addEventListener(‘click’,()=>{
if(sweep){ stopSweep(); return; }
const s=$(‘#tSlider’); let from=+s.value; if(from>29) from=0;
s.value=from;
sweep=tween(6500,k=>{ const t=from+(30-from)*k; s.value=t; updateTemp(t); },
()=>{ sweep=null; sweepBtn.textContent=’Σάρωση 0 → 30 °C’; }, k=>k);
sweepBtn.textContent=’Διακοπή σάρωσης’;
});
$(‘#tSlider’).addEventListener(‘input’,e=>{ stopSweep(); updateTemp(+e.target.value); });
updateTemp(15);
/* =========================================================
Δ΄ — Στρωμάτωση υγρών & επιπλέωση σωμάτων
========================================================= */
const LIQ=[
{id:’alc’,n:’Οινόπνευμα’,rho:0.79,c:’#e7ead0′},
{id:’oil’,n:’Ηλιέλαιο’,rho:0.91,c:’#e2c458′},
{id:’wat’,n:’Νερό’,rho:1.00,c:’#bcd8d1′},
{id:’gly’,n:’Γλυκερίνη’,rho:1.26,c:’#d9ded3′},
{id:’hon’,n:’Μέλι’,rho:1.42,c:’#c98f33′},
];
const BOD=[
{id:’cork’,n:’Φελλός’,rho:0.24,w:30,h:22,c:’#c8a06a’},
{id:’wood’,n:’Ξύλο’,rho:0.70,w:32,h:20,c:’#9a6b45′,grain:true},
{id:’ice’,n:’Πάγος’,rho:0.92,w:26,h:24,c:’#e2eef2′},
{id:’pvc’,n:’Πλαστικό PVC’,rho:1.40,w:28,h:22,c:’#cfd2ce’},
{id:’alu’,n:’Αλουμίνιο’,rho:2.70,w:30,h:24,c:’#c9ced5′},
{id:’iron’,n:’Σίδηρος’,rho:7.87,w:26,h:22,c:’#474c54′,dark:true},
];
const BX=74,BW=222,BBOT=424,LH=54, BXS=[110,158,204,248,132,182];
const liqSel=new Set(); let bodies=[];
function strata(){
const arr=LIQ.filter(l=>liqSel.has(l.id)).sort((a,b)=>a.rho-b.rho);
let yb=BBOT; const out=[];
for(let i=arr.length-1;i>=0;i–){ out.unshift({…arr[i],yBot:yb,yTop:yb-LH}); yb-=LH; }
return out;
}
function renderStrata(){
const gS=$(‘#strata’), gL=$(‘#strataLabels’); gS.innerHTML=”; gL.innerHTML=”;
const L=strata();
$(‘#emptyHint’).style.display = L.length ? ‘none’ : ‘block’;
L.forEach(l=>{
svgEl(‘rect’,{x:BX,y:l.yTop,width:BW,height:LH,fill:l.c,opacity:0.94},gS);
svgEl(‘rect’,{x:BX,y:l.yTop,width:BW,height:2.5,fill:’#28241a’,opacity:0.14},gS);
const cy=(l.yTop+l.yBot)/2;
svgEl(‘line’,{x1:300,y1:cy,x2:308,y2:cy,stroke:’#28241a’,’stroke-width’:1},gL);
const t=svgEl(‘text’,{x:312,y:cy+4,’font-size’:12,fill:’#28241a’},gL);
t.textContent=`${l.n} · ρ=${fmt(l.rho,2)}`;
});
}
function computeSettle(b){
const L=strata();
if(!L.length) return {y:BBOT-b.h, txt:’παραμένει στον πυθμένα’};
if(b.rho > L[L.length-1].rho)
return {y:BBOT-b.h, txt:’βυθίζεται μέσα από όλα τα υγρά και κατακάθεται στον πυθμένα’};
for(let i=0;i<L.length;i++){
const l=L[i];
if(Math.abs(b.rho-l.rho)<0.005)
return {y:(l.yTop+l.yBot)/2-b.h/2, txt:`αιωρείται μέσα στο ${l.n} (σχεδόν ίσες πυκνότητες!)`};
if(b.rho<l.rho){
if(i===0){
const f=Math.max(.18,Math.min(.9,b.rho/l.rho));
return {y:l.yTop-(1-f)*b.h, txt:`επιπλέει στην επιφάνεια του ${l.n}`};
}
return {y:l.yTop-0.38*b.h, txt:`σταματά στη διεπιφάνεια ${L[i-1].n}–${l.n}`};
}
}
return {y:BBOT-b.h, txt:’κατακάθεται στον πυθμένα’};
}
function renderLog(){
const ul=$(‘#obsLog’);
if(!bodies.length){ ul.innerHTML='<li class=”empty”>Οι παρατηρήσεις σου θα εμφανιστούν εδώ…</li>’; return; }
ul.innerHTML=bodies.map(b=>`<li><span class=”sw” style=”background:${b.def.c}”></span><span><strong>${b.def.n}</strong> <span class=”rho”>(ρ=${fmt(b.def.rho,2)} g/mL)</span> — ${b.txt}</span></li>`).join(”);
}
function bkBubbles(y){
for(let i=0;i<3;i++){
const c=svgEl(‘circle’,{cx:BX+30+Math.random()*(BW-60),cy:y+4,r:2+Math.random()*2,fill:’#ffffff’,opacity:.8},$(‘#bodyG’));
const dy=26+Math.random()*36;
c.animate([{transform:’translateY(0)’,opacity:.8},{transform:`translateY(-${dy}px)`,opacity:0}],
{duration:650+Math.random()*450,easing:’ease-out’}).finished.then(()=>c.remove());
}
}
function dropAnim(b){
b.falling=true;
let v=0, crossed=false, iter=0;
const surf = strata()[0] ? strata()[0].yTop : BBOT;
(function step(){
iter++; v+=1.05; b.y+=v;
if(!crossed && b.y+b.def.h>=surf+6){ crossed=true; bkBubbles(surf); }
if(b.y>=b.target){
b.y=b.target;
if(v>3.4 && iter<400){ v=-v*0.24; }
else{
b.el.setAttribute(‘transform’,`translate(${b.x},${b.y})`);
const s2=computeSettle(b.def); b.txt=s2.txt; renderLog();
if(Math.abs(s2.y-b.target)>1) tween(380,k=>{},null); // ελάχιστη αναμονή
b.falling=false;
return;
}
}
b.el.setAttribute(‘transform’,`translate(${b.x},${b.y})`);
requestAnimationFrame(step);
})();
}
function dmsg(kind,html){ const m=$(‘#beakerMsg’); m.className=’msg’+(kind?’ ‘+kind:”); m.innerHTML=html; }
function dropBody(def){
if(!liqSel.size){ dmsg(‘bad’,’Πρόσθεσε πρώτα τουλάχιστον ένα υγρό — αλλιώς το σώμα δεν έχει πού να πέσει.’); return; }
if(bodies.length>=6){ dmsg(‘bad’,’Το δοχείο γέμισε σώματα· άδειασέ το για να συνεχίσεις.’); return; }
const x=BXS[bodies.length%BXS.length]+(Math.random()*8-4);
const g=svgEl(‘g’,{},$(‘#bodyG’));
svgEl(‘rect’,{x:0,y:0,width:def.w,height:def.h,rx:3,fill:def.c,stroke:’#28241a’,’stroke-width’:2},g);
if(def.grain) svgEl(‘line’,{x1:3,y1:def.h*0.5,x2:def.w-3,y2:def.h*0.5,stroke:’#28241a’,opacity:.35,’stroke-width’:1},g);
const ti=svgEl(‘title’,{},g); ti.textContent=`${def.n} — ρ=${fmt(def.rho,2)} g/mL`;
const s=computeSettle(def);
const b={def,x,y:10,el:g,txt:s.txt,target:s.y};
bodies.push(b);
g.setAttribute(‘transform’,`translate(${x},10)`);
renderLog(); dmsg(”,”);
dropAnim(b);
}
function resettle(){
bodies.forEach(b=>{
if(b.falling) return;
const s=computeSettle(b.def); b.txt=s.txt;
const y0=b.y, y1=s.y;
tween(420,k=>{ b.y=y0+(y1-y0)*k; b.el.setAttribute(‘transform’,`translate(${b.x},${b.y})`); });
});
renderLog();
}
LIQ.forEach(l=>{
const b=el(‘button’,’chip’);
b.innerHTML=`<span class=”sw” style=”background:${l.c}”></span>${l.n} · ${fmt(l.rho,2)}`;
b.setAttribute(‘aria-pressed’,’false’);
b.addEventListener(‘click’,()=>{
if(liqSel.has(l.id)){ liqSel.delete(l.id); b.setAttribute(‘aria-pressed’,’false’); }
else{ liqSel.add(l.id); b.setAttribute(‘aria-pressed’,’true’); }
renderStrata(); resettle();
});
$(‘#liqChips’).appendChild(b);
});
BOD.forEach(d=>{
const b=el(‘button’,’chip’);
b.innerHTML=`${IARROW}${d.n} <span class=”rho”>(${fmt(d.rho,2)})</span>`;
b.addEventListener(‘click’,()=>dropBody(d));
$(‘#bodBtns’).appendChild(b);
});
$(‘#btnEmpty’).addEventListener(‘click’,()=>{
bodies=[]; $(‘#bodyG’).innerHTML=”; liqSel.clear();
document.querySelectorAll(‘#liqChips .chip’).forEach(c=>c.setAttribute(‘aria-pressed’,’false’));
renderStrata(); renderLog(); dmsg(”,”);
});
renderStrata(); renderLog();
/* =========================================================
Ε΄ — Quiz
========================================================= */
const QUIZ=[
{q:’Η πυκνότητα ενός υλικού σώματος ορίζεται ως:’,
o:[‘ο χώρος που καταλαμβάνει το σώμα’,’η ποσότητα της ύλης που περιέχει το σώμα’,’ο σταθερός λόγος της μάζας προς τον όγκο, σε σταθερή θερμοκρασία και πίεση’,’η δύναμη με την οποία το έλκει η Γη’], c:2,
why:’ρ = m/V. Η πυκνότητα είναι ιδιότητα του υλικού: ίδια για όλα τα σώματα από το ίδιο υλικό, στις ίδιες συνθήκες.’},
{q:’Σε συσκευασία φαρμάκου συναντάμε τη μονάδα 1 cc (cubic centimeter). Ισούται με:’,
o:[‘1 mL’,’1 g’,’1 mg’,’1 cm (μήκους)’], c:0,
why:’cc = κυβικό εκατοστόμετρο = 1 cm³ = 1 mL = 1000 mL του λίτρου… απλά: 1 cm³ = 1 mL.’},
{q:’Τέσσερα δοχεία περιέχουν την ίδια ουσία: Α 250 g, Β 25.000 mg, Γ 0,24 kg, Δ 25 μg. Η μάζα αυξάνεται κατά τη σειρά:’,
o:[‘Α < Β < Γ < Δ’,’Α < Γ < Β < Δ’,’Δ < Β < Γ < Α’,’Δ < Β < Α < Γ’], c:2,
why:’Μετατροπές: Β = 25 g, Γ = 240 g, Δ = 0,000025 g. Άρα: Δ (25 μg) < Β (25 g) < Γ (240 g) < Α (250 g).’},
{q:’Τεμαχίζουμε μια μάζα χρυσού (ρ = 19,3 g/mL) σε δύο ίσα μέρη. Η πυκνότητα κάθε μέρους είναι:’,
o:[‘ίση με την αρχική’,’διπλάσια της αρχικής’,’η μισή της αρχικής’,’μικρότερη, γιατί μειώθηκε η μάζα’], c:0,
why:’Μάζα και όγκος μειώνονται εξίσου· ο λόγος τους μένει σταθερός — η πυκνότητα είναι ιδιότητα του υλικού, δεν εξαρτάται από m ή V.’},
{q:’Νόμισμα μάζας 38,19 g ανεβάζει τη στάθμη νερού σε ογκομετρικό κύλινδρο από 50,0 mL σε 53,8 mL. Με ρ(ασήμι) = 10,5 g/mL, συμπεραίνουμε ότι το νόμισμα:’,
o:[‘είναι σίγουρα από καθαρό άργυρο’,’δεν είναι καθαρό άργυρος: προκύπτει ρ ≈ 10,05 g/mL ≠ 10,5 g/mL’,’είναι από χρυσό, που είναι πυκνότερος’,’από αυτά τα δεδομένα δεν βγαίνει κανένα συμπέρασμα’], c:1,
why:’V = 53,8 − 50,0 = 3,8 mL και ρ = 38,19 g ÷ 3,8 mL ≈ 10,05 g/mL. Η διαφορά από την τιμή του ασημιού δείχνει ότι πρόκειται μάλλον για κράμα.’},
{q:’Ένα σώμα μεταφέρεται από τη Γη στη Σελήνη. Ποιο μέγεθος θα μεταβληθεί;’,
o:[‘Η μάζα του’,’Το βάρος του’,’Ο όγκος του’,’Η πυκνότητα του υλικού του’], c:1,
why:’w = m·g: η επιτάχυνση της βαρύτητας στη Σελήνη είναι περίπου 1/6 της γήινης, άρα το βάρος ελαττώνεται. Μάζα, όγκος και πυκνότητα μένουν ίδιες.’},
{q:’Η πυκνότητα ενός αερίου εξαρτάται:’,
o:[‘μόνο από τη θερμοκρασία’,’μόνο από την πίεση’,’από καμία από τις δύο’,’από τη θερμοκρασία και την πίεση’], c:3,
why:’Τα αέρια συστέλλονται και διαστέλλονται πολύ εύκολα: μεταβολή πίεσης ή θερμοκρασίας αλλάζει δραστικά τον όγκο, άρα και την πυκνότητα.’},
{q:’Η πυκνότητα του νερού είναι μέγιστη στους:’,
o:[‘0 °C’,’2 °C’,’10 °C’,’4 °C’], c:3,
why:’Από 0 έως 4 °C το νερό συνεχίζει να συστέλλεται — η ανωμαλία του νερού. Γι\’ αυτό ο πάγος (λιγότερο πυκνός) επιπλέει.’},
];
let score=0;
function renderQuiz(){
score=0; $(‘#scoreTxt’).textContent=`Σωστές απαντήσεις: 0 / ${QUIZ.length}`;
const box=$(‘#quizBox’); box.innerHTML=”;
QUIZ.forEach((q,i)=>{
const qbox=el(‘div’,’q’);
qbox.innerHTML=`
<div class=”q-head”><span class=”q-num”>${i+1}</span><span class=”q-text”>${q.q}</span></div>
<div class=”opts”>${q.o.map((o,j)=>`<label class=”opt”><input type=”radio” name=”q${i}” value=”${j}”><span>${o}</span></label>`).join(”)}</div>
<div class=”actions” style=”margin:0″><button class=”btn small”>Έλεγχος απάντησης</button></div>
<div class=”qmsg msg” aria-live=”polite”></div>
<div class=”why”>${q.why}</div>`;
box.appendChild(qbox);
const btn=qbox.querySelector(‘button’), qm=qbox.querySelector(‘.qmsg’);
qbox.querySelectorAll(‘input’).forEach(inp=>inp.addEventListener(‘change’,()=>{ qm.className=’qmsg msg’; qm.textContent=”; }));
btn.addEventListener(‘click’,()=>{
const sel=qbox.querySelector(‘input:checked’);
if(!sel){ qm.className=’qmsg msg bad’; qm.textContent=’Διάλεξε πρώτα μια απάντηση.’; return; }
const j=+sel.value;
qbox.classList.add(‘done’); btn.disabled=true;
qbox.querySelectorAll(‘input’).forEach(x=>x.disabled=true);
qbox.querySelectorAll(‘.opt’).forEach((l,k)=>{ if(k===q.c) l.classList.add(‘mark-ok’); else if(k===j) l.classList.add(‘mark-bad’); });
if(j===q.c){ score++; qm.className=’qmsg msg ok’; qm.textContent=’Σωστά!’; }
else { qm.className=’qmsg msg bad’; qm.textContent=’Λάθος — η σωστή απάντηση είναι επισημασμένη με πράσινο.’; }
$(‘#scoreTxt’).textContent=`Σωστές απαντήσεις: ${score} / ${QUIZ.length}`;
});
});
}
$(‘#btnQuizReset’).addEventListener(‘click’,renderQuiz);
renderQuiz();
/* ———- πλοήγηση: ενεργή ενότητα ———- */
const links=[…document.querySelectorAll(‘#topnav a’)];
const io=new IntersectionObserver(es=>{
es.forEach(e=>{ if(e.isIntersecting) links.forEach(a=>a.classList.toggle(‘current’,a.hash===’#’+e.target.id)); });
},{rootMargin:’-40% 0px -55% 0px’});
document.querySelectorAll(‘main section’).forEach(s=>io.observe(s));
})();
</script>
</body>
</html>