Română B1/B2 – Exerciții
:root {
–ink: #1a1208;
–cream: #f7f2e8;
–gold: #c8922a;
–rust: #b84a2a;
–sage: #4a6741;
–mist: #e8e2d4;
–shadow: rgba(26,18,8,0.12);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(–cream);
color: var(–ink);
font-family: ‘Source Serif 4’, serif;
min-height: 100vh;
padding: 0 0 60px;
}
header {
background: var(–ink);
color: var(–cream);
padding: 36px 24px 28px;
text-align: center;
position: relative;
overflow: hidden;
}
header::before {
content: ”;
position: absolute;
inset: 0;
background: repeating-linear-gradient(
45deg,
transparent,
transparent 18px,
rgba(200,146,42,0.07) 18px,
rgba(200,146,42,0.07) 19px
);
}
header h1 {
font-family: ‘Playfair Display’, serif;
font-size: clamp(1.8rem, 5vw, 2.8rem);
letter-spacing: 0.02em;
position: relative;
}
header h1 span { color: var(–gold); }
header p {
margin-top: 8px;
font-size: 0.95rem;
opacity: 0.7;
font-style: italic;
position: relative;
}
.progress-bar-wrap {
background: rgba(255,255,255,0.1);
height: 4px;
margin-top: 20px;
border-radius: 2px;
position: relative;
overflow: hidden;
}
.progress-bar-fill {
height: 100%;
background: var(–gold);
border-radius: 2px;
transition: width 0.4s ease;
width: 0%;
}
.score-display {
position: relative;
font-size: 0.85rem;
margin-top: 8px;
opacity: 0.8;
letter-spacing: 0.05em;
}
main {
max-width: 720px;
margin: 0 auto;
padding: 32px 20px 0;
}
.exercise {
background: white;
border-radius: 4px;
padding: 28px 26px;
margin-bottom: 20px;
box-shadow: 0 2px 12px var(–shadow);
border-left: 4px solid var(–mist);
transition: border-color 0.3s;
animation: slideIn 0.35s ease both;
}
@keyframes slideIn {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
.exercise.correct { border-left-color: var(–sage); }
.exercise.wrong { border-left-color: var(–rust); }
.ex-header {
display: flex;
align-items: baseline;
gap: 12px;
margin-bottom: 14px;
}
.ex-num {
font-family: ‘Playfair Display’, serif;
font-size: 1.3rem;
color: var(–gold);
min-width: 28px;
}
.ex-type {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.12em;
color: #888;
font-weight: 600;
}
.ex-question {
font-size: 1.05rem;
line-height: 1.6;
font-weight: 300;
color: var(–ink);
}
.ex-question strong {
font-weight: 600;
color: var(–gold);
border-bottom: 1px solid rgba(200,146,42,0.3);
}
/* Multiple choice */
.choices {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: 16px;
}
@media(max-width: 480px) { .choices { grid-template-columns: 1fr; } }
.choice-btn {
background: var(–cream);
border: 1.5px solid var(–mist);
border-radius: 3px;
padding: 10px 14px;
font-family: ‘Source Serif 4’, serif;
font-size: 0.95rem;
color: var(–ink);
cursor: pointer;
text-align: left;
transition: all 0.18s;
line-height: 1.4;
}
.choice-btn:hover:not(:disabled) {
border-color: var(–gold);
background: #fdf8ef;
transform: translateX(3px);
}
.choice-btn.selected-correct {
background: #edf6ea;
border-color: var(–sage);
color: var(–sage);
font-weight: 600;
}
.choice-btn.selected-wrong {
background: #fceee9;
border-color: var(–rust);
color: var(–rust);
}
.choice-btn.reveal-correct {
background: #edf6ea;
border-color: var(–sage);
color: var(–sage);
}
.choice-btn:disabled { cursor: default; }
/* Fill in the blank */
.fitb-wrap {
margin-top: 16px;
display: flex;
gap: 10px;
align-items: center;
flex-wrap: wrap;
}
.fitb-input {
border: none;
border-bottom: 2px solid var(–ink);
background: transparent;
font-family: ‘Playfair Display’, serif;
font-style: italic;
font-size: 1.1rem;
color: var(–ink);
padding: 4px 8px;
min-width: 120px;
width: 160px;
outline: none;
transition: border-color 0.2s;
}
.fitb-input:focus { border-color: var(–gold); }
.fitb-input.correct-input { border-color: var(–sage); color: var(–sage); }
.fitb-input.wrong-input { border-color: var(–rust); color: var(–rust); }
.check-btn {
background: var(–ink);
color: var(–cream);
border: none;
border-radius: 2px;
padding: 8px 18px;
font-family: ‘Source Serif 4’, serif;
font-size: 0.9rem;
cursor: pointer;
letter-spacing: 0.04em;
transition: background 0.18s;
}
.check-btn:hover { background: var(–gold); }
.check-btn:disabled { opacity: 0.4; cursor: default; }
.feedback {
margin-top: 12px;
font-size: 0.9rem;
padding: 10px 14px;
border-radius: 2px;
display: none;
line-height: 1.5;
}
.feedback.show { display: block; }
.feedback.fb-correct { background: #edf6ea; color: var(–sage); }
.feedback.fb-wrong { background: #fceee9; color: var(–rust); }
.feedback em { font-style: normal; font-weight: 600; }
/* Summary */
#summary {
display: none;
text-align: center;
padding: 40px 20px;
}
#summary h2 {
font-family: ‘Playfair Display’, serif;
font-size: 2rem;
color: var(–ink);
}
#summary .big-score {
font-family: ‘Playfair Display’, serif;
font-size: 4rem;
color: var(–gold);
margin: 16px 0;
}
#summary p { font-size: 1.05rem; color: #555; margin-bottom: 24px; }
#restart-btn {
background: var(–ink);
color: var(–cream);
border: none;
padding: 14px 32px;
font-family: ‘Source Serif 4’, serif;
font-size: 1rem;
cursor: pointer;
letter-spacing: 0.06em;
border-radius: 2px;
transition: background 0.2s;
}
#restart-btn:hover { background: var(–gold); }
.section-label {
font-family: ‘Playfair Display’, serif;
font-size: 1.1rem;
color: var(–ink);
margin: 36px 0 16px;
padding-bottom: 8px;
border-bottom: 1px solid var(–mist);
font-style: italic;
}
Felicitări!
const exercises = [
// ── CONJUNCTIVE / SUBJUNCTIVE ──────────────────────────────
{
section: “Modul conjunctiv”,
type: “mc”,
q: “Vreau
să ___ la cinematograf mâine seară.”,
choices: [“merg”, “mers”, “merg eu”, “mersul”],
answer: 0,
explain: “
Să merg — conjunctivul prezent, persoana I singular.”
},
{
type: “mc”,
q: “Mama i-a spus copilului
să ___ înainte de culcare.”,
choices: [“se spălă”, “se spele”, “spălat”, “se spăla”],
answer: 1,
explain: “
Să se spele — conjunctiv prezent al verbului reflexiv
a se spăla.”
},
// ── CONDITIONAL ───────────────────────────────────────────
{
section: “Condiţionalul”,
type: “fitb”,
q: “Dacă aș ști răspunsul, ți-___ spune imediat.”,
answer: [“aș”, “as”],
explain: “Condiţionalul prezent:
aș spune (I would tell you).”
},
{
type: “mc”,
q: “Dacă ar fi plecat mai devreme,
___ autobuzul.”,
choices: [“ar prinde”, “ar fi prins”, “prindea”, “ar prins”],
answer: 1,
explain: “
Ar fi prins — condiţionalul perfect, pentru o ipoteză despre trecut.”
},
// ── PAST TENSES ───────────────────────────────────────────
{
section: “Timpurile trecutului”,
type: “mc”,
q: “Ieri dimineaţă eu ___ o cafea și ___ ziarul.”,
choices: [“am băut / am citit”, “beam / citeam”, “băusem / citisem”, “beau / citeam”],
answer: 0,
explain: “
Am băut / am citit — perfectul compus pentru acţiuni terminate în trecut.”
},
{
type: “fitb”,
q: “Când eram mic, ___ (a merge) la bunici în fiecare vară.”,
answer: [“mergeam”],
explain: “
Mergeam — imperfectul exprimă o acţiune obişnuită în trecut.”
},
{
type: “mc”,
q: “Până să ajungă ea, el deja ___ tot mâncarea.”,
choices: [“a mâncat”, “mâncase”, “mânca”, “va mânca”],
answer: 1,
explain: “
Mâncase — mai mult ca perfectul indică o acţiune anterioară altei acţiuni trecute.”
},
// ── PASSIVE VOICE ─────────────────────────────────────────
{
section: “Diateza pasivă”,
type: “mc”,
q: “Cartea ___ de elevi cu mult entuziasm.”,
choices: [“s-a citit”, “s-au citit”, “au citit”, “a citit”],
answer: 0,
explain: “
S-a citit — pasiv reflexiv cu subiect singular
cartea.”
},
{
type: “fitb”,
q: “Raportul a ___ (scrie) de secretară ieri.”,
answer: [“fost scris”],
explain: “
A fost scris — pasivul cu
a fi + participiu.”
},
// ── GERUNZIU / INFINITIV ──────────────────────────────────
{
section: “Gerunziul şi infinitivul”,
type: “mc”,
q: “El a plecat fără ___ un cuvânt.”,
choices: [“să spune”, “a spune”, “spunând”, “spus”],
answer: 2,
explain: “
Spunând — gerunziul după
fără în construcţii adverbiale.”
},
{
type: “mc”,
q: “___ româna bine este o sarcină dificilă, dar posibilă.”,
choices: [“Să vorbeşti”, “A vorbi”, “Vorbeşti”, “Vorbind”],
answer: 1,
explain: “
A vorbi — infinitivul lung cu rol de subiect al propoziţiei.”
},
// ── PRONOUNS ──────────────────────────────────────────────
{
section: “Pronume şi clitice”,
type: “mc”,
q: “I-am dat ___ cadoul ieri.”,
choices: [“lui Ion”, “pe Ion”, “Ion”, “al Ion”],
answer: 0,
explain: “
Lui Ion — dativul numelui propriu, corespunde cliticului
i-.”
},
{
type: “fitb”,
q: “Nu ___ (a vedea, pe ei) de mult timp. (completaţi cu forma corectă a pronumelui + verbului)”,
answer: [“i-am văzut”, “i am văzut”],
explain: “
Nu i-am văzut — acuzativul cliticului
îi → i- înaintea verbului.”
},
// ── PREPOSITIONS & CASES ──────────────────────────────────
{
section: “Prepoziţii şi cazuri”,
type: “mc”,
q: “Mă duc ___ prietenul meu în fiecare sâmbătă.”,
choices: [“la”, “spre”, “până la”, “de la”],
answer: 0,
explain: “
La indică destinaţia / persoana vizitată.”
},
{
type: “mc”,
q: “Casa ___ vecinului nostru a fost vândută.”,
choices: [“al”, “a”, “lui”, “de al”],
answer: 2,
explain: “
Lui — genitivul pronominal/adverbial pentru posesie:
casa lui.”
},
// ── VOCABULARY / COLLOCATIONS ─────────────────────────────
{
section: “Vocabular şi colocaţii”,
type: “mc”,
q: “A ___ o greşeală înseamnă a recunoaşte că ai greşit.”,
choices: [“face”, “recunoaşte”, “lua”, “pune”],
answer: 0,
explain: “
A face o greşeală — colocaţie standard în română.”
},
{
type: “fitb”,
q: “Îmi pare foarte ___ că nu am putut veni la petrecerea ta. (regret, remorse)”,
answer: [“rău”],
explain: “
Îmi pare rău = I’m sorry / I regret. Expresie fixă.”
},
{
type: “mc”,
q: “El a luat ___ şi a plecat fără să spună nimic.”,
choices: [“la revedere”, “cu bun rămas”, “la plecare”, “tăcere”],
answer: 0,
explain: “
A lua la revedere — expresie fixă pentru a-şi lua rămas bun.”
},
// ── RELATIVE CLAUSES ─────────────────────────────────────
{
section: “Propoziţii relative”,
type: “mc”,
q: “Băiatul ___ carte am citit-o este un scriitor celebru.”,
choices: [“al cărui”, “a cărei”, “a cărui”, “pe care”],
answer: 2,
explain: “
A cărui carte — pronume relativ genitival masculin singular.”
},
{
type: “fitb”,
q: “Persoana ___ (pe care / căreia) i-am trimis scrisoarea nu a răspuns.”,
answer: [“căreia”],
explain: “
Căreia — dativul pronumelui relativ feminin, corespunde cliticului dativ
i-.”
}
];
let answered = 0;
let correct = 0;
let total = exercises.length;
function buildExercises() {
const container = document.getElementById(‘exercisesContainer’);
container.innerHTML = ”;
let currentSection = ”;
exercises.forEach((ex, i) => {
if (ex.section && ex.section !== currentSection) {
currentSection = ex.section;
const label = document.createElement(‘div’);
label.className = ‘section-label’;
label.textContent = ex.section;
container.appendChild(label);
}
const div = document.createElement(‘div’);
div.className = ‘exercise’;
div.id = `ex-${i}`;
div.style.animationDelay = `${i * 0.03}s`;
const header = `
${ex.q}
`;
let body = ”;
if (ex.type === ‘mc’) {
body = `
` +
ex.choices.map((c, ci) =>
``
).join(”) +
`
`;
} else {
body = `
`;
}
const feedback = `
`;
div.innerHTML = header + body + feedback;
container.appendChild(div);
});
}
function markAnswered(idx, isCorrect) {
answered++;
if (isCorrect) correct++;
updateProgress();
if (answered === total) {
setTimeout(showSummary, 800);
}
}
function updateProgress() {
document.getElementById(‘progressFill’).style.width = `${(answered/total)*100}%`;
document.getElementById(‘scoreDisplay’).textContent = `${correct} / ${total} răspunsuri corecte`;
}
function showFeedback(idx, isCorrect, ex) {
const fb = document.getElementById(`fb-${idx}`);
fb.className = `feedback show ${isCorrect ? ‘fb-correct’ : ‘fb-wrong’}`;
fb.innerHTML = (isCorrect ? ‘✓ Corect! ‘ : ‘✗ Incorect. ‘) + ex.explain;
}
function checkMC(idx, chosen) {
const ex = exercises[idx];
const div = document.getElementById(`ex-${idx}`);
const btns = div.querySelectorAll(‘.choice-btn’);
btns.forEach(b => b.disabled = true);
const isCorrect = chosen === ex.answer;
btns[chosen].classList.add(isCorrect ? ‘selected-correct’ : ‘selected-wrong’);
if (!isCorrect) btns[ex.answer].classList.add(‘reveal-correct’);
div.classList.add(isCorrect ? ‘correct’ : ‘wrong’);
showFeedback(idx, isCorrect, ex);
markAnswered(idx, isCorrect);
}
function checkFITB(idx) {
const ex = exercises[idx];
const inp = document.getElementById(`inp-${idx}`);
const btn = document.getElementById(`btn-${idx}`);
const div = document.getElementById(`ex-${idx}`);
const val = inp.value.trim().toLowerCase();
if (!val) return;
const isCorrect = ex.answer.some(a => a.toLowerCase() === val);
inp.disabled = true;
btn.disabled = true;
inp.classList.add(isCorrect ? ‘correct-input’ : ‘wrong-input’);
if (!isCorrect) {
// show correct answer
inp.value = ex.answer[0];
inp.classList.remove(‘wrong-input’);
inp.classList.add(‘correct-input’);
const wrongSpan = document.createElement(‘span’);
wrongSpan.style.cssText = ‘color:var(–rust);font-size:0.85rem;text-decoration:line-through’;
wrongSpan.textContent = val;
inp.parentNode.insertBefore(wrongSpan, inp);
}
div.classList.add(isCorrect ? ‘correct’ : ‘wrong’);
showFeedback(idx, isCorrect, ex);
markAnswered(idx, isCorrect);
}
function showSummary() {
document.getElementById(‘exercisesContainer’).style.display = ‘none’;
const summary = document.getElementById(‘summary’);
summary.style.display = ‘block’;
document.getElementById(‘finalScore’).textContent = `${correct} / ${total}`;
let msg;
const pct = correct / total;
if (pct >= 0.9) msg = “Excelent! Nivelul tău este cu adevărat B2.”;
else if (pct >= 0.7) msg = “Foarte bine! Continuă să exersezi.”;
else if (pct >= 0.5) msg = “Bine! Mai ai de lucru, dar eşti pe drumul cel bun.”;
else msg = “Nu-ţi face griji — revizuieşte gramatica şi încearcă din nou!”;
document.getElementById(‘finalMsg’).textContent = msg;
}
function restart() {
answered = 0; correct = 0;
document.getElementById(‘summary’).style.display = ‘none’;
document.getElementById(‘exercisesContainer’).style.display = ‘block’;
updateProgress();
buildExercises();
window.scrollTo({top:0, behavior:’smooth’});
}
buildExercises();