/* ==========================================================================
   login.css — the branded sign-in screen
   University of Bridgeport

   Loaded only on wp-login.php, by ubridgeport_login_assets() in functions.php.

   ── WHY THIS SHEET FIGHTS FOR SPECIFICITY ──────────────────────────────────
   wp-login.php is not a theme template. WordPress prints its own login.css and
   there is no hook to dequeue it that does not also take the form's layout and
   the password-visibility toggle with it. So core's sheet stays, loads FIRST,
   and this one overrides it.

   That is why selectors here are longer than they would be in a theme
   stylesheet — `body.login #loginform` rather than `#loginform`. They are
   matched to core's own specificity, not padded past it: core styles
   `.login form`, so `body.login form` beats it on one extra class and nothing
   here needs !important except where core itself used it. Trimming these
   selectors "for tidiness" hands the rule back to core.

   ── TOKENS, NOT LITERALS ───────────────────────────────────────────────────
   Every colour and duration below reads a custom property that
   inc/theme-design/ compiles from Appearance -> Theme Design. The theme's
   token block prints at `wp_head`, which does NOT fire on the login screen —
   functions.php prints it at `login_head` for exactly this reason. Hardcoding
   #592d82 here would look identical today and silently stop following the
   palette the moment anyone changes it.

   Fallbacks in var() are the shipped defaults, so the screen is still correct
   if the token block is ever absent.

   ── THE TWO-PANEL LAYOUT ───────────────────────────────────────────────────
   Wide viewports get a photograph on the left and the form on the right. The
   split is a grid on <body>, which works because core wraps everything in
   #login — one element to place. Below 900px the photograph is dropped
   (`display: none`, not a shorter column: a 200px-tall crop of a campus wide
   shot is noise, and it would push the form below the fold on a phone).
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Local tokens.

   Named on :root rather than inlined so the knight SVG can read them too — it
   is loaded as an <img>, which cannot inherit, so the mark carries its own
   fallbacks and these apply to the CSS side of the screen.
   -------------------------------------------------------------------------- */
:root {
  --login-ground: var(--ub-purple-deep, #2a1240);
  --login-card: var(--white, #ffffff);
  --login-field-border: #d6d0dd;
  --login-radius: 4px;          /* Not var(--btn-radius): see the button rule. */
  --login-panel-w: 46%;
  /* The disc behind the knight. A token because it is a real design decision
     (see the logo rule for why the artwork needs a light ground) and someone
     reasonably might want it off-white or a pale tint of the brand purple. */
  --ub-knight-disc: #ffffff;
}

/* --------------------------------------------------------------------------
   Page shell
   -------------------------------------------------------------------------- */
body.login {
  /* Core sets `background: #f0f0f1` on html; the deep purple has to beat it
     on both elements or a rubber-band scroll on iOS shows grey behind. */
  background: var(--login-ground);
  /* A guard, not a fix for anything currently broken: nothing in the form is
     wide enough to stretch the page today, and this keeps a future long
     error string or a plugin's own field from introducing a horizontal
     scrollbar on a phone. */
  max-width: 100%;
  overflow-x: hidden;
  font-family: var(--font-primary, 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
  min-height: 100vh;
  margin: 0;
  display: grid;
  /* Single column by default — the photograph is opted INTO at 900px, rather
     than opted out of below it, so the phone layout is the one that needs no
     media query to be correct. */
  grid-template-columns: 1fr;
  align-items: stretch;
  /* Rows flow naturally in the one-column (phone) layout, where the only items
     are #login and the help line. The two-panel rule at 900px pins a single
     full-height row and places every item into it — see there for why. */
  grid-template-rows: auto;
}

html {
  background: var(--login-ground);
}

/* Core's page-title <h1> is visually hidden but still a grid item, so it claims
   a cell and pushes the form into the next one. Taken out of flow entirely; it
   keeps its clip-based hiding from core and stays in the accessibility tree. */
body.login > h1.screen-reader-text {
  position: absolute;
}

/* The campus photograph AND its purple wash, in ONE pseudo-element.

   Both layers ride on ::before as a two-stop background — the gradient first,
   the photograph under it — rather than one each on ::before and ::after. That
   is not tidiness: <body> here is a grid, ::before and ::after are grid items,
   and spending both on the left panel leaves the help line (which core prints
   outside #login, see inc/login.php) with no pseudo-element to stack against
   and nowhere to sit but the photograph's cell.

   One element for the panel means ::after stays free, and the wash is
   guaranteed to be exactly co-extensive with the image it is washing.

   An ::before on <body> rather than a real element because wp-login.php is not
   a template — there is no markup to add without filtering core's output.
   Decorative, so no alt-text obligation: the mark and the heading say where
   you are.

   The gradient echoes the site's own hero treatment (css/home.css
   .hero2-media::after) so this screen reads as the same institution rather
   than as a stock login with a picture on it. */
body.login::before {
  content: '';
  display: none;                /* switched on at 900px */
  /* The wash reads the SAME tokens as the rest of the screen, via
     color-mix() — an rgba() literal cannot take a custom property as its
     channels, and hardcoding the purples here was a real bug: changing the
     brand colour recoloured the whole screen and left this one gradient
     purple, which is exactly the drift the token block exists to prevent.
     `transparent` in a color-mix is how the alpha steps are expressed. */
  background-image:
    linear-gradient(150deg,
      color-mix(in srgb, var(--login-ground) 88%, transparent) 0%,
      color-mix(in srgb, var(--login-ground) 52%, transparent) 46%,
      color-mix(in srgb, var(--ub-purple, #592d82) 66%, transparent) 100%),
    var(--login-photo, none);
  background-size: cover, cover;
  background-position: center, center 38%;
  background-repeat: no-repeat, no-repeat;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   The form column
   -------------------------------------------------------------------------- */
body.login #login {
  width: 100%;
  max-width: 460px;
  margin: 0 auto;
  /* Core ships `padding: 8% 0 0`, which pins the form to a percentage of the
     viewport and leaves it high on a short window and low on a tall one.
     Centring in the grid track is stable at any height. */
  padding: 40px 20px;
  align-self: center;
  box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   Brand lockup — replaces core's WordPress logo

   Core renders the logo as an <h1><a> whose background-image is the W mark. It
   is emptied here and the knight is set on the <a>, keeping core's markup and
   its link to the site (which functions.php re-points at the homepage) rather
   than filtering the header away and rebuilding it.
   -------------------------------------------------------------------------- */
/* Scoped to .wp-login-logo, NOT `body.login h1`. Core prints a SECOND <h1> —
   `h1.screen-reader-text`, the page title, a sibling of #login — and the loose
   selector styled that too, which added a stray item to the body grid. */
body.login h1.wp-login-logo {
  margin: 0 0 4px;
  text-align: center;
}

body.login h1.wp-login-logo a {
  background-image: url('../images/ub-knight.png');
  background-position: center;
  background-repeat: no-repeat;
  /* The supplied artwork is 192x201 — very slightly taller than wide — and the
     box keeps that ratio so the mark is never squashed. Displayed at exactly
     half its pixel size, so it is always downscaled, never stretched, which is
     what keeps it sharp on a 2x panel. Do not raise these past 192x201. */
  width: 96px;
  height: 100px;
  /* The medallion. The supplied artwork is drawn for a LIGHT ground — its
     darkest purples and its black linework are within a few percent of this
     screen's own background, so on bare deep purple the helmet's shaded side
     dissolves into the page and the mark reads as a fragment.

     A light disc behind it restores the contrast the artwork was drawn for.
     This is also how the athletics mark is normally presented on dark: on a
     light roundel rather than knocked out or recoloured, neither of which is
     ours to do to a licensed identity asset.

     Padding is what keeps the mark off the disc's edge, so the box is larger
     than the 96x100 image and `background-size` stays explicit rather than
     `contain` — which would otherwise scale the artwork to the padded box. */
  box-sizing: content-box;
  padding: 16px;
  background-color: var(--ub-knight-disc, #ffffff);
  background-size: 96px 100px;
  border-radius: 50%;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.34),
              0 0 0 1px rgba(255, 255, 255, 0.16);
  margin: 0 auto 18px;
  text-indent: -9999px;         /* keeps the accessible name, hides the text */
  overflow: hidden;
  display: block;
  outline-offset: 6px;
  /* A soft shadow so the mark sits on the ground rather than reading as a flat
     sticker. The artwork's own white keyline does the separating. */
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.35));
  transition: var(--transition, all 300ms cubic-bezier(0.25, 0.8, 0.25, 1));
}

body.login h1.wp-login-logo a:hover,
body.login h1.wp-login-logo a:focus {
  transform: translateY(-2px);
}

/* Wordmark and eyebrow, printed by ubridgeport_login_brand() */
.ub-login-brand {
  text-align: center;
  margin: 0 0 26px;
}

.ub-login-brand__name {
  font-family: var(--font-display, var(--font-primary, 'Outfit', sans-serif));
  font-weight: var(--heading-weight, 800);
  font-size: 1.55rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--white, #ffffff);
  margin: 0 0 8px;
  text-wrap: balance;
}

.ub-login-brand__eyebrow {
  display: block;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--eyebrow-tracking, 0.2em);
  /* Blue on deep purple is the site's own accent pairing. Lightened from
     --ub-blue because that value is chosen for contrast on white; on this
     ground it needs to come up to clear 4.5:1. */
  color: #6fd3f5;
  margin: 0 0 10px;
}

/* --------------------------------------------------------------------------
   The card

   Core's `.login form` is a white box with a 1px grey border and a small
   shadow. Kept as a card — a form on a photograph needs an opaque ground to
   stay legible — but given the site's own elevation and squared corners.
   -------------------------------------------------------------------------- */
body.login form {
  background: var(--login-card);
  border: 0;
  border-radius: 8px;
  box-shadow: var(--shadow-lg, 0 20px 40px rgba(0, 0, 0, 0.12)),
              0 0 0 1px rgba(255, 255, 255, 0.06);
  padding: 30px 30px 26px;
  margin-top: 0;
  /* A purple edge along the top, the same device the site uses on cards
     (css/style.css .stat-card). Two pixels, not four: at card width this is a
     detail, not a banner. */
  border-top: 3px solid var(--ub-purple, #592d82);
  overflow: hidden;
  /* Core does not set this, so the 30px padding above was being added OUTSIDE
     the inherited width and the card overflowed the right edge of a 390px
     screen. Not cosmetic: it pushed the submit button partly off-screen. */
  box-sizing: border-box;
  width: 100%;
}

body.login form .forgetmenot {
  font-weight: 400;
  float: none;
  margin: 0;
}

/* --------------------------------------------------------------------------
   Fields
   -------------------------------------------------------------------------- */
body.login form label {
  color: var(--text-main, #2c3e50);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.5;
}

body.login form .input,
body.login form input[type="text"],
body.login form input[type="password"],
body.login form input[type="email"] {
  background: #fcfbfd;
  border: 1px solid var(--login-field-border);
  border-radius: var(--login-radius);
  color: var(--text-main, #2c3e50);
  font-family: inherit;
  font-size: 1rem;
  /* Core sets 16px on this input via `font-size: 24px` on .input and then
     shrinks it; 1rem plus generous padding is a 44px-tall target, which is the
     minimum comfortable tap size. */
  padding: 11px 13px;
  margin: 0 0 18px;
  width: 100%;
  box-sizing: border-box;
  box-shadow: none;
  transition: var(--transition, all 300ms cubic-bezier(0.25, 0.8, 0.25, 1));
}

body.login form input[type="text"]:focus,
body.login form input[type="password"]:focus,
body.login form input[type="email"]:focus {
  border-color: var(--ub-purple, #592d82);
  /* A ring rather than a border-width change, so focusing a field does not
     shift the layout by a pixel. Core uses its own blue box-shadow here, which
     this replaces rather than layers on. */
  box-shadow: 0 0 0 3px rgba(89, 45, 130, 0.16);
  outline: 2px solid transparent;   /* visible in forced-colours mode */
  outline-offset: 0;
}

/* The password-visibility toggle. Core positions it inside the field wrapper;
   only its colours need saying, and its focus ring must clear the field's. */
body.login .wp-pwd {
  position: relative;
}

body.login .wp-pwd input[type="text"],
body.login .wp-pwd input[type="password"] {
  padding-right: 46px;
}

body.login button.wp-hide-pw {
  color: var(--text-light, #5b6a75);
  height: 44px;
  width: 44px;
  top: 0;
}

body.login button.wp-hide-pw:hover,
body.login button.wp-hide-pw:focus {
  color: var(--ub-purple, #592d82);
}

body.login button.wp-hide-pw:focus {
  box-shadow: 0 0 0 2px var(--ub-purple, #592d82);
  border-radius: var(--login-radius);
}

/* --------------------------------------------------------------------------
   Submit button — the site's .btn-primary, restated

   It cannot reuse .btn: core prints class="button button-primary" and there is
   no filter on the submit button's attributes. So the values are restated from
   css/style.css .btn / .btn-primary and read the SAME tokens, which is what
   keeps the two in step when the button settings change.

   --btn-radius is deliberately NOT used. It ships as 0 for the site's square
   buttons; against this card's 8px corners and 4px fields a square button
   reads as a rendering fault rather than a choice, so the card sets its own.
   -------------------------------------------------------------------------- */
body.login form .button-primary,
body.login form input[type="submit"].button-primary {
  background: var(--ub-purple, #592d82);
  border: var(--btn-border-width, 2px) solid transparent;
  border-radius: var(--login-radius);
  color: var(--white, #ffffff);
  float: none;
  font-family: inherit;
  font-size: calc(1rem * var(--btn-font-scale, 1));
  font-weight: var(--btn-weight, 600);
  letter-spacing: var(--btn-tracking, 0em);
  text-transform: var(--btn-transform, none);
  text-shadow: none;
  box-shadow: none;
  width: 100%;
  height: auto;
  padding: calc(12px * var(--btn-pad-scale, 1)) calc(24px * var(--btn-pad-scale, 1));
  margin: 4px 0 0;
  cursor: pointer;
  transition: var(--transition, all 300ms cubic-bezier(0.25, 0.8, 0.25, 1));
}

body.login form .button-primary:hover,
body.login form .button-primary:focus {
  background: var(--ub-purple-dark, #3f1d61);
  border-color: transparent;
  color: var(--white, #ffffff);
  transform: translateY(calc(var(--btn-lift, 2px) * -1));
  box-shadow: var(--shadow-md, 0 10px 20px rgba(0, 0, 0, 0.08));
}

body.login form .button-primary:focus-visible {
  outline: 3px solid #6fd3f5;
  outline-offset: 2px;
}

body.login form .button-primary:active {
  transform: translateY(0);
  box-shadow: none;
}

/* --------------------------------------------------------------------------
   Links below the card

   Core renders "Lost your password?" and "Back to <site>" as #nav and
   #backtoblog, unstyled white-on-grey. Here they sit directly on the purple
   ground, so they need to be light and to keep a visible focus state.
   -------------------------------------------------------------------------- */
body.login #nav,
body.login #backtoblog {
  padding: 0;
  margin: 0;
  text-align: center;
  text-shadow: none;
}

body.login #nav {
  margin: 20px 0 6px;
}

body.login #backtoblog {
  margin: 0 0 4px;
}

body.login #nav a,
body.login #backtoblog a,
body.login .privacy-policy-link {
  color: rgba(255, 255, 255, 0.82);
  font-size: 0.875rem;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.28);
  padding-bottom: 1px;
  transition: var(--transition, all 300ms cubic-bezier(0.25, 0.8, 0.25, 1));
}

body.login #nav a:hover,
body.login #backtoblog a:hover,
body.login .privacy-policy-link:hover {
  color: var(--white, #ffffff);
  border-bottom-color: #6fd3f5;
}

body.login #nav a:focus-visible,
body.login #backtoblog a:focus-visible,
body.login .privacy-policy-link:focus-visible {
  outline: 2px solid #6fd3f5;
  outline-offset: 3px;
  border-radius: 2px;
}

body.login .privacy-policy-page-link {
  margin: 12px 0 0;
}

/* The support line, printed by ubridgeport_login_footer() at `login_footer`.

   That hook fires OUTSIDE #login (see the function for why it is still the
   right one), so this is a grid item in its own right and is placed explicitly
   into the form column at 900px. Without that placement it lands in the
   photograph's cell. */
.ub-login-help {
  text-align: center;
  color: rgba(255, 255, 255, 0.62);
  font-size: 0.8125rem;
  line-height: 1.6;
  /* Pulled up under the card's links; #login carries the column's own padding
     and this sits after it in the same track. */
  margin: -18px auto 28px;
  max-width: 34ch;
  padding: 0 24px;
  position: relative;
  z-index: 2;
}

.ub-login-help a {
  color: rgba(255, 255, 255, 0.88);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.ub-login-help a:hover {
  color: var(--white, #ffffff);
}

.ub-login-help a:focus-visible {
  outline: 2px solid #6fd3f5;
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   Messages: errors, notices, password-reset confirmations

   Core's `.login .message` is a white box with a blue left border and
   `.login #login_error` the same in red. Both are re-grounded so they read as
   part of the card stack rather than as WordPress admin notices, and both keep
   a left border — colour alone must not be the only signal.
   -------------------------------------------------------------------------- */
body.login #login_error,
body.login .notice,
body.login .message,
body.login .success {
  background: var(--login-card);
  border: 0;
  border-left: 4px solid var(--ub-blue, #00a7e0);
  border-radius: var(--login-radius);
  box-shadow: var(--shadow-md, 0 10px 20px rgba(0, 0, 0, 0.08));
  color: var(--text-main, #2c3e50);
  font-size: 0.9rem;
  line-height: 1.6;
  padding: 13px 16px;
  margin: 0 0 18px;
  word-break: break-word;
}

body.login #login_error {
  border-left-color: #c0392b;
}

body.login #login_error a,
body.login .message a {
  color: var(--ub-blue-text, #0a6e8f);
}

/* Core's own "shake" on a failed login is kept — it is a useful signal — but
   suppressed for anyone who has asked for less motion. */
@media (prefers-reduced-motion: reduce) {
  body.login * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  body.login h1.wp-login-logo a:hover,
  body.login form .button-primary:hover {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Language switcher (WP 5.9+) — core drops a <select> under the form
   -------------------------------------------------------------------------- */
body.login .language-switcher {
  margin: 14px 0 0;
}

body.login .language-switcher label {
  color: rgba(255, 255, 255, 0.75);
}

body.login .language-switcher select {
  border-radius: var(--login-radius);
  border: 1px solid rgba(255, 255, 255, 0.3);
  background-color: rgba(255, 255, 255, 0.08);
  color: var(--white, #ffffff);
  padding: 6px 8px;
}

body.login .language-switcher .button {
  border-radius: var(--login-radius);
}

/* --------------------------------------------------------------------------
   Two-panel layout

   900px is where the form column plus a photograph wide enough to read as a
   photograph both fit. Below it the image is dropped entirely.
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {
  body.login {
    grid-template-columns: var(--login-panel-w) 1fr;
    /* FOUR rows: a flexible spacer, the card, the help line, another spacer.
       The two `1fr` rows centre the middle pair as a group; the middle two size
       to their content.

       Why not one row with both items in it: two grid items in the same cell
       STACK on top of each other, and core's markup gives #login and the help
       line no shared wrapper to lay out inside (the line comes from
       `login_footer`, which fires outside #login — see inc/login.php). Placing
       them in one cell each with a hand-tuned offset was the first attempt and
       it broke on the first login error, because #login_error makes the card
       taller and the line slid under the links. Giving each its own auto row is
       the only arrangement that cannot collide at any card height. */
    grid-template-rows: 1fr auto auto 1fr;
    min-height: 100vh;
  }

  /* The photograph spans every row, which is what keeps the panel full-height
     however the form column is divided. */
  body.login::before {
    display: block;
    grid-row: 1 / -1;
    grid-column: 1;
  }

  body.login #login {
    grid-row: 2;
    grid-column: 2;
    max-width: 480px;
    /* No vertical padding: the 1fr rows above and below do the centring, and
       padding here would fight them. */
    padding: 0 40px;
  }

  body.login .ub-login-help {
    grid-row: 3;
    grid-column: 2;
    margin: 16px auto 0;
  }
}

/* The grid above centres the card in the window. On a tall screen that reads
   slightly low, because the eye weights the wordmark above the card — so the
   top spacer is given less of the free space than the bottom one, lifting the
   pair to optical centre. */
@media (min-width: 900px) and (min-height: 860px) {
  body.login {
    grid-template-rows: 0.8fr auto auto 1fr;
  }
}

/* Very short windows — a laptop with devtools open, or a phone in landscape —
   must scroll rather than clip the submit button.

   The two `1fr` spacer rows are collapsed to `0` so the card starts at the top
   and the page grows past the viewport instead of the content being squeezed
   inside 100vh. The card and the help line KEEP their own rows: flattening this
   to `auto` would put both in one cell and reintroduce the overlap the
   four-row layout exists to prevent. */
@media (max-height: 620px) {
  body.login {
    grid-template-rows: 0 auto auto 0;
    align-items: start;
  }

  body.login #login {
    padding-top: 28px;
  }

  body.login .ub-login-help {
    margin-bottom: 28px;
  }
}

/* --------------------------------------------------------------------------
   Forced colours / high contrast

   The purple ground and the white card both become system colours here, so the
   card's only remaining separation is its border — which the base rule removes.
   Put one back.
   -------------------------------------------------------------------------- */
@media (forced-colors: active) {
  body.login form {
    border: 1px solid CanvasText;
  }

  body.login h1.wp-login-logo a {
    filter: none;
  }
}
