/* ============================================================
   File:        users.css
   Project:     StudioFlow (Grace Aerobics & Fitness Center)
   Developer:   Janvi Vakhariya — V Techno Labs
   Created:     2026-09-01  (updated 2026-09-07)
   Purpose:     Design system for Manage Users — four screens, one family:
                1) Users list  2) Add User  3) Edit User  4) Reset Password.
                ONE list pattern (.sf-user-person) and ONE form pattern
                (.sf-user-form / .sf-user-field) shared by screens 2-4.
   Copyright:   © 2026 V Techno Labs. All rights reserved.
                Proprietary software developed by V Techno Labs.
   ============================================================

   Same "Sunset" language as the other final screens: sunset wash ground,
   white glass cards with soft pink shadows, 20px radius, Archivo, the wing
   gradient as a thin ribbon. A small, calm settings area.

   Prefix: sf-user-, and nothing else. Never sf-dash- / sf-idash- / sf-dev-,
   so this module and the two dashboards and Manage Devices cannot reach
   each other's rules. The only non-prefixed selectors below are (a) the
   .sf-app shell overrides and (b) the two classes site.js injects for the
   password eye, both scoped so they cannot leak — see notes 3 and 5.

   Seven things this file does differently from the supplied design, all of
   them because it now lives inside the StudioFlow app shell:

   1. This sheet paints NO page background. The design pointed one at
      /img/stripes.jpeg and this file had it switched off, which is how
      Manage Users ended up the screen with no ground at all while Plans had
      a tiled one. The ground is now declared once, in site.css, and every
      signed-in screen takes it. To change it, change that one line there --
      not this file.

   2. The bar variables are bound to the shell's real bar heights
      (--appbar-h 56px, --tabbar-h 64px, from site.css :root) and then
      zeroed inside .sf-app, which already pads the body past both fixed
      bars. Reserving the space again would leave a second bar's worth of
      gap.

   3. The ground is painted by a fixed backdrop behind the whole page
      rather than as a block behind the column, so the wash reaches the
      screen edges instead of stopping at the 640px content column.

   4. container-type: inline-size is not declared. The design set it, but
      no @container query in this file reads it, and containment would make
      .sf-user the containing block for the fixed backdrop in note 3.

   5. The password eye is drawn by the shared toggle in site.js, which
      wraps the input in .sf-input-wrap and appends a .sf-eye button. Those
      two get the design's .sf-user-pw / .sf-user-peek treatment here,
      scoped under .sf-user-form. Restyling them beats rewriting the
      script: the same toggle serves Login and Change Password too.

   6. .sf-user-check is an addition. Edit User carries the "Account active"
      checkbox, which is a guard rail the app has and the design's four
      screens do not show, so it needed a pattern in this language.

   7. .sf-user-alert and .sf-user-error are additions for the validation
      summary and the per-field messages the Razor tag helpers emit. The
      design has no error state; a form that cannot show one is not
      finished.

   The footer here is the rainbow rule only. The tagline and the credit
   under it come from the shared _SiteFooter partial the layout already
   renders, so the design's .sf-user-foot-tag / -credit rules are left out —
   keeping them would say "Music on. Chaos off." twice on one screen.

   Icons: every .sf-user-ico is a 20×20 slot for the app's own SVGs
   (16×16 chevrons via .sf-user-go, a 12×12 padlock via .sf-user-lock).
   currentColor applies. Archivo 400/600/700/800 is loaded once by
   _PwaHead, not here.
   ============================================================ */

.sf-user {
  /* NO PAGE BACKGROUND IMAGE HERE. site.css declares the one background the
     whole signed-in app uses, on .sf-frame. A second photo in this sheet is
     how the app ended up with a different ground on every screen. */
  --sf-user-wing: linear-gradient(90deg,#43a047,#d4b91e,#f57c00,#e53957,#c2185b,#7e57c2,#5c6f91);

  /* The wash alone now. This sheet was the OTHER half of the inconsistency:
     its photo slot was set to none, so Manage Users was the screen with no
     ground at all while Plans had a tiled one. Both take the shared one. */
  --sf-user-ground:
    linear-gradient(178deg, rgba(255,250,250,.5) 0%, rgba(255,246,240,.42) 40%, rgba(250,244,252,.48) 100%);
  /* Muted deepened from #6d6b58, which measured 4.05:1 against the darkest
     part of the shared ball-pit ground -- under the 4.5:1 minimum for any
     muted line that sits on the ground rather than inside a card. #615F4E
     measures 4.85:1 there and 6.45:1 on white. Deepening the ink was the fix,
     not a panel behind the text. */
  --sf-user-ink: #2b2a1f; --sf-user-muted: #615F4E;
  --sf-user-pink: #c2185b; --sf-user-pink-deep: #98123f;
  --sf-user-card: #ffffff;   /* solid: the scrim is the only translucency */ --sf-user-edge: rgba(255,255,255,.92);
  --sf-user-line: rgba(43,42,31,.12);
  --sf-user-good: #1d7a3f; --sf-user-good-tint: #e3f3e8;
  --sf-user-warn: #9a5b00; --sf-user-warn-tint: #fdf0d7;
  --sf-user-bad: #b3261e;  --sf-user-bad-deep: #8c1d17; --sf-user-bad-tint: #fdecea;
  --sf-user-admin: #c2185b;  --sf-user-admin-tint: #fce8f0;   /* role chips */
  --sf-user-instr: #0f766e;  --sf-user-instr-tint: #e0f2f0;
  --sf-user-support: #6d28d9; --sf-user-support-tint: #f0e9fc;
  --sf-user-radius: 20px; --sf-user-tap: 48px;

  /* The shell's real fixed bars, read from site.css :root. The fallbacks are
     the same 56/64 the design shipped with, so a standalone use of .sf-user
     outside the shell still clears them. Zeroed below — see note 2. */
  --sf-user-top-bar: var(--appbar-h, 56px); --sf-user-bottom-bar: var(--tabbar-h, 64px);

  box-sizing: border-box; max-width: 640px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 16px;
  padding: calc(var(--sf-user-top-bar) + 14px) 16px calc(var(--sf-user-bottom-bar) + 26px + env(safe-area-inset-bottom, 0px));
  background: var(--sf-user-ground);
  color: var(--sf-user-ink);
  font-family: "Archivo", system-ui, sans-serif; font-size: 15px; line-height: 1.5;
  -webkit-tap-highlight-color: transparent;
}

/* Inside the app shell the layout has already done the spacing: .sf-app pads
   the body past both fixed bars, and .sf-content supplies the 1rem side gutter
   and caps the column at 640px. Repeating either would double it. */
.sf-app .sf-user {
  --sf-user-top-bar: 0px;
  --sf-user-bottom-bar: 0px;
  padding-left: 0; padding-right: 0;
  background: transparent;
}

/* The sunset wash, painted across the whole viewport rather than behind the
   column (note 3). Fixed and out of flow, so it is not a flex item and does
   not scroll away on a long list. It sits above the body's grey and below
   every card; the app bar and tab bar are fixed at z-index 20 with their own
   navy, so neither is touched. */
/* No page backdrop here any more. site.css paints ONE background on .sf-app for
   every signed-in page, so this sheet no longer paints its own: four stylesheets
   each drawing their own ground is exactly how Plans ended up tiled while Users
   ended up plain. The --sf-user-ground variable above is kept for the standalone,
   outside-the-shell case documented at the top of this file. */

.sf-user *, .sf-user *::before, .sf-user *::after { box-sizing: border-box; }
:where(.sf-user a) { color: inherit; text-decoration: none; }
.sf-user :focus-visible { outline: 2px solid var(--sf-user-pink); outline-offset: 2px; }
.sf-user-ico { display: inline-block; width: 20px; height: 20px; flex: none; }
.sf-user-go { display: inline-block; width: 16px; height: 16px; flex: none; opacity: .7; }

/* ---------- shared: back link, page intro, card shell ---------- */
.sf-user-back {
  display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
  min-height: 44px; margin: -6px 0 -10px;
  font-size: 14px; font-weight: 800; color: var(--sf-user-pink);
}
.sf-user-back:active { text-decoration: underline; text-underline-offset: 3px; }
.sf-user-back .sf-user-go { transform: rotate(180deg); opacity: 1; }

.sf-user-intro { margin: 0 2px; }
.sf-user-title { margin: 0; font-size: 22px; font-weight: 800; letter-spacing: -.01em; }
.sf-user-sub { margin: 2px 0 0; font-size: 14px; color: var(--sf-user-muted); text-wrap: pretty; }
.sf-user-sub strong { color: var(--sf-user-ink); font-weight: 700; }

.sf-user-card {
  background: var(--sf-user-card);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border: 1.5px solid var(--sf-user-edge);
  border-radius: var(--sf-user-radius);
  box-shadow: 0 14px 30px -16px rgba(194,24,91,.4);
  padding: 16px; position: relative; overflow: hidden;
}
.sf-user-card--ribbon::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 5px; background: var(--sf-user-wing); }

/* ============================================================
   LIST PATTERN — .sf-user-person
   One card per account: avatar, name, @username, chips, then a
   quiet action row. Small numbers, big targets.
   ============================================================ */
.sf-user-list { display: flex; flex-direction: column; gap: 12px; }

.sf-user-person {
  background: var(--sf-user-card);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border: 1.5px solid var(--sf-user-edge);
  border-radius: var(--sf-user-radius);
  box-shadow: 0 14px 30px -16px rgba(194,24,91,.4);
  padding: 14px 16px 10px;
}
.sf-user-person-top { display: flex; align-items: center; gap: 12px; }

.sf-user-avatar {
  flex: none; display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: linear-gradient(155deg, #e0447a, #98123f);
  color: #fff; font-size: 17px; font-weight: 800; text-transform: uppercase;
  border: 2px solid rgba(255,255,255,.6);
  box-shadow: 0 6px 14px -7px rgba(20,10,35,.5);
  user-select: none;
}
/* feather rotation for variety; --you and --support override below */
.sf-user-person:nth-of-type(3n+2) .sf-user-avatar { background: linear-gradient(155deg, #1fb3a4, #0b6f64); }
.sf-user-person:nth-of-type(3n)   .sf-user-avatar { background: linear-gradient(155deg, #f99b2d, #d06a00); }

.sf-user-person-id { flex: 1; min-width: 0; }
.sf-user-person-name { margin: 0; display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 16px; font-weight: 800; text-transform: capitalize; }
.sf-user-person-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sf-user-person-handle { margin: 0; font-size: 13px; color: var(--sf-user-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* status pill, top right */
.sf-user-status { flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: 26px; padding: 0 10px; border-radius: 999px; font-size: 12px; font-weight: 800; white-space: nowrap; }
.sf-user-status--active { background: var(--sf-user-good-tint); color: var(--sf-user-good); }
.sf-user-status--inactive { background: rgba(43,42,31,.08); color: var(--sf-user-muted); }

/* chips row: role + extras */
.sf-user-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 0 0; }
.sf-user-chip { display: inline-flex; align-items: center; gap: 5px; min-height: 24px; padding: 0 9px; border-radius: 999px; font-size: 11.5px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; white-space: nowrap; }
.sf-user-chip--admin { background: var(--sf-user-admin-tint); color: var(--sf-user-admin); }
.sf-user-chip--instr { background: var(--sf-user-instr-tint); color: var(--sf-user-instr); }
.sf-user-chip--support { background: var(--sf-user-support-tint); color: var(--sf-user-support); }
.sf-user-chip--you { background: var(--sf-user-ink); color: #fff; }
.sf-user-mobile { font-size: 13px; color: var(--sf-user-muted); font-variant-numeric: tabular-nums; }

/* action row: quiet, equal targets, ruled off from the identity */
.sf-user-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; padding: 10px 0 6px; border-top: 1px solid var(--sf-user-line); }
.sf-user-act {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 0 14px; border-radius: 12px; cursor: pointer;
  border: 1.5px solid var(--sf-user-line); background: transparent;
  color: var(--sf-user-ink); font-family: inherit; font-size: 13.5px; font-weight: 800; white-space: nowrap;
}
.sf-user-act:active { background: rgba(43,42,31,.06); }
/* sensitive actions carry their colour but stay outline until pressed */
.sf-user-act--reset { border-color: rgba(194,24,91,.35); color: var(--sf-user-pink); }
.sf-user-act--reset:active { background: var(--sf-user-admin-tint); }
.sf-user-act--off { border-color: rgba(154,91,0,.4); color: var(--sf-user-warn); }
.sf-user-act--off:active { background: var(--sf-user-warn-tint); }
.sf-user-act--on { border-color: rgba(29,122,63,.4); color: var(--sf-user-good); }
.sf-user-act--on:active { background: var(--sf-user-good-tint); }

/* An action the server would refuse: your own account, the support account,
   the last active admin. Shown flat and unclickable rather than hidden, so
   the row still says what exists, and its title says why it is off. */
.sf-user-act--blocked {
  border-color: transparent; background: rgba(43,42,31,.06);
  color: var(--sf-user-muted); cursor: default;
}

/* Deactivate/Activate is a POST, so its button arrives wrapped in a form that
   carries the antiforgery token. The form is the flex item and shrinks to the
   button inside it, so the row still reads as three equal targets. */
.sf-user-actform { margin: 0; display: inline-flex; }

/* the support account: visibly different, protected */
.sf-user-person--support { background: linear-gradient(0deg, rgba(109,40,217,.06), rgba(109,40,217,.06)), var(--sf-user-card); border-color: rgba(109,40,217,.28); }
.sf-user-person--support .sf-user-avatar { background: linear-gradient(155deg, #9d76e8, #5f3aad); }
.sf-user-protected { display: flex; align-items: center; gap: 6px; margin-top: 12px; padding: 10px 0 6px; border-top: 1px solid rgba(109,40,217,.18); font-size: 12.5px; font-weight: 600; color: var(--sf-user-support); }

/* Arrived here from a "Deactivate X instead" link on Manage Devices: the row
   asked for by #user-<id> lights up, so the admin does not have to re-find the
   person they were already looking at. Scroll-margin keeps it clear of the
   fixed app bar. */
.sf-user-person:target {
  border-color: var(--sf-user-pink);
  box-shadow: 0 0 0 3px rgba(194,24,91,.18), 0 14px 30px -16px rgba(194,24,91,.4);
  scroll-margin-top: calc(var(--appbar-h, 56px) + 12px);
}

/* inactive accounts: dimmed card */
.sf-user-person--inactive { opacity: .72; }
.sf-user-person--inactive .sf-user-avatar { filter: grayscale(1); }

/* Reveal row for the inactive accounts. The design used a native <details>;
   the app's list is filtered server-side by ?showInactive=true, so this is a
   link wearing the same clothes. .sf-user-reveal-btn is the button face and
   --open is what [open] was: the chevron turns and a gap opens below. */
.sf-user-reveal-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; border-radius: 12px;
  border: 1.5px dashed rgba(43,42,31,.25);
  color: var(--sf-user-muted); font-size: 13.5px; font-weight: 800;
}
.sf-user-reveal-btn:active { background: rgba(43,42,31,.05); }
.sf-user-reveal-btn--open .sf-user-go { transform: rotate(90deg); }

/* add user — the list's one loud action */
.sf-user-add {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 52px; border: 0; border-radius: 16px; cursor: pointer;
  background: linear-gradient(155deg, #e0447a, var(--sf-user-pink-deep));
  color: #fff; font-family: inherit; font-size: 15px; font-weight: 800;
  box-shadow: 0 12px 24px -12px rgba(194,24,91,.7);
}
.sf-user-add:active { transform: translateY(1px); filter: brightness(.95); }

/* quiet cross-link (e.g. Manage Devices) */
.sf-user-crosslink {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--sf-user-tap); border-radius: 14px;
  border: 1.5px solid var(--sf-user-edge); background: var(--sf-user-card);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  font-size: 14px; font-weight: 700; color: var(--sf-user-ink);
}
.sf-user-crosslink:active { filter: brightness(.96); }

/* ============================================================
   FORM PATTERN — .sf-user-form
   Screens 2, 3, 4 are the same card: who/what up top, fields,
   one primary action, cancel below the card.
   ============================================================ */
.sf-user-form { display: flex; flex-direction: column; gap: 14px; }

.sf-user-field { display: flex; flex-direction: column; gap: 6px; }
.sf-user-label { font-size: 13px; font-weight: 800; letter-spacing: .02em; }
.sf-user-label small { font-weight: 600; color: var(--sf-user-muted); }

.sf-user-input {
  width: 100%; min-height: 52px; padding: 0 14px;
  border: 1.5px solid rgba(43,42,31,.2); border-radius: 14px;
  background: #fff; color: var(--sf-user-ink);
  font-family: inherit; font-size: 16px; font-weight: 600;
}
.sf-user-input::placeholder { color: rgba(43,42,31,.35); font-weight: 400; }
.sf-user-input:focus { border-color: var(--sf-user-pink); outline: none; box-shadow: 0 0 0 3px rgba(194,24,91,.15); }

.sf-user-hint { margin: 0; font-size: 12.5px; color: var(--sf-user-muted); text-wrap: pretty; }

/* Password field: input + eye toggle in one wrap. .sf-input-wrap and .sf-eye
   are what site.js injects around any input carrying .js-password (note 5);
   they are matched here only inside .sf-user-form, so Login and Change
   Password keep the shell's own version untouched. */
.sf-user-pw,
.sf-user-form .sf-input-wrap { position: relative; display: block; }
.sf-user-pw .sf-user-input,
.sf-user-form .sf-input-wrap .sf-user-input { padding-right: 52px; }
.sf-user-peek,
.sf-user-form .sf-eye {
  position: absolute; top: 50%; right: 4px; transform: translateY(-50%);
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; background: transparent; border-radius: 12px; cursor: pointer;
  color: var(--sf-user-muted);
}
.sf-user-peek:active,
.sf-user-form .sf-eye:active { background: rgba(43,42,31,.07); }
.sf-user-peek.is-on { color: var(--sf-user-pink); }   /* app toggles .is-on with input type */
/* the script marks the revealed state with aria-pressed, so the eye can go
   pink at exactly the moment the password is on screen */
.sf-user-form .sf-eye[aria-pressed="true"] { color: var(--sf-user-pink); }
.sf-user-form .sf-eye svg { width: 20px; height: 20px; display: block; }

/* the fixed username on Edit — visibly locked, not silently disabled */
.sf-user-fixed {
  display: flex; align-items: center; gap: 10px;
  min-height: 52px; padding: 0 14px;
  border: 1.5px dashed rgba(43,42,31,.25); border-radius: 14px;
  background: rgba(43,42,31,.05); color: var(--sf-user-muted);
  font-size: 16px; font-weight: 700;
}
.sf-user-fixed strong { color: var(--sf-user-ink); font-weight: 800; }
.sf-user-lock { display: inline-grid; place-items: center; margin-left: auto; width: 24px; height: 24px; border-radius: 7px; background: rgba(43,42,31,.08); }
.sf-user-lock .sf-user-ico { width: 12px; height: 12px; }

/* role picker: two big radio tiles, one thumb each */
.sf-user-roles { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }
.sf-user-role { position: relative; display: block; min-width: 0; }
.sf-user-role input { position: absolute; opacity: 0; inset: 0; pointer-events: none; }
.sf-user-role-card {
  display: flex; flex-direction: column; gap: 2px;
  min-height: 64px; padding: 10px 12px; border-radius: 14px; cursor: pointer;
  border: 1.5px solid rgba(43,42,31,.2); background: #fff;
}
.sf-user-role-name { font-size: 15px; font-weight: 800; }
.sf-user-role-desc { font-size: 12px; color: var(--sf-user-muted); }
.sf-user-role input:checked + .sf-user-role-card { border-color: var(--sf-user-pink); background: var(--sf-user-admin-tint); box-shadow: 0 0 0 3px rgba(194,24,91,.15); }
.sf-user-role input:checked + .sf-user-role-card .sf-user-role-name { color: var(--sf-user-pink); }
.sf-user-role input:focus-visible + .sf-user-role-card { outline: 2px solid var(--sf-user-pink); outline-offset: 2px; }

/* The "Account active" tick on Edit User (note 6). A row, not a bare box:
   the whole thing is the tap target, and the consequence is spelled out
   underneath rather than left to the label. */
.sf-user-check {
  display: flex; align-items: center; gap: 12px;
  min-height: var(--sf-user-tap); padding: 8px 14px;
  border: 1.5px solid rgba(43,42,31,.2); border-radius: 14px;
  background: #fff; cursor: pointer;
  font-size: 15px; font-weight: 700;
}
.sf-user-check-box { flex: none; width: 22px; height: 22px; accent-color: var(--sf-user-pink); cursor: pointer; }
.sf-user-check:has(.sf-user-check-box:checked) { border-color: var(--sf-user-pink); background: var(--sf-user-admin-tint); }

/* who this form is about (Edit / Reset) — unmistakable */
.sf-user-whom {
  display: flex; align-items: center; gap: 12px;
  padding: 12px; border-radius: 16px;
  background: var(--sf-user-admin-tint);
  border: 1.5px solid rgba(194,24,91,.25);
}
.sf-user-whom .sf-user-avatar { width: 40px; height: 40px; font-size: 15px; }
.sf-user-whom-name { margin: 0; font-size: 15px; font-weight: 800; text-transform: capitalize; }
.sf-user-whom-sub { margin: 0; font-size: 13px; color: var(--sf-user-muted); }

/* primary + cancel */
.sf-user-submit {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 52px; margin-top: 2px;
  border: 0; border-radius: 16px; cursor: pointer;
  background: linear-gradient(155deg, #e0447a, var(--sf-user-pink-deep));
  color: #fff; font-family: inherit; font-size: 16px; font-weight: 800;
  box-shadow: 0 12px 24px -12px rgba(194,24,91,.7);
}
.sf-user-submit:active { transform: translateY(1px); filter: brightness(.95); }
/* reset-password submit: same shape, deliberate red — this one changes a login */
.sf-user-submit--danger { background: linear-gradient(155deg, #c4372e, var(--sf-user-bad-deep)); box-shadow: 0 12px 24px -12px rgba(140,29,23,.7); }

.sf-user-cancel {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: var(--sf-user-tap);
  border: 1.5px solid var(--sf-user-edge); border-radius: 14px; cursor: pointer;
  background: var(--sf-user-card); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  color: var(--sf-user-ink); font-family: inherit; font-size: 15px; font-weight: 700;
}
.sf-user-cancel:active { filter: brightness(.96); }

/* careful note on Reset Password */
.sf-user-careful {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border-radius: 14px;
  background: var(--sf-user-warn-tint); color: #6b4a00;
  font-size: 13px; font-weight: 600; text-wrap: pretty;
}
.sf-user-careful .sf-user-ico { color: var(--sf-user-warn); margin-top: 1px; }

/* ---------- validation (note 7) ----------
   The summary block the view prints when the server rejects a post, and the
   per-field message the asp-validation-for span carries. The span keeps its
   own .sf-field-error class from site.css and wears .sf-user-error as well,
   so the tag helper's markup is untouched and this file only recolours it.
   input-validation-error is jQuery Validate's own class, put on the input
   itself; it is matched here so a wrong field looks wrong, not just its
   message. */
.sf-user-alert {
  display: flex; flex-direction: column; gap: 4px;
  margin: 0 0 14px; padding: 12px 14px; border-radius: 14px;
  background: var(--sf-user-bad-tint); color: var(--sf-user-bad-deep);
  border: 1.5px solid rgba(179,38,30,.3);
  font-size: 13.5px; font-weight: 600; text-wrap: pretty;
}
.sf-user-error { font-size: 12.5px; font-weight: 700; color: var(--sf-user-bad); }
.sf-user-error:empty { display: none; }
/* a field the server or the client marked wrong reads as wrong, not just the
   message under it */
.sf-user-input.input-validation-error { border-color: var(--sf-user-bad); background: #fffafa; }

/* ---------- footer ---------- */
.sf-user-foot { text-align: center; padding: 2px 2px 0; }
.sf-user-wingbar { height: 4px; border: 0; width: 132px; margin: 0 auto 12px; border-radius: 999px; background: var(--sf-user-wing); }
