% europasscv2025.cls
% An unofficial LaTeX class for the Europass CV (2025 "classic" template)
%
% Copyright 2025 Lorenzo Calisti
%
% This work may be distributed and/or modified under the conditions of
% the LaTeX Project Public License, either version 1.3 of this license
% or (at your option) any later version.
% The latest version of this license is in
%   https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Lorenzo Calisti.
%
% COMPATIBILITY:
%   This class works with pdfLaTeX, XeLaTeX, and LuaLaTeX.
%   The engine is auto-detected; no changes needed.

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{europasscv2025}[2026-05-20 Europass CV class (2025 classic template)]

% ============================================================
% EARLY PACKAGES (safe before LoadClass)
% ============================================================
\RequirePackage{iftex}
\RequirePackage{etoolbox}

% ============================================================
% CLASS OPTIONS
% ============================================================

% Debug mode
\newif\ifecv@debug\ecv@debugfalse
\DeclareOption{debug}{\ecv@debugtrue}

% Europass logo
\newif\ifecv@nologo\ecv@nologofalse
\DeclareOption{nologo}{\ecv@nologotrue}

% Page number on the footer
\newif\ifecv@nototpages\ecv@nototpagesfalse
\DeclareOption{nototpages}{\ecv@nototpagestrue}

% Language
\newcommand{\ecv@lang}{english}% Default to english
\DeclareOption{english}{\renewcommand{\ecv@lang}{english}}
\DeclareOption{italian}{\renewcommand{\ecv@lang}{italian}}

% Color schemes
\newcommand{\ecv@colorscheme}{default}% Default color scheme
\DeclareOption{color-default}{\renewcommand{\ecv@colorscheme}{default}}
\DeclareOption{color-darkblue}{\renewcommand{\ecv@colorscheme}{darkblue}}
\DeclareOption{color-blue}{\renewcommand{\ecv@colorscheme}{blue}}
\DeclareOption{color-darkgreen}{\renewcommand{\ecv@colorscheme}{darkgreen}}
\DeclareOption{color-green}{\renewcommand{\ecv@colorscheme}{green}}
\DeclareOption{color-darkviolet}{\renewcommand{\ecv@colorscheme}{darkviolet}}
\DeclareOption{color-violet}{\renewcommand{\ecv@colorscheme}{violet}}

% Pass remaining options to the base class
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions\relax

\LoadClass[a4paper]{article}

% ============================================================
% PACKAGES (loaded after LoadClass so dimensions are set)
% ============================================================
\RequirePackage{xcolor}
\RequirePackage{graphicx}
\RequirePackage{geometry}
\RequirePackage{fancyhdr}
\RequirePackage{lastpage}
\RequirePackage{tikz}
\RequirePackage{ragged2e}
\RequirePackage{array}
\RequirePackage{tabularx}
\RequirePackage{booktabs}
\RequirePackage{colortbl}
\RequirePackage{longtable}
\RequirePackage[expansion=false]{microtype}
\RequirePackage{pgfkeys}
\RequirePackage[normalem]{ulem}
\RequirePackage{tcolorbox}
\RequirePackage{xparse}
\ifecv@debug \RequirePackage{showframe} \fi

% hyperref needs to be the last loaded package
\RequirePackage{hyperref}

\hypersetup{
  colorlinks=true,
  allcolors=ecv@color@link
}

% ============================================================
% FONT SETUP (Engine-aware)
% ============================================================
% Detect the TeX engine and set up fonts accordingly
\ifPDFTeX
    \RequirePackage[T1]{fontenc}
    \RequirePackage[utf8]{inputenc}
    \RequirePackage{helvet}
    \renewcommand{\familydefault}{\sfdefault}
\else
    % XeLaTex and LuaLaTex
    \RequirePackage{fontspec}
    \setmainfont{Helvetica}
    \setsansfont{Helvetica}
    \renewcommand{\familydefault}{\sfdefault}
\fi

% ============================================================
% LOAD LANGUAGE LABELS
% ============================================================
\InputIfFileExists{locale/ecv_\ecv@lang.def}{}{%
    \PackageWarning{europasscv2025}{Language file 'ecv_\ecv@lang.def' not found, falling back to english}%
    \input{locale/ecv_english.def}%
}

% ============================================================
% PAGE GEOMETRY
% ============================================================
\newlength{\ecv@margin@top}
\newlength{\ecv@margin@bottom}
\newlength{\ecv@margin@left}
\newlength{\ecv@margin@right}

\setlength{\ecv@margin@top}{10mm}
\setlength{\ecv@margin@bottom}{10mm}
\setlength{\ecv@margin@left}{14mm}
\setlength{\ecv@margin@right}{14mm}

\geometry{
  paper=a4paper,
  left=\ecv@margin@left,
  right=\ecv@margin@right,
  top=\ecv@margin@top,
  bottom=\ecv@margin@bottom,
  includefoot=true
}

% ============================================================
% LOAD COLORS SCHEMES
% ============================================================
\InputIfFileExists{colors/ecv_\ecv@colorscheme.def}{}{%
    \PackageWarning{europasscv2025}{Color file 'ecv_\ecv@color.def' not found, falling back to default}%
    \input{colors/ecv_default.def}%
}

% Setter for all colors
\newcommand{\ecvaccentcolor}[1]{\definecolor{ecv@color@accent}{HTML}{#1}}
\newcommand{\ecvtextcolor}[1]{\definecolor{ecv@color@text}{HTML}{#1}}
\newcommand{\ecvbordercolor}[1]{\definecolor{ecv@color@border}{HTML}{#1}}
\newcommand{\ecvtitlecolor}[1]{\definecolor{ecv@color@title}{HTML}{#1}}
\newcommand{\ecvinfocolor}[1]{\definecolor{ecv@color@info}{HTML}{#1}}
\newcommand{\ecvinfolinkcolor}[1]{\definecolor{ecv@color@infolink}{HTML}{#1}}
\newcommand{\ecvsectioncolor}[1]{\definecolor{ecv@color@section}{HTML}{#1}}
\newcommand{\ecvhighlightcolor}[1]{\definecolor{ecv@color@highlight}{HTML}{#1}}
\newcommand{\ecvlinkcolor}[1]{\definecolor{ecv@color@link}{HTML}{#1}}
\newcommand{\ecvtableitemcolor}[1]{\definecolor{ecv@color@tableitem}{HTML}{#1}}
\newcommand{\ecvtablesepcolor}[1]{\definecolor{ecv@color@tablesep}{HTML}{#1}}

% ============================================================
% PAGE STYLE (footer with logo + page number)
% ============================================================
\fancypagestyle{ecv@footer}{%
    \fancyhf{}%
    \renewcommand{\headrulewidth}{0pt}%
    \fancyfoot[R]{%
        \ifecv@nologo\else%
            % Europass logo
            \raisebox{-0.20\height}{%
                \includegraphics[height=4mm]{europass_logo.pdf}%
            }%
            \hspace{0.5em}%
            \fi%
        \ifecv@nototpages\else%
            {%
                \color{ecv@color@text}%
                Page~\thepage/\pageref*{LastPage}%
            }
            \normalcolor
        \fi%
    }%
}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0pt}
\renewcommand{\normalcolor}{\color{ecv@color@text}}
\AtBeginDocument{\pagestyle{ecv@footer}}

% ============================================================
% HELPER FUNCTIONS
% ============================================================
% Adds a ' | ' text separator that can be broken to a new line
\newcommand{\ecv@sep}{%
    \allowbreak\space\textbar\space\allowbreak%
}

% Adds an url with underline
\newcommand{\ecv@url}[2][ecv@color@link]{%
    \begingroup%
        \hypersetup{allcolors=#1}%
        \href{#2}{\uline{#2}}%
    \endgroup%
}

% ============================================================
% USER PHOTO
% ============================================================
\newlength{\ecv@photosize}
\setlength{\ecv@photosize}{3.5cm} 

\newif\ifecv@photo\ecv@photofalse
\newcommand{\ecv@photo}{}
\newcommand{\ecvphoto}[1]{\ecv@phototrue\renewcommand{\ecv@photo}{#1}}

% ============================================================
% PERSONAL INFO
% ============================================================
\newcommand{\ecv@info@name}{}
\newcommand{\ecv@info@dob}{}
\newcommand{\ecv@info@gender}{}
\newcommand{\ecv@info@nationalitylist}{}
\newcommand{\ecv@info@addresslist}{}
\newcommand{\ecv@info@phonelist}{}
\newcommand{\ecv@info@emaillist}{}
\newcommand{\ecv@info@websitelist}{}
\newcommand{\ecv@info@sociallist}{}
\newcommand{\ecv@info@imlist}{}

\newcommand{\ecvname}[1]{\renewcommand{\ecv@info@name}{#1}}%
\newcommand{\ecvdateofbirth}[1]{\renewcommand{\ecv@info@dob}{#1}}%
\newcommand{\ecvgender}[1]{\renewcommand{\ecv@info@gender}{#1}}%
\newcommand{\ecvnationality}[1]{%
    \ifdefempty{\ecv@info@nationalitylist}{%
        \renewcommand{\ecv@info@nationalitylist}{#1}%
    }{%
        \gappto{\ecv@info@nationalitylist}{,\ #1}%
    }%
}%
\newcommand{\ecvaddress}[2][\ecv@label@home]{%
    \ifdefempty{\ecv@info@addresslist}{%
        \renewcommand{\ecv@info@addresslist}{#2\ (#1)}%
    }{%
        \gappto{\ecv@info@addresslist}{,\ #2\ (#1)}%
    }%
}%
\newcommand{\ecvphone}[2][\ecv@label@mobile]{%
    \ifdefempty{\ecv@info@phonelist}{%
        \renewcommand{\ecv@info@phonelist}{#2\ (#1)}%
    }{%
        \gappto{\ecv@info@phonelist}{,\ #2\ (#1)}%
    }%
}%
\newcommand{\ecvemail}[1]{%
    \ifdefempty{\ecv@info@emaillist}{%
        \renewcommand{\ecv@info@emaillist}{\ecv@url[ecv@color@infolink]{#1}}%
    }{%
        \gappto{\ecv@info@emaillist}{,\ \ecv@url[ecv@color@infolink]{#1}}%
    }%
}%
\newcommand{\ecvwebsite}[1]{%
    \ifdefempty{\ecv@info@websitelist}{%
        \renewcommand{\ecv@info@websitelist}{\ecv@url[ecv@color@infolink]{#1}}%
    }{%
        \gappto{\ecv@info@websitelist}{,\ \ecv@url[ecv@color@infolink]{#1}}%
    }%
}%
\newcommand{\ecvsocial}[2]{%
    \ifdefempty{\ecv@info@sociallist}{%
        \renewcommand{\ecv@info@sociallist}{#1:~\ecv@url[ecv@color@infolink]{#2}}%
    }{%
        \gappto{\ecv@info@sociallist}{\ #1:~\ecv@url[ecv@color@infolink]{#2}}%
    }%
}%
\newcommand{\ecvim}[2]{%
    \ifdefempty{\ecv@info@imlist}{%
        \renewcommand{\ecv@info@imlist}{#1:~#2}%
    }{%
        \gappto{\ecv@info@imlist}{\ #1:~#2}%
    }%
}%

% ------------------------------------------------------------
% List with personal info
% ------------------------------------------------------------
\newcommand{\ecv@personalinfolist}{}
\newcommand{\ecv@personalinfolist@append}[1]{%
    \ifdefempty{\ecv@personalinfolist}{%
        \renewcommand{\ecv@personalinfolist}{#1}%
    }{%
        \gappto{\ecv@personalinfolist}{\ecv@sep#1}%
    }%
}
\newcommand{\ecv@makepersonalinfolist}{%
    % Create list of personal info displayed in the header
    %
    % Date of birth
    \ifdefempty{\ecv@info@dob}{}{%
        \ecv@personalinfolist@append{\ecv@label@dob:~\ecv@info@dob}%
    }%
    % Gender
    \ifdefempty{\ecv@info@gender}{}{%
        \ecv@personalinfolist@append{\ecv@label@gender:~\ecv@info@gender}%
    }%
    % Nationalities
    \ifdefempty{\ecv@info@nationalitylist}{}{%
        \ecv@personalinfolist@append{\ecv@label@nationality:~\ecv@info@nationalitylist}%
    }%
    % Phone numbers
    \ifdefempty{\ecv@info@phonelist}{}{%
        \ecv@personalinfolist@append{\ecv@label@phone:~\ecv@info@phonelist}%
    }%
    % Email address
    \ifdefempty{\ecv@info@emaillist}{}{%
        \ecv@personalinfolist@append{\ecv@label@email:~\ecv@info@emaillist}%
    }%
    % Personal Websites
    \ifdefempty{\ecv@info@websitelist}{}{%
        \ecv@personalinfolist@append{\ecv@label@website:~\ecv@info@websitelist}%
    }%
    % Social media
    \ifdefempty{\ecv@info@sociallist}{}{%
        \ecv@personalinfolist@append{\ecv@info@sociallist}%
    }%
    % Address
    \ifdefempty{\ecv@info@addresslist}{}{%
        \ecv@personalinfolist@append{\ecv@label@address:~\ecv@info@addresslist}%
    }%
}

% ------------------------------------------------------------
% Personal info content widget
% -----------------------------------------------------------
\newcommand{\ecv@personalinfo@content}{%
    % Name
    \ifdefempty{\ecv@info@name}{}{%
        {%
            \color{ecv@color@title}%
            \LARGE\textbf{\ecv@info@name}\par\vspace{8pt}%
        }\normalcolor%
    }%
    {%
        \color{ecv@color@info}%
        \ecv@personalinfolist%
    }\normalcolor%
}

% ------------------------------------------------------------
% User photo widget
% ------------------------------------------------------------
\newcommand{\ecv@photo@content}{%
    \begin{tikzpicture}%
        \clip (0,0) circle (0.5\ecv@photosize);%
        \node [anchor=center] at (0,0) {%
            \includegraphics[%
                width=\ecv@photosize,%
                height=\ecv@photosize,%
                keepaspectratio=false%
            ]{\ecv@photo}%
        };%
        \draw[%
            color=ecv@color@accent,%
            line width=1pt%
        ] (0,0) circle (\dimexpr0.5\ecv@photosize-1pt);%
        \draw[%
            color=ecv@color@border,%
            line width=2pt%
        ] (0,0) circle (0.5\ecv@photosize);%
    \end{tikzpicture}%
}

% ------------------------------------------------------------
% Header content widget
% ------------------------------------------------------------
\newsavebox{\ecv@headerbox}%
\newlength{\ecv@header@height}%
\newlength{\ecv@header@contentwidth}%
\newlength{\ecv@header@contentheight}%
\newlength{\ecv@header@textheight}%

\newcommand{\ecv@header@content}{%
    % -----------------------------------------------------
    % Compute content width
    % -----------------------------------------------------
    \setlength{\ecv@header@contentwidth}{%
        \dimexpr\paperwidth-\ecv@margin@left-\ecv@margin@right\relax%
    }%
    \ifecv@photo%
        \addtolength{\ecv@header@contentwidth}{-\ecv@photosize}%
        \addtolength{\ecv@header@contentwidth}{-0.8cm}% Space between photo and info
    \fi%
    % -----------------------------------------------------
    % Measure text content height
    % -----------------------------------------------------
    \savebox{\ecv@headerbox}{%
        \parbox[t]{\ecv@header@contentwidth}{%
            \RaggedRight%
            \ecv@personalinfo@content%
        }%
    }%
    \setlength{\ecv@header@contentheight}{%
        \dimexpr\ht\ecv@headerbox+\dp\ecv@headerbox\relax%
    }%
    % -----------------------------------------------------
    % Header height
    % -----------------------------------------------------
    \ifecv@photo%
        % Photo and personal info
        \setlength{\ecv@header@height}{%
            \dimexpr%
            1cm%top padding
            +\ecv@photosize%
            +0.5cm%bottom padding
            \relax%
        }%
        % Personal info + its paddings
        \setlength{\ecv@header@textheight}{%
            \dimexpr%
            1.5cm%
            +\ecv@header@contentheight%
            +0.5cm%
            \relax%
        }%
        % Take the maximum between photo + paddings and info + padding
        \ifdim\ecv@header@textheight>\ecv@header@height%
            \setlength{\ecv@header@height}{\ecv@header@textheight}%
        \fi%
    \else%
        % No photo, only personal info
        \setlength{\ecv@header@height}{%
            \dimexpr%
            1.5cm% top text padding
            + \ecv@header@contentheight%
            + 0.5cm% bottom padding
            \relax%
        }%
    \fi%
    % -----------------------------------------------------
    % Reserve vertical space
    % -----------------------------------------------------
    \noindent\vspace*{%
        \dimexpr%
            \ecv@header@height% header
            -\ecv@margin@top% top margin
            -\baselineskip% text baseline
        \relax%
    }%
    % -----------------------------------------------------
    % Draw header
    % -----------------------------------------------------
    \begin{tikzpicture}[remember picture, overlay, baseline=0pt]%
        \useasboundingbox (0,0);%
        % -------------------------------------------------
        % Background
        % -------------------------------------------------
        \fill[ecv@color@accent]%
            ([yshift=-\ecv@header@height] current page.north west)%
            rectangle%
            (current page.north east);%
        % -------------------------------------------------
        % Photo
        % -------------------------------------------------
        \ifecv@photo%
            \node[anchor=north west] 
            at (%
                [xshift=\ecv@margin@left,%
                yshift=-\ecv@margin@top]%
                current page.north west%
            ) {\ecv@photo@content};%
        \fi%
        % -------------------------------------------------
        % Text content
        % -------------------------------------------------
        \node[%
            anchor=north west,%
            inner sep=0pt,%
            outer sep=0pt,%
        ]%
        at ([xshift=\dimexpr%
            \ecv@margin@left%
            + \ifecv@photo%
                \ecv@photosize+0.8cm%Photo + spacing
            \else%
                +0pt%
            \fi%
            \relax,%
            yshift=-15mm]%
            current page.north west%
        )%
        {%
            \begin{minipage}{\ecv@header@contentwidth}%
                \RaggedRight%
                \ecv@personalinfo@content%
            \end{minipage}%
        };%
    \end{tikzpicture}%
    \ignorespaces%
}

\newenvironment{ecvinfo}{%
    % Reset environment variables
    \renewcommand{\ecv@info@name}{}
    \renewcommand{\ecv@info@dob}{}
    \renewcommand{\ecv@info@gender}{}
    \renewcommand{\ecv@info@nationalitylist}{}
    \renewcommand{\ecv@info@addresslist}{}
    \renewcommand{\ecv@info@phonelist}{}
    \renewcommand{\ecv@info@emaillist}{}
    \renewcommand{\ecv@info@websitelist}{}
    \renewcommand{\ecv@info@sociallist}{}
}{%
    % Make list with personal info
    \ecv@makepersonalinfolist%
    % Display header
    \ecv@header@content%
}

% ============================================================
% SECTIONS
% ============================================================
% \ecvsection{title}
% Bold small label + full-width rule below
\newcommand{\ecvsection}[1]{%
    \par\vspace{12pt}%
    \noindent{%
        {%
            \color{ecv@color@section}%
            \footnotesize\textbf{#1}%
            \hspace{4pt}%
            \leaders\hbox{%
                \raisebox{0.5ex}{\rule{1pt}{0.5pt}}%
            }\hfill\kern0pt%
        }%
    }\par%
    \normalcolor%
    \ignorespaces%
}

% ============================================================
% SECTION ENTRY
% ============================================================
\pgfkeys{
    /ecv/entry/.is family,
    /ecv/entry/.cd,
    title/.store in=\ecv@entry@title,
    organization/.store in=\ecv@entry@org,
    date/.store in=\ecv@entry@date,
    location/.store in=\ecv@entry@location,
    description/.store in=\ecv@entry@desc,
    link/.store in=\ecv@entry@link
}
\NewDocumentCommand{\ecventry}{s m}{%
    % Reset values
    \pgfkeys{/ecv/entry/.cd,
        title={},
        organization={},
        date={},
        location={},
        description={},
        link={}
    }%

    % Parse input
    \pgfkeys{/ecv/entry/.cd,#2}%

    \vspace{8pt}
    \noindent
    {%
        \color{ecv@color@highlight}
        \textbf{\ecv@entry@title}%
        \ifdefempty{\ecv@entry@org}{}{\ecv@sep\ecv@entry@org}%
        \IfBooleanTF{#1}{%
            \ifdefempty{\ecv@entry@date}{}{\ecv@sep\ecv@entry@date}%
            \ifdefempty{\ecv@entry@location}{}{\ecv@sep\ecv@entry@location}%
        }{%
            \normalcolor%
            \ifdefempty{\ecv@entry@date}{}{\footnotesize\ecv@sep\ecv@entry@date}%
            \ifdefempty{\ecv@entry@location}{}{\footnotesize\ecv@sep\ecv@entry@location}%
        }%
        \normalcolor%
    }\par%
    \ifdefempty{\ecv@entry@desc}{}{%
        \vspace{4pt}
        {\IfBooleanTF{#1}{\footnotesize}{}\ecv@entry@desc}\par%
    }%
    \ifdefempty{\ecv@entry@link}{}{%
        \vspace{6pt}%
        \ecv@url{\ecv@entry@link}\par%
    }%
    \ignorespaces%
}

% ============================================================
% LANGUAGE SKILLS TABLE
% ============================================================
% Internal storage for language lists
\newcommand{\ecv@mtlist}{}
\newcommand{\ecv@langrows}{}
\newif\ifecv@cefrlevels\ecv@cefrlevelsfalse
\newcommand{\ecvcefrlevels}{\ecv@cefrlevelstrue}

% Set row length and spacing
\renewcommand{\arraystretch}{2}
\newlength{\ecv@langrowsep}
\setlength{\ecv@langrowsep}{\dimexpr((\baselineskip * \arraystretch) - 2mm)}

\newcommand{\ecvmothertongue}[1]{%
    \ifdefempty{\ecv@mtlist}{%
        \renewcommand{\ecv@mtlist}{#1}%
    }{%
        \gappto{\ecv@mtlist}{\ecv@sep#1}%
    }%
}

\newcommand{\ecv@languagerow}[6]{%
    \rowcolor{ecv@color@accent}%
    \textcolor{ecv@color@tableitem}{\textbf{#1}} &%
    \textcolor{ecv@color@tableitem}{#2} &%
    \textcolor{ecv@color@tableitem}{#3} &%
    \textcolor{ecv@color@tableitem}{#4} &%
    \textcolor{ecv@color@tableitem}{#5} &%
    \textcolor{ecv@color@tableitem}{#6} \\%
}

\newcommand{\ecvlanguage}[6]{%
    \ifdefempty{\ecv@langrows}{%
        \renewcommand{\ecv@langrows}{\ecv@languagerow{#1}{#2}{#3}{#4}{#5}{#6}}%
    }{%
        \gappto{\ecv@langrows}{%
            & & & & & \\[-\ecv@langrowsep]%
            \ecv@languagerow{#1}{#2}{#3}{#4}{#5}{#6}%
        }%
    }%
}

\newenvironment{ecvlanguages}{%
    % Reset language lists
    \renewcommand{\ecv@mtlist}{}%
    \renewcommand{\ecv@langrows}{}%
}{%
    % ==== Mother Tongues ====
    \par\vspace{6pt}
    {%
        \color{ecv@color@highlight}%
        \small\ecv@label@mothertongue: \textbf{\ecv@mtlist}%
    }\normalcolor%
    \par\vspace{6pt}

    % ==== Other languages ====
    \arrayrulecolor{ecv@color@tablesep}%
    \begin{tabularx}{\linewidth}{%
        >{\raggedright\arraybackslash}p{3cm}%  Language name
        |%
        >{\centering\arraybackslash}X%    Understanding - Listening
        >{\centering\arraybackslash}X%    Understanding - Reading
        |%
        >{\centering\arraybackslash}X%    Speaking - Prod.
        >{\centering\arraybackslash}X%    Speaking - Int.
        |%
        >{\centering\arraybackslash}p{3cm}%    Writing
        }%
        % ==== HEADER ====
        & \multicolumn{2}{c|}{\textbf{\ecv@label@understanding}} & \multicolumn{2}{c|}{\textbf{\ecv@label@speaking}} & \textbf{\ecv@label@writing} \\
        & \footnotesize{\ecv@label@listening} & \footnotesize{\ecv@label@reading} & \footnotesize{\ecv@label@spokenproduction} & \footnotesize{\ecv@label@spokeninteraction} & \\
        
        % ==== ROWS ====
        \ecv@langrows%
    \end{tabularx}\par%
    % ==== Language proficency lavel
    \ifecv@cefrlevels
        \vspace{16pt}
        \footnotesize\textit{\ecv@label@cefrlevels}
    \fi
}

% ============================================================
% PERSONAL SKILLS
% ============================================================
% Internal storage for skills
\newcommand{\ecv@skillstitle}{}
\newcommand{\ecv@skillslist}{}

\newcommand{\ecvskill}[1]{%
    \ifdefempty{\ecv@skillslist}{%
        \renewcommand{\ecv@skillslist}{#1}%
    }{%
        \gappto{\ecv@skillslist}{\ecv@sep#1}%
    }%
}

\newenvironment{ecvskills}[1][]{%
    \renewcommand{\ecv@skillslist}{}%
    \renewcommand{\ecv@skillstitle}{#1}%
    }{%
    \vspace{8pt}%
    \noindent%
    \ifdefempty{\ecv@skillstitle}{}{%
        \textbf{\ecv@skillstitle}%
        \color{ecv@color@highlight}%
        \ecv@sep%
    }%
    {%
        \color{ecv@color@highlight}%
        \ecv@skillslist%
    }\normalcolor%
    \par%
}

% ============================================================
% DRIVING LICENCES
% ============================================================
% Internal storage for licences
\newcommand{\ecv@licenceslist}{}

\newcommand{\ecv@drivinglicenceitem}[1]{%
    \vspace{8pt}%
    \noindent%
    \textbf{\ecv@label@drivinglicence~#1}%
    \par%
}

\newcommand{\ecvdrivinglicence}[1]{%
    \ifdefempty{\ecv@licenceslist}{%
        \renewcommand{\ecv@licenceslist}{\ecv@drivinglicenceitem{#1}}%
    }{%
        \gappto{\ecv@licenceslist}{\ecv@drivinglicenceitem{#1}}%
    }%
}

\newenvironment{ecvdrivinglicences}[1][]{%
    \renewcommand{\ecv@licenceslist}{}%
}{%
    {%
        \color{ecv@color@highlight}%
        \ecv@licenceslist%
    }\normalcolor%
}