Index: app.py
===================================================================
--- app.py	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ app.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -45,15 +45,15 @@
 @app.route('/')
 def index():
-    return '''
-    <h1>🧪 SIMLAB - Виртуелна Хемиска Лабораторија</h1>
-    <h3>📊 SQL пристап за Бази на Податоци</h3>
-    <ul>
-        <li><a href="/users">👥 Прикажи корисници</a></li>
-        <li><a href="/elements">🔬 Прикажи хемиски елементи</a></li>
-        <li><a href="/equipment">🛠 Прикажи лабораториска опрема</a></li>
-        <li><a href="/reports">📈 SQL Извештаи</a></li>
-        <li><a href="/test-db">🔍 Тестирај база</a></li>
-    </ul>
-    '''
+    # Ако сакаш логнатите веднаш да одат на Dashboard, одкоментирај ги 3-те линии подолу
+    # if 'user_id' in session:
+    #     return redirect(url_for('dashboard'))
+
+    return render_template(
+        'home.html',
+        is_logged=('user_id' in session),
+        user_name=session.get('user_name'),
+        role=session.get('role')  # 'student' или 'teacher'
+    )
+
 
 
@@ -655,8 +655,6 @@
 
 @app.route('/reports/adv/students_experiments_detailed')
+@require_login('teacher')
 def reports_adv_students_experiments_detailed():
-    if 'user_id' not in session or session.get('role') != 'teacher':
-        return redirect('/login')
-
     sql = """
         SELECT 
@@ -671,14 +669,9 @@
         JOIN experiment e ON up.experiment_id = e.experiment_id
         WHERE s.teacher_id = %s
-        ORDER BY full_name, participation_time DESC
+        ORDER BY u.user_name, up.participation_timestamp DESC
     """
     rows = DatabaseManager.execute_query(sql, (session['user_id'],)) or []
-
-    # Ако сакаш брзо да провериш дали има глобални податоци без филтер по професор:
-    if not rows and request.args.get('all') == '1':
-        sql_all = sql.replace("WHERE s.teacher_id = %s", "")
-        rows = DatabaseManager.execute_query(sql_all) or []
-
     return _render_generic("Детален извештај: студенти и експерименти", rows)
+
 
 @app.route('/reports/adv/experiment_participants')
Index: routes/api.py
===================================================================
--- routes/api.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
+++ routes/api.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -0,0 +1,35 @@
+from flask import Blueprint, request, jsonify
+from utils.database_manager import DatabaseManager
+import logging
+
+log = logging.getLogger(__name__)
+api_bp = Blueprint("api_bp", __name__)
+
+@api_bp.post("/api/simulate-reaction")
+def simulate_reaction():
+    try:
+        payload = request.get_json(silent=True) or {}
+        sym1 = (payload.get("element1") or "").strip()
+        sym2 = (payload.get("element2") or "").strip()
+
+        if not sym1 or not sym2:
+            return jsonify(success=False, message="Недостасуваат елементи."), 400
+        if sym1.upper() == sym2.upper():
+            return jsonify(success=False, message="Ист елемент од двете страни не е дозволено."), 200
+
+        rxn = DatabaseManager.get_reaction_by_symbols(sym1, sym2)
+        if not rxn:
+            return jsonify(success=False, message="Нема дефинирана реакција за оваа комбинација."), 200
+
+        return jsonify(
+            success=True,
+            reaction_id=rxn["reaction_id"],
+            product=rxn["product"],
+            conditions=rxn.get("conditions"),
+            elements=f"{sym1}+{sym2}",
+        ), 200
+
+    except Exception:
+        log.exception("/api/simulate-reaction failed")
+        # важно: враќаме JSON дури и на грешка, не HTML
+        return jsonify(success=False, message="Внатрешна серверска грешка."), 500
Index: routes/reaction_experiment.py
===================================================================
--- routes/reaction_experiment.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
+++ routes/reaction_experiment.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -0,0 +1,48 @@
+# SIMLAB/routes/reaction_experiment.py
+import logging
+from flask import Blueprint, request, jsonify
+from utils.database_manager import DatabaseManager
+
+
+bp = Blueprint("reaction_experiment", __name__, url_prefix="/api")
+log = logging.getLogger(__name__)
+
+@bp.post("/reaction-experiment")
+def create_rxn_exp():
+    data = request.get_json(silent=True) or {}
+
+    # задолжителни полиња
+    required = ["teacher_id", "element1_id", "element2_id"]
+    missing = [k for k in required if data.get(k) in (None, "", [])]
+    if missing:
+        return jsonify({"ok": False, "error": f"Недостасува: {', '.join(missing)}"}), 400
+
+    # нормализирај листа од equipment_ids ако ја има
+    equipment_ids = data.get("equipment_ids")
+    if equipment_ids is not None:
+        if not isinstance(equipment_ids, list):
+            return jsonify({"ok": False, "error": "equipment_ids мора да е листа од цели броеви"}), 400
+        try:
+            equipment_ids = [int(x) for x in equipment_ids]
+        except Exception:
+            return jsonify({"ok": False, "error": "equipment_ids содржи невалидни вредности"}), 400
+
+    try:
+        res = DatabaseManager.create_reaction_and_experiment(
+            teacher_id=int(data["teacher_id"]),
+            element1_id=int(data["element1_id"]),
+            element2_id=int(data["element2_id"]),
+            product=data.get("product"),
+            conditions=data.get("conditions"),
+            experiment_result=data.get("experiment_result"),
+            safety_warning=data.get("safety_warning"),
+            equipment_ids=equipment_ids,
+        )
+        if not res:
+            return jsonify({"ok": False, "error": "Креирањето не успеа"}), 500
+
+        return jsonify({"ok": True, **res}), 201
+
+    except Exception:
+        log.exception("create_rxn_exp failed")
+        return jsonify({"ok": False, "error": "Внатрешна грешка"}), 500
Index: routes/virtual_lab.py
===================================================================
--- routes/virtual_lab.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
+++ routes/virtual_lab.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -0,0 +1,121 @@
+# routes/virtual_lab.py
+from flask import Blueprint, render_template, request, jsonify, session
+from utils.database_manager import DatabaseManager  # <-- ако е на друго место, прилагоди
+
+bp = Blueprint("virtual_lab", __name__)
+
+# Паге со симулацијата
+@bp.get("/virtual-lab")
+def virtual_lab_page():
+    elements = DatabaseManager.get_all_elements() or []
+    return render_template("virtual_labaratory.html", elements=elements)
+
+# Хелпери
+def _find_reaction(e1_id: int, e2_id: int):
+    sql = """
+      SELECT r.*,
+             e1.symbol AS e1_symbol, e1.element_name AS e1_name, e1.hazard_type AS e1_hz,
+             e2.symbol AS e2_symbol, e2.element_name AS e2_name, e2.hazard_type AS e2_hz
+        FROM reaction r
+        JOIN elements e1 ON r.element1_id = e1.element_id
+        JOIN elements e2 ON r.element2_id = e2.element_id
+       WHERE (r.element1_id = %s AND r.element2_id = %s)
+          OR (r.element1_id = %s AND r.element2_id = %s)
+       LIMIT 1
+    """
+    rows = DatabaseManager.execute_query(sql, (e1_id, e2_id, e2_id, e1_id)) or []
+    return rows[0] if rows else None
+
+def _get_element(el_id: int):
+    return DatabaseManager.get_element_by_id(el_id) or {}
+
+def _hz_factor(hz: str | None) -> float:
+    if not hz:
+        return 1.0
+    hz = hz.lower()
+    if "flamm" in hz or "оган" in hz:
+        return 1.4
+    if "corros" in hz or "кисел" in hz or "короз" in hz:
+        return 1.25
+    if "toxic" in hz or "токс" in hz:
+        return 1.2
+    return 1.0
+
+def _simulate_curve(reactivity: float, duration_sec=60):
+    amb, k, cool = 25.0, 0.9, 0.05
+    t, T = 0, amb
+    times, temps = [], []
+    while t <= duration_sec:
+        times.append(t); temps.append(T)
+        dT = k*reactivity - cool*(T - amb)
+        T = T + dT
+        t += 1
+    return times, temps
+
+# API: симулација
+@bp.post("/api/simulate-reaction")
+def simulate_reaction():
+    data = request.get_json(force=True)
+    e1 = int(data.get("element1_id"))
+    e2 = int(data.get("element2_id"))
+    amount = float(data.get("amount") or 1.0)
+
+    rxn = _find_reaction(e1, e2)
+    el1 = _get_element(e1)
+    el2 = _get_element(e2)
+
+    # едноставен (дидактички) модел за реактивност
+    an1 = el1.get("atomic_number") or 10
+    an2 = el2.get("atomic_number") or 10
+    hz = _hz_factor(el1.get("hazard_type")) * _hz_factor(el2.get("hazard_type")) * (1.1 if rxn else 1.0)
+    reactivity = (an1 + an2) / 5.0 * hz * amount
+
+    times, temps = _simulate_curve(reactivity, duration_sec=60)
+
+    return jsonify({
+        "ok": True,
+        "reaction": {
+            "found": bool(rxn),
+            "reaction_id": rxn.get("reaction_id") if rxn else None,
+            "product": rxn.get("product") if rxn else None,
+            "conditions": rxn.get("conditions") if rxn else None,
+            "e1": {"id": e1, "symbol": el1.get("symbol"), "name": el1.get("element_name")},
+            "e2": {"id": e2, "symbol": el2.get("symbol"), "name": el2.get("element_name")},
+        },
+        "series": {"time": times, "temperature": temps}
+    })
+
+# API: зачувување експеримент + учество
+@bp.post("/save-experiment")
+def save_experiment():
+    """
+    Очекува JSON: reaction_id, result, safety_warning
+    Креира ред во experiment и логира во userparticipatesinexperiment за тековниот user.
+    """
+    data = request.get_json(force=True)
+    reaction_id = int(data.get("reaction_id"))
+    result = data.get("result") or "Виртуелна симулација"
+    safety = data.get("safety_warning") or None
+
+    # user од сесија (прилагоди на твојата апликација)
+    user = session.get("user") or {}
+    user_id = user.get("user_id")
+
+    if not user_id:
+        return jsonify({"success": False, "message": "Немаш активна сесија."}), 401
+
+    me = DatabaseManager.get_user_by_id(user_id)  # дава role и teacher_id ако е студент
+    if not me:
+        return jsonify({"success": False, "message": "Корисникот не е најден."}), 400
+
+    # teacher_id за experiment: ако си teacher -> самиот, ако си student -> неговиот teacher
+    teacher_id = me.get("user_id") if me.get("role") == "teacher" else me.get("teacher_id")
+    if not teacher_id:
+        return jsonify({"success": False, "message": "Недостасува teacher_id за експеримент."}), 400
+
+    exp_id = DatabaseManager.insert_experiment(teacher_id, reaction_id, result, safety)
+    if not exp_id:
+        return jsonify({"success": False, "message": "Креирањето експеримент не успеа."}), 500
+
+    DatabaseManager.track_experiment_participation(user_id, exp_id)
+    return jsonify({"success": True, "experiment_id": exp_id})
Index: templates/add_element.html
===================================================================
--- templates/add_element.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/add_element.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,74 +3,141 @@
 
 {% block content %}
-<div class="row justify-content-center">
-    <div class="col-md-8">
-        <div class="card">
-            <div class="card-header">
-                <h3>Додај нов хемиски елемент</h3>
+<style>
+  .hero{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .pill{width:54px;height:54px;border-radius:14px;background:#ffffff22;display:flex;align-items:center;justify-content:center;font-weight:900;font-size:20px}
+  .type-badge{background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;font-weight:600;letter-spacing:.2px}
+  .wrap{display:grid;grid-template-columns:1.35fr .85fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){.wrap{grid-template-columns:1fr}}
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .muted{color:#6c757d}
+  .chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;margin:4px;border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;cursor:pointer;border:1px solid rgba(63,81,181,.25);user-select:none;font-size:.9rem}
+  .sticky-actions{position:sticky;bottom:0;background:#fff;border-top:1px solid #eef1f4;padding:12px 0;margin-top:8px}
+</style>
+
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div class="pill" id="sym-pill">—</div>
+    <div>
+      <h2 class="mb-0 text-truncate">Додај нов хемиски елемент</h2>
+      <div class="small opacity-75">Внеси основни податоци и безбедност</div>
+    </div>
+  </div>
+  <div class="d-flex align-items-center gap-2 flex-wrap">
+    <span class="type-badge">Полиња со <b>*</b> се задолжителни</span>
+    <a href="/elements" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-list"></i> Листа</a>
+  </div>
+</div>
+
+<div class="wrap">
+  <!-- Лево: форма -->
+  <div class="card block">
+    <div class="card-body">
+      <h5 class="section-title"><i class="bi bi-plus-circle"></i> Податоци за елемент</h5>
+      {% if error %}<div class="alert alert-danger">{{ error }}</div>{% endif %}
+
+      <form method="POST" id="element-form" novalidate>
+        <div class="row g-3">
+          <div class="col-md-4">
+            <label class="form-label">Симбол *</label>
+            <input type="text" class="form-control" name="symbol" id="symbol"
+                   maxlength="3" required pattern="^[A-Za-z]{1,3}$" placeholder="Na, Cl, Al...">
+            <div class="form-text">1–3 букви, ќе се запише како големи.</div>
+          </div>
+          <div class="col-md-8">
+            <label class="form-label">Име на елемент *</label>
+            <input type="text" class="form-control" name="name" id="el-name" required placeholder="Натриум">
+          </div>
+
+          <div class="col-md-4">
+            <label class="form-label">Атомски број *</label>
+            <input type="number" class="form-control" name="atomic_number" id="el-num" min="1" max="118" required>
+          </div>
+          <div class="col-md-4">
+            <label class="form-label">Атомска маса *</label>
+            <div class="input-group">
+              <input type="number" step="0.0001" class="form-control" name="atomic_weight" id="el-weight" required>
+              <span class="input-group-text">u</span>
             </div>
-            <div class="card-body">
-                {% if error %}
-                    <div class="alert alert-danger">{{ error }}</div>
-                {% endif %}
-                
-                <form method="POST">
-                    <div class="row">
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="symbol" class="form-label">Симбол</label>
-                                <input type="text" class="form-control" name="symbol" maxlength="2" required>
-                            </div>
-                        </div>
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="name" class="form-label">Име на елемент</label>
-                                <input type="text" class="form-control" name="name" required>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="row">
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="atomic_number" class="form-label">Атомски број</label>
-                                <input type="number" class="form-control" name="atomic_number" min="1" max="118" required>
-                            </div>
-                        </div>
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="atomic_weight" class="form-label">Атомска маса</label>
-                                <input type="number" step="0.001" class="form-control" name="atomic_weight" required>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="row">
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="melting_point" class="form-label">Точка на топење (°C)</label>
-                                <input type="number" step="0.1" class="form-control" name="melting_point">
-                            </div>
-                        </div>
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="boiling_point" class="form-label">Точка на вриење (°C)</label>
-                                <input type="number" step="0.1" class="form-control" name="boiling_point">
-                            </div>
-                        </div>
-                    </div>
-                    <div class="mb-3">
-                        <label for="hazard_type" class="form-label">Тип на опасност</label>
-                        <input type="text" class="form-control" name="hazard_type" maxlength="50" placeholder="Корозивен, Токсичен, Експлозивен...">
-                        <small class="form-text text-muted">Kраток опис на ризикот</small>
-                    </div>
-                    <div class="mb-3">
-                        <label for="description" class="form-label">Опис</label>
-                        <textarea class="form-control" name="description" rows="3"></textarea>
-                    </div>
-                    
-                    <button type="submit" class="btn btn-success">Додај елемент</button>
-                    <a href="/dashboard" class="btn btn-secondary">Откажи</a>
-                </form>
+          </div>
+          <div class="col-md-4"></div>
+
+          <div class="col-md-6">
+            <label class="form-label">Точка на топење (°C)</label>
+            <input type="number" step="0.1" class="form-control" name="melting_point" placeholder="опц.">
+          </div>
+          <div class="col-md-6">
+            <label class="form-label">Точка на вриење (°C)</label>
+            <input type="number" step="0.1" class="form-control" name="boiling_point" placeholder="опц.">
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Тип на опасност</label>
+            <input type="text" class="form-control" name="hazard_type" id="hazard" maxlength="50" placeholder="Нема опасност / Корозивно / Токсично ...">
+            <div class="form-text">Брз избор:</div>
+            <div>
+              <span class="chip" onclick="pickHazard('Нема опасност')">✔ Нема опасност</span>
+              <span class="chip" onclick="pickHazard('Корозивно')">⚠ Корозивно</span>
+              <span class="chip" onclick="pickHazard('Токсично')">☠ Токсично</span>
+              <span class="chip" onclick="pickHazard('Запалливо')">🔥 Запалливо</span>
+              <span class="chip" onclick="pickHazard('Иритант')">❗ Иритант</span>
             </div>
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Опис</label>
+            <textarea class="form-control" name="description" rows="4" placeholder="Краток опис, својства, забелешки..."></textarea>
+          </div>
         </div>
+
+        <div class="sticky-actions d-flex justify-content-between align-items-center">
+          <a href="/elements" class="btn btn-outline-secondary"><i class="bi bi-arrow-left"></i> Откажи</a>
+          <button type="submit" class="btn btn-success"><i class="bi bi-check2-circle"></i> Додај елемент</button>
+        </div>
+      </form>
     </div>
+  </div>
+
+  <!-- Десно: жив преглед -->
+  <div class="card block">
+    <div class="card-body">
+      <h6 class="section-title"><i class="bi bi-magic"></i> Жив преглед</h6>
+      <div class="d-flex align-items-center gap-3 mb-3">
+        <div class="pill" id="preview-pill">—</div>
+        <div>
+          <div class="fw-bold" id="preview-name">Име на елемент</div>
+          <div class="small muted">№ <span id="preview-atomic">—</span> • <span id="preview-weight">—</span> u</div>
+        </div>
+      </div>
+      <hr class="my-3"/>
+      <h6 class="section-title"><i class="bi bi-lightbulb"></i> Совети</h6>
+      <ul class="small mb-0">
+        <li>Провери уникатност на симболот (Na ≠ N).</li>
+        <li>Атомската маса запиши со децимали (на пр. 22.9898).</li>
+      </ul>
+    </div>
+  </div>
 </div>
+
+<script>
+  const sym = document.getElementById('symbol');
+  const nameEl = document.getElementById('el-name');
+  const numEl = document.getElementById('el-num');
+  const wEl   = document.getElementById('el-weight');
+
+  function updatePreview(){
+    const s = sym.value || '—';
+    document.getElementById('sym-pill').textContent = s;
+    document.getElementById('preview-pill').textContent = s;
+    document.getElementById('preview-name').textContent = nameEl.value || 'Име на елемент';
+    document.getElementById('preview-atomic').textContent = numEl.value || '—';
+    document.getElementById('preview-weight').textContent = wEl.value || '—';
+  }
+  function pickHazard(txt){ const hz=document.getElementById('hazard'); hz.value=txt; hz.focus(); }
+  sym.addEventListener('input', ()=>{ sym.value = sym.value.toUpperCase(); updatePreview(); });
+  nameEl.addEventListener('input', updatePreview);
+  numEl.addEventListener('input', updatePreview);
+  wEl.addEventListener('input', updatePreview);
+  updatePreview();
+</script>
 {% endblock %}
Index: templates/add_equipment.html
===================================================================
--- templates/add_equipment.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/add_equipment.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,43 +3,98 @@
 
 {% block content %}
-<div class="row justify-content-center">
-    <div class="col-md-8">
-        <div class="card">
-            <div class="card-header">
-                <h3>Додај нова лабораториска опрема</h3>
-            </div>
-            <div class="card-body">
-                {% if error %}
-                    <div class="alert alert-danger">{{ error }}</div>
-                {% endif %}
-                
-                <form method="POST">
-                    <div class="mb-3">
-                        <label for="name" class="form-label">Име на опремата</label>
-                        <input type="text" class="form-control" name="name" maxlength="50" required>
-                        <small class="form-text text-muted">Максимум 50 карактери</small>
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="type" class="form-label">Тип на опрема</label>
-                        <input type="text" class="form-control" name="type" maxlength="50" placeholder="Стаклена опрема, Мерни инструменти...">
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="description" class="form-label">Опис</label>
-                        <textarea class="form-control" name="description" rows="3" placeholder="Детален опис за употребата на опремата..."></textarea>
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="safety_info" class="form-label">Безбедносни информации</label>
-                        <textarea class="form-control" name="safety_info" rows="2" placeholder="Безбедносни мерки при користење..."></textarea>
-                    </div>
-                    
-                    <button type="submit" class="btn btn-success">Додај опрема</button>
-                    <a href="/dashboard" class="btn btn-secondary">Откажи</a>
-                </form>
-            </div>
+<style>
+  .hero{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .pill{width:42px;height:42px;border-radius:12px;background:#ffffff22;display:flex;align-items:center;justify-content:center;font-size:20px}
+  .type-badge{background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;font-weight:600;letter-spacing:.2px}
+  .wrap{display:grid;grid-template-columns:1.35fr .85fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){.wrap{grid-template-columns:1fr}}
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .muted{color:#6c757d}
+  .chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;margin:4px;border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;cursor:pointer;border:1px solid rgba(63,81,181,.25);user-select:none;font-size:.9rem}
+  .sticky-actions{position:sticky;bottom:0;background:#fff;border-top:1px solid #eef1f4;padding:12px 0;margin-top:8px}
+</style>
+
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div class="pill"><i class="bi bi-tools"></i></div>
+    <div>
+      <h2 class="mb-0 text-truncate">Додај нова лабораториска опрема</h2>
+      <div class="small opacity-75">Име, тип, опис и безбедност</div>
+    </div>
+  </div>
+  <div class="d-flex align-items-center gap-2">
+    <span class="type-badge">Полиња со <b>*</b> се задолжителни</span>
+    <a href="/equipment" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-list"></i> Листа</a>
+  </div>
+</div>
+
+<div class="wrap">
+  <!-- Лево: форма -->
+  <div class="card block">
+    <div class="card-body">
+      <h5 class="section-title"><i class="bi bi-plus-circle"></i> Податоци за опрема</h5>
+      {% if error %}<div class="alert alert-danger">{{ error }}</div>{% endif %}
+
+      <form method="POST" id="equip-form" novalidate>
+        <div class="mb-3">
+          <label class="form-label">Име на опремата *</label>
+          <input type="text" class="form-control" name="name" id="eq-name" maxlength="50" required placeholder="Пипета, Термометар...">
+          <small class="form-text text-muted">Максимум 50 карактери.</small>
         </div>
+
+        <div class="mb-2">
+          <label class="form-label">Тип на опрема</label>
+          <input type="text" class="form-control" name="type" id="eq-type" maxlength="50" placeholder="Стакларија, Мерење, Загревање...">
+          <div class="form-text">Брз избор:</div>
+          <div>
+            <span class="chip" onclick="pickType('Стакларија')">Стакларија</span>
+            <span class="chip" onclick="pickType('Мерење')">Мерење</span>
+            <span class="chip" onclick="pickType('Загревање')">Загревање</span>
+            <span class="chip" onclick="pickType('Безбедност')">Безбедност</span>
+            <span class="chip" onclick="pickType('Општа')">Општа</span>
+          </div>
+        </div>
+
+        <div class="mb-3">
+          <label class="form-label">Опис</label>
+          <textarea class="form-control" name="description" id="eq-desc" rows="4" placeholder="Краток опис, употреба, напомени..."></textarea>
+        </div>
+
+        <div class="mb-1">
+          <label class="form-label">Безбедносни информации</label>
+          <textarea class="form-control" name="safety_info" id="eq-safe" rows="3" placeholder="ППЕ, чистење, складирање..."></textarea>
+        </div>
+
+        <div class="sticky-actions d-flex justify-content-between align-items-center">
+          <a href="/equipment" class="btn btn-outline-secondary"><i class="bi bi-arrow-left"></i> Откажи</a>
+          <button type="submit" class="btn btn-success"><i class="bi bi-check2-circle"></i> Додај опрема</button>
+        </div>
+      </form>
     </div>
+  </div>
+
+  <!-- Десно: жив преглед / брзи факти -->
+  <div class="card block">
+    <div class="card-body">
+      <h6 class="section-title"><i class="bi bi-magic"></i> Жив преглед</h6>
+      <div class="mb-2"><b>Име:</b> <span id="prev-name" class="fw-semibold">—</span></div>
+      <div class="mb-2"><b>Тип:</b> <span id="prev-type" class="fw-semibold">—</span></div>
+
+      <hr class="my-3"/>
+      <h6 class="section-title"><i class="bi bi-lightbulb"></i> Совети</h6>
+      <ul class="small mb-0">
+        <li>Конзистентен тип (за филтри и извештаи).</li>
+        <li>Во опис: употреба + специфични напомени.</li>
+        <li>Безбедност: кратко и применливо (ППЕ, чистење, складирање).</li>
+      </ul>
+    </div>
+  </div>
 </div>
+
+<script>
+  function pickType(txt){ const t=document.getElementById('eq-type'); t.value=txt; t.focus(); document.getElementById('prev-type').textContent=txt; }
+  document.getElementById('eq-name').addEventListener('input', e=>{ document.getElementById('prev-name').textContent=e.target.value||'—'; });
+  document.getElementById('eq-type').addEventListener('input', e=>{ document.getElementById('prev-type').textContent=e.target.value||'—'; });
+</script>
 {% endblock %}
Index: templates/add_reaction.html
===================================================================
--- templates/add_reaction.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/add_reaction.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,128 +3,191 @@
 
 {% block content %}
-<div class="row">
-    <div class="col-md-10 offset-md-1">
-        <div class="card">
-            <div class="card-header bg-primary text-white">
-                <h4>Додај нова реакција и експеримент</h4>
+<style>
+  .hero{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .pill{width:48px;height:48px;border-radius:12px;background:#ffffff22;display:flex;align-items:center;justify-content:center;font-size:20px}
+  .type-badge{background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;font-weight:600}
+  .wrap{display:grid;grid-template-columns:1.2fr .8fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){.wrap{grid-template-columns:1fr}}
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;margin:4px;border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;cursor:pointer;border:1px solid rgba(63,81,181,.25);user-select:none;font-size:.9rem}
+  .eq-preview{font-weight:800;font-size:18px;background:#f8f9fa;border:1px solid #edf0f4;border-radius:12px;padding:10px 12px}
+  .sticky-actions{position:sticky;bottom:0;background:#fff;border-top:1px solid #eef1f4;padding:12px 0;margin-top:8px}
+  .equip-grid{max-height:340px;overflow:auto;border:1px solid #eef1f4;border-radius:12px;padding:10px}
+</style>
+
+<!-- HERO -->
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div class="pill"><i class="bi bi-diagram-3"></i></div>
+    <div>
+      <h2 class="mb-0 text-truncate">Додај нова реакција</h2>
+      <div class="small opacity-75">Реактанти, услови и поврзан експеримент</div>
+    </div>
+  </div>
+  <div class="d-flex align-items-center gap-2">
+    <span class="type-badge">Полиња со <b>*</b> се задолжителни</span>
+    <a href="/reactions" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-list"></i> Сите реакции</a>
+  </div>
+</div>
+
+<div class="wrap">
+  <!-- ЛЕВО: Реактанти + Реакција -->
+  <div class="card block">
+    <div class="card-body">
+      {% if error %}<div class="alert alert-danger">{{ error }}</div>{% endif %}
+      <h5 class="section-title"><i class="bi bi-flask"></i> Реактанти</h5>
+
+      <form method="POST" id="add-reaction-form" novalidate>
+        <div class="row g-3">
+          <div class="col-md-6">
+            <label class="form-label">Прв елемент *</label>
+            <select class="form-select" name="element1_id" id="element1_id" required>
+              <option value="">-- Избери елемент --</option>
+              {% for element in elements %}
+              <option value="{{ element.element_id }}"
+                      data-symbol="{{ element.symbol }}"
+                      data-name="{{ element.element_name }}">
+                {{ element.symbol }} — {{ element.element_name }}
+              </option>
+              {% endfor %}
+            </select>
+          </div>
+          <div class="col-md-6">
+            <label class="form-label">Втор елемент *</label>
+            <select class="form-select" name="element2_id" id="element2_id" required>
+              <option value="">-- Избери елемент --</option>
+              {% for element in elements %}
+              <option value="{{ element.element_id }}"
+                      data-symbol="{{ element.symbol }}"
+                      data-name="{{ element.element_name }}">
+                {{ element.symbol }} — {{ element.element_name }}
+              </option>
+              {% endfor %}
+            </select>
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Преглед на равенка</label>
+            <div class="eq-preview" id="eqPreview">A + B → ___</div>
+          </div>
+
+          <div class="col-md-6">
+            <label class="form-label">Продукт (формула)</label>
+            <input type="text" class="form-control" name="product" id="product" placeholder="H2O, NaCl, CO2">
+          </div>
+          <div class="col-md-6">
+            <label class="form-label">Услови</label>
+            <textarea class="form-control" name="conditions" id="conditions" rows="1" placeholder="Стандардни услови">Стандардни услови</textarea>
+            <div class="form-text">Дополнителни параметри подолу ќе се додадат автоматски.</div>
+          </div>
+
+          <div class="col-md-4">
+            <input type="text" class="form-control" name="temperature" id="temperature" placeholder="Темп. °C">
+          </div>
+          <div class="col-md-4">
+            <input type="text" class="form-control" name="pressure" id="pressure" placeholder="Притисок (atm)">
+          </div>
+          <div class="col-md-4">
+            <input type="text" class="form-control" name="catalyst" id="catalyst" placeholder="Катализатор">
+          </div>
+
+          <div class="col-12">
+            <div class="form-text">Брзи услови:</div>
+            <div>
+              <span class="chip" onclick="addCond('Собна температура')">Собна температура</span>
+              <span class="chip" onclick="addCond('Суви услови')">Суви услови</span>
+              <span class="chip" onclick="addCond('Инертна атмосфера (Ar)')">Инертна атмосфера (Ar)</span>
+              <span class="chip" onclick="addCond('Светлина')">Светлина</span>
+              <span class="chip" onclick="addCond('Без катализатор')">Без катализатор</span>
             </div>
-            <div class="card-body">
-                {% if error %}
-                <div class="alert alert-danger">{{ error }}</div>
-                {% endif %}
-                
-                <form method="POST">
-                    <div class="row">
-                        <div class="col-md-6">
-                            <h5 class="text-primary mb-3">Реактанти</h5>
-                            <div class="form-group mb-3">
-                                <label for="element1_id">Прв елемент:</label>
-                                <select class="form-control" name="element1_id" id="element1_id" required>
-                                    <option value="">-- Избери елемент --</option>
-                                    {% for element in elements %}
-                                    <option value="{{ element.element_id }}">{{ element.symbol }} - {{ element.element_name }}</option>
-                                    {% endfor %}
-                                </select>
-                            </div>
-                            <div class="form-group mb-3">
-                                <label for="element2_id">Втор елемент:</label>
-                                <select class="form-control" name="element2_id" id="element2_id" required>
-                                    <option value="">-- Избери елемент --</option>
-                                    {% for element in elements %}
-                                    <option value="{{ element.element_id }}">{{ element.symbol }} - {{ element.element_name }}</option>
-                                    {% endfor %}
-                                </select>
-                            </div>
-                        </div>
-                        
-                        <div class="col-md-6">
-                            <h5 class="text-success mb-3">Реакција</h5>
-                            <div class="form-group mb-3">
-                                <label for="product">Продукт (формула):</label>
-                                <input type="text" class="form-control" name="product" id="product" placeholder="пр. H2O, NaCl, CO2">
-                            </div>
-                            <div class="form-group mb-3">
-                                <label for="conditions">Услови:</label>
-                                <textarea class="form-control" name="conditions" id="conditions" rows="2" placeholder="Општи услови">Стандардни услови</textarea>
-                            </div>
-                            <div class="row">
-                                <div class="col-md-4 mb-2">
-                                    <input type="text" class="form-control" name="temperature" placeholder="Темп. °C">
-                                </div>
-                                <div class="col-md-4 mb-2">
-                                    <input type="text" class="form-control" name="pressure" placeholder="Притисок (atm)">
-                                </div>
-                                <div class="col-md-4 mb-2">
-                                    <input type="text" class="form-control" name="catalyst" placeholder="Катализатор">
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                    
-                    <hr>
-                    
-                    <div class="row">
-                        <div class="col-md-6">
-                            <h5 class="text-info mb-3">Експеримент</h5>
-                            <div class="form-group mb-3">
-                                <label for="experiment_result">Опис на експериментот:</label>
-                                <textarea class="form-control" name="experiment_result" id="experiment_result" rows="3" placeholder="Опишете чекори, забелешки, очекуван тек на експериментот..."></textarea>
-                            </div>
-                        </div>
-                        
-                        <div class="col-md-6">
-                            <h5 class="text-warning mb-3">Безбедност</h5>
-                            <div class="form-group mb-3">
-                                <label for="safety_warning">Безбедносни предупредувања:</label>
-                                <textarea class="form-control" name="safety_warning" id="safety_warning" rows="3">Стандардни безбедносни мерки</textarea>
-                            </div>
-                        </div>
-                    </div>
-                    
-                    <hr>
-                    
-                    <div class="row">
-                        <div class="col-12">
-                            <h5 class="text-secondary mb-3">Лабораториска опрема</h5>
-                            <div class="form-group">
-                                {% for item in equipment %}
-                                <div class="form-check">
-                                    <input class="form-check-input" type="checkbox" name="equipment_ids" id="eq{{ item.equipment_id }}" value="{{ item.equipment_id }}">
-                                    <label class="form-check-label" for="eq{{ item.equipment_id }}">
-                                        {{ item.equipment_name }} ({{ item.type }})
-                                    </label>
-                                </div>
-                                {% endfor %}
-                            </div>
-                        </div>
-                    </div>
-                    
-                    <div class="alert alert-info mt-3">
-                        <strong>Напомена:</strong> Со креирање на реакција, автоматски се додава и експеримент кој студентите можат да го извршуваат во виртуелната лабораторија.
-                    </div>
-                    
-                    <div class="text-center">
-                        <button type="submit" class="btn btn-success">
-                            <i class="bi bi-plus-circle"></i> Креирај
-                        </button>
-                        <a href="/reactions" class="btn btn-secondary">Откажи</a>
-                    </div>
-                </form>
-            </div>
+          </div>
         </div>
+
+        <hr class="my-4"/>
+
+        <h5 class="section-title"><i class="bi bi-journal-text"></i> Експеримент</h5>
+        <div class="mb-3">
+          <label class="form-label">Опис на експериментот</label>
+          <textarea class="form-control" name="experiment_result" id="experiment_result" rows="3"
+                    placeholder="Чекори, забелешки, очекуван тек..."></textarea>
+        </div>
+
+        <h5 class="section-title mt-3"><i class="bi bi-shield-exclamation"></i> Безбедност</h5>
+        <div class="mb-3">
+          <label class="form-label">Безбедносни предупредувања</label>
+          <textarea class="form-control" name="safety_warning" id="safety_warning" rows="2">Стандардни безбедносни мерки</textarea>
+        </div>
+
+        <h5 class="section-title mt-3"><i class="bi bi-tools"></i> Лабораториска опрема</h5>
+        <div class="equip-grid">
+          {% for item in equipment %}
+          <div class="form-check">
+            <input class="form-check-input" type="checkbox" name="equipment_ids" id="eq{{ item.equipment_id }}" value="{{ item.equipment_id }}">
+            <label class="form-check-label" for="eq{{ item.equipment_id }}">
+              {{ item.equipment_name }}{% if item.type %} ({{ item.type }}){% endif %}
+            </label>
+          </div>
+          {% endfor %}
+        </div>
+
+        <div class="alert alert-info mt-3">
+          <strong>Напомена:</strong> Со креирање на реакција, автоматски се додава и експеримент кој студентите можат да го извршуваат во виртуелната лабораторија.
+        </div>
+
+        <div class="sticky-actions d-flex justify-content-between align-items-center">
+          <a href="/reactions" class="btn btn-outline-secondary"><i class="bi bi-arrow-left"></i> Откажи</a>
+          <button type="submit" class="btn btn-success"><i class="bi bi-plus-circle"></i> Креирај</button>
+        </div>
+      </form>
     </div>
+  </div>
+
+  <!-- ДЕСНО: Помош и брз преглед -->
+  <div class="card block">
+    <div class="card-body">
+      <h6 class="section-title"><i class="bi bi-magic"></i> Брз преглед</h6>
+      <div class="eq-preview" id="eqPreviewSide">A + B → ___</div>
+
+      <hr class="my-3"/>
+      <h6 class="section-title"><i class="bi bi-lightbulb"></i> Совети</h6>
+      <ul class="small mb-0">
+        <li>Елементите мора да бидат различни.</li>
+        <li>„Темп./Притисок/Катализатор“ ќе се додадат кон <em>Услови</em> на backend (не дуплирај рачно).</li>
+        <li>Продуктот може да остане празен ако е непознат.</li>
+      </ul>
+    </div>
+  </div>
 </div>
 
 <script>
-function validateElements() {
-    const elem1 = document.getElementById('element1_id').value;
-    const elem2 = document.getElementById('element2_id').value;
-    if (elem1 && elem2 && elem1 === elem2) {
-        alert('Мора да изберете два различни елементи!');
-        document.getElementById('element2_id').value = '';
+  function getSelText(sel){ const o=sel.options[sel.selectedIndex]; return o? (o.dataset.symbol||''):''; }
+  function updateEq(){
+    const a = getSelText(document.getElementById('element1_id')) || 'A';
+    const b = getSelText(document.getElementById('element2_id')) || 'B';
+    const p = (document.getElementById('product').value||'___').trim() || '___';
+    const eq = `${a} + ${b} → ${p}`;
+    document.getElementById('eqPreview').textContent = eq;
+    document.getElementById('eqPreviewSide').textContent = eq;
+  }
+  function addCond(txt){
+    const ta = document.getElementById('conditions');
+    const val = ta.value.trim();
+    ta.value = val ? (val + '; ' + txt) : txt;
+    ta.focus();
+  }
+  function validateDiff(){
+    const e1=document.getElementById('element1_id'), e2=document.getElementById('element2_id');
+    if(e1.value && e2.value && e1.value===e2.value){
+      alert('Мора да изберете два различни елементи!');
+      e2.value=''; updateEq(); return false;
     }
-}
-document.getElementById('element1_id').addEventListener('change', validateElements);
-document.getElementById('element2_id').addEventListener('change', validateElements);
+    return true;
+  }
+  ['element1_id','element2_id','product'].forEach(id=>{
+    document.getElementById(id).addEventListener('change', ()=>{ validateDiff(); updateEq(); });
+    document.getElementById(id).addEventListener('input',  ()=>{ updateEq(); });
+  });
+  updateEq();
 </script>
 {% endblock %}
Index: templates/base.html
===================================================================
--- templates/base.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/base.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -8,18 +8,24 @@
 </head>
 <body>
-    <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
-        <div class="container">
-            <a class="navbar-brand" href="/">🧪 SIMLAB</a>
-            <div class="navbar-nav ms-auto">
-                {% if session.user_id %}
-                    <span class="navbar-text me-3">Добредојде, {{ session.user_name }}</span>
-                    <a class="nav-link" href="/logout">Одјави се</a>
-                {% else %}
-                    <a class="nav-link" href="/login">Најави се</a>
-                    <a class="nav-link" href="/register">Регистрирај се</a>
-                {% endif %}
-            </div>
-        </div>
-    </nav>
+    <nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-3 shadow-sm">
+  <div class="container">
+    <a class="navbar-brand fw-bold" href="/">🧪 SIMLAB</a>
+    <button class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navMain">
+      <span class="navbar-toggler-icon"></span>
+    </button>
+    <div id="navMain" class="collapse navbar-collapse">
+      <ul class="navbar-nav me-auto">
+        <li class="nav-item"><a class="nav-link" href="/dashboard">Dashboard</a></li>
+        <li class="nav-item"><a class="nav-link" href="/elements">Елементи</a></li>
+        <li class="nav-item"><a class="nav-link" href="/equipment">Опрема</a></li>
+        <li class="nav-item"><a class="nav-link" href="/laboratory">Лабораторија</a></li>
+      </ul>
+      <div class="d-flex align-items-center gap-2">
+        <span class="text-white-50 small d-none d-md-inline">{{ session.user_name }}</span>
+        <a class="btn btn-outline-light btn-sm" href="/logout">Одјава</a>
+      </div>
+    </div>
+  </div>
+</nav>
 
     <div class="container mt-4">
Index: templates/dashboard_student.html
===================================================================
--- templates/dashboard_student.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/dashboard_student.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -1,79 +1,148 @@
 {% extends "base.html" %}
-{% block title %}Dashboard - Студент{% endblock %}
+{% block title %}Dashboard · Студент{% endblock %}
 
 {% block content %}
-<div class="row">
-    <div class="col-12">
-        <h2>Добредојде, {{ user_name }}!</h2>
-        <p class="lead">Студентска контролна табла</p>
+<style>
+  :root{
+    --grad-1: linear-gradient(135deg,#6a11cb 0%,#2575fc 100%);
+    --grad-2: linear-gradient(135deg,#00c6ff 0%,#0072ff 100%);
+    --grad-3: linear-gradient(135deg,#f7971e 0%,#ffd200 100%);
+    --grad-4: linear-gradient(135deg,#11998e 0%,#38ef7d 100%);
+  }
+  .hero{
+    background: var(--grad-1); color:#fff; border-radius:18px; padding:24px 28px;
+    box-shadow:0 14px 30px rgba(37,117,252,.25);
+  }
+  .stat-card{
+    border:0; border-radius:16px; color:#fff; overflow:hidden;
+    box-shadow:0 12px 28px rgba(0,0,0,.12);
+  }
+  .stat-card .card-body{padding:18px 18px 16px}
+  .stat-card h2{font-weight:800; margin:0}
+  .hover-lift{transition:transform .15s ease, box-shadow .15s ease}
+  .hover-lift:hover{transform:translateY(-2px); box-shadow:0 16px 34px rgba(0,0,0,.12)}
+  .list-clean .list-group-item{border:0; padding:.6rem .75rem}
+</style>
+
+<div class="hero mb-4">
+  <div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
+    <div>
+      <h2 class="mb-1">Добредојде, {{ user_name }} 👋</h2>
+      <div class="opacity-75">Студентска контролна табла · брз пристап до лабораторија, елементи и твои активности</div>
     </div>
+    <div>
+      <a href="/laboratory" class="btn btn-light btn-lg fw-semibold shadow-sm">
+        ⚗️ Отвори виртуелна лабораторија
+      </a>
+    </div>
+  </div>
 </div>
 
-<!-- Главни картички -->
-<div class="row mt-4">
-    <div class="col-md-4 mb-3">
-        <div class="card h-100">
-            <div class="card-header bg-primary text-white">
-                <h5><i class="bi bi-flask"></i> Хемиски елементи</h5>
-            </div>
-            <div class="card-body">
-                <p>Истражете ги достапните хемиски елементи и нивните својства</p>
-                <a href="/elements" class="btn btn-primary">Прегледај елементи</a>
-            </div>
-        </div>
+<!-- STAT cards -->
+<div class="row g-3 mb-4">
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:var(--grad-2)">
+      <div class="card-body">
+        <div class="small opacity-75">Мои експерименти</div>
+        <h2 class="count-up" data-target="{{ stats.experiment_count or 0 }}">0</h2>
+      </div>
     </div>
-    
-    <div class="col-md-4 mb-3">
-        <div class="card h-100">
-            <div class="card-header bg-success text-white">
-                <h5><i class="bi bi-tools"></i> Лабораториска опрема</h5>
-            </div>
-            <div class="card-body">
-                <p>Запознајте се со достапната лабораториска опрема</p>
-                <a href="/equipment" class="btn btn-success">Прегледај опрема</a>
-            </div>
-        </div>
+  </div>
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:var(--grad-4)">
+      <div class="card-body">
+        <div class="small opacity-75">Различни реакции</div>
+        <h2 class="count-up" data-target="{{ stats.reaction_count or 0 }}">0</h2>
+      </div>
     </div>
-    
-    <div class="col-md-4 mb-3">
-        <div class="card h-100">
-            <div class="card-header bg-danger text-white">
-                <h5><i class="bi bi-radioactive"></i> Виртуелна лабораторија</h5>
-            </div>
-            <div class="card-body">
-                <p>Симулирајте хемиски реакции и учествувајте во експерименти</p>
-                <a href="/laboratory" class="btn btn-danger">Отвори лабораторија</a>
-            </div>
-        </div>
+  </div>
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:var(--grad-3)">
+      <div class="card-body">
+        <div class="small opacity-75">Прегледани елементи</div>
+        <h2 class="count-up" data-target="{{ stats.element_count or 0 }}">0</h2>
+      </div>
     </div>
+  </div>
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:linear-gradient(135deg,#ff512f,#dd2476)">
+      <div class="card-body">
+        <div class="small opacity-75">Прегледана опрема</div>
+        <h2 class="count-up" data-target="{{ stats.equipment_count or 0 }}">0</h2>
+      </div>
+    </div>
+  </div>
+</div>
+<br>
+<br>
+<!-- Quick sections -->
+<div class="row g-3">
+  <div class="col-lg-4">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-primary text-white"><i class="bi bi-flask"></i> Хемиски елементи</div>
+      <div class="card-body">
+        <p>Истражи својства и безбедносни информации.</p>
+        <a href="/elements" class="btn btn-primary">Прегледај елементи</a>
+      </div>
+    </div>
+  </div>
+  <div class="col-lg-4">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-success text-white"><i class="bi bi-tools"></i> Лабораториска опрема</div>
+      <div class="card-body">
+        <p>Провери упатства и безбедносни препораки.</p>
+        <a href="/equipment" class="btn btn-success">Прегледај опрема</a>
+      </div>
+    </div>
+  </div>
+  <div class="col-lg-4">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-danger text-white"><i class="bi bi-radioactive"></i> Виртуелна лабораторија</div>
+      <div class="card-body">
+        <p>Влечи 2 елементи и симулирај реакција.</p>
+        <a href="/laboratory" class="btn btn-danger">Отвори лабораторија</a>
+      </div>
+    </div>
+  </div>
+</div>
+<br>
+<br>
+<div class="row g-3 mt-1">
+  <div class="col-lg-6">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-warning text-dark"><i class="bi bi-journal-text"></i> Мои експерименти</div>
+      <div class="card-body">
+        <p>Историја на учества и резултати од експерименти.</p>
+        <a href="/my-experiments" class="btn btn-warning">Отвори листа</a>
+      </div>
+    </div>
+  </div>
+  <div class="col-lg-6">
+    <div class="card h-100 hover-lift">
+      <div class="card-header text-white" style="background:linear-gradient(135deg,#667eea,#764ba2)"><i class="bi bi-graph-up"></i> Мој напредок</div>
+      <div class="card-body">
+        <ul class="list-group list-clean">
+          <li class="list-group-item"><i class="bi bi-check-circle text-success me-1"></i> Експерименти: <b>{{ stats.experiment_count or 0 }}</b></li>
+          <li class="list-group-item"><i class="bi bi-check-circle text-success me-1"></i> Реакции: <b>{{ stats.reaction_count or 0 }}</b></li>
+          <li class="list-group-item"><i class="bi bi-check-circle text-success me-1"></i> Елементи видени: <b>{{ stats.element_count or 0 }}</b></li>
+        </ul>
+        <a href="/my-experiments" class="btn btn-outline-light mt-2">Види детално</a>
+      </div>
+    </div>
+  </div>
 </div>
 
-<!-- Втор ред картички -->
-<div class="row">
-    <div class="col-md-4 mb-3">
-        <div class="card h-100">
-            <div class="card-header bg-warning text-dark">
-                <h5><i class="bi bi-journal-text"></i> Мои експерименти</h5>
-            </div>
-            <div class="card-body">
-                <p>Прегледајте ги експериментите во кои сте учествувале</p>
-                <a href="/my-experiments" class="btn btn-warning">Види експерименти</a>
-            </div>
-        </div>
-    </div>
-    
-    
-    
-    <div class="col-md-4 mb-3">
-        <div class="card h-100">
-            <div class="card-header text-white" style="background: linear-gradient(45deg, #667eea, #764ba2);">
-                <h5><i class="bi bi-graph-up"></i> Мој напредок</h5>
-            </div>
-            <div class="card-body">
-                <p>Следете го вашиот напредок и активности</p>
-                <a href="/my-experiments" class="btn btn-secondary">Види напредок</a>
-            </div>
-        </div>
-    </div>
-</div>
+<script>
+// мал „count-up“ ефект за бројките
+document.querySelectorAll('.count-up').forEach(el=>{
+  const target = Number(el.dataset.target||0);
+  const dur = 600; const start = performance.now();
+  const step = t=>{
+    const p = Math.min(1,(t-start)/dur);
+    el.textContent = Math.round(target * p);
+    if(p<1) requestAnimationFrame(step);
+  };
+  requestAnimationFrame(step);
+});
+</script>
 {% endblock %}
Index: templates/dashboard_teacher.html
===================================================================
--- templates/dashboard_teacher.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/dashboard_teacher.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -1,22 +1,76 @@
 {% extends "base.html" %}
-{% block title %}Dashboard - Професор{% endblock %}
+{% block title %}Dashboard · Професор{% endblock %}
 
 {% block content %}
-<div class="row">
-  <div class="col-12">
-    <h2>Добредојде, {{ user_name }}!</h2>
-    <p class="lead">Професорска контролна табла</p>
+<style>
+  :root{
+    --grad-a: linear-gradient(135deg,#00b09b,#96c93d);
+    --grad-b: linear-gradient(135deg,#f7971e,#ffd200);
+    --grad-c: linear-gradient(135deg,#36d1dc,#5b86e5);
+    --grad-d: linear-gradient(135deg,#ff512f,#dd2476);
+  }
+  .hero{background:linear-gradient(135deg,#232526,#414345); color:#fff; border-radius:18px; padding:24px 28px}
+  .stat-card{border:0;border-radius:16px;color:#fff;overflow:hidden;box-shadow:0 12px 28px rgba(0,0,0,.12)}
+  .stat-card .card-body{padding:18px}
+  .stat-card h2{font-weight:800;margin:0}
+  .hover-lift{transition:transform .15s ease, box-shadow .15s ease}
+  .hover-lift:hover{transform:translateY(-2px); box-shadow:0 16px 34px rgba(0,0,0,.12)}
+</style>
+
+<div class="hero mb-4 d-flex flex-wrap align-items-center justify-content-between gap-2">
+  <div>
+    <h2 class="mb-1">Добредојде, {{ user_name }}</h2>
+    <div class="opacity-75">Професорска контролна табла · управување со содржини и следење активности</div>
+  </div>
+  <div class="d-flex gap-2">
+    <a href="/reactions/add" class="btn btn-light fw-semibold"> Нова реакција</a>
+    <a href="/laboratory" class="btn btn-outline-light">Лабораторија</a>
   </div>
 </div>
 
+<!-- STAT cards -->
+<div class="row g-3 mb-4">
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:var(--grad-a)">
+      <div class="card-body">
+        <div class="small opacity-75">Студенти</div>
+        <h2 class="count-up" data-target="{{ stats.student_count or 0 }}">0</h2>
+      </div>
+    </div>
+  </div>
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:var(--grad-b)">
+      <div class="card-body">
+        <div class="small opacity-75">Реакции</div>
+        <h2 class="count-up" data-target="{{ stats.reaction_count or 0 }}">0</h2>
+      </div>
+    </div>
+  </div>
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:var(--grad-c)">
+      <div class="card-body">
+        <div class="small opacity-75">Експерименти</div>
+        <h2 class="count-up" data-target="{{ stats.experiment_count or 0 }}">0</h2>
+      </div>
+    </div>
+  </div>
+  <div class="col-6 col-lg-3">
+    <div class="card stat-card hover-lift" style="background:var(--grad-d)">
+      <div class="card-body">
+        <div class="small opacity-75">Активности денес</div>
+        <h2 class="count-up" data-target="{{ stats.activity_count or 0 }}">0</h2>
+      </div>
+    </div>
+  </div>
+</div>
+<br>
+<br>
+
 <!-- Управување со содржина -->
-<div class="row mt-4">
-  <div class="col-md-3 mb-3">
-    <div class="card h-100">
-      <div class="card-header bg-primary text-white">
-        <h5><i class="bi bi-flask"></i> Хемиски елементи</h5>
-      </div>
-      <div class="card-body">
-        <p>Управување со хемиски елементи</p>
+<div class="row g-3">
+  <div class="col-lg-3">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-primary text-white"><i class="bi bi-flask"></i> Хемиски елементи</div>
+      <div class="card-body d-grid gap-2">
         <a href="/elements" class="btn btn-outline-primary btn-sm">Прегледај</a>
         <a href="/elements/add" class="btn btn-primary btn-sm">Додај нов</a>
@@ -24,12 +78,8 @@
     </div>
   </div>
-
-  <div class="col-md-3 mb-3">
-    <div class="card h-100">
-      <div class="card-header bg-success text-white">
-        <h5><i class="bi bi-tools"></i> Лабораториска опрема</h5>
-      </div>
-      <div class="card-body">
-        <p>Управување со опрема</p>
+  <div class="col-lg-3">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-success text-white"><i class="bi bi-tools"></i> Лаб. опрема</div>
+      <div class="card-body d-grid gap-2">
         <a href="/equipment" class="btn btn-outline-success btn-sm">Прегледај</a>
         <a href="/equipment/add" class="btn btn-success btn-sm">Додај нова</a>
@@ -37,12 +87,8 @@
     </div>
   </div>
-
-  <div class="col-md-3 mb-3">
-    <div class="card h-100">
-      <div class="card-header bg-warning text-dark">
-        <h5><i class="bi bi-diagram-3"></i> Реакции</h5>
-      </div>
-      <div class="card-body">
-        <p>Креирање на реакции</p>
+  <div class="col-lg-3">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-warning text-dark"><i class="bi bi-diagram-3"></i> Реакции</div>
+      <div class="card-body d-grid gap-2">
         <a href="/reactions" class="btn btn-outline-warning btn-sm">Прегледај</a>
         <a href="/reactions/add" class="btn btn-warning btn-sm">Додај нова</a>
@@ -50,13 +96,43 @@
     </div>
   </div>
+  <div class="col-lg-3">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-danger text-white"><i class="bi bi-radioactive"></i> Лабораторија</div>
+      <div class="card-body">
+        <p>Тестирај комбинации и услови.</p>
+        <a href="/laboratory" class="btn btn-danger w-100">Отвори</a>
+      </div>
+    </div>
+  </div>
+</div>
+<br>
+<br>
 
-  <div class="col-md-3 mb-3">
-    <div class="card h-100">
-      <div class="card-header bg-danger text-white">
-        <h5><i class="bi bi-radioactive"></i> Лабораторија</h5>
+<!-- Извештаи и студенти -->
+<div class="row g-3 mt-1">
+  <div class="col-lg-4">
+    <div class="card h-100 hover-lift">
+      <div class="card-header text-white" style="background:linear-gradient(135deg,#FF6B6B,#4ECDC4)"><i class="bi bi-journal-check"></i> Експерименти</div>
+      <div class="card-body d-grid gap-2">
+        <a href="/experiments" class="btn btn-outline-info btn-sm">Сите експерименти</a>
+        <a href="/reports/detailed_experiments" class="btn btn-outline-info btn-sm">Експерименти на студенти</a>
       </div>
-      <div class="card-body">
-        <p>Тестирај реакции</p>
-        <a href="/laboratory" class="btn btn-danger">Отвори</a>
+    </div>
+  </div>
+  <div class="col-lg-4">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-info text-white"><i class="bi bi-people"></i> Студенти</div>
+      <div class="card-body d-grid gap-2">
+        <a href="/my_students" class="btn btn-info">Мои студенти</a>
+        <a href="/reports/low_activity_students" class="btn btn-outline-dark">Ниска активност</a>
+      </div>
+    </div>
+  </div>
+  <div class="col-lg-4">
+    <div class="card h-100 hover-lift">
+      <div class="card-header bg-secondary text-white"><i class="bi bi-file-earmark-bar-graph"></i> Извештаи</div>
+      <div class="card-body d-grid gap-2">
+        <a href="/reports" class="btn btn-secondary">Мени за извештаи</a>
+        <a href="/reports/element_views" class="btn btn-outline-secondary">Прегледи на елементи</a>
       </div>
     </div>
@@ -64,72 +140,15 @@
 </div>
 
-<!-- Експерименти и студенти -->
-<div class="row">
-  <div class="col-md-4 mb-3">
-    <div class="card h-100">
-      <div class="card-header text-white" style="background: linear-gradient(45deg, #FF6B6B, #4ECDC4);">
-        <h5><i class="bi bi-journal-check"></i> Експерименти</h5>
-      </div>
-      <div class="card-body">
-        <p>Преглед на експерименти</p>
-        <a href="/experiments" class="btn btn-outline-info btn-sm">Сите</a>
-        <a href="/my-experiments" class="btn btn-info btn-sm">Мои</a>
-      </div>
-    </div>
-  </div>
-
-  <div class="col-md-4 mb-3">
-    <div class="card h-100">
-      <div class="card-header bg-info text-white">
-        <h5><i class="bi bi-people"></i> Студенти</h5>
-      </div>
-      <div class="card-body">
-        <p>Следете го напредокот на студентите</p>
-        <a href="/my_students" class="btn btn-info">Види студенти</a>
-      </div>
-    </div>
-  </div>
-
-  <div class="col-md-4 mb-3">
-    <div class="card h-100">
-      <div class="card-header bg-secondary text-white">
-        <h5><i class="bi bi-file-earmark-bar-graph"></i> Извештаи</h5>
-      </div>
-      <div class="card-body">
-        <p>Детални статистики</p>
-        <a href="/reports" class="btn btn-secondary">Види извештаи</a>
-      </div>
-    </div>
-  </div>
-</div>
-
-<!-- Брзи акции -->
-<div class="row mt-4">
-  <div class="col-12">
-    <div class="card">
-      <div class="card-header bg-dark text-white">
-        <h5><i class="bi bi-lightning"></i> Брзи акции</h5>
-      </div>
-      <div class="card-body">
-        <div class="btn-group" role="group">
-          <a href="/reactions/add" class="btn btn-outline-primary">
-            <i class="bi bi-plus-circle"></i> Нова реакција
-          </a>
-          <a href="/elements/add" class="btn btn-outline-success">
-            <i class="bi bi-plus-circle"></i> Нов елемент
-          </a>
-          <a href="/equipment/add" class="btn btn-outline-warning">
-            <i class="bi bi-plus-circle"></i> Нова опрема
-          </a>
-          <a href="/reports/detailed_experiments" class="btn btn-outline-info">
-            <i class="bi bi-graph-up"></i> Експерименти на студенти
-          </a>
-          <a href="/reports/low_activity_students" class="btn btn-outline-danger">
-            <i class="bi bi-exclamation-triangle"></i> Неактивни студенти
-          </a>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
+<script>
+document.querySelectorAll('.count-up').forEach(el=>{
+  const target = Number(el.dataset.target||0);
+  const dur = 600; const start = performance.now();
+  const step = t=>{
+    const p = Math.min(1,(t-start)/dur);
+    el.textContent = Math.round(target * p);
+    if(p<1) requestAnimationFrame(step);
+  };
+  requestAnimationFrame(step);
+});
+</script>
 {% endblock %}
Index: templates/edit_element.html
===================================================================
--- templates/edit_element.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/edit_element.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,77 +3,149 @@
 
 {% block content %}
-<div class="row justify-content-center">
-    <div class="col-md-8">
-        <div class="card">
-            <div class="card-header">
-                <h3>Едитирај хемиски елемент</h3>
+<style>
+  .hero{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .pill{width:54px;height:54px;border-radius:14px;background:#ffffff22;display:flex;align-items:center;justify-content:center;font-weight:900;font-size:20px}
+  .type-badge{background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;font-weight:600;letter-spacing:.2px}
+  .wrap{display:grid;grid-template-columns:1.35fr .85fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){.wrap{grid-template-columns:1fr}}
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .muted{color:#6c757d}
+  .chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;margin:4px;border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;cursor:pointer;border:1px solid rgba(63,81,181,.25);user-select:none;font-size:.9rem}
+  .sticky-actions{position:sticky;bottom:0;background:#fff;border-top:1px solid #eef1f4;padding:12px 0;margin-top:8px}
+</style>
+
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div class="pill" id="sym-pill">{{ element.symbol }}</div>
+    <div>
+      <h2 class="mb-0 text-truncate">Едитирај: {{ element.element_name }}</h2>
+      <div class="small opacity-75">Хемиски елемент • ID #{{ element.element_id }}</div>
+    </div>
+  </div>
+  <div class="d-flex align-items-center gap-2 flex-wrap">
+    <span class="type-badge">№ {{ element.atomic_number }}</span>
+    <span class="type-badge">
+      {{ "%.2f"|format(element.atomic_weight) if element.atomic_weight is not none else "—" }} u
+    </span>
+    <a href="/elements/{{ element.element_id }}" class="btn btn-light btn-sm fw-semibold">
+      <i class="bi bi-eye"></i> Преглед
+    </a>
+  </div>
+</div>
+
+<div class="wrap">
+  <!-- Лево: форма -->
+  <div class="card block">
+    <div class="card-body">
+      <h5 class="section-title"><i class="bi bi-pencil-square"></i> Податоци за елемент</h5>
+      {% if error %}<div class="alert alert-danger">{{ error }}</div>{% endif %}
+
+      <form method="POST" id="element-form" novalidate>
+        <div class="row g-3">
+          <div class="col-md-4">
+            <label class="form-label">Симбол</label>
+            <input type="text" class="form-control" name="symbol" id="symbol"
+                   value="{{ element.symbol }}" maxlength="3" required pattern="^[A-Za-z]{1,3}$"
+                   placeholder="Na, Cl, Al...">
+            <div class="form-text">1–3 букви, авто-големи.</div>
+          </div>
+          <div class="col-md-8">
+            <label class="form-label">Име на елемент</label>
+            <input type="text" class="form-control" name="name" value="{{ element.element_name }}" required>
+          </div>
+
+          <div class="col-md-4">
+            <label class="form-label">Атомски број</label>
+            <input type="number" class="form-control" name="atomic_number" value="{{ element.atomic_number }}" min="1" required>
+          </div>
+          <div class="col-md-4">
+            <label class="form-label">Атомска маса</label>
+            <div class="input-group">
+              <input type="number" step="0.0001" class="form-control" name="atomic_weight" value="{{ element.atomic_weight }}" required>
+              <span class="input-group-text">u</span>
             </div>
-            <div class="card-body">
-                {% if error %}
-                    <div class="alert alert-danger">{{ error }}</div>
-                {% endif %}
-                
-                <form method="POST">
-                    <div class="row">
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="symbol" class="form-label">Симбол</label>
-                                <input type="text" class="form-control" name="symbol" maxlength="2" value="{{ element.symbol }}" required>
-                            </div>
-                        </div>
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="name" class="form-label">Име на елемент</label>
-                                <input type="text" class="form-control" name="name" value="{{ element.element_name }}" required>
-                            </div>
-                        </div>
-                    </div>
-                    
-                    <div class="row">
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="atomic_number" class="form-label">Атомски број</label>
-                                <input type="number" class="form-control" name="atomic_number" value="{{ element.atomic_number }}" required>
-                            </div>
-                        </div>
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="atomic_weight" class="form-label">Атомска маса</label>
-                                <input type="number" step="0.001" class="form-control" name="atomic_weight" value="{{ element.atomic_weight }}" required>
-                            </div>
-                        </div>
-                    </div>
-                    
-                    <div class="row">
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="melting_point" class="form-label">Точка на топење (°C)</label>
-                                <input type="number" step="0.1" class="form-control" name="melting_point" value="{{ element.melting_point or '' }}">
-                            </div>
-                        </div>
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="boiling_point" class="form-label">Точка на вриење (°C)</label>
-                                <input type="number" step="0.1" class="form-control" name="boiling_point" value="{{ element.boiling_point or '' }}">
-                            </div>
-                        </div>
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="hazard_type" class="form-label">Тип на опасност</label>
-                        <input type="text" class="form-control" name="hazard_type" maxlength="50" value="{{ element.hazard_type or '' }}">
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="description" class="form-label">Опис</label>
-                        <textarea class="form-control" name="description" rows="3">{{ element.description_element or '' }}</textarea>
-                    </div>
-                    
-                    <button type="submit" class="btn btn-success">Ажурирај елемент</button>
-                    <a href="/elements" class="btn btn-secondary">Откажи</a>
-                </form>
+          </div>
+          <div class="col-md-4"></div>
+
+          <div class="col-md-6">
+            <label class="form-label">Точка на топење (°C)</label>
+            <input type="number" step="0.1" class="form-control" name="melting_point" value="{{ element.melting_point or '' }}">
+          </div>
+          <div class="col-md-6">
+            <label class="form-label">Точка на вриење (°C)</label>
+            <input type="number" step="0.1" class="form-control" name="boiling_point" value="{{ element.boiling_point or '' }}">
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Тип на опасност</label>
+            <input type="text" class="form-control" name="hazard_type" id="hazard" maxlength="50" value="{{ element.hazard_type or '' }}">
+            <div class="form-text">Брз избор:</div>
+            <div>
+              <span class="chip" onclick="pickHazard('Нема опасност')">✔ Нема опасност</span>
+              <span class="chip" onclick="pickHazard('Корозивно')">⚠ Корозивно</span>
+              <span class="chip" onclick="pickHazard('Токсично')">☠ Токсично</span>
+              <span class="chip" onclick="pickHazard('Запалливо')">🔥 Запалливо</span>
+              <span class="chip" onclick="pickHazard('Иритант')">❗ Иритант</span>
             </div>
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Опис</label>
+            <textarea class="form-control" name="description" rows="4" placeholder="Краток опис...">{{ element.description_element or '' }}</textarea>
+          </div>
         </div>
+
+        <div class="sticky-actions d-flex justify-content-between align-items-center">
+          <a href="/elements" class="btn btn-outline-secondary"><i class="bi bi-arrow-left"></i> Откажи</a>
+          <button type="submit" class="btn btn-success"><i class="bi bi-check2-circle"></i> Ажурирај елемент</button>
+        </div>
+      </form>
     </div>
+  </div>
+
+  <!-- Десно: жив преглед -->
+  <div class="card block">
+    <div class="card-body">
+      <h6 class="section-title"><i class="bi bi-magic"></i> Жив преглед</h6>
+      <div class="d-flex align-items-center gap-3 mb-3">
+        <div class="pill" id="preview-pill">{{ element.symbol }}</div>
+        <div>
+          <div class="fw-bold" id="preview-name">{{ element.element_name }}</div>
+          <div class="small muted">№ <span id="preview-atomic">{{ element.atomic_number }}</span> •
+            <span id="preview-weight">{{ element.atomic_weight }}</span> u
+          </div>
+        </div>
+      </div>
+      <hr class="my-3"/>
+      <h6 class="section-title"><i class="bi bi-lightbulb"></i> Совет</h6>
+      <ul class="small mb-0">
+        <li>Симбол: 1–3 букви (Na, Cl, Al).</li>
+        <li>Атомска маса со децимали (на пр. 22.9898).</li>
+      </ul>
+    </div>
+  </div>
 </div>
+
+<script>
+  const sym = document.getElementById('symbol');
+  const nameEl = document.querySelector('input[name="name"]');
+  const numEl = document.querySelector('input[name="atomic_number"]');
+  const wEl = document.querySelector('input[name="atomic_weight"]');
+
+  function updatePreview(){
+    const s = sym.value || '—';
+    document.getElementById('sym-pill').textContent = s;
+    document.getElementById('preview-pill').textContent = s;
+    document.getElementById('preview-name').textContent = nameEl.value || 'Име на елемент';
+    document.getElementById('preview-atomic').textContent = numEl.value || '—';
+    document.getElementById('preview-weight').textContent = wEl.value || '—';
+  }
+  function pickHazard(txt){ const hz=document.getElementById('hazard'); hz.value=txt; hz.focus(); }
+  sym.addEventListener('input', ()=>{ sym.value = sym.value.toUpperCase(); updatePreview(); });
+  nameEl.addEventListener('input', updatePreview);
+  numEl.addEventListener('input', updatePreview);
+  wEl.addEventListener('input', updatePreview);
+  updatePreview();
+</script>
 {% endblock %}
Index: templates/edit_equipment.html
===================================================================
--- templates/edit_equipment.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/edit_equipment.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,42 +3,108 @@
 
 {% block content %}
-<div class="row justify-content-center">
-    <div class="col-md-8">
-        <div class="card">
-            <div class="card-header">
-                <h3>Едитирај лабораториска опрема</h3>
-            </div>
-            <div class="card-body">
-                {% if error %}
-                    <div class="alert alert-danger">{{ error }}</div>
-                {% endif %}
-                
-                <form method="POST">
-                    <div class="mb-3">
-                        <label for="name" class="form-label">Име на опремата</label>
-                        <input type="text" class="form-control" name="name" maxlength="50" value="{{ equipment.equipment_name }}" required>
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="type" class="form-label">Тип на опрема</label>
-                        <input type="text" class="form-control" name="type" maxlength="50" value="{{ equipment.type or '' }}">
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="description" class="form-label">Опис</label>
-                        <textarea class="form-control" name="description" rows="3">{{ equipment.description or '' }}</textarea>
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="safety_info" class="form-label">Безбедносни информации</label>
-                        <textarea class="form-control" name="safety_info" rows="2">{{ equipment.safety_info or '' }}</textarea>
-                    </div>
-                    
-                    <button type="submit" class="btn btn-success">Ажурирај опрема</button>
-                    <a href="/equipment" class="btn btn-secondary">Откажи</a>
-                </form>
-            </div>
+<style>
+  .hero{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .pill{width:42px;height:42px;border-radius:12px;background:#ffffff22;display:flex;align-items:center;justify-content:center;font-size:20px}
+  .type-badge{background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;font-weight:600;letter-spacing:.2px}
+  .wrap{display:grid;grid-template-columns:1.35fr .85fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){.wrap{grid-template-columns:1fr}}
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .muted{color:#6c757d}
+  .chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;margin:4px;border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;cursor:pointer;border:1px solid rgba(63,81,181,.25);user-select:none;font-size:.9rem}
+  .sticky-actions{position:sticky;bottom:0;background:#fff;border-top:1px solid #eef1f4;padding:12px 0;margin-top:8px}
+</style>
+
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div class="pill"><i class="bi bi-tools"></i></div>
+    <div>
+      <h2 class="mb-0 text-truncate">Едитирај: {{ equipment.equipment_name }}</h2>
+      <div class="small opacity-75">Лабораториска опрема • ID #{{ equipment.equipment_id }}</div>
+    </div>
+  </div>
+  <div class="d-flex align-items-center gap-2">
+    <span class="type-badge"><i class="bi bi-tag me-1"></i>{{ equipment.type or 'Не е специфициран' }}</span>
+    <a href="/equipment/{{ equipment.equipment_id }}" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-eye"></i> Преглед</a>
+  </div>
+</div>
+
+<div class="wrap">
+  <!-- Лево: форма -->
+  <div class="card block">
+    <div class="card-body">
+      <h5 class="section-title"><i class="bi bi-pencil-square"></i> Податоци за опрема</h5>
+      {% if error %}<div class="alert alert-danger">{{ error }}</div>{% endif %}
+
+      <form method="POST" id="equip-form" novalidate>
+        <div class="mb-3">
+          <label class="form-label">Име на опремата</label>
+          <input type="text" class="form-control" name="name" maxlength="50" value="{{ equipment.equipment_name }}" required placeholder="Пипета, Термометар...">
         </div>
+
+        <div class="mb-2">
+          <label class="form-label">Тип на опрема</label>
+          <input type="text" class="form-control" name="type" maxlength="50" value="{{ equipment.type or '' }}" placeholder="Стакларија, Мерење, Загревање...">
+          <div class="form-text">Брз избор:</div>
+          <div>
+            <span class="chip" onclick="pickType('Стакларија')">Стакларија</span>
+            <span class="chip" onclick="pickType('Мерење')">Мерење</span>
+            <span class="chip" onclick="pickType('Загревање')">Загревање</span>
+            <span class="chip" onclick="pickType('Безбедност')">Безбедност</span>
+            <span class="chip" onclick="pickType('Општа')">Општа</span>
+          </div>
+        </div>
+
+        <div class="mb-3">
+          <label class="form-label">Опис</label>
+          <textarea class="form-control" name="description" rows="4" placeholder="Краток опис, употреба, напомени...">{{ equipment.description or '' }}</textarea>
+        </div>
+
+        <div class="mb-1">
+          <label class="form-label">Безбедносни информации</label>
+          <textarea class="form-control" name="safety_info" rows="3" placeholder="ППЕ, чистење, складирање...">{{ equipment.safety_info or '' }}</textarea>
+        </div>
+
+        <div class="sticky-actions d-flex justify-content-between align-items-center">
+          <a href="/equipment" class="btn btn-outline-secondary"><i class="bi bi-arrow-left"></i> Откажи</a>
+          <button type="submit" class="btn btn-success"><i class="bi bi-check2-circle"></i> Ажурирај опрема</button>
+        </div>
+      </form>
     </div>
+  </div>
+
+  <!-- Десно: брзи факти / помош -->
+  <div class="card block">
+    <div class="card-body">
+      <h6 class="section-title"><i class="bi bi-list-ul"></i> Брзи факти</h6>
+      <div class="row">
+        <div class="col-5 muted">Име</div>
+        <div class="col-7 fw-semibold" id="prev-name">{{ equipment.equipment_name }}</div>
+      </div>
+      <div class="row">
+        <div class="col-5 muted">Тип</div>
+        <div class="col-7 fw-semibold" id="prev-type">{{ equipment.type or '—' }}</div>
+      </div>
+      <div class="row">
+        <div class="col-5 muted">ID</div>
+        <div class="col-7 fw-semibold">#{{ equipment.equipment_id }}</div>
+      </div>
+
+      <hr class="my-3"/>
+
+      <h6 class="section-title"><i class="bi bi-lightbulb"></i> Совети</h6>
+      <ul class="small mb-0">
+        <li>Типот држи го конзистентно за полесни филтри и извештаи.</li>
+        <li>Во опис: употреба + специфични напомени.</li>
+        <li>Безбедност: кратко, јасно и применливо.</li>
+      </ul>
+    </div>
+  </div>
 </div>
+
+<script>
+  function pickType(txt){ const t=document.querySelector('input[name="type"]'); t.value=txt; t.focus(); document.getElementById('prev-type').textContent=txt; }
+  document.querySelector('input[name="name"]').addEventListener('input', e=>{ document.getElementById('prev-name').textContent=e.target.value||'—'; });
+  document.querySelector('input[name="type"]').addEventListener('input', e=>{ document.getElementById('prev-type').textContent=e.target.value||'—'; });
+</script>
 {% endblock %}
Index: templates/edit_reaction.html
===================================================================
--- templates/edit_reaction.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/edit_reaction.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,62 +3,120 @@
 
 {% block content %}
-<div class="row justify-content-center">
-    <div class="col-md-8">
-        <div class="card">
-            <div class="card-header">
-                <h3>Едитирај реакција #{{ reaction.reaction_id }}</h3>
-            </div>
-            <div class="card-body">
-                {% if error %}
-                    <div class="alert alert-danger">{{ error }}</div>
-                {% endif %}
-                
-                <form method="POST">
-                    <div class="row">
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="element1_id" class="form-label">Првин елемент</label>
-                                <select class="form-select" name="element1_id" required>
-                                    {% for element in elements %}
-                                    <option value="{{ element.element_id }}" 
-                                            {% if element.element_id == reaction.element1_id %}selected{% endif %}>
-                                        {{ element.symbol }} - {{ element.element_name }}
-                                    </option>
-                                    {% endfor %}
-                                </select>
-                            </div>
-                        </div>
-                        <div class="col-md-6">
-                            <div class="mb-3">
-                                <label for="element2_id" class="form-label">Втор елемент</label>
-                                <select class="form-select" name="element2_id" required>
-                                    {% for element in elements %}
-                                    <option value="{{ element.element_id }}" 
-                                            {% if element.element_id == reaction.element2_id %}selected{% endif %}>
-                                        {{ element.symbol }} - {{ element.element_name }}
-                                    </option>
-                                    {% endfor %}
-                                </select>
-                            </div>
-                        </div>
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="product" class="form-label">Продукт на реакцијата</label>
-                        <input type="text" class="form-control" name="product" maxlength="50" 
-                               value="{{ reaction.product }}" required>
-                    </div>
-                    
-                    <div class="mb-3">
-                        <label for="conditions" class="form-label">Услови за реакцијата</label>
-                        <textarea class="form-control" name="conditions" rows="3">{{ reaction.conditions or '' }}</textarea>
-                    </div>
-                    
-                    <button type="submit" class="btn btn-success">Ажурирај реакција</button>
-                    <a href="/reactions" class="btn btn-secondary">Откажи</a>
-                </form>
-            </div>
+<style>
+  .hero{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .pill{width:48px;height:48px;border-radius:12px;background:#ffffff22;display:flex;align-items:center;justify-content:center;font-size:20px}
+  .wrap{display:grid;grid-template-columns:1fr .7fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){.wrap{grid-template-columns:1fr}}
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .eq-preview{font-weight:800;font-size:18px;background:#f8f9fa;border:1px solid #edf0f4;border-radius:12px;padding:10px 12px}
+  .sticky-actions{position:sticky;bottom:0;background:#fff;border-top:1px solid #eef1f4;padding:12px 0;margin-top:8px}
+</style>
+
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div class="pill"><i class="bi bi-pencil-square"></i></div>
+    <div>
+      <h2 class="mb-0">Едитирај реакција #{{ reaction.reaction_id }}</h2>
+      <div class="small opacity-75">Ажурирај реактанти, продукт и услови</div>
+    </div>
+  </div>
+  <a href="/reactions" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-list"></i> Сите реакции</a>
+</div>
+
+<div class="wrap">
+  <div class="card block">
+    <div class="card-body">
+      {% if error %}<div class="alert alert-danger">{{ error }}</div>{% endif %}
+
+      <form method="POST" id="edit-reaction-form" novalidate>
+        <h5 class="section-title"><i class="bi bi-flask"></i> Реактанти</h5>
+        <div class="row g-3">
+          <div class="col-md-6">
+            <label class="form-label">Прв елемент</label>
+            <select class="form-select" name="element1_id" id="element1_id" required>
+              {% for element in elements %}
+              <option value="{{ element.element_id }}"
+                      data-symbol="{{ element.symbol }}"
+                      {% if element.element_id == reaction.element1_id %}selected{% endif %}>
+                {{ element.symbol }} — {{ element.element_name }}
+              </option>
+              {% endfor %}
+            </select>
+          </div>
+          <div class="col-md-6">
+            <label class="form-label">Втор елемент</label>
+            <select class="form-select" name="element2_id" id="element2_id" required>
+              {% for element in elements %}
+              <option value="{{ element.element_id }}"
+                      data-symbol="{{ element.symbol }}"
+                      {% if element.element_id == reaction.element2_id %}selected{% endif %}>
+                {{ element.symbol }} — {{ element.element_name }}
+              </option>
+              {% endfor %}
+            </select>
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Преглед на равенка</label>
+            <div class="eq-preview" id="eqPreview">—</div>
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Продукт *</label>
+            <input type="text" class="form-control" name="product" id="product"
+                   value="{{ reaction.product }}" maxlength="50" required>
+          </div>
+
+          <div class="col-12">
+            <label class="form-label">Услови</label>
+            <textarea class="form-control" name="conditions" id="conditions" rows="3">{{ reaction.conditions or '' }}</textarea>
+          </div>
         </div>
+
+        <div class="sticky-actions d-flex justify-content-between align-items-center">
+          <a href="/reactions" class="btn btn-outline-secondary"><i class="bi bi-arrow-left"></i> Откажи</a>
+          <button type="submit" class="btn btn-success"><i class="bi bi-check2-circle"></i> Ажурирај реакција</button>
+        </div>
+      </form>
     </div>
+  </div>
+
+  <div class="card block">
+    <div class="card-body">
+      <h6 class="section-title"><i class="bi bi-lightbulb"></i> Совети</h6>
+      <ul class="small mb-0">
+        <li>Елементите мора да бидат различни.</li>
+        <li>Не внесувај „Темп./Притисок/Катализатор“ ако веќе се системски додадени во описот.</li>
+      </ul>
+    </div>
+  </div>
 </div>
+
+<script>
+  function getSym(id){
+    const sel=document.getElementById(id);
+    const opt=sel.options[sel.selectedIndex];
+    return opt ? (opt.dataset.symbol||'') : '';
+  }
+  function updateEq(){
+    const a=getSym('element1_id')||'A';
+    const b=getSym('element2_id')||'B';
+    const p=(document.getElementById('product').value||'___').trim()||'___';
+    document.getElementById('eqPreview').textContent = `${a} + ${b} → ${p}`;
+  }
+  function validateDiff(){
+    const e1=document.getElementById('element1_id'), e2=document.getElementById('element2_id');
+    if(e1.value && e2.value && e1.value===e2.value){
+      alert('Мора да изберете два различни елементи!');
+      e2.value=''; updateEq(); return false;
+    }
+    return true;
+  }
+  ['element1_id','element2_id','product'].forEach(id=>{
+    document.getElementById(id).addEventListener('change', ()=>{ validateDiff(); updateEq(); });
+    document.getElementById(id).addEventListener('input',  updateEq);
+  });
+  updateEq();
+</script>
 {% endblock %}
Index: templates/element_detail.html
===================================================================
--- templates/element_detail.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/element_detail.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,54 +3,188 @@
 
 {% block content %}
-<div class="row">
-    <div class="col-md-8 mx-auto">
-        <div class="card">
-            <div class="card-header d-flex justify-content-between">
-                <h3>{{ element.symbol }} - {{ element.element_name }}</h3>
-                {% if user_role == 'teacher' %}
-                    <a href="/elements/{{ element.element_id }}/edit" class="btn btn-warning btn-sm">Едитирај</a>
-                {% endif %}
-            </div>
-            <div class="card-body">
-                <div class="row">
-                    <div class="col-md-6">
-                        <h5>Основни информации</h5>
-                        <p><strong>Атомски број:</strong> {{ element.atomic_number }}</p>
-                        <p><strong>Атомска маса:</strong> {{ element.atomic_weight }}</p>
-                        {% if element.melting_point %}
-                            <p><strong>Точка на топење:</strong> {{ element.melting_point }}°C</p>
-                        {% endif %}
-                        {% if element.boiling_point %}
-                            <p><strong>Точка на вриење:</strong> {{ element.boiling_point }}°C</p>
-                        {% endif %}
-                    </div>
-                    <div class="col-md-6">
-                        <h5>Безбедносни информации</h5>
-                        {% if element.hazard_type %}
-                            <div class="alert alert-warning">
-                                <strong>Опасност:</strong> {{ element.hazard_type }}
-                            </div>
-                        {% else %}
-                            <p class="text-muted">Нема специфични предупредувања</p>
-                        {% endif %}
-                    </div>
-                </div>
-                
-                {% if element.description_element %}
-                    <hr>
-                    <h5>Опис</h5>
-                    <p>{{ element.description_element }}</p>
-                {% endif %}
-                
-                <hr>
-                <p class="text-muted"><small>Создадено од: {{ element.created_by }}</small></p>
-            </div>
+<style>
+  .hero{
+    background: linear-gradient(135deg,#6a11cb,#2575fc);
+    color:#fff;border-radius:18px;padding:18px 22px;
+    display:flex;align-items:center;justify-content:space-between;gap:12px
+  }
+  .type-badge{
+    background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;
+    font-weight:600; letter-spacing:.2px
+  }
+  .wrap{display:grid;grid-template-columns:1.4fr .8fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){ .wrap{grid-template-columns:1fr} }
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .muted{color:#6c757d}
+  .line-clamp-8{
+    display:-webkit-box;-webkit-line-clamp:8;-webkit-box-orient:vertical;overflow:hidden
+  }
+  .fact-row .row + .row{margin-top:10px}
+  .badge-soft-success{
+    background:#e6f4ea;color:#166534;border:1px solid #cfead7;font-weight:600;
+  }
+  .badge-soft-danger{
+    background:#fde8e8;color:#b91c1c;border:1px solid #f5c2c7;font-weight:600;
+  }
+  .pill{
+    width:54px;height:54px;border-radius:14px;background:#ffffff22;
+    display:flex;align-items:center;justify-content:center;font-weight:900;font-size:20px
+  }
+  .btn-ghost{background:#00000008;border:1px solid #ffffff55;color:#fff}
+</style>
+
+{# нормализација на hazard за значка/филтер #}
+{% set hazard_txt  = (element.hazard_type or '') %}
+{% set _hz_norm    = hazard_txt|lower|trim %}
+{% set hazard_clean = _hz_norm if _hz_norm not in ['','нема','нема опасност','безбедно','safe','none'] else 'без опасност' %}
+
+<!-- HERO -->
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div class="pill">{{ element.symbol }}</div>
+    <div>
+      <h2 class="mb-0 text-truncate">{{ element.element_name }}</h2>
+      <div class="small opacity-75">Хемиски елемент</div>
+    </div>
+  </div>
+
+  <div class="d-flex align-items-center gap-2 flex-wrap">
+    <span class="type-badge" title="Атомски број">№ {{ element.atomic_number }}</span>
+    <span class="type-badge" title="Атомска маса">
+      {{ "%.2f"|format(element.atomic_weight) if element.atomic_weight is not none else "—" }}
+    </span>
+    {% if hazard_clean != 'без опасност' %}
+      <span class="type-badge"><i class="bi bi-exclamation-triangle"></i> {{ element.hazard_type }}</span>
+    {% else %}
+      <span class="type-badge"><i class="bi bi-shield-check"></i> Без опасност</span>
+    {% endif %}
+    {% if user_role == 'teacher' %}
+      <a href="/elements/{{ element.element_id }}/edit" class="btn btn-light btn-sm fw-semibold">
+        <i class="bi bi-pencil-square"></i> Едитирај
+      </a>
+    {% endif %}
+    <button class="btn btn-ghost btn-sm" onclick="window.print()"><i class="bi bi-printer"></i></button>
+  </div>
+</div>
+
+<div class="wrap">
+  <!-- ЛЕВО: опис + својства + безбедност -->
+  <div class="card block">
+    <div class="card-body">
+      <h5 class="section-title"><i class="bi bi-info-circle"></i> Основни информации</h5>
+
+      <div class="row g-3">
+        <div class="col-md-6">
+          <ul class="list-unstyled mb-0">
+            <li><span class="muted">Симбол</span>: <b>{{ element.symbol }}</b></li>
+            <li><span class="muted">Атомски број</span>: <b>{{ element.atomic_number }}</b></li>
+            <li><span class="muted">Атомска маса</span>:
+              <b>{{ "%.4f"|format(element.atomic_weight) if element.atomic_weight is not none else "—" }}</b>
+            </li>
+          </ul>
         </div>
-        
-        <div class="mt-3">
-            <a href="/elements" class="btn btn-secondary">Назад до листа</a>
-            <a href="/dashboard" class="btn btn-primary">Dashboard</a>
+        <div class="col-md-6">
+          <ul class="list-unstyled mb-0">
+            <li>
+              <span class="muted">Точка на топење</span>:
+              <b>{{ element.melting_point }}°C</b>{% if not element.melting_point %}<span class="muted"> —</span>{% endif %}
+            </li>
+            <li>
+              <span class="muted">Точка на вриење</span>:
+              <b>{{ element.boiling_point }}°C</b>{% if not element.boiling_point %}<span class="muted"> —</span>{% endif %}
+            </li>
+          </ul>
         </div>
+      </div>
+
+      {% if element.description_element %}
+        <hr class="my-4"/>
+        <h5 class="section-title"><i class="bi bi-journal-text"></i> Опис</h5>
+        <p class="line-clamp-8" id="desc">{{ element.description_element }}</p>
+        <button class="btn btn-outline-secondary btn-sm" onclick="copyText('#desc')">
+          <i class="bi bi-clipboard"></i> Копирај опис
+        </button>
+      {% endif %}
+
+      <hr class="my-4"/>
+
+      <h5 class="section-title"><i class="bi bi-shield-exclamation"></i> Безбедносни информации</h5>
+      {% if hazard_clean != 'без опасност' %}
+        <div class="badge badge-soft-danger mb-2">⚠ {{ element.hazard_type }}</div>
+        <div class="alert alert-warning mb-2" id="haz">
+          При ракување користи PPE (ракавици, очила, мантила) и следи протоколи за складирање и отстранување.
+        </div>
+        <button class="btn btn-outline-warning btn-sm" onclick="copyText('#haz')">
+          <i class="bi bi-clipboard-check"></i> Копирај препораки
+        </button>
+      {% else %}
+        <span class="badge badge-soft-success">✔ Без опасност</span>
+        <p class="muted mt-2">Нема специфични предупредувања.</p>
+      {% endif %}
+
+      <hr class="my-4"/>
+      <p class="text-muted mb-0"><small>Создадено од: {{ element.created_by }}</small></p>
     </div>
+  </div>
+
+  <!-- ДЕСНО: брзи факти + навигација -->
+  <div class="card block">
+    <div class="card-body fact-row">
+      <h6 class="section-title"><i class="bi bi-list-ul"></i> Брзи факти</h6>
+      <div class="row">
+        <div class="col-5 muted">ID</div>
+        <div class="col-7 fw-semibold">#{{ element.element_id }}</div>
+      </div>
+      <div class="row">
+        <div class="col-5 muted">Симбол</div>
+        <div class="col-7 fw-semibold">{{ element.symbol }}</div>
+      </div>
+      <div class="row">
+        <div class="col-5 muted">Атомски број</div>
+        <div class="col-7 fw-semibold">{{ element.atomic_number }}</div>
+      </div>
+      <div class="row">
+        <div class="col-5 muted">Маса</div>
+        <div class="col-7 fw-semibold">
+          {{ "%.4f"|format(element.atomic_weight) if element.atomic_weight is not none else "—" }}
+        </div>
+      </div>
+      <div class="row">
+        <div class="col-5 muted">Опасност</div>
+        <div class="col-7 fw-semibold">
+          {% if hazard_clean != 'без опасност' %}{{ element.hazard_type }}{% else %}Без опасност{% endif %}
+        </div>
+      </div>
+
+      <hr class="my-3"/>
+
+      <h6 class="section-title"><i class="bi bi-compass"></i> Навигација</h6>
+      <div class="d-grid gap-2">
+        <a href="/elements" class="btn btn-outline-primary btn-sm">
+          <i class="bi bi-arrow-left"></i> Назад до листа
+        </a>
+        <a href="/dashboard" class="btn btn-outline-secondary btn-sm">
+          <i class="bi bi-speedometer2"></i> Dashboard
+        </a>
+        <a href="/laboratory" class="btn btn-outline-dark btn-sm">
+          <i class="bi bi-flask"></i> Виртуелна лабораторија
+        </a>
+      </div>
+    </div>
+  </div>
 </div>
+
+<script>
+  function copyText(selector){
+    const el = document.querySelector(selector);
+    if(!el) return;
+    const text = el.innerText.trim();
+    if(!text) return;
+    navigator.clipboard.writeText(text).then(()=>{
+      const btn = document.activeElement;
+      if(btn) { const old = btn.innerHTML; btn.innerHTML='✔ Копирано'; setTimeout(()=>btn.innerHTML=old,1200); }
+    });
+  }
+</script>
 {% endblock %}
Index: templates/elements_list.html
===================================================================
--- templates/elements_list.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/elements_list.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,92 +3,216 @@
 
 {% block content %}
-<div class="container mt-4">
-
-    <div class="d-flex justify-content-between align-items-center mb-4">
-        <h2 class="fw-bold text-primary"><i class="bi bi-flask"></i> Хемиски елементи</h2>
-        {% if user_role == 'teacher' %}
-            <a href="/elements/add" class="btn btn-success">
-                <i class="bi bi-plus-circle"></i> Додај нов елемент
+<style>
+  .page-hero{
+    background: linear-gradient(135deg,#232526,#414345);
+    color:#fff;border-radius:18px;padding:18px 22px;
+    display:flex;align-items:center;justify-content:space-between;gap:12px
+  }
+  .toolbar{
+    display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:14px 0
+  }
+  .search-input{min-width:260px}
+
+  .chip{
+    display:inline-flex;align-items:center;gap:8px;padding:6px 12px;margin:4px;
+    border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;cursor:pointer;
+    border:1px solid rgba(63,81,181,.25); user-select:none
+  }
+  .chip.active{background:#3f51b5;color:#fff}
+
+  .elem-card{border:0;border-radius:16px;overflow:hidden;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .elem-card .card-header{
+    background:linear-gradient(135deg,#6a11cb,#2575fc);
+    color:#fff;display:flex;justify-content:space-between;align-items:center
+  }
+  .type-badge{
+    background:#ffffff22;color:#fff;border-radius:999px;padding:2px 10px;font-size:.8rem
+  }
+  .line-clamp-3{
+    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden
+  }
+  .empty{
+    border:2px dashed #e9ecef;border-radius:16px;padding:24px;text-align:center;color:#6c757d
+  }
+  .badge-soft-success{
+    background:#e6f4ea;color:#166534;border:1px solid #cfead7;font-weight:600;
+  }
+  .badge-soft-danger{
+    background:#fde8e8;color:#b91c1c;border:1px solid #f5c2c7;font-weight:600;
+  }
+</style>
+
+<div class="page-hero">
+  <div>
+    <h2 class="mb-1"><i class="bi bi-flask me-1"></i> Хемиски елементи</h2>
+    <div class="opacity-75">Вкупно: <b>{{ elements|length if elements else 0 }}</b> записи</div>
+  </div>
+  {% if user_role == 'teacher' %}
+    <a href="/elements/add" class="btn btn-light fw-semibold">
+      <i class="bi bi-plus-circle"></i> Додај нов елемент
+    </a>
+  {% endif %}
+</div>
+
+<div class="toolbar">
+  <div class="input-group search-input">
+    <span class="input-group-text"><i class="bi bi-search"></i></span>
+    <input id="search" class="form-control" placeholder="Пребарај по симбол/име/опис…">
+  </div>
+
+  <select id="sort" class="form-select" style="max-width:260px">
+    <option value="name_az">Сортирај: Име (A–Z)</option>
+    <option value="name_za">Име (Z–A)</option>
+    <option value="symbol_az">Симбол (A–Z)</option>
+    <option value="symbol_za">Симбол (Z–A)</option>
+    <option value="atomic_asc">Атомски број ↑</option>
+    <option value="atomic_desc">Атомски број ↓</option>
+    <option value="weight_asc">Атомска маса ↑</option>
+    <option value="weight_desc">Атомска маса ↓</option>
+  </select>
+
+  <div class="ms-auto d-flex align-items-center gap-2 flex-wrap">
+    <small class="text-muted">Филтер по опасност:</small>
+    <div id="hazard-chips"></div>
+  </div>
+</div>
+
+{% if not elements %}
+  <div class="empty">
+    <div style="font-size:36px">🧪</div>
+    <div class="mt-2">Нема внесени елементи.</div>
+    {% if user_role == 'teacher' %}
+      <a href="/elements/add" class="btn btn-primary btn-sm mt-2">Додај прв елемент</a>
+    {% endif %}
+  </div>
+{% else %}
+  <div id="elem-grid" class="row">
+    {% for el in elements %}
+    {% set hazard_txt = (el.hazard_type or '') %}
+    {% set hazard_norm = hazard_txt|lower|trim %}
+    {% set hazard_clean =
+         hazard_norm if hazard_norm not in ['','нема','нема опасност','безбедно','safe','none'] else 'без опасност' %}
+    <div class="col-md-6 col-lg-4 mb-3 elem-item"
+         data-id="{{ el.element_id }}"
+         data-symbol="{{ el.symbol|lower }}"
+         data-name="{{ el.element_name|lower }}"
+         data-atomic="{{ el.atomic_number or 0 }}"
+         data-weight="{{ el.atomic_weight or 0 }}"
+         data-hazard="{{ hazard_clean }}"
+         data-text="{{ (el.symbol ~ ' ' ~ el.element_name ~ ' ' ~ hazard_txt ~ ' ' ~ (el.description_element or ''))|lower }}">
+      <div class="card elem-card h-100">
+        <div class="card-header">
+          <h5 class="mb-0 text-truncate">{{ el.element_name }}</h5>
+          <span class="type-badge" title="Атомски број">№ {{ el.atomic_number }}</span>
+        </div>
+        <div class="card-body d-flex flex-column">
+          <div class="d-flex justify-content-center align-items-center mb-2" style="gap:10px">
+            <div class="display-6 fw-bold">{{ el.symbol }}</div>
+            <span class="text-muted">({{ "%.2f"|format(el.atomic_weight) if el.atomic_weight is not none else "—" }})</span>
+          </div>
+
+          <ul class="list-unstyled small text-muted mb-2">
+            {% if el.melting_point %}<li>Топење: {{ el.melting_point }}°C</li>{% endif %}
+            {% if el.boiling_point %}<li>Вриење: {{ el.boiling_point }}°C</li>{% endif %}
+          </ul>
+
+          {% if hazard_clean != 'без опасност' %}
+            <span class="badge badge-soft-danger">⚠ {{ el.hazard_type }}</span>
+          {% else %}
+            <span class="badge badge-soft-success">✔ Безбедно</span>
+          {% endif %}
+
+          {% if el.description_element %}
+            <p class="mt-2 line-clamp-3">{{ el.description_element }}</p>
+          {% endif %}
+
+          <div class="mt-auto d-flex gap-2">
+            <a href="/elements/{{ el.element_id }}" class="btn btn-outline-primary btn-sm">
+              <i class="bi bi-eye"></i> Детали
             </a>
-        {% endif %}
+            {% if user_role == 'teacher' %}
+            <a href="/elements/{{ el.element_id }}/edit" class="btn btn-outline-warning btn-sm">
+              <i class="bi bi-pencil-square"></i> Едитирај
+            </a>
+            {% endif %}
+          </div>
+        </div>
+      </div>
     </div>
-
-    {% if error %}
-        <div class="alert alert-warning">{{ error }}</div>
-    {% else %}
-        <div class="row g-4">
-            {% for element in elements %}
-            <div class="col-sm-6 col-md-4 col-lg-3">
-                <div class="card element-card shadow-lg border-0 h-100 
-                    {% if element.hazard_type and (element.hazard_type != 'Нема опасност' and element.hazard_type != 'Нема') %} element-hazard {% endif %}">
-                    
-                    <div class="card-body text-center">
-                        <div class="element-symbol mb-2">{{ element.symbol }}</div>
-                        <h6 class="text-muted">{{ element.element_name }}</h6>
-
-                        <ul class="list-unstyled small mt-3">
-                            <li><strong>№:</strong> {{ element.atomic_number }}</li>
-                            <li><strong>Маса:</strong> {{ element.atomic_weight }}</li>
-                            {% if element.melting_point %}
-                                <li>Топење: {{ element.melting_point }}°C</li>
-                            {% endif %}
-                            {% if element.boiling_point %}
-                                <li>Вриење: {{ element.boiling_point }}°C</li>
-                            {% endif %}
-                        </ul>
-
-                        {% if element.hazard_type and element.hazard_type != 'Нема опасност' %}
-                        <span class="badge bg-danger mt-2">⚠ {{ element.hazard_type }}</span>
-                        {% else %}
-                        <span class="badge bg-success mt-2">✔ Безбедно</span>
-                        {% endif %}
-                        
-                        <div class="d-flex justify-content-center gap-2 mt-3">
-                            <a href="/elements/{{ element.element_id }}" class="btn btn-outline-primary btn-sm">
-                                <i class="bi bi-search"></i> Детали
-                            </a>
-                            {% if user_role == 'teacher' %}
-                                <a href="/elements/{{ element.element_id }}/edit" class="btn btn-outline-warning btn-sm">
-                                    <i class="bi bi-pencil"></i> Едитирај
-                                </a>
-                            {% endif %}
-                        </div>
-                    </div>
-                </div>
-            </div>
-            {% endfor %}
-        </div>
-    {% endif %}
-
-    <div class="mt-4">
-        <a href="/dashboard" class="btn btn-secondary">
-            <i class="bi bi-arrow-left"></i> Назад до Dashboard
-        </a>
-    </div>
+    {% endfor %}
+  </div>
+{% endif %}
+
+<div class="mt-3">
+  <a href="/dashboard" class="btn btn-secondary"><i class="bi bi-arrow-left"></i> Назад до Dashboard</a>
 </div>
 
-<style>
-.element-card {
-    transition: transform 0.25s ease, box-shadow 0.25s ease;
-    border-radius: 15px;
-    background: linear-gradient(145deg, #ffffff, #f1f5f9);
-}
-.element-card:hover {
-    transform: translateY(-6px) scale(1.03);
-    box-shadow: 0 12px 24px rgba(0,0,0,0.15);
-}
-.element-symbol {
-    font-size: 2.8rem;
-    font-weight: bold;
-    color: #0d6efd; /* сина за нормални */
-}
-/* Ако е опасен елемент */
-.element-hazard {
-    background: linear-gradient(145deg, #fff5f5, #ffecec);
-    border: 1px solid #f5c2c7;
-}
-.element-hazard .element-symbol {
-    color: #dc3545; /* црвена боја за опасни */
-}
-</style>
+<script>
+  // Клиентска логика (ист „feeling“ како кај опрема)
+  const items   = [...document.querySelectorAll('.elem-item')];
+  const grid    = document.getElementById('elem-grid');
+  const search  = document.getElementById('search');
+  const sortSel = document.getElementById('sort');
+  const chipsWrap = document.getElementById('hazard-chips');
+
+  // 1) генерирај чипови по hazard (вкл. „без опасност“)
+  const HAZ = [...new Set(items.map(i => i.dataset.hazard))].sort((a,b)=>{
+    if(a==='без опасност') return -1;
+    if(b==='без опасност') return 1;
+    return a.localeCompare(b,'mk');
+  });
+  let activeHaz = null;
+  HAZ.forEach(h=>{
+    const chip = document.createElement('button');
+    chip.type='button'; chip.className='chip'; chip.textContent=h;
+    chip.addEventListener('click', ()=>{
+      if(activeHaz===h){ activeHaz=null; chip.classList.remove('active'); }
+      else{
+        activeHaz=h;
+        [...chipsWrap.children].forEach(c=>c.classList.remove('active'));
+        chip.classList.add('active');
+      }
+      applyFilters();
+    });
+    chipsWrap.appendChild(chip);
+  });
+
+  // 2) пребарување
+  search.addEventListener('input', applyFilters);
+
+  // 3) сортирање
+  sortSel.addEventListener('change', applySort);
+  function applySort(){
+    const val = sortSel.value;
+    const sorted = [...items].sort((a,b)=>{
+      const an=a.dataset.name, bn=b.dataset.name;
+      const as=a.dataset.symbol, bs=b.dataset.symbol;
+      const aZ=parseFloat(a.dataset.atomic)||0, bZ=parseFloat(b.dataset.atomic)||0;
+      const aW=parseFloat(a.dataset.weight)||0, bW=parseFloat(b.dataset.weight)||0;
+      if(val==='name_az')     return an.localeCompare(bn,'mk');
+      if(val==='name_za')     return bn.localeCompare(an,'mk');
+      if(val==='symbol_az')   return as.localeCompare(bs,'mk');
+      if(val==='symbol_za')   return bs.localeCompare(as,'mk');
+      if(val==='atomic_asc')  return aZ-bZ;
+      if(val==='atomic_desc') return bZ-aZ;
+      if(val==='weight_asc')  return aW-bW;
+      if(val==='weight_desc') return bW-aW;
+      return 0;
+    });
+    sorted.forEach(el=>grid.appendChild(el));
+  }
+
+  // 4) комбиниран филтер (search + hazard chip)
+  function applyFilters(){
+    const q = (search.value||'').toLowerCase().trim();
+    items.forEach(it=>{
+      const okText = it.dataset.text.includes(q);
+      const okHaz  = !activeHaz || it.dataset.hazard === activeHaz;
+      it.style.display = (okText && okHaz) ? '' : 'none';
+    });
+  }
+
+  // иницијално
+  applySort(); // default: name A–Z
+</script>
 {% endblock %}
Index: templates/equipment_detail.html
===================================================================
--- templates/equipment_detail.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/equipment_detail.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,40 +3,133 @@
 
 {% block content %}
-<div class="row">
-    <div class="col-md-8 mx-auto">
-        <div class="card">
-            <div class="card-header d-flex justify-content-between">
-                <h3>{{ equipment.equipment_name }}</h3>
-                {% if user_role == 'teacher' %}
-                    <a href="/equipment/{{ equipment.equipment_id }}/edit" class="btn btn-warning btn-sm">Едитирај</a>
-                {% endif %}
-            </div>
-            <div class="card-body">
-                <div class="row">
-                    <div class="col-md-6">
-                        <h5>Основни информации</h5>
-                        <p><strong>Тип:</strong> {{ equipment.type or 'Не е специфициран' }}</p>
-                        <p><strong>Опис:</strong></p>
-                        <p>{{ equipment.description or 'Нема достапен опис' }}</p>
-                    </div>
-                    <div class="col-md-6">
-                        <h5>Безбедносни информации</h5>
-                        {% if equipment.safety_info %}
-                            <div class="alert alert-warning">
-                                {{ equipment.safety_info }}
-                            </div>
-                        {% else %}
-                            <p class="text-muted">Нема специфични безбедносни барања</p>
-                        {% endif %}
-                    </div>
-                </div>
-            </div>
+<style>
+  .hero{
+    background: linear-gradient(135deg,#6a11cb,#2575fc);
+    color:#fff;border-radius:18px;padding:18px 22px;
+    display:flex;align-items:center;justify-content:space-between;gap:12px
+  }
+  .type-badge{
+    background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;
+    font-weight:600; letter-spacing:.2px
+  }
+  .wrap{display:grid;grid-template-columns:1.4fr .8fr;gap:18px;margin-top:16px}
+  @media (max-width: 992px){ .wrap{grid-template-columns:1fr} }
+  .card.block{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .section-title{font-weight:800;margin-bottom:.35rem}
+  .muted{color:#6c757d}
+  .line-clamp-6{
+    display:-webkit-box;-webkit-line-clamp:6;-webkit-box-orient:vertical;overflow:hidden
+  }
+  .fact-row .row + .row{margin-top:10px}
+  .btn-ghost{background:#00000008;border:1px solid #ffffff55;color:#fff}
+</style>
+
+<!-- HERO -->
+<div class="hero">
+  <div class="d-flex align-items-center gap-3">
+    <div style="width:42px;height:42px;border-radius:12px;background:#ffffff22;display:flex;align-items:center;justify-content:center">
+      <i class="bi bi-tools" style="font-size:20px"></i>
+    </div>
+    <div>
+      <h2 class="mb-0 text-truncate">{{ equipment.equipment_name }}</h2>
+      <div class="small opacity-75">Лабораториска опрема</div>
+    </div>
+  </div>
+
+  <div class="d-flex align-items-center gap-2">
+    <span class="type-badge" title="Тип на опрема">
+      <i class="bi bi-tag me-1"></i>{{ equipment.type or 'Не е специфициран' }}
+    </span>
+    {% if user_role == 'teacher' %}
+      <a href="/equipment/{{ equipment.equipment_id }}/edit" class="btn btn-light btn-sm fw-semibold">
+        <i class="bi bi-pencil-square"></i> Едитирај
+      </a>
+    {% endif %}
+    <button class="btn btn-ghost btn-sm" onclick="window.print()"><i class="bi bi-printer"></i></button>
+  </div>
+</div>
+
+<div class="wrap">
+  <!-- ЛЕВО -->
+  <div class="card block">
+    <div class="card-body">
+      <h5 class="section-title"><i class="bi bi-info-circle"></i> Основни информации</h5>
+      {% if equipment.description %}
+        <p class="mb-3 line-clamp-6" id="desc">{{ equipment.description }}</p>
+        <button class="btn btn-outline-secondary btn-sm" onclick="copyText('#desc')">
+          <i class="bi bi-clipboard"></i> Копирај опис
+        </button>
+      {% else %}
+        <p class="muted">Нема достапен опис.</p>
+      {% endif %}
+
+      <hr class="my-4"/>
+
+      <h5 class="section-title"><i class="bi bi-shield-exclamation"></i> Безбедносни информации</h5>
+      {% if equipment.safety_info %}
+        <div class="alert alert-warning mb-2" id="safety">{{ equipment.safety_info }}</div>
+        <div class="d-flex gap-2">
+          <button class="btn btn-outline-warning btn-sm" onclick="copyText('#safety')">
+            <i class="bi bi-clipboard-check"></i> Копирај безбедност
+          </button>
+          <button class="btn btn-outline-dark btn-sm" data-bs-toggle="collapse" data-bs-target="#safetyTips">
+            <i class="bi bi-chevron-down"></i> Совети
+          </button>
         </div>
-        
-        <div class="mt-3">
-            <a href="/equipment" class="btn btn-secondary">Назад до листа</a>
-            <a href="/dashboard" class="btn btn-primary">Dashboard</a>
+        <div id="safetyTips" class="collapse mt-2">
+          <ul class="small mb-0">
+            <li>Провери PPE (ракавици/очила/мантила) пред употреба.</li>
+            <li>Почитувај процедури за чистење и складирање.</li>
+            <li>Пријави оштетувања и неисправности веднаш.</li>
+          </ul>
         </div>
+      {% else %}
+        <p class="muted">Нема специфични безбедносни барања.</p>
+      {% endif %}
     </div>
+  </div>
+
+  <!-- ДЕСНО -->
+  <div class="card block">
+    <div class="card-body fact-row">
+      <h6 class="section-title"><i class="bi bi-list-ul"></i> Брзи факти</h6>
+      <div class="row">
+        <div class="col-5 muted">Тип</div>
+        <div class="col-7 fw-semibold">{{ equipment.type or '—' }}</div>
+      </div>
+      <div class="row">
+        <div class="col-5 muted">ID</div>
+        <div class="col-7 fw-semibold">#{{ equipment.equipment_id }}</div>
+      </div>
+
+      <hr class="my-3"/>
+
+      <h6 class="section-title"><i class="bi bi-compass"></i> Навигација</h6>
+      <div class="d-grid gap-2">
+        <a href="/equipment" class="btn btn-outline-primary btn-sm">
+          <i class="bi bi-arrow-left"></i> Назад до листа
+        </a>
+        <a href="/dashboard" class="btn btn-outline-secondary btn-sm">
+          <i class="bi bi-speedometer2"></i> Dashboard
+        </a>
+        <a href="/laboratory" class="btn btn-outline-dark btn-sm">
+          <i class="bi bi-flask"></i> Виртуелна лабораторија
+        </a>
+      </div>
+    </div>
+  </div>
 </div>
+
+<script>
+  function copyText(selector){
+    const el = document.querySelector(selector);
+    if(!el) return;
+    const text = el.innerText.trim();
+    if(!text) return;
+    navigator.clipboard.writeText(text).then(()=>{
+      const btn = document.activeElement;
+      if(btn) { const old = btn.innerHTML; btn.innerHTML='✔ Копирано'; setTimeout(()=>btn.innerHTML=old,1200); }
+    });
+  }
+</script>
 {% endblock %}
Index: templates/equipment_list.html
===================================================================
--- templates/equipment_list.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/equipment_list.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,50 +3,178 @@
 
 {% block content %}
-<div class="row">
-    <div class="col-12">
-        <div class="d-flex justify-content-between align-items-center mb-3">
-            <h2>Лабораториска опрема</h2>
-            {% if user_role == 'teacher' %}
-                <a href="/equipment/add" class="btn btn-success">Додај нова опрема</a>
-            {% endif %}
-        </div>
-    </div>
+<style>
+  .page-hero{
+    background: linear-gradient(135deg,#232526,#414345);
+    color:#fff;border-radius:18px;padding:18px 22px;
+    display:flex;align-items:center;justify-content:space-between;gap:12px
+  }
+  .toolbar{
+    display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:14px 0
+  }
+  .search-input{min-width:260px}
+  .chip{
+    display:inline-flex;align-items:center;gap:8px;padding:6px 12px;margin:4px;
+    border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;cursor:pointer;
+    border:1px solid rgba(63,81,181,.25); user-select:none
+  }
+  .chip.active{background:#3f51b5;color:#fff}
+  .equip-card{border:0;border-radius:16px;overflow:hidden;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .equip-card .card-header{
+    background:linear-gradient(135deg,#6a11cb,#2575fc);
+    color:#fff;display:flex;justify-content:space-between;align-items:center
+  }
+  .type-badge{
+    background:#ffffff22;color:#fff;border-radius:999px;padding:2px 10px;font-size:.8rem
+  }
+  .line-clamp-3{
+    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden
+  }
+  .empty{
+    border:2px dashed #e9ecef;border-radius:16px;padding:24px;text-align:center;color:#6c757d
+  }
+</style>
+
+<div class="page-hero">
+  <div>
+    <h2 class="mb-1">Лабораториска опрема</h2>
+    <div class="opacity-75">Вкупно: <b>{{ equipment|length if equipment else 0 }}</b> записи</div>
+  </div>
+  {% if user_role == 'teacher' %}
+    <a href="/equipment/add" class="btn btn-light fw-semibold"><i class="bi bi-plus-circle"></i> Додај нова опрема</a>
+  {% endif %}
 </div>
 
-{% if error %}
-    <div class="alert alert-warning">{{ error }}</div>
+<div class="toolbar">
+  <div class="input-group search-input">
+    <span class="input-group-text"><i class="bi bi-search"></i></span>
+    <input id="search" class="form-control" placeholder="Пребарај по име/тип/опис...">
+  </div>
+  <select id="sort" class="form-select" style="max-width:220px">
+    <option value="name_az">Сортирај: Име (A–Z)</option>
+    <option value="name_za">Име (Z–A)</option>
+    <option value="type_az">Тип (A–Z)</option>
+    <option value="newest">Најново (ID ↓)</option>
+    <option value="oldest">Најстаро (ID ↑)</option>
+  </select>
+  <div id="type-chips" class="ms-auto"></div>
+</div>
+
+{% if not equipment %}
+  <div class="empty">
+    <div style="font-size:36px">🧰</div>
+    <div class="mt-2">Нема внесена опрема.</div>
+    {% if user_role == 'teacher' %}
+      <a href="/equipment/add" class="btn btn-primary btn-sm mt-2">Додај прва ставка</a>
+    {% endif %}
+  </div>
 {% else %}
-    <div class="row">
-        {% for item in equipment %}
-        <div class="col-md-6 col-lg-4 mb-3">
-            <div class="card">
-                <div class="card-header d-flex justify-content-between">
-                    <h5 class="mb-0">{{ item.equipment_name }}</h5>
-                    <small class="text-muted">{{ item.type }}</small>
-                </div>
-                <div class="card-body">
-                    <p class="card-text">{{ item.description }}</p>
-                    
-                    {% if item.safety_info %}
-                        <div class="alert alert-warning alert-sm p-2">
-                            <strong>Безбедност:</strong> {{ item.safety_info }}
-                        </div>
-                    {% endif %}
-                    
-                    <div class="mt-2">
-                        <a href="/equipment/{{ item.equipment_id }}" class="btn btn-info btn-sm">Детали</a>
-                        {% if user_role == 'teacher' %}
-                            <a href="/equipment/{{ item.equipment_id }}/edit" class="btn btn-warning btn-sm">Едитирај</a>
-                        {% endif %}
-                    </div>
-                </div>
-            </div>
+  <div id="equip-grid" class="row">
+    {% for item in equipment %}
+    <div class="col-md-6 col-lg-4 mb-3 equip-item"
+         data-id="{{ item.equipment_id }}"
+         data-name="{{ item.equipment_name|lower }}"
+         data-type="{{ (item.type or '')|lower }}"
+         data-text="{{ (item.equipment_name ~ ' ' ~ (item.type or '') ~ ' ' ~ (item.description or ''))|lower }}">
+      <div class="card equip-card h-100">
+        <div class="card-header">
+          <h5 class="mb-0 text-truncate"><i class="bi bi-tools me-1"></i>{{ item.equipment_name }}</h5>
+          <span class="type-badge text-truncate" title="Тип">{{ item.type or '—' }}</span>
         </div>
-        {% endfor %}
+        <div class="card-body d-flex flex-column">
+          {% if item.description %}
+          <p class="card-text line-clamp-3">{{ item.description }}</p>
+          {% else %}
+          <p class="text-muted">Нема опис.</p>
+          {% endif %}
+
+          {% if item.safety_info %}
+          <div class="alert alert-warning py-2 px-3 mt-auto">
+            <strong><i class="bi bi-shield-exclamation"></i> Безбедност:</strong>
+            <span class="d-block mt-1">{{ item.safety_info }}</span>
+          </div>
+          {% endif %}
+
+          <div class="mt-3 d-flex gap-2">
+            <a href="/equipment/{{ item.equipment_id }}" class="btn btn-outline-primary btn-sm">
+              <i class="bi bi-eye"></i> Детали
+            </a>
+            {% if user_role == 'teacher' %}
+            <a href="/equipment/{{ item.equipment_id }}/edit" class="btn btn-outline-warning btn-sm">
+              <i class="bi bi-pencil-square"></i> Едитирај
+            </a>
+            {% endif %}
+          </div>
+        </div>
+      </div>
     </div>
+    {% endfor %}
+  </div>
 {% endif %}
 
 <div class="mt-3">
-    <a href="/dashboard" class="btn btn-secondary">Назад до Dashboard</a>
+  <a href="/dashboard" class="btn btn-secondary"><i class="bi bi-arrow-left"></i> Назад до Dashboard</a>
 </div>
+
+<script>
+  // Клиентски филтер/сортирање/чипови – без бекенд промени
+  const items = [...document.querySelectorAll('.equip-item')];
+  const search = document.getElementById('search');
+  const sortSel = document.getElementById('sort');
+  const chipsWrap = document.getElementById('type-chips');
+
+  // 1) генерирај филтер по тип (чипови)
+  const TYPES = [...new Set(items.map(i => i.dataset.type).filter(Boolean))].sort();
+  let activeType = null;
+  TYPES.forEach(t=>{
+    const chip = document.createElement('button');
+    chip.type='button';
+    chip.className='chip';
+    chip.textContent = t || '—';
+    chip.addEventListener('click', ()=>{
+      if(activeType===t){ activeType=null; chip.classList.remove('active'); }
+      else{
+        activeType=t;
+        [...chipsWrap.children].forEach(c=>c.classList.remove('active'));
+        chip.classList.add('active');
+      }
+      applyFilters();
+    });
+    chipsWrap.appendChild(chip);
+  });
+
+  // 2) пребарување
+  search.addEventListener('input', applyFilters);
+
+  // 3) сортирање
+  sortSel.addEventListener('change', applySort);
+  function applySort(){
+    const val = sortSel.value;
+    const grid = document.getElementById('equip-grid');
+    const sorted = [...items].sort((a,b)=>{
+      const an=a.dataset.name, bn=b.dataset.name;
+      const at=a.dataset.type, bt=b.dataset.type;
+      const ai=+a.dataset.id, bi=+b.dataset.id;
+      if(val==='name_az')   return an.localeCompare(bn,'mk');
+      if(val==='name_za')   return bn.localeCompare(an,'mk');
+      if(val==='type_az'){  const c=at.localeCompare(bt,'mk'); return c||an.localeCompare(bn,'mk'); }
+      if(val==='newest')    return bi-ai;
+      if(val==='oldest')    return ai-bi;
+      return 0;
+    });
+    sorted.forEach(el=>grid.appendChild(el));
+  }
+
+  // 4) комбиниран филтер
+  function applyFilters(){
+    const q = (search.value||'').toLowerCase().trim();
+    items.forEach(it=>{
+      const matchText = it.dataset.text.includes(q);
+      const matchType = !activeType || it.dataset.type===activeType;
+      it.style.display = (matchText && matchType) ? '' : 'none';
+    });
+  }
+
+  // иницијално сортирај (A–Z)
+  applySort();
+</script>
 {% endblock %}
Index: templates/experiments_list.html
===================================================================
--- templates/experiments_list.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/experiments_list.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,127 +3,199 @@
 
 {% block content %}
-<div class="row">
-    <div class="col-12">
-        <h2>🧪 Сите експерименти во системот</h2>
-        <p class="text-muted">
-            {% if user_role == 'teacher' %}
-            Преглед на сите експерименти (професорски пристап)
-            {% else %}
-            Преглед на јавно достапни експерименти
+<style>
+  .page-hero{background:linear-gradient(135deg,#232526,#414345);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:14px 0}
+  .search-input{min-width:260px}
+  .chip{display:inline-flex;align-items:center;gap:8px;padding:6px 12px;margin:4px;border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;border:1px solid rgba(63,81,181,.25);user-select:none;font-size:.9rem;cursor:pointer}
+  .chip.active{background:#3f51b5;color:#fff}
+  .exp-card{border:0;border-radius:16px;overflow:hidden;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .exp-card .card-header{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;display:flex;justify-content:space-between;align-items:center}
+  .eq{font-weight:800;font-size:18px;background:#f8f9fa;border:1px solid #edf0f4;border-radius:12px;padding:10px 12px}
+  .empty{border:2px dashed #e9ecef;border-radius:16px;padding:24px;text-align:center;color:#6c757d}
+  .meta-badges{display:flex;gap:6px;flex-wrap:wrap}
+  .meta-badges .badge{border-radius:999px}
+  .showmore{border:0;background:#eef2ff;border-radius:10px;padding:6px 10px;font-weight:600}
+</style>
+
+<div class="page-hero">
+  <div>
+    <h2 class="mb-1">🧪 Сите експерименти</h2>
+    <div class="opacity-75">
+      {% if user_role == 'teacher' %}Професорски преглед{% else %}Јавно достапни{% endif %}
+      · Вкупно: <b>{{ experiments|length if experiments else 0 }}</b>
+    </div>
+  </div>
+  <div class="d-flex gap-2">
+    <a href="/dashboard" class="btn btn-light btn-sm"><i class="bi bi-speedometer2"></i> Dashboard</a>
+    <a href="/laboratory" class="btn btn-outline-light btn-sm"><i class="bi bi-flask"></i> Лабораторија</a>
+  </div>
+</div>
+
+{% if not experiments %}
+  <div class="empty mt-3">
+    Нема експерименти во системот.
+    {% if user_role == 'teacher' %}<div class="mt-2"><a href="/reactions/add" class="btn btn-primary btn-sm">Додај реакција</a></div>{% else %}
+    <div class="mt-2"><a href="/laboratory" class="btn btn-primary btn-sm">Отвори лабораторија</a></div>{% endif %}
+  </div>
+{% else %}
+  <!-- Toolbar -->
+  <div class="toolbar">
+    <div class="input-group search-input">
+      <span class="input-group-text"><i class="bi bi-search"></i></span>
+      <input id="search" class="form-control" placeholder="Пребарај по елемент/продукт/услов/опис...">
+    </div>
+    <select id="sort" class="form-select" style="max-width:220px">
+      <option value="id_desc">Најново (ID ↓)</option>
+      <option value="id_asc">Најстаро (ID ↑)</option>
+      <option value="prod_az">Продукт (A–Z)</option>
+      <option value="elem_az">Елементи (A–Z)</option>
+    </select>
+    <div class="ms-auto d-flex align-items-center flex-wrap" id="chips">
+      <!-- ќе се полни од JS -->
+    </div>
+  </div>
+
+  <!-- Grid -->
+  <div id="exp-grid" class="row">
+    {% for e in experiments %}
+    {% set has_eq = (e.equipment and e.equipment|length>0) %}
+    {% set has_warn = (e.safety_warning and e.safety_warning|length>0) %}
+    <div class="col-md-6 col-lg-4 mb-3 exp-item"
+         data-id="{{ e.experiment_id }}"
+         data-prod="{{ (e.product or '')|lower }}"
+         data-elems="{{ (e.element1_symbol ~ ' ' ~ e.element2_symbol ~ ' ' ~ e.element1_name ~ ' ' ~ e.element2_name)|lower }}"
+         data-conds="{{ (e.conditions or '')|lower }}"
+         data-text="{{ (e.result or '')|lower }}"
+         data-has-eq="{{ 1 if has_eq else 0 }}"
+         data-has-warn="{{ 1 if has_warn else 0 }}">
+      <div class="card exp-card h-100">
+        <div class="card-header">
+          <h5 class="mb-0 text-truncate">
+            <span class="badge bg-dark">#{{ e.experiment_id }}</span>
+            {{ e.element1_symbol }} + {{ e.element2_symbol }}
+          </h5>
+          <small class="text-truncate">
+            {% if e.time_stamp %}{{ e.time_stamp.strftime('%d.%m.%Y') }}{% endif %}
+          </small>
+        </div>
+        <div class="card-body d-flex flex-column">
+          <div class="eq mb-3 text-center">
+            {{ e.element1_symbol }} + {{ e.element2_symbol }} → {{ e.product or '—' }}
+          </div>
+
+          <div class="meta-badges mb-2">
+            {% if has_eq %}<span class="badge text-bg-primary"><i class="bi bi-tools"></i> Опрема</span>{% endif %}
+            {% if has_warn %}<span class="badge text-bg-warning"><i class="bi bi-exclamation-triangle"></i> Предупредување</span>{% endif %}
+          </div>
+
+          <ul class="small list-unstyled mb-2">
+            <li><b>Реакција:</b> {{ e.element1_name }} + {{ e.element2_name }}</li>
+            <li><b>Услови:</b> {{ e.conditions or 'Стандардни услови' }}</li>
+          </ul>
+
+          {% if e.result %}
+          <div class="mb-2">
+            <b>Резултат:</b>
+            <div class="text-muted" id="res-{{e.experiment_id}}">
+              {{ e.result[:140] }}{% if e.result|length>140 %}…{% endif %}
+            </div>
+          </div>
+          {% endif %}
+
+          {% if has_eq %}
+          <div class="mt-2">
+            <b>Опрема:</b>
+            <ul class="small text-muted mb-0">
+              {% for q in e.equipment %}
+              <li>{{ q.equipment_name }}{% if q.type %} <span class="text-secondary">({{ q.type }})</span>{% endif %}</li>
+              {% endfor %}
+            </ul>
+          </div>
+          {% endif %}
+
+          {% if has_warn %}
+          <div class="alert alert-warning py-2 px-3 mt-2">
+            <small><b>⚠ Безбедност:</b> {{ e.safety_warning }}</small>
+          </div>
+          {% endif %}
+
+          <div class="mt-auto d-flex justify-content-between align-items-center">
+            <small class="text-muted"><b>Креирано од:</b> {{ e.created_by }}</small>
+            {% if e.result and e.result|length>140 %}
+              <button class="showmore" onclick="toggleMore({{e.experiment_id}})">Повеќе</button>
             {% endif %}
-        </p>
-    </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    {% endfor %}
+  </div>
+{% endif %}
+
+<div class="mt-3 text-center">
+  <a href="/dashboard" class="btn btn-secondary">🏠 Dashboard</a>
+  <a href="/laboratory" class="btn btn-success">🔬 Лабораторија</a>
+  {% if user_role == 'teacher' %}<a href="/reactions" class="btn btn-info">⚗️ Реакции</a>{% endif %}
 </div>
 
-{% if experiments %}
-<div class="row mt-3">
-    {% for experiment in experiments %}
-    <div class="col-md-6 mb-4">
-        <div class="card h-100">
-            <div class="card-header d-flex justify-content-between align-items-center">
-                <h5 class="mb-0">
-                    <span class="badge bg-primary">#{{ experiment.experiment_id }}</span>
-                    {{ experiment.element1_symbol }} + {{ experiment.element2_symbol }}
-                </h5>
-                <small class="text-muted">
-                    {{ experiment.time_stamp.strftime('%d.%m.%Y') if experiment.time_stamp }}
-                </small>
-            </div>
-            <div class="card-body">
-                <h6 class="card-title text-success">
-                    <strong>Продукт:</strong> {{ experiment.product }}
-                </h6>
-                
-                <div class="mb-3">
-                    <p class="mb-2">
-                        <strong>Реакција:</strong> 
-                        {{ experiment.element1_name }} + {{ experiment.element2_name }}
-                    </p>
-                    
-                    <p class="mb-2">
-                        <strong>Услови:</strong> 
-                        <span class="text-muted">{{ experiment.conditions or 'Стандардни услови' }}</span>
-                    </p>
-                    
-                    <p class="mb-2">
-                        <strong>Резултат:</strong> 
-                        <span class="text-muted">{{ experiment.result[:100] }}{% if experiment.result|length > 100 %}...{% endif %}</span>
-                    </p>
-                </div>
-                
-                {% if experiment.safety_warning %}
-                <div class="alert alert-warning py-2 mb-3">
-                    <small><strong>⚠️ Безбедност:</strong> {{ experiment.safety_warning }}</small>
-                </div>
-                {% endif %}
-                {% if experiment.equipment and experiment.equipment|length > 0 %}
-                    <p class="mb-2">
-                        <strong>Опрема:</strong>
-                    <ul class="small text-muted mb-0">
-                        {% for eq in experiment.equipment %}
-                        <li>
-                            {{ eq.equipment_name }}
-                            {% if eq.type %}<span class="text-secondary">({{ eq.type }})</span>{% endif %}
-                        </li>
-                        {% endfor %}
-                    </ul>
-                    </p>
-                    {% else %}
-                    <p class="mb-2">
-                        <strong>Опрема:</strong>
-                        <span class="text-muted">Нема евидентирана опрема</span>
-                    </p>
-                    {% endif %}
-                <div class="d-flex justify-content-between align-items-center">
-                    <small class="text-muted">
-                        <strong>Креирано од:</strong> {{ experiment.created_by }}
-                    </small>
-                </div>
-            </div>
-        </div>
-    </div>
-    {% endfor %}
-</div>
-
-<!-- Пагинација (ако има многу експерименти) -->
-{% if experiments|length > 12 %}
-<nav aria-label="Page navigation">
-    <ul class="pagination justify-content-center">
-        <li class="page-item disabled">
-            <a class="page-link" href="#" tabindex="-1">Previous</a>
-        </li>
-        <li class="page-item active"><a class="page-link" href="#">1</a></li>
-        <li class="page-item"><a class="page-link" href="#">2</a></li>
-        <li class="page-item"><a class="page-link" href="#">3</a></li>
-        <li class="page-item">
-            <a class="page-link" href="#">Next</a>
-        </li>
-    </ul>
-</nav>
-{% endif %}
-
-{% else %}
-<div class="row mt-4">
-    <div class="col-12">
-        <div class="alert alert-info text-center">
-            <h4>Нема експерименти во системот</h4>
-            {% if user_role == 'teacher' %}
-            <p>Започнете со креирање на реакции и експерименти.</p>
-            <a href="/reactions/add" class="btn btn-primary">Додај реакција</a>
-            {% else %}
-            <p>Сè уште нема извршени експерименти. Бидете први!</p>
-            <a href="/laboratory" class="btn btn-primary">Отвори лабораторија</a>
-            {% endif %}
-        </div>
-    </div>
-</div>
-{% endif %}
-
-<div class="mt-4 text-center">
-    <a href="/dashboard" class="btn btn-secondary">🏠 Dashboard</a>
-    <a href="/laboratory" class="btn btn-success">🔬 Лабораторија</a>
-    {% if user_role == 'teacher' %}
-    <a href="/reactions" class="btn btn-info">⚗️ Реакции</a>
-    {% endif %}
-</div>
+<script>
+  // Toggle long result text
+  function toggleMore(id){
+    const el=document.getElementById('res-'+id);
+    if(!el) return;
+    el.classList.toggle('expanded');
+    // прост toggle – ако сакаш, можеш да чуваш full текст во data-attr и да го заменаваш
+  }
+
+  const items=[...document.querySelectorAll('.exp-item')];
+  const search=document.getElementById('search');
+  const sortSel=document.getElementById('sort');
+  const chips=document.getElementById('chips');
+
+  // Чипови: Има опрема / Со предупредување
+  const filters = { eq:null, warn:null }; // null=all, 1=only yes, 0=only no
+  function addChip(label,key,val){
+    const c=document.createElement('button'); c.type='button'; c.className='chip'; c.textContent=label;
+    c.addEventListener('click', ()=>{
+      // циклус: null -> 1 -> 0 -> null
+      if(filters[key]===null) { filters[key]=1; c.classList.add('active'); c.textContent=label+' ✓'; }
+      else if(filters[key]===1){ filters[key]=0; c.classList.remove('active'); c.textContent=label+' ✕'; }
+      else { filters[key]=null; c.textContent=label; }
+      applyFilters();
+    });
+    chips.appendChild(c);
+  }
+  addChip('Има опрема','eq');
+  addChip('Предупредување','warn');
+
+  function applyFilters(){
+    const q=(search?.value||'').toLowerCase().trim();
+    items.forEach(it=>{
+      const text = [it.dataset.prod,it.dataset.elems,it.dataset.conds,it.dataset.text].join(' ');
+      const okText = text.includes(q);
+      const okEq   = (filters.eq===null)   || (+it.dataset.hasEq===filters.eq);
+      const okWarn = (filters.warn===null) || (+it.dataset.hasWarn===filters.warn);
+      it.style.display = (okText && okEq && okWarn) ? '' : 'none';
+    });
+  }
+  function applySort(){
+    const val=sortSel.value;
+    const grid=document.getElementById('exp-grid');
+    const sorted=[...items].sort((a,b)=>{
+      const ai=+a.dataset.id, bi=+b.dataset.id;
+      const ap=a.dataset.prod, bp=b.dataset.prod;
+      const ae=a.dataset.elems, be=b.dataset.elems;
+      if(val==='id_desc') return bi-ai;
+      if(val==='id_asc')  return ai-bi;
+      if(val==='prod_az') return ap.localeCompare(bp,'mk');
+      if(val==='elem_az') return ae.localeCompare(be,'mk');
+      return 0;
+    });
+    sorted.forEach(el=>grid.appendChild(el));
+  }
+
+  search?.addEventListener('input', applyFilters);
+  sortSel?.addEventListener('change', applySort);
+  applySort();
+</script>
 {% endblock %}
Index: templates/home.html
===================================================================
--- templates/home.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
+++ templates/home.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -0,0 +1,203 @@
+{% extends "base.html" %}
+{% block title %}SIMLAB — Виртуелна лабораторија{% endblock %}
+
+{% block content %}
+<style>
+  .hero{
+    background: linear-gradient(135deg,#232526,#414345);
+    color:#fff;border-radius:18px;padding:22px 24px;margin-bottom:18px;
+    display:flex;align-items:center;justify-content:space-between;gap:14px
+  }
+  .hero .kicker{opacity:.85;font-size:.95rem}
+  .hero .cta-wrap{display:flex;gap:10px;flex-wrap:wrap}
+  .soft{
+    background:#ffffff;border-radius:16px;box-shadow:0 10px 24px rgba(0,0,0,.06);
+    border:0
+  }
+  .feature-card .card-header{
+    background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border:0
+  }
+  .feature-card .iconbox{
+    width:42px;height:42px;border-radius:12px;background:#ffffff22;
+    display:flex;align-items:center;justify-content:center
+  }
+  .muted{color:#6c757d}
+  .quick{
+    display:grid;grid-template-columns:repeat(3,1fr);gap:14px
+  }
+  @media (max-width: 992px){ .quick{grid-template-columns:1fr} }
+  .pill-link{
+    display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:999px;
+    border:1px solid #e9ecef;background:#f8fafc;font-weight:600;text-decoration:none
+  }
+  .pill-link:hover{background:#eef2ff;border-color:#dfe4ff}
+</style>
+
+<!-- HERO -->
+<div class="hero">
+  <div>
+    <div class="kicker">🧪 SIMLAB — Виртуелна хемиска лабораторија</div>
+    <h2 class="mb-1">Учете, симулирајте и анализирајте реакции</h2>
+    <div class="opacity-75">Безбедно окружење за студенти и професори со реални податоци и извештаи</div>
+  </div>
+
+  <div class="cta-wrap">
+    {% if is_logged %}
+      <a href="/dashboard" class="btn btn-light fw-semibold">
+        <i class="bi bi-speedometer2"></i> Оди на Dashboard
+      </a>
+    {% else %}
+      <a href="/login" class="btn btn-light fw-semibold">
+        <i class="bi bi-box-arrow-in-right"></i> Најава
+      </a>
+      <a href="/register" class="btn btn-outline-light">
+        <i class="bi bi-person-plus"></i> Регистрација
+      </a>
+    {% endif %}
+    <button id="db-check" class="btn btn-ghost btn-sm" style="border:1px solid #ffffff55;color:#fff">
+      <i class="bi bi-activity"></i> Провери база
+    </button>
+  </div>
+</div>
+
+<!-- КЛУЧНИ ПАТЕКИ -->
+<div class="row g-3">
+  <!-- Елементи -->
+  <div class="col-md-4">
+    <div class="card soft feature-card h-100">
+      <div class="card-header d-flex align-items-center justify-content-between">
+        <div class="d-flex align-items-center gap-2">
+          <div class="iconbox"><i class="bi bi-flask"></i></div>
+          <h5 class="mb-0">Хемиски елементи</h5>
+        </div>
+        {% if role == 'teacher' %}
+          <a href="/elements/add" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-plus-circle"></i></a>
+        {% endif %}
+      </div>
+      <div class="card-body">
+        <p class="muted">Прелистајте ги елементите и нивните својства.</p>
+        <a href="/elements" class="btn btn-outline-primary">
+          <i class="bi bi-search"></i> Прегледај елементи
+        </a>
+      </div>
+    </div>
+  </div>
+
+  <!-- Опрема -->
+  <div class="col-md-4">
+    <div class="card soft feature-card h-100">
+      <div class="card-header d-flex align-items-center justify-content-between" style="background:linear-gradient(135deg,#11998e,#38ef7d)">
+        <div class="d-flex align-items-center gap-2">
+          <div class="iconbox"><i class="bi bi-tools"></i></div>
+          <h5 class="mb-0">Лабораториска опрема</h5>
+        </div>
+        {% if role == 'teacher' %}
+          <a href="/equipment/add" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-plus-circle"></i></a>
+        {% endif %}
+      </div>
+      <div class="card-body">
+        <p class="muted">Каталог на опрема со безбедносни насоки.</p>
+        <a href="/equipment" class="btn btn-outline-success">
+          <i class="bi bi-wrench"></i> Прегледај опрема
+        </a>
+      </div>
+    </div>
+  </div>
+
+  <!-- Лабораторија -->
+  <div class="col-md-4">
+    <div class="card soft feature-card h-100">
+      <div class="card-header d-flex align-items-center justify-content-between" style="background:linear-gradient(135deg,#ee0979,#ff6a00)">
+        <div class="d-flex align-items-center gap-2">
+          <div class="iconbox"><i class="bi bi-radioactive"></i></div>
+          <h5 class="mb-0">Виртуелна лабораторија</h5>
+        </div>
+      </div>
+      <div class="card-body">
+        <p class="muted">Симулирај реакции со drag-and-drop и евидентирај експерименти.</p>
+        <a href="/laboratory" class="btn btn-outline-danger">
+          <i class="bi bi-flask"></i> Отвори лабораторија
+        </a>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- Брзи врски / контекст по улога -->
+<div class="card soft mt-3">
+  <div class="card-body">
+    <div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
+      <div class="fw-bold"><i class="bi bi-lightning"></i> Брзи врски</div>
+      <div class="quick">
+        {% if role == 'teacher' %}
+          <a class="pill-link" href="/reactions"><i class="bi bi-diagram-3"></i> Реакции</a>
+          <a class="pill-link" href="/reports"><i class="bi bi-bar-chart"></i> Извештаи</a>
+          <a class="pill-link" href="/my_students"><i class="bi bi-people"></i> Мои студенти</a>
+        {% elif role == 'student' %}
+          <a class="pill-link" href="/my-experiments"><i class="bi bi-journal-text"></i> Мои експерименти</a>
+          <a class="pill-link" href="/elements"><i class="bi bi-flask"></i> Елементи</a>
+          <a class="pill-link" href="/laboratory"><i class="bi bi-radioactive"></i> Лабораторија</a>
+        {% else %}
+          <a class="pill-link" href="/elements"><i class="bi bi-flask"></i> Елементи</a>
+          <a class="pill-link" href="/equipment"><i class="bi bi-tools"></i> Опрема</a>
+          <a class="pill-link" href="/reports"><i class="bi bi-bar-chart"></i> Извештаи</a>
+        {% endif %}
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- Инфо секција -->
+<div class="row g-3 mt-3">
+  <div class="col-lg-7">
+    <div class="card soft">
+      <div class="card-body">
+        <h5 class="mb-2"><i class="bi bi-info-circle"></i> Што нуди SIMLAB?</h5>
+        <ul class="mb-0 muted">
+          <li>Каталог на елементи и лабораториска опрема.</li>
+          <li>Визуелна симулација на реакции со евиденција на експерименти.</li>
+          <li>Извештаи за активност/опрема/популарност на елементи.</li>
+          <li>Различни улоги: професор/студент со прилагодени алатки.</li>
+        </ul>
+      </div>
+    </div>
+  </div>
+  <div class="col-lg-5">
+    <div class="card soft">
+      <div class="card-body">
+        <h6 class="mb-2"><i class="bi bi-broadcast-pin"></i> Состојба на систем</h6>
+        <div id="db-status" class="small muted">Базата: <em>непроверено</em></div>
+        <div id="db-msg" class="mt-2"></div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<script>
+  // Лесен health-check кон /test-db (истиот што веќе го имаш)
+  const btn = document.getElementById('db-check');
+  const status = document.getElementById('db-status');
+  const msg = document.getElementById('db-msg');
+  if(btn){
+    btn.addEventListener('click', async () => {
+      btn.disabled = true; btn.innerHTML = '<i class="bi bi-hourglass-split"></i> Проверувам...';
+      try{
+        const res = await fetch('/test-db');
+        const data = await res.json();
+        if(data.status === 'success'){
+          status.innerHTML = 'Базата: <span class="text-success fw-semibold">онлајн</span>';
+          msg.innerHTML = '<div class="alert alert-success py-2 my-2"><i class="bi bi-check-circle"></i> ' + (data.message||'') + '</div>';
+        }else{
+          status.innerHTML = 'Базата: <span class="text-danger fw-semibold">проблем</span>';
+          msg.innerHTML = '<div class="alert alert-danger py-2 my-2"><i class="bi bi-x-octagon"></i> ' + (data.message||'') + '</div>';
+        }
+      }catch(e){
+        status.innerHTML = 'Базата: <span class="text-danger fw-semibold">недостапна</span>';
+        msg.innerHTML = '<div class="alert alert-danger py-2 my-2">Исклучок: ' + e + '</div>';
+      }finally{
+        btn.disabled = false; btn.innerHTML = '<i class="bi bi-activity"></i> Провери база';
+      }
+    });
+  }
+</script>
+{% endblock %}
Index: templates/my_experiments.html
===================================================================
--- templates/my_experiments.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/my_experiments.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,155 +3,190 @@
 
 {% block content %}
-<div class="row">
-    <div class="col-12">
-        <h2>📊 Мои експерименти</h2>
-        <p class="text-muted">
-            <strong>{{ user_name }}</strong> |
-            <span class="badge bg-{{ 'primary' if user_role == 'teacher' else 'success' }}">
-                {{ 'Професор' if user_role == 'teacher' else 'Студент' }}
-            </span>
-        </p>
-    </div>
+<style>
+  .hero{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .role-badge{background:#ffffff22;color:#fff;border-radius:999px;padding:6px 12px;font-weight:700}
+  .stat-card{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:14px 0}
+  .search-input{min-width:260px}
+  .exp-card{border:0;border-radius:16px;overflow:hidden;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .exp-card .card-header{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}
+  .eq{font-weight:800;font-size:18px;background:#f8f9fa;border:1px solid #edf0f4;border-radius:12px;padding:10px 12px}
+  .empty{border:2px dashed #e9ecef;border-radius:16px;padding:24px;text-align:center;color:#6c757d}
+</style>
+
+<!-- HERO -->
+<div class="hero">
+  <div>
+    <h2 class="mb-0">📊 Мои експерименти</h2>
+    <div class="small opacity-75">{{ user_name }}</div>
+  </div>
+  <div class="d-flex align-items-center gap-2">
+    <span class="role-badge"><i class="bi bi-person-badge"></i> {{ 'Професор' if user_role=='teacher' else 'Студент' }}</span>
+    <a href="/dashboard" class="btn btn-light btn-sm"><i class="bi bi-speedometer2"></i> Dashboard</a>
+    <a href="/laboratory" class="btn btn-outline-light btn-sm"><i class="bi bi-flask"></i> Нов експеримент</a>
+  </div>
 </div>
 
-{% if experiments %}
-<!-- Статистики -->
-<div class="row mt-3">
-    <div class="col-md-3">
-        <div class="card text-center">
-            <div class="card-body">
-                <h3 class="text-success">{{ experiments|map(attribute='product')|unique|list|length }}</h3>
-                <p class="text-muted mb-0">Различни продукти</p>
+{% if not experiments %}
+  <div class="empty mt-3">
+    📚 Немате извршено експерименти.
+    <div class="mt-2"><a href="/laboratory" class="btn btn-primary btn-sm">🔬 Отвори лабораторија</a></div>
+  </div>
+{% else %}
+
+  <!-- Mini-статистики -->
+  <div class="row mt-3">
+    <div class="col-md-4 mb-3">
+      <div class="card stat-card text-center">
+        <div class="card-body">
+          <h3 class="text-success">{{ experiments|map(attribute='product')|unique|list|length }}</h3>
+          <div class="text-muted mb-0">Различни продукти</div>
+        </div>
+      </div>
+    </div>
+    <div class="col-md-4 mb-3">
+      <div class="card stat-card text-center">
+        <div class="card-body">
+          <h3 class="text-warning">{{ experiments|selectattr('safety_warning')|list|length }}</h3>
+          <div class="text-muted mb-0">Со предупредувања</div>
+        </div>
+      </div>
+    </div>
+    <div class="col-md-4 mb-3">
+      <div class="card stat-card text-center">
+        <div class="card-body">
+          <h3 class="text-info">
+            {% if experiments[0].participation_timestamp %}
+              {{ experiments[0].participation_timestamp.strftime('%d.%m') }}
+            {% elif experiments[0].time_stamp %}
+              {{ experiments[0].time_stamp.strftime('%d.%m') }}
+            {% endif %}
+          </h3>
+          <div class="text-muted mb-0">Последен експеримент</div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- Toolbar (client-side filter/sort) -->
+  <div class="toolbar">
+    <div class="input-group search-input">
+      <span class="input-group-text"><i class="bi bi-search"></i></span>
+      <input id="search" class="form-control" placeholder="Пребарај по елемент/продукт/услов...">
+    </div>
+    <select id="sort" class="form-select" style="max-width:220px">
+      <option value="date_desc">Најново</option>
+      <option value="date_asc">Најстаро</option>
+      <option value="prod_az">Продукт (A–Z)</option>
+      <option value="elem_az">Елементи (A–Z)</option>
+    </select>
+  </div>
+
+  <!-- Grid -->
+  <div id="myexp-grid" class="row mt-1">
+    {% for x in experiments %}
+    <div class="col-md-6 col-lg-4 mb-4 myexp-item"
+         data-id="{{ x.experiment_id }}"
+         data-prod="{{ (x.product or '')|lower }}"
+         data-elems="{{ (x.element1_symbol ~ ' ' ~ x.element2_symbol ~ ' ' ~ x.element1_name ~ ' ' ~ x.element2_name)|lower }}"
+         data-conds="{{ (x.conditions or '')|lower }}"
+         data-date="{% if x.participation_timestamp %}{{ x.participation_timestamp.strftime('%Y%m%d%H%M%S') }}{% elif x.time_stamp %}{{ x.time_stamp.strftime('%Y%m%d%H%M%S') }}{% else %}0000{% endif %}">
+      <div class="card exp-card h-100">
+        <div class="card-header">
+          <div class="d-flex justify-content-between align-items-center text-white">
+            <span><i class="bi bi-flask"></i> Експеримент #{{ x.experiment_id }}</span>
+            <small>
+              {% if x.participation_timestamp %}{{ x.participation_timestamp.strftime('%d.%m.%Y') }}
+              {% elif x.time_stamp %}{{ x.time_stamp.strftime('%d.%m.%Y') }}{% endif %}
+            </small>
+          </div>
+        </div>
+        <div class="card-body">
+          <div class="reaction-equation text-center mb-3 p-3 bg-light rounded">
+            <strong class="d-block eq">{{ x.element1_symbol }} + {{ x.element2_symbol }} → {{ x.product }}</strong>
+          </div>
+
+          <div class="experiment-details">
+            <p class="mb-2"><strong>Реактанти:</strong><br>
+              <span class="text-muted">{{ x.element1_name }} + {{ x.element2_name }}</span></p>
+
+            <p class="mb-2"><strong>Услови:</strong><br>
+              <span class="text-muted">{{ x.conditions or 'Стандардни услови' }}</span></p>
+
+            {% if x.result %}
+            <p class="mb-2"><strong>Резултат:</strong><br>
+              <span class="text-muted">{{ x.result[:100] }}{% if x.result|length>100 %}…{% endif %}</span></p>
+            {% endif %}
+
+            {% if x.safety_warning %}
+            <div class="alert alert-warning py-2 px-2 mb-2">
+              <small><strong>⚠️ Безбедност:</strong> {{ x.safety_warning }}</small>
             </div>
+            {% endif %}
+
+            {% if x.equipment and x.equipment|length>0 %}
+            <p class="mb-2"><strong>Опрема:</strong></p>
+            <ul class="small text-muted mb-0">
+              {% for eq in x.equipment %}
+              <li>{{ eq.equipment_name }}{% if eq.type %} <span class="text-secondary">({{ eq.type }})</span>{% endif %}</li>
+              {% endfor %}
+            </ul>
+            {% else %}
+            <p class="mb-2"><strong>Опрема:</strong> <span class="text-muted">Нема евидентирана опрема</span></p>
+            {% endif %}
+          </div>
+
+          {% if x.participation_timestamp or x.time_stamp %}
+          <p class="text-muted text-center mt-3 mb-0">
+            <small><i class="bi bi-clock"></i>
+              {% if x.participation_timestamp %}{{ x.participation_timestamp.strftime('%H:%M:%S') }}
+              {% elif x.time_stamp %}{{ x.time_stamp.strftime('%H:%M:%S') }}{% endif %}
+            </small>
+          </p>
+          {% endif %}
         </div>
+      </div>
     </div>
-    <div class="col-md-3">
-        <div class="card text-center">
-            <div class="card-body">
-                <h3 class="text-warning">{{ experiments|selectattr('safety_warning')|list|length }}</h3>
-                <p class="text-muted mb-0">Со предупредувања</p>
-            </div>
-        </div>
-    </div>
-    <div class="col-md-3">
-        <div class="card text-center">
-            <div class="card-body">
-                <h3 class="text-info">
-                    {% if experiments[0].participation_timestamp %}
-                    {{ experiments[0].participation_timestamp.strftime('%d.%m') }}
-                    {% elif experiments[0].time_stamp %}
-                    {{ experiments[0].time_stamp.strftime('%d.%m') }}
-                    {% endif %}
-                </h3>
-                <p class="text-muted mb-0">Последен експеримент</p>
-            </div>
-        </div>
-    </div>
+    {% endfor %}
+  </div>
+
+{% endif %}
+
+<div class="mt-3 text-center">
+  <a href="/dashboard" class="btn btn-secondary">🏠 Dashboard</a>
+  <a href="/laboratory" class="btn btn-success">➕ Нов експеримент</a>
+  {% if user_role == 'teacher' %}<a href="/experiments" class="btn btn-info">📋 Сите експерименти</a>{% endif %}
 </div>
 
-<!-- Листа на експерименти -->
-<div class="row mt-4">
-    {% for experiment in experiments %}
-    <div class="col-md-6 col-lg-4 mb-4">
-        <div class="card shadow-sm h-100">
-            <div class="card-header bg-gradient" style="background: linear-gradient(45deg, #667eea, #764ba2);">
-                <div class="d-flex justify-content-between align-items-center text-white">
-                    <span><i class="bi bi-flask"></i> Експеримент #{{ experiment.experiment_id }}</span>
-                    <small>
-                        {% if experiment.participation_timestamp %}
-                        {{ experiment.participation_timestamp.strftime('%d.%m.%Y') }}
-                        {% elif experiment.time_stamp %}
-                        {{ experiment.time_stamp.strftime('%d.%m.%Y') }}
-                        {% endif %}
-                    </small>
-                </div>
-            </div>
-            <div class="card-body">
-                <!-- Реакција -->
-                <div class="reaction-equation text-center mb-3 p-3 bg-light rounded">
-                    <strong style="font-size: 18px; color: #764ba2;">
-                        {{ experiment.element1_symbol }} + {{ experiment.element2_symbol }} → {{ experiment.product }}
-                    </strong>
-                </div>
+<script>
+  const items=[...document.querySelectorAll('.myexp-item')];
+  const search=document.getElementById('search');
+  const sortSel=document.getElementById('sort');
 
-                <!-- Детали -->
-                <div class="experiment-details">
-                    <p class="mb-2">
-                        <strong>Реактанти:</strong><br>
-                        <span class="text-muted">{{ experiment.element1_name }} + {{ experiment.element2_name }}</span>
-                    </p>
-
-                    <p class="mb-2">
-                        <strong>Услови:</strong><br>
-                        <span class="text-muted">{{ experiment.conditions or 'Стандардни услови' }}</span>
-                    </p>
-
-                    <p class="mb-2">
-                        <strong>Резултат:</strong><br>
-                        <span class="text-muted">{{ experiment.result[:80] }}{% if experiment.result|length > 80 %}...{%
-                            endif %}</span>
-                    </p>
-
-                    {% if experiment.safety_warning %}
-                    <div class="alert alert-warning py-2 px-2 mb-2">
-                        <small><strong>⚠️ Безбедност:</strong> {{ experiment.safety_warning }}</small>
-                    </div>
-                    {% endif %}
-
-                    {% if experiment.participation_timestamp or experiment.time_stamp %}
-                    <p class="text-muted text-center mt-3 mb-0">
-                        <small>
-                            <i class="bi bi-clock"></i>
-                            {% if experiment.participation_timestamp %}
-                            {{ experiment.participation_timestamp.strftime('%H:%M:%S') }}
-                            {% else %}
-                            {{ experiment.time_stamp.strftime('%H:%M:%S') }}
-                            {% endif %}
-                        </small>
-                    </p>
-                    {% endif %}
-                    {% if experiment.equipment and experiment.equipment|length > 0 %}
-                    <p class="mb-2">
-                        <strong>Опрема:</strong>
-                    <ul class="small text-muted mb-0">
-                        {% for eq in experiment.equipment %}
-                        <li>
-                            {{ eq.equipment_name }}
-                            {% if eq.type %}<span class="text-secondary">({{ eq.type }})</span>{% endif %}
-                        </li>
-                        {% endfor %}
-                    </ul>
-                    </p>
-                    {% else %}
-                    <p class="mb-2">
-                        <strong>Опрема:</strong>
-                        <span class="text-muted">Нема евидентирана опрема</span>
-                    </p>
-                    {% endif %}
-                </div>
-            </div>
-        </div>
-    </div>
-    {% endfor %}
-</div>
-{% else %}
-<!-- Нема експерименти -->
-<div class="row mt-4">
-    <div class="col-12">
-        <div class="alert alert-info text-center">
-            <h4>📚 Немате извршено експерименти</h4>
-            <p>Започнете со користење на виртуелната лабораторија за да создадете ваши експерименти.</p>
-            <a href="/laboratory" class="btn btn-primary">🔬 Отвори лабораторија</a>
-        </div>
-    </div>
-</div>
-{% endif %}
-
-<div class="mt-4 text-center">
-    <a href="/dashboard" class="btn btn-secondary">🏠 Dashboard</a>
-    <a href="/laboratory" class="btn btn-success">➕ Нов експеримент</a>
-    {% if user_role == 'teacher' %}
-    <a href="/experiments" class="btn btn-info">📋 Сите експерименти</a>
-    {% endif %}
-</div>
+  function applyFilters(){
+    const q=(search?.value||'').toLowerCase().trim();
+    items.forEach(it=>{
+      const hay=[it.dataset.prod,it.dataset.elems,it.dataset.conds].join(' ');
+      it.style.display = hay.includes(q) ? '' : 'none';
+    });
+  }
+  function applySort(){
+    const v=sortSel?.value||'date_desc';
+    const grid=document.getElementById('myexp-grid');
+    const sorted=[...items].sort((a,b)=>{
+      const ad=+a.dataset.date, bd=+b.dataset.date;
+      const ap=a.dataset.prod, bp=b.dataset.prod;
+      const ae=a.dataset.elems, be=b.dataset.elems;
+      if(v==='date_desc') return bd-ad;
+      if(v==='date_asc')  return ad-bd;
+      if(v==='prod_az')   return ap.localeCompare(bp,'mk');
+      if(v==='elem_az')   return ae.localeCompare(be,'mk');
+      return 0;
+    });
+    sorted.forEach(el=>grid.appendChild(el));
+  }
+  search?.addEventListener('input', applyFilters);
+  sortSel?.addEventListener('change', applySort);
+  applySort();
+</script>
 {% endblock %}
Index: templates/my_students.html
===================================================================
--- templates/my_students.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/my_students.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -76,5 +76,5 @@
         <div class="card text-center">
             <div class="card-body">
-                {% set total_views = students|sum(attribute='total_elements_viewed') %}
+                {% set total_views = students|sum(attribute='total_elements_viewed')+ students|sum(attribute='total_lab_equipment_viewed') %}
                 <h5 class="card-title">{{ total_views }}</h5>
                 <p class="card-text">Вкупно прегледи</p>
Index: templates/reactions_list.html
===================================================================
--- templates/reactions_list.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/reactions_list.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,64 +3,143 @@
 
 {% block content %}
-<div class="row">
-    <div class="col-12">
-        <div class="d-flex justify-content-between align-items-center mb-3">
-            <h2>Хемиски реакции</h2>
-            {% if user_role == 'teacher' %}
-                <a href="/reactions/add" class="btn btn-success">Додај нова реакција</a>
-            {% endif %}
-        </div>
-    </div>
+<style>
+  .page-hero{background:linear-gradient(135deg,#232526,#414345);color:#fff;border-radius:18px;padding:18px 22px;display:flex;align-items:center;justify-content:space-between;gap:12px}
+  .toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:14px 0}
+  .search-input{min-width:260px}
+  .chip{display:inline-flex;align-items:center;gap:8px;padding:6px 12px;margin:4px;border-radius:999px;background:#eef2ff;color:#3f51b5;font-weight:600;border:1px solid rgba(63,81,181,.25);user-select:none;font-size:.9rem;cursor:pointer}
+  .chip.active{background:#3f51b5;color:#fff}
+  .rx-card{border:0;border-radius:16px;overflow:hidden;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .rx-card .card-header{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;display:flex;justify-content:space-between;align-items:center}
+  .eq{font-weight:800;font-size:18px;background:#f8f9fa;border:1px solid #edf0f4;border-radius:12px;padding:10px 12px}
+  .empty{border:2px dashed #e9ecef;border-radius:16px;padding:24px;text-align:center;color:#6c757d}
+</style>
+
+<div class="page-hero">
+  <div>
+    <h2 class="mb-1">Хемиски реакции</h2>
+    <div class="opacity-75">Вкупно: <b>{{ reactions|length if reactions else 0 }}</b></div>
+  </div>
+  {% if user_role == 'teacher' %}
+    <a href="/reactions/add" class="btn btn-light fw-semibold"><i class="bi bi-plus-circle"></i> Додај нова</a>
+  {% endif %}
 </div>
 
-<div class="row">
-    {% for reaction in reactions %}
-    <div class="col-md-6 col-lg-4 mb-3">
-        <div class="card">
-            <div class="card-header">
-                <h5 class="mb-0">Реакција #{{ reaction.reaction_id }}</h5>
-                <small class="text-muted">{{ reaction.created_by }}</small>
-            </div>
-            <div class="card-body">
-                <div class="reaction-equation text-center mb-3" style="font-size: 18px; font-weight: bold; background: #f8f9fa; padding: 15px; border-radius: 10px;">
-                    {{ reaction.element1_symbol }} + {{ reaction.element2_symbol }} → {{ reaction.product }}
-                </div>
-                
-                <p><strong>Елементи:</strong> {{ reaction.element1_name }} + {{ reaction.element2_name }}</p>
-                <p><strong>Продукт:</strong> {{ reaction.product }}</p>
-                <p><strong>Услови:</strong> {{ reaction.conditions or 'Стандардни услови' }}</p>
-                
-                <div class="mt-3">
-                    {% if user_role == 'teacher' %}
-                        <a href="/reactions/{{ reaction.reaction_id }}/edit" class="btn btn-warning btn-sm">Едитирај</a>
-                        <form method="POST" action="/reactions/{{ reaction.reaction_id }}/delete" style="display: inline;" 
-                              onsubmit="return confirm('Дали сте сигурни дека сакате да ја избришете реакцијата?')">
-                            <button type="submit" class="btn btn-danger btn-sm">Избриши</button>
-                        </form>
-                    {% endif %}
-                </div>
-            </div>
+<div class="toolbar">
+  <div class="input-group search-input">
+    <span class="input-group-text"><i class="bi bi-search"></i></span>
+    <input id="search" class="form-control" placeholder="Пребарај по симбол/име/услов...">
+  </div>
+  <select id="sort" class="form-select" style="max-width:220px">
+    <option value="id_desc">Најново (ID ↓)</option>
+    <option value="id_asc">Најстаро (ID ↑)</option>
+    <option value="sym_az">Симболи (A–Z)</option>
+    <option value="prod_az">Продукт (A–Z)</option>
+  </select>
+  <div id="chips" class="ms-auto"></div>
+</div>
+
+{% if not reactions %}
+  <div class="empty">
+    <div style="font-size:36px">🧪</div>
+    <div class="mt-2">Нема дефинирани реакции.</div>
+    {% if user_role == 'teacher' %}
+      <a href="/reactions/add" class="btn btn-primary btn-sm mt-2">Додај прва реакција</a>
+    {% endif %}
+  </div>
+{% else %}
+  <div id="rx-grid" class="row">
+    {% for r in reactions %}
+    <div class="col-md-6 col-lg-4 mb-3 rx-item"
+         data-id="{{ r.reaction_id }}"
+         data-sym="{{ (r.element1_symbol ~ r.element2_symbol)|lower }}"
+         data-prod="{{ (r.product or '')|lower }}"
+         data-text="{{ (r.element1_symbol ~ ' ' ~ r.element2_symbol ~ ' ' ~ (r.product or '') ~ ' ' ~ (r.conditions or '') ~ ' ' ~ (r.element1_name or '') ~ ' ' ~ (r.element2_name or ''))|lower }}">
+      <div class="card rx-card h-100">
+        <div class="card-header">
+          <h5 class="mb-0 text-truncate">Реакција #{{ r.reaction_id }}</h5>
+          <small class="text-truncate">{{ r.created_by }}</small>
         </div>
-    </div>
-    {% else %}
-    <div class="col-12">
-        <div class="alert alert-info text-center">
-            <h4>Нема дефинирани реакции</h4>
+        <div class="card-body d-flex flex-column">
+          <div class="eq mb-3 text-center">
+            {{ r.element1_symbol }} + {{ r.element2_symbol }} → {{ r.product or '—' }}
+          </div>
+
+          <ul class="small list-unstyled mb-2">
+            <li><b>Елементи:</b> {{ r.element1_name }} + {{ r.element2_name }}</li>
+            <li><b>Продукт:</b> {{ r.product or '—' }}</li>
+            <li><b>Услови:</b> {{ r.conditions or 'Стандардни услови' }}</li>
+          </ul>
+
+          <div class="mt-auto d-flex gap-2">
             {% if user_role == 'teacher' %}
-                <p>Започнете со додавање на нови реакции за вашите студенти.</p>
-                <a href="/reactions/add" class="btn btn-primary">Додај прва реакција</a>
-            {% else %}
-                <p>Вашиот професор сè уште не додал реакции во системот.</p>
+              <a href="/reactions/{{ r.reaction_id }}/edit" class="btn btn-outline-warning btn-sm">
+                <i class="bi bi-pencil-square"></i> Едитирај
+              </a>
+              <form method="POST" action="/reactions/{{ r.reaction_id }}/delete" onsubmit="return confirm('Да ја избришам реакцијата?')">
+                <button type="submit" class="btn btn-outline-danger btn-sm"><i class="bi bi-trash"></i> Избриши</button>
+              </form>
             {% endif %}
+          </div>
         </div>
+      </div>
     </div>
     {% endfor %}
+  </div>
+{% endif %}
+
+<div class="mt-3">
+  <a href="/dashboard" class="btn btn-secondary"><i class="bi bi-arrow-left"></i> Назад до Dashboard</a>
+  {% if user_role == 'student' %}
+    <a href="/laboratory" class="btn btn-primary"><i class="bi bi-flask"></i> Виртуелна лабораторија</a>
+  {% endif %}
 </div>
 
-<div class="mt-3">
-    <a href="/dashboard" class="btn btn-secondary">Назад до Dashboard</a>
-    {% if user_role == 'student' %}
-        <a href="/laboratory" class="btn btn-primary">Отвори лабораторија</a>
-    {% endif %}
-</div>
+<script>
+  const items=[...document.querySelectorAll('.rx-item')];
+  const search=document.getElementById('search');
+  const sortSel=document.getElementById('sort');
+  const chipsWrap=document.getElementById('chips');
+
+  // генерирај чипови за брз филтер по прва буква на продукт
+  const PROD_LETTERS=[...new Set(items.map(i=>(i.dataset.prod||'').charAt(0)).filter(Boolean))].sort();
+  let activeLetter=null;
+  PROD_LETTERS.forEach(l=>{
+    const c=document.createElement('button');
+    c.type='button'; c.className='chip'; c.textContent=l.toUpperCase();
+    c.addEventListener('click', ()=>{
+      if(activeLetter===l){ activeLetter=null; c.classList.remove('active'); }
+      else { activeLetter=l; [...chipsWrap.children].forEach(x=>x.classList.remove('active')); c.classList.add('active'); }
+      applyFilters();
+    });
+    chipsWrap.appendChild(c);
+  });
+
+  search.addEventListener('input', applyFilters);
+  sortSel.addEventListener('change', applySort);
+
+  function applyFilters(){
+    const q=(search.value||'').toLowerCase().trim();
+    items.forEach(it=>{
+      const matchText=it.dataset.text.includes(q);
+      const matchLetter=!activeLetter || (it.dataset.prod||'').startsWith(activeLetter);
+      it.style.display=(matchText && matchLetter) ? '' : 'none';
+    });
+  }
+  function applySort(){
+    const val=sortSel.value;
+    const grid=document.getElementById('rx-grid');
+    const sorted=[...items].sort((a,b)=>{
+      const ai=+a.dataset.id, bi=+b.dataset.id;
+      const as=a.dataset.sym, bs=b.dataset.sym;
+      const ap=a.dataset.prod, bp=b.dataset.prod;
+      if(val==='id_desc') return bi-ai;
+      if(val==='id_asc')  return ai-bi;
+      if(val==='sym_az')  return as.localeCompare(bs,'mk');
+      if(val==='prod_az') return ap.localeCompare(bp,'mk');
+      return 0;
+    });
+    sorted.forEach(el=>grid.appendChild(el));
+  }
+  applySort();
+</script>
 {% endblock %}
Index: templates/reports/detailed_experiments.html
===================================================================
--- templates/reports/detailed_experiments.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/reports/detailed_experiments.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -25,10 +25,23 @@
             {% for experiment in experiments %}
             <tr>
-                <td>{{ experiment.full_name }}</td>
+                <td>
+                    {{ experiment.get('full_name')
+                    or experiment.get('student_name')
+                    or ('#' ~ (experiment.get('student_id')|string)) }}
+                </td>
+
                 <td>
                     <span class="badge bg-primary">#{{ experiment.experiment_id }}</span>
                 </td>
                 <td>{{ experiment.result[:50] }}{% if experiment.result|length > 50 %}...{% endif %}</td>
-                <td>{{ experiment.participation_time.strftime('%d.%m.%Y %H:%M') if experiment.participation_time }}</td>
+                {% set ts = experiment.participation_date or expperiment.participation_time or experiment.time_stamp %}
+                <td>
+                    {% if ts %}
+                    {{ ts.strftime('%Y-%m-%d %H:%M') }}
+                    {% else %}
+                    —
+                    {% endif %}
+                </td>
+
                 <td><span class="badge bg-success">Завршен</span></td>
             </tr>
@@ -65,5 +78,6 @@
         <div class="card text-center">
             <div class="card-body">
-                {% set avg = (experiments|length / experiments|map(attribute='full_name')|unique|list|length)|round(1) if experiments %}
+                {% set avg = (experiments|length / experiments|map(attribute='full_name')|unique|list|length)|round(1)
+                if experiments %}
                 <h5 class="card-title">{{ avg if avg else 0 }}</h5>
                 <p class="card-text">Просечно по студент</p>
Index: templates/reports/generic_report.html
===================================================================
--- templates/reports/generic_report.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/reports/generic_report.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -5,35 +5,113 @@
 <div class="row">
   <div class="col-12">
-    <h2>{{ title }}</h2>
+    <h2 class="mb-1">{{ title }}</h2>
+    <p class="text-muted">{{ subtitle or "Преглед на податоци" }}</p>
   </div>
 </div>
 
 {% if rows and headers %}
-<div class="table-responsive mt-3">
-  <table class="table table-striped table-hover">
-    <thead class="table-light">
-      <tr>
-        {% for h in headers %}
-          <th>{{ h }}</th>
-        {% endfor %}
-      </tr>
-    </thead>
-    <tbody>
-      {% for r in rows %}
+  <!-- Toolbar -->
+  <div class="row align-items-center mb-3 g-2">
+    <div class="col-md-6">
+      <div class="input-group">
+        <span class="input-group-text"><i class="bi bi-search"></i></span>
+        <input id="rep-search" class="form-control" placeholder="Пребарај во табелата...">
+      </div>
+    </div>
+    <div class="col-md-6 text-md-end">
+      <button id="rep-export" class="btn btn-outline-secondary btn-sm">
+        <i class="bi bi-download"></i> CSV
+      </button>
+    </div>
+  </div>
+
+  <!-- Table -->
+  <div class="table-responsive">
+    <table class="table table-striped table-hover" id="rep-table">
+      <thead class="table-info">
         <tr>
           {% for h in headers %}
-            <td>{{ r[h] }}</td>
+            <th>{{ h.replace('_',' ')|title }}</th>
           {% endfor %}
         </tr>
-      {% endfor %}
-    </tbody>
-  </table>
-</div>
+      </thead>
+      <tbody>
+        {% for r in rows %}
+          <tr>
+            {% for h in headers %}
+              {% set v = r[h] %}
+              {% set key = h|lower %}
+              <td>
+                {# badge за ID полиња #}
+                {% if key.endswith('id') and v is not none %}
+                  <span class="badge bg-primary">#{{ v }}</span>
+                {% elif 'status' in key and v %}
+                  {% set vs = v|string|lower %}
+                  {% set cls = 'secondary' %}
+                  {% if 'успеш' in vs or 'done' in vs or 'complete' in vs %}{% set cls = 'success' %}{% endif %}
+                  {% if 'warn' in vs or 'pending' in vs or 'очек' in vs %}{% set cls = 'warning' %}{% endif %}
+                  {% if 'fail' in vs or 'error' in vs or 'греш' in vs %}{% set cls = 'danger' %}{% endif %}
+                  <span class="badge bg-{{ cls }}">{{ v }}</span>
+                {% else %}
+                  {% if v is string and v|length > 80 %}
+                    <span title="{{ v }}">{{ v[:80] }}…</span>
+                  {% else %}
+                    {{ v if v is not none and v != '' else '—' }}
+                  {% endif %}
+                {% endif %}
+              </td>
+            {% endfor %}
+          </tr>
+        {% endfor %}
+      </tbody>
+    </table>
+  </div>
+
+  <!-- Мали статистики (генерички) -->
 {% else %}
-<div class="alert alert-info mt-3">Нема податоци за прикажување.</div>
+  <div class="alert alert-info mt-3">Нема податоци за прикажување.</div>
 {% endif %}
 
 <div class="mt-3">
-  <a href="/reports" class="btn btn-secondary">◀ Назад кон извештаи</a>
+  <a href="/reports" class="btn btn-secondary"><i class="bi bi-arrow-left"></i> Назад кон извештаи</a>
 </div>
+
+<script>
+(() => {
+  const table = document.getElementById('rep-table');
+  if(!table) return;
+
+  // Live search
+  const search = document.getElementById('rep-search');
+  search.addEventListener('input', () => {
+    const q = (search.value || '').toLowerCase().trim();
+    [...table.tBodies[0].rows].forEach(tr => {
+      tr.style.display = tr.innerText.toLowerCase().includes(q) ? '' : 'none';
+    });
+  });
+
+  // CSV export (почитува активен филтер)
+  document.getElementById('rep-export').addEventListener('click', () => {
+    const head = [...table.tHead.rows[0].cells].map(th => th.innerText.trim());
+    const lines = [];
+    lines.push(head.map(csvEscape).join(','));
+    [...table.tBodies[0].rows].forEach(tr => {
+      if(tr.style.display==='none') return;
+      const row = [...tr.cells].map(td => csvEscape(td.innerText.trim()));
+      lines.push(row.join(','));
+    });
+    const blob = new Blob([lines.join('\n')], {type: 'text/csv;charset=utf-8;'});
+    const a = document.createElement('a');
+    a.href = URL.createObjectURL(blob);
+    a.download = (('{{ title|replace(" ", "_") }}' || 'report') + '.csv').toLowerCase();
+    a.click();
+  });
+
+  function csvEscape(s){
+    s = (s||'').replace(/\r?\n|\r/g,' ');
+    if (s.includes(',') || s.includes('"')) s = '"' + s.replace(/"/g,'""') + '"';
+    return s;
+  }
+})();
+</script>
 {% endblock %}
Index: templates/reports/menu.html
===================================================================
--- templates/reports/menu.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/reports/menu.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,126 +3,217 @@
 
 {% block content %}
-<div class="row">
-  <div class="col-12">
-    <h2>Извештаи и статистики</h2>
-    <p class="text-muted">Изберете извештај за преглед</p>
-  </div>
-</div>
-
-<div class="row mt-4">
-  <!-- Активност на студенти -->
-  <div class="col-md-6 mb-4">
-    <div class="list-group">
-      <h5 class="mb-2"><i class="bi bi-people"></i> Активност на студенти</h5>
-
-      <a href="/my_students" class="list-group-item list-group-item-action">
-        <strong>Мои студенти</strong><br>
-        <small>Преглед на активностите на вашите студенти</small>
-      </a>
-
-      <a href="/reports/inactive_students" class="list-group-item list-group-item-action">
-        <strong>Неактивни студенти</strong><br>
-        <small>Студенти кои не учествувале во експерименти</small>
-      </a>
-
-      <a href="/reports/low_activity_students" class="list-group-item list-group-item-action">
-        <strong>Слабо активни студенти</strong><br>
-        <small>Студенти со помалку од 3 експерименти</small>
-      </a>
+<style>
+  .page-hero{
+    background: linear-gradient(135deg,#232526,#414345);
+    color:#fff;border-radius:18px;padding:18px 22px;
+    display:flex;align-items:center;justify-content:space-between;gap:12px
+  }
+  .page-hero .sub{opacity:.85}
+  .hero-actions .btn-ghost{
+    background:#00000010;border:1px solid #ffffff55;color:#fff
+  }
+
+  .toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:14px 0}
+  .search-input{min-width:300px}
+
+  .panel{border:0;border-radius:16px;box-shadow:0 12px 28px rgba(0,0,0,.08)}
+  .panel h6{font-weight:800;letter-spacing:.2px}
+
+  .tile{
+    display:flex;gap:12px;align-items:flex-start;
+    padding:12px 14px;margin-bottom:10px;border-radius:12px;
+    background:#fff;border:0;text-decoration:none;color:inherit;
+    box-shadow:0 6px 16px rgba(0,0,0,.06); transition:transform .12s ease, box-shadow .12s ease
+  }
+  .tile:hover{transform:translateY(-2px);box-shadow:0 10px 22px rgba(0,0,0,.10)}
+  .tile i{font-size:1.2rem;opacity:.9;margin-top:.2rem}
+  .tile strong{display:block}
+  .tile small{color:#6c757d}
+  .pill{
+    background:#eef2ff;color:#3f51b5;border:1px solid rgba(63,81,181,.25);
+    border-radius:999px;padding:6px 10px;font-weight:600
+  }
+
+  .grp-title{display:flex;align-items:center;gap:8px;margin-bottom:.5rem}
+  .grp-title i{opacity:.85}
+</style>
+
+<!-- HERO -->
+<div class="page-hero">
+  <div>
+    <h2 class="mb-0">Извештаи и статистики</h2>
+    <div class="sub">Изберете извештај за преглед или пребарајте по наслов/опис</div>
+  </div>
+  <div class="hero-actions d-flex align-items-center gap-2">
+    <span class="pill d-none d-md-inline"><i class="bi bi-graph-up-arrow"></i> аналитика</span>
+    <a href="/dashboard" class="btn btn-light btn-sm fw-semibold"><i class="bi bi-speedometer2"></i> Dashboard</a>
+  </div>
+</div>
+
+<!-- TOOLBAR -->
+<div class="toolbar">
+  <div class="input-group search-input">
+    <span class="input-group-text"><i class="bi bi-search"></i></span>
+    <input id="rep-search" class="form-control" placeholder="Пребарај: студент, опрема, најчесто, учество...">
+  </div>
+  <div class="ms-auto d-flex align-items-center gap-2">
+    <span class="pill"><i class="bi bi-funnel"></i> групирано по тема</span>
+  </div>
+</div>
+
+<!-- GRID -->
+<div id="reports-grid" class="row">
+  <!-- ГРУПА: Активност на студенти -->
+  <div class="col-lg-4 mb-4">
+    <div class="panel card h-100">
+      <div class="card-body">
+        <div class="grp-title"><i class="bi bi-people"></i><h6 class="mb-0">Активност на студенти</h6></div>
+
+        <a href="/my_students" class="tile" data-text="мои студенти активност учество напредок">
+          <i class="bi bi-person-check text-primary"></i>
+          <div>
+            <strong>Мои студенти</strong>
+            <small>Преглед на активностите на вашите студенти</small>
+          </div>
+        </a>
+
+        <a href="/reports/inactive_students" class="tile" data-text="неактивни без учество студенти">
+          <i class="bi bi-emoji-frown text-primary"></i>
+          <div>
+            <strong>Неактивни студенти</strong>
+            <small>Студенти кои не учествувале во експерименти</small>
+          </div>
+        </a>
+
+        <a href="/reports/low_activity_students" class="tile" data-text="слабо активни малку експерименти под 3">
+          <i class="bi bi-thermometer-low text-primary"></i>
+          <div>
+            <strong>Слабо активни студенти</strong>
+            <small>Студенти со помалку од 3 експерименти</small>
+          </div>
+        </a>
+
+        <a href="/reports/adv/students_below_threshold?max=3" class="tile" data-text="под праг threshold параметар max">
+          <i class="bi bi-arrow-bar-down text-primary"></i>
+          <div>
+            <strong>Под праг на учество</strong>
+            <small>Флексибилно: под дефиниран праг на учества (параметар <code>max</code>)</small>
+          </div>
+        </a>
+
+      </div>
     </div>
   </div>
 
-  <!-- Детални извештаи -->
-  <div class="col-md-6 mb-4">
-    <div class="list-group">
-      <h5 class="mb-2"><i class="bi bi-journal-text"></i> Детални извештаи</h5>
-
-      <a href="/reports/detailed_experiments" class="list-group-item list-group-item-action">
-        <strong>Детални експерименти</strong><br>
-        <small>Сите експерименти по студент</small>
-      </a>
-
-      <a href="/reports/element_views" class="list-group-item list-group-item-action">
-        <strong>Прегледи на елементи</strong><br>
-        <small>Кој корисник кои елементи ги прегледал</small>
-      </a>
-
-      <a href="/reports/teacher_statistics" class="list-group-item list-group-item-action">
-        <strong>Статистики по професор</strong><br>
-        <small>Споредба помеѓу професори</small>
-      </a>
+  <!-- ГРУПА: Детални извештаи -->
+  <div class="col-lg-4 mb-4">
+    <div class="panel card h-100">
+      <div class="card-body">
+        <div class="grp-title"><i class="bi bi-journal-text"></i><h6 class="mb-0">Детални извештаи</h6></div>
+
+        <a href="/reports/detailed_experiments" class="tile" data-text="детални експерименти студенти временска линија">
+          <i class="bi bi-journal-richtext text-success"></i>
+          <div>
+            <strong>Детални експерименти</strong>
+            <small>Сите експерименти по студент, со временска линија</small>
+          </div>
+        </a>
+
+        <a href="/reports/element_views" class="tile" data-text="прегледи елементи кој ги гледал popularnost">
+          <i class="bi bi-eye text-success"></i>
+          <div>
+            <strong>Прегледи на елементи</strong>
+            <small>Кој корисник кои елементи ги прегледал</small>
+          </div>
+        </a>
+
+        <a href="/reports/teacher_statistics" class="tile" data-text="статистики професор споредба наставници">
+          <i class="bi bi-bar-chart text-success"></i>
+          <div>
+            <strong>Статистики по професор</strong>
+            <small>Агрегати и споредба по професор</small>
+          </div>
+        </a>
+
+        <a href="/reports/adv/experiment_participants" class="tile" data-text="учесници по експеримент листа селекција">
+          <i class="bi bi-people-fill text-success"></i>
+          <div>
+            <strong>Учесници по експеримент</strong>
+            <small>Изберете експеримент и видете ги учесниците</small>
+          </div>
+        </a>
+      </div>
     </div>
   </div>
-</div>
-
-<hr class="my-4">
-
-<!-- Напредни извештаи (SQL) -->
-<div class="row">
-  <div class="col-12">
-    <h4><i class="bi bi-bar-chart-steps"></i> Напредни извештаи (SQL)</h4>
-    <p class="text-muted">Извештаи базирани на директни SQL-записи</p>
-  </div>
-
-  <div class="col-md-6 mb-4">
-    <div class="list-group">
-      <h6 class="mb-2">Студенти & учество</h6>
-
-      <a href="/reports/adv/student_experiment_counts" class="list-group-item list-group-item-action">
-        <strong>Студенти и број на експерименти</strong><br>
-        <small>Колку експерименти има извршено секој студент</small>
-      </a>
-
-      <a href="/reports/adv/experiment_participants" class="list-group-item list-group-item-action">
-        <strong>Учесници по експеримент</strong><br>
-        <small>Изберете експеримент и видете кои студенти учествувале</small>
-      </a>
-
-      <a href="/reports/adv/never_participated_students" class="list-group-item list-group-item-action">
-        <strong>Никогаш не учествувале</strong><br>
-        <small>Студенти без ниту едно учество во експерименти</small>
-      </a>
-
-      <a href="/reports/adv/students_below_threshold?max=3" class="list-group-item list-group-item-action">
-        <strong>Под праг на учество</strong><br>
-        <small>Студенти со помалку од 3 експерименти (параметар: <code>max</code>)</small>
-      </a>
+
+  <!-- ГРУПА: Напредни (SQL) -->
+  <div class="col-lg-4 mb-4">
+    <div class="panel card h-100">
+      <div class="card-body">
+        <div class="grp-title"><i class="bi bi-bar-chart-steps"></i><h6 class="mb-0">Напредни извештаи (SQL)</h6></div>
+
+        <a href="/reports/adv/student_experiment_counts" class="tile" data-text="студенти број експерименти count">
+          <i class="bi bi-list-ol text-warning"></i>
+          <div>
+            <strong>Студенти и број на експерименти</strong>
+            <small>Колку експерименти има извршено секој студент</small>
+          </div>
+        </a>
+
+        <a href="/reports/adv/equipment_usage" class="tile" data-text="користеност опрема инструмент колку пати">
+          <i class="bi bi-hammer text-warning"></i>
+          <div>
+            <strong>Користеност на опрема</strong>
+            <small>Број на употреби по инструмент</small>
+          </div>
+        </a>
+
+        <a href="/reports/adv/avg_equipment_per_experiment" class="tile" data-text="просек опрема по експеримент average">
+          <i class="bi bi-diagram-3 text-warning"></i>
+          <div>
+            <strong>Просечен број инструменти</strong>
+            <small>Просек на опрема по експеримент</small>
+          </div>
+        </a>
+
+        <a href="/reports/adv/most_used_elements" class="tile" data-text="најчесто користени елементи реакции">
+          <i class="bi bi-stars text-warning"></i>
+          <div>
+            <strong>Најчесто користени елементи</strong>
+            <small>Елементи кои најмногу се појавуваат во реакции</small>
+          </div>
+        </a>
+
+        <a href="/reports/adv/most_performed_experiments" class="tile" data-text="најреализирани експерименти најмногу учесници">
+          <i class="bi bi-trophy text-warning"></i>
+          <div>
+            <strong>Најреализирани експерименти</strong>
+            <small>Експерименти со најмногу учесници</small>
+          </div>
+        </a>
+
+      </div>
     </div>
   </div>
-
-  <div class="col-md-6 mb-4">
-    <div class="list-group">
-      <h6 class="mb-2">Опрема, елементи & популарност</h6>
-
-      <a href="/reports/adv/equipment_usage" class="list-group-item list-group-item-action">
-        <strong>Користеност на опрема</strong><br>
-        <small>Колку пати е користен секој инструмент</small>
-      </a>
-
-      <a href="/reports/adv/avg_equipment_per_experiment" class="list-group-item list-group-item-action">
-        <strong>Просечен број инструменти</strong><br>
-        <small>Просек на опрема по експеримент</small>
-      </a>
-
-      <a href="/reports/adv/most_used_elements" class="list-group-item list-group-item-action">
-        <strong>Најчесто користени елементи</strong><br>
-        <small>Елементи кои најмногу се појавуваат во реакции</small>
-      </a>
-
-      <a href="/reports/adv/most_performed_experiments" class="list-group-item list-group-item-action">
-        <strong>Најреализирани експерименти</strong><br>
-        <small>Експерименти со најмногу учесници</small>
-      </a>
-
-      <a href="/reports/adv/student_views" class="list-group-item list-group-item-action">
-        <strong>Прегледи: елементи & опрема</strong><br>
-        <small>Број на прегледани елементи/опрема по студент</small>
-      </a>
-    </div>
-  </div>
-</div>
-
-<div class="mt-4">
-  <a href="/dashboard" class="btn btn-primary">Назад до Dashboard</a>
-</div>
+</div>
+
+<div class="mt-2 text-center">
+  <a href="/dashboard" class="btn btn-secondary"><i class="bi bi-arrow-left"></i> Назад до Dashboard</a>
+</div>
+
+<script>
+  // Едноставно пребарување низ сите плочки (tile)
+  (function(){
+    const q = document.getElementById('rep-search');
+    if(!q) return;
+    const tiles = [...document.querySelectorAll('#reports-grid a.tile')];
+    q.addEventListener('input', ()=>{
+      const s = (q.value||'').toLowerCase().trim();
+      tiles.forEach(a=>{
+        const hay = (a.textContent + ' ' + (a.dataset.text||'')).toLowerCase();
+        a.style.display = hay.includes(s) ? '' : 'none';
+      });
+    });
+  })();
+</script>
 {% endblock %}
Index: templates/virtual_laboratory.html
===================================================================
--- templates/virtual_laboratory.html	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ templates/virtual_laboratory.html	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -3,302 +3,408 @@
 
 {% block content %}
+<style>
+  :root{
+    --bg:#f7f9fc; --card:#ffffff;
+    --border:#e6ebf2; --muted:#6c7a8a;
+    --primary:#2c7be5; --success:#2bb673; --warning:#f59f00; --danger:#e03131;
+  }
+  body{background:var(--bg)}
+  .lab-grid{display:grid;grid-template-columns:1fr 520px 1fr;gap:28px;align-items:start}
+  @media (max-width: 1200px){.lab-grid{grid-template-columns:1fr}}
+  .panel{background:var(--card);border:1px solid var(--border);border-radius:16px;box-shadow:0 10px 25px rgba(0,0,0,.05)}
+  .panel-head{padding:14px 16px;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center}
+  .panel-title{margin:0;font-weight:700}
+  .panel-body{padding:12px 12px 6px}
+  .filter-input{width:100%;border-radius:12px;border:1px solid var(--border);padding:10px 12px;margin-bottom:10px}
+  .chips{min-height:46px}
+  .chip{
+    display:inline-flex;align-items:center;gap:8px;padding:8px 12px;margin:6px;border-radius:999px;color:#fff;
+    font-weight:700;cursor:grab;user-select:none;border:1px solid rgba(255,255,255,.25);
+    box-shadow:0 6px 14px rgba(0,0,0,.12);transition:transform .15s ease, box-shadow .15s ease, opacity .15s ease
+  }
+  .chip small{opacity:.95;font-weight:600}
+  .chip:active{transform:scale(.97)}
+  .chip[data-disabled="1"]{opacity:.35;cursor:not-allowed;box-shadow:none}
+
+  .bench.panel-body{padding:18px}
+  .drop-wrap{display:grid;grid-template-columns:1fr 100px 1fr;gap:16px;align-items:center}
+  .drop-zone{
+    height:160px;border:2px dashed var(--primary);border-radius:18px;background:#f3f7ff;
+    display:flex;align-items:center;justify-content:center;flex-direction:column;transition:all .2s ease
+  }
+  .drop-zone.hover{background:#eaf2ff;border-color:#4c9dff;box-shadow:0 10px 20px rgba(76,157,255,.2)}
+  .placeholder{color:var(--muted);font-weight:700;text-align:center;line-height:1.25}
+  .pill{
+    display:flex;flex-direction:column;align-items:center;justify-content:center;
+    width:126px;height:126px;border-radius:999px;color:#fff;font-weight:900;font-size:34px;
+    letter-spacing:.3px;box-shadow:0 16px 30px rgba(0,0,0,.18);border:1px solid rgba(255,255,255,.25)
+  }
+  .pill span{font-size:12px;font-weight:700;opacity:.95;margin-top:3px}
+
+  .center-controls{display:flex;flex-direction:column;align-items:center;gap:8px}
+  .btn-round{border-radius:999px;padding:10px 16px}
+
+  #result-card{border-radius:14px}
+  .result-eq{font-size:24px;font-weight:800;margin:10px 0}
+  .pop{animation:pop .28s ease}
+  @keyframes pop{0%{transform:scale(.94);opacity:0}100%{transform:scale(1);opacity:1}}
+
+  .info-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px}
+  .badge-soft{border:1px solid var(--border);background:#f7fbff;color:#264b7f;border-radius:10px;padding:8px 10px}
+</style>
+
 <div class="container-fluid">
-    <div class="row">
-        <div class="col-12 text-center mb-4">
-            <h2>🧪 Виртуелна хемиска лабораторија</h2>
-            <p class="lead">Изберете два елементи за да симулирате реакција</p>
+  <div class="row mb-3">
+    <div class="col-12 text-center">
+      <h2 class="mb-1">🧪 Виртуелна хемиска лабораторија</h2>
+      <p class="lead mb-1">Влечи-и-пушти два елементи на „работната маса“, па кликни <b>Реагирај</b>.</p>
+      <small class="text-muted">* Боја по hazard (или атомски број) — можеш да смениш подолу.</small>
+    </div>
+  </div>
+
+  <div class="lab-grid">
+    <!-- ЛЕВО -->
+    <div class="panel">
+      <div class="panel-head">
+        <h6 class="panel-title">Елементи (лево)</h6>
+        <div class="btn-group btn-group-sm" role="group" aria-label="color-mode">
+          <input type="radio" class="btn-check" name="colorMode" id="cm-hazard" checked>
+          <label class="btn btn-outline-secondary" for="cm-hazard">Hazard</label>
+          <input type="radio" class="btn-check" name="colorMode" id="cm-atomic">
+          <label class="btn btn-outline-secondary" for="cm-atomic">Atomic</label>
         </div>
+      </div>
+      <div class="panel-body">
+        <input class="filter-input" id="filter-left" placeholder="🔎 филтрирај по симбол/име..."/>
+        <div id="list-left" class="chips"></div>
+      </div>
     </div>
 
-    <div class="row justify-content-center">
-        <div class="col-md-10">
-            <div class="card shadow-lg">
-                <div class="card-body p-4">
-                    <!-- Симулациска област -->
-                    <div style="display: grid; grid-template-columns: 1fr 150px 1fr; gap: 40px; align-items: center; margin-bottom: 40px;">
-                        
-                        <!-- Прв елемент -->
-                        <div class="text-center">
-                            <div id="element1-display" style="width: 130px; height: 130px; border: 3px dashed #007bff; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; margin: 0 auto; background: #f8f9fa; transition: all 0.3s ease;">
-                                <span style="color: #666;">Избери<br>Елемент 1</span>
-                            </div>
-                            <select class="form-select mt-3" id="element1-select" style="max-width: 200px; margin: 15px auto;">
-                                <option value="">-- Избери прв елемент --</option>
-                                {% for element in elements %}
-                                <option value="{{ element.symbol }}" data-name="{{ element.element_name }}">
-                                    {{ element.symbol }} - {{ element.element_name }}
-                                </option>
-                                {% endfor %}
-                            </select>
-                        </div>
-                        
-                        <!-- Центар со копче -->
-                        <div class="text-center">
-                            <div style="font-size: 24px; color: #28a745; font-weight: bold; margin-bottom: 15px;">+</div>
-                            <button class="btn btn-success btn-lg" id="react-btn" disabled onclick="simulateReaction()" style="border-radius: 20px; padding: 12px 25px;">
-                                ⚗️ Реагирај
-                            </button>
-                            <div style="font-size: 24px; color: #007bff; font-weight: bold; margin-top: 15px;">→</div>
-                        </div>
-                        
-                        <!-- Втор елемент -->
-                        <div class="text-center">
-                            <div id="element2-display" style="width: 130px; height: 130px; border: 3px dashed #007bff; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; margin: 0 auto; background: #f8f9fa; transition: all 0.3s ease;">
-                                <span style="color: #666;">Избери<br>Елемент 2</span>
-                            </div>
-                            <select class="form-select mt-3" id="element2-select" style="max-width: 200px; margin: 15px auto;">
-                                <option value="">-- Избери втор елемент --</option>
-                                {% for element in elements %}
-                                <option value="{{ element.symbol }}" data-name="{{ element.element_name }}">
-                                    {{ element.symbol }} - {{ element.element_name }}
-                                </option>
-                                {% endfor %}
-                            </select>
-                        </div>
-                    </div>
-                    
-                    <!-- Резултат област -->
-                    <div id="result-area" style="display: none; margin-top: 30px;">
-                        <div class="card" id="result-card">
-                            <div class="card-body text-center">
-                                <div id="result-content"></div>
-                                
-                                <!-- Копче за учество во експеримент - САМО ЗА СТУДЕНТИ -->
-                                <button class="btn btn-primary mt-3" id="participate-btn" onclick="participateInExperiment()" style="display: none;">
-                                    📝 Запиши учество во експеримент
-                                </button>
-                                
-                                <div id="experiment-details" style="display: none; margin-top: 20px;">
-                                    <!-- Тука ќе се прикажат деталите за експериментот -->
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
+    <!-- СРЕДИНА (работна маса) -->
+    <div class="panel">
+      <div class="panel-head">
+        <h6 class="panel-title mb-0">Работна маса</h6>
+        <div class="text-muted small" id="selection-hint">Нема избрани елементи</div>
+      </div>
+      <div class="panel-body bench">
+        <div class="drop-wrap mb-2">
+          <div id="drop1" class="drop-zone">
+            <div class="placeholder">Влечи тука<br><b>Елемент 1</b></div>
+          </div>
+
+          <div class="center-controls">
+            <button class="btn btn-outline-secondary btn-round" id="swap-btn" title="Замени" disabled>⇄</button>
+            <button class="btn btn-success btn-round" id="react-btn" disabled>⚗️ Реагирај</button>
+            <button class="btn btn-outline-danger btn-round" id="clear-btn" disabled>✖</button>
+          </div>
+
+          <div id="drop2" class="drop-zone">
+            <div class="placeholder">Влечи тука<br><b>Елемент 2</b></div>
+          </div>
+        </div>
+
+        <div class="info-grid" id="selected-info" style="display:none">
+          <div class="badge-soft" id="info-e1"></div>
+          <div class="badge-soft" id="info-e2"></div>
+        </div>
+
+        <div id="result-area" style="display:none">
+          <div class="card border-success mt-3" id="result-card">
+            <div class="card-body text-center">
+              <div id="result-content"></div>
+              <button class="btn btn-primary mt-3" id="participate-btn" style="display:none">
+                📝 Запиши учество во експеримент
+              </button>
+              <div id="experiment-details" style="display:none;margin-top:16px"></div>
             </div>
+          </div>
         </div>
+      </div>
     </div>
-</div>
-
-<div class="mt-4 text-center">
+
+    <!-- ДЕСНО -->
+    <div class="panel">
+      <div class="panel-head">
+        <h6 class="panel-title">Елементи (десно)</h6>
+        <span class="small text-muted" id="count-right"></span>
+      </div>
+      <div class="panel-body">
+        <input class="filter-input" id="filter-right" placeholder="🔎 филтрирај по симбол/име..."/>
+        <div id="list-right" class="chips"></div>
+      </div>
+    </div>
+  </div>
+
+  <div class="mt-4 text-center">
     <a href="/dashboard" class="btn btn-secondary">Назад до Dashboard</a>
     <a href="/my-experiments" class="btn btn-warning">📊 Мои Експерименти</a>
+  </div>
 </div>
 
 <script>
-let selectedElements = {};
+/* ---------- Податоци од сервер ---------- */
+const ELEMENTS = {{ elements|tojson|safe }};
+
+/* ---------- Состојба ---------- */
+let selected = { e1:null, e2:null };
 let currentReactionData = null;
-let currentExperimentId = null;
-
-document.addEventListener('DOMContentLoaded', function() {
-    document.getElementById('element1-select').addEventListener('change', function() {
-        updateElementDisplay(this, 'element1-display', 'element1');
-        checkReactionReady();
+let colorMode = 'hazard'; // 'hazard' | 'atomic'
+
+/* ---------- Палета по hazard (флексибилна и со македонски клучни зборови) ---------- */
+const HAZARD_PALETTE = [
+  {k:['flammable','запал'], base:'#e85d04'},
+  {k:['toxic','токс'],      base:'#6a040f'},
+  {k:['corros','короз'],    base:'#2a9d8f'},
+  {k:['radio','радио'],     base:'#ffd60a'},
+  {k:['inert','инерт','неутрал'], base:'#6c757d'},
+];
+function pickHazardBase(el){
+  const t = (el.hazard_type || '').toLowerCase();
+  for(const h of HAZARD_PALETTE){
+    if(h.k.some(x => t.includes(x))) return h.base;
+  }
+  return '#2c7be5'; // default
+}
+
+/* ---------- Бои ---------- */
+function shade(hex, pct){
+  // hex -> darker/lighter
+  let c = hex.replace('#','');
+  if(c.length===3){ c = c.split('').map(x=>x+x).join(''); }
+  const num = parseInt(c,16);
+  let r = (num>>16) + Math.round(255*pct);
+  let g = ((num>>8)&0x00FF) + Math.round(255*pct);
+  let b = (num&0x0000FF) + Math.round(255*pct);
+  r = Math.max(0,Math.min(255,r)); g = Math.max(0,Math.min(255,g)); b = Math.max(0,Math.min(255,b));
+  return '#' + (r<<16 | g<<8 | b).toString(16).padStart(6,'0');
+}
+function gradFromHex(hex){ return `linear-gradient(135deg, ${hex}, ${shade(hex,-0.18)})`; }
+function gradFromAtomic(n){
+  const h = (Number(n||0)*29)%360;
+  return `linear-gradient(135deg, hsl(${h} 80% 48%), hsl(${(h+28)%360} 82% 44%))`;
+}
+function chipBackground(el){
+  return colorMode==='hazard' ? gradFromHex(pickHazardBase(el)) : gradFromAtomic(el.atomic_number);
+}
+
+/* ---------- Chips / Pills / Info ---------- */
+function chipHTML(el){
+  const bg = chipBackground(el);
+  return `
+    <div class="chip" draggable="true"
+         data-symbol="${el.symbol}" data-name="${el.element_name}"
+         data-atomic="${el.atomic_number||0}" data-hazard="${el.hazard_type||''}"
+         style="background:${bg}">
+      <div style="display:flex;gap:8px;align-items:center">
+        <span style="font-size:16px;font-weight:900">${el.symbol}</span>
+        <small>${el.element_name}</small>
+      </div>
+    </div>`;
+}
+function pillHTML(el){
+  const bg = chipBackground(el);
+  return `<div class="pill pop" style="background:${bg}">${el.symbol}<span>${el.element_name}</span></div>`;
+}
+function infoHTML(el){
+  const mp = (el.melting_point ?? '') === '' ? '—' : el.melting_point;
+  const bp = (el.boiling_point ?? '') === '' ? '—' : el.boiling_point;
+  const hz = el.hazard_type || '—';
+  return `<b>${el.symbol}</b> · ${el.element_name}<br/>
+          <small>№ ${el.atomic_number} · MP: ${mp} · BP: ${bp} · Hazard: ${hz}</small>`;
+}
+
+/* ---------- Рендер листи + филтри ---------- */
+function renderLists(){
+  const html = ELEMENTS.map(chipHTML).join('');
+  const L = document.getElementById('list-left');
+  const R = document.getElementById('list-right');
+  L.innerHTML = html; R.innerHTML = html;
+  document.getElementById('count-right').innerText = `${ELEMENTS.length} елементи`;
+  bindChips(L); bindChips(R);
+  updateControls(); // за „disabled“ визуелно
+}
+function bindChips(container){
+  container.querySelectorAll('.chip').forEach(ch=>{
+    ch.addEventListener('dragstart', ev=>{
+      ev.dataTransfer.setData('text/plain', JSON.stringify({
+        symbol: ch.dataset.symbol, name: ch.dataset.name,
+        atomic: ch.dataset.atomic, hazard: ch.dataset.hazard
+      }));
     });
-    
-    document.getElementById('element2-select').addEventListener('change', function() {
-        updateElementDisplay(this, 'element2-display', 'element2');
-        checkReactionReady();
+    ch.addEventListener('click', ()=>{
+      const el = ELEMENTS.find(e=>e.symbol===ch.dataset.symbol) || {
+        symbol: ch.dataset.symbol, element_name: ch.dataset.name, atomic_number: ch.dataset.atomic, hazard_type: ch.dataset.hazard
+      };
+      const target = !selected.e1 ? 'e1' : (!selected.e2 ? 'e2' : 'e1');
+      setSelected(target, el);
     });
+  });
+}
+function applyFilter(inputId, listId){
+  const q = document.getElementById(inputId).value.trim().toLowerCase();
+  document.getElementById(listId).querySelectorAll('.chip').forEach(ch=>{
+    const hay = (ch.dataset.symbol+' '+ch.dataset.name).toLowerCase();
+    ch.style.display = hay.includes(q) ? 'inline-flex' : 'none';
+  });
+}
+
+/* ---------- Drop-зони ---------- */
+function bindDropZone(zoneId, key){
+  const dz = document.getElementById(zoneId);
+  dz.addEventListener('dragover', ev=>{ ev.preventDefault(); dz.classList.add('hover'); });
+  dz.addEventListener('dragleave', ()=> dz.classList.remove('hover'));
+  dz.addEventListener('drop', ev=>{
+    ev.preventDefault(); dz.classList.remove('hover');
+    try{
+      const d = JSON.parse(ev.dataTransfer.getData('text/plain'));
+      const el = ELEMENTS.find(e=>e.symbol===d.symbol) || {
+        symbol:d.symbol, element_name:d.name, atomic_number:d.atomic, hazard_type:d.hazard
+      };
+      setSelected(key, el);
+    }catch(_){}
+  });
+}
+function setSelected(key, el){
+  const other = key==='e1'?'e2':'e1';
+  if(selected[other] && selected[other].symbol===el.symbol){
+    alert('Не може ист елемент во двете полиња.'); return;
+  }
+  selected[key] = el;
+  document.getElementById(key==='e1'?'drop1':'drop2').innerHTML = pillHTML(el);
+  document.getElementById('selected-info').style.display = 'grid';
+  document.getElementById('info-e1').innerHTML = selected.e1 ? infoHTML(selected.e1) : '';
+  document.getElementById('info-e2').innerHTML = selected.e2 ? infoHTML(selected.e2) : '';
+  document.getElementById('selection-hint').innerText =
+    (selected.e1?selected.e1.symbol:'—') + ' + ' + (selected.e2?selected.e2.symbol:'—');
+  document.getElementById('result-area').style.display = 'none';
+  updateControls();
+}
+
+/* ---------- Контроли ---------- */
+function updateControls(){
+  const react = document.getElementById('react-btn');
+  const swap  = document.getElementById('swap-btn');
+  const clr   = document.getElementById('clear-btn');
+  const ready = !!(selected.e1 && selected.e2);
+  react.disabled = !ready; swap.disabled = !(selected.e1 || selected.e2); clr.disabled = !(selected.e1 || selected.e2);
+
+  document.querySelectorAll('.chip').forEach(ch=>{
+    const sym = ch.dataset.symbol;
+    const used = (selected.e1 && selected.e1.symbol===sym) || (selected.e2 && selected.e2.symbol===sym);
+    ch.dataset.disabled = used ? "1" : "0";
+  });
+}
+function swapSelected(){
+  const t = selected.e1; selected.e1 = selected.e2; selected.e2 = t;
+  document.getElementById('drop1').innerHTML = selected.e1 ? pillHTML(selected.e1) : `<div class="placeholder">Влечи тука<br><b>Елемент 1</b></div>`;
+  document.getElementById('drop2').innerHTML = selected.e2 ? pillHTML(selected.e2) : `<div class="placeholder">Влечи тука<br><b>Елемент 2</b></div>`;
+  document.getElementById('info-e1').innerHTML = selected.e1 ? infoHTML(selected.e1) : '';
+  document.getElementById('info-e2').innerHTML = selected.e2 ? infoHTML(selected.e2) : '';
+  document.getElementById('selection-hint').innerText =
+    (selected.e1?selected.e1.symbol:'—') + ' + ' + (selected.e2?selected.e2.symbol:'—');
+  document.getElementById('result-area').style.display = 'none';
+  updateControls();
+}
+function clearSelected(){
+  selected = {e1:null,e2:null};
+  document.getElementById('drop1').innerHTML = `<div class="placeholder">Влечи тука<br><b>Елемент 1</b></div>`;
+  document.getElementById('drop2').innerHTML = `<div class="placeholder">Влечи тука<br><b>Елемент 2</b></div>`;
+  document.getElementById('selected-info').style.display='none';
+  document.getElementById('selection-hint').innerText = 'Нема избрани елементи';
+  document.getElementById('result-area').style.display = 'none';
+  updateControls();
+}
+
+/* ---------- API ---------- */
+async function simulateReaction(){
+  if(!(selected.e1 && selected.e2)) return;
+  const btn = document.getElementById('react-btn');
+  btn.disabled = true; btn.innerText = '⏳ Проверувам...';
+  try{
+    const res = await fetch('/api/simulate-reaction',{
+      method:'POST', headers:{'Content-Type':'application/json'},
+      body: JSON.stringify({ element1:selected.e1.symbol, element2:selected.e2.symbol })
+    });
+    const data = await res.json();
+    showResult(data);
+  }catch(e){ console.error(e); alert('Грешка при симулација.'); }
+  finally{ btn.disabled=false; btn.innerText='⚗️ Реагирај'; }
+}
+function showResult(data){
+  const area = document.getElementById('result-area');
+  const content = document.getElementById('result-content');
+  const participateBtn = document.getElementById('participate-btn');
+  area.style.display='block';
+  if(data.success){
+    currentReactionData = data;
+    content.innerHTML = `
+      <h4 class="text-success">✅ Успешна реакција!</h4>
+      <div class="result-eq pop">${selected.e1.symbol} + ${selected.e2.symbol} → <span>${data.product}</span></div>
+      <div class="row g-2 justify-content-center">
+        <div class="col-md-5"><div class="alert alert-success py-2 mb-2"><b>Продукт:</b> ${data.product}</div></div>
+        <div class="col-md-5"><div class="alert alert-info py-2 mb-2"><b>Услови:</b> ${data.conditions || 'Стандардни'}</div></div>
+      </div>
+      <small class="text-muted">ℹ️ За да се евидентира како активност, кликни „Запиши учество“.</small>`;
+    participateBtn.style.display='inline-block';
+  }else{
+    currentReactionData = null;
+    content.innerHTML = `
+      <h4 class="text-warning">⚠️ Реакцијата не е дефинирана</h4>
+      <div class="result-eq pop">${selected.e1.symbol} + ${selected.e2.symbol} → ?</div>
+      <div class="alert alert-warning">Оваа комбинација не е додадена. Контактирај професор.</div>`;
+    participateBtn.style.display='none';
+  }
+  document.getElementById('experiment-details').style.display='none';
+  document.getElementById('experiment-details').innerHTML='';
+}
+async function participate(){
+  if(!currentReactionData) return;
+  const btn = document.getElementById('participate-btn');
+  btn.disabled=true; btn.innerText='⏳ Запишувам...';
+  try{
+    const res = await fetch('/save-experiment',{
+      method:'POST', headers:{'Content-Type':'application/json'},
+      body: JSON.stringify({
+        reaction_id: currentReactionData.reaction_id,
+        result:`Симулирана реакција: ${selected.e1.symbol}+${selected.e2.symbol} → ${currentReactionData.product}`,
+        safety_warning:'Виртуелна симулација - безбедно извршено'
+      })
+    });
+    const data = await res.json();
+    if(data.success){
+      btn.classList.replace('btn-primary','btn-success');
+      btn.innerText='✅ Запишано!';
+      const det = document.getElementById('experiment-details');
+      det.style.display='block';
+      det.innerHTML = `<div class="alert alert-success">
+        <b>Експеримент ID:</b> #${data.experiment_id}<br/>
+        Гледај во <a href="/my-experiments">Мои Експерименти</a>.
+      </div>`;
+    }else{
+      alert('Грешка при запишување: '+(data.message||'Непозната грешка'));
+      btn.disabled=false; btn.innerText='📝 Запиши учество во експеримент';
+    }
+  }catch(e){
+    console.error(e); alert('Грешка при запишување.');
+    btn.disabled=false; btn.innerText='📝 Запиши учество во експеримент';
+  }
+}
+
+/* ---------- Init ---------- */
+document.addEventListener('DOMContentLoaded', ()=>{
+  renderLists();
+  bindDropZone('drop1','e1'); bindDropZone('drop2','e2');
+
+  document.getElementById('filter-left').addEventListener('input', ()=>applyFilter('filter-left','list-left'));
+  document.getElementById('filter-right').addEventListener('input',()=>applyFilter('filter-right','list-right'));
+
+  document.getElementById('swap-btn').addEventListener('click', swapSelected);
+  document.getElementById('clear-btn').addEventListener('click', clearSelected);
+  document.getElementById('react-btn').addEventListener('click', simulateReaction);
+  document.getElementById('participate-btn').addEventListener('click', participate);
+
+  document.getElementById('cm-hazard').addEventListener('change', e=>{ if(e.target.checked){ colorMode='hazard'; renderLists(); }});
+  document.getElementById('cm-atomic').addEventListener('change', e=>{ if(e.target.checked){ colorMode='atomic'; renderLists(); }});
 });
-
-function updateElementDisplay(select, displayId, elementKey) {
-    const display = document.getElementById(displayId);
-    const value = select.value;
-    const name = select.options[select.selectedIndex]?.dataset?.name || '';
-    
-    if (value) {
-        display.innerHTML = `
-            <div style="font-size: 36px; font-weight: bold; color: white;">${value}</div>
-            <div style="font-size: 12px; margin-top: 5px; color: white;">${name}</div>
-        `;
-        display.style.borderColor = '#28a745';
-        display.style.background = 'linear-gradient(45deg, #28a745, #20c997)';
-        
-        selectedElements[elementKey] = { symbol: value, name: name };
-    } else {
-        display.innerHTML = displayId === 'element1-display' ? 
-            '<span style="color: #666;">Избери<br>Елемент 1</span>' : 
-            '<span style="color: #666;">Избери<br>Елемент 2</span>';
-        display.style.borderColor = '#007bff';
-        display.style.background = '#f8f9fa';
-        
-        delete selectedElements[elementKey];
-    }
-    
-    // Ресетирај резултат кога се менуваат елементите
-    document.getElementById('result-area').style.display = 'none';
-    document.getElementById('participate-btn').style.display = 'none';
-}
-
-function checkReactionReady() {
-    const reactBtn = document.getElementById('react-btn');
-    reactBtn.disabled = !(selectedElements.element1 && selectedElements.element2);
-}
-
-function simulateReaction() {
-    if (!selectedElements.element1 || !selectedElements.element2) return;
-    
-    const btn = document.getElementById('react-btn');
-    btn.innerHTML = '⏳ Проверувам...';
-    btn.disabled = true;
-    
-    // Повикај API за симулација на реакција
-    fetch('/api/simulate-reaction', {
-        method: 'POST',
-        headers: {
-            'Content-Type': 'application/json',
-        },
-        body: JSON.stringify({
-            element1: selectedElements.element1.symbol,
-            element2: selectedElements.element2.symbol
-        })
-    })
-    .then(response => response.json())
-    .then(data => {
-        showResult(data);
-        btn.innerHTML = '⚗️ Реагирај';
-        btn.disabled = false;
-    })
-    .catch(error => {
-        console.error('Грешка:', error);
-        btn.innerHTML = '⚗️ Реагирај';
-        btn.disabled = false;
-        alert('Грешка при симулација на реакцијата');
-    });
-}
-
-function showResult(data) {
-    const resultArea = document.getElementById('result-area');
-    const resultCard = document.getElementById('result-card');
-    const resultContent = document.getElementById('result-content');
-    const participateBtn = document.getElementById('participate-btn');
-    
-    resultArea.style.display = 'block';
-    
-    if (data.success) {
-        currentReactionData = data;
-        
-        // За студенти - прикажи резултат и можност за учество во експеримент
-        resultCard.className = 'card border-success';
-        resultContent.innerHTML = `
-            <h4 class="text-success">✅ Успешна реакција!</h4>
-            <div style="font-size: 24px; font-weight: bold; margin: 20px 0; color: #28a745;">
-                ${selectedElements.element1.symbol} + ${selectedElements.element2.symbol} → ${data.product}
-            </div>
-            <div class="row">
-                <div class="col-md-6">
-                    <strong>Продукт:</strong> ${data.product}
-                </div>
-                <div class="col-md-6">
-                    <strong>Услови:</strong> ${data.conditions || 'Стандардни услови'}
-                </div>
-            </div>
-            <div class="alert alert-info mt-3">
-                <small>ℹ️ За да го зачувате овој резултат, запишете учество во експеримент</small>
-            </div>
-        `;
-        
-        // Прикажи копче за учество во експеримент
-        participateBtn.style.display = 'inline-block';
-        
-    } else {
-        currentReactionData = null;
-        resultCard.className = 'card border-warning';
-        resultContent.innerHTML = `
-            <h4 class="text-warning">⚠️ Реакцијата не е дефинирана</h4>
-            <p class="mb-3">${data.message}</p>
-            <div style="font-size: 18px; color: #856404; margin: 15px 0;">
-                ${selectedElements.element1.symbol} + ${selectedElements.element2.symbol} → ?
-            </div>
-            <div class="alert alert-warning">
-                <small>Оваа реакција сè уште не е додадена во системот. Контактирајте го вашиот професор.</small>
-            </div>
-        `;
-        participateBtn.style.display = 'none';
-    }
-}
-
-function participateInExperiment() {
-    if (!currentReactionData) return;
-    
-    const participateBtn = document.getElementById('participate-btn');
-    participateBtn.innerHTML = '⏳ Запишувам...';
-    participateBtn.disabled = true;
-    
-    // Зачувај учество во експеримент
-    fetch('/save-experiment', {
-        method: 'POST',
-        headers: {
-            'Content-Type': 'application/json',
-        },
-        body: JSON.stringify({
-            reaction_id: currentReactionData.reaction_id,
-            result: `Симулирана реакција: ${currentReactionData.elements} → ${currentReactionData.product}`,
-            safety_warning: 'Виртуелна симулација - безбедно извршено'
-        })
-    })
-    .then(response => response.json())
-    .then(data => {
-        if (data.success) {
-            participateBtn.innerHTML = '✅ Успешно запишано!';
-            participateBtn.className = 'btn btn-success mt-3';
-            participateBtn.disabled = true;
-            
-            // Прикажи детали за експериментот
-            document.getElementById('experiment-details').style.display = 'block';
-            document.getElementById('experiment-details').innerHTML = `
-                <div class="alert alert-success">
-                    <h5>🎉 Успешно учество во експеримент!</h5>
-                    <p>Експеримент ID: #${data.experiment_id}</p>
-                    <p>Вашето учество е запишано. Можете да го видите во <a href="/my-experiments">Мои Експерименти</a></p>
-                </div>
-            `;
-            
-            // По 3 секунди ресетирај за нов експеримент
-            setTimeout(() => {
-                resetExperiment();
-            }, 5000);
-            
-        } else {
-            alert('Грешка при запишување: ' + (data.message || 'Непозната грешка'));
-            participateBtn.innerHTML = '📝 Запиши учество во експеримент';
-            participateBtn.disabled = false;
-        }
-    })
-    .catch(error => {
-        console.error('Грешка:', error);
-        alert('Грешка при запишување на учеството');
-        participateBtn.innerHTML = '📝 Запиши учество во експеримент';
-        participateBtn.disabled = false;
-    });
-}
-
-function resetExperiment() {
-    // Ресетирај селекција
-    document.getElementById('element1-select').value = '';
-    document.getElementById('element2-select').value = '';
-    
-    // Ресетирај приказ
-    document.getElementById('element1-display').innerHTML = '<span style="color: #666;">Избери<br>Елемент 1</span>';
-    document.getElementById('element1-display').style.borderColor = '#007bff';
-    document.getElementById('element1-display').style.background = '#f8f9fa';
-    
-    document.getElementById('element2-display').innerHTML = '<span style="color: #666;">Избери<br>Елемент 2</span>';
-    document.getElementById('element2-display').style.borderColor = '#007bff';
-    document.getElementById('element2-display').style.background = '#f8f9fa';
-    
-    // Скриј резултати
-    document.getElementById('result-area').style.display = 'none';
-    document.getElementById('participate-btn').style.display = 'none';
-    document.getElementById('experiment-details').style.display = 'none';
-    
-    // Ресетирај податоци
-    selectedElements = {};
-    currentReactionData = null;
-    
-    // Оневозможи копче за реакција
-    document.getElementById('react-btn').disabled = true;
-}
 </script>
 {% endblock %}
Index: utils/database_manager.py
===================================================================
--- utils/database_manager.py	(revision 988d42fb535fb8a7fce8ba843be908cd9a221d50)
+++ utils/database_manager.py	(revision d9deb6686c5d9c4a8445309fa4e45bf74b861d47)
@@ -1,6 +1,9 @@
 # database_manager.py
+import os, logging
+from contextlib import contextmanager
 import psycopg2
-from psycopg2.extras import RealDictCursor
-
+from psycopg2.extras import RealDictCursor, execute_values
+
+log = logging.getLogger("simlab.db")
 class DatabaseManager:
     # ---------- CONNECTION ----------
@@ -8,37 +11,44 @@
     def get_connection():
         return psycopg2.connect(
-            host='localhost',
-            port=9999,
-            database='db_202425z_va_prj_simlab25',
-            user='db_202425z_va_prj_simlab25_owner',
-            password='c9e5ebb7d332',
+            host=os.getenv('DB_HOST', 'localhost'),
+            port=int(os.getenv('DB_PORT', '9999')),
+            database=os.getenv('DB_NAME', 'db_202425z_va_prj_simlab25'),
+            user=os.getenv('DB_USER', 'db_202425z_va_prj_simlab25_owner'),
+            password=os.getenv('DB_PASS', 'c9e5ebb7d332'),
             cursor_factory=RealDictCursor
         )
-
-    # ЕДИНСТВЕНА execute_query (го избришавме дупликатот)
+    
+@contextmanager
+def _conn_cur():
+    conn = DatabaseManager.get_connection()
+    try:
+        with conn:
+            with conn.cursor() as cur:
+                yield cur
+    finally:
+        conn.close()
+
+class DatabaseManager(DatabaseManager):  # extend class with methods
+    # ---------- GENERIC EXEC ----------
     @staticmethod
     def execute_query(query, params=None):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute(query, params or ())
-            result = cur.fetchall()
-            cur.close()
-            conn.close()
-            return result
-        except Exception as e:
-            print(f"Грешка во execute_query: {e}")
-            return None
+            with _conn_cur() as cur:
+                cur.execute(query, params or ())
+                return cur.fetchall()
+        except Exception:
+            log.exception("execute_query failed: %s | params=%s", query, params)
+            return None
+
+
 
     @staticmethod
     def test_connection():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("SELECT 1")
-            cur.close()
-            conn.close()
+            with _conn_cur() as cur:
+                cur.execute("SELECT 1")
             return True
         except Exception:
+            log.exception("test_connection failed")
             return False
 
@@ -46,68 +56,58 @@
     @staticmethod
     def authenticate_user(email, password):
-        """Автентикација (враќа row од \"User\" или None). Password проверката прави ја во сервис/route (bcrypt)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute(
-                'SELECT user_id, user_name, user_surname, email, role, password FROM "User" WHERE email = %s',
-                (email,)
-            )
-            user = cur.fetchone()
-            cur.close()
-            conn.close()
-            return dict(user) if user else None
-        except Exception as e:
-            print(f"Грешка при автентикација: {e}")
+        """Fetch user row by email. Password check is done in service layer."""
+        try:
+            with _conn_cur() as cur:
+                cur.execute(
+                    'SELECT user_id, user_name, user_surname, email, role, password '
+                    'FROM "User" WHERE email = %s',
+                    (email,)
+                )
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("authenticate_user failed (email=%s)", email)
             return None
 
     @staticmethod
     def register_user(name, surname, email, password_hash, role, teacher_id=None):
-        """Регистрирај нов корисник. Ако role='student' → внес во student; ако role='teacher' → внес во teacher."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-
-            # User
-            cur.execute(
-                'INSERT INTO "User" (user_name, user_surname, email, password, role) '
-                'VALUES (%s, %s, %s, %s, %s) RETURNING user_id',
-                (name, surname, email, password_hash, role)
-            )
-            user_id = cur.fetchone()['user_id']
-
-            # Subtype
-            if role == 'student' and teacher_id:
-                cur.execute('INSERT INTO student (student_id, teacher_id) VALUES (%s, %s)',
-                            (user_id, teacher_id))
-            elif role == 'teacher':
-                cur.execute('INSERT INTO teacher (teacher_id) VALUES (%s)', (user_id,))
-
-            conn.commit()
-            cur.close()
-            conn.close()
-            return user_id
-        except Exception as e:
-            print(f"Грешка при регистрација: {e}")
+        try:
+            with _conn_cur() as cur:
+                # User
+                cur.execute(
+                    'INSERT INTO "User" (user_name, user_surname, email, password, role) '
+                    'VALUES (%s, %s, %s, %s, %s) RETURNING user_id',
+                    (name, surname, email, password_hash, role)
+                )
+                user_id = cur.fetchone()['user_id']
+
+                # Subtype
+                if role == 'student' and teacher_id:
+                    cur.execute(
+                        'INSERT INTO student (student_id, teacher_id) VALUES (%s, %s)',
+                        (user_id, teacher_id)
+                    )
+                elif role == 'teacher':
+                    cur.execute('INSERT INTO teacher (teacher_id) VALUES (%s)', (user_id,))
+
+                return user_id
+        except Exception:
+            log.exception("register_user failed (email=%s, role=%s)", email, role)
             return None
 
     @staticmethod
     def get_user_by_id(user_id):
-        """Земи корисник + teacher_id ако е студент (LEFT JOIN со student во мали букви)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT u.*, s.teacher_id
-                FROM "User" u
-                LEFT JOIN student s ON u.user_id = s.student_id
-                WHERE u.user_id = %s
-            ''', (user_id,))
-            row = cur.fetchone()
-            cur.close()
-            conn.close()
-            return dict(row) if row else None
-        except Exception as e:
-            print(f"Грешка: {e}")
+        try:
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT u.*, s.teacher_id
+                    FROM "User" u
+                    LEFT JOIN student s ON u.user_id = s.student_id
+                    WHERE u.user_id = %s
+                ''', (user_id,))
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("get_user_by_id failed (%s)", user_id)
             return None
 
@@ -115,18 +115,14 @@
     def get_all_teachers():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT t.teacher_id, u.user_name, u.user_surname
-                FROM teacher t
-                JOIN "User" u ON t.teacher_id = u.user_id
-                ORDER BY u.user_name
-            ''')
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT t.teacher_id, u.user_name, u.user_surname
+                    FROM teacher t
+                    JOIN "User" u ON t.teacher_id = u.user_id
+                    ORDER BY u.user_name
+                ''')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_all_teachers failed")
             return []
 
@@ -134,13 +130,9 @@
     def get_all_users():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('SELECT user_id, user_name, user_surname, email, role FROM "User" ORDER BY user_name')
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('SELECT user_id, user_name, user_surname, email, role FROM "User" ORDER BY user_name')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_all_users failed")
             return None
 
@@ -149,37 +141,30 @@
     def get_all_elements():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT element_id, symbol, element_name, atomic_number, 
-                       atomic_weight, melting_point, boiling_point, hazard_type, description_element
-                FROM elements
-                ORDER BY atomic_number
-            ''')
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
-            return None
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT element_id, symbol, element_name, atomic_number, 
+                           atomic_weight, melting_point, boiling_point, hazard_type, description_element
+                    FROM elements
+                    ORDER BY atomic_number
+                ''')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_all_elements failed")
+            return None
+        
 
     @staticmethod
     def add_element(symbol, name, atomic_number, atomic_weight, melting_point, boiling_point, hazard_type, description, teacher_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                INSERT INTO elements (symbol, element_name, atomic_number, atomic_weight, melting_point, boiling_point, hazard_type, description_element, teacher_id)
-                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
-                RETURNING element_id
-            ''', (symbol, name, atomic_number, atomic_weight, melting_point, boiling_point, hazard_type, description, teacher_id))
-            el_id = cur.fetchone()['element_id']
-            conn.commit()
-            cur.close()
-            conn.close()
-            return el_id
-        except Exception as e:
-            print(f"Грешка при додавање елемент: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    INSERT INTO elements (symbol, element_name, atomic_number, atomic_weight, 
+                                          melting_point, boiling_point, hazard_type, description_element, teacher_id)
+                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
+                    RETURNING element_id
+                ''', (symbol, name, atomic_number, atomic_weight, melting_point, boiling_point, hazard_type, description, teacher_id))
+                return cur.fetchone()['element_id']
+        except Exception:
+            log.exception("add_element failed (symbol=%s, name=%s)", symbol, name)
             return None
 
@@ -187,18 +172,14 @@
     def update_element(element_id, symbol, name, atomic_number, atomic_weight, melting_point, boiling_point, hazard_type, description):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                UPDATE elements 
-                SET symbol = %s, element_name = %s, atomic_number = %s, atomic_weight = %s, 
-                    melting_point = %s, boiling_point = %s, hazard_type = %s, description_element = %s
-                WHERE element_id = %s
-            ''', (symbol, name, atomic_number, atomic_weight, melting_point, boiling_point, hazard_type, description, element_id))
-            conn.commit()
-            cur.close()
-            conn.close()
-            return True
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    UPDATE elements 
+                    SET symbol = %s, element_name = %s, atomic_number = %s, atomic_weight = %s, 
+                        melting_point = %s, boiling_point = %s, hazard_type = %s, description_element = %s
+                    WHERE element_id = %s
+                ''', (symbol, name, atomic_number, atomic_weight, melting_point, boiling_point, hazard_type, description, element_id))
+                return True
+        except Exception:
+            log.exception("update_element failed (element_id=%s)", element_id)
             return False
 
@@ -206,18 +187,15 @@
     def get_element_by_id(element_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT e.*, u.user_name || ' ' || u.user_surname AS created_by
-                FROM elements e
-                JOIN "User" u ON e.teacher_id = u.user_id
-                WHERE e.element_id = %s
-            ''', (element_id,))
-            row = cur.fetchone()
-            cur.close()
-            conn.close()
-            return dict(row) if row else None
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT e.*, u.user_name || ' ' || u.user_surname AS created_by
+                    FROM elements e
+                    JOIN "User" u ON e.teacher_id = u.user_id
+                    WHERE e.element_id = %s
+                ''', (element_id,))
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("get_element_by_id failed (%s)", element_id)
             return None
 
@@ -226,17 +204,13 @@
     def get_all_equipment():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT equipment_id, equipment_name, type, description, safety_info
-                FROM labequipment
-                ORDER BY equipment_name
-            ''')
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT equipment_id, equipment_name, type, description, safety_info
+                    FROM labequipment
+                    ORDER BY equipment_name
+                ''')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_all_equipment failed")
             return None
 
@@ -244,18 +218,13 @@
     def add_lab_equipment(name, equipment_type, description, safety_info, teacher_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                INSERT INTO labequipment (equipment_name, type, description, safety_info, teacher_id)
-                VALUES (%s, %s, %s, %s, %s)
-                RETURNING equipment_id
-            ''', (name, equipment_type, description, safety_info, teacher_id))
-            eq_id = cur.fetchone()['equipment_id']
-            conn.commit()
-            cur.close()
-            conn.close()
-            return eq_id
-        except Exception as e:
-            print(f"Грешка при додавање опрема: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    INSERT INTO labequipment (equipment_name, type, description, safety_info, teacher_id)
+                    VALUES (%s, %s, %s, %s, %s)
+                    RETURNING equipment_id
+                ''', (name, equipment_type, description, safety_info, teacher_id))
+                return cur.fetchone()['equipment_id']
+        except Exception:
+            log.exception("add_lab_equipment failed (name=%s, type=%s)", name, equipment_type)
             return None
 
@@ -263,28 +232,29 @@
     def update_equipment(equipment_id, name, equipment_type, description, safety_info):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                UPDATE labequipment 
-                SET equipment_name = %s, type = %s, description = %s, safety_info = %s
-                WHERE equipment_id = %s
-            ''', (name, equipment_type, description, safety_info, equipment_id))
-            conn.commit()
-            cur.close()
-            conn.close()
-            return True
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    UPDATE labequipment 
+                    SET equipment_name = %s, type = %s, description = %s, safety_info = %s
+                    WHERE equipment_id = %s
+                ''', (name, equipment_type, description, safety_info, equipment_id))
+                return True
+        except Exception:
+            log.exception("update_equipment failed (equipment_id=%s)", equipment_id)
             return False
 
     @staticmethod
     def get_equipment_by_id(equipment_id):
-        rows = DatabaseManager.get_all_equipment()
-        if not rows:
-            return None
-        for item in rows:
-            if item['equipment_id'] == equipment_id:
-                return item
-        return None
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT equipment_id, equipment_name, type, description, safety_info
+                    FROM labequipment WHERE equipment_id = %s
+                """, (equipment_id,))
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("get_equipment_by_id failed (%s)", equipment_id)
+            return None
+
 
     # ---------- REACTIONS ----------
@@ -292,18 +262,13 @@
     def add_reaction(teacher_id, element1_id, element2_id, product, conditions):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                INSERT INTO reaction (teacher_id, element1_id, element2_id, product, conditions)
-                VALUES (%s, %s, %s, %s, %s)
-                RETURNING reaction_id
-            ''', (teacher_id, element1_id, element2_id, product, conditions))
-            rid = cur.fetchone()['reaction_id']
-            conn.commit()
-            cur.close()
-            conn.close()
-            return rid
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    INSERT INTO reaction (teacher_id, element1_id, element2_id, product, conditions)
+                    VALUES (%s, %s, %s, %s, %s)
+                    RETURNING reaction_id
+                ''', (teacher_id, element1_id, element2_id, product, conditions))
+                return cur.fetchone()['reaction_id']
+        except Exception:
+            log.exception("add_reaction failed")
             return None
 
@@ -311,17 +276,13 @@
     def update_reaction(reaction_id, element1_id, element2_id, product, conditions):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                UPDATE reaction 
-                SET element1_id = %s, element2_id = %s, product = %s, conditions = %s
-                WHERE reaction_id = %s
-            ''', (element1_id, element2_id, product, conditions, reaction_id))
-            conn.commit()
-            cur.close()
-            conn.close()
-            return True
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    UPDATE reaction 
+                    SET element1_id = %s, element2_id = %s, product = %s, conditions = %s
+                    WHERE reaction_id = %s
+                ''', (element1_id, element2_id, product, conditions, reaction_id))
+                return True
+        except Exception:
+            log.exception("update_reaction failed (reaction_id=%s)", reaction_id)
             return False
 
@@ -329,13 +290,9 @@
     def delete_reaction(reaction_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('DELETE FROM reaction WHERE reaction_id = %s', (reaction_id,))
-            conn.commit()
-            cur.close()
-            conn.close()
-            return True
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('DELETE FROM reaction WHERE reaction_id = %s', (reaction_id,))
+                return True
+        except Exception:
+            log.exception("delete_reaction failed (reaction_id=%s)", reaction_id)
             return False
 
@@ -343,34 +300,42 @@
     def get_all_reactions():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT r.*,
-                       e1.symbol  AS element1_symbol, e1.element_name AS element1_name,
-                       e2.symbol  AS element2_symbol, e2.element_name AS element2_name,
-                       u.user_name || ' ' || u.user_surname AS created_by
-                FROM reaction r
-                JOIN elements e1 ON r.element1_id = e1.element_id
-                JOIN elements e2 ON r.element2_id = e2.element_id
-                JOIN "User" u   ON r.teacher_id = u.user_id
-                ORDER BY r.reaction_id DESC
-            ''')
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT r.*,
+                           e1.symbol  AS element1_symbol, e1.element_name AS element1_name,
+                           e2.symbol  AS element2_symbol, e2.element_name AS element2_name,
+                           u.user_name || ' ' || u.user_surname AS created_by
+                    FROM reaction r
+                    JOIN elements e1 ON r.element1_id = e1.element_id
+                    JOIN elements e2 ON r.element2_id = e2.element_id
+                    JOIN "User"  u   ON r.teacher_id = u.user_id
+                    ORDER BY r.reaction_id DESC
+                ''')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_all_reactions failed")
             return []
 
     @staticmethod
     def get_reaction_by_id(reaction_id):
-        rows = DatabaseManager.get_all_reactions()
-        if not rows:
-            return None
-        for r in rows:
-            if r['reaction_id'] == reaction_id:
-                return r
-        return None
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT r.*,
+                           e1.symbol  AS element1_symbol, e1.element_name AS element1_name,
+                           e2.symbol  AS element2_symbol, e2.element_name AS element2_name,
+                           u.user_name || ' ' || u.user_surname AS created_by
+                    FROM reaction r
+                    JOIN elements e1 ON r.element1_id = e1.element_id
+                    JOIN elements e2 ON r.element2_id = e2.element_id
+                    JOIN "User"  u   ON r.teacher_id = u.user_id
+                    WHERE r.reaction_id = %s
+                """, (reaction_id,))
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("get_reaction_by_id failed (%s)", reaction_id)
+            return None
+        
 
     # ---------- EXPERIMENTS ----------
@@ -378,18 +343,13 @@
     def insert_experiment(teacher_id, reaction_id, result, safety_warning):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                INSERT INTO experiment (teacher_id, reaction_id, result, safety_warning, time_stamp)
-                VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP)
-                RETURNING experiment_id
-            ''', (teacher_id, reaction_id, result, safety_warning))
-            eid = cur.fetchone()['experiment_id']
-            conn.commit()
-            cur.close()
-            conn.close()
-            return eid
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    INSERT INTO experiment (teacher_id, reaction_id, result, safety_warning, time_stamp)
+                    VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP)
+                    RETURNING experiment_id
+                ''', (teacher_id, reaction_id, result, safety_warning))
+                return cur.fetchone()['experiment_id']
+        except Exception:
+            log.exception("insert_experiment failed")
             return None
 
@@ -397,51 +357,73 @@
     def get_all_experiments():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT e.experiment_id,
-                       e.result,
-                       e.time_stamp,
-                       e.safety_warning,
-                       r.product,
-                       r.conditions,
-                       el1.symbol AS element1_symbol,
-                       el1.element_name AS element1_name,
-                       el2.symbol AS element2_symbol,
-                       el2.element_name AS element2_name,
-                       u.user_name || ' ' || u.user_surname AS created_by
-                FROM experiment e
-                JOIN reaction r ON e.reaction_id = r.reaction_id
-                JOIN elements el1 ON r.element1_id = el1.element_id
-                JOIN elements el2 ON r.element2_id = el2.element_id
-                JOIN "User" u ON e.teacher_id = u.user_id
-                ORDER BY e.time_stamp DESC
-            ''')
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
-            return []
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT e.experiment_id,
+                           e.result,
+                           e.time_stamp,
+                           e.safety_warning,
+                           r.product,
+                           r.conditions,
+                           el1.symbol AS element1_symbol,
+                           el1.element_name AS element1_name,
+                           el2.symbol AS element2_symbol,
+                           el2.element_name AS element2_name,
+                           u.user_name || ' ' || u.user_surname AS created_by
+                    FROM experiment e
+                    JOIN reaction r ON e.reaction_id = r.reaction_id
+                    JOIN elements el1 ON r.element1_id = el1.element_id
+                    JOIN elements el2 ON r.element2_id = el2.element_id
+                    JOIN "User" u ON e.teacher_id = u.user_id
+                    ORDER BY e.time_stamp DESC
+                ''')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_all_experiments failed")
+            return []
+
+    @staticmethod
+    def get_experiment_by_id(experiment_id):
+        try:
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT e.experiment_id,
+                           e.result,
+                           e.time_stamp,
+                           e.safety_warning,
+                           r.product,
+                           r.conditions,
+                           el1.symbol AS element1_symbol,
+                           el1.element_name AS element1_name,
+                           el2.symbol AS element2_symbol,
+                           el2.element_name AS element2_name,
+                           u.user_name || ' ' || u.user_surname AS created_by
+                    FROM experiment e
+                    JOIN reaction r ON e.reaction_id = r.reaction_id
+                    JOIN elements el1 ON r.element1_id = el1.element_id
+                    JOIN elements el2 ON r.element2_id = el2.element_id
+                    JOIN "User" u ON e.teacher_id = u.user_id
+                    WHERE e.experiment_id = %s
+                ''', (experiment_id,))
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("get_experiment_by_id failed (%s)", experiment_id)
+            return None
 
     @staticmethod
     def get_experiment_equipment(experiment_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT le.equipment_name, le.type, le.safety_info
-                FROM experimentlabequipment ele
-                JOIN labequipment le ON ele.equipment_id = le.equipment_id
-                WHERE ele.experiment_id = %s
-            ''', (experiment_id,))
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
-            return []
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT le.equipment_name, le.type, le.safety_info
+                    FROM experimentlabequipment ele
+                    JOIN labequipment le ON ele.equipment_id = le.equipment_id
+                    WHERE ele.experiment_id = %s
+                ''', (experiment_id,))
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_experiment_equipment failed (%s)", experiment_id)
+            return []
+
 
     # ---------- PARTICIPATION / VIEWS ----------
@@ -449,42 +431,34 @@
     def track_experiment_participation(user_id, experiment_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                INSERT INTO userparticipatesinexperiment (user_id, experiment_id)
-                VALUES (%s, %s)
-            ''', (user_id, experiment_id))
-            conn.commit()
-            cur.close()
-            conn.close()
-        except Exception as e:
-            print(f"Грешка при додавање учество: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    INSERT INTO userparticipatesinexperiment (user_id, experiment_id)
+                    VALUES (%s, %s)
+                ''', (user_id, experiment_id))
+        except Exception:
+            log.exception("track_experiment_participation failed")
 
     @staticmethod
     def get_user_experiments(user_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT e.*,
-                       r.product,
-                       r.conditions,
-                       el1.symbol AS element1_symbol, el1.element_name AS element1_name,
-                       el2.symbol AS element2_symbol, el2.element_name AS element2_name,
-                       up.participation_timestamp
-                FROM experiment e
-                JOIN userparticipatesinexperiment up ON e.experiment_id = up.experiment_id
-                JOIN reaction r ON e.reaction_id = r.reaction_id
-                JOIN elements el1 ON r.element1_id = el1.element_id
-                JOIN elements el2 ON r.element2_id = el2.element_id
-                WHERE up.user_id = %s
-                ORDER BY up.participation_timestamp DESC
-            ''', (user_id,))
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT e.*,
+                           r.product,
+                           r.conditions,
+                           el1.symbol AS element1_symbol, el1.element_name AS element1_name,
+                           el2.symbol AS element2_symbol, el2.element_name AS element2_name,
+                           up.participation_timestamp
+                    FROM experiment e
+                    JOIN userparticipatesinexperiment up ON e.experiment_id = up.experiment_id
+                    JOIN reaction r ON e.reaction_id = r.reaction_id
+                    JOIN elements el1 ON r.element1_id = el1.element_id
+                    JOIN elements el2 ON r.element2_id = el2.element_id
+                    WHERE up.user_id = %s
+                    ORDER BY up.participation_timestamp DESC
+                ''', (user_id,))
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_user_experiments failed (%s)", user_id)
             return []
 
@@ -492,32 +466,23 @@
     def track_element_view(user_id, element_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('SELECT 1 FROM userviewselement WHERE user_id = %s AND element_id = %s',
-                        (user_id, element_id))
-            if not cur.fetchone():
-                cur.execute('INSERT INTO userviewselement (user_id, element_id) VALUES (%s, %s)',
-                            (user_id, element_id))
-                conn.commit()
-            cur.close()
-            conn.close()
-        except Exception as e:
-            print(f"Грешка при tracking (element): {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    INSERT INTO userviewselement(user_id, element_id)
+                    VALUES (%s, %s) ON CONFLICT DO NOTHING
+                ''', (user_id, element_id))
+        except Exception:
+            log.exception("track_element_view failed")
 
     @staticmethod
     def track_equipment_view(user_id, equipment_id):
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('SELECT 1 FROM userviewslabequipment WHERE user_id = %s AND equipment_id = %s',
-                        (user_id, equipment_id))
-            if not cur.fetchone():
-                cur.execute('INSERT INTO userviewslabequipment (user_id, equipment_id) VALUES (%s, %s)',
-                            (user_id, equipment_id))
-                conn.commit()
-            cur.close()
-            conn.close()
-        except Exception as e:
-            print(f"Грешка при tracking (equipment): {e}")
+            with _conn_cur() as cur:
+                cur.execute('''
+                    INSERT INTO userviewslabequipment(user_id, equipment_id)
+                    VALUES (%s, %s) ON CONFLICT DO NOTHING
+                ''', (user_id, equipment_id))
+        except Exception:
+            log.exception("track_equipment_view failed")
+
 
     # ---------- REPORT EXAMPLES ----------
@@ -525,53 +490,44 @@
     def get_equipment_usage_report():
         try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute('''
-                SELECT le.equipment_name,
-                       COUNT(ele.experiment_id) AS usage_count
-                FROM experimentlabequipment ele
-                RIGHT JOIN labequipment le ON ele.equipment_id = le.equipment_id
-                GROUP BY le.equipment_name, le.equipment_id
-                ORDER BY usage_count DESC, le.equipment_name
-            ''')
-            rows = cur.fetchall()
-            cur.close()
-            conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка: {e}")
-            return []
+            with _conn_cur() as cur:
+                cur.execute('''
+                    SELECT le.equipment_name,
+                           COUNT(ele.experiment_id) AS usage_count
+                    FROM labequipment le
+                    LEFT JOIN experimentlabequipment ele ON ele.equipment_id = le.equipment_id
+                    GROUP BY le.equipment_name, le.equipment_id
+                    ORDER BY usage_count DESC, le.equipment_name
+                ''')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_equipment_usage_report failed")
+            return []
+
 
     # ---------- NEW: N:M helper ----------
     @staticmethod
     def add_experiment_equipment(experiment_id, equipment_ids, conn=None, cur=None):
-        """Bulk insert во experimentlabequipment; ако нема листа, ништо не прави."""
+        """Bulk insert into experimentlabequipment; idempotent via ON CONFLICT DO NOTHING."""
         if not equipment_ids:
             return
-        own = False
-        if conn is None or cur is None:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            own = True
-
-        values_sql = ",".join(["(%s,%s)"] * len(equipment_ids))
-        params = []
-        for eq_id in equipment_ids:
-            params.extend([experiment_id, eq_id])
-
-        cur.execute(f'''
-            INSERT INTO experimentlabequipment (experiment_id, equipment_id)
-            VALUES {values_sql}
-            ON CONFLICT DO NOTHING
-        ''', params)
-
-        if own:
-            conn.commit()
-            cur.close()
-            conn.close()
-
-    # ---------- NEW: main transactional creator ----------
-    @staticmethod
-    def create_reaction_and_experiment(
+        rows = [(experiment_id, eq_id) for eq_id in equipment_ids]
+        try:
+            if conn and cur:
+                execute_values(cur, """
+                    INSERT INTO experimentlabequipment (experiment_id, equipment_id)
+                    VALUES %s ON CONFLICT DO NOTHING
+                """, rows)
+            else:
+                with DatabaseManager.get_connection() as c:
+                    with c.cursor() as k:
+                        execute_values(k, """
+                            INSERT INTO experimentlabequipment (experiment_id, equipment_id)
+                            VALUES %s ON CONFLICT DO NOTHING
+                        """, rows)
+        except Exception:
+            log.exception("add_experiment_equipment failed (exp=%s)", experiment_id)
+
+    @staticmethod
+    def _create_reaction_and_experiment_python(
         teacher_id,
         element1_id,
@@ -579,116 +535,367 @@
         product,
         conditions,
-        experiment_result,         # опис во проза (НЕ product)
+        experiment_result,         # prose description (NOT product)
         safety_warning=None,
-        equipment_ids=None         # листа од int
+        equipment_ids=None
     ):
-        """Креира Reaction → Experiment (+ опрема) во ЕДНА транскација."""
+        """Create Reaction → Experiment (+equipment) in ONE transaction."""
         conn = None
         try:
             conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-
-            # 1) Reaction
-            cur.execute('''
-                INSERT INTO reaction (teacher_id, element1_id, element2_id, product, conditions)
-                VALUES (%s, %s, %s, %s, %s)
-                RETURNING reaction_id
-            ''', (teacher_id, element1_id, element2_id, product, conditions))
-            reaction_id = cur.fetchone()['reaction_id']
-
-            # 2) Ако нема експериментски опис → генерирај од симболи
-            if not experiment_result:
-                # симболи
-                cur.execute('SELECT symbol FROM elements WHERE element_id = %s', (element1_id,))
-                s1 = cur.fetchone()['symbol']
-                cur.execute('SELECT symbol FROM elements WHERE element_id = %s', (element2_id,))
-                s2 = cur.fetchone()['symbol']
-                experiment_result = (
-                    f"Експеримент со {s1} и {s2} под услови: {conditions or 'стандардни'}. "
-                    f"Очекуван производ: {product or 'непознат'}."
-                )
-
-            # 3) Experiment
-            cur.execute('''
-                INSERT INTO experiment (teacher_id, reaction_id, result, safety_warning, time_stamp)
-                VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP)
-                RETURNING experiment_id
-            ''', (teacher_id, reaction_id, experiment_result, safety_warning))
-            experiment_id = cur.fetchone()['experiment_id']
-
-            # 4) Equipment links
-            if equipment_ids:
-                DatabaseManager.add_experiment_equipment(
-                    experiment_id=experiment_id,
-                    equipment_ids=equipment_ids,
-                    conn=conn, cur=cur
-                )
-
-            conn.commit()
-            cur.close()
-            conn.close()
+            with conn:
+                with conn.cursor() as cur:
+                    # 1) Reaction
+                    cur.execute('''
+                        INSERT INTO reaction (teacher_id, element1_id, element2_id, product, conditions)
+                        VALUES (%s, %s, %s, %s, %s)
+                        RETURNING reaction_id
+                    ''', (teacher_id, element1_id, element2_id, product, conditions))
+                    reaction_id = cur.fetchone()['reaction_id']
+
+                    # 2) fallback experiment_result if missing
+                    if not experiment_result:
+                        cur.execute('SELECT symbol FROM elements WHERE element_id = %s', (element1_id,))
+                        s1 = cur.fetchone()['symbol']
+                        cur.execute('SELECT symbol FROM elements WHERE element_id = %s', (element2_id,))
+                        s2 = cur.fetchone()['symbol']
+                        experiment_result = (
+                            f"Експеримент со {s1} и {s2} под услови: {conditions or 'стандардни'}. "
+                            f"Очекуван производ: {product or 'непознат'}."
+                        )
+
+                    # 3) Experiment
+                    cur.execute('''
+                        INSERT INTO experiment (teacher_id, reaction_id, result, safety_warning, time_stamp)
+                        VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP)
+                        RETURNING experiment_id
+                    ''', (teacher_id, reaction_id, experiment_result, safety_warning))
+                    experiment_id = cur.fetchone()['experiment_id']
+
+                    # 4) Equipment links
+                    if equipment_ids:
+                        DatabaseManager.add_experiment_equipment(
+                            experiment_id=experiment_id,
+                            equipment_ids=equipment_ids,
+                            conn=conn, cur=cur
+                        )
+
             return {"reaction_id": reaction_id, "experiment_id": experiment_id}
 
-        except Exception as e:
+        except Exception:
             if conn:
-                conn.rollback()
-                conn.close()
-            print(f"Грешка при креирање реакција+експеримент: {e}")
-            return None
-# --- ДОДАДИ ВО КЛАСАТА DatabaseManager ---
-
+                try:
+                    conn.rollback()
+                except Exception:
+                    pass
+                try:
+                    conn.close()
+                except Exception:
+                    pass
+            log.exception("_create_reaction_and_experiment_python failed")
+            return None
+
+    # ---------- helpers / views / stats ----------
     @staticmethod
     def get_experiment_by_reaction(reaction_id):
-        """Врати го најновиот експеримент за дадена реакција (или None)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT *
-                FROM experiment
-                WHERE reaction_id = %s
-                ORDER BY time_stamp DESC
-                LIMIT 1
-            """, (reaction_id,))
-            row = cur.fetchone()
-            cur.close(); conn.close()
-            return dict(row) if row else None
-        except Exception as e:
-            print(f"Грешка get_experiment_by_reaction: {e}")
-            return None
-
-
-    @staticmethod
-    def add_experiment_equipment(experiment_id, equipment_ids, conn=None, cur=None):
-        """Додај повеќе записи во N:M табелата experimentlabequipment."""
-        own_conn = own_cur = False
-        try:
-            if conn is None or cur is None:
-                conn = DatabaseManager.get_connection(); own_conn = True
-                cur = conn.cursor(); own_cur = True
-
-            if equipment_ids:
-                cur.executemany(
-                    "INSERT INTO experimentlabequipment (experiment_id, equipment_id) VALUES (%s, %s)",
-                    [(experiment_id, eq_id) for eq_id in equipment_ids]
-                )
-
-            if own_conn:
-                conn.commit()
-            return True
-        except Exception as e:
-            if own_conn and conn:
-                conn.rollback()
-            print(f"Грешка add_experiment_equipment: {e}")
-            return False
-        finally:
-            if own_cur:
-                cur.close()
-            if own_conn and conn:
-                conn.close()
-
-
-    @staticmethod
-    def create_reaction_and_experiment(
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT *
+                    FROM experiment
+                    WHERE reaction_id = %s
+                    ORDER BY time_stamp DESC
+                    LIMIT 1
+                """, (reaction_id,))
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("get_experiment_by_reaction failed (%s)", reaction_id)
+            return None
+
+    @staticmethod
+    def get_student_participation_experiments(student_id):
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT
+                        e.experiment_id,
+                        e.result,
+                        e.safety_warning,
+                        e.time_stamp,
+                        r.product,
+                        r.conditions,
+                        el1.symbol AS element1_symbol,
+                        el1.element_name AS element1_name,
+                        el2.symbol AS element2_symbol,
+                        el2.element_name AS element2_name
+                    FROM userparticipatesinexperiment up
+                    JOIN experiment e ON up.experiment_id = e.experiment_id
+                    JOIN reaction  r  ON e.reaction_id = r.reaction_id
+                    JOIN elements el1 ON r.element1_id = el1.element_id
+                    JOIN elements el2 ON r.element2_id = el2.element_id
+                    WHERE up.user_id = %s
+                    ORDER BY e.time_stamp DESC
+                """, (student_id,))
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_student_participation_experiments failed (%s)", student_id)
+            return []
+
+    @staticmethod
+    def get_student_statistics(student_id):
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT 
+                        (SELECT COUNT(*) FROM userparticipatesinexperiment WHERE user_id = %s) AS experiment_count,
+                        (SELECT COUNT(*) FROM userviewselement             WHERE user_id = %s) AS element_count,
+                        (SELECT COUNT(*) FROM userviewslabequipment        WHERE user_id = %s) AS equipment_count,
+                        (
+                            SELECT COUNT(DISTINCT e.reaction_id)
+                            FROM userparticipatesinexperiment up
+                            JOIN experiment e ON up.experiment_id = e.experiment_id
+                            WHERE up.user_id = %s
+                        ) AS reaction_count
+                """, (student_id, student_id, student_id, student_id))
+                row = cur.fetchone()
+                return dict(row) if row else {
+                    'experiment_count': 0, 'element_count': 0, 'equipment_count': 0, 'reaction_count': 0
+                }
+        except Exception:
+            log.exception("get_student_statistics failed (%s)", student_id)
+            return {'experiment_count': 0, 'element_count': 0, 'equipment_count': 0, 'reaction_count': 0}
+
+    @staticmethod
+    def get_teacher_dashboard_statistics(teacher_id):
+        try:
+            with _conn_cur() as cur:
+                def get_c():
+                    row = cur.fetchone()
+                    if row is None:
+                        return 0
+                    try:
+                        return int(row['c'])
+                    except Exception:
+                        return int(row[0])
+
+                cur.execute("""
+                    SELECT COUNT(*) AS c
+                    FROM student
+                    WHERE teacher_id = %s
+                """, (teacher_id,))
+                student_count = get_c()
+
+                cur.execute("""
+                    SELECT COUNT(*) AS c
+                    FROM reaction
+                    WHERE teacher_id = %s
+                """, (teacher_id,))
+                reaction_count = get_c()
+
+                cur.execute("""
+                    SELECT COUNT(*) AS c
+                    FROM experiment
+                    WHERE teacher_id = %s
+                """, (teacher_id,))
+                experiment_count = get_c()
+
+                try:
+                    cur.execute("""
+                        SELECT COUNT(*) AS c
+                        FROM userparticipatesinexperiment up
+                        JOIN student s ON up.user_id = s.student_id
+                        WHERE s.teacher_id = %s
+                        AND up.participation_timestamp::date = CURRENT_DATE
+                    """, (teacher_id,))
+                    activity_count = get_c()
+                except Exception:
+                    cur.execute("""
+                        SELECT COUNT(*) AS c
+                        FROM userparticipatesinexperiment up
+                        JOIN student   s ON up.user_id       = s.student_id
+                        JOIN experiment e ON up.experiment_id = e.experiment_id
+                        WHERE s.teacher_id = %s
+                        AND e.time_stamp::date = CURRENT_DATE
+                    """, (teacher_id,))
+                    activity_count = get_c()
+
+                return {
+                    'student_count': student_count,
+                    'reaction_count': reaction_count,
+                    'experiment_count': experiment_count,
+                    'activity_count': activity_count
+                }
+        except Exception:
+            log.exception("get_teacher_dashboard_statistics failed (teacher_id=%s)", teacher_id)
+            return {'student_count': 0, 'reaction_count': 0, 'experiment_count': 0, 'activity_count': 0}
+
+    @staticmethod
+    def get_my_students_activity(teacher_id):
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT 
+                        s.student_id,
+                        (u.user_name || ' ' || u.user_surname) AS full_name,
+                        COALESCE(COUNT(DISTINCT uve.element_id), 0)      AS total_elements_viewed,
+                        COALESCE(COUNT(DISTINCT uvl.equipment_id), 0)    AS total_lab_equipment_viewed
+                    FROM student s
+                    JOIN "User" u ON s.student_id = u.user_id
+                    LEFT JOIN userviewselement      uve ON s.student_id = uve.user_id
+                    LEFT JOIN userviewslabequipment uvl ON s.student_id = uvl.user_id
+                    WHERE s.teacher_id = %s
+                    GROUP BY s.student_id, full_name
+                    ORDER BY total_elements_viewed DESC, total_lab_equipment_viewed DESC
+                """, (teacher_id,))
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_my_students_activity failed")
+            return []
+
+    @staticmethod
+    def get_students_without_experiments(teacher_id):
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT 
+                        s.student_id,
+                        (u.user_name || ' ' || u.user_surname) AS full_name
+                    FROM student s
+                    JOIN "User" u ON s.student_id = u.user_id
+                    LEFT JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
+                    WHERE s.teacher_id = %s
+                      AND up.user_id IS NULL
+                    ORDER BY full_name
+                """, (teacher_id,))
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_students_without_experiments failed")
+            return []
+
+    @staticmethod
+    def get_students_with_few_experiments(teacher_id, max_experiments=3):
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT 
+                        s.student_id,
+                        (u.user_name || ' ' || u.user_surname) AS full_name,
+                        COUNT(up.experiment_id) AS total_experiments
+                    FROM student s
+                    JOIN "User" u ON s.student_id = u.user_id
+                    LEFT JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
+                    WHERE s.teacher_id = %s
+                    GROUP BY s.student_id, full_name
+                    HAVING COUNT(up.experiment_id) < %s
+                    ORDER BY total_experiments ASC, full_name
+                """, (teacher_id, max_experiments))
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_students_with_few_experiments failed")
+            return []
+
+    @staticmethod
+    def get_element_views_report():
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT 
+                        (u.user_name || ' ' || u.user_surname) AS full_name,
+                        u.role,
+                        e.symbol,
+                        e.element_name,
+                        COUNT(*) AS view_count
+                    FROM userviewselement uve
+                    JOIN "User" u ON uve.user_id = u.user_id
+                    JOIN elements e ON uve.element_id = e.element_id
+                    GROUP BY u.user_id, u.user_name, u.user_surname, u.role, 
+                            e.element_id, e.symbol, e.element_name
+                    ORDER BY u.user_name, e.symbol
+                """)
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_element_views_report failed")
+            return []
+
+    @staticmethod
+    def get_teacher_statistics():
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT 
+                        t.teacher_id,
+                        (u.user_name || ' ' || u.user_surname) AS full_name,
+                        COUNT(DISTINCT s.student_id) AS total_students,
+                        COUNT(up.experiment_id)      AS total_experiments,
+                        ROUND(
+                            COUNT(up.experiment_id) * 1.0 / NULLIF(COUNT(DISTINCT s.student_id), 0), 2
+                        ) AS avg_experiments_per_student
+                    FROM teacher t
+                    JOIN "User" u ON t.teacher_id = u.user_id
+                    LEFT JOIN student s ON t.teacher_id = s.teacher_id
+                    LEFT JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
+                    GROUP BY t.teacher_id, full_name
+                    ORDER BY avg_experiments_per_student DESC, full_name
+                """)
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_teacher_statistics failed")
+            return []
+
+    @staticmethod
+    def get_students_experiments_for_teacher(teacher_id):
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT 
+                        (u.user_name || ' ' || u.user_surname) AS student_name,
+                        s.student_id,
+                        e.experiment_id,
+                        e.result,
+                        e.time_stamp,
+                        r.product,
+                        el1.symbol AS element1_symbol,
+                        el2.symbol AS element2_symbol,
+                        up.participation_timestamp AS participation_date
+                    FROM student s
+                    JOIN "User" u ON s.student_id = u.user_id
+                    JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
+                    JOIN experiment e ON up.experiment_id = e.experiment_id
+                    JOIN reaction  r ON e.reaction_id   = r.reaction_id
+                    JOIN elements el1 ON r.element1_id = el1.element_id
+                    JOIN elements el2 ON r.element2_id = el2.element_id
+                    WHERE s.teacher_id = %s
+                    ORDER BY up.participation_timestamp DESC, student_name
+                """, (teacher_id,))
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_students_experiments_for_teacher failed")
+            return []
+
+    # Views
+    @staticmethod
+    def vw_students_experiments_detailed():
+        try:
+            with _conn_cur() as cur:
+                cur.execute('SELECT * FROM vw_students_experiments_detailed')
+                return cur.fetchall()
+        except Exception:
+            log.exception("vw_students_experiments_detailed failed")
+            return []
+
+    @staticmethod
+    def vw_students_experiments_for_teacher(teacher_id):
+        try:
+            with _conn_cur() as cur:
+                cur.execute('SELECT * FROM vw_students_experiments_for_teacher WHERE teacher_id = %s',
+                            (teacher_id,))
+                return cur.fetchall()
+        except Exception:
+            log.exception("vw_students_experiments_for_teacher failed (teacher_id=%s)", teacher_id)
+            return []
+
+    # DB function wrapper + fallback
+    @staticmethod
+    def create_reaction_and_experiment_dbfn(
         teacher_id,
         element1_id,
@@ -700,412 +907,107 @@
         equipment_ids=None
     ):
-        """
-        Креирај реакција + експеримент во една транскација.
-        experiment_result е опис во проза (не е исто со product).
-        equipment_ids е листа од INT (опционално).
-        """
-        conn = None
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-
-            # 1) Reaction
-            cur.execute("""
-                INSERT INTO reaction (teacher_id, element1_id, element2_id, product, conditions)
-                VALUES (%s, %s, %s, %s, %s)
-                RETURNING reaction_id
-            """, (teacher_id, element1_id, element2_id, product, conditions))
-            reaction_id = cur.fetchone()[0]
-
-            # 2) Experiment
-            if not experiment_result:
-                experiment_result = f"Експеримент за: {product or 'непознат производ'}"
-
-            cur.execute("""
-                INSERT INTO experiment (teacher_id, reaction_id, result, safety_warning, time_stamp)
-                VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP)
-                RETURNING experiment_id
-            """, (teacher_id, reaction_id, experiment_result, safety_warning or 'Стандардни безбедносни мерки'))
-            experiment_id = cur.fetchone()[0]
-
-            # 3) Опрема (ако има)
-            if equipment_ids:
-                cur.executemany(
-                    "INSERT INTO experimentlabequipment (experiment_id, equipment_id) VALUES (%s, %s)",
-                    [(experiment_id, eq_id) for eq_id in equipment_ids]
+        try:
+            with _conn_cur() as cur:
+                cur.execute(
+                    '''
+                    SELECT * FROM create_reaction_and_experiment_fn(
+                        %s, %s, %s, %s, %s, %s, %s, %s::int[]
+                    )
+                    ''',
+                    (
+                        teacher_id,
+                        element1_id,
+                        element2_id,
+                        product,
+                        conditions,
+                        experiment_result,
+                        safety_warning,
+                        equipment_ids
+                    )
                 )
-
-            conn.commit()
-            cur.close(); conn.close()
-            return {'reaction_id': reaction_id, 'experiment_id': experiment_id}
-
-        except Exception as e:
-            if conn: conn.rollback()
-            print(f"Грешка create_reaction_and_experiment: {e}")
-            return None
-        finally:
-            if conn:
-                try: conn.close()
-                except: pass
-    
-    @staticmethod
-    def get_student_participation_experiments(student_id):
-        """Експерименти во кои студентот учествувал (со детали за реакцијата)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT
-                    e.experiment_id,
-                    e.result,
-                    e.safety_warning,
-                    e.time_stamp,
-                    r.product,
-                    r.conditions,
-                    el1.symbol AS element1_symbol,
-                    el1.element_name AS element1_name,
-                    el2.symbol AS element2_symbol,
-                    el2.element_name AS element2_name
-                FROM userparticipatesinexperiment up
-                JOIN experiment e ON up.experiment_id = e.experiment_id
-                JOIN reaction  r  ON e.reaction_id = r.reaction_id
-                JOIN elements el1 ON r.element1_id = el1.element_id
-                JOIN elements el2 ON r.element2_id = el2.element_id
-                WHERE up.user_id = %s
-                ORDER BY e.time_stamp DESC
-            """, (student_id,))
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_student_participation_experiments: {e}")
-            return []
-    @staticmethod
-    def get_student_statistics(student_id):
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    (SELECT COUNT(*) FROM userparticipatesinexperiment WHERE user_id = %s) AS experiment_count,
-                    (SELECT COUNT(*) FROM userviewselement             WHERE user_id = %s) AS element_count,
-                    (SELECT COUNT(*) FROM userviewslabequipment        WHERE user_id = %s) AS equipment_count,
-                    (
-                        SELECT COUNT(DISTINCT e.reaction_id)
-                        FROM userparticipatesinexperiment up
-                        JOIN experiment e ON up.experiment_id = e.experiment_id
-                        WHERE up.user_id = %s
-                    ) AS reaction_count
-            """, (student_id, student_id, student_id, student_id))
-            row = cur.fetchone()
-            cur.close(); conn.close()
-            return dict(row) if row else {
-                'experiment_count': 0, 'element_count': 0, 'equipment_count': 0, 'reaction_count': 0
-            }
-        except Exception as e:
-            print(f"Грешка get_student_statistics: {e}")
-            return {'experiment_count': 0, 'element_count': 0, 'equipment_count': 0, 'reaction_count': 0}
-
-    @staticmethod
-    def get_teacher_dashboard_statistics(teacher_id):
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-
-            def get_c():
                 row = cur.fetchone()
-                if row is None:
-                    return 0
-                try:
-                    return int(row['c'])   # RealDictRow
-                except Exception:
-                    return int(row[0])     # tuple fallback
-
-            # 1) број на студенти
-            cur.execute("""
-                SELECT COUNT(*) AS c
-                FROM student
-                WHERE teacher_id = %s
-            """, (teacher_id,))
-            student_count = get_c()
-
-            # 2) број на реакции на овој професор
-            cur.execute("""
-                SELECT COUNT(*) AS c
-                FROM reaction
-                WHERE teacher_id = %s
-            """, (teacher_id,))
-            reaction_count = get_c()
-
-            # 3) број на експерименти креирани од овој професор
-            cur.execute("""
-                SELECT COUNT(*) AS c
-                FROM experiment
-                WHERE teacher_id = %s
-            """, (teacher_id,))
-            experiment_count = get_c()
-
-            # 4) активности денес — прво пробај participation_timestamp; ако ја нема колоната, падни на e.time_stamp
+                return dict(row) if row else None
+        except Exception:
+            log.exception("create_reaction_and_experiment_dbfn failed")
+            return None
+
+    @staticmethod
+    def create_reaction_and_experiment(
+        teacher_id,
+        element1_id,
+        element2_id,
+        product,
+        conditions,
+        experiment_result,
+        safety_warning=None,
+        equipment_ids=None
+    ):
+        # Try DB function first
+        res = DatabaseManager.create_reaction_and_experiment_dbfn(
+            teacher_id, element1_id, element2_id, product, conditions,
+            experiment_result, safety_warning, equipment_ids
+        )
+        if res:
+            return res
+        # Fallback to Python transaction
+        try:
+            return DatabaseManager._create_reaction_and_experiment_python(
+                teacher_id, element1_id, element2_id, product, conditions,
+                experiment_result, safety_warning, equipment_ids
+            )
+        except Exception:
+            log.exception("fallback _create_reaction_and_experiment_python failed")
+            return None
+
+    @staticmethod
+    def get_students_experiments_detailed(teacher_id: int):
+        return DatabaseManager.vw_students_experiments_for_teacher(teacher_id)
+
+    @staticmethod
+    def get_user_activity_summary():
+        try:
+            with _conn_cur() as cur:
+                cur.execute('SELECT * FROM vw_user_activity_summary ORDER BY full_name')
+                return cur.fetchall()
+        except Exception:
+            log.exception("get_user_activity_summary view failed; falling back to raw SELECT")
             try:
-                cur.execute("""
-                    SELECT COUNT(*) AS c
-                    FROM userparticipatesinexperiment up
-                    JOIN student s ON up.user_id = s.student_id
-                    WHERE s.teacher_id = %s
-                    AND up.participation_timestamp::date = CURRENT_DATE
-                """, (teacher_id,))
-                activity_count = get_c()
+                with _conn_cur() as cur:
+                    cur.execute("""
+                        SELECT 
+                            u.user_id,
+                            (u.user_name || ' ' || u.user_surname) AS full_name,
+                            u.role,
+                            COUNT(DISTINCT uve.element_id)     AS elements_viewed,
+                            COUNT(DISTINCT uvl.equipment_id)   AS equipment_viewed,
+                            COUNT(DISTINCT upe.experiment_id)  AS experiments_participated
+                        FROM "User" u
+                        LEFT JOIN userviewselement           uve ON u.user_id = uve.user_id
+                        LEFT JOIN userviewslabequipment      uvl ON u.user_id = uvl.user_id
+                        LEFT JOIN userparticipatesinexperiment upe ON u.user_id = upe.user_id
+                        GROUP BY u.user_id, full_name, u.role
+                        ORDER BY full_name
+                    """)
+                    return cur.fetchall()
             except Exception:
-                cur.execute("""
-                    SELECT COUNT(*) AS c
-                    FROM userparticipatesinexperiment up
-                    JOIN student   s ON up.user_id       = s.student_id
-                    JOIN experiment e ON up.experiment_id = e.experiment_id
-                    WHERE s.teacher_id = %s
-                    AND e.time_stamp::date = CURRENT_DATE
-                """, (teacher_id,))
-                activity_count = get_c()
-
-            cur.close(); conn.close()
-            return {
-                'student_count': student_count,
-                'reaction_count': reaction_count,
-                'experiment_count': experiment_count,
-                'activity_count': activity_count
-            }
-        except Exception as e:
-            print("Грешка get_teacher_dashboard_statistics:", e)
-            try:
-                cur.close(); conn.close()
-            except Exception:
-                pass
-            return {'student_count': 0, 'reaction_count': 0, 'experiment_count': 0, 'activity_count': 0}
-
-    @staticmethod
-    def get_my_students_activity(teacher_id):
-        """Активност на студентите на конкретен професор: прегледани елементи/опрема."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    s.student_id,
-                    (u.user_name || ' ' || u.user_surname) AS full_name,
-                    COALESCE(COUNT(DISTINCT uve.element_id), 0)      AS total_elements_viewed,
-                    COALESCE(COUNT(DISTINCT uvl.equipment_id), 0)    AS total_lab_equipment_viewed
-                FROM student s
-                JOIN "User" u ON s.student_id = u.user_id
-                LEFT JOIN userviewselement      uve ON s.student_id = uve.user_id
-                LEFT JOIN userviewslabequipment uvl ON s.student_id = uvl.user_id
-                WHERE s.teacher_id = %s
-                GROUP BY s.student_id, full_name
-                ORDER BY total_elements_viewed DESC, total_lab_equipment_viewed DESC
-            """, (teacher_id,))
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_my_students_activity: {e}")
-            return []
-        
-    @staticmethod
-    def get_students_without_experiments(teacher_id):
-        """Студенти на конкретен професор кои немаат ниту еден експеримент."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    s.student_id,
-                    (u.user_name || ' ' || u.user_surname) AS full_name
-                FROM student s
-                JOIN "User" u ON s.student_id = u.user_id
-                LEFT JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
-                WHERE s.teacher_id = %s
-                AND up.user_id IS NULL
-                ORDER BY full_name
-            """, (teacher_id,))
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_students_without_experiments: {e}")
-            return []
-
-
-    @staticmethod
-    def get_students_with_few_experiments(teacher_id, max_experiments=3):
-        """Студенти со помалку од max_experiments експерименти."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    s.student_id,
-                    (u.user_name || ' ' || u.user_surname) AS full_name,
-                    COUNT(up.experiment_id) AS total_experiments
-                FROM student s
-                JOIN "User" u ON s.student_id = u.user_id
-                LEFT JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
-                WHERE s.teacher_id = %s
-                GROUP BY s.student_id, full_name
-                HAVING COUNT(up.experiment_id) < %s
-                ORDER BY total_experiments ASC, full_name
-            """, (teacher_id, max_experiments))
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_students_with_few_experiments: {e}")
-            return []
-
-
-    @staticmethod
-    def get_students_experiments_detailed(teacher_id):
-        """Детален извештај за студентите на професорот и нивните експерименти."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    s.student_id,
-                    (u.user_name || ' ' || u.user_surname) AS full_name,
-                    e.experiment_id,
-                    e.result,
-                    e.time_stamp AS participation_time
-                FROM student s
-                JOIN "User" u ON s.student_id = u.user_id
-                JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
-                JOIN experiment e ON up.experiment_id = e.experiment_id
-                WHERE s.teacher_id = %s
-                ORDER BY u.user_name, e.time_stamp DESC
-            """, (teacher_id,))
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_students_experiments_detailed: {e}")
-            return []
-
-
-    @staticmethod
-    def get_element_views_report():
-        """Кој корисник кои елементи ги прегледал (агрегиран извештај)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    (u.user_name || ' ' || u.user_surname) AS full_name,
-                    u.role,
-                    e.symbol,
-                    e.element_name,
-                    COUNT(*) AS view_count
-                FROM userviewselement uve
-                JOIN "User" u ON uve.user_id = u.user_id
-                JOIN elements e ON uve.element_id = e.element_id
-                GROUP BY u.user_id, u.user_name, u.user_surname, u.role, 
-                        e.element_id, e.symbol, e.element_name
-                ORDER BY u.user_name, e.symbol
-            """)
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_element_views_report: {e}")
-            return []
-
-
-    @staticmethod
-    def get_teacher_statistics():
-        """Статистики за сите професори (вкупно студенти/експерименти и просек по студент)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    t.teacher_id,
-                    (u.user_name || ' ' || u.user_surname) AS full_name,
-                    COUNT(DISTINCT s.student_id) AS total_students,
-                    COUNT(up.experiment_id)      AS total_experiments,
-                    ROUND(
-                        COUNT(up.experiment_id) * 1.0 / NULLIF(COUNT(DISTINCT s.student_id), 0), 2
-                    ) AS avg_experiments_per_student
-                FROM teacher t
-                JOIN "User" u ON t.teacher_id = u.user_id
-                LEFT JOIN student s ON t.teacher_id = s.teacher_id
-                LEFT JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
-                GROUP BY t.teacher_id, full_name
-                ORDER BY avg_experiments_per_student DESC, full_name
-            """)
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_teacher_statistics: {e}")
-            return []
-
-
-    @staticmethod
-    def get_students_experiments_for_teacher(teacher_id):
-        """Експерименти изведени од студентите на даден професор (за извештаи)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    (u.user_name || ' ' || u.user_surname) AS student_name,
-                    s.student_id,
-                    e.experiment_id,
-                    e.result,
-                    e.time_stamp,
-                    r.product,
-                    el1.symbol AS element1_symbol,
-                    el2.symbol AS element2_symbol,
-                    up.participation_timestamp AS participation_date
-                FROM student s
-                JOIN "User" u ON s.student_id = u.user_id
-                JOIN userparticipatesinexperiment up ON s.student_id = up.user_id
-                JOIN experiment e ON up.experiment_id = e.experiment_id
-                JOIN reaction  r ON e.reaction_id   = r.reaction_id
-                JOIN elements el1 ON r.element1_id = el1.element_id
-                JOIN elements el2 ON r.element2_id = el2.element_id
-                WHERE s.teacher_id = %s
-                ORDER BY up.participation_timestamp DESC, student_name
-            """, (teacher_id,))
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_students_experiments_for_teacher: {e}")
-            return []
-
-
-    @staticmethod
-    def get_user_activity_summary():
-        """Сумарен извештај за активности по корисник (елементи/опрема/експерименти)."""
-        try:
-            conn = DatabaseManager.get_connection()
-            cur = conn.cursor()
-            cur.execute("""
-                SELECT 
-                    u.user_id,
-                    (u.user_name || ' ' || u.user_surname) AS full_name,
-                    u.role,
-                    COUNT(DISTINCT uve.element_id)     AS elements_viewed,
-                    COUNT(DISTINCT uvl.equipment_id)   AS equipment_viewed,
-                    COUNT(DISTINCT upe.experiment_id)  AS experiments_participated
-                FROM "User" u
-                LEFT JOIN userviewselement           uve ON u.user_id = uve.user_id
-                LEFT JOIN userviewslabequipment      uvl ON u.user_id = uvl.user_id
-                LEFT JOIN userparticipatesinexperiment upe ON u.user_id = upe.user_id
-                GROUP BY u.user_id, full_name, u.role
-                ORDER BY full_name
-            """)
-            rows = cur.fetchall()
-            cur.close(); conn.close()
-            return rows
-        except Exception as e:
-            print(f"Грешка get_user_activity_summary: {e}")
-            return []
-
+                log.exception("get_user_activity_summary fallback failed")
+                return []
+
+    @staticmethod
+    def get_reaction_by_symbols(sym1: str, sym2: str):
+        try:
+            with _conn_cur() as cur:
+                cur.execute("""
+                    SELECT r.reaction_id, r.product, r.conditions
+                    FROM reaction r
+                    JOIN elements e1 ON r.element1_id = e1.element_id
+                    JOIN elements e2 ON r.element2_id = e2.element_id
+                    WHERE (UPPER(e1.symbol) = UPPER(%s) AND UPPER(e2.symbol) = UPPER(%s))
+                       OR (UPPER(e1.symbol) = UPPER(%s) AND UPPER(e2.symbol) = UPPER(%s))
+                    LIMIT 1
+                """, (sym1, sym2, sym2, sym1))
+                row = cur.fetchone()
+                return dict(row) if row else None
+        except Exception:
+            log.exception("get_reaction_by_symbols failed (%s, %s)", sym1, sym2)
+            return None
