/* ============================================================================
   visitor-auth-supplement.css — the auth-surface rules that belong to Vahary
   Visitor, layered on top of the shared shell
   (_content/Vahary.Branding/vahary-auth-shell.css).

   THE ONE RULE FOR THIS FILE: it may only ADD elements the shared shell does not
   have. It must never restate, override, or "improve" a shell rule. There are no
   longer any exceptions to that. This file used to carry exactly one countermand —
   a suppression of the focus ring the framework's FocusOnNavigate provoked on the
   product noun — and it is gone, so the rule above reads true again.

   It is gone for TWO reasons, and the second is the one that is easy to get wrong.
   Vahary.Branding 0.6.0 scoped the shell's ring to interactive elements, so the
   PACKAGE no longer draws its 2px violet box around the noun. That alone would not
   have been enough: <FocusOnNavigate Selector="h1" /> still focuses the noun on
   every routed load, the noun still MATCHES :focus-visible, and Chrome's own UA rule
   (:focus-visible { outline: auto 1px }) was never the package's to remove. What
   actually keeps the noun ringless is app.css's `h1:focus { outline: none }` — the
   stock Blazor project-template rule, which exists for precisely this reason and
   loads on every route, these included.

   Measured on the running app (/login, headless Chrome, h1.vh-product given
   tabindex="-1" and focused programmatically, as FocusOnNavigate does it):
       as shipped .............................. outline-style: none
       with app.css's h1:focus rule disabled ... outline-style: auto, 1px, rgb(16,16,16)
   The second line is the black UA box. It is why that one-line rule in app.css is
   load-bearing for this surface rather than template cruft — deleting it puts a
   black box around "Visitor" on every auth page, and nothing would catch it. The
   durable fix is h1[tabindex="-1"]:focus{outline:none} in the shared sheet (a 0.7.0);
   until that lands, app.css is what is holding it.

   If you find yourself needing another countermand here, that is the signal to
   change the package instead.

   That rule is the whole point. Visitor used to vendor its own copy of the
   shell, and the copy drifted a generation behind the source — the custom
   properties had been renamed to a "vh" prefix and the class vocabulary with
   them. Nothing caught it: a stylesheet that no longer matches its own markup
   still compiles and still passes every test. It only looks wrong. Anything in
   here that duplicates the shell is the beginning of that same divergence, so if
   a rule below ever needs to change because the SHELL changed, it is in the
   wrong file — push it upstream instead.

   Everything here is expressed in the shell's own --vh-* tokens and hangs off
   .vh-shell (or a .vis-* variant class the wrapper puts on the root), so it
   inherits the tenant accent and the Night ground rather than carrying a second
   opinion about either.

   These rules were previously split across the vendored sheet and the
   .vahary-auth block in app.css; they are collected here so the auth surface has
   exactly two stylesheets — the package's and this one.
   ============================================================================ */

/* CenteredLayout's host element. The old vendored sheet carried this rule quietly, and dropping
   the sheet would have dropped it: <main class="auth-shell"> is the Night ground the shell paints
   onto, and without it the console's light `body { background: var(--visitor-bg) }` is what shows
   through any gutter — including the flash before the shell's own background paints, and the strip
   below it at viewport heights the shell does not fill.

   It matters more than it did, not less: the vendored shell was `position: fixed; inset: 0` and
   covered the viewport unconditionally. The package's .vh-shell is `position: relative;
   min-height: 100vh` — a normal-flow element, so what its host does is now visible.

   The ground is a literal, not var(--vh-void): the shell defines its tokens on .vh-shell itself,
   which is this element's CHILD, so they are not in scope here. It matches --vh-void by value. */
.auth-shell {
  display: block;
  background: #0D1013;
  min-height: 100vh;
  padding: 0;
}

/* ---- the interstitial variant (/logout, /auth/refresh) ---------------------------------------
   MonumentShell maps its CoreClass="transition" parameter to this modifier on the shell ROOT,
   because the shared shell exposes no hook on .vh-core. These pages are a status line, not a
   sign-in: no form, no giant product noun — a centered eyebrow and one sentence on the same Night
   ground, so the auth journey reads as one design.

   The suppressed noun is why this is an ADD and not an override of .vh-core: the shell has no
   concept of a surface without a product name, and these two pages are Visitor's only ones. */
.vis-core-transition .vh-core { max-width: none; align-items: center; text-align: center; }
.vis-core-transition .vh-product { display: none; }
.vh-shell .vis-transition-eyebrow {
  font-family: var(--vh-font-mono); font-size: .72rem; font-weight: 400;
  letter-spacing: .30em; text-transform: uppercase; color: var(--vh-steel); margin: 0 0 1.1rem;
  animation: vh-rise var(--vh-rise-dur) var(--vh-rise-ease) 150ms both;
}
.vh-shell .vis-transition-eyebrow .vh-ap { color: var(--vh-accent-bright); }
.vh-shell .vis-transition-line {
  margin: 0; color: var(--vh-paper); font-family: var(--vh-font-display);
  font-weight: 500; font-size: clamp(1.35rem, 2.6vw, 1.9rem); letter-spacing: .01em; line-height: 1.2;
  animation: vh-rise var(--vh-rise-dur) var(--vh-rise-ease) 260ms both;
}

/* ---- arrival notices (login Wave 1, VW4) ------------------------------------------------------
   "Your session expired", "your password has been reset": a STATUS, not a fault — the user did
   nothing wrong. The shell has .vh-error and nothing else, so this is the same hairline
   composition in steel, with the accent dot marking "the system speaking". If another product
   grows one of these, this is the rule to move upstream. */
.vh-shell .vis-notice {
  display: flex; gap: .55rem; margin: 0 0 1.4rem; padding: .7rem 0;
  border-top: 1px solid var(--vh-hairline); border-bottom: 1px solid var(--vh-hairline);
  color: var(--vh-paper); font-size: .86rem; line-height: 1.45;
  animation: vh-rise 200ms var(--vh-rise-ease) both;
}
.vh-shell .vis-notice::before { content: "●"; color: var(--vh-accent-bright); }

/* ---- per-tenant SSO entry (VW2) ---------------------------------------------------------------
   The shell ships .vh-btn-sso as a <button>. Visitor's affordance is a GET to /login/sso/{id}, so
   it must be an <a> — and an <a> gets none of a button's box. This is the shell's own
   .vh-btn-sso geometry re-hung on an anchor rather than a different opinion about it; it is the
   one rule here closest to the line, and the right long-term fix is for .vh-btn-sso upstream to
   cover anchors too. */
.vh-shell a.vis-sso {
  height: 52px; padding: 0 1.2rem; border: 1px solid var(--vh-hairline); border-radius: 2px;
  cursor: pointer; background: transparent; color: var(--vh-paper); font: inherit; font-size: .9rem;
  display: inline-flex; align-items: center; gap: .55rem; text-decoration: none;
  transition: border-color var(--vh-touch-dur), background var(--vh-touch-dur);
}
.vh-shell a.vis-sso:hover { border-color: var(--vh-steel); background: rgba(242, 243, 241, .03); }
.vh-shell a.vis-sso svg { width: 14px; height: 14px; flex: none; }
@media (max-width: 760px) { .vh-shell .vh-actions a.vis-sso { justify-content: center; } }

/* ---- password-rule feedback (/reset-password) -------------------------------------------------
   Each policy rule lights accent as it is met. Progressive enhancement over the server render;
   mono meta register, so it reads as instrumentation rather than as copy. */
.vh-shell .vis-pwrules {
  list-style: none; display: flex; flex-wrap: wrap; gap: .35rem 1.1rem;
  margin: -1.1rem 0 1.6rem; padding: 0;
}
.vh-shell .vis-pwrules li {
  font-family: var(--vh-font-mono); font-size: .64rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--vh-steel); transition: color var(--vh-touch-dur);
}
.vh-shell .vis-pwrules li::before { content: "○ "; }
.vh-shell .vis-pwrules li.met { color: var(--vh-accent-bright); }
.vh-shell .vis-pwrules li.met::before { content: "● "; }

/* ---- copy lines -------------------------------------------------------------------------------
   .vis-fieldhint is the page's sentence of guidance (/forgot-password, /login/2fa); .vis-errline
   stacks the individual policy failures inside one error band, which is why /reset-password draws
   its own band instead of passing VaharyAuthShell's string Error parameter. */
.vh-shell .vis-fieldhint {
  color: var(--vh-steel); font-size: .86rem; line-height: 1.55; margin: 0 0 1.2rem;
  animation: vh-rise var(--vh-rise-dur) var(--vh-rise-ease) 220ms both;
}
.vh-shell .vis-errline { display: block; }

/* ---- terminal states ("check your email", "link expired") -------------------------------------
   Same register as the notice, one step quieter, with an attention-coloured tag: these end a flow
   rather than annotating a form, and they carry the way out (request a new link). */
.vh-shell .vis-terminal {
  margin-top: 2.2rem; padding: 1rem 0;
  border-top: 1px solid var(--vh-hairline); border-bottom: 1px solid var(--vh-hairline);
  color: var(--vh-steel); font-size: .9rem; line-height: 1.6;
  animation: vh-rise var(--vh-rise-dur) var(--vh-rise-ease) 260ms both;
}
.vh-shell .vis-terminal .vis-tag {
  display: block; font-family: var(--vh-font-mono); font-size: .64rem; letter-spacing: .22em;
  text-transform: uppercase; color: var(--vh-attention); margin-bottom: .35rem;
}
.vh-shell .vis-terminal a {
  color: var(--vahary-violet-tint, #D8C9F7); text-decoration: none;
  border-bottom: 1px solid var(--vahary-violet-tint, #D8C9F7);
}

/* ---- Blazor's framework-emitted classes -------------------------------------------------------
   .invalid / .valid.modified / .validation-errors / .validation-message are chosen by ASP.NET
   Core, not by us, so the shared shell cannot reasonably own them — a static-HTML consumer would
   never produce them.

   app.css gives every .invalid field a 1px outline box (the Blazor template's treatment). On this
   surface that is the wrong language: a field states its fault as a fault-red hairline under it,
   the way .vh-input states focus. The validation list is shaped to match .vh-error so a
   framework-rendered message and a hand-written one read as the same thing. */
.vh-shell .invalid,
.vh-shell .valid.modified:not([type=checkbox]) { outline: none; }
.vh-shell .vh-input.invalid { border-bottom-color: var(--vh-fault); }
.vh-shell .validation-errors {
  list-style: none; margin: 0 0 1.4rem; padding: .7rem 0;
  border-top: 1px solid rgba(248, 113, 113, .4); border-bottom: 1px solid rgba(248, 113, 113, .4);
  display: flex; flex-direction: column; gap: .25rem;
  animation: vh-rise 200ms var(--vh-rise-ease) both;
}
/* An EditForm renders the <ul> whether or not it has anything to say. */
.vh-shell .validation-errors:not(:has(li)) { display: none; }
.vh-shell .validation-message { color: var(--vh-fault); font-size: .86rem; line-height: 1.45; }

@media (prefers-reduced-motion: reduce) {
  .vh-shell .vis-transition-eyebrow,
  .vh-shell .vis-transition-line,
  .vh-shell .vis-notice,
  .vh-shell .vis-fieldhint,
  .vh-shell .vis-terminal,
  .vh-shell .validation-errors {
    animation: none;
    opacity: 1;
    transform: none;
  }
}
