As variáveis declaradas "não existem" porquê são chamadas antes de main?

Não, as variáveis não existem porque elas não foram declaradas neste escopo.

float half(float bill, float tax, int tip)
{
    float tax_decimal = tax_percent / 100.0; // deveria ser "tax" e não "tax_percent"
    ...

No código acima, você estaria tentando tirar um valor de uma variável chamada "tax_percent", mas no escopo ela não existe. O que existe, no entanto, é a variável chamada "tax".

Além disso, como que bill_after_tax (e tax/tip_decimal) sabe que bill terá os valores de bill_amount? Seria por causa do float half(float bill, float tax, int tip)?

Como você está criando a função e nomeando os parâmetros nesta ordem (float bill, float tax, int tip), sempre que você chamar a função, os parâmetros serão gravados nesta ordem. Por exemplo:

float aaa = 50.0;
float bbb = 10.0;
int ccc = 15;

half(aaa, bbb, ccc);

Como mostra o exemplo acima, os valores recebidos pela função independem dos nomes dados as variáveis utilizada nas chamadas.

Espero ter ajudado

Não, as variáveis não existem porque elas não foram declaradas neste escopo.

Agora eu entendi perfeitamente

Espero ter ajudado

Ajudou e muito, muito obrigado.