/* CSHS pass on Authelia's login portal. Colors match Payload's/Listmonk's
   native login-page colors (rgb(47,47,47) primary, not CSHS blue -- that
   was tried and rejected for the other two login pages, see
   project_cshs_all_in_one_build memory), not guessed: Authelia's real
   frontend is shadcn/ui (Radix + Tailwind), confirmed directly from its
   own source (authelia/authelia v4.39.24, web/src/components/UI/Button.tsx
   uses `bg-primary text-primary-foreground` etc.) and its live served CSS
   (auth.cshs.dev/static/css/index.*.css), not assumed to be MUI as an
   earlier draft of this plan guessed.

   Real, live root variable values pulled directly from the served CSS
   before writing this -- only --primary/--ring/--radius are overridden,
   everything else (--background, --border, --foreground, etc.) is
   already a neutral value matching the "native colors, no CSHS blue"
   direction, same reasoning as leaving Payload's own borders untouched. */

:root,
[data-theme='light'] {
  --primary: rgb(47, 47, 47);
  --ring: rgb(47, 47, 47);
  --radius: 3px;
}

[data-theme='dark'] {
  --primary: rgb(235, 235, 235);
  --primary-foreground: rgb(20, 20, 20);
  --ring: rgb(235, 235, 235);
  --radius: 3px;
}

/* Everything below is real, structural work grounded in Authelia's own
   v4.39.24 source (web/src/views/LoginPortal/FirstFactor/
   FirstFactorForm.tsx, web/src/components/UI/FloatingInput.tsx,
   web/src/layouts/LoginLayout.tsx, web/src/components/
   AppBarItemLanguage.tsx) -- every selector below is a real id/class
   confirmed in that source, not guessed. */

/* Font: applied at #first-factor-stage level so it cascades to every
   descendant by inheritance, instead of the earlier, incomplete
   per-element approach (missed the inputs, the button, and the
   heading). Form controls (input/button) don't inherit font-family
   from an ancestor by default in browsers unless something resets
   them to -- Authelia's own Tailwind Preflight does this, confirmed
   live (the button/input already picked up the change once this was
   moved to a single ancestor rule). */
#first-factor-stage {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* LoginLayout's own outer wrapper sets `text-center` (confirmed from
   its source: className="flex min-h-[90vh] items-center justify-center
   text-center") -- text-align is inherited, so this centers every
   descendant text node by default, including the labels, unless
   explicitly overridden back to left. */
#first-factor-stage {
  text-align: left;
}

/* Avatar/logo: real default is a generic user-silhouette SVG
   (UserSvg, classes mx-auto my-2 w-16 = 64px), 20% smaller. Kept
   centered (mx-auto is untouched) -- only the text below it needed
   the text-align fix above, the logo itself was never centered via
   text-align. */
.w-16.mx-auto.my-2 {
  /* translateY listed BEFORE scale so it applies to the already-
     scaled box (outermost), giving an exact, unscaled -5px shift.
     Purely visual -- doesn't change this element's flow height, so
     unlike margin-top it can't trigger the whole-page recentering
     effect (the form's vertical-center container reacts to total
     flow height, not to transforms). */
  transform: translateY(-5px) scale(0.8);
  margin-top: -20px;
}

/* Login container: Authelia's real default class is `max-w-[444px]`
   -- a Tailwind arbitrary-value class (confirmed live via getComputedStyle
   after an earlier attempt at this selector, targeting the wrong class
   name `max-w-xs`, silently matched nothing at all). Brackets need
   escaping in the CSS selector since they're literal characters in
   the class name here, not a CSS attribute selector. Also had px-8
   padding (2rem/32px each side) INSIDE that width -- same class of bug
   already hit once on Listmonk's own container this session (.wrap's
   padding eating into its max-width). Payload's real 480px container
   (.template-minimal__wrap) has ZERO padding of its own -- matched
   exactly here instead of just compensating the max-width number. */
#first-factor-stage .max-w-\[444px\] {
  max-width: 480px;
}

#first-factor-stage .px-8 {
  padding-left: 0;
  padding-right: 0;
}

/* "Login" heading -- hidden entirely instead of styled, matching
   Payload and Listmonk exactly (neither shows a heading here at all;
   Listmonk's was explicitly removed for the same reason earlier this
   session). The locale rename from "Sign in" to "Login" stays --
   that's the real translation string Authelia uses elsewhere too
   (e.g. the document title), this just stops it from rendering as
   visible page text here. */
#first-factor-stage h5 {
  display: none;
}

/* Top app bar (language selector + account settings) -- the one
   piece of chrome Authelia has that Payload's login page doesn't,
   confirmed to measurably push the centered form down (60px real
   height, live-measured) since it sits ABOVE LoginLayout's own
   min-h-[90vh] centering container, not inside it. Padding trimmed
   (was pt-2 pb-4 = 8px+16px) to reduce that offset without removing
   the bar itself. */
header.bg-transparent > div {
  padding-top: 5px;
  padding-bottom: 0;
}

/* Logo's own wrapper div (LoginLayout: <div className="w-full p-2">)
   adds another 8px above/below on top of the logo's own my-2 margin
   -- trimmed together with the header change above for the requested
   ~15-20px total upward shift. */
#first-factor-stage .p-2:has(.w-16.mx-auto.my-2) {
  padding-top: 0;
  padding-bottom: 0;
}

/* Top-right language selector button + its visible text. */
#language-button,
#language-button span {
  font-size: 13px;
  color: rgb(47, 47, 47);
}

/* Username/password fields: Authelia's FloatingInput defaults to
   h-14 (56px) with a floating, overlapping label (confirmed from its
   own source: the label is position:absolute, sitting inside the
   input's own box). Flattened to Payload's real 40px height, and the
   label pulled OUT of the box into its own static line above the
   input instead of floating over it. Radius corrected to Payload's
   real $style-radius-s (confirmed from vars.scss: exactly 3px) --
   an earlier pass set this to 0 per a literal "no rounded corners"
   request, but Payload's own fields do have a small, barely-visible
   radius, not none. */
[data-slot='floating-input'] {
  height: 40px;
  border-radius: 3px;
  padding: 8px 15px;
  font-size: 13px;
  /* Payload's real field shadow, confirmed from its compiled CSS
     (formInput() mixin, shared by .field-type.text/.email/.password
     input) -- a subtle shadow under the field, not guessed. */
  box-shadow: 0 2px 2px -1px #0000001a;
}

/* Username field only, 1px lower relative to its own label -- safe to
   touch now that the label's leftover `translate: -50%` bug (see the
   label rule below) is fixed; the label no longer has any positional
   dependency on the input's box.

   Scoped to #first-factor-stage: the reset-password page reuses the
   same id="username-textfield" on its own, unrelated input -- an
   unscoped rule here would nudge that page's field too. */
#first-factor-stage #username-textfield {
  margin-top: 1px;
}

#first-factor-stage #password-textfield {
  margin-top: 0px;
}

/* The label's wrapping div (FloatingInput's own root, class="relative
   w-full") needs to become a column flex container so the label can
   sit above the input via `order` instead of absolutely overlapping
   it. Scoped with :has() to only the two wrappers that actually
   contain a floating-input, not every .relative.w-full on the page. */
div.relative.w-full:has([data-slot='floating-input']) {
  display: flex;
  flex-direction: column;
}

/* Password visibility toggle (real selector: the only button with
   this aria-label, confirmed from FirstFactorForm.tsx -- it has no
   id). Authelia's own default (`absolute right-2 top-1/2
   -translate-y-1/2`) centers it within its WHOLE wrapper div, which
   was fine when the label floated inside/overlapped the input
   (wrapper height ~= input height) but broke once the label became a
   separate static line above the input (wrapper is now taller than
   just the input, so centering-in-the-wrapper no longer lines up
   with the input itself). Anchored to the bottom instead, matching
   the input's own real 40px height, since the input is always the
   last thing in this now-column-flex wrapper (label has order:-1). */
button[aria-label='Toggle password visibility'] {
  top: auto;
  bottom: 0;
  /* Same leftover-`translate`-property bug as the label above: this
     button still carries Authelia's native `top-1/2 -translate-y-1/2`
     classes, which Tailwind v4 compiles to a standalone `translate:
     0 -50%` -- untouched by `top: auto` and shifting the icon up by
     50% of its own 40px height (20px) regardless. This is the real
     reason earlier attempts needed a hand-tuned `bottom: -20px`
     "compensation" that then had to be re-tuned every time the input
     moved -- the actual bug was never about the input's position at
     all. Neutralizing it here makes `bottom: 0` mean what it says:
     flush with the input's own bottom edge, no compensation needed. */
  translate: none;
  height: 40px;
  display: flex;
  align-items: center;
}

[data-slot='floating-input'] ~ label {
  position: static;
  order: -1;
  transform: none;
  /* Root cause of every earlier "textfield up = username moves" bug,
     found via direct computed-style inspection: Authelia's native
     floating label uses Tailwind's `-translate-y-1/2` utility, which
     Tailwind v4 compiles to the standalone CSS `translate` property,
     NOT into `transform` -- confirmed live (`getComputedStyle(label)
     .translate` returned "0px -50%" even with `transform: none` set
     above). `translate` is unaffected by overriding `transform`, so
     the label was rendering 50% of its own box height (9.75px)
     higher than its real static-flow position, on top of a phantom
     `top: 50%` (inert here since position is static, but confirms the
     leftover floating-label styles). This never depended on the
     input at all -- any edit to the label's OWN box height (line-height,
     padding) shifted this offset and looked like the label "moving,"
     which is why every previous attempt at the gap kept failing
     regardless of which side was touched. Neutralizing it here closes
     ~10px of the visual label-to-input gap on its own, with zero
     change to margin/padding on either element. */
  translate: none;
  text-align: left;
  font-size: 13px;
  color: rgb(47, 47, 47);
  margin-bottom: 5px;
}

/* Required-asterisk coloring dropped: Authelia bakes " *" directly
   into the label's OWN translated text string (`label={translate(
   "Username") + " *"}`, confirmed from FirstFactorForm.tsx), not a
   separately-stylable element the way Payload's <span class="required">
   is. Recoloring just the asterisk needed hiding the real text and
   reconstructing it via CSS `content`, which hardcoded the English
   words "Username"/"Password" -- broke the language switcher for
   just these two labels (confirmed live: every other string on the
   page translates correctly, these two didn't). Left as Authelia's
   own native text now instead, asterisk included at its default
   (grey) color -- fully i18n-correct, no hack. A JS-based fix (strip
   the trailing " *" and re-wrap just that in a colored span, language-
   agnostic since the suffix itself isn't translated) would recover
   the red color without the i18n cost, but needs actual script
   injection alongside the CSS -- not built. */

/* Row layout: Authelia's own default DOM order is username, password,
   remember-me, submit button, reset-password (reset-password comes
   LAST, after the button -- confirmed from FirstFactorForm.tsx).

   Back to Reset-password + Remember-me sharing one row (tried moving
   Remember-me to share the submit-button row instead, mirroring
   Payload's paired-button row -- reverted per direct feedback, felt
   misplaced there). Submit button back to its own full-width row.

   .grid.grid-cols-1 is already a real CSS grid in Authelia's own
   markup, overridden here to 2 columns with named areas so
   username/password/submit stay full-width (spanning both columns)
   while the resetpw/rememberme row splits. */
.grid.grid-cols-1 {
  grid-template-columns: 1fr 1fr;
  grid-template-areas:
    'username username'
    'password password'
    'resetpw rememberme'
    'submit submit';
}

.grid.grid-cols-1 > div:has(#username-textfield) {
  grid-area: username;
  margin-top: 21px;
}

.grid.grid-cols-1 > div:has(#password-textfield) {
  grid-area: password;
  /* Pulls the password field 3px closer to username. The 20px space
     above it is the grid's own row-gap (confirmed live via
     getComputedStyle), shared uniformly by every row in this grid --
     so this is set on password's own outer div specifically (same
     pattern as the resetpw/rememberme rows below), not by touching
     row-gap itself (which would also shift password-to-resetpw
     spacing) and not by touching anything on username's own label or
     field. */
  margin-top: -2px;
}

.grid.grid-cols-1 > div:has(#reset-password-button) {
  grid-area: resetpw;
  /* Authelia's own default right-aligns this row (justify-end);
     Payload's forgot-password is left-aligned. */
  justify-content: flex-start;
  align-self: center;
  /* The grid's own gap-5 (20px) is correct for username-to-password
     (matches Payload's real .login__form__inputWrap gap exactly),
     but Payload's gap from the field group to what follows is only
     5px (margin-bottom: calc(var(--base)/4)) -- pulled up here to
     match, rather than leaving every row at the same 20px.

     Frozen at the original -15px baseline -- same cascade bug as
     username's own row (see that rule's comment): margin-top on a
     grid item grows that item's own margin-box, which grows the
     shared resetpw/rememberme row's auto-sized track height, which
     pushes the submit row and footer below it down too. Kept fixed
     here so nothing downstream shifts again; the cumulative 8px
     visual nudge requested this round now lives on the transform
     below instead, which doesn't participate in track sizing. */
  margin-top: -15px;
  transform: translateY(6px);
}

#reset-password-button {
  font-size: 13px;
  /* Authelia's own default only underlines on hover, AND at a large
     offset (Tailwind's underline-offset-4 = 1rem/16px -- confirmed
     the real cause of the underline reading as "way off" from the
     text, not a rendering bug). Always-on per earlier direct
     request, offset brought down to something that actually reads as
     an underline, not a separate line beneath the text. */
  text-decoration: underline;
  text-underline-offset: 2px;
}

.grid.grid-cols-1 > div:has(#remember-checkbox) {
  grid-area: rememberme;
  align-self: center;
  /* Same -15px as the resetpw row above -- both are on the same grid
     row (grid-area rows align by definition), but margin still needs
     setting on both sides or the row's own height/alignment could be
     computed from whichever div didn't get pulled up. */
  margin-top: -15px;
}

/* Remember-me's own inner flex row (the div directly wrapping the
   checkbox + label) left-aligns by default; pushed right within its
   own grid column per direct request. */
.grid.grid-cols-1 > div:has(#remember-checkbox) > div {
  justify-content: flex-end;
}

label[for='remember-checkbox'] {
  font-size: 13px;
  color: rgb(47, 47, 47);
  /* Payload's real field-label weight (confirmed from its compiled
     CSS: .field-label{font-weight:400}) -- Authelia's own default is
     bolder. */
  font-weight: 400;
}

.grid.grid-cols-1 > div:has(#sign-in-button) {
  grid-area: submit;
  /* transform, not margin-top -- margin-top here would grow this
     row's own track height and push the footer below it down too
     (same cascade bug hit on username's and resetpw's rows). */
  transform: translateY(23px);
}

/* Login button: Authelia's own default is uppercase (Button.tsx's
   base cva classes include "uppercase") at the browser's default
   button font-size -- removed the transform and matched Payload's
   real 13px body-text size instead. border-radius set explicitly
   here rather than relying on the shared --radius token: shadcn's
   own Button component computes its actual radius as a fraction of
   --radius internally (confirmed live -- with --radius:3px the
   button rendered at ~1px, imperceptible), so --radius alone wasn't
   enough to give it Payload's real, visible 3px. */
#sign-in-button {
  text-transform: none;
  font-size: 13px;
  border-radius: 3px;
  /* Payload's real primary-button weight (confirmed from its
     compiled CSS: .btn{--btn-font-weight: normal}) -- Authelia's own
     default here is bolder. */
  font-weight: 400;
}

/* "Powered by Authelia" footer -- sits directly after the form with
   no margin of its own (LoginLayout's <Brand /> has none set),
   reading as too close to the submit button. */
#first-factor-stage .flex.items-center.justify-center.gap-2.w-full {
  margin-top: 20px;
  /* transform, not more margin-top -- this is the last element on
     the page, so margin-top here can't cascade into a row below it,
     but it still grows total flow height, which shifts EVERYTHING
     via the form's vertical-centering (confirmed live: this exact
     property, 20px->30px, was the real cause of a "whole page
     shifted" report). transform sidesteps that entirely. */
  transform: translateY(20px);
}

/* Note: the capslock-warning row and PasskeyForm's own row aren't
   given an explicit grid-area -- both are conditionally rendered
   (capslock only while actively triggered, passkey confirmed disabled
   on this deployment via data-passkeylogin="false") and would need
   their own named areas if either becomes a real, regularly-visible
   concern. */

/* ============================================================
   Reset-password page (#reset-password-step1-stage)
   ============================================================
   Shares LoginLayout with the login page (same header/avatar/
   max-w-[444px] container -- the unscoped rules above, like
   .w-16.mx-auto.my-2 and header.bg-transparent > div, already
   apply here too) but its username field is a completely
   different component -- confirmed live via direct DOM inspection,
   not assumed: plain shadcn Input + Label (h-14 rounded-md
   border-input input, flex items-center gap-2 text-sm label),
   NOT FloatingInput. No data-slot='floating-input', no absolute/
   translate label mechanics, no required-asterisk text baked in.
   Already in label-then-input DOM order, so none of the
   FloatingInput-specific rules above (or their translate:none
   fixes) apply or are needed here. */
#reset-password-step1-stage {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  text-align: left;
}

#reset-password-step1-stage .max-w-\[444px\] {
  max-width: 480px;
}

#reset-password-step1-stage .px-8 {
  padding-left: 0;
  padding-right: 0;
}

/* Heading kept visible (unlike login's, which was hidden to match
   Payload/Listmonk's headingless pattern) -- there's no equivalent
   Payload/Listmonk forgot-password page built yet to match against,
   and this page has no other on-screen context otherwise. Styled
   down from Authelia's own default (text-2xl / 24px) to something
   closer to Payload's own heading scale. */
#reset-password-step1-stage h5 {
  font-size: 16px;
  font-weight: 400;
  color: rgb(47, 47, 47);
  text-align: left;
  margin-bottom: 15px;
}

#reset-password-step1-stage label {
  display: block;
  font-size: 13px;
  font-weight: 400;
  color: rgb(47, 47, 47);
  margin-bottom: 10px;
}

#reset-password-step1-stage input {
  width: 100%;
  height: 40px;
  border-radius: 3px;
  padding: 8px 15px;
  font-size: 13px;
  box-shadow: 0 2px 2px -1px #0000001a;
}

/* Both Reset and Cancel currently render identically (Authelia's own
   default: both bg-primary) -- left as-is rather than inventing an
   unrequested secondary/outline treatment; just brought in line with
   the login button's own styling (no uppercase, 13px, 3px radius). */
#reset-button,
#cancel-button {
  text-transform: none;
  font-size: 13px;
  border-radius: 3px;
}

/* Column gap matched to Payload's real side-by-side button row
   (.template-minimal__wrap's column-gap: 20px, confirmed from its
   own custom.css) -- Authelia's own default here was gap-4 (16px).

   grid-template-columns forced to 1fr 1fr: confirmed live that
   Authelia's own grid-cols-2 here was resolving to content-sized
   columns (106px 106px, matching the buttons' own text width), not
   stretching to fill the row -- explicit 1fr 1fr matches Payload's
   own .template-minimal__wrap, which sets this explicitly rather
   than relying on a utility default too. */
#reset-password-step1-stage .grid.grid-cols-2:has(#reset-button) {
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}


/* Authelia doesn't render a required-field asterisk on this page's
   own label (confirmed live: plain "Username" text, no "*") -- added
   to match the login page's fields and Payload's own required-field
   convention. Simpler than login's version: this label isn't hidden
   via font-size:0, so the asterisk can just be appended directly. */
#reset-password-step1-stage label[for='username-textfield']::after {
  content: '*';
  font-size: 13px;
  color: rgb(47, 47, 47);
  margin-left: 5px;
}

/* ============================================================
   Toast notifications (data-slot='toast')
   ============================================================
   Confirmed live by actually triggering one (submitting the
   reset-password form): a real Base UI toast, viewport fixed
   top-right, one visible on this deployment ("An email has been
   sent..."). Unscoped -- this component isn't specific to the
   reset-password page, it's Authelia's app-wide notification system
   (also used for login errors, etc.), same as the avatar/header rules
   above.

   Colors sourced from Payload's own real color tokens (
   @payloadcms/ui/dist/scss/colors.scss), matching its banner
   component's info/success/warning/error palette -- not guessed:
   --color-base-100/800 (info/default), --color-success-100/600,
   --color-warning-100/600, --color-error-100/600.

   Authelia's own toast computes its colors via `oklch(from
   var(--toast-accent) ...)` from a single accent variable -- rather
   than fight that derivation, --toast-surface/--toast-ink (the two
   custom properties its own Tailwind classes actually read
   background/text color from) are overridden directly per data-type,
   same technique already proven for --primary/--radius elsewhere in
   this file. */
[data-slot='toast'] {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  font-size: 13px;
  border: 0;
  border-radius: 4px;
  box-shadow: 0 2px 2px -1px #0000001a;
}

[data-slot='toast'][data-type='info'] {
  --toast-surface: rgb(235, 235, 235);
  --toast-ink: rgb(47, 47, 47);
}

[data-slot='toast'][data-type='success'] {
  --toast-surface: rgb(218, 237, 248);
  --toast-ink: rgb(11, 110, 153);
}

[data-slot='toast'][data-type='warning'] {
  --toast-surface: rgb(248, 232, 219);
  --toast-ink: rgb(150, 87, 11);
}

[data-slot='toast'][data-type='error'] {
  --toast-surface: rgb(252, 229, 227);
  --toast-ink: rgb(182, 54, 54);
}
