﻿html {
    position: fixed;
    font-size: 16px;
    font-family: 'Roboto', Arial, sans-serif;
    height: 100dvh;
    width: 100dvw;
    overflow-x: hidden;
    overflow-y: hidden;
    margin: 0px;
    padding: 0px;
}

/*
   All three layers of the backdrop live here, on ONE element, so they paint
   in the same frame.

   The vignette used to be a background on .radial_background - a div inside
   Home.razor - while the colour wash was here. With prerender:false that div
   does not exist until the circuit connects, so the wash painted from the
   static HTML immediately and the vignette dropped on top of it a moment
   later. Two paints, visibly.

   Layer order is first-on-top: vignette over the blue and violet washes,
   over the base colour.
*/
body {
    position: fixed;
    background: radial-gradient(circle at center, rgba(0, 0, 0, 0) 66%, rgba(0, 0, 0, 0.12) 80%, rgba(0, 0, 0, 1)), radial-gradient(circle at 20% 20%, #1e40af 0%, transparent 45%), radial-gradient(circle at 80% 80%, #7c3aed 0%, transparent 45%), #050816;
    height: 100dvh;
    width: 100dvw;
    overflow-x: hidden;
    overflow-y: hidden;
    margin: 0px;
    padding: 0px;
}

/*
   .btn-link is Bootstrap's, and nothing in this project applies it yet. It
   is listed here so a link-styled button matches a real link the day one is
   written, which is the same bet the validation rules at the bottom make.
*/
a, a:link, .btn-link {
    color: white;
    text-decoration: underline;
    text-decoration-color: rgba(255,204,102,0.5);
    text-decoration-thickness: 2px;
    text-shadow: 0px 0px 2px rgba(0,0,0,0.7);
    transition: all 0.2s ease;
}

    a:hover, .btn-link:hover {
        cursor: pointer;
        text-decoration-color: rgba(255,204,102,1);
    }

ul {
    list-style-position: inside;
}

/*
   Drawer menus - the launcher's and the minimized-group ones - sit above
   the drawer scrim, which is itself above the window popup layer (1000).
   Bootstrap's own .dropdown-menu z-index is 1000, which would leave a menu
   blurred underneath the very scrim it raised.

   Global rather than in either component's stylesheet: the class is applied
   by two different components, and CSS isolation would scope a rule in
   either of them to that component's own markup only.
*/
.window_drawer_menu {
    z-index: 1600;
}

/*
   Global for the same reason .window_drawer_menu is: the class is worn by
   both the launcher's dropdown and the minimized-group ones, and a rule in
   either component's stylesheet would be scoped to that component's own
   markup and miss the other.
*/
.menu {
    /*
       The menu's lift, in three layers, held in a variable so a variant can
       ADD to it rather than restate it - .window_group_menu does exactly
       that, and before this it silently replaced the lot.

       1. a large soft drop, which is what puts the menu above the page
       2. a tight ambient ring, so the edge does not dissolve into a dark
          backdrop - the drawer scrim blurs everything behind an open menu
       3. an inset 1px catch light along the top, the glass edge
    */
    --menu-shadow: 0 40px 120px rgba(0,0,0,0.55), 0 0 8px 4px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.12);
    position: absolute;
    border-radius: 10px;
    border: 1px solid rgba(0,0,0,.25);
    background-color: rgba(64,64,64,0.5);
    box-shadow: var(--menu-shadow);
    margin: 0px;
    padding: 0px;
    overflow: hidden;
}

/*
   These three layers sat on a .menu::before for a while and painted NOTHING,
   which is worth writing down because putting them back there is the obvious
   thing to try. The pseudo-element was `content: ""` and nothing else - a
   zero-size inline box - so its shadow had no box to cast from. Neither of
   the two ways of finishing it works:

   - Give it `position: absolute; inset: 0` and the OUTER layers vanish. An
     element's own box-shadow is not clipped by its own overflow, but a
     DESCENDANT's is, and .menu is overflow: hidden - which it has to be, or
     a hovered first or last item squares off the 10px corner. So layers 1
     and 2 can only ever live on .menu itself.

   - The inset layer would survive that, but it then scrolls. .window_group_menu
     is overflow-y: auto with a max-height, and an absolutely positioned child
     of a scroll container is anchored to the scroll origin, not the border
     box. Measured in the browser: the overlay sat 0.8px below the menu top at
     scrollTop 0 and -79.2px at scrollTop 80, i.e. it slid straight out of the
     frame it was meant to be part of. An inset shadow on .menu does not move,
     because a background does not scroll with content.

   The one thing an overlay would have bought is painting the catch light
   OVER the first child rather than under it, and that is not worth the two
   problems above: in the launcher the first child is a separator band at 10%
   white, so the highlight reads through it almost unchanged, and in the group
   menu the 6px padding means nothing reaches the top edge at all.
*/

/*
   A window's notice band - something the reader needs to know that is NOT
   about a field, rendered above the content rather than as a
   ValidationMessage. Two windows use it for what their OPENER had to say
   (RegisterConfirm, ResendCodeComplete); Logout uses it for a message it
   writes itself.

   THAT THIRD CASE IS FORCED RATHER THAN CHOSEN, and it is the sharpest reason
   this class exists. Logout is a Section form with no fields, and Section
   derives its Submit button's disabled state from whether the message store
   holds anything - a store refilled only by a validation pass, which is raised
   only by a field change or another submit. With no fields there is no field
   change, so a failure written as a ValidationMessage would disable the only
   button on the window forever. A plain element cannot do that.

   Global for the same reason .menu and .window_drawer_menu are: three separate
   components wear it, and CSS isolation would scope a rule in any one of their
   stylesheets to that component's own markup and miss the others. It WAS a
   copy in two of them - byte-for-byte identical, and named
   .register_confirm_notice in both, so the resend window's stylesheet was named
   after the register window and changing one colour meant editing two files.

   Warning-coloured rather than error-coloured on purpose: nothing has gone
   wrong that the reader did, and whatever the message is about is still
   recoverable by trying again - ask for the code again, press Logout again.
   That is a different message from "that failed, give up".
*/
.window_notice {
    margin-bottom: 12px;
    padding: 10px 12px;
    /* The amber the drawer and the focus rings already use, so this reads as
       part of the same interface rather than as a browser default. */
    border: 1px solid rgba(255, 204, 102, 0.55);
    border-radius: 6px;
    background-color: rgba(255, 204, 102, 0.12);
    color: inherit;
    font-weight: 600;
}

/*
   The class names below are BLAZOR'S, not ours - no markup in this project
   writes any of them, and none should. `modified`, `valid` and
   `invalid` are applied to an input by the EditContext's field CSS class
   provider, and `validation-message` is what the ValidationMessage and
   ValidationSummary components render. So they are styled here for the same
   reason the default Blazor template styles them: they turn up the moment a
   form does.

   Forms exist now - Login, Register, RegisterConfirm and ResendCode all
   render one - so these DO match, which they did not when the note here said
   otherwise. Still do not write any of them by hand: the EditContext and the
   ValidationMessage component are the only things that should apply them.
*/
.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid indianred;
}

.validation-message {
    color: indianred;
}
