Calculate angle based on time of day not working

I have some code (relevant portions below) that I feel should work, but it doesn’t. It starts at 60 deg (I’m controlling a servo angle) at morning time and rotates slowly as time passes. It should be 120 deg at sunset but instead it’s capping out at like 104 deg and earlier in the day than it should.

Any help is appreciated! Thanks!

#include <avr/io.h>
#include <avr/interrupt.h>
#include "uart.h"

static volatile uint64_t milliseconds = 0;

int hour = 0;
int minute = 0;

int morning = 6;
int morning_min = 27;

int evening = 20;
int evening_min = 50;

void delay_ms(int ms)
{
	uint64_t timestamp = milliseconds;
	while(milliseconds - timestamp < ms);
}

int main(void)
{
	initUART();
	
	int now = (hour * 60) + minute;
	int morn = (morning * 60) + morning_min;
	int even = (evening * 60) + evening_min;
	
	//setup if mid day
	if (now >= morn && now <= even)
	{
		int denomenator = even - morn;
		double numerator = now - morn;
		
		double ratio = numerator / denomenator;
		
		int angle = (ratio * 60) + 60;
		
		OCR1A = angle;
	}
	else
	{
		OCR1A = 60;
	}
	
	char start[18] = {0};
	sprintf(start, "Startup-%02d:%02d-%d\n", hour, minute, OCR1A);
	writeString(start);
	
	DDRB |= (1 << PORTB1); //servo pin 6
	
	//timer 0
	OCR0A = 249; //1ms interval
	TIMSK0 |= (1 << OCIE0A); //enable oputput compare interrupt
	TCCR0A |= (1 << WGM01); //ctc
	TCCR0B |= (1 << CS01) | (1 << CS00); //prescaler 64
	
	//timer 1
	TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10); // clear on match, fast pwm 
	TCCR1B |= (0 << WGM13) | (1 << WGM12) | (1 << CS12) | (0 << CS10); //1024 prescaler 
	
	sei(); //enable interrupts globally
	
    while(1)
    {
		if((milliseconds % 10) == 0) {
			minute++;
			
			if(minute % 60 == 0)
			{
				minute = 0;
				hour++;
			}
			
			if(hour % 24 == 0) { hour = 0; }
			
			int now = (hour * 60) + minute;
			if(now >= morn && now <= even)
			{
				int denomenator = even - morn;
				double numerator = now - morn;
				
				double ratio = numerator / denomenator;
				
				int angle = (ratio * 60) + 60;
				
				OCR1A = angle;
			}
			
			char message[10] = {0};
			sprintf(message, "%02d:%02d-%d\n", hour, minute, OCR1A);
			writeString(message);
		}
    }
}

ISR(TIMER0_COMPA_vect)
{
	milliseconds++;
}

I guess this is for testing and in real life it would be milliseconds % 60000:

    while(1)
    {
		if((milliseconds % 10) == 0) {
			minute++;
			
			if(minute % 60 == 0)

Correct, in practice it would be mod 60000, but for testing i did mod 10 to speed it up so i could see a whole 24 hour period in much less time

I think the problem is that you are not properly converting angles to servo pulse lengths. Servo pulses run from 1000 microseconds (0°) to 2000 microseconds (180°). You can't just use the angle value directly. The code doesn't have comments to show what the Timer1 clock rate is.