/* Philentia — the sign-in screen
 * Copyright (c) 2026, IT Business Dominicana (ITBD)
 *
 * The first screen anybody sees, and until now the least designed: Frappe's
 * default, left-aligned, serif, with the full lockup at full size.
 *
 * Styled entirely from outside. Frappe owns `www/login.html`, and ADR-003
 * forbids modifying it, so this works on the DOM it already emits —
 * `.for-login`, `.page-card`, `.page-card-head`, `.form-control`, `.btn-login`.
 * The trade is that a Frappe upgrade could rename a class; the alternative is
 * a template fork that silently stops receiving security fixes.
 *
 * ---------------------------------------------------------------------------
 * Why the selectors are long
 * ---------------------------------------------------------------------------
 * `login.bundle.css` is loaded from the template's own `head_include`, which
 * renders *after* `web_include_css`. So Frappe's login styles win on equal
 * specificity, and `.app-logo { max-height: 32px }` quietly shrank the mark to
 * a thumbnail while `.btn-primary` kept its near-black.
 *
 * The answer is specificity, not `!important`: `body .for-login .page-card …`
 * outranks a single class and still loses to a deliberate override later.
 * Reaching for `!important` here would win the argument and leave nothing able
 * to adjust this page afterwards.
 *
 * Built only on `philentia-tokens.css`. No hex values below this line.
 */

/* ===========================================================================
 * Which switch decides the theme
 * ===========================================================================
 * Frappe's `login.bundle.css` switches on `[data-theme]` and ignores
 * `prefers-color-scheme` entirely. `philentia-tokens.css` honours both, which
 * is right everywhere else in the product and wrong here: on a login page with
 * no `data-theme` set, opened in a browser that prefers dark, the two halves
 * disagreed. Our `--surface` went dark; Frappe's `--gray-100` did not. The
 * card rendered white with a dark secondary button — measured, not guessed:
 * `--surface: #101828` against `card: rgb(255,255,255)`.
 *
 * Following the media query harder would be worse, not better. Frappe styles
 * the inputs, the labels and "Forgot password?" from its own light tokens on
 * this page, and nothing we do moves them. A card that went dark on OS
 * preference would leave those light-on-dark and unreadable.
 *
 * So the sign-in card follows `data-theme` only, exactly as Frappe does. An
 * explicit choice of dark still works — `[data-theme="dark"]` moves both sets
 * together. A mere OS preference does not, because only half the page would
 * hear it.
 */
@media (prefers-color-scheme: dark) {
	html:not([data-theme="dark"]) body.login-page,
	html:not([data-theme="dark"]) body[data-path="login"] {
		--surface: var(--white);
		--surface-secondary: var(--neutral-50);
		--text-primary: var(--neutral-950);
		--text-secondary: var(--neutral-700);
		--text-muted: var(--neutral-600);
		--text-link: var(--philentia-blue-600);
		--brand-primary: var(--philentia-blue-600);
		--brand-primary-hover: var(--philentia-blue-700);
	}
}

/* ===========================================================================
 * The page
 * =========================================================================== */

body.login-page,
body[data-path="login"] {
	min-height: 100vh;
	margin: 0;
	font-family: var(--font-ui);
	color: var(--text-primary);
	background: var(--philentia-navy);
	/* The brand gradient, held still. A login is a doorway, not a showcase. */
	background-image: var(--gradient-brand);
	background-attachment: fixed;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-6) var(--space-4);
}

/* The ascending arrow of the mark, expressed as light rather than drawn again
 * (§58: growth is a direction, not a decoration). Two slow, very soft washes.
 * They move once every twenty seconds and never cross the card. */
body.login-page::before,
body[data-path="login"]::before {
	content: "";
	position: fixed;
	inset: -30% -10% auto -30%;
	height: 90vh;
	background: radial-gradient(
		ellipse at 30% 40%,
		rgba(124, 207, 44, 0.16) 0%,
		transparent 60%
	);
	animation: ph-drift 22s var(--ease-out) infinite alternate;
	pointer-events: none;
}

body.login-page::after,
body[data-path="login"]::after {
	content: "";
	position: fixed;
	inset: auto -30% -30% 20%;
	height: 80vh;
	background: radial-gradient(
		ellipse at 60% 60%,
		rgba(3, 139, 239, 0.28) 0%,
		transparent 62%
	);
	animation: ph-drift 26s var(--ease-out) infinite alternate-reverse;
	pointer-events: none;
}

@keyframes ph-drift {
	from { transform: translate3d(0, 0, 0) scale(1); }
	to   { transform: translate3d(4%, -3%, 0) scale(1.12); }
}

/* ===========================================================================
 * The card
 * =========================================================================== */

.for-login,
.for-email-login,
.for-forgot,
.for-signup,
.for-login-with-email-link {
	width: 100%;
	display: flex;
	justify-content: center;
}

body .page-card {
	width: min(420px, 100%);
	background: var(--surface);
	border: 0;
	border-radius: var(--radius-xl);
	box-shadow: 0 24px 60px rgba(6, 48, 120, 0.28);
	padding: var(--space-10) var(--space-8) var(--space-8);
	animation: ph-rise var(--duration-slow) var(--ease-out) both;
}

@keyframes ph-rise {
	from { opacity: 0; transform: translateY(12px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* --- Head ---------------------------------------------------------------- */

.page-card-head {
	text-align: center;
	margin-bottom: var(--space-8);
	border: 0;
	padding: 0;
}

/* The full lockup is square and carries two lines of tagline. At the size a
 * login wants it, that tagline is a smear — so the mark is capped and the
 * words are left to the wordmark inside it. */
body .for-login .page-card-head .app-logo,
body .for-email-login .page-card-head .app-logo,
body .for-forgot .page-card-head .app-logo,
body .for-signup .page-card-head .app-logo,
body .for-login-with-email-link .page-card-head .app-logo {
	height: 104px;
	max-height: none;
	width: auto;
	max-width: 78%;
	margin: 0 auto var(--space-5);
	display: block;
	object-fit: contain;
}

.page-card-head h4 {
	font-family: var(--font-brand);
	font-size: var(--text-h3);
	font-weight: var(--weight-bold);
	color: var(--text-primary);
	margin: 0 0 var(--space-2);
	letter-spacing: -0.01em;
}

.page-card-head p,
.page-card-head .text-muted {
	color: var(--text-muted);
	font-size: var(--text-body);
	margin: 0;
	line-height: var(--leading-relaxed);
}

/* ===========================================================================
 * Fields
 * =========================================================================== */

.page-card .form-group { margin-bottom: var(--space-5); }

.page-card label,
.page-card .control-label {
	display: block;
	font-size: var(--text-body);
	font-weight: var(--weight-medium);
	color: var(--text-secondary);
	margin-bottom: var(--space-2);
}

body .page-card .form-control,
body .page-card input[type="text"],
.page-card input[type="email"],
.page-card input[type="password"] {
	width: 100%;
	height: var(--control-height);
	padding: 0 var(--space-3);
	background: var(--surface);
	border: 1px solid var(--border-control);
	border-radius: var(--radius-md);
	font-family: var(--font-ui);
	font-size: var(--text-body);
	color: var(--text-primary);
	box-shadow: none;
	transition: border-color var(--duration-fast) var(--ease-out),
		box-shadow var(--duration-fast) var(--ease-out);
}

.page-card .form-control:focus {
	outline: none;
	border-color: var(--border-focus);
	box-shadow: var(--focus-ring);
}

.page-card .form-control::placeholder { color: var(--text-muted); }

/* ===========================================================================
 * Buttons
 *
 * Frappe styles these as
 * `.for-login .page-card .page-card-actions .btn-login` — four classes. A
 * three-class selector loses however sensible it reads, which is why the
 * primary button stayed near-black through two attempts. Matching the shape
 * and adding `body` wins by one element and nothing more.
 * =========================================================================== */

body .for-login .page-card .page-card-actions .btn-login,
body .for-forgot .page-card .page-card-actions .btn-login,
body .for-login-with-email-link .page-card .page-card-actions .btn-login,
body .for-signup .page-card .page-card-actions .btn-login,
body .for-email-login .page-card .page-card-actions .btn-login,
body .for-reset-password .page-card .page-card-actions .btn-login,
body .for-login .page-card .page-card-actions .btn-ldap-login,
body .for-forgot .page-card .page-card-actions .btn-ldap-login,
body .for-login-with-email-link .page-card .page-card-actions .btn-ldap-login,
body .for-signup .page-card .page-card-actions .btn-ldap-login,
body .for-email-login .page-card .page-card-actions .btn-ldap-login,
body .for-reset-password .page-card .page-card-actions .btn-ldap-login {
	width: 100%;
	min-height: var(--control-height);
	background: var(--brand-primary);
	border: 1px solid transparent;
	border-radius: var(--radius-md);
	color: var(--text-on-fill);
	font-family: var(--font-ui);
	font-size: var(--text-body);
	font-weight: var(--weight-semibold);
	box-shadow: none;
	transition: background-color var(--duration-hover) var(--ease-out),
		transform var(--duration-press) var(--ease-out);
}

body .for-login .page-card .page-card-actions .btn-login:hover,
body .for-forgot .page-card .page-card-actions .btn-login:hover,
body .for-login-with-email-link .page-card .page-card-actions .btn-login:hover,
body .for-signup .page-card .page-card-actions .btn-login:hover,
body .for-email-login .page-card .page-card-actions .btn-login:hover,
body .for-reset-password .page-card .page-card-actions .btn-login:hover,
body .for-login .page-card .page-card-actions .btn-login:focus,
body .for-forgot .page-card .page-card-actions .btn-login:focus,
body .for-login-with-email-link .page-card .page-card-actions .btn-login:focus,
body .for-signup .page-card .page-card-actions .btn-login:focus,
body .for-email-login .page-card .page-card-actions .btn-login:focus,
body .for-reset-password .page-card .page-card-actions .btn-login:focus,
body .for-login .page-card .page-card-actions .btn-login:active,
body .for-forgot .page-card .page-card-actions .btn-login:active,
body .for-login-with-email-link .page-card .page-card-actions .btn-login:active,
body .for-signup .page-card .page-card-actions .btn-login:active,
body .for-email-login .page-card .page-card-actions .btn-login:active,
body .for-reset-password .page-card .page-card-actions .btn-login:active {
	background: var(--brand-primary-hover);
	color: var(--text-on-fill);
	border: 1px solid transparent;
	box-shadow: none;
}

body .for-login .page-card .page-card-actions .btn-login:active,
body .for-forgot .page-card .page-card-actions .btn-login:active,
body .for-login-with-email-link .page-card .page-card-actions .btn-login:active,
body .for-signup .page-card .page-card-actions .btn-login:active,
body .for-email-login .page-card .page-card-actions .btn-login:active,
body .for-reset-password .page-card .page-card-actions .btn-login:active { transform: translateY(1px); }

body .for-login .page-card .page-card-actions .btn-login:focus-visible,
body .for-forgot .page-card .page-card-actions .btn-login:focus-visible,
body .for-login-with-email-link .page-card .page-card-actions .btn-login:focus-visible,
body .for-signup .page-card .page-card-actions .btn-login:focus-visible,
body .for-email-login .page-card .page-card-actions .btn-login:focus-visible,
body .for-reset-password .page-card .page-card-actions .btn-login:focus-visible {
	outline: 2px solid var(--philentia-navy);
	outline-offset: 2px;
}

/* The secondary ways in — email link, SSO — are choices, not the choice. */
body .for-login .page-card .page-card-actions .btn-login-option,
body .for-forgot .page-card .page-card-actions .btn-login-option,
body .for-login-with-email-link .page-card .page-card-actions .btn-login-option,
body .for-signup .page-card .page-card-actions .btn-login-option,
body .for-email-login .page-card .page-card-actions .btn-login-option,
body .for-reset-password .page-card .page-card-actions .btn-login-option {
	width: 100%;
	min-height: var(--control-height);
	margin-top: var(--space-3);
	background: var(--surface);
	border: 1px solid var(--border-control);
	border-radius: var(--radius-md);
	color: var(--text-secondary);
	font-weight: var(--weight-medium);
	box-shadow: none;
}

body .for-login .page-card .page-card-actions .btn-login-option:hover,
body .for-forgot .page-card .page-card-actions .btn-login-option:hover,
body .for-login-with-email-link .page-card .page-card-actions .btn-login-option:hover,
body .for-signup .page-card .page-card-actions .btn-login-option:hover,
body .for-email-login .page-card .page-card-actions .btn-login-option:hover,
body .for-reset-password .page-card .page-card-actions .btn-login-option:hover {
	background: var(--surface-secondary);
	color: var(--text-primary);
}

/* ===========================================================================
 * Links and footer
 * =========================================================================== */

.page-card a {
	color: var(--text-link);
	text-decoration: none;
	font-size: var(--text-body-sm);
}
.page-card a:hover { text-decoration: underline; }

.page-card .forgot-password-message,
.page-card .sign-up-message {
	text-align: center;
	margin-top: var(--space-5);
	font-size: var(--text-body-sm);
	color: var(--text-muted);
}

/* Frappe's attribution line sits outside the card on the page background,
 * where it is unreadable against the gradient. */
.footer-powered,
.web-footer,
footer .text-muted {
	text-align: center;
	margin-top: var(--space-6);
	color: rgba(255, 255, 255, 0.68);
	font-size: var(--text-caption);
}
.footer-powered a,
.web-footer a { color: rgba(255, 255, 255, 0.9); }

/* ===========================================================================
 * Small screens
 * =========================================================================== */

@media (max-width: 480px) {
	.page-card {
		padding: var(--space-8) var(--space-5) var(--space-6);
		border-radius: var(--radius-lg);
	}
	body .for-login .page-card-head .app-logo { height: 84px; }
}

/* Somebody who gets motion sick does not need a drifting background to sign
 * in. Everything below is decoration, and decoration is the first thing that
 * should stop. */
@media (prefers-reduced-motion: reduce) {
	body.login-page::before,
	body.login-page::after,
	body[data-path="login"]::before,
	body[data-path="login"]::after {
		animation: none;
	}
	.page-card { animation: none; }
}

/* ===========================================================================
 * The scene behind the card
 * ===========================================================================
 * Drawn by `philentia-login.js` (ADR-003: the template is Frappe's). Fixed,
 * full-bleed, behind everything; the card is lifted above it. Colours are the
 * tokens at low opacity so the gradient still reads as the ground.
 */
.ph-scene {
	position: fixed;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	overflow: hidden;
}

.ph-scene svg {
	width: 100%;
	height: 100%;
	display: block;
}

body[data-path="login"] .page-card,
body.login-page .page-card {
	position: relative;
	z-index: 1;
}

.ph-scene__line {
	fill: none;
	stroke: rgba(255, 255, 255, 0.14);
	stroke-width: 1.2;
}

.ph-scene__node {
	fill: rgba(255, 255, 255, 0.35);
}

.ph-scene__node--person {
	fill: rgba(124, 207, 44, 0.55);
}

/* The contributions in motion: white going in, lime coming out — money
 * arrives, impact leaves. */
.ph-scene__gift {
	fill: #ffffff;
	opacity: 0.9;
	filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.7));
}

.ph-scene__gift--out {
	fill: var(--growth-lime-500);
	filter: drop-shadow(0 0 6px rgba(124, 207, 44, 0.8));
}

.ph-scene__hex {
	fill: rgba(255, 255, 255, 0.06);
	stroke: rgba(255, 255, 255, 0.35);
	stroke-width: 2;
	animation: ph-hex-pulse 6s ease-in-out infinite;
}

@keyframes ph-hex-pulse {
	0%, 100% { stroke-opacity: 0.35; }
	50% { stroke-opacity: 0.7; }
}

/* The ascending arrow of the mark draws itself, then holds. */
.ph-scene__arrow {
	fill: none;
	stroke: var(--growth-lime-500);
	stroke-width: 4;
	stroke-linecap: round;
	stroke-linejoin: round;
	stroke-dasharray: 320;
	stroke-dashoffset: 320;
	animation: ph-arrow-draw 4s var(--ease-out) 1s forwards;
}

@keyframes ph-arrow-draw {
	to { stroke-dashoffset: 0; }
}

/* Impact bars rise in turn and keep breathing. */
.ph-scene__bar {
	fill: rgba(124, 207, 44, 0.35);
	transform-box: fill-box;
	transform-origin: bottom;
	animation: ph-bar-rise 7s ease-in-out infinite;
}

@keyframes ph-bar-rise {
	0% { transform: scaleY(0.35); }
	45% { transform: scaleY(1); }
	70% { transform: scaleY(0.85); }
	100% { transform: scaleY(0.35); }
}

/* Still by preference: the shapes stay, the motion goes. */
.ph-scene--still .ph-scene__hex,
.ph-scene--still .ph-scene__bar,
.ph-scene--still .ph-scene__arrow {
	animation: none;
	stroke-dashoffset: 0;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.ph-scene__hex, .ph-scene__bar, .ph-scene__arrow { animation: none; stroke-dashoffset: 0; transform: none; }
}
