/* This allows each test list to disappear behind the header instead of in front */
section.hero {
    position: relative;
    z-index: 2;
}

/* Centre everything, just to be lazy as it's not possible to align the fake dropdowns next to one another */
form {
    text-align: center;
    position: relative;
}

.strike {
    text-decoration: line-through;
}

/* Correct the damage done to the bulma styles by making the button inline */
.section form label.fake-dropdown-toggle {
    display: inline;
    line-height: 40px;
    padding: 7px 12px;
}

.section form .button {
    display: inline-block;
    margin-top: 5px;
}

/* This is a copy of the Font Awesome styles so we can apply icons with CSS */
.fake-dropdown-toggle:after, .progress-list li:after {
    margin-left: 5px;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    display: inline-block;
    font-style: normal;
    font-variant: normal;
    text-rendering: auto;
    font-family: Font Awesome\ 5 Pro;
    font-weight: normal;
    text-align: right;
}

.fake-dropdown-toggle:after {
    content: '\f078';
    line-height: 40px;
    width: 30px;
    height: 28px;
}

/* All the inputs can be hidden from the user, we just need their state */
input[type="radio"], input[type="checkbox"], .certificate-elements {
    display: none;
}

/* The labels allow the user to select the inputs without showing them. Show them in a list to mimic a dropdown */
.section form label.radio {
    display: list-item;
    margin: 0 auto;
}

/* Lots of styles to allow for a smoother dropdown animation */
label.radio {
    position: relative;
    z-index: -1;
    list-style: none;
    max-height: 0;
    min-height: 0;
    width: 0;
    margin-top: 0;
    padding: 0;
    opacity: 0;
    transition: 0.5s max-height ease-in-out, 0.5s opacity ease-in-out, 0.5s margin-top ease-in-out, 0.5s, 0.5s padding ease-in-out;
}

/* We cover the dropdown once a selection has been made, so add some context */
.intensity.fake-dropdown-toggle ~ input[type="radio"]:checked + label.radio[for^="intensity"]:after {
    content: 'intensity';
    padding-left: 5px;
}

.intensity.fake-dropdown-toggle:focus ~ label.radio[for^="intensity"],
.tester.fake-dropdown-toggle:focus ~ label.radio[for^="tester"] {
    z-index: 1;
    width: auto;
    max-height: 100px;
    opacity: 1;
}

.tester.fake-dropdown-toggle ~ input[type="radio"]:checked + label.radio[for^="tester"]:before {
    content: 'Tester:';
    padding-right: 5px;
}

.control {
    text-align: center;
}

input[type="text"] {
    width: 50vw;
}

/* This covers up the dropdown */
input[type="radio"]:checked + label.radio {
    z-index: 1;
    max-height: 100px;
    opacity: 1;
    background: white;
    margin-top: -38px;
    padding: 8px 0;
    cursor: default;
    min-width: 150px;
}

/* Initial state based conditional classes for the form */
.when-vw-mode, .when-start-test, [for="start-test"].tile.is-1 {
    opacity: 0;
    max-height: 0;
    min-height: 0;
    transition: 0.5s opacity ease-in-out, 0.5s max-height ease-in-out, 0.5s padding ease-in-out, 0.5s margin ease-in-out;
}

/* Probably one of the jankier parts, this is effectively "validation" so the user can start testing
without at least inputing an intensity and tester. If we don't have these most of the remainder of the app won't work */
input[name="intensity"]:not(:checked) ~ input[name="intensity"]:not(:checked) ~ input[name="intensity"]:not(:checked) ~ [for="start-test"],
input[name="tester"]:not(:checked) ~ input[name="tester"]:not(:checked) ~ input[name="tester"]:not(:checked) + input[name="tester"]:not(:checked) ~ [for="start-test"] {
    max-width: 0;
}

/* As Bulma applies margin and padding styles earlier on, we can't just apply these to [for="start-test"] otherwise we
can't reset those styles once validation passes */
#vw-mode ~ .when-vw-mode.enabled,
#vw-mode:checked ~ .when-vw-mode.disabled,
input[name="intensity"]:not(:checked) ~ input[name="intensity"]:not(:checked) ~ input[name="intensity"]:not(:checked) ~ [for="start-test"],
input[name="tester"]:not(:checked) ~ input[name="tester"]:not(:checked) ~ input[name="tester"]:not(:checked) + input[name="tester"]:not(:checked) ~ [for="start-test"] {
    max-height: 0;
    opacity: 0;
    margin: 0;
    padding: 0;
}

/* Actually shows anything using initial conditional classes and the "passes" validation to show the start button */
#vw-mode ~ .when-vw-mode.disabled,
#vw-mode:checked ~ .when-vw-mode.enabled,
input[name="intensity"]:checked ~ input[name="tester"]:checked ~ [for="start-test"] {
    max-height: 100px;
    max-width: 100vw;
    opacity: 1;
}

/* Show state based pages when that state is selected */
#start-test ~ .when-start-test.disabled,
#start-test:checked ~ .when-start-test.enabled,
#start-test:checked ~ #run-tests,
#complete-test:checked ~ #generate-certificate {
    max-height: 100vh;
    opacity: 1;
}

/* Hide everything else when a state is selected and don't show that state when it isn't selected */
#start-test ~ .when-start-test.enabled,
#start-test:checked ~ .when-start-test.disabled,
#start-test ~ #run-tests,
#start-test:checked ~ :not(#run-tests),
#complete-test ~ #generate-certificate,
#complete-test:checked ~ :not(#generate-certificate) {
    max-height: 0;
    opacity: 0;
    margin: 0;
    padding: 0;
}

/* Some entrance animations for states, we also set a counter here that we'll use in the loading bar later */
.page {
    counter-reset: percentageComplete;
    transition: 1s transform ease-in-out, 0.5s opacity ease-in-out, 0.5s max-height ease-in-out;
    overflow: hidden;
    position: relative;
}

#start-test:checked ~ #run-tests {
    transform: translateY(-150px);
}

/* Conditional classes for the tester input */
#tester-invasive ~ .page .when-invasive,
#tester-lenient ~ .page .when-lenient,
#tester-cautious ~ .page .when-cautious,
#tester-nuclear ~ .page .when-nuclear {
    display: none;
}

#tester-invasive:checked ~ .page .when-invasive,
#tester-lenient:checked ~ .page .when-lenient,
#tester-cautious:checked ~ .page .when-cautious,
#tester-nuclear:checked ~ .page .when-nuclear {
    display: initial;
}

.progress-list {
    text-align: left;
    margin: 0 auto;
    width: 40vw;
    position: relative;
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(360deg);
    }
}

/* 
tick: '\f058' #00d1b2
cross: '\f057' hsl(348, 100%, 61%)

Originally we set the final result icon and colour here, but that didn't work with variables (or print styles)
*/
@keyframes loadAndComplete {
    from {
        content: '\f021';
        color: rgb(74, 74, 74);
    }

    to {
        
    }
}

/* Set the speed of testing based on the intensity inputs */
#intensity-low:checked ~ .page {
    --load-speed: 15s;
    --spin-iterations: 15;
}

#intensity-medium:checked ~ .page {
    --load-speed: 10s;
    --spin-iterations: 10;
}

#intensity-high:checked ~ .page {
    --load-speed: 5s;
    --spin-iterations: 5;
}

/* We can generically calculate other variables based for overall timings */
.page {
    --list-load-speed: calc(var(--load-speed) * 4);
    --total-load-speed: calc(var(--list-load-speed) * 3);
}

/* Fill out the page, it looked a little sparse before */
.page .progress-list li {
    padding: 2vh 0;
}

/* Set a generic animation which uses conditional variables 
We don't want to preserve any icon state after "loading" has finished, 
so only fill the first frame of loadAndComplete until it runs */
.page .progress-list li:after {
    float: right;
    animation: 1s linear var(--spin-start) var(--spin-iterations) both spin,
    0s linear var(--spin-end) backwards loadAndComplete;
}

/* Each test must run one after the other.

The --run-start variable allows list items to hold off until that list is being shown to the user */
.page .progress-list li:nth-child(1):after {
    --spin-start: var(--run-start);
    --spin-end: calc(var(--run-start) + var(--load-speed));
}

.page .progress-list li:nth-child(2):after {
    --spin-start: calc(var(--run-start) + var(--load-speed));
    --spin-end: calc((var(--load-speed) * 2) + var(--run-start));
}

.page .progress-list li:nth-child(3):after {
    --spin-start: calc((var(--load-speed) * 2) + var(--run-start));
    --spin-end: calc((var(--load-speed) * 3) + var(--run-start));
}

.page .progress-list li:nth-child(4):after {
    --spin-start: calc((var(--load-speed) * 3) + var(--run-start));
    --spin-end: calc((var(--load-speed) * 4) + var(--run-start));
}

/* Every single list item that should pass, differing depending on which tester is performing the test.

Note VW mode trumps everything and forces the test to pass */
[id^='tester-']:checked ~ #vw-mode:checked ~ .page .progress-list li:after,
#tester-invasive:checked ~ .page .tests:nth-child(odd) .progress-list li:nth-child(1n+1):after,
#tester-invasive:checked ~ .page .tests:nth-child(even) .progress-list li:not(:last-child):after,
#tester-lenient:checked ~ .page .progress-list li:after,
#tester-cautious:checked ~ .page .progress-list li:nth-child(odd):after,
#tester-cautious:checked ~ .page .tests:last-child .progress-list li:nth-child(even):after {
    content: '\f058';
    color: #00d1b2;
}

/* Same as above for test failures. Gives things a slightly less samey feeling */
#tester-invasive:checked ~ .page .tests:nth-child(odd) .progress-list li:nth-child(1):after,
#tester-invasive:checked ~ .page .tests:nth-child(even) .progress-list li:nth-child(4):after,
#tester-cautious:checked ~ .page .progress-list li:nth-child(even):after,
#tester-cautious:checked ~ .page .tests:last-child .progress-list li:nth-child(odd):after,
#tester-nuclear:checked ~ .page .progress-list li:after {
    content: '\f057';
    color: hsl(348, 100%, 61%);
}

@keyframes exit {
    from {
        transform: translateY(0);
        opacity: 1;
    }

    to {
        transform: translateY(-50%);
        opacity: 0;
    }
}

@keyframes entrance {
    from {
        transform: translateY(50%);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

/* Tests are broken up into sets of 4, each set has its own loading percentage using the counter
from earlier and an entrance and exit timed via the --run-start and --run-end variables.

--run-start was also used earlier by the progress lists so there's an odd variable hooking deal 

There was an issue where these animations were conflicting with one another as I'd set bother
animation-fill-mode's to "both" This meant that the first exit keyframe was trumping the first entrance keyframe. 

We now only preseve the final keyframe of the exit animation */
.page .tests {
    width: 100%;
    animation: 0.5s linear var(--run-start) entrance both, 
    0.5s linear var(--run-end) exit forwards;
    height: 50vh;
    counter-increment: percentageComplete 33;
    position: relative;
    z-index: 1;
}

/* Bit of a hack here to display a counter over the loading bar, this also meant .tests elements
had to be set to z-index: 1 to get the layer order right. */
.page .tests:after {
    content: counter(percentageComplete) "%";
    position: absolute;
    bottom: -43px;
    left: -50px;
    right: -50px;
    font-size: 1.5rem;
    color: white;
}

/* Hide everything other than the first test set */
.page .tests:not(:first-child),
.page .complete {
    position: absolute;
    top: 0;
    opacity: 0;
}

/* Queue each test set and the final completion. We use the previously set intensity variables
to allow this to differ based on input */
.page .tests:nth-child(1) {
    --run-start: 0s;
    --run-end: var(--list-load-speed);
}

.page .tests:nth-child(2) {
    --run-start: var(--list-load-speed);
    --run-end: calc(var(--list-load-speed) * 2);
}

.page .tests:nth-child(3) {
    --run-start: calc(var(--list-load-speed) * 2);
    --run-end: calc(var(--list-load-speed) * 3);
}

.page .complete {
    animation: 0.5s linear calc(var(--list-load-speed) * 3) entrance both;
    width: 100%;
    z-index: 2;
}

/* This didn't really need to be that complicated but I thought I'd muck around a bit.

I also purposely tried to make this loading bar one of those really annoying ones that
looks like it's flying along, then sits at the final few percent for ages. I hate those. */
@keyframes loadBar {
    0% {
        width: 0;
        background-color: hsl(348, 100%, 61%);
    }

    10% {
        background-color: hsl(48, 100%, 67%);
    }

    20% {
        background-color: hsl(171, 100%, 41%);
    }

    50% {
        width: 75%;
    }

    100% {
        width: 100%;
        /* There was an odd moment where the animation faded the 
        whole background out because there was no further colour rules set */
        background-color: hsl(171, 100%, 41%);
    }
}

@keyframes fade {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

/* Basic progress bar wrapper with a fade out when all testing is complete */
.page .progress-bar {
    width: 40vw;
    height: 50px;
    margin: 0 auto;
    border-radius: 3em;
    background: #c3c3c3;
    position: relative;
    overflow: hidden;
    animation: 0.5s linear var(--total-load-speed) fade both;
}

/* To compound the already annoying loading bar, I messed about with a custom timing function
that exponentially slows to the end. */
.page .progress-bar:before {
    content: '\00a0';
    display: block;
    height: 100%;
    animation: var(--total-load-speed) cubic-bezier(0.11, 1.01, 0.58, 1) var(--load-speed) loadBar both;
}

.page .progress-bar:after {
    position: absolute;
    top: 0;
}

.page button.button {
    display: inline-flex;
}

/* Controlling all animations to ensure they'll only start playing (or timing)
when the state is shown */
#start-test:not(:checked) ~ .page > * {
    animation-play-state: paused;
}

#start-test:checked ~ .page > * {
    animation-play-state: running;
}

@media print {

    /* I set up the print styles for the "certificate" right at the end of this
    and got a bit lazy. So many of the styles for individual elements were still required so I went
    with the nuclear option and slammed * and "!important" everywhere. Do not try at home. */

    body * {
        opacity: 1 !important;
        transform: none !important;
        position: static !important;
        max-height: 10000px !important;
    }

    /* Hide some specific elements like the header, all inputs, most labels and some states */
    section.hero, label:not(.radio), input:not(:checked) + label.radio, 
    input:not([type="text"]), .complete, button, form > p:not(.when-vw-mode), 
    p.help, .progress-bar, .tests:after, #generate-certificate {
        display: none !important;
    }

    /* Rip out bulmas section padding to allow things to align */
    section {
        padding: 0 !important;
    }

    /* Fake the input into a read-only test */
    input[type="text"] {
        border: none;
        box-shadow: none;
        font-size: 3rem;
        text-align: center;
        margin-top:  8rem;
    }

    /* Had some funny issues getting this state to show again when it was outside the start-test state */
    #start-test ~ #run-tests {
        display: initial !important;
        opacity: 0 !important;
    }

    /* This adds margin as #run-tests is now inline and won't react to margins */
    #run-tests > :first-child {
        margin-top: 6rem !important;
    }

    /* Turn off all animations. This was what caused the bug that ultimately lead to the third generate-certificate state */
    #run-tests * {
        animation: none !important;
    }

    /* Make the test items A4 friendly */
    .page .tests .progress-list li {
        padding: 3px 0;
    }

    /* Had some issues where the loading spinners returned in print mode. Kill any animation state. */
    #run-tests .progress-list li:after {
        animation-fill-mode: none, none;
    }

    /* The only time we need these elements */
    .certificate-elements {
        display: block;
    }

    .certificate-elements * {
        position: absolute !important;
        width: 100%;
    }

    /* Dreaded absolute positioning */
    .certificate-elements .blurb {
        top: 7rem;
    }

    .certificate-elements i {
        font-size: 6rem;
        left: 0;
        top: 0;
    }

    .certificate-elements .status {
        font-size: 2.5rem;
        top: 15rem;
        display: none;
    }

    .passed.status {
        color: hsl(171, 100%, 41%);
    }

    .failed.status {
        color: hsl(348, 100%, 61%);
    }

    /* Determine, based on the tester and therefore the tests that passed and failed, the overall test status.

    Note again the VW mode will trump everything and force a pass. */
    #tester-invasive:checked ~ .certificate-elements .passed.status,
    #tester-lenient:checked ~ .certificate-elements .passed.status,
    #tester-cautious:checked ~ .certificate-elements .failed.status,
    #tester-nuclear:checked ~ .certificate-elements .failed.status,
    [id^='tester']:checked ~ #vw-mode:checked ~ .certificate-elements .passed.status {
        display: block;
    }

    /* We need to hide the failed if VW mode is on */
    #vw-mode:checked ~ .certificate-elements .failed.status {
        display: none;
    }

    .page .tests {
        height: auto;
    }

    .page .progress-list {
        width: 75vw;
    }

    /* Repurpose the chosen inputs as a summary of the test settings */
    input:checked + label.radio {
        position: absolute !important;
        bottom: 25%;
        width: 100%;
    }

    input:checked + label.radio ~ input:checked + label.radio {
        bottom: 20%;
    }

    p.when-vw-mode.enabled {
        position: absolute !important;
        bottom: 15%;
        width: 100%;
    }
}
