A functional language (ideally) allows you to write a mathematical function, i.e. a function that takes n arguments and returns a value. If the program is executed, this function is evaluated.
A procedural language, on the other hand, performs a series of sequential steps, where the functional program would be nested. There’s a way of transforming sequential logic into functional logic called continuation passing style.
As a consequence, a purely functional program always yields the same value for an input, and the order of evaluation is not well-defined; which means that uncertain values like user input or random values are hard to model in purely functional languages.