/* The login page, restyled to the 2026-10-12 design — docs/design-system.md,
 * "Frame 1: login". The mockup is Horizon UI's sign-in page; the values below
 * are measured from it, not invented.
 *
 * Loaded by akam/website.py, only on /login and only on sites with
 * `akam_login_design` in site_config. Every rule is scoped to
 * body[data-path="login"] as well, so a stray include elsewhere does nothing.
 *
 * This restyles frappe's own markup (frappe/www/login.html) rather than
 * replacing the template. login.js binds to these classes and ids, and a forked
 * template would need re-diffing on every frappe upgrade. That is why the brand
 * panel is a pseudo-element and why the logo in it is the page's own <img>
 * moved there: the logo stays per-site data (Website Settings), so a site with
 * its own brand keeps it.
 *
 * TWO TEMPLATES. frappe's login markup differs between the frappe in the local
 * image (16.29) and the one production runs, and both come from the same
 * floating `frappe/erpnext:version-16` base image, so neither is "the" markup.
 * This file is written against both, and checked against both:
 *
 *                       frappe 16.29 (local)           production (2026-10-14)
 *   heading + logo      inside .login-content.page-card   beside it, in the <section>
 *   labels              visible                         sr-only
 *   password toggle     <svg> eye, centred by frappe    <span> «نمایش دهید», top: 5px
 *   page-card-body      one                             nested twice; the buttons
 *                                                       and options sit inside it
 *   email-link option   in .page-card-actions           in .social-logins, after a
 *                                                       p.login-divider «یا»
 *   failed login        .login-error-banner             message written into the
 *                                                       primary button itself
 *
 * So the column width goes on the <section>, which both share, never on the
 * card; and nothing below depends on where an element sits, only on what it is.
 * Check a change against production's live page, not only the local stack:
 * the 2026-10-13 version passed every local check and broke on crm.
 *
 * What the mockup has and this deliberately does not:
 *   - Google sign-in: the product has none. frappe only renders social buttons
 *     when a Social Login Key exists; if one ever does, .btn-login-option below
 *     gives it the mockup's secondary style. The «یا» divider is kept where
 *     frappe draws one, i.e. before the email-link option.
 *   - "Remember me": frappe has no such option (session length is
 *     System Settings.session_expiry), so a checkbox would be a lie.
 *   - The mockup's wording: strings are frappe's msgids, translated in
 *     akam/locale/fa.po; only missing or misspelt ones were added there.
 *   - Its font: not chosen yet, so no font-family is set here.
 *
 * Direction: logical properties only. The panel sits at inline-end — the
 * left under RTL, as drawn — and its rounded corner is end-start, the one
 * facing the form, in either direction. The email and password fields are
 * LTR islands because their content is Latin, so their icons follow the field
 * rather than the page. frappe positions those icons with physical left/right,
 * and under RTL it serves an rtlcss-mirrored copy of its bundle (dist/css-rtl/)
 * with the two swapped — right for an RTL field, wrong for an LTR island. The
 * overrides below set both edges explicitly.
 *
 * Load order: this file is linked before frappe's login bundle, so every rule
 * here has to out-specify frappe's rather than rely on coming later. Several
 * frappe rules are five or six classes deep; the selectors below are as long
 * as they are to beat those, not for structure.
 */

body[data-path="login"] {
	--akam-login-brand: #4318ff;
	--akam-login-brand-hover: #3311db; /* not in the frame: Horizon's next step down */
	--akam-login-ink: #1b2559; /* headings; the capture's darkest title pixel is #282f5f */
	--akam-login-ink-body: #44485b;
	/* The mockup's subtitle grey is ≈#b4b7c3, 2.0:1 on white. This is the
	 * lightest grey in its family that passes 4.5:1 for body text. */
	--akam-login-ink-muted: #6b7591;
	--akam-login-placeholder: #8f9bba;
	--akam-login-border: #e0e5f2;
	--akam-login-divider: #eaeaeb;
	--akam-login-fill: #f4f7fe;
	--akam-login-radius: 16px;
	--akam-login-control: 50px;
	--akam-login-gap: 20px;

	background-color: #ffffff;
}

/* ---- The brand panel --------------------------------------------------- */

body[data-path="login"]::before {
	content: "";
	position: fixed;
	inset-block: 0;
	inset-inline-end: 0;
	inline-size: 50%;
	border-end-start-radius: 200px;
	/* Measured: #00072c at the top, #000b41 below, a violet band (#2d1263)
	 * across the upper third. Centred horizontally so it needs no mirroring. */
	background:
		radial-gradient(90% 30% at 50% 22%, rgb(117 81 255 / 0.32), transparent 70%),
		linear-gradient(180deg, #00072c 0%, #000b41 100%);
	pointer-events: none;
}

/* The site's own logo, lifted out of the column into the panel's centre. Each
 * section (login, forgot, sign-up) has its own copy; frappe hides all but one
 * with display: none, so only the visible section's logo is placed. */
body[data-path="login"] .page-card-head img.app-logo {
	position: fixed;
	inset-inline-end: 0;
	inset-block-start: 50%;
	inline-size: 50%;
	block-size: 128px;
	max-block-size: none;
	translate: 0 -50%;
	object-fit: contain;
	margin: 0;
	z-index: 1;
}

/* position: fixed is relative to the nearest transformed ancestor, and frappe
 * shakes the whole .page-card with a transform on a failed login. Under 16.29
 * the logo is inside that card and would be yanked out of the panel for the
 * length of the shake. Shake the form instead: the same feedback, and the
 * logo's ancestors never transform. (Production's logo is outside the card,
 * so there it is merely harmless.) */
body[data-path="login"] .login-content.page-card.invalid-login {
	animation: none;
}

body[data-path="login"] .login-content.page-card.invalid-login form {
	animation: wiggle 0.4s ease-in-out;
}

/* ---- Layout: one 410px column, centred in the inline-start half -------- */

body[data-path="login"] .page-content-wrapper {
	position: relative;
	z-index: 1;
	display: flex;
	align-items: center;
	inline-size: 50%;
	min-block-size: 100vh;
	padding-block: 48px;
}

body[data-path="login"] .page-content-wrapper > main {
	inline-size: 100%;
}

/* The column. On the <section> because it is the one element that holds both
 * the heading and the card in both templates. */
body[data-path="login"] :is(
	section.for-login,
	section.for-email-login,
	section.for-forgot,
	section.for-signup,
	section.for-login-with-email-link
) {
	max-inline-size: 410px;
	margin-inline: auto;
}

/* The card dissolves into the column: no frame, no width of its own. */
body[data-path="login"] .login-content.page-card {
	inline-size: 100%;
	max-inline-size: none;
	margin: 0;
	padding: 0;
	gap: 36px;
	background: transparent;
	border: none;
	border-radius: 0;
	box-shadow: none;
}

/* Production: frappe caps the form at 320px inside the card. */
body[data-path="login"] .login-content.page-card form {
	display: flex;
	flex-direction: column;
	gap: var(--akam-login-gap);
	max-inline-size: none;
	margin: 0;
}

/* ---- Heading ----------------------------------------------------------- */

body[data-path="login"] .page-card-head {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 16px;
	margin: 0;
	padding: 0;
	/* Both templates set a physical or centred alignment here; under RTL the
	 * stock 16.29 page left-aligns its title. */
	text-align: start;
}

/* Production only: the heading is a sibling of the card, so the space between
 * them is a margin rather than the card's gap. */
body[data-path="login"] section > .page-card-head {
	margin-block-end: 36px;
}

body[data-path="login"] .page-card-head h4 {
	margin: 0;
	font-size: 36px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: normal;
	color: var(--akam-login-ink);
}

body[data-path="login"] .page-card-head .page-card-subtitle {
	font-size: 14px;
	line-height: 1.7;
	letter-spacing: normal;
	color: var(--akam-login-ink-muted);
}

/* ---- Fields ------------------------------------------------------------ */

/* Production nests one .page-card-body inside another; both get the same
 * rhythm, so the spacing reads the same in either template. */
body[data-path="login"] .login-content.page-card .page-card-body {
	display: flex;
	flex-direction: column;
	gap: var(--akam-login-gap);
}

body[data-path="login"] .login-content.page-card form .form-group {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin: 0;
}

body[data-path="login"] .page-card .page-card-body .form-label {
	font-size: 14px;
	font-weight: 500;
	line-height: 1.6;
	color: var(--akam-login-ink-body);
}

/* Both login fields are required, and the mockup marks them. A symbol, not a
 * word, so it needs no msgid. (Production's labels are sr-only, so there it
 * marks nothing visible.) */
body[data-path="login"] .page-card .page-card-body .form-label::after {
	content: "*";
	margin-inline-start: 2px;
	color: var(--akam-login-brand);
}

body[data-path="login"] .page-card .page-card-body .email-field,
body[data-path="login"] .page-card .page-card-body .password-field {
	direction: ltr;
}

body[data-path="login"] .page-card .page-card-body input[type="text"],
body[data-path="login"] .page-card .page-card-body input[type="email"],
body[data-path="login"] .page-card .page-card-body input[type="password"] {
	block-size: var(--akam-login-control);
	margin: 0;
	padding-block: 0;
	padding-inline: 20px;
	font-size: 14px;
	color: var(--akam-login-ink);
	background-color: #ffffff;
	border: 1px solid var(--akam-login-border);
	border-radius: var(--akam-login-radius);
	box-shadow: none;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

body[data-path="login"] .page-card .page-card-body .password-field input {
	padding-inline-end: 48px;
}

/* Production's toggle is a word, not an icon, so it needs more room. */
body[data-path="login"] .page-card .page-card-body .password-field:has(> span.toggle-password) input {
	padding-inline-end: 96px;
}

body[data-path="login"] .page-card .page-card-body input:focus {
	border-color: var(--akam-login-brand);
	box-shadow: 0 0 0 3px rgb(67 24 255 / 0.15);
	outline: none;
}

body[data-path="login"] .page-card .page-card-body ::placeholder {
	color: var(--akam-login-placeholder);
	opacity: 1;
	/* The fields are LTR, but production's forgot and email-link fields have
	 * a Persian placeholder («آدرس ایمیل»), which would sit at the left.
	 * plaintext takes the direction from the placeholder's own first letter,
	 * so jane@example.com stays left and «آدرس ایمیل» goes right. */
	unicode-bidi: plaintext;
	text-align: start;
}

/* frappe's red border for a refused field, restated: the rule above is more
 * specific than frappe's base rule and would otherwise hide it. */
body[data-path="login"] .page-card .page-card-body.invalid input[type="text"],
body[data-path="login"] .page-card .page-card-body.invalid input[type="email"],
body[data-path="login"] .page-card .page-card-body.invalid input[type="password"],
body[data-path="login"] .page-card .page-card-body .form-group.invalid input {
	border-color: var(--outline-red-2, #f06548);
}

/* The mockup has no envelope or padlock inside the fields; it keeps the eye. */
body[data-path="login"] .page-card .page-card-body .field-icon {
	display: none;
}

/* Both edges, not just the end. Under RTL frappe serves its rtlcss-mirrored
 * bundle (css-rtl/), where its `right: 9px` arrives as `left: 9px` — and
 * inside this LTR field a set left beats a set right. */
body[data-path="login"] .page-card .page-card-body .password-field .toggle-password {
	inset-inline-start: auto;
	inset-inline-end: 16px;
	fill: var(--akam-login-placeholder);
}

/* Production's word toggle: frappe pins it 5px from the top. Stretch it to
 * the field's height and centre the word instead. The 16.29 eye is an <svg>
 * that frappe already centres with a transform, so it is left alone. */
body[data-path="login"] .page-card .page-card-body .password-field span.toggle-password {
	inset-block: 0;
	display: flex;
	align-items: center;
	font-size: 13px;
	line-height: 1;
	user-select: none;
}

body[data-path="login"] .page-card .page-card-body .forgot-password-message {
	margin: 0;
	line-height: 1.6;
	/* frappe: text-align right (16.29) or left (production's rtl bundle).
	 * The mockup puts the link at the end in either direction. */
	text-align: end;
}

body[data-path="login"] .page-card .page-card-body .forgot-password-message > a {
	font-size: 14px;
	font-weight: 500;
	color: var(--akam-login-brand);
}

body[data-path="login"] .page-card .page-card-body .login-error-banner,
body[data-path="login"] .page-card .page-card-body .login-success-banner {
	padding: 12px 16px;
	border-radius: 12px;
}

/* ---- Buttons ----------------------------------------------------------- */

body[data-path="login"] .login-content.page-card .page-card-actions {
	display: flex;
	flex-direction: column;
	gap: var(--akam-login-gap);
	margin: 0;
}

body[data-path="login"] .login-content.page-card .page-card-actions .btn,
body[data-path="login"] .login-content.page-card .btn.btn-login-option {
	display: flex;
	align-items: center;
	justify-content: center;
	block-size: var(--akam-login-control);
	padding-block: 0;
	padding-inline: 20px;
	font-size: 14px;
	line-height: 1.6;
	border: none;
	border-radius: var(--akam-login-radius);
	box-shadow: none;
}

/* The primary action. 16.29's sign-in button is .btn-default, production's
 * is .btn-primary, and the send-link buttons are .btn-primary in both. */
body[data-path="login"] .login-content.page-card .page-card-actions :is(.btn-login, .btn-ldap-login, .btn-primary) {
	font-weight: 700;
	color: #ffffff;
	background: var(--akam-login-brand);
}

/* :focus with :hover, because frappe ships a dark-grey rule for exactly those
 * three states (login.bundle: `.btn-login:hover, :focus, :active`). It did not
 * win against the base rule above when checked in a browser on 2026-10-14,
 * but naming all three keeps that from depending on how frappe's selector
 * happens to be built in a given release. */
body[data-path="login"] .login-content.page-card .page-card-actions :is(.btn-login, .btn-ldap-login, .btn-primary):is(:hover, :focus, :active) {
	color: #ffffff;
	background: var(--akam-login-brand-hover);
	box-shadow: none;
}

/* Disabled: while a login is in flight, and the send-link buttons until an
 * email is typed. Production also writes its error message into this button
 * (login.set_status), so it has to stay legible in every state. */
body[data-path="login"] .login-content.page-card .page-card-actions :is(.btn-login, .btn-ldap-login, .btn-primary):disabled {
	color: #ffffff;
	background: var(--akam-login-brand);
	opacity: 0.6;
}

body[data-path="login"] .login-content.page-card .page-card-actions .btn:focus-visible,
body[data-path="login"] .login-content.page-card .btn.btn-login-option:focus-visible {
	outline: 2px solid var(--akam-login-brand);
	outline-offset: 2px;
}

/* Email-link login, LDAP-as-option, any social provider: the mockup's
 * Google-button treatment, now the secondary style. */
body[data-path="login"] .login-content.page-card .btn.btn-login-option {
	inline-size: 100%;
	font-weight: 500;
	color: var(--akam-login-ink-body);
	background: var(--akam-login-fill);
}

body[data-path="login"] .login-content.page-card .btn.btn-login-option:hover {
	color: var(--akam-login-ink-body);
	background: var(--akam-login-border);
}

/* #signup on a site with sign-up disabled: the «صفحه اصلی» button sits outside
 * .page-card-actions in both templates. */
body[data-path="login"] section.for-signup.signup-disabled .btn.btn-primary {
	padding-block: 10px;
	padding-inline: 24px;
	font-weight: 700;
	color: #ffffff;
	background: var(--akam-login-brand);
	border: none;
	border-radius: var(--akam-login-radius);
}

/* ---- Production's «یا» and the options under it ------------------------ */

body[data-path="login"] .login-content.page-card .social-logins {
	display: flex;
	flex-direction: column;
	gap: var(--akam-login-gap);
	margin: 0;
}

/* The mockup's divider: a hairline either side of the word. */
body[data-path="login"] .login-content.page-card .login-divider {
	display: flex;
	align-items: center;
	gap: 12px;
	margin: 0;
	font-size: 13px;
	line-height: 1.6;
}

body[data-path="login"] .login-content.page-card .login-divider::before,
body[data-path="login"] .login-content.page-card .login-divider::after {
	content: "";
	flex: 1;
	border-block-start: 1px solid var(--akam-login-divider);
}

body[data-path="login"] .login-content.page-card .social-logins .social-login-buttons {
	margin: 0;
}

/* The provider list is rendered even with no provider, as an empty <div>
 * (whitespace only, so :empty misses it); in a flex column it would still
 * take a gap and double the space under «یا». */
body[data-path="login"] .login-content.page-card .social-logins .social-login-buttons:not(:has(*)) {
	display: none;
}

/* frappe gives each option a third or half of the row and 4px of side
 * padding, which made the email-link button narrower than the fields. */
body[data-path="login"] .login-content.page-card .social-logins .social-login-buttons .login-button-wrapper {
	min-inline-size: 0;
	inline-size: 100%;
	margin: 0;
	padding: 0;
}

/* ---- "Don't have an account?" / "Back to sign in" ---------------------- */

body[data-path="login"] .sign-up-message {
	margin: 0;
	font-size: 14px;
	line-height: 1.7;
	color: var(--akam-login-ink-body);
	/* The mockup starts this line at the column's start edge. frappe puts
	 * Bootstrap's .text-center on it, which is !important, so this has to be. */
	text-align: start !important;
}

body[data-path="login"] .sign-up-message a {
	font-weight: 700;
	color: var(--akam-login-brand);
	text-decoration: none;
}

body[data-path="login"] .sign-up-message a:hover {
	text-decoration: underline;
}

/* ---- Narrow screens: no panel, logo back in the column ----------------- */

@media (max-width: 991.98px) {
	body[data-path="login"]::before {
		display: none;
	}

	body[data-path="login"] .page-content-wrapper {
		inline-size: auto;
		align-items: flex-start;
	}

	body[data-path="login"] .page-card-head img.app-logo {
		position: static;
		inline-size: auto;
		block-size: 48px;
		translate: none;
	}

	body[data-path="login"] .page-card-head h4 {
		font-size: 28px;
	}
}
