/* levvr-auth.css
   ============================================================================
   The auth pages' components, reproducing MUI v6.5.0 as the React app renders
   it -- in plain CSS, because IdentityApi is Razor + Bootstrap and has no JS or
   CSS build step.

   Geometry read from @mui/material@6.5.0 source, not from the docs:
     OutlinedInput/OutlinedInput.js   OutlinedInput/NotchedOutline.js
     InputBase/InputBase.js           InputLabel/InputLabel.js
     FormLabel/FormLabel.js           FormHelperText/FormHelperText.js
     FormControl/FormControl.js       Button/Button.js
     ButtonBase/ButtonBase.js         internal/SwitchBase.js
     FormControlLabel/FormControlLabel.js  Alert/Alert.js  Link/Link.js

   App-specific deltas from Frontend/src/theme/components.ts:
     - MuiTextField.defaultProps.variant = 'outlined'
     - MuiOutlinedInput.styleOverrides.input = { ...typography.body2 }
     - MuiOutlinedInput.styleOverrides.notchedOutline.borderColor = steel.A021
     - MuiOutlinedInput focused notchedOutline borderWidth = 1px (not MUI's 2px)
     - MuiFormControl :first-of-type:has(label) margin-top 9px
     - MuiButton.defaultProps.disableElevation = true
     - typography.button.textTransform = 'none'

   This file may only READ --levvr-* from levvr-tokens.css; it defines no values.

   Namespaced .lvr-* rather than reusing .login__* on purpose: .login__title is
   on 12 pages, .login__section on 10, .login__input on 4 (including
   Areas/Management/Pages/Users/Index.cshtml). Redefining those to mean "MUI"
   would silently restyle pages nobody would think to check. The two systems
   coexist until the last .login__* consumer is migrated.

   Requires no JavaScript at all -- not for the floating label, not for the
   notch, not for autofill, not for the error state.
   ============================================================================ */


/* ===========================================================================
   1. Auth shell
   =========================================================================== */

/* One centred column. The design has no split pane and no hero image -- the
   card sits alone on a white page, so there is nothing to hide at the md
   breakpoint and no second flex child to size. */
.lvr-auth {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100%;
  padding: 48px 24px;
  background-color: var(--levvr-surface);

  /* The backdrop the fields sit on. Only consumed by the autofill mask below,
     which needs a known opaque colour, so it has to move in lockstep with the
     background-color above. */
  --lvr-field-backdrop: var(--levvr-surface);

  /* Views/Shared/_Layout.cshtml wraps RenderBody in .container-fluid, which
     adds 15px of horizontal padding. Bootstrap's .row cancels it with negative
     margins and the old markup relied on that; this page uses no Bootstrap
     classes, so it cancels the gutter itself. Remove if the layout ever stops
     using .container-fluid. */
  margin: 0 -15px;
}

.lvr-auth__panel {
  width: 100%;
  max-width: 440px;   /* the Figma frame's own width -- not 400 */
}

/* The mark is a byte-identical copy of Frontend/src/assets/logo.svg. There is
   no shared-asset pipeline between the two apps, so `diff` is what keeps them
   honest -- do not edit the copy in wwwroot. */
.lvr-auth__logo {
  display: block;
  margin: 0 auto 16px;   /* Figma: symbol bottom (86) to title top (102) = 16 */
}

/* h4's size and line-height. Default weight is 400 so Logged out stays
   regular; Welcome opts into 600 with .lvr-auth__title--semibold. */
.lvr-auth__title {
  margin: 0;
  text-align: center;
  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  font-size: var(--levvr-fs-h4);
  line-height: var(--levvr-lh-h4);
  color: var(--levvr-text-primary);
}

.lvr-auth__title--semibold {
  font-weight: var(--levvr-fw-semibold);
}

.lvr-auth__subtitle {
  margin: 16px 0 0;   /* Figma: title bottom (150) to subtitle top (166) = 16 */
  text-align: center;
  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  font-size: var(--levvr-fs-body1);
  line-height: var(--levvr-lh-body1);
  color: var(--levvr-text-secondary);
}

/* LoggedOut.cshtml has no <form> -- its button sits directly in the panel --
   so it needs the vertical-rhythm margin .lvr-auth__form supplies on Login.
   Scoped to a direct child so it cannot match Login's button, which is nested
   one level deeper inside .lvr-auth__form. */
.lvr-auth__panel > .lvr-btn {
  margin-top: calc(var(--levvr-space) * 2);
}

.lvr-auth__form {
  /* 16px below the subtitle, on top of the 9px notch clearance below. */
  margin-top: 16px;

  /* A shrunk outlined label sits at translate(14px, -9px), i.e. 9px above its
     own field's top border -- that overhang is what draws the notch. Nothing
     in the field itself provides that clearance; it comes from whatever
     precedes it. components.ts solves this in the app with
     `MuiFormControl:first-of-type:has(.MuiInputLabel-root) { margin-top: 9px }`.
     We put it on the form instead of on `.lvr-field:first-of-type`, because
     :first-of-type matches on element *type*, not class -- so a preceding
     sibling of the same tag (the error alert, which is also a div) would stop
     it matching and the first label would straddle the heading above it. */
  padding-top: 9px;
}

/* Vertical rhythm. MUI leaves this to the call site; the app uses
   <Stack spacing={2}> = 16px.

   The extra `.lvr-auth` is load-bearing, not decoration. Both components this
   has to space -- `.lvr-field` and `.lvr-btn` -- carry `margin: 0` (faithful to
   MuiFormControl margin='none' and MuiButtonBase), and those are declared later
   in this file. At equal (0,1,0) specificity source order wins, so the plain
   `.lvr-auth__form > * + *` lost to both: the two fields stacked flush against
   each other and the button sat flush under the remember-me row. (0,2,0) wins
   regardless of where the component sections move to. */
.lvr-auth .lvr-auth__form > * + * {
  margin-top: calc(var(--levvr-space) * 2);
}

/* The remember-me / forgot-password row. */
.lvr-auth__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

/* FormControlLabel's own margin-right exists to separate it from a following
   control; in this row `gap` already does that, so drop it rather than paying
   both. The negative margin-left stays -- that is what pulls the checkbox's
   9px icon padding back to the panel's left edge. */
.lvr-auth__row > .lvr-check {
  margin-right: 0;
}


/* ===========================================================================
   2. Text field -- MuiTextField variant='outlined' fullWidth
   =========================================================================== */

/* --- MuiFormControl --- */
.lvr-field {
  /* MUI is inline-flex + `fullWidth` -> width: 100%; flex is equivalent here. */
  display: flex;
  flex-direction: column;
  position: relative;
  width: 100%;
  min-width: 0;
  padding: 0;
  margin: 0;                  /* margin='none' is the default; spacing is explicit */
  border: 0;
  vertical-align: top;
}

/* --- MuiOutlinedInput root --- */
.lvr-field__control {
  position: relative;
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  width: 100%;
  cursor: text;
  border-radius: var(--levvr-radius);
  color: var(--levvr-text-primary);
  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  font-size: var(--levvr-fs-body1);
  line-height: var(--levvr-field-line);
}

/* --- MuiOutlinedInput input ---
   DOM order inside .lvr-field__control is input -> fieldset -> label, so the
   sibling combinators below can reach both from the input's own state. MUI's
   DOM has the label first and drives `shrink` from React state; we have no JS,
   so the order is inverted. <label for> associates regardless of DOM order,
   and the label's containing block is unchanged because MuiFormControl has
   margin: 0, so the control's top edge and the field's top edge coincide. */
.lvr-field__input {
  /* MUST be explicit: site.css has `* { box-sizing: border-box }`, under which
     `height: 1.4375em` becomes the *total* height and the 56px field collapses
     to ~33px with the text clipped. */
  box-sizing: content-box;

  padding: 16.5px 14px;
  height: var(--levvr-field-line);   /* 1.4375em of 16px = 23px */
  /* => 23 + 16.5 + 16.5 = 56px exactly. The outline fieldset is absolutely
     positioned, so its 1px border contributes nothing to layout height. */

  display: block;
  width: 100%;
  min-width: 0;                      /* lets the flex shrink undo the padding overflow */
  margin: 0;
  border: 0;
  border-radius: inherit;
  background: none;
  color: currentColor;

  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  font-size: var(--levvr-fs-body2);  /* the theme's input override: body2 */
  line-height: var(--levvr-lh-body2);
  letter-spacing: normal;            /* see the note in levvr-tokens.css */

  -webkit-tap-highlight-color: transparent;
}

.lvr-field__input:focus {
  outline: 0;
  /* site.css has a naked `input:focus { background: rgba(13,6,40,0.04) }` that
     would tint the field grey on focus. Our (0,2,0) beats its (0,1,1), but
     only because this line exists. */
  background-color: transparent;
}

/* Firefox's red required/invalid glow (MUI does the same). */
.lvr-field__input:invalid {
  box-shadow: none;
}

/* --- MuiOutlinedInput notchedOutline ---
   A real <fieldset><legend>, as MUI does it, rather than a background-coloured
   chip covering the border. The fieldset *removes* border where the label goes
   instead of painting over it, so it is correct over a flat colour, a card, a
   gradient or the background image alike -- and it is the same geometry, so it
   cannot end up close-but-1px-off. Cost is that the label text appears twice:
   visibly in <label>, and invisibly in <legend><span>, which exists only to
   size the gap. Login.cshtml renders both from DisplayNameFor so they cannot
   drift. */
.lvr-field__outline {
  position: absolute;
  inset: -5px 0 0 0;
  margin: 0;
  padding: 0 8px;
  pointer-events: none;
  overflow: hidden;
  min-width: 0%;                 /* MUI's literal value -- keep the % */
  text-align: left;
  border-radius: inherit;

  /* Longhands rather than the `border` shorthand, so the state rules below can
     change only the colour. Also overrides Bootstrap's `fieldset { border: 0 }`. */
  border-style: solid;
  border-width: 1px;
  border-color: var(--levvr-outline);

  transition: border-color var(--levvr-dur-shortest) var(--levvr-ease-in-out);
}

.lvr-field__outline > legend {
  /* Every declaration here except max-width and transition exists to beat
     Bootstrap's legend reset (display:block; width:100%; max-width:100%;
     margin-bottom:.5rem; font-size:1.5rem; line-height:inherit;
     white-space:normal). If max-width:100% leaks through, the notch is
     permanently open on every field and reads as a broken border rather than
     as a CSS bug. MUI's own source carries `float: 'unset'` and
     `width: 'auto'` with the comment "Fix conflict with bootstrap". */
  float: unset;
  display: block;
  width: auto;
  max-width: 0.01px;
  height: 11px;
  padding: 0;
  margin: 0;
  overflow: hidden;
  visibility: hidden;
  white-space: nowrap;
  font-size: 0.75em;             /* of .lvr-field__control's body1 -> 13.71px */
  line-height: inherit;
  color: inherit;
  transition: max-width 50ms var(--levvr-ease-out);
}

.lvr-field__outline > legend > span {
  display: inline-block;
  padding-left: 5px;
  padding-right: 5px;
  opacity: 0;
  visibility: visible;           /* re-shown so it still takes up width */
}

/* --- MuiInputLabel, outlined --- */
.lvr-field__label {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  pointer-events: none;
  transform-origin: top left;
  transform: translate(14px, 16px) scale(1);
  max-width: calc(100% - 24px);
  padding: 0;
  margin: 0;                     /* Bootstrap gives label a margin-bottom */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;

  color: var(--levvr-text-secondary);
  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  font-size: var(--levvr-fs-body1);   /* body1, NOT body2 -- 18.29px */
  line-height: var(--levvr-field-line);

  transition:
    color var(--levvr-dur-shorter) var(--levvr-ease-out),
    transform var(--levvr-dur-shorter) var(--levvr-ease-out),
    max-width var(--levvr-dur-shorter) var(--levvr-ease-out);
}

/* --- Shrink the label and open the notch ---
   Three triggers: focus, a non-empty value, and autofill. They MUST stay in
   separate rules. A single unrecognised selector invalidates the entire comma
   list it appears in, so grouping :autofill with :focus would silently drop
   label-floating altogether on engines that don't know :autofill
   (Chrome < 110, Firefox < 86) -- a failure with no error and no symptom until
   someone actually uses a password manager.

   `:not(:placeholder-shown)` needs a non-empty placeholder, hence the
   placeholder=" " in the markup. Per the accessible-name computation
   <label for> outranks placeholder, so a whitespace placeholder never
   contributes to the accessible name and is not announced. Do NOT put real
   placeholder text there: MUI hides its placeholder behind React's
   `data-shrink`, which we have no equivalent for, so the text would show
   underneath the resting label.

   :-webkit-autofill is what makes Chrome's autofill *preview* work -- Chrome
   maps it onto -internal-autofill-previewed as well as -selected, so the label
   floats while the user is still hovering the suggestion. MUI needs a JS
   animationstart listener to detect the same thing. */
.lvr-field__input:focus ~ .lvr-field__label,
.lvr-field__input:not(:placeholder-shown) ~ .lvr-field__label {
  transform: translate(14px, -9px) scale(0.75);
  max-width: calc(133% - 32px);
  user-select: none;
  pointer-events: auto;
}

.lvr-field__input:autofill ~ .lvr-field__label {
  transform: translate(14px, -9px) scale(0.75);
  max-width: calc(133% - 32px);
}

.lvr-field__input:-webkit-autofill ~ .lvr-field__label {
  transform: translate(14px, -9px) scale(0.75);
  max-width: calc(133% - 32px);
}

.lvr-field__input:focus ~ .lvr-field__outline > legend,
.lvr-field__input:not(:placeholder-shown) ~ .lvr-field__outline > legend {
  max-width: 100%;
  transition: max-width 100ms var(--levvr-ease-out) 50ms;
}

.lvr-field__input:autofill ~ .lvr-field__outline > legend {
  max-width: 100%;
}

.lvr-field__input:-webkit-autofill ~ .lvr-field__outline > legend {
  max-width: 100%;
}

/* --- Hover and focus --- */
.lvr-field__control:hover .lvr-field__outline {
  /* MUI hovers to text.primary -- near-black, and much stronger than the
     resting steel.A021. Faithful. */
  border-color: var(--levvr-text-primary);
}

@media (hover: none) {
  /* On touch, MUI resets to its own hard-coded rgba(0,0,0,0.23) rather than to
     the themed steel.A021. Faithful quirk. */
  .lvr-field__control:hover .lvr-field__outline {
    border-color: rgba(0, 0, 0, 0.23);
  }
}

.lvr-field__input:focus ~ .lvr-field__outline {   /* (0,3,0) beats hover's (0,2,0) */
  border-color: var(--levvr-primary);
  border-width: 1px;                              /* the theme forces 1px; MUI's default is 2px */
}

.lvr-field__input:focus ~ .lvr-field__label {
  color: var(--levvr-primary);
}

/* --- MuiFormHelperText, contained --- */
.lvr-field__helper {
  display: block;
  margin: 3px 14px 0;
  text-align: left;
  color: var(--levvr-text-secondary);
  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  font-size: var(--levvr-fs-caption);
  line-height: var(--levvr-lh-caption);
}

/* asp-validation-for always renders the span; it is empty while the field is
   valid, and jquery-validation-unobtrusive empties it again on re-validation.
   Without this, the 3px margin-top puts a permanent 3px of dead space under
   every field. */
.lvr-field__helper:empty {
  display: none;
}

/* --- Disabled --- */
.lvr-field__input:disabled {
  -webkit-text-fill-color: var(--levvr-text-disabled);
  opacity: 1;
}

.lvr-field__input:disabled ~ .lvr-field__outline {
  border-color: var(--levvr-text-disabled);
}

.lvr-field__input:disabled ~ .lvr-field__label {
  color: var(--levvr-text-disabled);
}

/* --- Autofill background ---
   DELIBERATE DEVIATION: MUI leaves Chrome's yellow autofill fill alone in
   light mode. On a login page autofill is the common path, not an edge case,
   so mask it with the field's own backdrop. This is why --lvr-field-backdrop
   exists on .lvr-auth: the mask needs a known opaque colour, so it must be
   changed in lockstep with the panel background. */
.lvr-field__input:-webkit-autofill,
.lvr-field__input:-webkit-autofill:hover,
.lvr-field__input:-webkit-autofill:focus {
  border-radius: inherit;
  -webkit-box-shadow: 0 0 0 100px var(--lvr-field-backdrop) inset;
  box-shadow: 0 0 0 100px var(--lvr-field-backdrop) inset;
  -webkit-text-fill-color: var(--levvr-text-primary);
  caret-color: var(--levvr-text-primary);
}


/* ===========================================================================
   3. Button -- MuiButton variant='contained' color='primary' disableElevation
   =========================================================================== */

.lvr-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  box-sizing: border-box;
  min-width: 64px;
  padding: 6px 16px;                   /* medium; line-height 28px => 40px tall */
  margin: 0;
  border: 0;
  border-radius: var(--levvr-radius);  /* 4px. NOT the old 25px/100px pill. */
  outline: 0;
  background-color: transparent;
  -webkit-appearance: none;
  cursor: pointer;
  user-select: none;
  vertical-align: middle;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;

  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-medium);
  font-size: var(--levvr-fs-button);
  line-height: var(--levvr-lh-button);
  letter-spacing: normal;
  text-transform: none;                /* typography.button.textTransform */
  box-shadow: none;                    /* disableElevation: true */

  transition:
    background-color var(--levvr-dur-short) var(--levvr-ease-in-out),
    box-shadow var(--levvr-dur-short) var(--levvr-ease-in-out),
    border-color var(--levvr-dur-short) var(--levvr-ease-in-out),
    color var(--levvr-dur-short) var(--levvr-ease-in-out);
}

.lvr-btn--contained {
  background-color: var(--levvr-primary);
  color: var(--levvr-primary-contrast);
}

@media (hover: hover) {
  /* `color` is repeated here, not just on the base rule, because
     LoggedOut.cshtml's button is an <a> (Login's is a <button>) and
     Bootstrap's `a:hover { color }` -- (0,1,1) -- outranks the base
     `.lvr-btn--contained` rule's (0,1,0) color. This rule is (0,2,0), so it
     wins regardless of element type and keeps MUI's actual hover behaviour:
     background darkens, contrastText stays put. */
  .lvr-btn--contained:hover {
    background-color: var(--levvr-primary-dark);
    color: var(--levvr-primary-contrast);
    text-decoration: none;
    box-shadow: none;
  }
}

.lvr-btn--contained:disabled {
  color: var(--levvr-text-disabled);
  background-color: var(--levvr-divider);   /* action.disabledBackground */
  box-shadow: none;
  cursor: default;
  pointer-events: none;
}

.lvr-btn--full {
  width: 100%;
}

/* DELIBERATE ADDITION: disableElevation removes MuiButton's only focus
   affordance (its Mui-focusVisible box-shadow) and ButtonBase sets outline: 0,
   so the app's buttons currently have no visible keyboard focus state at all.
   Not acceptable on a login form. */
.lvr-btn:focus-visible {
  outline: 2px solid var(--levvr-primary);
  outline-offset: 2px;
}


/* ===========================================================================
   4. Checkbox -- MuiCheckbox color='primary' inside MuiFormControlLabel
   =========================================================================== */

.lvr-check {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  vertical-align: middle;
  /* FormControlLabel: margin-left -11 pulls the 9px icon padding back to the
     text baseline; margin-right 16 separates it from what follows. */
  margin: 0 16px 0 -11px;
  -webkit-tap-highlight-color: transparent;
}

.lvr-check__box {
  position: relative;             /* containing block for the hidden input */
  display: inline-flex;
  flex-shrink: 0;
  padding: 9px;                   /* SwitchBase */
  border-radius: 50%;
  color: var(--levvr-text-secondary);
  transition: background-color var(--levvr-dur-shortest) var(--levvr-ease-in-out);
}

@media (hover: hover) {
  .lvr-check:hover .lvr-check__box {
    background-color: var(--levvr-primary-a004);
  }
}

.lvr-check__input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: inherit;
  z-index: 1;
}

.lvr-check__icon {
  width: var(--levvr-icon-medium);
  height: var(--levvr-icon-medium);
  fill: currentColor;
  display: block;
  flex-shrink: 0;
  user-select: none;
}

/* Two stacked icons swapped by :checked, mirroring MuiCheckbox's icon /
   checkedIcon pair. Sibling combinators only -- no :has() needed, so the
   checked state works on every engine that renders the rest of this file. */
.lvr-check__icon--on {
  display: none;
}

.lvr-check__input:checked ~ .lvr-check__icon--off {
  display: none;
}

.lvr-check__input:checked ~ .lvr-check__icon--on {
  display: block;
  color: var(--levvr-primary);
}

/* DELIBERATE ADDITION, same reasoning as the button. */
.lvr-check__input:focus-visible ~ .lvr-check__icon {
  outline: 2px solid var(--levvr-primary);
  outline-offset: 2px;
  border-radius: 2px;
}

.lvr-check__label {
  margin: 0;
  padding: 0;
  cursor: inherit;
  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  /* body2, not body1 -- matches the size of the text actually typed into the
     fields above it (.lvr-field__input is body2 too), rather than the
     label's own resting size. */
  font-size: var(--levvr-fs-body2);
  line-height: var(--levvr-lh-body2);
  color: var(--levvr-text-primary);
}


/* ===========================================================================
   5. Alert -- MuiAlert severity='error' variant='standard'
   =========================================================================== */

.lvr-alert {
  display: flex;
  /* Figma sizes this instance at 320/centered, but that leaves its edges
     misaligned with the full-width fields below it -- matching the fields
     wins over matching that one Figma measurement literally. */
  padding: 6px 16px;
  border-radius: var(--levvr-radius);
  box-shadow: none;                    /* elevation 0 */
  font-family: var(--levvr-font-family);
  font-weight: var(--levvr-fw-regular);
  font-size: var(--levvr-fs-body2);
  line-height: var(--levvr-lh-body2);
}

.lvr-alert--error {
  color: var(--levvr-error-alert-fg);
  background-color: var(--levvr-error-alert-bg);
}

.lvr-alert__icon {
  display: flex;
  margin-right: 12px;
  padding: 7px 0;
  opacity: 0.9;
  color: var(--levvr-error);            /* the icon keeps error.main, not the darkened text */
}

.lvr-alert__icon svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
}

.lvr-alert__content {
  padding: 8px 0;
  min-width: 0;
}

/* MuiAlertTitle: body1 at weight 500, with MUI's own -2px/4px nudges. */
.lvr-alert__title {
  margin-top: -2px;
  margin-bottom: 4px;
  font-size: var(--levvr-fs-body1);
  line-height: var(--levvr-lh-body1);
  font-weight: var(--levvr-fw-medium);
}

.lvr-alert__message {
  min-width: 0;
}

/* asp-validation-summary renders a <ul><li>. MUI's Alert has no list, so strip
   the bullets and let the message read as prose. */
.lvr-alert__message ul {
  list-style: none;
  margin: 0;
  padding: 0;
}


/* ===========================================================================
   6. Link -- MuiLink underline='always' (the theme has no MuiLink override)
   =========================================================================== */

.lvr-link {
  color: var(--levvr-primary);
  text-decoration: underline;
  text-decoration-color: rgba(67, 97, 238, 0.4);   /* alpha(primary.main, 0.4) */
  font-family: var(--levvr-font-family);
  font-size: var(--levvr-fs-body2);
  line-height: var(--levvr-lh-body2);
}

.lvr-link:hover {
  text-decoration-color: inherit;
}

.lvr-link:focus-visible {
  outline: 2px solid var(--levvr-primary);
  outline-offset: 2px;
  border-radius: 2px;
}


/* ===========================================================================
   7. Error state -- MUST stay last
   ===========================================================================
   ASP.NET adds `input-validation-error` to the input (server-side via
   HtmlHelper.ValidationInputCssClassName, and client-side via
   jquery-validation-unobtrusive) and `field-validation-error` to the message
   span.

   These are (0,3,0) -- exactly equal to the :focus rules in section 2 -- so
   source order is what makes error win over focus. That is also how MUI
   resolves it: its error variant is declared after its colour variants. Moving
   this block earlier in the file makes an errored field turn blue on focus. */

.lvr-field__input.input-validation-error ~ .lvr-field__outline {
  border-color: var(--levvr-error);
}

.lvr-field__input.input-validation-error ~ .lvr-field__label {
  color: var(--levvr-error);
}

.lvr-field__helper.field-validation-error {
  color: var(--levvr-error);
}


/* ===========================================================================
   8. Reduced motion -- MUI ships no such guard; deliberate improvement
   =========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .lvr-field__label,
  .lvr-field__outline,
  .lvr-field__outline > legend,
  .lvr-check__box,
  .lvr-btn {
    transition: none;
  }
}
