Code viewer for World: Clash of Minds AI
// Cloned by Mohamed Afrath Segu Mohamed on 24 Nov 2024 from World "Chat with GPT model" by Starter user 
// Please leave this clone trail here.

// URL for accessing the Hugging Face API for inference
// The URL is used to call the Hugging Face inference API with a specific model
// You can append the model name to this base URL to make predictions using a model, for example: https://api-inference.huggingface.co/models/gpt-3.5-turbo
const openaiURL = 'https://api-inference.huggingface.co/models/'; 

// Default API key and prompt:
var apikey = "";
var theprompt = "hello";

// Boolean flag to track whether the debate has been initiated or not
let debateInitiated = false;

// Set the margin of the body element to 20px on all sides
$('body').css("margin", "20px");
// Set the padding of the body element to 20px on all sides
$('body').css("padding", "20px");
// Set the text alignment of the body content to center
$('body').css("text-align", "center");

// Mohamed Afrath Segu Mohamed & Asmitha Satesh
// Write the HTML content directly to the document using document.write()
document.write(`
 <!-- Header section with the title and a description of the debate -->
<header><div style="width:100%"><strong> Clash of Minds AI </strong><br> 
<i>Engage in a lively debate between two AI models.</i></div>
<div>
<!-- Link to explore a world with an associated image -->
<a href="https://ancientbrain.com/world.php?world=3982138295"><img src="/uploads/afu60/Debate_PNG.png" title="Explore this world!.." style="padding-right:35px" width="50" height="60"></a>
</div>
</header>
<div id=enterkey>
<!-- Section for entering the API key to unlock the debate -->
<pre class="pre-text">
Enter API key: 
The key to unlocking a compelling debate: an "API key".
Register for free and get your API key <a href='https://huggingface.co/settings/tokens'>here</a>.
Enter your API key below and initiate the debate.
</pre>
<div class="api-key">
    <!-- Input field for the user to enter the API key -->
	<input type='password' style='width:50%;margin-right:20px' maxlength='2000' NAME="apikey" id="apikey" VALUE='' > 
	 <!-- Button to set the API key -->
	<button onclick='setkey();' style="margin-top:0px !important" class=ab-normbutton >Set API key</button>
</div>
<p id="keyWarning"></p>
</div>

<div class="debate-div">
 <!-- Section for selecting AI models to participate in the debate -->
<h3> Select AI Models for Debate </h3>
<div class="selector-div">
<div class="select-model">
<label for="ai1Select"><strong>Select Supporter:</strong></label>
 <!-- Dropdown to select the AI model for the supporter -->
<select id="ai1Select">
  <option value="meta-llama/Llama-3.2-3B-Instruct">Llama-3.2-3B-Instruct</option>
  <option value="microsoft/Phi-3.5-mini-instruct">Phi-3.5-mini-instruct</option>
  <option value="tiiuae/falcon-7b-instruct">falcon-7b-instruct</option>
  <option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen2.5-Coder-32B-Instruct</option>
</select>
</div>
<div class="select-model">
<label for="ai2Select"><strong>Select Challenger:</strong></label>
<!-- Dropdown to select the AI model for the challenger -->
<select id="ai2Select" style="width:25vw;">
  <option value="meta-llama/Llama-3.2-3B-Instruct">Llama-3.2-3B-Instruct</option>
  <option value="microsoft/Phi-3.5-mini-instruct">Phi-3.5-mini-instruct</option>
  <option value="tiiuae/falcon-7b-instruct">falcon-7b-instruct</option>
  <option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen2.5-Coder-32B-Instruct</option>
</select>
</div> 
<div class="select-model">
<label for="judgeSelect"><strong>Select Judge:</strong></label>
 <!-- Dropdown to select the AI model for the judge -->
<select id="judgeSelect">
  <option value="meta-llama/Llama-3.2-3B-Instruct">Llama-3.2-3B-Instruct</option>
  <option value="microsoft/Phi-3.5-mini-instruct">Phi-3.5-mini-instruct</option> 
  <option value="tiiuae/falcon-7b-instruct">falcon-7b-instruct</option>
  <option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen2.5-Coder-32B-Instruct</option>
</select>
</div>
</div>
<p id="aiWarning"></p>
<h3> Debate Topic </h3>
<div style="display:flex;justify-content:space-between;align-items:center">
 <!-- Input field for entering the debate topic -->
<input type="text", style='width:95%' id=debateTopic value="Debate topic: What are the key benefits of renewable energy?" >
<!-- Image button to generate a new debate topic using Qwen2.5-Coder-32B-Instruct -->
 <img src= '/uploads/afu60/add1.png' width = '40' onclick="generateDebate()" title="Generate Debate Topic Using Qwen2.5-Coder-32B-Instruct" height='40' style= 'margin-bottom:5px;cursor:pointer'/>
</div>
 <!-- Button to start the debate -->
<button id='initiate-debate' onclick="initiateDebate()" class=ab-normbutton > Start Debate </button> 
</div>

<!-- Divs to display the perspectives of the supporter, challenger, and judge -->
<div style="display: flex; justify-content: center; width: 100%;">
  <div style="width: 40%; background-color:#3498db; border-radius:12px; margin-right:20px; padding: 20px;">
   <img src="/uploads/afu60/bot_blue.jpeg" width='60' height='60' style="mix-blend-mode: darken"/>
    <h3 id="ai1Name">Supporter's Perspective</h3>
    <!-- Placeholder for supporter argument -->
    <pre id=ai1Argument > </pre>
  </div>

  <div style="width: 40%; background-color:#db4747; border-radius:12px;  padding: 20px;">
    <img src="/uploads/afu60/bot_red.jpeg" width='60' height='60' style="mix-blend-mode: darken;filter: grayscale(1);"/>
    <h3 id="ai2Name">Challenger's Counterpoint</h3>
    <!-- Placeholder for challenger's counterpoint -->
    <pre id=ai2Counterpoint > </pre>
  </div>
</div>

<div style="width:60vw; background-color:#e6ffe6; border-radius:12px; margin:20px auto; padding: 20px;">
<h3 id="judgeName">Judge's Decision</h3>
 <!-- Placeholder for judge's decision -->
<pre id=judgeDecision > </pre>
 <!-- Winner's card, hidden initially -->
<div id= "winnercard" style="display:none;justify-content:center">
<div style="display:flex;justify-content:center">
<img src="/uploads/afu60/bot_blue.jpeg" width='60' height='60' style="mix-blend-mode: darken"/>
<p id="blue_winner" style="padding:14px 20px; margin:0; font-weight: bold;font-size: 24px;"><p/>
</div>
<div style="display:flex;justify-content:center">
<img src="/uploads/afu60/bot_red.jpeg" width='60' height='60' style="mix-blend-mode: darken;"/>
<p id="red_winner" style="padding:14px 20px; margin:0 ;font-weight: bold;font-size: 24px;"><p/>
</div>
</div>
</div>
 
<!-- Footer warning about potential inaccuracy of AI responses -->
<p><i> This AI project is for research and educational purposes only, and its outputs should not be considered definitive. <br>
Users are advised to verify results independently, as the developers are not liable for any misuse.</i> </p>

<pre>

</pre>
`);


// This function retrieves the API key entered by the user in the input field, trims any extra spaces, 
// and updates the HTML content of the #enterkey element to indicate that the API key has been successfully set.
function setkey() {
    apikey = jQuery("input#apikey").val();
    apikey = apikey.trim();
    $("#enterkey").html("<b> API key has been set. </b>");
}

// This function validates whether the API key has been set before initiating the debate.
// If the API key is empty, it displays an error message and returns false.
// If the API key is set, it clears any previous warning messages and returns true.
function validateApiKey() {
    if (apikey === "") {
        $("#keyWarning").html("<b>Error: Please set your API key before initiating the debate.</b>");
        return false;
    }
    $("#keyWarning").html("");
    return true;
}

// Mohamed Afrath Segu Mohamed
// This function initiates the debate process by first validating the API key and checking if a debate has already been initiated.
// It clears any previous debate data (arguments, winner text, and judge decision) and ensures that each role (Supporter, Challenger, and Judge) 
// is assigned a unique AI model. If the roles are not unique, an error message is displayed.
// Once the roles are validated, it prepares the debate information (AI models, topic, and judge) and starts the debate by sending the 
// selected AI models and topic to the AI system for generating arguments and counterpoints.
function initiateDebate() {
    if (!validateApiKey()) return;
    if (!debateInitiated) {
        $("#red_winner").text("");
        $("#blue_winner").text("");
        $("#ai1Argument").text("");
        $("#ai2Argument").text("");
        $("#judgeDecision").text("");
        if ($('#red_winner').hasClass('winnerText')) {
            $('#red_winner').removeClass('winnerText');
        }
        if ($('#blue_winner').hasClass('winnerText')) {
            $('#blue_winner').removeClass('winnerText');
        }
        $("#winnercard").css("display", "none");
        let ai1Name = $("#ai1Select option:selected").text();
        let ai2Name = $("#ai2Select option:selected").text();
        $("#ai1Name").text(`${ai1Name} Argument`);
        $("#ai2Name").text(`${ai2Name} Counterpoint`);
        let selectedAI1 = $("#ai1Select").val();
        let selectedAI2 = $("#ai2Select").val();
        let judge = $("#judgeSelect").val();
        $("#judgeName").text(`${$("#judgeSelect option:selected").text()} Decision`);
        let topic = $("#debateTopic").val();

        if (selectedAI1 === selectedAI2 || selectedAI2 == judge || judge == selectedAI1) {
            $("#aiWarning").html("<b>Error: Each role (Supporter, Challenger, and Judge) must be assigned a unique AI model. Please select different models for each role.</b>");
            return;
        } else {
            $("#aiWarning").html("");
        }

        showLoader("#ai1Argument");
        debateInitiated = true;
        $("#initiate-debate").prop("disabled", debateInitiated);
        sendChatAI1(selectedAI1, topic, selectedAI2);
    }
}

// Asmitha Satesh
// Common function for making API requests
function makeRequest(url, data, successCallback, errorCallback, loader, retries = 3, delay = 10000) {
    // Convert data to JSON string
    var dataString = JSON.stringify(data);

    // Set HTTP headers including API key
    $.ajaxSetup({
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + apikey
        }
    });

    // Recursive function to handle retries
    function attemptRequest(attempt) {
        $.ajax({
            type: "POST",
            url: url,
            data: dataString,
            dataType: "json",
            success: function(d, rc) {
                successCallback(d, rc);
            },
            error: function(xhr) {
                if (xhr.responseText && xhr.responseText.includes("is currently loading")) {
                    console.error(`Attempt ${attempt + 1} failed: Model still loading`);
                    if (attempt < retries - 1) {
                        setTimeout(() => attemptRequest(attempt + 1), delay);
                    } else {
                        errorCallback(xhr, "Model still loading");
                    }
                } else {
                    errorCallback(xhr, "Request failed");
                }
            },
            complete: function() {
                hideLoader(loader);
            }
        });
    }

    // Start the first request
    attemptRequest(0);
}

// Mohamed Afrath Segu Mohamed
// Send AI 1 Argument
function sendChatAI1(selectedAI, topic, selectedAI2, retries = 3, delay = 10000) {
    var theprompt = topic;

    // Construct request as JSON
    var thedata = {
        "inputs": `I want to have a debate on the topic: ${theprompt} Please list out two supportive arguments each. Do not include any introduction or additional text—just list the two supportive arguments.`,
        parameters: {
            "temperature": 0.7,
            "return_full_text": false,
            "max_length": 500,
            "top_p": 0.95,
        }
    };

    makeRequest(
        openaiURL + selectedAI,
        thedata,
        function(d, rc) {
            successfnAI1(d, rc, selectedAI2); 
        },
        function(xhr, errorMsg) {
            handleLoadingError(xhr, "#ai1Argument"); 
        },
        '#ai1Argument',
        retries,
        delay
    );
}

// Asmitha Satesh
// This function processes an AI-generated response to extract meaningful arguments or a winner's justification.
// It splits the response into lines, filters out irrelevant or prompt-related content, and joins the filtered lines into a cleaned result.
// If the `isJudge` parameter is true, it attempts to identify and return a winner sentence from the filtered content.
function extractArguments(response, isJudge = false) {
    // Split the response into lines
    const sentencePattern = /[.!?]$/;
    let lines = response.replace(/\"/g, '').split("\n");
    if (!lines.includes("\n")) {
        lines = response.split(/(?<=\.|\?|!)(?=\s)/);
    }
    // Remove lines containing the prompt
    console.log(lines);
    let filteredLines = lines.filter(line =>
        !line.startsWith("I want to have a debate") && sentencePattern.test(line) && line.trim().length > 2 &&
        !line.trim().startsWith("Please list out") && !line.trim().startsWith("Each argument should be one or two") &&
        !line.startsWith("Provide exactly two strong counterpoints") && !line.trim().startsWith("Focus solely on logical, ethical, or practical concerns") &&
        !line.trim().startsWith("Do not include any introduction or additional text—just") && !line.startsWith("Based on the following debate, determine the winner") &&
        !line.startsWith("Provide only one thought-provoking") && !line.trim().startsWith("The response should be only one debate question not more than")
    );
    console.log(filteredLines)
    filteredLines = filteredLines.join("\n").trim();
    if (!isJudge) {
        // Join the remaining lines
        console.log(filteredLines)
        return filteredLines;
    } else {
        console.log(response)
        let parts = filteredLines.split("The winner of the debate");
        // Check if there is a second occurrence
        if (parts.length > 0) {
            // Return the second winner sentence by combining "The winner of the debate" with the rest of the sentence
            return parts.length > 1 ? "The winner of the debate " + parts[1].trim() : "The winner of the debate " + parts[0].trim();
        }
        return "Winner sentence not found";
    }

}

// Mohamed Afrath Segu Mohamed
// Creates a typewriter effect by gradually displaying the characters of a given text inside a specified HTML element.
// Each character is appended one at a time at a specified speed, and an optional callback is triggered after completion.
function typeWriter(text, elementId, speed, callback) {
    let i = 0;
    const outputElement = $(elementId);

    // Function that adds each character with a delay
    function typing() {
        if (i < text.length) {
            outputElement.append(text.charAt(i));
            i++;
            setTimeout(typing, speed);
        } else {
            if (callback) callback();
        }
    }

    typing();
}

// Mohamed Afrath Segu Mohamed
// Handles the response from the AI for the first argument in a debate.
// It extracts the generated arguments, displays them using a typewriter effect, and then sends the argument to the second AI for counterpoints. 
// Additionally, it manages the display of loading indicators during the process.
function successfnAI1(data, rc, selectedAI2) {
    let arguments = extractArguments(data[0]["generated_text"]);
    var answer = arguments;

    // Pass a callback function to typeWriter
    typeWriter(answer, '#ai1Argument', 10, function() {
        // Callback after typing is finished: Now send to the next AI
        sendChatAI2(selectedAI2, $("#ai1Argument").text());
        hideLoader('#ai1Argument');
    });

    showLoader("#ai2Counterpoint");
}

// Asmitha Satesh
// Send AI 2 Counterpoint
function sendChatAI2(selectedAI, ai1Response, retries = 3, delay = 10000) {
    var thedata = {
        "inputs": `Provide exactly two strong counterpoints against the topic '${$("#debateTopic").val()}'. Focus solely on logical, ethical, or practical concerns. Do not include any introduction or additional text—just list the two counterpoints.`,
        parameters: {
            "temperature": 0.7,
            "return_full_text": false,
            "max_length": 500,
            "top_p": 0.95,
        }
    };
    // then as string representing that JSON:
    makeRequest(
        openaiURL + selectedAI,
        thedata,
        function(d, rc) {
            successfnAI2(d, rc, selectedAI);
        },
        function(xhr, errorMsg) {
            handleLoadingError(xhr, "#ai2Argument");
        },
        '#ai2Counterpoint',
        retries,
        delay
    );
}

// Asmitha Satesh
// Handles the response from the AI for the counter argument in a debate.
// It extracts the generated arguments, displays them using a typewriter effect, and then sends the argument to the Judge for decision. 
// Additionally, it manages the display of loading indicators during the process.
function successfnAI2(data, rc) {
    let arguments = extractArguments(data[0]["generated_text"]);
    var answer = arguments;

    // Pass a callback function to typeWriter
    typeWriter(answer, '#ai2Counterpoint', 10, function() {
        // Callback after typing is finished: Now send to the next AI
        hideLoader('#ai2Counterpoint');
        showLoader("#judgeDecision");
        sendJudgeDecision($("#judgeSelect").val());
    });
}


// Asmitha Satesh
// Send Judge Decision
function sendJudgeDecision(selectedAI, retries = 3, delay = 10000) {
    // construct request as JSON
    let ai1Argument = $("#ai1Argument").text();
    let ai2Counterpoint = $("#ai2Counterpoint").text();
    let judgementPrompt = `Act as a debate judge. Determine the one winner of this debate (${$("#ai1Select option:selected").text()} or ${$("#ai2Select option:selected").text()}) and provide a one-line justification with no additional context: 
    ${$("#ai1Select option:selected").text()}: ${ai1Argument} 
    ${$("#ai2Select option:selected").text()}: ${ai2Counterpoint}. Start the response with 'The winner of the debate is'`;

    var thedata = {
        "inputs": judgementPrompt,
        parameters: {
            "return_full_text": false,
            "temperature": 0.7,
            "max_length": 1000,
            "top_p": 0.95,
        }
    };

    // then as string representing that JSON:
    var thedatastring = JSON.stringify(thedata);

    // POST to 3rd party URL: 
    makeRequest(
        openaiURL + selectedAI,
        thedata,
        function(d, rc) {
            successfnJudge(d, rc); 
        },
        function(xhr, errorMsg) {
            handleLoadingError(xhr, "#ai2Argument");
        },
        '#judgeDecision',
        retries,
        delay
    );
}

// Asmitha Satesh
// Handles the response from the AI for the final decision of the debate.
// It extracts the generated arguments, displays them using a typewriter effect, and then returns the winner. 
function successfnJudge(data, rc) {
    let arguments = extractArguments(data[0]["generated_text"], true);

    var answer = arguments;

    // Pass a callback function to typeWriter
    typeWriter(answer, '#judgeDecision', 10, function() {
        // Callback after typing is finished: Now send to the next AI
        hideLoader('#judgeDecision');
        debateInitiated = false;
        $("#winnercard").css("display", "flex");
        if (answer.includes(`The winner of the debate is ${$("#ai1Select option:selected").text()}`)) {
            $("#blue_winner").text("Winner");
            $("#blue_winner").addClass("winnerText");
            $("#red_winner").text("Runner");
        }
        if (answer.includes(`The winner of the debate is ${$("#ai2Select option:selected").text()}`)) {
            $("#red_winner").text("Winner");
            $("#red_winner").addClass("winnerText");
            $("#blue_winner").text("Runner");
        }
        $("#initiate-debate").prop("disabled", false);
    });
}

// Mohamed Afrath Segu Mohamed
// Sends a request to an AI API to generate a single debate question unrelated to a specified topic. 
// The function constructs the request payload, handles the response or errors, and includes retry logic with a delay.
function generateDebate(retries = 3, delay = 10000) {
    if (!validateApiKey()) return;
    var thedata = {
        "inputs": `Provide only one thought-provoking debate question that is not related to "${$("#debateTopic").val()}. The response should be only one debate question not more than that.`,
        parameters: {
            "temperature": 0.7,
            "max_length": 1000,
            "top_p": 0.95,
        }
    };
    // then as string representing that JSON:
    var thedatastring = JSON.stringify(thedata);
    // POST to 3rd party URL: 
    makeRequest(
        openaiURL + 'Qwen/Qwen2.5-Coder-32B-Instruct',
        thedata,
        function(d, rc) {
            successfnDebate(d, rc);
        },
        function(xhr, errorMsg) {
            handleLoadingError(xhr, "#ai2Argument");
        },
        '#judgeDecision',
        retries,
        delay
    );
}

// Mohamed Afrath Segu Mohamed
// Processes the response from the AI to extract and format a debate question. 
// It extracts the generated text, identifies and isolates the debate question using a regular expression, and updates the value of the `#debateTopic` input field.
function successfnDebate(data, rc) {
    let arguments = extractArguments(data[0]["generated_text"]);
    var answer = arguments;
    const extractQuestion = (answer) => {
        const questions = answer.match(/Debate Question: (.+?)(?=\n|$)/g);
        return questions ? questions[0] : answer;
    };
    answer = extractQuestion(answer);
    $("#debateTopic").val(answer);
}

// Asmitha Satesh
// Handles errors related to the loading process when making requests to the AI model. 
// If the error indicates that the model is still loading, it displays the estimated wait time. Otherwise, it displays a generic error message.
function handleLoadingError(xhr, targetElement) {
    if (xhr.responseJSON && xhr.responseJSON.error && xhr.responseJSON.error.includes("currently loading")) {
        var estimatedTime = xhr.responseJSON.estimated_time;
        $(targetElement).html(`<font color=red><b> The model is currently loading. Please wait approximately ${estimatedTime.toFixed(1)} seconds and try again. </b></font>`);
    }else if(xhr.responseJSON && xhr.responseJSON.error && xhr.responseJSON.error.includes("the token seems invalid")){
            $("#enterkey").html("<b style='color:red'> Please reload and try again with a valid token!. </b>");
    }else {
        $(targetElement).html("<font color=red><b> Unknown error. </b></font>");
    }
}

// Display error Message
function errorfn() {
    if (apikey == "") $("#ai2Counterpoint").html("<font color=red><b> Enter API key to be able to debate. </b></font>");
    else $("#ai2Counterpoint").html("<font color=red><b> Unknown error. </b></font>");
}

// Mohamed Afrath Segu Mohamed
// Shows Loader
function showLoader(targetElement) {
    $(targetElement).html('<div class="loader"></div>');
}

// Hides Loader
function hideLoader(targetElement) {
    $(targetElement).find('.loader').remove();
}

// Mohamed Afrath Segu Mohamed & Asmitha Satesh
// Adding CSS for the Webpage
$('<style>').prop('type', 'text/css').html(`
  .loader {
    border: 8px solid #f3f3f3;
    border-top: 8px solid #3498db;
    border-radius: 50%;
    width: 40px;
    height: 40px;
    animation: spin 2s linear infinite;
    margin: 20px auto;
  }
  
  /* General body styling for clean, modern look */
/* General body styling for a clean, modern, realistic look */
body {
    font-family: 'Roboto', sans-serif;
    background-image: url('uploads/afu60/1905.i211.003_tribunedebatecomposition.jpg'); /* Replace with the actual path to your image */
    background-size: cover; /* Ensures the entire image covers the screen */
    background-repeat: no-repeat; /* Prevents the image from repeating */
    background-position: center; /* Centers the image */
    background-attachment: fixed; /* Keeps the background image fixed during scrolling */
    color: #333;
    margin: 0;
    margin-top:80px !important;
    padding: 0;
    text-align: center;
    line-height: 1.6;
    overflow-x: hidden;
}
header{
  display:flex;
  justify-content:space-between;
  align-items: center;
  position: fixed;
  font-family : sans-serif;
  top: 0;
  left: 0;
  width: 100%;
  background-color: #013561; /* Choose your preferred background color */
  color: white;
  font-size : 25px;
  padding: 10px 20px; /* Adjust padding as needed */
  text-align: center;
  z-index: 1000; /* Ensures the header stays on top of other content */
}
/* Header for main title styling */
h1 {
    color: #ffffff;
    font-size: 3em;
    margin: 20px 0;
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
}

/* Link styling for World link */
a {
    color: #00bfff;
    text-decoration: none;
    font-weight: bold;
}
a:hover {
    text-decoration: underline;
}

/* Input and button styling for a modern, realistic UI */
input[type="text"], input[type="password"] {
    width: 100%;
    padding: 12px;
    margin: 10px 0;
    border: 1px solid #ccc;
    border-radius: 5px;
    background-color: rgba(255, 255, 255, 0.9);
    font-size: 20px !important;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.winnerText {
    padding-top : 0 !important;
    text-align: center;
    opacity: 0; /* Start with the text hidden */
    transform: translateY(20px); /* Start slightly below */
    animation: winnerAnimation 3s ease-out infinite; /* Apply animation */
}

/* Define the animation */
@keyframes winnerAnimation {
    0% {
        opacity: 0;
        transform: translateY(20px);
    }
    50% {
        opacity: 1;
        transform: translateY(-10px);
    }
    100% {
        opacity: 1;
        transform: translateY(0);
    }
}

.selector-div{
    display:flex;
    flex-flow: wrap;
    flex-direction: row;
    justify-content: space-evenly;
}

button {
    background-color: #007bff;
    color: white;
    border: none;
    padding: 12px 25px;
    text-align: center;
    text-decoration: none;
    font-size: 1em;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s ease;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
button:hover {
    background-color: #0056b3;
}

/* Warning messages */
#aiWarning,#keyWarning {
    width:100%;
    text-align: center;
    color: red;
    font-weight: bold;
    padding: 10px;
    border-radius: 5px;
    display: inline-block;
    margin-bottom: 20px;
}

.api-key{
display: flex;
justify-content: center;
align-items:center;
}

/* Container for debate initiation and model selection */
#enterkey, div[style*="background-color:white"] {
    width: 64%;
    background-color: rgba(255, 255, 255, 0.95);
    border: 1px solid #ddd;
    margin: 30px auto;
    padding: 30px;
    border-radius: 12px;
    box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
    text-align: left;
}

/* Styling for AI arguments and counterpoints containers */
#ai1Argument, #ai2Counterpoint,#judgeDecision {
    background-color: rgba(255, 255, 255, 0.95);
    border: 1px solid #013561;
    padding: 20px;
    border-radius: 12px;
    margin-top: 20px;
    white-space: pre-line;
    text-align: justify;
    font-size: 1.1em;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}

/* Distinct styling for counterpoints container */
#ai2Counterpoint {
    border-color: #d9534f;
}

/* Judge decision box styling */
#judgeDecision {
    border-color: #228b22;
}

/* Flexbox styling for debate layout */
#debateWrapper {
    display: flex;
    justify-content: space-between;
    width: 90%;
    max-width: 1200px;
    gap: 30px;
    margin: 30px auto;
}

/* Loader animation for async actions */
.loader {
    border: 8px solid #f3f3f3;
    border-top: 8px solid #3498db;
    border-radius: 50%;
    width: 50px;
    height: 50px;
    animation: spin 2s linear infinite;
    margin: 20px auto;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Style for headers inside containers */
h3 {
    color: #333;
    font-size: 1.8em;
    margin-top: 0 !important;
    margin-bottom: 15px;
    text-align: center;
}

/* Improved button styling for judge initiation */
button.ab-normbutton {
    background-color: #4caf50;
    border: none;
    color: white;
    padding: 12px 25px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 1em;
    margin-top: 20px;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s ease;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
button.ab-normbutton:hover {
    background-color: #388e3c;
}

.pre-text{
    text-align:center;
    font-size:20px;
}

.select-model{
    display: flex;
    flex-direction: column;
}

.debate-div {
    width: 65%;
    background-color: white;
    border: 1px solid #ddd;
    border-radius:12px;
    margin: 20px auto;
    padding: 20px;
    display: flex;
    justify-content: center;
    flex-direction: column;
    background-color: rgba(255, 255, 255, 0.95);
}

/* Styling AI model selection dropdowns */
select {
    width: 25vw;
    max-width: 300px;
    padding: 12px;
    margin: 10px 0;
    border: 1px solid #ccc;
    border-radius: 5px;
    background-color: rgba(255, 255, 255, 0.9);
    font-size: 1em;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

/* Footer warning styling */
p i {
    font-size: 0.9em;
    color: #ffffff;
    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
}


  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
`).appendTo('head');