diff --git a/AGREEmip_app.py b/AGREEmip_app.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ea9a51f9dd9e529c98d01dad0289094e7ab44dd
--- /dev/null
+++ b/AGREEmip_app.py
@@ -0,0 +1,1146 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Mon Apr  8 19:07:35 2024
+
+@author: W.Wojnowski
+"""
+# imports:
+import tkinter as tk
+from tkinter import ttk
+from tkinter import messagebox
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+from matplotlib.colors import LinearSegmentedColormap
+from tkinter import filedialog
+from math import log
+from fpdf import FPDF
+import os
+from datetime import datetime
+import numpy as np
+
+'''
+--------------------------------
+'''
+
+# start the main app
+root = tk.Tk()
+root.title('AGREEmip - Analytical Greenness Metric for MIPs')
+root.geometry('800x490')
+root.iconbitmap('AGREEmip_icon.ico')
+
+# fix the window dimensions:
+root.resizable(0, 0)
+
+# define the color palette. This can be based on https://flatuicolors.com
+colors = {
+    'foreground': '#ffffff',
+    'background': '#dfe4ea',
+    # 'background': '#dfe4ea',
+    'accent': '#70a1ff',
+    # 'accent': '#9b59b6',
+    'text': 'black'
+}
+
+# configure the background:
+root.configure(bg=colors['background'], padx=8, pady=8)
+
+# create and configure a style to be used in tabs and labels
+s = ttk.Style()
+
+
+s.theme_create("AGREEmip_theme", parent="alt", settings={
+    "TNotebook": {
+        "configure": {
+            'background': colors['background'],
+            'borderwidth': 0,
+            'tabmargins': [0, 0, 0, 0],
+            'padding': [0, 0, 5, 0],
+            'relief': 'flat'}},
+    "TNotebook.Tab": {
+        "configure": {
+            'padding': [7, 1],
+            'background': colors['accent'],
+            'foreground': colors['text'],
+            # change the colour of a dashed frame around the title of the
+            # selected frame to the foreground colour, so that it is not visible:
+            'focuscolor': colors['foreground'],
+            'borderwidth': 0,
+            'bordercolor': 'red'},
+        "map": {
+            "background": [("selected", colors['foreground'])],
+            "expand": [("selected", [1, 1, 1, 0])]}},
+    'TLabel': {
+        'configure': {
+            'background': colors['foreground'],
+            'foreground': colors['text'],
+            'padding': [5, 5, 5, 5]}},
+    'TFrame': {
+        'configure': {
+            'background': colors['foreground'],
+            'borderwidth': 0},
+        "map": {
+            "background": [("focus", colors['accent']),
+                           ("pressed", colors['accent']),
+                           ("disabled", colors['accent']),
+                           ("readonly", colors['accent']),
+                           ],
+            "relief": [("focus", 'sunken'),
+                           ("pressed", 'sunken'),
+                           ("disabled", 'sunken'),
+                           ("readonly", 'sunken'),
+                           ]}},
+    'TEntry': {
+        'configure': {
+            'background': 'red',
+            'fieldbackground': colors['background'],
+            'foreground': colors['text'],
+            'insertcolor': colors['text'],
+            'selectbackground': colors['accent'],
+        }},
+    'TButton': {
+        'configure': {
+            'background': colors['accent'],
+            'focuscolor': colors['accent'],
+            'foreground': colors['text'],
+            'anchor': 'center'},
+        'map': {
+            'relief': [('pressed', 'groove')]
+        }},
+    'TRadiobutton': {
+        'configure': {
+            'focuscolor': colors['foreground'],
+            'background': colors['foreground'],
+            'foreground': colors['text'],
+            'indicatorcolor': colors['background']},
+        "map": {
+            "background": [("active", colors['accent']),
+                           ("pressed", colors['accent']),
+                           ("disabled", colors['accent'])],
+            "foreground": [("active", colors['text'])],
+            'indicatorcolor': [('selected', colors['accent'])]
+        }},
+    'TCheckbutton': {
+        'configure': {
+            'focuscolor': colors['foreground'],
+            'background': colors['background'],
+            'foreground': colors['text'],
+            'focusthickness': 0,
+            'indicatorcolor': colors['background'],
+            'padding': 0,},
+        "map": {
+            "background": [("active", colors['accent']),
+                           ("pressed", colors['accent']),
+                           ("disabled", colors['accent']),
+                           ],
+            'focuscolor': [("active", colors['accent']),
+                           ("pressed", colors['background']),
+                           ("disabled", colors['background']),
+                           ('selected', colors['accent']),
+                           ('alternate', colors['background']),
+                           ('readonly', colors['background']),
+                           ],
+            "foreground": [("active", colors['text'])],
+            "padding": [('active', 0),
+                        ('alternate', 0),
+                        ('pressed', 0),
+                        ('disabled', 0),
+                        ('selected', 0),
+                        ('readonly', 0)],
+            'focusthickness': [('pressed', 0)],
+            'indicatorcolor': [('selected', colors['accent'])]
+        }},
+    'TMenubutton': {
+        'configure': {
+            'background': colors['accent'],
+            'foreground': colors['text'],
+            'width': '20'
+        }},
+    'TMenu': {
+        'configure': {
+            'background': colors['accent'],
+            'foreground': colors['text'],
+            'width': '20',
+            'arrowcolor': colors['text'],
+        }},
+    
+    'Vertical.TScrollbar': {
+        'configure': {
+            'background': colors['accent'],
+            'troughcolor': colors['foreground'],
+            'foreground': colors['foreground'],
+            'arrowcolor': colors['text'],
+            'relief': 'flat',
+            'borderwidth': 2,
+        }},
+    
+})
+
+    
+s.theme_use("AGREEmip_theme")
+
+# to remove relief from the TEntry widget
+# based on https://stackoverflow.com/questions/44383730/
+s.layout('AGREEmip_theme', [
+    ('Entry.highlight', {
+        'sticky': 'nswe',
+        'children':
+            [('Entry.border', {
+                'border': '1',
+                'sticky': 'nswe',
+                'children':
+                    [('Entry.padding', {
+                        'sticky': 'nswe',
+                        'children':
+                            [('Entry.textarea',
+                              {'sticky': 'nswe'})]
+                    })]
+            })]
+    })])
+
+s.configure('AGREEmip_theme', relief='flat',
+            background=colors['background'],
+            foreground=colors['text'],
+            insertcolor=colors['text'],
+            selectbackground=colors['accent']
+            )
+
+
+'''
+---------------------------------------------------
+Global functions
+'''
+
+def save_image():
+    ftypes = [('PNG file', '.png'), ('SVG file', '.svg'), ('All files', '*')]
+    filename = filedialog.asksaveasfilename(filetypes=ftypes, defaultextension='.png')
+    # save the plot in the specified path; the 'tight' option removes the whitespace from around the figure:
+    plt.savefig(filename, bbox_inches='tight', dpi=300)
+
+
+def call_info_popup():
+    win = tk.Toplevel()
+    win_frame = tk.Frame(win, width=500, background=colors['foreground'])
+    win_frame.pack()
+    win.iconbitmap('AGREEmip_icon.ico')
+    win.wm_title('About and citation info')
+    text = ttk.Label(win_frame, text='If you use AGREEmip, please cite:', wraplength=280, justify='left')
+    text.grid(column=0, row=0, padx=8, pady=8, sticky='w')
+    text2 = tk.Text(win_frame, width=50, height=5, wrap='word', bg=colors['background'])
+    citation = 'Author 1, Author 2 ..., AGREEmip - Analytical Greenness Metric' \
+               ' for MIPs, Journal Name (2024), doi.org/10.0000/0000000000'
+    text2.grid(column=0, row=1, padx=8, pady=8, sticky='w')
+    text2.insert(tk.END, citation)
+    text3 = ttk.Label(win_frame, text='Most recent version of the source code can be found at:', wraplength=320, justify='left')
+    text3.grid(column=0, row=2, padx=8, pady=8, sticky='w')
+    text4 = tk.Text(win_frame, width=50, height=1, wrap='word', bg=colors['background'])
+    source_link = 'git.pg.edu.pl/p174235/agreemip'
+    text4.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+    text4.insert(tk.END, source_link)
+    text5 = ttk.Label(win_frame, text='Copyright (c) 2024 Authors, '
+                                      'available under the MIT License', wraplength=380,
+                      justify='left')
+    text5.grid(column=0, row=4, padx=8, pady=8, sticky='w')
+
+
+def reset_scores():
+    for criterion in criteria:
+        criterion.textvar.set('1.0')
+        criterion.optionvar.set('Select')
+        criterion.valuevar.set('Input')
+
+    criteria[0].radiovar.set(1)
+    criteria[1].radiovar.set(2)
+    criteria[2].radiovar.set(1)
+    criteria[3].radiovar.set(3)
+    criteria[4].radiovar.set(4)
+    criteria[5].radiovar.set(3)
+    criteria[6].radiovar.set(2)
+    criteria[7].radiovar.set(3)
+    criteria[8].radiovar.set(1)
+    criteria[9].radiovar.set(4)
+    criteria[10].radiovar.set(3)
+    criteria[11].radiovar.set(3)
+    
+    # Reset all checkboxes in all tabs
+    for tab_items_state in tabs_items_states:
+        for item_state in tab_items_state:
+            item_state['var'].set(0)
+
+    create_plot()
+
+def temp_func():
+    pass
+
+
+def generate_report():
+    report = Report(tabs, criteria)
+    report.savePDF()
+
+
+def create_menu():
+    menu = tk.Menu()
+    root.config(menu=menu)
+    file_menu = tk.Menu(menu)
+    file_menu.config(background=colors['background'],
+                     activeborderwidth=5,
+                     activeforeground=colors['text'],
+                     activebackground=colors['accent'],
+                     foreground=colors['text'],
+                     tearoff=0)
+
+    file_menu.add_command(label='Save image', command=save_image)
+    file_menu.add_command(label='Re-set', command=reset_scores)
+    file_menu.add_command(label='Report', command=generate_report)
+    about_menu = tk.Menu(menu)
+    about_menu.config(background=colors['background'],
+                      activeborderwidth=5,
+                      activeforeground=colors['text'],
+                      activebackground=colors['accent'],
+                      foreground=colors['text'],
+                      tearoff=0)
+    menu.add_cascade(label='File', menu=file_menu)
+    menu.add_cascade(label='About', menu=about_menu)
+    about_menu.add_command(label='Info', command=call_info_popup)
+
+
+def calculate_score():
+    indv_scores = 0
+    weights = 0
+    for criterion in criteria:
+        indv_scores += (float(criterion.textvar.get()) * criterion.radiovar.get())
+        weights += criterion.radiovar.get()
+    score = indv_scores / weights
+    return score
+
+
+# a function for restarting the right frame (to clear the memory after each change)
+# it is then used when there is a need to change the plot
+def clear_frame(frame):
+    frame.destroy()
+    global right_frame
+    right_frame = tk.Frame(root, bd=1, padx=2, pady=2, width=500, height=500, bg=colors['foreground'])
+    right_frame.pack(side='right', anchor='n')
+
+
+# connect a float in range 0.0 : 1.0 to a colour in a spectrum from red to yellow to green
+# (256^3 discrete colour values):
+def colorMapper(value):
+    cmap = LinearSegmentedColormap.from_list('rg', ["red", "yellow", "green"], N=256)
+    mapped_color = int(value * 255)
+    color = cmap(mapped_color)
+    return color
+
+
+def change_dropdown(criterion, tab_choices, *args):
+    if criterion.optionvar.get() == 'Select':
+        criterion.textvar.set(1.0)
+    else:
+        criterion.textvar.set(tab_choices[criterion.optionvar.get()])
+        create_plot()
+
+
+def create_plot(event=None):
+    # event=None is passed so that the entry.bind
+    # does not return a positional argument;
+    # close the current plot window (otherwise the generated plots remain open in the memory):
+    plt.close()
+    
+    # re-generate the frame:
+    clear_frame(right_frame)
+
+    fig = plt.figure(figsize=(8, 8), dpi=150, facecolor=colors['foreground'])
+    ax = plt.subplot()
+    ax.set_aspect('equal', adjustable='datalim')
+
+    scores = []
+    weights = []
+
+    for criterion in criteria:
+        scores.append(float(criterion.textvar.get()))
+        weights.append(criterion.radiovar.get())
+
+    # radius of the central circle
+    R = 5.0 # 4 for 10 circles
+    
+    outer_radii = [round(0.28 * w + 0.4, 2) for w in weights]
+    main_score = calculate_score()
+
+    central_x = 0
+    central_y = 0
+    angles = np.linspace(0, 2 * np.pi, len(outer_radii), endpoint=False) - np.pi / 2
+
+    for angle, r, i , score in zip(angles, outer_radii, range(len(outer_radii)), scores):
+        x = central_x + (R + 2 * r - 2.1) * np.cos(-angle)
+        y = central_y + (R + 2 * r - 2.1) * np.sin(-angle)
+    
+        # Create a clipping annulus
+        outer_circle_border = plt.Circle((x, y), r + 0.18, facecolor='white', edgecolor='black',
+                                  linewidth=1, zorder=2)
+        central_circle = plt.Circle((central_x, central_y), R, facecolor=colorMapper(main_score),
+                                edgecolor='black', linewidth=1, zorder=1)
+    
+        ax.add_patch(central_circle)
+        outer_circle_border.set_clip_path(central_circle)
+    
+        ax.add_patch(outer_circle_border)
+    
+        outer_circle_border_noedge = plt.Circle((x, y), r + 0.14, facecolor='white', edgecolor='blue',
+                                  linewidth=0, zorder=3)
+        ax.add_patch(outer_circle_border_noedge)
+    
+    
+        outer_circle = plt.Circle((x, y), r, facecolor=colorMapper(score), edgecolor='black',
+                                  linewidth=1, zorder=4)
+        ax.add_patch(outer_circle)
+    
+        ax.annotate(str(i + 1), xy=(x, y), fontsize=8, ha='center', va='center', zorder=5)
+
+    central_circle = plt.Circle((central_x, central_y), R, facecolor=colorMapper(main_score),
+                              edgecolor='black', linewidth=1, zorder=1)
+    ax.add_patch(central_circle)
+
+    ax.annotate(str(round(main_score, 2)), xy=(0, 0), fontsize=20, ha='center', va='center')       
+    
+    margin = 7.91    
+    ax.set(ylim=(-margin, margin),
+          xlim=(-margin, margin))
+    
+    plt.axis('off')
+    plt.tight_layout()      
+        
+    canvas = FigureCanvasTkAgg(figure=fig, master=right_frame)
+    plot_widget = canvas.get_tk_widget()
+    plot_widget.pack(side='top')
+
+        
+def create_scrollable_list(tab_frame, global_items, tab_index, row, height=130):
+    # Ensure tab state initialization with a more robust check and initialization
+    while len(tabs_items_states) <= tab_index:
+        tabs_items_states.append([])
+
+    # Proceed with setting up the container, canvas, and scrollbar
+    container_frame = ttk.Frame(tab_frame)
+    container_frame.grid(row=row, column=0, sticky='w', pady=0)
+    tab_frame.grid_rowconfigure(row, weight=0)
+    tab_frame.grid_columnconfigure(0, weight=1)
+
+    canvas = tk.Canvas(container_frame, height=height, background=colors['background'], border=0)
+    scrollbar = ttk.Scrollbar(container_frame, orient='vertical', command=canvas.yview)
+    canvas.configure(yscrollcommand=scrollbar.set, highlightthickness=4, highlightcolor=colors['background'])
+    canvas.grid(row=0, column=0, sticky='w')
+    scrollbar.grid(row=0, column=1, sticky='ns')
+    container_frame.grid_columnconfigure(0, weight=1)
+    container_frame.grid_rowconfigure(0, weight=0)
+
+    # Setup for scrollable frame
+    scrollable_frame = ttk.Frame(canvas, style='AGREEmip_theme')
+    canvas.create_window((0, 0), window=scrollable_frame, anchor='nw', tags="scrollable_frame")
+    canvas.bind("<Configure>", lambda e: canvas.itemconfig("scrollable_frame", width=e.width))
+    scrollable_frame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
+
+    # Populate with items
+    for item in global_items:
+        var = tk.IntVar()
+        # Using 'code' as the label text directly, since it includes the description
+        check = ttk.Checkbutton(scrollable_frame, text=item['code'], variable=var)
+        check.grid(sticky="w", pady=0)
+        # Append each new variable and item to the state list for this specific tab
+        tabs_items_states[tab_index].append({'var': var, 'item': item})
+
+
+
+
+
+# calculate the sum of selected hazards from the scroll-down list
+def calculate_sum(tab_index):
+    if tab_index < len(tabs_items_states):
+        tab_items_state = tabs_items_states[tab_index]
+        total = sum(item_state['item']['value'] for item_state in tab_items_state if item_state['var'].get() == 1)
+        print("Total value of selected items for tab", tab_index, ":", total)
+        return total
+    else:
+        print("Invalid tab index")
+        return 0
+
+
+
+'''
+--------------------------------------------------
+Script
+'''
+create_menu()
+
+
+# create the two main frames of the GUI
+left_frame = tk.Frame(root, bd=0, padx=2, pady=0, width=300, height=500, bg=colors['background'])
+left_frame.pack(side='left', anchor='n')
+
+right_frame = tk.Frame(root, bd=1, padx=2, pady=2, width=500, height=500, bg=colors['foreground'])
+right_frame.pack(side='right', anchor='n')
+
+
+# notebook which will house the 10 tabs (in the left frame)
+class Notebook:
+
+    def __init__(self, parent):
+        self.parent = parent
+        self.notebook = ttk.Notebook(self.parent, height=500, width=300)
+        self.notebook.pack()
+
+    def add_tab(self, tab, text):
+        self.notebook.add(tab, text=text)
+
+
+tab_bar = Notebook(left_frame)
+
+
+class Tab:
+
+    def __init__(self, tab_no, title, text1, text2, criterion):
+        self.title = title
+        self.parent = tab_bar
+        self.frame = tk.Frame(self.parent.notebook, bg=colors['foreground'])
+        self.parent.add_tab(self.frame, text=tab_no)
+        self.header = ttk.Label(self.frame, text=title, wraplength=280, font=('TkDefaultFont', 10, 'bold'))
+        self.header.grid(column=0, row=0, sticky='w')
+        self.label1 = ttk.Label(self.frame, text=text1, wraplength=280)
+        self.label1.grid(column=0, row=1, sticky='w')
+        self.label2 = ttk.Label(self.frame, text=text2, wraplength=280)
+        self.label2.grid(column=0, row=2, sticky='w')
+
+        self.criterion = criterion
+
+        self.ratio_label = ttk.Label(self.frame, text='Modify the default weight:')
+        self.ratio_label.place(rely=0.91, relx=0.025, anchor='sw')
+
+        self.radio_1 = ttk.Radiobutton(self.frame, text='1', variable=self.criterion.radiovar, command=create_plot,
+                                       value=1)
+        self.radio_1.place(rely=0.95, relx=0.05, anchor='sw')
+        self.radio_2 = ttk.Radiobutton(self.frame, text='2', variable=self.criterion.radiovar, command=create_plot,
+                                       value=2)
+        self.radio_2.place(rely=0.95, relx=0.15, anchor='sw')
+        self.radio_3 = ttk.Radiobutton(self.frame, text='3', variable=self.criterion.radiovar, command=create_plot,
+                                       value=3)
+        self.radio_3.place(rely=0.95, relx=0.25, anchor='sw')
+        self.radio_4 = ttk.Radiobutton(self.frame, text='4', variable=self.criterion.radiovar, command=create_plot,
+                                       value=4)
+        self.radio_4.place(rely=0.95, relx=0.35, anchor='sw')
+
+
+class Criterion:
+
+    def __init__(self, number):
+        self.number = number
+        self.textvar = tk.StringVar()
+        self.textvar.set('1.0')
+        self.radiovar = tk.IntVar()
+        self.optionvar = tk.StringVar()
+        self.optionvar.set('Select')
+        self.valuevar = tk.StringVar()
+        self.valuevar.set('Input')
+
+
+# create the 12 criteria values. They can be later called as
+# list elements, e.g. to get the value of criterion 3: criteria[2].textvar.get()
+criteria = []
+for i in range(1, 13):
+    criteria.append(Criterion(i))
+
+# assign the default weights (this could be done using itemgetter or itertools.compress, but
+# that would require importing additional packages):
+criteria[0].radiovar.set(1)
+criteria[1].radiovar.set(2)
+criteria[2].radiovar.set(1)
+criteria[3].radiovar.set(3)
+criteria[4].radiovar.set(4)
+criteria[5].radiovar.set(3)
+criteria[6].radiovar.set(2)
+criteria[7].radiovar.set(3)
+criteria[8].radiovar.set(1)
+criteria[9].radiovar.set(4)
+criteria[10].radiovar.set(3)
+criteria[11].radiovar.set(3)
+
+# start the GUI with a default plot
+create_plot()
+
+
+class Report:
+    def __init__(self, tabs, criteria):
+        self.pdf = FPDF('P', 'mm', 'A4')  # 'P' - Portrait
+        self.pdf.set_font('Helvetica', '', 10)
+        self.pdf.add_page()
+        self.pdf.set_margins(left=25, top=20)
+        self.tabs = tabs
+        self.criteria = criteria
+        plt.savefig('temp_figure.png', bbox_inches='tight')
+        # insert image (image, x, y, width):
+        self.pdf.image('temp_figure.png', 107, 10, 80)
+        # delete the temp file from drive:
+        os.remove('temp_figure.png')
+
+        self.fill_color = (240, 240, 240)
+
+        # insert title (Helvetica, 'B'old, 14 pt):
+        self.pdf.set_font('Helvetica', 'B', 18)
+        self.pdf.ln(20)
+        self.pdf.cell(100, 12, 'AGREEmip')
+        self.pdf.set_font('Helvetica', '', 12)
+        self.pdf.ln(10)
+        self.pdf.multi_cell(55, 4, 'Analytical Greenness Metric for MIPs')
+        self.pdf.ln(10)
+        self.pdf.set_font('Helvetica', '', 10)
+        self.pdf.cell(100, 12, datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
+        self.pdf.ln(30)
+
+        def fieldColor(score):
+            x = colorMapper(score)[0] * 255
+            y = colorMapper(score)[1] * 255
+            z = colorMapper(score)[2] * 255
+            self.pdf.set_fill_color(x, y, z)
+
+        def create_header():
+            self.pdf.set_font('Helvetica', 'B', 10)
+            self.pdf.cell(12, 6, '#', align='C')
+            self.pdf.cell(120, 6, 'Criterion', align='L')
+            self.pdf.cell(12, 6, 'Score', align='C')
+            self.pdf.cell(12, 6, 'Weight', align='C')
+            self.pdf.ln(8)
+            self.pdf.set_font('Helvetica', '', 10)
+
+        create_header()
+
+        def create_report_field(number, tabs, criterion, text):
+            self.pdf.cell(12, 12, number, border=1, align='C')
+            self.pdf.set_fill_color(240, 240, 240)
+            self.pdf.set_font('Helvetica', 'B', 10)
+            self.pdf.cell(120, 6, tabs.title, border=1, ln=2, align='L', fill=True)
+            self.pdf.set_font('Helvetica', '', 8)
+            self.pdf.cell(120, 6, text, border=1, ln=0, align='L', fill=False)
+            self.pdf.set_font('Helvetica', '', 10)
+
+            # modify the position of the following cells to ensure proper alignment:
+            x = self.pdf.get_x()
+            y = self.pdf.get_y()
+            self.pdf.set_xy(x, y - 6)
+
+            # set the colour of the score field:
+            fieldColor(float(criterion.textvar.get()))
+            self.pdf.cell(12, 12, str(round(float(criterion.textvar.get()), 2)), border=1, fill=True, align='C')
+            self.pdf.set_fill_color(240, 240, 240)
+            self.pdf.cell(12, 12, str(criterion.radiovar.get()), border=1, fill=True, align='C')
+            self.pdf.ln(15)
+
+        create_report_field('1.', self.tabs[0], self.criteria[0],
+                            ('Waste generation: ' + self.criteria[0].optionvar.get()))
+
+        create_report_field('2.', self.tabs[1], self.criteria[1],
+                            ('Total mass of the functional monomer: ' + self.criteria[1].valuevar.get() + ' [g]'))
+
+        create_report_field('3.', self.tabs[2], self.criteria[2],
+                            ('Total mass of the template: ' + self.criteria[2].valuevar.get() + ' [g]'))
+
+        create_report_field('4.', self.tabs[3], self.criteria[3],
+                            ('Total mass of the cross-linking agent: ' + self.criteria[3].valuevar.get() + ' [g]'))
+
+        create_report_field('5.', self.tabs[4], self.criteria[4],
+                            ('Total mass of the porogen/solvent: ' + self.criteria[4].valuevar.get() + ' [g]'))
+
+        create_report_field('6.', self.tabs[5], self.criteria[5],
+                            ('Total mass of other reagents, adjuvants, or carriers: ' + self.criteria[5].valuevar.get() + ' [g]'))
+
+        create_report_field('7.', self.tabs[6], self.criteria[6],
+                            ('Total mass of reagents used in core/particles preparation, surface modification, or both: ' + self.criteria[6].valuevar.get() + ' [g]'))
+
+        create_report_field('8.', self.tabs[7], self.criteria[7],
+                            ('Initiator: ' + self.criteria[7].optionvar.get()))
+
+        create_report_field('9.', self.tabs[8], self.criteria[8],
+                            ('Grains size range: ' + self.criteria[8].optionvar.get()))
+
+        create_report_field('10.', self.tabs[9], self.criteria[9],
+                            ('No. of distinct hazards: ' + str(calc_n_10())))
+
+        create_report_field('11.', self.tabs[10], self.criteria[10],
+                            ('Elution technique: ' + self.criteria[10].optionvar.get()))
+
+        create_report_field('12.', self.tabs[11], self.criteria[11],
+                            ('Times the end products can be reused: ' + self.criteria[11].optionvar.get()))
+        
+
+
+    def savePDF(self):
+        ftypes = [('PDF file', '.pdf'), ('All files', '*')]
+        filename = filedialog.asksaveasfilename(filetypes=ftypes, defaultextension='.pdf')
+        # save the pdf
+        self.pdf.output(filename, 'F')
+        # open the file in the system default viewer:
+        os.system('start ' + filename)
+
+
+
+
+global_items = [
+    {'code': '[H224] Extremely flammable liquid and vapour', 'value': 9},
+    {'code': '[H225] Highly flammable liquid or vapour', 'value': 7},
+    {'code': '[H226] Flammable liquid and vapour', 'value': 3},
+    {'code': '[H228] Flammable solid', 'value': 3},
+    {'code': '[H242] Heating may cause fire', 'value': 3},
+    {'code': '[H251] Self-heating; may catch fire', 'value': 3},
+    {'code': '[H261] In contact with water releases\nflammable gas', 'value': 2},
+    {'code': '[H280] Contains gas under pressure; may\nexplode if heated', 'value': 2},
+    {'code': '[H290] May be corrosive to metals', 'value': 2},
+    {'code': '[H300] Fatal if swallowed', 'value': 10},
+    {'code': '[H301] Toxic if swallowed', 'value': 7},
+    {'code': '[H302] Harmful if swallowed', 'value': 5},
+    {'code': '[H304] May be fatal if swallowed and\nenters airways', 'value': 8},
+    {'code': '[H310] Fatal in contact with skin', 'value': 10},
+    {'code': '[H311] Toxic in contact with skin', 'value': 7},
+    {'code': '[H312] Harmful in contact with skin', 'value': 5},
+    {'code': '[H314] Causes severe skin burns and eye\ndamage', 'value': 5},
+    {'code': '[H315] Causes skin irritation', 'value': 2},
+    {'code': '[H317] May cause an allergic skin reaction', 'value': 2},
+    {'code': '[H318] Causes serious eye damage', 'value': 7},
+    {'code': '[H319] Causes serious eye irritation', 'value': 5},
+    {'code': '[H330] Fatal if inhaled', 'value': 10},
+    {'code': '[H331] Toxic if inhaled', 'value': 7},
+    {'code': '[H332] Harmful if inhaled', 'value': 5},
+    {'code': '[H334] May cause allergy or asthma symptoms\nor breathing difficulties if inhaled', 'value': 3},
+    {'code': '[H335] May cause respiratory irritation', 'value': 2},
+    {'code': '[H336] May cause drowsiness or dizziness', 'value': 2},
+    {'code': '[H341] Suspected of causing genetic defects', 'value': 7},
+    {'code': '[H350] May cause cancer', 'value': 10},
+    {'code': '[H351] Suspected of causing cancer', 'value': 7},
+    {'code': '[H360] May damage fertility or the unborn child', 'value': 10},
+    {'code': '[H361] Suspected of damaging fertility or the\nunborn child', 'value': 7},
+    {'code': '[H370] Causes damage to organs', 'value': 10},
+    {'code': '[H372] Causes damage to organs through\nprolonged or repeated exposure', 'value': 8},
+    {'code': '[H373] May cause damage to organs through\nprolonged or repeated exposure', 'value': 7},
+    {'code': '[H400] Very toxic to aquatic life', 'value': 10},
+    {'code': '[H410] Very toxic to aquatic life with\nlong-lasting effects', 'value': 10},
+    {'code': '[H411] Toxic to aquatic life with\nlong-lasting effects', 'value': 10},
+    {'code': '[H412] Harmful to aquatic life with\nlong-lasting effects', 'value': 7},
+    {'code': '[H413] May cause long-lasting harmful\neffects on aquatic life', 'value': 5},
+    ]
+    # Add more items as needed
+
+# Assuming this global structure to hold each tab's selection state
+tabs_items_states = []
+
+
+
+'''
+Populate the tabs
+'''
+# --------------------------- TAB1 ---------------------------
+tab1 = Tab(tab_no='1 ', title='Preparation of polymerization reaction substrates - removal of polymerization inhibitors',
+           text1='Assessment of the consequences of removal of polymerization inhibitor from polymerization mixture. This can be done with solid and/or liquid waste generation, or without any resulting waste.',
+           text2='Waste generation:', criterion=criteria[0])
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f1 = tk.Frame(tab1.frame, border=2, background=colors['accent'])
+f1.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+tab1_choices = {'Lack of waste': 1.0,
+                'Generation of solid waste': 0.5,
+                'Generation of liquid waste': 0.2,
+                'Generation of solid and liquid waste': 0.0}
+dropdown1 = ttk.OptionMenu(tab1.frame, criteria[0].optionvar, criteria[0].optionvar.get(), *tab1_choices.keys(),
+                           command=lambda x: change_dropdown(criteria[0], tab1_choices))
+# the ttk style for OptionMenu does not include a style for the tk dropdown menu,
+# so this has to be configured separately:
+dropdown1['menu'].config(background=colors['background'],
+                         activeborderwidth=5,
+                         activebackground=colors['accent'],
+                         activeforeground=colors['text'],
+                         foreground=colors['text'],)
+dropdown1.config(width=40)
+
+dropdown1.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+
+# --------------------------- TAB2 ---------------------------
+tab2 = Tab(tab_no='2 ', title='Functional monomer',
+           text1='Duis semper turpis ipsum, pretium venenatis mauris ultricies sit amet.',
+           text2='Select the relevant hazard statements:',
+           criterion=criteria[1])
+
+
+
+create_scrollable_list(tab2.frame, global_items, 1, row=3)
+
+def calc_crit_2(event=None):
+    try:
+        if criteria[1].valuevar.get() == 'Input':
+            criteria[1].textvar.set(1.0)
+        else:
+            criteria[1].textvar.set(
+                round(abs(2.718281828459 **(float(criteria[1].valuevar.get()) * calculate_sum(1) * -0.004)), 2))
+    except ValueError:
+        messagebox.showerror(title='Value error',
+                             message='The mass has to be a float or an integer, e.g. 0.14 or 21.')
+    create_plot()
+    print('criterion 2: ', criteria[1].textvar.get())
+
+
+label_tab2 = ttk.Label(tab2.frame, text='Input the total mass [g] of the functional monomer:',
+                       wraplength=280)
+label_tab2.grid(column=0, row=4, sticky='w')
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f2 = tk.Frame(tab2.frame, border=2, background=colors['accent'])
+f2.grid(column=0, row=5, padx=8, pady=8, sticky='w')
+# create the entry and pack it in the frame
+entry2 = ttk.Entry(f2, textvariable=criteria[1].valuevar, width=10, style='AGREEmip_theme')
+entry2.grid(column=0, row=0, sticky='w')
+
+entry2.bind('<Return>', calc_crit_2)
+ttk.Button(tab2.frame, text='Set', command=calc_crit_2, width=8).grid(column=0, row=5, padx=80, pady=8, sticky='w')
+
+# --------------------------- TAB3 ---------------------------
+tab3 = Tab(tab_no='3 ', title='Template',
+           text1='Duis semper turpis ipsum, pretium venenatis mauris ultricies sit amet.',
+           text2='Select the relevant hazard statements:',
+           criterion=criteria[2])
+
+create_scrollable_list(tab3.frame, global_items, tab_index=2, row=3)
+
+def calc_crit_3(event=None):
+    try:
+        if criteria[2].valuevar.get() == 'Input':
+            criteria[2].textvar.set(1.0)
+        else:
+            criteria[2].textvar.set(
+                round(abs(2.718281828459 **(float(criteria[2].valuevar.get()) * calculate_sum(2) * -0.004)), 2))
+    except ValueError:
+        messagebox.showerror(title='Value error',
+                             message='The mass has to be a float or an integer, e.g. 0.14 or 21.')
+    create_plot()
+    print('criterion 3: ', criteria[2].textvar.get())
+
+
+label_tab3 = ttk.Label(tab3.frame, text='Input the total mass [g] of the template:',
+                       wraplength=280)
+label_tab3.grid(column=0, row=4, sticky='w')
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f3 = tk.Frame(tab3.frame, border=2, background=colors['accent'])
+f3.grid(column=0, row=5, padx=8, pady=8, sticky='w')
+# create the entry and pack it in the frame
+entry3 = ttk.Entry(f3, textvariable=criteria[2].valuevar, width=10, style='AGREEmip_theme')
+entry3.grid(column=0, row=0, sticky='w')
+
+entry3.bind('<Return>', calc_crit_3)
+ttk.Button(tab3.frame, text='Set', command=calc_crit_3, width=8).grid(column=0, row=5, padx=80, pady=8, sticky='w')
+
+
+# --------------------------- TAB4 ---------------------------
+tab4 = Tab(tab_no='4 ', title='Cross-linking agent',
+           text1='Duis semper turpis ipsum, pretium venenatis mauris ultricies sit amet.',
+           text2='Select the relevant hazard statements:',
+           criterion=criteria[3])
+
+create_scrollable_list(tab4.frame, global_items, tab_index=3, row=3)
+
+def calc_crit_4(event=None):
+    try:
+        if criteria[3].valuevar.get() == 'Input':
+            criteria[3].textvar.set(1.0)
+        else:
+            criteria[3].textvar.set(
+                round(abs(2.718281828459 **(float(criteria[3].valuevar.get()) * calculate_sum(3) * -0.004)), 2))
+    except ValueError:
+        messagebox.showerror(title='Value error',
+                             message='The mass has to be a float or an integer, e.g. 0.14 or 21.')
+    create_plot()
+
+label_tab4 = ttk.Label(tab4.frame, text='Input the total mass [g] of the cross-linking agent:',
+                       wraplength=280)
+label_tab4.grid(column=0, row=4, sticky='w')
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f4 = tk.Frame(tab4.frame, border=2, background=colors['accent'])
+f4.grid(column=0, row=5, padx=8, pady=8, sticky='w')
+# create the entry and pack it in the frame
+entry4 = ttk.Entry(f4, textvariable=criteria[3].valuevar, width=10, style='AGREEmip_theme')
+entry4.grid(column=0, row=0, sticky='w')
+
+entry4.bind('<Return>', calc_crit_4)
+ttk.Button(tab4.frame, text='Set', command=calc_crit_4, width=8).grid(column=0, row=5, padx=80, pady=8, sticky='w')
+
+
+# --------------------------- TAB5 ---------------------------
+tab5 = Tab(tab_no='5 ', title='Porogen / solvent',
+           text1='Duis semper turpis ipsum, pretium venenatis mauris ultricies sit amet.',
+           text2='Select the relevant hazard statements:',
+           criterion=criteria[4])
+
+create_scrollable_list(tab5.frame, global_items, tab_index=4, row=3)
+
+def calc_crit_5(event=None):
+    try:
+        if criteria[4].valuevar.get() == 'Input':
+            criteria[4].textvar.set(1.0)
+        else:
+            criteria[4].textvar.set(
+                round(abs(2.718281828459 **(float(criteria[4].valuevar.get()) * calculate_sum(4) * -0.004)), 2))
+    except ValueError:
+        messagebox.showerror(title='Value error',
+                             message='The mass has to be a float or an integer, e.g. 0.14 or 21.')
+    create_plot()
+
+label_tab5 = ttk.Label(tab5.frame, text='Input the total mass [g] of the porogen / solvent:',
+                       wraplength=280)
+label_tab5.grid(column=0, row=4, sticky='w')
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f5 = tk.Frame(tab5.frame, border=2, background=colors['accent'])
+f5.grid(column=0, row=5, padx=8, pady=8, sticky='w')
+# create the entry and pack it in the frame
+entry5 = ttk.Entry(f5, textvariable=criteria[4].valuevar, width=10, style='AGREEmip_theme')
+entry5.grid(column=0, row=0, sticky='w')
+
+entry5.bind('<Return>', calc_crit_5)
+ttk.Button(tab5.frame, text='Set', command=calc_crit_5, width=8).grid(column=0, row=5, padx=80, pady=8, sticky='w')
+
+
+# --------------------------- TAB6 ---------------------------
+tab6 = Tab(tab_no='6 ', title='Other reagents, adjuvants, or carriers',
+           text1='Duis semper turpis ipsum, pretium venenatis mauris ultricies sit amet.',
+           text2='Select the relevant hazard statements:',
+           criterion=criteria[5])
+
+create_scrollable_list(tab6.frame, global_items, tab_index=5, row=3)
+
+def calc_crit_6(event=None):
+    try:
+        if criteria[5].valuevar.get() == 'Input':
+            criteria[5].textvar.set(1.0)
+        else:
+            criteria[5].textvar.set(
+                round(abs(2.718281828459 **(float(criteria[5].valuevar.get()) * calculate_sum(5) * -0.004)), 2))
+    except ValueError:
+        messagebox.showerror(title='Value error',
+                             message='The mass has to be a float or an integer, e.g. 0.14 or 21.')
+    create_plot()
+
+label_tab6 = ttk.Label(tab6.frame, text='Input the total mass [g] of other reagents, adjuvants, or carriers:',
+                       wraplength=280)
+label_tab6.grid(column=0, row=4, sticky='w')
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f6 = tk.Frame(tab6.frame, border=2, background=colors['accent'])
+f6.grid(column=0, row=5, padx=8, pady=8, sticky='w')
+# create the entry and pack it in the frame
+entry6 = ttk.Entry(f6, textvariable=criteria[5].valuevar, width=10, style='AGREEmip_theme')
+entry6.grid(column=0, row=0, sticky='w')
+
+entry6.bind('<Return>', calc_crit_6)
+ttk.Button(tab6.frame, text='Set', command=calc_crit_6, width=8).grid(column=0, row=5, padx=80, pady=8, sticky='w')
+
+
+# --------------------------- TAB7 ---------------------------
+tab7 = Tab(tab_no='7 ', title='Core / particles preparation and surface modification',
+           text1='Duis semper turpis ipsum, pretium venenatis mauris ultricies sit amet.',
+           text2='Select the relevant hazard statements:',
+           criterion=criteria[6])
+
+create_scrollable_list(tab7.frame, global_items, tab_index=6, row=3)
+
+def calc_crit_7(event=None):
+    try:
+        if criteria[6].valuevar.get() == 'Input':
+            criteria[6].textvar.set(1.0)
+        else:
+            criteria[6].textvar.set(
+                round(abs(2.718281828459 **(float(criteria[6].valuevar.get()) * calculate_sum(6) * -0.004)), 2))
+    except ValueError:
+        messagebox.showerror(title='Value error',
+                             message='The mass has to be a float or an integer, e.g. 0.14 or 21.')
+    create_plot()
+
+label_tab7 = ttk.Label(tab7.frame, text='Input the total mass [g] of reagents used during core / particles preparation, surface modification, or both:',
+                       wraplength=280)
+label_tab7.grid(column=0, row=4, sticky='w')
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f7 = tk.Frame(tab7.frame, border=2, background=colors['accent'])
+f7.grid(column=0, row=5, padx=8, pady=8, sticky='w')
+# create the entry and pack it in the frame
+entry7 = ttk.Entry(f7, textvariable=criteria[6].valuevar, width=10, style='AGREEmip_theme')
+entry7.grid(column=0, row=0, sticky='w')
+
+entry7.bind('<Return>', calc_crit_7)
+ttk.Button(tab7.frame, text='Set', command=calc_crit_7, width=8).grid(column=0, row=5, padx=80, pady=8, sticky='w')
+
+
+# --------------------------- TAB8 ---------------------------
+tab8 = Tab(tab_no='8 ', title='Polymerisation initiation',
+           text1='Lorem ipsum dolor sit amet.',
+           text2='Select the initiator:', criterion=criteria[7])
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f8 = tk.Frame(tab8.frame, border=2, background=colors['accent'])
+f8.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+tab8_choices = {'Electropolymerisation': 1.0,
+                'Initiating the reaction with UV rays': 0.9,
+                'Sonication or microwaves': 0.8,
+                'Heating + mixing': 0.5,
+                'Chemical reagent + mixing': 0.2,
+                'Chemical reagent + heating + mixing': 0.0}
+
+dropdown8 = ttk.OptionMenu(tab8.frame, criteria[7].optionvar, criteria[7].optionvar.get(), *tab8_choices.keys(),
+                           command=lambda x: change_dropdown(criteria[7], tab8_choices))
+# the ttk style for OptionMenu does not include a style for the tk dropdown menu,
+# so this has to be configured separately:
+dropdown8['menu'].config(background=colors['background'],
+                         activeborderwidth=5,
+                         activebackground=colors['accent'],
+                         activeforeground=colors['text'],
+                         foreground=colors['text'],)
+dropdown8.config(width=40)
+
+dropdown8.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+
+# --------------------------- TAB9 ---------------------------
+tab9 = Tab(tab_no='9 ', title='Size of polymer particles',
+           text1='Lorem ipsum dolor sit amet.',
+           text2='Select the sorbent grain size:', criterion=criteria[8])
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f9 = tk.Frame(tab9.frame, border=2, background=colors['accent'])
+f9.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+tab9_choices = {'In-situ polymerisation': 1.0,
+                '> 1000 nm': 0.8,
+                '100-1000 nm': 0.6,
+                '10-100 nm': 0.4, 
+                'Carbon dots': 0.2,
+                'Quantum dots': 0.1,
+                }
+
+dropdown9 = ttk.OptionMenu(tab9.frame, criteria[8].optionvar, criteria[8].optionvar.get(), *tab9_choices.keys(),
+                           command=lambda x: change_dropdown(criteria[8], tab9_choices))
+# the ttk style for OptionMenu does not include a style for the tk dropdown menu,
+# so this has to be configured separately:
+dropdown9['menu'].config(background=colors['background'],
+                         activeborderwidth=5,
+                         activebackground=colors['accent'],
+                         activeforeground=colors['text'],
+                         foreground=colors['text'],)
+dropdown9.config(width=40)
+
+dropdown9.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+
+# --------------------------- TAB10 ---------------------------
+tab10 = Tab(tab_no='10', title='Template elution solvent',
+           text1='Duis semper turpis ipsum, pretium venenatis mauris ultricies sit amet.',
+           text2='Select the relevant hazard statements:',
+           criterion=criteria[9])
+
+create_scrollable_list(tab10.frame, global_items, tab_index=9, row=3)
+
+def calc_crit_10(event=None):
+
+    criteria[9].textvar.set(
+        round(abs(-0.0256 * calculate_sum(9) + 1), 2))
+
+    create_plot()
+
+
+# calculate the sum of selected hazards from the scroll-down list
+def calc_n_10():
+    if 9 < len(tabs_items_states):
+        tab_items_state = tabs_items_states[9]
+        number = 0 
+        for item_state in tab_items_state:
+            if item_state['var'].get() == 1:
+                number += 1
+        return number
+    else:
+        print("Invalid tab index")
+        return 0
+
+ttk.Button(tab10.frame, text='Set', command=calc_crit_10, width=8).grid(column=0, row=5, padx=80, pady=8, sticky='w')
+
+
+# --------------------------- TAB11 ---------------------------
+tab11 = Tab(tab_no='11', title='Template elution technique',
+           text1='Lorem ipsum dolor sit amet.',
+           text2='Select the relevant elution technique:', criterion=criteria[10])
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f11 = tk.Frame(tab11.frame, border=2, background=colors['accent'])
+f11.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+tab11_choices = {'Ultrasounds': 1.0,
+                'Supercritical CO2': 0.8,
+                'Regular mixing or shaking': 0.5,
+                'Soxhlet technique': 0.0,
+                }
+
+dropdown11 = ttk.OptionMenu(tab11.frame, criteria[10].optionvar, criteria[10].optionvar.get(), *tab11_choices.keys(),
+                           command=lambda x: change_dropdown(criteria[10], tab11_choices))
+# the ttk style for OptionMenu does not include a style for the tk dropdown menu,
+# so this has to be configured separately:
+dropdown11['menu'].config(background=colors['background'],
+                         activeborderwidth=5,
+                         activebackground=colors['accent'],
+                         activeforeground=colors['text'],
+                         foreground=colors['text'],)
+dropdown11.config(width=40)
+
+dropdown11.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+
+# --------------------------- TAB12 ---------------------------
+tab12 = Tab(tab_no='12', title='Final product reusability',
+           text1='Lorem ipsum dolor sit amet.',
+           text2='How many times can the final product be reused?', criterion=criteria[11])
+
+# create a frame to pack the entry into in order to get a border for the entry:
+f12 = tk.Frame(tab12.frame, border=2, background=colors['accent'])
+f12.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+tab12_choices = {'Reused > 10 times': 1.0,
+                'Reused 2-10 times': 0.6,
+                'Single use': 0.0,
+                }
+
+dropdown12 = ttk.OptionMenu(tab12.frame, criteria[11].optionvar, criteria[11].optionvar.get(), *tab11_choices.keys(),
+                           command=lambda x: change_dropdown(criteria[11], tab11_choices))
+# the ttk style for OptionMenu does not include a style for the tk dropdown menu,
+# so this has to be configured separately:
+dropdown12['menu'].config(background=colors['background'],
+                         activeborderwidth=5,
+                         activebackground=colors['accent'],
+                         activeforeground=colors['text'],
+                         foreground=colors['text'],)
+dropdown12.config(width=40)
+
+dropdown12.grid(column=0, row=3, padx=8, pady=8, sticky='w')
+
+
+
+# Create a list of the tabs and generate the report:
+tabs = [tab1, tab2, tab3, tab4, tab5, tab6,
+        tab7, tab8, tab9, tab10, tab11, tab12]
+
+
+# run the app in a loop
+def main():
+    while True:
+        root.mainloop()
+
+
+main()
+
+
+
+
+
+
+