/* ============================================================================
   NUSdirect login - 2026 refresh
   ----------------------------------------------------------------------------
   Values below are resolved from the approved deck's own XML
   (New NUSdirect Login Page.pptx), including the luminance modifiers that
   PowerPoint layers on top of a theme colour - those are where the greys come
   from, and reading only the scheme slot gets them wrong:

     left panel   bg1 lumMod 95%              -> #F2F2F2
     card         bg1                          -> #FFFFFF
     card border  bg1 lumMod 75%               -> #BFBFBF
     input border tx2 lumMod 25% lumOff 75%    -> #A6CAEC   (from #0E2841)
     input glow   #00B0F0 @ 40%, 5pt blur
     links        #0070C0
     footer text  no explicit colour, i.e. tx1 -> #000000, centred
     strapline    #0C112F @ 70% OPAQUE (PowerPoint's "Transparency 30%"),
                  white text, 20pt, CENTRED

   Geometry, as proportions of the deck rather than slide points:
     panels       two equal halves meeting at the centre line
     card         42.5% of the panel width; corner radius 2.59% of card width
     inputs       80% of the card width (achieved here via the card's 10%
                  horizontal padding), aspect 8:1
     strapline    76.5% of the image panel, vertically centred

   Prefixed .nl-* so nothing collides with the older .nus-form-login /
   .nav-login-btn rules still in Site.css.
   ============================================================================ */

:root {
    --nl-ink:           #0E2841;
    --nl-ink-soft:      #55657A;
    --nl-footer-ink:    #404040;   /* deck specifies tx1 (black); softened - see footer note */
    --nl-link:          #0070C0;
    --nl-link-hover:    #005596;
    --nl-panel:         #F2F2F2;
    --nl-card:          #FFFFFF;
    --nl-card-border:   #BFBFBF;
    --nl-input-border:  #A6CAEC;
    --nl-glow:          rgba(0, 176, 240, .40);
    --nl-overlay:       rgba(12, 17, 47, .70);
    --nl-danger:        #A3342A;
    --nl-warn-bg:       #FDF6E3;
    --nl-warn-border:   #D9A93C;
    --nl-warn-ink:      #7A5410;
    --nl-input-h:       46px;
    --nl-font:          "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto,
                        "Helvetica Neue", Arial, sans-serif;
}

/* ---------------------------------------------------------------- the shell */

body.nl-body {
    margin: 0;
    min-height: 100vh;
    background: var(--nl-panel);
    font-family: var(--nl-font);
    color: var(--nl-ink);
    -webkit-font-smoothing: antialiased;
}

.nl-shell {
    display: flex;
    min-height: 100vh;
    align-items: stretch;
}

.nl-panel-form {
    flex: 1 1 50%;
    background: var(--nl-panel);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    padding: 40px 24px 24px;
    box-sizing: border-box;
}

/* The deck crops the source image to its left half (srcRect r="50000");
   login-bg.jpg is pre-cropped to match, so cover/centre is faithful. */
.nl-panel-image {
    flex: 1 1 50%;
    position: relative;
    background-color: #0A0F24;
    background-repeat: no-repeat;
    background-size: cover;
    background-position: center center;
    display: flex;
    align-items: center;
    justify-content: center;
}

.nl-strapline {
    width: 76.5%;
    background: var(--nl-overlay);
    color: #FFFFFF;
    padding: 56px 44px;
    box-sizing: border-box;
    font-size: 2.15rem;
    line-height: 1.38;
    font-weight: 400;
    text-align: center;
    text-wrap: balance;
    margin: 0;
}

/* ------------------------------------------------------------------ the card */

.nl-form-area {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
}

/* Heading, fields, button and links all sit inside this box, as in the deck. */
/* NB the horizontal padding is in px, not %. Percentage padding on a flex item
   resolves against the CONTAINING BLOCK, not the element, so a 10% value here
   was measured off the panel and left the input at 46% of the card instead of
   the deck's 80%. 46px against the 460px max width reproduces that 80%. */
.nl-card {
    width: clamp(320px, 42.5%, 460px);
    box-sizing: border-box;
    background: var(--nl-card);
    border: 1px solid var(--nl-card-border);
    border-radius: 12px;            /* deck: 2.59% of card width */
    padding: 34px 46px 30px;
}

.nl-heading {
    margin: 0 0 34px;
    text-align: center;
    font-size: 1.6rem;
    font-weight: 600;               /* deck: Segoe UI Semibold */
    letter-spacing: -0.01em;
    color: var(--nl-ink);
}

.nl-field { margin-bottom: 18px; }

/* Explanatory copy - used on the account-reactivation step (LoginStep3), which
   the deck does not cover. Kept quiet so it informs without competing with the
   fields. */
.nl-note {
    margin: 0 0 20px;
    font-size: .875rem;
    line-height: 1.45;
    color: var(--nl-ink-soft);
}

.nl-note:last-of-type { margin-bottom: 14px; }

/* A wider card for the two-factor pages, which carry step-by-step instructions
   rather than just fields. The old versions were a fixed 600px; this keeps the
   same shape as the sign-in card but gives the copy room. */
/* Overrides width, not max-width: the base card sets width via clamp(), and a
   max-width can only cap that value, never widen it. */
.nl-card-wide { width: clamp(320px, 52%, 560px); }

/* Numbered instructions on the two-factor pages. */
.nl-steps {
    margin: 0 0 18px;
    padding-left: 20px;
    font-size: .9rem;
    line-height: 1.5;
    color: var(--nl-ink-soft);
}

.nl-steps > li { margin-bottom: 14px; }
.nl-steps > li:last-child { margin-bottom: 0; }

/* Six single-character boxes for the authenticator code. The .otp-input class
   is retained because the page's script selects on it to auto-advance focus and
   to join the digits into the hidden Input_Code field before submitting. */
.nl-otp {
    display: flex;
    gap: 10px;
    justify-content: center;
    margin: 16px 0 20px;
}

.nl-otp input {
    width: 46px;
    height: 54px;
    padding: 0;
    box-sizing: border-box;
    text-align: center;
    font-family: inherit;
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--nl-ink);
    background: #FFFFFF;
    border: 1px solid var(--nl-input-border);
    border-radius: 8px;
    box-shadow: 0 0 11px var(--nl-glow);
    transition: box-shadow .15s ease, border-color .15s ease;
}

.nl-otp input:focus {
    outline: none;
    border-color: #00B0F0;
    box-shadow: 0 0 0 3px var(--nl-glow), 0 0 14px var(--nl-glow);
}

@media (max-width: 420px) {
    .nl-otp { gap: 6px; }
    .nl-otp input { width: 38px; height: 46px; font-size: 1.1rem; }
}

/* ------------------------------------------------- 2FA enrolment extras */

/* QR code container. The qrcode.js library injects a canvas/img into #qrCode,
   so this only needs to frame and centre whatever it produces. */
.nl-qr {
    display: flex;
    justify-content: center;
    margin: 16px 0;
    padding: 18px;
    background: #FFFFFF;
    border: 1px solid var(--nl-input-border);
    border-radius: 8px;
}

.nl-qr canvas,
.nl-qr img { display: block; }

/* The manual-entry key shown beside the QR code. */
.nl-key {
    display: inline-block;
    padding: 3px 8px;
    background: #EEF4FA;
    border: 1px solid var(--nl-input-border);
    border-radius: 4px;
    font-family: "Segoe UI Mono", Consolas, "Courier New", monospace;
    font-size: .9375rem;
    color: var(--nl-ink);
    word-break: break-all;
}

/* Standing warning on the recovery-codes page - these codes are the only way
   back in if the device is lost, so it should carry weight. */
.nl-warn {
    margin: 0 0 20px;
    padding: 14px 16px;
    background: var(--nl-warn-bg);
    border: 1px solid var(--nl-warn-border);
    border-left-width: 3px;
    border-radius: 4px;
}

.nl-warn strong {
    display: block;
    margin-bottom: 4px;
    color: var(--nl-warn-ink);
}

.nl-warn p {
    margin: 0;
    font-size: .875rem;
    line-height: 1.45;
    color: var(--nl-ink-soft);
}

/* The recovery codes themselves, two to a row as before. */
.nl-codes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px 14px;
    margin: 0 0 22px;
}

.nl-codes code {
    padding: 7px 10px;
    background: #F7FAFD;
    border: 1px solid var(--nl-input-border);
    border-radius: 4px;
    font-family: "Segoe UI Mono", Consolas, "Courier New", monospace;
    font-size: .9375rem;
    color: var(--nl-ink);
    text-align: center;
}

@media (max-width: 420px) {
    .nl-codes { grid-template-columns: 1fr; }
}

.nl-label {
    display: block;
    margin-bottom: 6px;
    font-size: .9375rem;
    color: var(--nl-ink-soft);
}

/* The cyan glow is the design's signature, so it is present at rest and
   strengthened on focus rather than appearing only on focus. */
.nl-input {
    display: block;
    width: 100%;
    height: var(--nl-input-h);
    padding: 0 14px;
    box-sizing: border-box;
    font-family: inherit;
    font-size: 1rem;
    color: var(--nl-ink);
    background: #FFFFFF;
    border: 1px solid var(--nl-input-border);
    border-radius: 8px;             /* deck: default roundRect adj, ~16.7% of height */
    box-shadow: 0 0 11px var(--nl-glow);
    transition: box-shadow .15s ease, border-color .15s ease;
}

.nl-input:focus {
    outline: none;
    border-color: #00B0F0;
    box-shadow: 0 0 0 3px var(--nl-glow), 0 0 14px var(--nl-glow);
}

.nl-input[readonly] {
    color: var(--nl-ink-soft);
    background: #F7FAFD;
    box-shadow: none;
}

.nl-btn {
    display: block;
    width: 100%;
    height: var(--nl-input-h);
    margin-top: 4px;
    border: 1px solid var(--nl-link);
    border-radius: 8px;
    background: var(--nl-link);
    color: #FFFFFF;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}

.nl-btn:hover,
.nl-btn:focus {
    background: var(--nl-link-hover);
    border-color: var(--nl-link-hover);
}

.nl-btn:focus-visible {
    outline: 3px solid var(--nl-glow);
    outline-offset: 2px;
}

.nl-links {
    margin-top: 26px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.nl-links a {
    color: var(--nl-link);
    font-size: .875rem;
    text-decoration: none;
}

.nl-links a:hover,
.nl-links a:focus { text-decoration: underline; }

/* --------------------------------------- validation summary + caps-lock note */

/* _ValidationSummary.cshtml is shared with other pages, so it is restyled from
   here rather than edited. It emits
       .validation-summary-errors.col-12 > ul.list-group > li.list-group-item
   plus a hidden #capsLock <li> the capslockstate handler reveals. Placing that
   partial between the field and the button puts both the errors and the
   caps-lock notice where they belong, without a second element of that id. */
.nl-errors { margin: 0; }

.nl-errors .validation-summary-errors { padding: 0; max-width: 100%; }

.nl-errors .list-group { margin: 0; padding: 0; list-style: none; }

.nl-errors .list-group-item,
.nl-errors .list-group-item-danger {
    display: block;
    margin: 10px 0 0;
    padding: 0;
    border: 0;
    background: none;
    font-size: .875rem;
    line-height: 1.4;
    color: var(--nl-danger);
}

.nl-errors .list-group-item .fa { padding-right: 6px !important; }
.nl-errors #capsLock { color: var(--nl-ink-soft); }
.nl-errors #capsLock img { height: 14px; vertical-align: -2px; margin-right: 6px; }

/* ------------------------------------------------------- footer, in-panel */

/* The deck puts the footer inside the left panel, centred below the card, in
   the default text colour - not the blue, full-width fixed bar used elsewhere.
   _Footer.cshtml is shared with _HeaderClient and System/Offline so it is not
   modified; its positioning and inline link colours are overridden here only,
   inside the login shell. The !important is unavoidable: the partial sets
   style="color: #215F9A" inline on every link and separator. */
.nl-footer-slot {
    width: 100%;
    flex: 0 0 auto;
}

.nl-footer-slot .footer,
.nl-footer-slot .footer.fixed-bottom {
    position: static;
    background: none;
}

.nl-footer-slot .footer .container-fluid {
    background: none !important;
    height: auto !important;
}

/* The deck inherits tx1 for this text - confirmed pure black through both
   presentation.xml defaultTextStyle and the master's otherStyle. Rendered in a
   browser at regular weight that reads harder than the deck does, because
   _Footer.cshtml sets font-weight:500 inline and heavier reads darker. Weight is
   dropped back to the deck's regular and the black softened slightly, which
   matches what the deck looks like rather than what it literally specifies. */
.nl-footer-slot .footer a,
.nl-footer-slot .footer span {
    color: var(--nl-footer-ink) !important;
}

.nl-footer-slot .footer ul,
.nl-footer-slot .footer div {
    font-weight: 400 !important;
}

.nl-footer-slot .footer a:hover,
.nl-footer-slot .footer a:focus {
    text-decoration: underline;
}

/* ------------------------------------------------------------- responsive */

/* Below this width the image panel is dropped and the card takes the screen.
   This also gives the ForgotPassword / LoginHelp pop-ups (opened at 610px)
   a clean single-column treatment automatically. */
@media (max-width: 900px) {
    .nl-panel-image { display: none; }

    .nl-panel-form {
        flex: 1 1 100%;
        padding: 32px 20px 20px;
    }

    .nl-card {
        width: 100%;
        max-width: 460px;
        padding: 30px 28px 26px;
    }
}

@media (max-width: 420px) {
    .nl-card { min-width: 0; padding: 26px 20px 22px; }
    .nl-heading { font-size: 1.35rem; margin-bottom: 26px; }
}

@media (max-height: 620px) {
    .nl-panel-form { padding-top: 20px; }
    .nl-heading { margin-bottom: 24px; }
}

@media (prefers-reduced-motion: reduce) {
    .nl-input, .nl-btn { transition: none; }
}

/* Password-policy checklist on the forced-change page. The .changepasswordPopOverItem_*
   classes are toggled by nus.account.changepassword.js and coloured in Site.css, so
   only spacing is set here. */
.nl-policy {
    margin: 18px 0 0;
    font-size: .875rem;
    line-height: 1.5;
}

.nl-policy p { margin: 0 0 4px; }
