/*
 * The sign-in page, brought to the VRTO design (Figma 124:5190).
 *
 * ─── Why this is CSS and not a React component ──────────────────────────────
 *
 * AdminJS ships `componentLoader.override('Login', …)`, which would be the
 * obvious tool. It is deliberately not used: a `.jsx` override has to live
 * outside `src/` (this workspace builds with `tsc` alone, no `jsx` option), is
 * compiled by AdminJS's Babel bundler on FIRST BOOT inside the container, and
 * pins us to AdminJS 7's internal component contract. A stylesheet costs one
 * `<link>` and survives a minor upgrade.
 *
 * ─── Two things that will bite anyone editing this file ─────────────────────
 *
 * 1. 🔴 SPECIFICITY. styled-components v5 injects its `<style>` into
 *    `document.head` at RUN TIME — i.e. after this file's `<link>`. Its rules
 *    are single-class (0,1,0), so a bare `.adminjs_Input { … }` has equal
 *    specificity and LOSES on source order. Every rule here is scoped under
 *    `#app` or `.login__Wrapper` to clear that bar, and anything
 *    styled-components also sets is marked `!important`. Dropping the scope
 *    does not "clean up" a rule; it silently disables it.
 *
 * 2. 🔴 SCOPE. `assets.styles` is injected into the main console template too,
 *    not just the login template. `.login__Wrapper` exists only on the sign-in
 *    page, so scoping under it is what keeps this file from reshaping the
 *    console. Never add a top-level element or `.adminjs_*` rule here.
 *
 * ─── The layout trick ───────────────────────────────────────────────────────
 *
 * Stock markup nests the copy and the form in two sibling `<section>`s:
 *
 *   .login__Wrapper
 *     └── .adminjs_Box                       the card
 *           ├── .adminjs_Box:first-child     <h2> heading, subtitle, illustrations
 *           └── form.adminjs_Box             <h5> logo, inputs, button
 *
 * The design wants all of it in ONE vertical stack with the logo on top.
 * `display: contents` on both children promotes every grandchild to a flex item
 * of the card, after which a single `order` moves the logo. It does not change
 * DOM ancestry, so the <form> still submits normally.
 */

/* ───────────────────────────── Typography ──────────────────────────────────
 * TTF rather than WOFF2 because `vrto-expo` ships no WOFF2 and this repo has no
 * font tooling. Five faces, not the thirty-two in the Expo bundle: Regular,
 * Medium and Bold carry body and labels; the Expanded family is the design's
 * "Complimentary Font", used only for the heading and the button.
 */

@font-face {
  font-family: 'Zalando Sans';
  src: url('/admin-assets/fonts/ZalandoSans-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Zalando Sans';
  src: url('/admin-assets/fonts/ZalandoSans-Medium.ttf') format('truetype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Zalando Sans';
  src: url('/admin-assets/fonts/ZalandoSans-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Zalando Sans Expanded';
  src: url('/admin-assets/fonts/ZalandoSans_Expanded-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Zalando Sans Expanded';
  src: url('/admin-assets/fonts/ZalandoSans_Expanded-Black.ttf') format('truetype');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

/* Brand tokens. Declared on `:root` rather than under the scope so the
 * `@media` block and the pseudo-elements can reach them; custom properties
 * paint nothing on their own, so this does not leak into the console. */
:root {
  --vrto-obsidian: #191a1d;
  --vrto-obsidian-80: rgba(25, 26, 29, 0.8);
  --vrto-obsidian-60: rgba(25, 26, 29, 0.6);
  --vrto-smoke: #e7e8ed;
  --vrto-coral: #ff623e;
  --vrto-art-width: 49.4%; /* 632 / 1280, measured off the Figma frame */
  --vrto-form-width: 394px;
}

/* ─────────────────────────────── Shell ─────────────────────────────────── */

/* The stock wrapper is a centring flex COLUMN on a grey field. The design is a
 * two-panel row on white. The art panel is a `::before` — a flex container's
 * pseudo-element is itself a flex item, which is what makes the split work
 * without any wrapper element to hang it on. */
#app .login__Wrapper {
  flex-direction: row !important;
  align-items: stretch !important;
  justify-content: flex-start !important;
  background: #fff !important;
  padding: 0 !important;
  min-height: 100vh;
}

#app .login__Wrapper::before {
  content: '';
  flex: 0 0 var(--vrto-art-width);
  background-color: var(--vrto-obsidian);
  background-image: url('/admin-assets/svgs/login-art.svg');
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
}

/* The card stops being a card: no shadow, no fixed height, no 2/3 width. It
 * becomes the right-hand panel, with the 394px stack centred inside it. */
#app .login__Wrapper > .adminjs_Box {
  flex: 1 1 auto !important;
  width: auto !important;
  height: auto !important;
  min-width: 0;
  flex-direction: column !important;
  align-items: stretch !important;
  justify-content: center !important;
  gap: 24px;
  box-shadow: none !important;
  background: #fff !important;
  max-width: calc(var(--vrto-form-width) + 96px);
  margin: 0 auto;
  padding: 48px 24px !important;
  box-sizing: border-box;
}

/* Promote the grandchildren — see the header comment. */
#app .login__Wrapper > .adminjs_Box > .adminjs_Box:first-child,
#app .login__Wrapper > .adminjs_Box > form.adminjs_Box {
  display: contents !important;
}

/* ──────────────────────────── Stack contents ───────────────────────────── */

/* The logo lives inside the <form>, so it lands after the heading once the
 * wrappers are dissolved. One `order` puts it back on top. */
#app .login__Wrapper .adminjs_H5 {
  order: -1;
  margin: 0 !important;
  padding: 0 !important;
}

/* `StyledLogo` hardcodes `max-width: 200px` and `margin: theme.space.md 0`. */
#app .login__Wrapper .adminjs_H5 img {
  display: block;
  width: 63px !important;
  height: 32px !important;
  max-width: none !important;
  margin: 0 !important;
}

/* Planet / Astronaut / FlagInCog.
 *
 * 🔴 The child combinator inside `:has()` is load-bearing. `:has()` matches any
 * DEPTH of descendant, so a bare `.adminjs_Box:has(.adminjs_Illustration)` also
 * matches the card — which is an ancestor of the illustrations too — and blanks
 * the entire page. Measured, not theorised.
 *
 * The nesting is: IllustrationsWrapper > inline Box > .adminjs_Illustration.
 * Neither wrapper carries a stable class, so each is addressed by its exact
 * distance from the illustration. The rule on `.adminjs_Illustration` itself is
 * the fallback: if `:has()` is ever unavailable the SVGs still go, leaving only
 * empty boxes. */
#app .login__Wrapper .adminjs_Illustration,
#app .login__Wrapper .adminjs_Box:has(> .adminjs_Illustration),
#app .login__Wrapper .adminjs_Box:has(> .adminjs_Box > .adminjs_Illustration) {
  display: none !important;
}

/* "SIGN IN". Stock passes `fontWeight="lighter"` (200) and `fontSize="h2"`. */
#app .login__Wrapper .adminjs_H2 {
  order: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: 'Zalando Sans Expanded', 'Zalando Sans', sans-serif !important;
  font-weight: 900 !important;
  font-size: 24px !important;
  line-height: 32px !important;
  letter-spacing: 0 !important;
  text-transform: uppercase;
  color: var(--vrto-obsidian) !important;
  margin: 0 !important;
  padding: 0 !important;
}

#app .login__Wrapper .adminjs_H2::before {
  content: 'VRTO ADMIN CONSOLE';
  font-family: 'Zalando Sans', sans-serif;
  font-weight: 500;
  font-size: 12px;
  line-height: 18px;
  letter-spacing: 0.8px;
  color: var(--vrto-obsidian-60);
}

/* The subtitle, and the empty `<div class="adminjs_Text">` the stock form
 * renders above the button. Both are `.adminjs_Text`; the first is the only one
 * with copy in it, so the sibling rule below hides the rest. */
#app .login__Wrapper .adminjs_Text {
  font-size: 14px !important;
  line-height: 22px !important;
  letter-spacing: -0.2px;
  font-weight: 400 !important;
  color: var(--vrto-obsidian-80) !important;
  margin: 0 !important;
  padding: 0 !important;
  text-align: left !important;
}

/* The stock spacer between the password field and the button. It is empty, but
 * the card's `gap` would still give it 24px. */
#app .login__Wrapper form .adminjs_Text:empty {
  display: none !important;
}

/* ─────────────────────────────── Fields ────────────────────────────────── */

/* `FormGroup` gets no `adminjs_` class — only a styled-components hash, which
 * is unstable across builds and must never be targeted. `:has()` on the label
 * it always contains is the stable handle. */
#app .login__Wrapper > .adminjs_Box > form > div:has(> .adminjs_Label) {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0 !important;
  width: 100%;
}

#app .login__Wrapper .adminjs_Label {
  font-family: 'Zalando Sans', sans-serif !important;
  font-weight: 500 !important;
  font-size: 14px !important;
  line-height: 22px !important;
  color: var(--vrto-obsidian) !important;
  margin: 0 !important;
  padding: 0 !important;
  display: flex;
  align-items: flex-start;
  gap: 2px;
}

/* Stock renders the required marker as a `::before` asterisk in `primary100`.
 * The design puts a coral dot after the text instead. */
#app .login__Wrapper .adminjs_Label::before {
  content: '' !important;
  order: 2;
  width: 4px;
  height: 4px;
  margin: 4px 0 0 !important;
  border-radius: 50%;
  background: var(--vrto-coral);
  flex: 0 0 auto;
}

#app .login__Wrapper .adminjs_Input {
  width: 100% !important;
  box-sizing: border-box;
  font-family: 'Zalando Sans', sans-serif !important;
  font-weight: 500 !important;
  font-size: 14px !important;
  line-height: 22px !important;
  color: var(--vrto-obsidian) !important;
  background: #fff !important;
  border: 1px solid var(--vrto-smoke) !important;
  border-radius: 8px !important;
  padding: 14px 12px !important;
  transition: border-color 0.15s ease;
}

#app .login__Wrapper .adminjs_Input::placeholder {
  color: var(--vrto-obsidian-60) !important;
  font-weight: 400 !important;
}

/* Stock focus is a `primary100` border plus a blue `inputFocus` glow. */
#app .login__Wrapper .adminjs_Input:focus {
  border-color: var(--vrto-obsidian) !important;
  box-shadow: none !important;
  outline: none !important;
}

/* ─────────────────────────────── Button ────────────────────────────────── */

/* Stock `variant="contained"` paints from `colors.primary100`, which
 * `branding.theme` has already moved to obsidian — the radius is the part
 * `branding.theme` cannot express, because `space.sm` doubles as a spacing unit
 * and moving it would shift padding across the whole console. */
#app .login__Wrapper .adminjs_Button {
  width: 100%;
  justify-content: center;
  font-family: 'Zalando Sans Expanded', 'Zalando Sans', sans-serif !important;
  font-weight: 700 !important;
  font-size: 14px !important;
  line-height: normal !important;
  letter-spacing: 0.2px;
  text-transform: uppercase;
  color: #fff !important;
  background: var(--vrto-obsidian) !important;
  border: 1px solid var(--vrto-obsidian) !important;
  border-radius: 64px !important;
  padding: 14px 24px !important;
  height: auto !important;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

#app .login__Wrapper .adminjs_Button:hover {
  background: var(--vrto-obsidian) !important;
  border-color: var(--vrto-obsidian) !important;
  opacity: 0.85;
}

#app .login__Wrapper .adminjs_Button:focus-visible {
  outline: 2px solid var(--vrto-coral);
  outline-offset: 2px;
}

/* ── Signing in ──
 *
 * The form is a plain POST, so the state lasts from the submit until the
 * browser swaps the document — either for the console or for a re-rendered
 * login carrying the error. `public/login.js` sets the attribute; the header of
 * that file says why the state is not a React override.
 *
 * The label is a bare text node inside the button, so it cannot be replaced in
 * CSS — it is made transparent instead and the spinner is centred over it,
 * which also keeps the button exactly the width it already was. `opacity` and
 * `background` are restated because the design system dims a `:disabled`
 * button, and dimmed-plus-spinning reads as broken rather than busy. */
#app .login__Wrapper form[data-vrto-submitting] .adminjs_Button,
#app .login__Wrapper form[data-vrto-submitting] .adminjs_Button:disabled,
#app .login__Wrapper form[data-vrto-submitting] .adminjs_Button:hover {
  position: relative;
  color: transparent !important;
  background: var(--vrto-obsidian) !important;
  border-color: var(--vrto-obsidian) !important;
  opacity: 1 !important;
  cursor: progress;
  pointer-events: none;
}

#app .login__Wrapper form[data-vrto-submitting] .adminjs_Button::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: vrto-login-spin 0.7s linear infinite;
}

/* The fields go quiet with it — the values are already on their way, and an
 * editable field that no longer affects the request invites a correction that
 * silently does nothing. */
#app .login__Wrapper form[data-vrto-submitting] .adminjs_Input {
  color: var(--vrto-obsidian-60) !important;
  pointer-events: none;
}

@keyframes vrto-login-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Without the rotation there is nothing to see, so the state falls back to a
 * static ring plus the dimmed fields. */
@media (prefers-reduced-motion: reduce) {
  #app .login__Wrapper form[data-vrto-submitting] .adminjs_Button::after {
    animation: none;
    border-color: rgba(255, 255, 255, 0.5);
    border-top-color: #fff;
  }
}

/* ────────────────────────── Failed sign-in ─────────────────────────────── */

/* The only path that renders this is a rejected credential, so it has to stay
 * legible after everything above.
 *
 * ⚠️ The `adminjs_MessageBox` class is on an OUTER wrapper that paints nothing.
 * `errorLight` (#F9E5E7) is painted by the `adminjs_Box` inside it, which sits
 * on top — styling only the wrapper leaves the stock pink visible and looks
 * like the rule never applied. Both are needed. */
#app .login__Wrapper .adminjs_MessageBox {
  width: 100%;
  margin: 0 !important;
  border-radius: 8px !important;
  background: rgba(255, 98, 62, 0.1) !important;
  border: 1px solid var(--vrto-coral) !important;
  overflow: hidden;
}

#app .login__Wrapper .adminjs_MessageBox > .adminjs_Box {
  background: transparent !important;
  border-radius: 0 !important;
}

#app .login__Wrapper .adminjs_MessageBox .adminjs_Text {
  color: var(--vrto-obsidian) !important;
  font-weight: 500 !important;
  font-size: 14px !important;
}

/* The icon chip, stock `colors.error` #C20012. */
#app .login__Wrapper .adminjs_MessageBox .adminjs_Icon {
  background: var(--vrto-coral) !important;
}

/* ───────────────────────────── Narrow ──────────────────────────────────── */

/* Below the tablet breakpoint the art panel would squeeze the form past
 * usable. It goes, and the stack takes the full width. */
@media (max-width: 768px) {
  #app .login__Wrapper::before {
    display: none;
  }

  /* Not `max-width: none` — at 768px that yields a 720px-wide login form. */
  #app .login__Wrapper > .adminjs_Box {
    max-width: 460px;
    padding: 32px 24px !important;
  }
}
