/**
 * thkey - App Login Experience: frontend styles.
 *
 * Design language borrowed from Fifty Guest Gate so the two feel like one
 * product: navy scrim with a blur, a white card at 22px radius, a lime badge,
 * heavy 800-weight titles, and a spring pop on entry.
 *
 * Everything a setting can change is a CSS custom property, injected once by
 * PHP. Everything else lives here so the browser can cache it.
 *
 * All insets are logical (inset-inline-*, inset-block-*) so Arabic RTL mirrors
 * without a second stylesheet.
 */

/* ================================================================== *
 * 1. The overlay shell
 * ================================================================== */

.tale-veil {
	position: fixed;
	inset: 0;
	z-index: var( --tale-z, 2147483000 );
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	padding: 24px;
	overflow-y: auto;
	opacity: 0;
	visibility: hidden;
	transition: opacity var( --tale-fade, 280ms ) ease, visibility 0s linear var( --tale-fade, 280ms );
	-webkit-font-smoothing: antialiased;
}

.tale-veil * {
	box-sizing: border-box;
}

.tale-veil.is-on {
	opacity: 1;
	visibility: visible;
	transition: opacity var( --tale-fade, 280ms ) ease, visibility 0s;
}

/* ------------------------------------------------------------------ *
 * Layout: card (default) - a white panel floating over a blurred page
 * ------------------------------------------------------------------ */

.tale-veil--card,
.tale-veil--sheet {
	background: var( --tale-scrim, rgba( 25, 25, 77, 0.45 ) );
	-webkit-backdrop-filter: blur( var( --tale-blur, 8px ) );
	backdrop-filter: blur( var( --tale-blur, 8px ) );
}

.tale-veil--card .tale-veil__inner,
.tale-veil--sheet .tale-veil__inner {
	width: 100%;
	max-width: 340px;
	padding: 34px 28px 30px;
	color: var( --tale-card-fg, #19194d );
	text-align: center;
	background: var( --tale-card-bg, #ffffff );
	border-radius: var( --tale-radius, 22px );
	box-shadow: 0 24px 70px rgba( 25, 25, 77, 0.4 );
}

.tale-veil--card.is-on .tale-veil__inner {
	animation: tale-pop 380ms cubic-bezier( 0.2, 0.9, 0.3, 1.2 ) both;
}

/* ------------------------------------------------------------------ *
 * Layout: sheet - anchored to the bottom, the way a native app asks
 * ------------------------------------------------------------------ */

.tale-veil--sheet {
	align-items: flex-end;
	padding: 0;
}

.tale-veil--sheet .tale-veil__inner {
	/* The shared rule sets margin:auto to centre the card. On a flex item that
	   also cancels align-items, so the sheet would float in the middle instead
	   of sitting on the bottom edge. Push it down explicitly. */
	margin-block: auto 0;
	max-width: none;
	padding: 14px 28px calc( 34px + env( safe-area-inset-bottom, 0px ) );
	border-radius: var( --tale-radius, 22px ) var( --tale-radius, 22px ) 0 0;
	box-shadow: 0 -14px 50px rgba( 25, 25, 77, 0.34 );
}

.tale-veil--sheet.is-on .tale-veil__inner {
	animation: tale-rise 400ms cubic-bezier( 0.2, 0.9, 0.3, 1.05 ) both;
}

/* The little drag handle. Decorative, and only on the sheet. */
.tale-veil--sheet .tale-veil__grip {
	display: block;
	width: 42px;
	height: 4px;
	margin: 0 auto 20px;
	background: currentColor;
	border-radius: 999px;
	opacity: 0.18;
}

.tale-veil__grip {
	display: none;
}

/* ------------------------------------------------------------------ *
 * Layout: full screen - solid brand colour, no card
 * ------------------------------------------------------------------ */

.tale-veil--fullscreen {
	color: var( --tale-fg, #ffffff );
	background: var( --tale-bg, #19194d );
}

.tale-veil--fullscreen.tale-veil--gradient {
	background: radial-gradient( circle at 50% 38%, var( --tale-bg2, #2b2b74 ), var( --tale-bg, #19194d ) 72% );
}

.tale-veil--fullscreen .tale-veil__inner {
	text-align: center;
}

.tale-veil--fullscreen.is-on .tale-veil__inner {
	animation: tale-lift 420ms cubic-bezier( 0.2, 0.9, 0.3, 1 ) both;
}

/* ------------------------------------------------------------------ *
 * Layout: frosted - the page shows through, tinted and blurred
 * ------------------------------------------------------------------ */

.tale-veil--blur {
	color: var( --tale-fg, #ffffff );
	background: var( --tale-bg-soft, rgba( 25, 25, 77, 0.72 ) );
	-webkit-backdrop-filter: blur( calc( var( --tale-blur, 8px ) * 2 ) ) saturate( 140% );
	backdrop-filter: blur( calc( var( --tale-blur, 8px ) * 2 ) ) saturate( 140% );
}

.tale-veil--blur.is-on .tale-veil__inner {
	animation: tale-lift 420ms cubic-bezier( 0.2, 0.9, 0.3, 1 ) both;
}

/* ================================================================== *
 * 2. Card contents
 * ================================================================== */

.tale-veil__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	margin: auto;
}

.tale-veil__logo {
	display: block;
	width: auto;
	height: auto;
	max-width: var( --tale-logo, 96px );
	max-height: var( --tale-logo, 96px );
	margin: 0 auto 18px;
	object-fit: contain;
}

.tale-veil__logo.is-pulsing {
	animation: tale-pulse 1.9s ease-in-out infinite;
}

.tale-veil__title {
	margin: 0;
	font-size: var( --tale-title-size, 20px );
	font-weight: 800;
	line-height: 1.3;
	letter-spacing: -0.2px;
}

.tale-veil__sub {
	margin: 7px 0 0;
	font-size: var( --tale-sub-size, 14.5px );
	line-height: 1.5;
	color: var( --tale-card-muted, #5a5f73 );
}

/* On the dark layouts the muted colour would vanish, so fade the inherited
   colour instead of using the light-card muted grey. */
.tale-veil--fullscreen .tale-veil__sub,
.tale-veil--blur .tale-veil__sub {
	color: inherit;
	opacity: 0.72;
}

/* Animated trailing dots. The width animates rather than the content, so the
   title never jumps sideways as they appear. */
.tale-dots::after {
	content: "\2026";
	display: inline-block;
	overflow: hidden;
	width: 1.2em;
	text-align: start;
	vertical-align: bottom;
	animation: tale-dots 1.4s steps( 4, end ) infinite;
}

/* ================================================================== *
 * 3. The badge - a lime disc with an icon, optionally orbited by a ring
 * ================================================================== */

.tale-badge {
	position: relative;
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: var( --tale-badge, 72px );
	height: var( --tale-badge, 72px );
	margin-block-end: 18px;
}

.tale-badge__disc {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 60%;
	height: 60%;
	color: var( --tale-card-fg, #19194d );
	background: var( --tale-accent, #dae83d );
	border-radius: 50%;
	box-shadow: 0 6px 18px var( --tale-accent-glow, rgba( 218, 232, 61, 0.5 ) );
}

.tale-badge__disc svg {
	width: 52%;
	height: 52%;
}

/* On the dark layouts the disc sits on navy, so its own glow is wasted. */
.tale-veil--fullscreen .tale-badge__disc,
.tale-veil--blur .tale-badge__disc {
	box-shadow: 0 6px 22px rgba( 0, 0, 0, 0.28 );
}

/* The orbiting ring. A conic gradient gives a tapered arc rather than the
   hard-edged segment a border-top would produce. */
.tale-badge__ring {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background: conic-gradient( from 0deg, transparent 0deg, transparent 210deg, var( --tale-ring, #19194d ) 350deg, var( --tale-ring, #19194d ) 360deg );
	-webkit-mask: radial-gradient( farthest-side, transparent calc( 100% - 3px ), #000 calc( 100% - 3px ) );
	mask: radial-gradient( farthest-side, transparent calc( 100% - 3px ), #000 calc( 100% - 3px ) );
	animation: tale-rotate var( --tale-spin-speed, 850ms ) linear infinite;
}

/* The faint full circle the arc travels along. */
.tale-badge__track {
	position: absolute;
	inset: 0;
	border: 3px solid var( --tale-ring, #19194d );
	border-radius: 50%;
	opacity: 0.13;
}

.tale-veil--fullscreen .tale-badge__track,
.tale-veil--blur .tale-badge__track {
	border-color: currentColor;
	opacity: 0.2;
}

.tale-veil--fullscreen .tale-badge__ring,
.tale-veil--blur .tale-badge__ring {
	background: conic-gradient( from 0deg, transparent 0deg, transparent 210deg, var( --tale-accent, #dae83d ) 350deg, var( --tale-accent, #dae83d ) 360deg );
}

/* Browsers without mask support would show a filled disc over the icon, which
   looks broken. Fall back to a plain bordered arc. */
@supports not ( ( -webkit-mask: radial-gradient( #000, #000 ) ) or ( mask: radial-gradient( #000, #000 ) ) ) {
	.tale-badge__ring {
		background: none;
		border: 3px solid transparent;
		border-top-color: var( --tale-ring, #19194d );
	}
}

/* ================================================================== *
 * 4. Standalone spinners (used when the style is not "ring")
 * ================================================================== */

.tale-spin {
	flex: 0 0 auto;
	margin-block-start: 18px;
	color: var( --tale-ring, #19194d );
}

.tale-veil--fullscreen .tale-spin,
.tale-veil--blur .tale-spin {
	color: var( --tale-accent, #dae83d );
}

.tale-spin--dots,
.tale-spin--bars {
	display: flex;
	align-items: center;
	height: var( --tale-spin-size, 40px );
}

.tale-spin--dots {
	gap: 8px;
}

.tale-spin--dots i {
	width: calc( var( --tale-spin-size, 40px ) / 4 );
	height: calc( var( --tale-spin-size, 40px ) / 4 );
	background: currentColor;
	border-radius: 50%;
	animation: tale-bounce var( --tale-spin-speed, 850ms ) ease-in-out infinite;
}

.tale-spin--dots i:nth-child( 2 ) { animation-delay: calc( var( --tale-spin-speed, 850ms ) * 0.16 ); }
.tale-spin--dots i:nth-child( 3 ) { animation-delay: calc( var( --tale-spin-speed, 850ms ) * 0.32 ); }

.tale-spin--bars {
	gap: 5px;
}

.tale-spin--bars i {
	width: calc( var( --tale-spin-size, 40px ) / 8 );
	height: 40%;
	background: currentColor;
	border-radius: 999px;
	animation: tale-stretch var( --tale-spin-speed, 850ms ) ease-in-out infinite;
}

.tale-spin--bars i:nth-child( 2 ) { animation-delay: calc( var( --tale-spin-speed, 850ms ) * 0.12 ); }
.tale-spin--bars i:nth-child( 3 ) { animation-delay: calc( var( --tale-spin-speed, 850ms ) * 0.24 ); }
.tale-spin--bars i:nth-child( 4 ) { animation-delay: calc( var( --tale-spin-speed, 850ms ) * 0.36 ); }

.tale-spin--pulse {
	position: relative;
	width: var( --tale-spin-size, 40px );
	height: var( --tale-spin-size, 40px );
}

.tale-spin--pulse i {
	position: absolute;
	inset: 0;
	background: currentColor;
	border-radius: 50%;
	opacity: 0.75;
	animation: tale-ripple calc( var( --tale-spin-speed, 850ms ) * 2 ) ease-out infinite;
}

.tale-spin--pulse i:nth-child( 2 ) {
	animation-delay: var( --tale-spin-speed, 850ms );
}

/* ================================================================== *
 * 5. Progress sliver across the top of the overlay
 * ================================================================== */

.tale-veil__bar {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	width: 100%;
	height: 3px;
	overflow: hidden;
	background: rgba( 255, 255, 255, 0.14 );
}

.tale-veil__bar i {
	display: block;
	width: 40%;
	height: 100%;
	background: var( --tale-accent, #dae83d );
	animation: tale-slide 1.4s ease-in-out infinite;
}

/* ================================================================== *
 * 6. Welcome card
 * ================================================================== */

.tale-welcome {
	position: fixed;
	z-index: var( --tale-z-welcome, 2147482900 );
	display: flex;
	align-items: center;
	gap: 13px;
	box-sizing: border-box;
	max-width: min( 92vw, 430px );
	padding: 13px 20px 13px 15px;
	color: var( --tale-welcome-fg, #19194d );
	background: var( --tale-welcome-bg, #ffffff );
	border-radius: var( --tale-welcome-radius, 18px );
	box-shadow: 0 16px 44px rgba( 25, 25, 77, 0.26 );
	opacity: 0;
	pointer-events: none;
	transition: opacity 320ms ease, transform 420ms cubic-bezier( 0.2, 0.9, 0.3, 1.15 );
}

.tale-welcome * {
	box-sizing: border-box;
}

.tale-welcome.is-on {
	pointer-events: auto;
}

/* A hairline of the accent down the leading edge. Small, but it is what makes
   the card read as "part of the brand" rather than a generic toast. */
.tale-welcome::before {
	position: absolute;
	inset-block: 12px;
	inset-inline-start: 0;
	width: 4px;
	content: "";
	background: var( --tale-accent, #dae83d );
	border-radius: 999px;
}

/* Horizontal centring is a translate, so each position needs its own pair.
   Written out rather than nested, so the RTL mirror stays readable. */
.tale-welcome--top {
	inset-block-start: calc( 16px + env( safe-area-inset-top, 0px ) );
	inset-inline-start: 50%;
	transform: translateX( -50% ) translateY( -18px ) scale( 0.96 );
}

.tale-welcome--bottom {
	inset-block-end: calc( 16px + env( safe-area-inset-bottom, 0px ) );
	inset-inline-start: 50%;
	transform: translateX( -50% ) translateY( 18px ) scale( 0.96 );
}

.tale-welcome--center {
	inset-block-start: 50%;
	inset-inline-start: 50%;
	transform: translateX( -50% ) translateY( -50% ) scale( 0.92 );
}

.tale-welcome--top.is-on,
.tale-welcome--bottom.is-on {
	opacity: 1;
	transform: translateX( -50% ) translateY( 0 ) scale( 1 );
}

.tale-welcome--center.is-on {
	opacity: 1;
	transform: translateX( -50% ) translateY( -50% ) scale( 1 );
}

[dir="rtl"] .tale-welcome--top {
	transform: translateX( 50% ) translateY( -18px ) scale( 0.96 );
}

[dir="rtl"] .tale-welcome--bottom {
	transform: translateX( 50% ) translateY( 18px ) scale( 0.96 );
}

[dir="rtl"] .tale-welcome--center {
	transform: translateX( 50% ) translateY( -50% ) scale( 0.92 );
}

[dir="rtl"] .tale-welcome--top.is-on,
[dir="rtl"] .tale-welcome--bottom.is-on {
	transform: translateX( 50% ) translateY( 0 ) scale( 1 );
}

[dir="rtl"] .tale-welcome--center.is-on {
	transform: translateX( 50% ) translateY( -50% ) scale( 1 );
}

/* Full-width banner. Self-contained on purpose: it spans the whole width, so
   it needs no horizontal centring and therefore no RTL mirror. Keeping it
   independent means it can never be caught by the [dir="rtl"] overrides
   above, which carry higher specificity. */
.tale-welcome--banner {
	inset-block-start: 0;
	inset-inline: 0;
	justify-content: center;
	max-width: none;
	padding-block: calc( 14px + env( safe-area-inset-top, 0px ) ) 14px;
	border-radius: 0;
	transform: translateY( -100% );
}

.tale-welcome--banner::before {
	inset-block: auto 0;
	inset-inline: 0;
	width: auto;
	height: 3px;
	border-radius: 0;
}

.tale-welcome--banner.is-on,
[dir="rtl"] .tale-welcome--banner.is-on {
	opacity: 1;
	transform: translateY( 0 );
}

.tale-welcome__icon {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	font-size: 15px;
	line-height: 1;
	color: var( --tale-welcome-fg, #19194d );
	background: var( --tale-accent, #dae83d );
	border-radius: 50%;
	box-shadow: 0 4px 12px var( --tale-accent-glow, rgba( 218, 232, 61, 0.5 ) );
	animation: tale-tick 520ms cubic-bezier( 0.2, 0.9, 0.3, 1.4 ) both;
	animation-play-state: paused;
}

.tale-welcome.is-on .tale-welcome__icon {
	animation-play-state: running;
}

.tale-welcome__icon svg {
	width: 17px;
	height: 17px;
}

.tale-welcome__icon--avatar {
	overflow: hidden;
	background: transparent;
	box-shadow: 0 0 0 2px var( --tale-accent, #dae83d );
}

.tale-welcome__icon--avatar img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.tale-welcome__copy {
	min-width: 0;
}

.tale-welcome__title {
	margin: 0;
	overflow: hidden;
	font-size: 15px;
	font-weight: 800;
	line-height: 1.35;
	letter-spacing: -0.1px;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.tale-welcome__sub {
	margin: 1px 0 0;
	font-size: 12.5px;
	line-height: 1.4;
	opacity: 0.62;
}

/* ================================================================== *
 * 7. Keyframes
 * ================================================================== */

@keyframes tale-rotate {
	to { transform: rotate( 360deg ); }
}

@keyframes tale-pop {
	from { opacity: 0; transform: translateY( 16px ) scale( 0.94 ); }
	to   { opacity: 1; transform: translateY( 0 ) scale( 1 ); }
}

@keyframes tale-rise {
	from { transform: translateY( 100% ); }
	to   { transform: translateY( 0 ); }
}

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

@keyframes tale-tick {
	0%   { transform: scale( 0.3 ); opacity: 0; }
	60%  { transform: scale( 1.14 ); opacity: 1; }
	100% { transform: scale( 1 ); opacity: 1; }
}

@keyframes tale-dots {
	0%   { width: 0; }
	100% { width: 1.2em; }
}

@keyframes tale-bounce {
	0%, 80%, 100% { transform: scale( 0.6 ); opacity: 0.45; }
	40%           { transform: scale( 1 );   opacity: 1; }
}

@keyframes tale-stretch {
	0%, 40%, 100% { height: 32%; }
	20%           { height: 100%; }
}

@keyframes tale-ripple {
	0%   { transform: scale( 0.25 ); opacity: 0.8; }
	100% { transform: scale( 1 );    opacity: 0; }
}

@keyframes tale-pulse {
	0%, 100% { transform: scale( 1 );    opacity: 1; }
	50%      { transform: scale( 1.07 ); opacity: 0.86; }
}

@keyframes tale-slide {
	0%   { transform: translateX( -100% ); }
	100% { transform: translateX( 350% ); }
}

/* ================================================================== *
 * 8. Small phones
 * ================================================================== */

@media ( max-width: 400px ) {
	.tale-veil--card .tale-veil__inner {
		padding: 28px 22px 24px;
	}

	.tale-veil__title {
		font-size: calc( var( --tale-title-size, 20px ) - 1px );
	}

	.tale-welcome {
		gap: 11px;
		padding-inline: 16px 14px;
	}
}

/* ================================================================== *
 * 9. Reduced motion
 * ================================================================== */

/* When "Respect reduced motion" is on, the plugin adds no class and the media
   query below strips the animation for visitors who asked their device to
   reduce motion. When the setting is switched off, PHP adds
   .tale-motion-always, and the :not() guards stop the media query applying -
   which is the only thing that makes the setting mean anything. */

@media ( prefers-reduced-motion: reduce ) {
	.tale-veil:not( .tale-motion-always ) .tale-veil__logo.is-pulsing,
	.tale-veil:not( .tale-motion-always ) .tale-veil__bar i,
	.tale-veil:not( .tale-motion-always ) .tale-dots::after {
		animation: none;
	}

	.tale-veil:not( .tale-motion-always ) .tale-veil__inner {
		animation: none !important;
	}

	/* The ring is the only signal that anything is happening, so it is slowed
	   rather than stopped. A frozen spinner reads as a crash. */
	.tale-veil:not( .tale-motion-always ) .tale-badge__ring {
		animation-duration: 2.4s;
	}

	.tale-welcome:not( .tale-motion-always ) .tale-welcome__icon {
		animation: none;
	}

	.tale-welcome:not( .tale-motion-always ) {
		transition-duration: 160ms;
	}
}
