Garage thermostat, working, but how much am I leaving on the table?

Quick background, very new to coding… Help desk and windows server support for 15 years, has helped me little for this! But I am trying.

I put together some parts to make a tstat for my garage furnace.
Uno
5v relays
DHT22
HRC501
W5500 ethernet wired in, not a shield.

The code is built from examples I’ve found, how to’s I’ve done, and guides that I’ve read. I had a solid running thermostat, and I decided to add web; turns out…
My HTTP abilities are non existent, and I feel it shows.
My request is for some tips, tricks, links or directions to go in to better my code in general. Ive briefly read about using ajax/java to do partial updates on the page, and I have read about other options that I really dont have any idea if it would even work. So Im hoping I can get some help building bridges here as I grow.

Some pieces are relics from stages as i went, but i think that most will get the flow
Any help is greatly appreciated!

#include <SPI.h>
#include <Ethernet.h>

#define tempIn 7
#define heatTrigger 6
#define humTrigger 4
#define motionIn 5

#include <DHT.h>

#include <neotimer.h>

DHT dht(tempIn, DHT22);
float setTemp = 65;
float setHum = 40;
float tempVarianceNoMotion = 10;
float tempVarianceMotion = 1;
float humVariance = 1;
bool heatOn = false;
bool humOn = false;
bool ledOn = false;

unsigned long safetyTimeout = 1000;
Neotimer safetyTimer = Neotimer(safetyTimeout);

unsigned long logTimeout = 10000;
Neotimer logTimer = Neotimer(logTimeout);

unsigned long motionTimeout = 600000;
Neotimer motionTimer = Neotimer(motionTimeout);
bool motion = false;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192,168,11,85}; 
byte gateway[] = { 192, 168, 11, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(80);
String readString;
String tempString;
String activeString;
String awayString;

void setup() {
  Ethernet.init(10);
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  Serial.begin(115200);
  dht.begin();
  pinMode(humTrigger, OUTPUT);
  pinMode(heatTrigger, OUTPUT);
  pinMode(motionIn, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  
  // get temp and humidity from DHT22 sensor
  float hum = dht.readHumidity();
  float tempF = (dht.readTemperature() * 1.8) + 32;
  unsigned long motionRemain = (motionTimer.getRemaining());
  

  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (readString.length() < 100) {
          readString += c;
          }
        if (c == '\n') {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Arduino Garage Thermostat</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");
          client.println("<H1>Arduino Garage Thermostat</H1>");
          client.println(String(tempF) + " :Temp
" + String(hum) + " :rH%</p>" + String(setTemp) + " :SetPoint
" + (motion ? String(setTemp-tempVarianceMotion) : String(setTemp-tempVarianceNoMotion)) + " :Adjusted</p>" + "Heat: " + (heatOn ? "On " : "Off")+ "
Humidity: " + (humOn ? "On " : "Off") + "
Away Mode in: ");
          if (!motionTimer.started()){
            if (motion==true){client.println(" MOTION DETECTED</p>");}
            else{
            client.println(" AWAY MODE ACTIVE</p>");}}
          else{
            client.println(String(motionRemain/60000) + " mins </p>");}
          //web input data
          client.println("<FORM ACTION='/' method=get >"); //uses IP/port of web page
          client.println("<INPUT TYPE=TEXT NAME='TEMP' VALUE='' SIZE='4' MAXLENGTH='2'> Temp Setting (50-80)
");
          client.println("<INPUT TYPE=TEXT NAME='ACTIVE' VALUE='' SIZE='4' MAXLENGTH='2'> Active Variance (0-5)
");
          client.println("<INPUT TYPE=TEXT NAME='AWAY' VALUE='' SIZE='4' MAXLENGTH='2'> Away Variance (10-20)
");
          client.println("<INPUT TYPE=SUBMIT NAME='submit' VALUE='Submit'>");
          client.println("</FORM>");
          client.println("
");
          //take submissions and do something with it
          tempString = readString.substring(11,13);
          activeString = readString.substring(21,22);
          awayString = readString.substring(28,30);
          
          if(readString.indexOf("submit") >0){
            if (tempString == "&A"){}
            else{
              if ((tempString.toInt()<50) || (tempString.toInt()>80)){}
              else{setTemp = tempString.toInt();}}
            if(activeString == "A" || activeString == "W" || activeString == "&"){}
            else{
              if ((activeString.toInt()<0) || (activeString.toInt()>5)){}
              else{tempVarianceMotion = activeString.toInt();}}
            if(awayString == "&s" || awayString == "bm" || awayString == "su" || awayString == "ub"){}
            else{
              if ((awayString.toInt() < 10) || (awayString.toInt() > 20)){}
              else{tempVarianceNoMotion = awayString.toInt();}}
            client.println("<meta http-equiv=refresh content=1;URL='http://192.168.11.85/'>");
            client.println("</BODY>");
            client.println("</HTML>");
            delay(1);
            client.stop();
            }
          else{
            client.println("</BODY>");
            client.println("</HTML>");
            delay(1);
            client.stop();
           }
          //clearing string for next read
          readString="";
        }
      }
    }
  }
  
  if (digitalRead(motionIn)) {
    if (!motion) {
      //Serial.println("  motion mode");
    }

    motion = true;
    motionTimer.reset();
  }
  else if(motion) {
    if (motionTimer.done()) {
      motion = false;
      motionTimer.reset();
      //Serial.println("  no motion mode");
    }
    else if (!motionTimer.waiting()) {
      motionTimer.start();
      //Serial.println("  no motion countdown started");
    }
  }

  // if we cant read data properly from the sensor, heat and humidity will default to off
  bool sensorUnplugged = isnan(tempF) || isnan(hum);
  if (sensorUnplugged) {
    heatOn = false;
    humOn = false;
  } else {
    // determine if heat output pin should be switched on or off or stay the same
    if ((!safetyTimer.started() || safetyTimer.done()) && ((motion && tempF <= (setTemp - tempVarianceMotion)) || (!motion && tempF <= (setTemp - tempVarianceNoMotion)))) {
      heatOn = true;
      safetyTimer.reset();
    } else if (tempF >= setTemp) {
      heatOn = false;
      safetyTimer.start();
    }

    // determine if humidity output pin should be switched on or off or stay the same
    if (hum < (setHum - humVariance)) {
      humOn = true;
    } else if (hum > (setHum + humVariance)) {
      humOn = false;
    }
  }

  // set the heat/humidity pin output values
  digitalWrite(heatTrigger, heatOn);
  digitalWrite(humTrigger, humOn);

  // log the temp/humidity and heater status on a timer
  if (logTimer.repeat()) {
    ledOn = !ledOn;
    digitalWrite(LED_BUILTIN, ledOn);
    if (sensorUnplugged) {
      Serial.println("Failed to read data from temperature/humidity sensor");
    } else {
      Serial.print("SetPoint/Adjusted/Temp/rH%: " + String(setTemp) + " " + (motion ? String(setTemp-tempVarianceMotion) : String(setTemp-tempVarianceNoMotion)) + " " + String(tempF) + " " + String(hum) + " Heat: " + (heatOn ? "On " : "Off")+ " Humidity: " + (humOn ? "On " : "Off") + " Motion: ");
      if (digitalRead(motionIn)){
        Serial.println("Yes");}
      else{
        Serial.println("No");}
    }
  }
}

It sounds like You have a good job so faar.
What is the problem? Any code that does the job is good code.

Thank you, no problem, but I feel like the browser is clunky, leaving options for data display and refresh that might make it more powerful or user friendly. I feel decent in the system code, but feel the http side is lacking maybe

Okey. That's very good. I leave the http for the helpers knowing that field. It's not my territory.

Specifically on the Away mode in ... portion, Id like to see that countdown be able to update, without having to update the whole page. Its checking for motion constantly, once motion stops it starts a ten min counter, and can display that info nicely, if i do a refresh at an interval. But the issue was I was sometimes refreshing while trying to enter data, which was annoying and the constant refreshing when left open on a browser or two would cause crashing.

Now I have it set to refresh only after a submission and the data has be dealt with, and also to refresh to the beginning page, docking the string after I capture it.

If ajax my option for that, or is there other methods I can/should research?

I suggest that you do some reading on css (cascading stylesheets) if you want to 'beautify' the looks adding some colours, different fonts etc.

Positioning of elements with css is possible but can be very tricky.