/* ==========================================================================
   Jo Cor Cloud — jocor_hero
   Injected on EVERY page by Application.php::boot(). That means every rule
   here must be scoped: an unscoped `header {}` rule also hits the empty
   guest header on /login and /apps/registration, which is exactly how the
   stray dark bar and the overflowing logo got there.

   Two scopes, and nothing may leak between them:
     AUTHENTICATED  #header:not(.header-guest), #app-dashboard, ...
     GUEST          #body-login (login + registration share this body id)
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */
:root {
	--jocor-accent: #13c2c0;
	--jocor-accent-bright: #36f1ce;
	--jocor-gold: #c9a661;
	--jocor-ink: #f1f7fb;
	--jocor-muted: #9fb3c8;
	--jocor-bg: #04060f;
	--jocor-surface: #0b1120;

	/* Semantic z-index scale — no arbitrary 999s. */
	--jocor-z-canvas: 0;
	--jocor-z-content: 10;
	--jocor-z-header: 100;

	/* Product-register motion: 150–250ms, ease-out. */
	--jocor-ease: cubic-bezier(0.22, 1, 0.36, 1);
	--jocor-fast: 160ms;
	--jocor-slow: 240ms;
}

/* ==========================================================================
   2. STARFIELD CANVAS (all pages)
   ========================================================================== */
.jocor-hero-canvas {
	position: fixed;
	inset: 0;
	/* inset:0 already sizes this to the viewport; the explicit 100vw/100vh below
	   used to override it and that is what made Nextcloud look broken on a phone
	   while loading. 100vh is the viewport height with the URL bar COLLAPSED, so
	   while the bar is still showing the starfield is taller than the visible
	   area and visibly jumps as the bar animates away. 100vw likewise ignores the
	   scrollbar. The vh/vw pair stays first as the fallback for browsers without
	   dynamic viewport units; dvh/dvw wins where supported and tracks what you
	   can actually see. */
	width: 100vw;
	height: 100vh;
	width: 100dvw;
	height: 100dvh;
	z-index: var(--jocor-z-canvas);
	pointer-events: none;
	display: block;
	transition: opacity var(--jocor-slow) var(--jocor-ease);
}

html,
body {
	background-color: var(--jocor-bg) !important;
}

#content,
#app-content {
	background: transparent !important;
}

/* ==========================================================================
   3. AUTHENTICATED CHROME
   Every selector below is guarded against the guest header. Without the
   :not(.header-guest) guard these rules paint a 64px bar across /login.
   ========================================================================== */
#header:not(.header-guest) {
	height: 64px !important;
	background: rgba(8, 10, 22, 0.88) !important;
	backdrop-filter: blur(24px) saturate(180%) !important;
	-webkit-backdrop-filter: blur(24px) saturate(180%) !important;
	border-bottom: 1px solid rgba(19, 194, 192, 0.25) !important;
	position: relative;
	z-index: var(--jocor-z-header) !important;
}

#header:not(.header-guest) .header-left,
#header:not(.header-guest) .header-right,
#header:not(.header-guest) .header-app,
#header:not(.header-guest) #header-actions {
	height: 64px !important;
	display: flex !important;
	align-items: center !important;
}

#header:not(.header-guest) .header-app .app-image,
#header:not(.header-guest) .app-image,
#header:not(.header-guest) .logo {
	width: 38px !important;
	height: 38px !important;
	max-width: 38px !important;
	max-height: 38px !important;
	background-size: contain !important;
	background-repeat: no-repeat !important;
	background-position: center !important;
	/* Jo 2026-07-27: nudged +6px down so the mark sits centered with the
	   64px header bar (previous 4px made it feel glued to the top edge). */
	margin: 10px 12px 0 10px !important;
	padding: 0 !important;
	background-image: url('../img/logo-mark-64.webp') !important;
	transition: transform var(--jocor-slow) var(--jocor-ease),
		filter var(--jocor-slow) var(--jocor-ease) !important;
	filter: drop-shadow(0 0 8px rgba(19, 194, 192, 0.5)) invert(1) !important;
	box-sizing: border-box !important;
	overflow: visible !important;
}

#header:not(.header-guest) .app-image:hover,
#header:not(.header-guest) .logo:hover {
	transform: scale(1.08) !important;
	filter: drop-shadow(0 0 16px rgba(54, 241, 206, 0.9)) invert(1) !important;
}

#header:not(.header-guest) {
	overflow: visible !important;
}

#header:not(.header-guest) .header-right {
	display: flex !important;
	align-items: center !important;
	gap: 14px !important;
	padding-right: 20px !important;
	overflow: visible !important;
}

/* Uniform 44px hit area for header icon buttons. NEVER include .avatardiv:
   that 12px radius + 44px box squared the account photo and cut the sides. */
#header:not(.header-guest) .header-right > button,
#header:not(.header-guest) .header-right > a,
#header:not(.header-guest) .header-right .header-actions__button {
	flex-shrink: 0 !important;
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	min-width: 44px !important;
	height: 44px !important;
}

#header:not(.header-guest) .header-right button svg,
#header:not(.header-guest) .header-right a svg,
#header:not(.header-guest) .header-right .header-actions__button svg {
	opacity: 0.92 !important;
	transition: opacity var(--jocor-fast) var(--jocor-ease) !important;
}
#header:not(.header-guest) .header-right button:hover svg,
#header:not(.header-guest) .header-right a:hover svg {
	opacity: 1 !important;
}

#header:not(.header-guest) .header-right button:not(.header-menu__trigger),
#header:not(.header-guest) .header-right a:not(.header-menu__trigger),
#header:not(.header-guest) .header-actions__button {
	border-radius: 12px !important;
	transition: background var(--jocor-fast) var(--jocor-ease),
		box-shadow var(--jocor-fast) var(--jocor-ease),
		transform var(--jocor-fast) var(--jocor-ease) !important;
}

#header:not(.header-guest) .header-right button:not(.header-menu__trigger):hover,
#header:not(.header-guest) .header-right a:not(.header-menu__trigger):hover {
	background: rgba(19, 194, 192, 0.15) !important;
	box-shadow: 0 0 12px rgba(19, 194, 192, 0.4) !important;
	transform: translateY(-1px) !important;
}

#header:not(.header-guest) .user-menu {
	flex-shrink: 0 !important;
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	height: 64px !important;
	overflow: visible !important;
	margin-inline-end: 2px !important;
}
#header:not(.header-guest) .header-menu .header-menu__trigger,
#header:not(.header-guest) .user-menu .header-menu__trigger {
	width: 44px !important;
	height: 44px !important;
	min-width: 44px !important;
	min-height: 44px !important;
	padding: 0 !important;
	border-radius: 8px !important;
	overflow: hidden !important;
	transform: none !important;
	background: transparent !important;
	box-shadow: none !important;
	display: grid !important;
	place-items: center !important;
}
#header:not(.header-guest) .user-menu .header-menu__trigger:hover {
	background: rgba(19, 194, 192, 0.12) !important;
	box-shadow: none !important;
	transform: none !important;
}
#header:not(.header-guest) .avatardiv {
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	width: 36px !important;
	height: 36px !important;
	min-width: 36px !important;
	min-height: 36px !important;
	max-width: 36px !important;
	max-height: 36px !important;
	padding: 0 !important;
	margin: 0 auto !important;
	line-height: 0 !important;
	border: 0 !important;
	border-radius: 50% !important;
	overflow: visible !important;
	flex-shrink: 0 !important;
	transform: none !important;
	clip-path: none !important;
	box-sizing: content-box !important;
	background-size: contain !important;
	background-position: center !important;
	background-repeat: no-repeat !important;
	box-shadow: none !important;
}
#header:not(.header-guest) .avatardiv img {
	width: 30px !important;
	height: 30px !important;
	max-width: 30px !important;
	max-height: 30px !important;
	object-fit: contain !important;
	object-position: center !important;
	border: 0 !important;
	border-radius: 50% !important;
	display: block !important;
	clip-path: none !important;
	margin: 0 !important;
}

/* Phone: keep the circle fully inside the bar, with room on both sides. */
@media (max-width: 720px) {
	#header:not(.header-guest) {
		padding-inline-end: max(18px, env(safe-area-inset-right, 0px)) !important;
		overflow: visible !important;
	}
	#header:not(.header-guest) .header-right {
		gap: 0 !important;
		padding-right: 18px !important;
		margin-right: 0 !important;
		overflow: visible !important;
	}
	#header:not(.header-guest) .header-right > button,
	#header:not(.header-guest) .header-right > a,
	#header:not(.header-guest) .header-right .header-actions__button {
		min-width: 36px !important;
		width: 36px !important;
		height: 36px !important;
		padding: 0 !important;
	}
	#header:not(.header-guest) .user-menu {
		width: 40px !important;
		margin-inline-end: 12px !important;
		overflow: visible !important;
	}
	#header:not(.header-guest) .user-menu .header-menu__trigger {
		width: 40px !important;
		height: 40px !important;
		min-width: 40px !important;
		min-height: 40px !important;
		overflow: visible !important;
	}
	#header:not(.header-guest) .avatardiv {
		width: 32px !important;
		height: 32px !important;
		min-width: 32px !important;
		min-height: 32px !important;
		max-width: 32px !important;
		max-height: 32px !important;
	}
	#header:not(.header-guest) .avatardiv img {
		width: 26px !important;
		height: 26px !important;
		min-width: 26px !important;
		min-height: 26px !important;
		max-width: 26px !important;
		max-height: 26px !important;
	}
}

/* ---- Dashboard ---- */
#app-dashboard .dashboard-heading,
#app-dashboard h2 {
	text-align: center !important;
	justify-content: center !important;
	width: 100% !important;
	margin: 0 auto 12px auto !important;
	display: flex !important;
	align-items: center !important;
}

#app-dashboard {
	padding: 24px !important;
}

#app-dashboard .panel,
#app-dashboard .dashboard-widget,
#app-dashboard .card,
#app-dashboard .app-dashboard-card,
#app-dashboard .vue-dashboard-widget,
#app-dashboard .dashboard-widget__content {
	background: rgba(10, 14, 26, 0.72) !important;
	backdrop-filter: blur(24px) saturate(180%) !important;
	-webkit-backdrop-filter: blur(24px) saturate(180%) !important;
	border: 1px solid rgba(19, 194, 192, 0.22) !important;
	border-radius: 16px !important;
	padding: 16px !important;
	transition: border-color var(--jocor-slow) var(--jocor-ease),
		transform var(--jocor-slow) var(--jocor-ease) !important;
}

#app-dashboard .panel:hover,
#app-dashboard .dashboard-widget:hover,
#app-dashboard .card:hover,
#app-dashboard .vue-dashboard-widget:hover {
	border-color: rgba(54, 241, 206, 0.45) !important;
	transform: translateY(-2px);
}

/* ---- Starfield toggle (authenticated only) ---- */
.nyx-stars-toggle-container {
	display: flex !important;
	justify-content: center !important;
	align-items: center !important;
	margin: 10px auto 16px auto !important;
	width: 100% !important;
	pointer-events: none !important;
}

.nyx-dashboard-toggle-wrap {
	display: inline-flex !important;
	align-items: center !important;
	gap: 10px !important;
	background: rgba(10, 13, 26, 0.85) !important;
	backdrop-filter: blur(20px) !important;
	-webkit-backdrop-filter: blur(20px) !important;
	border: 1px solid rgba(19, 194, 192, 0.35) !important;
	border-radius: 999px !important;
	padding: 5px 16px !important;
	font-size: 13px !important;
	font-weight: 500 !important;
	color: var(--jocor-ink) !important;
	user-select: none !important;
	cursor: pointer !important;
	pointer-events: auto !important;
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35) !important;
	transition: border-color var(--jocor-fast) var(--jocor-ease),
		transform var(--jocor-fast) var(--jocor-ease),
		box-shadow var(--jocor-fast) var(--jocor-ease) !important;
}

.nyx-dashboard-toggle-wrap:hover {
	border-color: rgba(54, 241, 206, 0.6) !important;
	box-shadow: 0 4px 20px rgba(19, 194, 192, 0.25) !important;
	transform: translateY(-1px);
}

.nyx-dashboard-toggle-wrap:active {
	transform: translateY(0);
}

.nyx-dashboard-toggle-wrap:focus-visible {
	outline: 2px solid var(--jocor-accent-bright) !important;
	outline-offset: 2px !important;
}

.nyx-bubble-label {
	font-size: 13px;
	font-weight: 500;
	color: #e2e8f0;
	cursor: pointer;
	letter-spacing: 0.02em;
	white-space: nowrap;
}

.nyx-switch {
	position: relative;
	display: inline-block;
	width: 36px;
	height: 18px;
	cursor: pointer;
}

.nyx-switch input {
	opacity: 0;
	width: 0;
	height: 0;
	position: absolute;
}

.nyx-switch-slider {
	position: absolute;
	cursor: pointer;
	inset: 0;
	background-color: rgba(255, 255, 255, 0.15);
	border: 1px solid rgba(19, 194, 192, 0.3);
	transition: var(--jocor-slow) var(--jocor-ease);
	border-radius: 999px;
	pointer-events: auto;
}

.nyx-switch-slider:before {
	position: absolute;
	content: "";
	height: 12px;
	width: 12px;
	left: 2px;
	bottom: 2px;
	background-color: #8da4b8;
	transition: var(--jocor-slow) var(--jocor-ease);
	border-radius: 50%;
}

.nyx-switch input:checked + .nyx-switch-slider {
	background-color: rgba(19, 194, 192, 0.4);
	border-color: var(--jocor-accent-bright);
}

.nyx-switch input:checked + .nyx-switch-slider:before {
	transform: translateX(18px);
	background-color: var(--jocor-accent-bright);
}

.nyx-switch input:focus-visible + .nyx-switch-slider {
	outline: 2px solid var(--jocor-accent-bright);
	outline-offset: 2px;
}

/* ==========================================================================
   4. GUEST PAGES — /login and /apps/registration
   Both render into <body id="body-login"> and share .guest-box, so this
   block styles them as one surface.

   The load-bearing idea: the registration app's signup.css is written
   entirely against Nextcloud theme variables. Redefining those variables
   here restyles every field, button and note on BOTH pages at once —
   no per-element overrides, and it keeps working if the app updates.
   ========================================================================== */
#body-login {
	--color-main-background: var(--jocor-surface);
	--color-main-background-blur: rgba(11, 17, 32, 0.9);
	--color-main-text: var(--jocor-ink);
	--color-text-maxcontrast: var(--jocor-muted);
	--color-text-light: var(--jocor-ink);
	--color-primary-element: var(--jocor-accent);
	--color-primary-element-hover: var(--jocor-accent-bright);
	--color-primary-element-text: #04060f;
	--color-primary-element-light: rgba(19, 194, 192, 0.16);
	--color-primary-element-light-hover: rgba(19, 194, 192, 0.26);
	--color-border: rgba(19, 194, 192, 0.18);
	--color-border-dark: rgba(19, 194, 192, 0.3);
	--color-border-maxcontrast: rgba(159, 179, 200, 0.55);
	--color-background-hover: rgba(19, 194, 192, 0.1);
	--color-background-dark: rgba(255, 255, 255, 0.06);
	--color-error: #ff8a8a;
	--color-success: var(--jocor-accent-bright);
	--color-warning: var(--jocor-gold);

	color: var(--jocor-ink);
	/* Depth behind the starfield: a cool core fading to near-black, so the
	   card reads as floating in the same sky as the rest of the product. */
	background-color: var(--jocor-bg) !important;
	background-image:
		radial-gradient(ellipse 90% 60% at 50% 0%, rgba(19, 194, 192, 0.14), transparent 70%),
		radial-gradient(ellipse 70% 50% at 50% 100%, rgba(201, 166, 97, 0.07), transparent 70%) !important;
	background-attachment: fixed !important;
}

/* The guest header is an empty shell that only carries the logo. Give it
   no bar, no blur, no fixed height — just room for the mark. */
#body-login header,
#header.header-guest {
	height: auto !important;
	min-height: 0 !important;
	background: none !important;
	backdrop-filter: none !important;
	-webkit-backdrop-filter: none !important;
	border: none !important;
	box-shadow: none !important;
	display: block !important;
	position: static !important;
	padding: 0 !important;
}

/* The login mark itself is owned by logo-swap.css — the full hero logo at
   200x156 with its layered glow. Do NOT set size, image or filter here:
   #header.header-guest .logo (1,2,0) outranks that file's #body-login .logo
   (1,1,0) and silently replaces the hero logo with the tiny header mark.
   Only stacking context belongs here. */
#header.header-guest .logo {
	position: relative;
	z-index: var(--jocor-z-content);
}

/* Keep the form above the canvas. */
#body-login .wrapper,
#body-login .guest-content,
#body-login footer {
	position: relative;
	z-index: var(--jocor-z-content);
}

/* ---- Brand line above the card ----
   Injected by jocor_hero.js on guest pages. Lives outside the card so the
   card stays a plain task surface and the brand voice sits above it. */
.jocor-guest-tagline {
	position: relative;
	z-index: var(--jocor-z-content);
	margin: 0 auto 20px auto;
	max-width: 34ch;
	text-align: center;
	text-wrap: balance;
	color: var(--jocor-ink);
	font-size: 1.6rem;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: -0.02em;
}

.jocor-guest-tagline__sub {
	display: block;
	margin-top: 8px;
	font-size: 0.9rem;
	font-weight: 400;
	letter-spacing: 0.01em;
	color: var(--jocor-muted);
}

/* ---- The card ---- */
#body-login .guest-box {
	background: rgba(11, 17, 32, 0.94) !important;
	/* Purposeful, not decorative: the card sits over a moving starfield and
	   the blur is what keeps the form legible while stars pass behind it.
	   The background stays near-opaque so contrast holds without it. */
	backdrop-filter: blur(14px) !important;
	-webkit-backdrop-filter: blur(14px) !important;
	border: 1px solid rgba(19, 194, 192, 0.28) !important;
	border-radius: 16px !important;
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.55) !important;
	color: var(--jocor-ink) !important;
	padding: 28px 26px !important;
}

#body-login .guest-box h2,
#body-login .signup-form__heading,
#body-login .login-box__header {
	color: var(--jocor-ink) !important;
	font-size: 1.35rem !important;
	font-weight: 600 !important;
	letter-spacing: -0.015em;
	text-wrap: balance;
	margin-bottom: 6px !important;
}

#body-login .signup-form__intro,
#body-login .guest-box p {
	color: var(--jocor-muted) !important;
}

/* ---- Fields: default / hover / focus / disabled ---- */
#body-login input[type="text"],
#body-login input[type="email"],
#body-login input[type="tel"],
#body-login input[type="password"],
#body-login .signup-field input {
	background-color: rgba(255, 255, 255, 0.05) !important;
	border: 1px solid rgba(159, 179, 200, 0.4) !important;
	border-radius: 10px !important;
	color: var(--jocor-ink) !important;
	transition: border-color var(--jocor-fast) var(--jocor-ease),
		background-color var(--jocor-fast) var(--jocor-ease) !important;
}

#body-login input::placeholder {
	color: #8da4b8 !important;
	opacity: 1 !important;
}

#body-login input:hover:not(:disabled) {
	border-color: rgba(19, 194, 192, 0.6) !important;
	background-color: rgba(255, 255, 255, 0.07) !important;
}

#body-login input:focus,
#body-login input:focus-visible {
	border-color: var(--jocor-accent-bright) !important;
	outline: 2px solid rgba(54, 241, 206, 0.35) !important;
	outline-offset: 1px !important;
	background-color: rgba(255, 255, 255, 0.08) !important;
}

#body-login input:disabled {
	opacity: 0.5 !important;
	cursor: not-allowed !important;
}

/* ---- Field spacing (Jo 2026-07-27) ----
   Login form fields stacked too tight against each other; this inserts
   a deliberate 14px vertical rhythm between inputs and a 12px gap before
   the submit button so the card breathes. */
#body-login .login-box__form,
#body-login .login-form,
#body-login .signup-form {
	display: flex;
	flex-direction: column;
}

#body-login .login-box__form > *,
#body-login .login-form > * {
	margin-top: 0;
	margin-bottom: 14px;
}

#body-login .login-box__form > *:last-child,
#body-login .login-form > *:last-child {
	margin-bottom: 0;
}

#body-login button[type="submit"],
#body-login .button-vue--vue-primary,
#body-login input[type="submit"] {
	margin-top: 8px !important;
}

/* Slight breathing room between the "Log in" button and the secondary
   "Log in with …" / register link that follows it. */
#body-login .login-box__footer,
#body-login .login-additional,
#body-login .login-bottom-text,
#body-login .signup-form__secondary {
	margin-top: 18px !important;
}

/* ---- Primary action ---- */
#body-login button[type="submit"],
#body-login .button-vue--vue-primary,
#body-login input[type="submit"] {
	background-color: var(--jocor-accent) !important;
	/* Dark ink on teal: white would land at 2.2:1 and fail. */
	color: #04060f !important;
	border: none !important;
	border-radius: 10px !important;
	font-weight: 600 !important;
	transition: background-color var(--jocor-fast) var(--jocor-ease),
		transform var(--jocor-fast) var(--jocor-ease) !important;
}

#body-login button[type="submit"]:hover:not(:disabled),
#body-login .button-vue--vue-primary:hover:not(:disabled) {
	background-color: var(--jocor-accent-bright) !important;
	transform: translateY(-1px);
}

#body-login button[type="submit"]:focus-visible,
#body-login .button-vue--vue-primary:focus-visible {
	outline: 2px solid var(--jocor-accent-bright) !important;
	outline-offset: 2px !important;
}

#body-login button[type="submit"]:disabled,
#body-login .button-vue--vue-primary:disabled {
	background-color: rgba(19, 194, 192, 0.28) !important;
	color: rgba(241, 247, 251, 0.55) !important;
	cursor: not-allowed !important;
	transform: none !important;
}

/* ---- Secondary / links ---- */
#body-login .button-vue--vue-secondary,
#body-login .button-vue--vue-tertiary {
	background-color: rgba(255, 255, 255, 0.07) !important;
	color: var(--jocor-ink) !important;
	border: 1px solid rgba(19, 194, 192, 0.28) !important;
	border-radius: 10px !important;
}

#body-login .button-vue--vue-secondary:hover,
#body-login .button-vue--vue-tertiary:hover {
	background-color: rgba(19, 194, 192, 0.16) !important;
	border-color: rgba(54, 241, 206, 0.5) !important;
}

#body-login a {
	color: var(--jocor-accent-bright) !important;
}

#body-login a:hover {
	color: var(--jocor-gold) !important;
}

/* ---- Checkbox / radio accent ---- */
#body-login input[type="checkbox"],
#body-login input[type="radio"] {
	accent-color: var(--jocor-accent) !important;
}

/* ---- Footer is also .guest-box; it must not read as a second card ---- */
#body-login footer.guest-box {
	background: none !important;
	backdrop-filter: none !important;
	-webkit-backdrop-filter: none !important;
	border: none !important;
	box-shadow: none !important;
	color: var(--jocor-muted) !important;
	padding: 14px 0 !important;
	font-size: 0.82rem !important;
}

#body-login footer.guest-box a {
	color: var(--jocor-muted) !important;
	text-decoration: underline;
	text-underline-offset: 2px;
}

#body-login footer.guest-box a:hover {
	color: var(--jocor-accent-bright) !important;
}

/* ==========================================================================
   5. TYPOGRAPHY — Geist across the product
   ========================================================================== */
@font-face {
	font-family: 'Geist';
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url('/custom_apps/jocor_hero/fonts/Geist[wght].woff2') format('woff2');
}

@font-face {
	font-family: 'Geist Mono';
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url('/custom_apps/jocor_hero/fonts/GeistMono[wght].woff2') format('woff2');
}

:root {
	--font-sans: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
	--font-mono: 'Geist Mono', ui-monospace, monospace !important;
}

body,
html,
input,
button,
select,
textarea,
#body-login,
.app-navigation,
.app-content {
	font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

/* ==========================================================================
   6. REDUCED MOTION
   The starfield is ambient decoration; under reduce it should hold still
   rather than crossfade forever.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
	.jocor-hero-canvas {
		display: none !important;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
	}
}

/* ==========================================================================
   8. PRESTIGE v5 — Jo 2026-07-27
   Supersedes v4. Four things v4 got wrong and this fixes:

     1. Card geometry was inherited from whatever page you were on, so /login
        (318px) and /apps/registration (397px) rendered two different frames.
        Geometry is now a token set applied to every guest surface at once.
     2. The card was only "ultra-transparent" in the comment — 0.22 alpha over
        a 36px blur reads as solid. The stars now actually come through.
     3. LOG IN / Register were two unrelated shapes. They are one pair now:
        same width, same rhythm, primary in metal, secondary in hairline gold.
     4. Nothing reserved space for the password generator's output, so
        "Generate a strong password" grew the card by ~60px. Space is now
        reserved whether or not the message is showing.
   ========================================================================== */

#body-login {
	/* One geometry for every guest surface. Change it here, not per page. */
	--jocor-card-w: 430px;
	--jocor-card-r: 24px;
	--jocor-card-pad: 40px;
	--jocor-btn-h: 56px;
	--jocor-btn-r: 14px;

	--jocor-au: #d4af37;          /* gold */
	--jocor-au-lit: #f7e8bd;      /* lit gold — text on dark */
	--jocor-au-white: #fff4d8;    /* specular */
}

/* ---- The frame: one card, every guest page -------------------------------
   A double stroke — an outer gold hairline and an inset light ring — is what
   separates a prestige frame from a glowing rectangle. The breathing is slow
   (9s) and shallow on purpose; v4's 5s pulse read as a notification badge. */
@keyframes jocor-frame-glow {
	0%, 100% {
		border-color: rgba(212, 175, 55, 0.44);
		box-shadow:
			0 0 0 1px rgba(255, 244, 216, 0.10),
			0 0 40px -6px rgba(212, 175, 55, 0.30),
			0 28px 90px -24px rgba(0, 0, 0, 0.9);
	}
	50% {
		border-color: rgba(255, 235, 175, 0.66);
		box-shadow:
			0 0 0 1px rgba(255, 244, 216, 0.20),
			0 0 56px -4px rgba(212, 175, 55, 0.46),
			0 28px 100px -20px rgba(0, 0, 0, 0.92);
	}
}

#body-login .guest-box:not(footer) {
	width: min(var(--jocor-card-w), calc(100vw - 32px)) !important;
	max-width: none !important;
	margin-left: auto !important;
	margin-right: auto !important;
	box-sizing: border-box !important;
	padding: var(--jocor-card-pad) var(--jocor-card-pad) 32px !important;
	border-radius: var(--jocor-card-r) !important;

	/* Genuinely transparent. The blur is what carries legibility, not the
	   fill — at 0.16 the starfield reads through the card without the text
	   ever dropping below AA on the ink colours used here. */
	background-color: rgba(4, 7, 16, 0.16) !important;
	backdrop-filter: blur(44px) saturate(150%) !important;
	-webkit-backdrop-filter: blur(44px) saturate(150%) !important;

	border: 1px solid rgba(212, 175, 55, 0.48) !important;
	animation: jocor-frame-glow 9s ease-in-out infinite !important;
	position: relative !important;
	isolation: isolate;
}

/* Inset ring — the second stroke of the double frame. */
#body-login .guest-box:not(footer)::before {
	content: "";
	position: absolute;
	inset: 7px;
	border: 1px solid rgba(255, 244, 216, 0.13);
	border-radius: calc(var(--jocor-card-r) - 8px);
	pointer-events: none;
	/* Above the card's own fill, not behind it — at 0.16 alpha a ring painted
	   underneath is washed out to nothing. It never covers a control: it is a
	   1px inset hairline with pointer-events off. */
	z-index: 4;
}

/* A single specular sweep across the top edge, the way light catches a
   bevelled frame. Static — one more animation here would be noise. */
#body-login .guest-box:not(footer)::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 1px;
	background: linear-gradient(90deg,
		transparent 0%,
		rgba(255, 244, 216, 0.55) 30%,
		rgba(255, 255, 255, 0.7) 50%,
		rgba(255, 244, 216, 0.55) 70%,
		transparent 100%);
	border-radius: var(--jocor-card-r) var(--jocor-card-r) 0 0;
	pointer-events: none;
	z-index: 4;
}

/* ---- Headings ------------------------------------------------------------ */
@keyframes jocor-gold-shimmer {
	0%   { background-position: 0% 50%; }
	50%  { background-position: 100% 50%; }
	100% { background-position: 0% 50%; }
}

#body-login .guest-box h2.login-form__headline,
#body-login .guest-box h2.login-box__header,
#body-login .guest-box h2.signup-form__heading,
#body-login .guest-box h2 {
	background-image: linear-gradient(120deg,
		#d4af37 0%, #fff4d8 25%, #d4af37 50%, #f7e8bd 75%, #aa820a 100%) !important;
	background-size: 200% auto !important;
	-webkit-background-clip: text !important;
	background-clip: text !important;
	color: transparent !important;
	-webkit-text-fill-color: transparent !important;
	animation: jocor-gold-shimmer 6s ease-in-out infinite !important;
	font-family: 'Geist', system-ui, sans-serif !important;
	font-size: 1.6rem !important;
	font-weight: 800 !important;
	letter-spacing: 0.22em !important;
	/* Trailing letter-spacing pushes centred text left by half a space;
	   the indent puts it back on the optical centre. */
	text-indent: 0.22em !important;
	line-height: 1.25 !important;
	text-transform: uppercase !important;
	text-align: center !important;
	text-wrap: balance;
	margin: 0 0 26px 0 !important;
	padding: 0 !important;
	filter: drop-shadow(0 0 18px rgba(212, 175, 55, 0.45)) !important;
}

/* Belt and braces on the login headline: if the Vue form ever re-renders
   before the rebrand script reaches it, the raw "Log in to …" string must not
   be able to paint. jocor_hero.js sets the attribute on mount and clears it
   the moment the text is swapped, so nothing can be left permanently blank. */
#body-login .guest-box h2[data-jocor-pending] {
	visibility: hidden !important;
}

#body-login .signup-form__intro {
	color: rgba(212, 175, 55, 0.85) !important;
	text-align: center !important;
	margin: -12px 0 26px 0 !important;
	font-size: 0.94rem !important;
	letter-spacing: 0.03em !important;
}

/* ---- Fields -------------------------------------------------------------- */
#body-login input[type="text"],
#body-login input[type="email"],
#body-login input[type="tel"],
#body-login input[type="password"],
#body-login .signup-field input {
	width: 100% !important;
	box-sizing: border-box !important;
	background-color: rgba(8, 10, 22, 0.34) !important;
	border: 1px solid rgba(212, 175, 55, 0.36) !important;
	border-radius: var(--jocor-btn-r) !important;
	padding: 15px 18px !important;
	font-size: 1rem !important;
	color: var(--jocor-au-lit) !important;
	box-shadow: 0 4px 18px rgba(0, 0, 0, 0.3),
		inset 0 0 14px rgba(212, 175, 55, 0.05) !important;
	transition: border-color 0.25s ease, background-color 0.25s ease,
		box-shadow 0.25s ease !important;
	margin-bottom: 0 !important;
}

#body-login .input-field,
#body-login .signup-field {
	margin-bottom: 18px !important;
}

#body-login input:hover:not(:disabled) {
	border-color: rgba(212, 175, 55, 0.72) !important;
	background-color: rgba(16, 20, 40, 0.42) !important;
	box-shadow: 0 4px 22px rgba(212, 175, 55, 0.2),
		inset 0 0 18px rgba(212, 175, 55, 0.09) !important;
}

#body-login input:focus,
#body-login input:focus-visible {
	border-color: var(--jocor-au-white) !important;
	outline: none !important;
	box-shadow: 0 0 26px rgba(212, 175, 55, 0.5),
		inset 0 0 18px rgba(212, 175, 55, 0.14) !important;
	background-color: rgba(20, 26, 50, 0.5) !important;
}

#body-login .input-field.input-field--trailing-icon {
	margin-bottom: 18px !important;
}

#body-login .checkbox-radio-switch,
#body-login [data-login-form-input-rememberme] {
	margin: 6px 0 18px 0 !important;
}

/* ---- Primary action: LOG IN / CONTINUE / CREATE ACCOUNT ------------------
   One shape for all three. The label is centred on the button, and the arrow
   is taken out of flow so its hover nudge cannot shift the text with it —
   that wobble was most of what made v4's LOG IN feel cheap. */
#body-login .guest-box button[type="submit"],
#body-login .guest-box input[type="submit"],
#body-login .guest-box .button-vue--vue-primary,
#body-login .guest-box .signup-button--primary {
	position: relative !important;
	width: 100% !important;
	min-height: var(--jocor-btn-h) !important;
	box-sizing: border-box !important;
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	padding: 0 46px !important;
	margin: 6px 0 0 0 !important;

	background: linear-gradient(158deg,
		#fffaf0 0%, #f3dfa8 18%, #d9b957 44%,
		#c39a26 68%, #a67c0c 88%, #8a6606 100%) !important;
	border: 1px solid rgba(255, 248, 220, 0.85) !important;
	border-radius: var(--jocor-btn-r) !important;
	color: #170f02 !important;
	cursor: pointer !important;

	font-family: 'Geist', system-ui, sans-serif !important;
	font-weight: 700 !important;
	font-size: 1rem !important;
	letter-spacing: 0.2em !important;
	text-indent: 0.2em !important;    /* optical centring, see heading */
	text-transform: uppercase !important;
	/* Engraved, not printed: a light edge above, a dark one below. */
	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5),
		0 -1px 0 rgba(0, 0, 0, 0.12) !important;

	box-shadow:
		0 1px 0 rgba(255, 255, 255, 0.75) inset,
		0 -1px 0 rgba(120, 88, 6, 0.45) inset,
		0 10px 30px -6px rgba(212, 175, 55, 0.6),
		0 0 22px rgba(212, 175, 55, 0.3) !important;
	transition: background 0.25s ease, transform 0.2s cubic-bezier(0.16, 1, 0.3, 1),
		box-shadow 0.25s ease !important;
}

/* Nextcloud ships its own icon slot in the login button; the arrow is ours. */
#body-login .guest-box button[type="submit"] .icon,
#body-login .guest-box button[type="submit"] svg,
#body-login .guest-box button[type="submit"] img,
#body-login .guest-box .button-vue--vue-primary .icon,
#body-login .guest-box .button-vue--vue-primary svg,
#body-login .guest-box .button-vue--vue-primary img {
	display: none !important;
}

#body-login .guest-box button[type="submit"]::after,
#body-login .guest-box .button-vue--vue-primary::after,
#body-login .guest-box .signup-button--primary::after {
	content: "\2192" !important;      /* → */
	position: absolute !important;
	right: 22px !important;
	top: 50% !important;
	font-size: 1.2rem !important;
	font-weight: 600 !important;
	line-height: 1 !important;
	text-indent: 0 !important;
	text-shadow: none !important;
	transform: translateY(-50%) !important;
	transition: transform 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important;
}

#body-login .guest-box button[type="submit"]:hover:not(:disabled)::after,
#body-login .guest-box .button-vue--vue-primary:hover:not(:disabled)::after,
#body-login .guest-box .signup-button--primary:hover:not(:disabled)::after {
	transform: translateY(-50%) translateX(6px) !important;
}

#body-login .guest-box button[type="submit"]:hover:not(:disabled),
#body-login .guest-box .button-vue--vue-primary:hover:not(:disabled),
#body-login .guest-box .signup-button--primary:hover:not(:disabled) {
	background: linear-gradient(158deg,
		#ffffff 0%, #fdf3d9 22%, #eccf78 50%, #d3ab3c 78%, #b5871a 100%) !important;
	transform: translateY(-2px) !important;
	box-shadow:
		0 1px 0 rgba(255, 255, 255, 0.9) inset,
		0 -1px 0 rgba(120, 88, 6, 0.4) inset,
		0 16px 40px -8px rgba(212, 175, 55, 0.8),
		0 0 30px rgba(212, 175, 55, 0.5) !important;
}

#body-login .guest-box button[type="submit"]:active:not(:disabled),
#body-login .guest-box .signup-button--primary:active:not(:disabled) {
	transform: translateY(0) !important;
	box-shadow:
		0 2px 6px rgba(0, 0, 0, 0.35) inset,
		0 4px 14px -4px rgba(212, 175, 55, 0.5) !important;
}

#body-login .guest-box button[type="submit"]:focus-visible,
#body-login .guest-box .signup-button--primary:focus-visible {
	outline: 2px solid var(--jocor-au-white) !important;
	outline-offset: 3px !important;
}

#body-login .guest-box button[type="submit"]:disabled,
#body-login .guest-box .button-vue--vue-primary:disabled,
#body-login .guest-box .signup-button--primary:disabled {
	background: linear-gradient(158deg, #6d6350 0%, #574d38 60%, #453c2a 100%) !important;
	border-color: rgba(255, 248, 220, 0.28) !important;
	color: rgba(255, 244, 216, 0.55) !important;
	text-shadow: none !important;
	box-shadow: none !important;
	transform: none !important;
	cursor: not-allowed !important;
}

/* ---- Secondary action: Register / Back to login --------------------------
   Same footprint as the primary so the pair reads as one control stack.
   Hairline gold on glass — an invitation, not a competing call to action.

   The login page's Register link lives in #alternative-logins, a sibling of
   the form and *outside* .guest-box, so it must be matched without that
   ancestor or it keeps core's grey .button-vue--vue-secondary styling. */
#body-login a.register-button,
#body-login #alternative-logins a,
#body-login .login-bottom-text a,
#body-login .login-additional a,
#body-login .signup-form__secondary a,
#body-login a[href*="register"],
#body-login a[href*="signup"],
#body-login .guest-box .signup-button--tertiary {
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	width: 100% !important;
	min-height: 52px !important;
	box-sizing: border-box !important;
	/* The gap is owned by the wrapper below, not by this margin: a top margin
	   on the first child of #alternative-logins collapses straight out of it
	   and the button ends up welded to LOG IN. */
	margin: 0 !important;
	padding: 0 20px !important;

	background: linear-gradient(158deg,
		rgba(212, 175, 55, 0.14) 0%,
		rgba(212, 175, 55, 0.05) 45%,
		rgba(10, 14, 30, 0.35) 100%) !important;
	border: 1px solid rgba(212, 175, 55, 0.5) !important;
	border-radius: var(--jocor-btn-r) !important;
	color: var(--jocor-au-lit) !important;

	font-family: 'Geist', system-ui, sans-serif !important;
	font-weight: 600 !important;
	font-size: 0.94rem !important;
	letter-spacing: 0.16em !important;
	text-indent: 0.16em !important;
	text-transform: uppercase !important;
	text-decoration: none !important;
	box-shadow:
		0 1px 0 rgba(255, 244, 216, 0.12) inset,
		0 6px 20px rgba(0, 0, 0, 0.3) !important;
	transition: background 0.25s ease, border-color 0.25s ease,
		color 0.25s ease, transform 0.2s cubic-bezier(0.16, 1, 0.3, 1),
		box-shadow 0.25s ease !important;
}

/* v4 hung a ✨ off every secondary link. Kill it. */
#body-login a.register-button::after,
#body-login #alternative-logins a::after,
#body-login .login-bottom-text a::after,
#body-login .login-additional a::after,
#body-login a[href*="register"]::after,
#body-login a[href*="signup"]::after,
#body-login .guest-box .signup-button--tertiary::after {
	content: none !important;
}

/* The wrapper carries the gap to the primary button. */
#body-login #alternative-logins,
#body-login .login-bottom-text,
#body-login .login-additional,
#body-login .signup-form__secondary {
	margin-top: 16px !important;
	padding-top: 0 !important;
}

/* Core's secondary-button skin would otherwise fight the rules above; the
   anchor and its inner wrapper both have to give up their own paint. */
#body-login #alternative-logins .button-vue--vue-secondary,
#body-login a.register-button {
	background-color: transparent !important;
}

#body-login #alternative-logins .button-vue__wrapper,
#body-login #alternative-logins .button-vue__text {
	color: inherit !important;
	font: inherit !important;
	letter-spacing: inherit !important;
	text-transform: inherit !important;
	margin: 0 !important;
}

#body-login a.register-button:hover,
#body-login #alternative-logins a:hover,
#body-login .login-bottom-text a:hover,
#body-login .login-additional a:hover,
#body-login .signup-form__secondary a:hover,
#body-login a[href*="register"]:hover,
#body-login a[href*="signup"]:hover,
#body-login .guest-box .signup-button--tertiary:hover {
	background: linear-gradient(158deg,
		rgba(212, 175, 55, 0.28) 0%,
		rgba(212, 175, 55, 0.14) 45%,
		rgba(24, 30, 60, 0.55) 100%) !important;
	border-color: var(--jocor-au-white) !important;
	color: #ffffff !important;
	transform: translateY(-1px) !important;
	box-shadow:
		0 1px 0 rgba(255, 244, 216, 0.28) inset,
		0 10px 28px rgba(212, 175, 55, 0.32),
		0 0 22px rgba(212, 175, 55, 0.26) !important;
}

#body-login .guest-box .signup-button--tertiary:focus-visible,
#body-login .login-bottom-text a:focus-visible {
	outline: 2px solid var(--jocor-au-white) !important;
	outline-offset: 3px !important;
}

#body-login .login-bottom-text,
#body-login .login-additional,
#body-login .signup-form__secondary {
	text-align: center !important;
	color: var(--jocor-muted) !important;
	font-size: 0.95rem !important;
	margin-top: 0 !important;
}

/* ---- Password step: the card must not change size -----------------------
   "Generate a strong password" reveals the Copy button and writes a two-line
   warning into the status line. Both were absent from the layout until the
   click, so the frame jumped ~60px. Reserve the space up front: the button
   keeps its box and only its paint is toggled, and the status line always
   holds two lines. Nothing here depends on signup-details.js, so an app
   update cannot bring the jump back. */
#body-login #signup-copy[hidden] {
	display: inline-flex !important;
	visibility: hidden !important;
}

#body-login .signup-field__actions {
	display: flex !important;
	align-items: center !important;
	gap: 16px !important;
	min-height: 24px !important;
	margin-top: 10px !important;
}

#body-login #signup-password-status {
	display: block !important;
	min-height: 2.6em !important;
	margin: 8px 0 0 0 !important;
	font-size: 0.82rem !important;
	line-height: 1.3 !important;
}

/* Step 1's availability line is a single short sentence — one line is enough,
   and reserving two is what left the dead gap under the username field. */
#body-login #signup-loginname-status {
	display: block !important;
	min-height: 1.4em !important;
	margin: 8px 0 0 0 !important;
	font-size: 0.82rem !important;
	line-height: 1.3 !important;
}

#body-login .signup-field__status--ok    { color: #7fe3b0 !important; }
#body-login .signup-field__status--error { color: #ff9b9b !important; }

/* The terms-of-service slot is empty on this instance; when it is empty it
   must not contribute height, or the two sign-up steps stop matching. */
#body-login #terms_of_service:empty {
	display: none !important;
}

/* Generate / Copy / Show read as controls, not as body links. */
#body-login .signup-link,
#body-login .signup-field__reveal {
	background: none !important;
	border: none !important;
	padding: 0 !important;
	color: rgba(212, 175, 55, 0.9) !important;
	font-size: 0.85rem !important;
	font-weight: 600 !important;
	letter-spacing: 0.04em !important;
	text-decoration: none !important;
	border-bottom: 1px solid rgba(212, 175, 55, 0.4) !important;
	cursor: pointer !important;
	transition: color 0.2s ease, border-color 0.2s ease !important;
}

#body-login .signup-link:hover,
#body-login .signup-field__reveal:hover {
	color: var(--jocor-au-white) !important;
	border-bottom-color: var(--jocor-au-white) !important;
}

#body-login .signup-field__password {
	position: relative !important;
}

#body-login .signup-field__reveal {
	position: absolute !important;
	right: 16px !important;
	top: 50% !important;
	transform: translateY(-50%) !important;
	border-bottom: none !important;
}

#body-login .signup-field__password input {
	padding-right: 68px !important;
}

/* Disabled username on step 2 is information, not a broken field. */
#body-login #signup-loginname:disabled {
	opacity: 1 !important;
	color: rgba(247, 232, 189, 0.7) !important;
	background-color: rgba(8, 10, 22, 0.5) !important;
	border-style: dashed !important;
	cursor: default !important;
}

#body-login .signup-field__label {
	display: block !important;
	margin-bottom: 7px !important;
	color: rgba(241, 247, 251, 0.9) !important;
	font-size: 0.86rem !important;
	font-weight: 600 !important;
	letter-spacing: 0.06em !important;
	text-transform: uppercase !important;
}

#body-login .signup-note {
	border-radius: 10px !important;
	padding: 10px 14px !important;
	margin: 0 0 18px 0 !important;
	font-size: 0.88rem !important;
	line-height: 1.4 !important;
}

#body-login .signup-note--error {
	background: rgba(255, 90, 90, 0.12) !important;
	border: 1px solid rgba(255, 120, 120, 0.45) !important;
	color: #ffc0c0 !important;
}

#body-login .signup-note--success {
	background: rgba(127, 227, 176, 0.1) !important;
	border: 1px solid rgba(127, 227, 176, 0.4) !important;
	color: #b8f0d5 !important;
}

/* ---- Logo ---------------------------------------------------------------- */
@keyframes jocor-prestige-pulse {
	0%, 100% {
		filter:
			invert(1)
			drop-shadow(0 0 8px rgba(19, 194, 192, 0.45))
			drop-shadow(0 0 22px rgba(201, 166, 97, 0.2))
			drop-shadow(0 4px 12px rgba(0, 0, 0, 0.6));
	}
	50% {
		filter:
			invert(1)
			drop-shadow(0 0 12px rgba(54, 241, 206, 0.65))
			drop-shadow(0 0 36px rgba(212, 175, 55, 0.4))
			drop-shadow(0 4px 14px rgba(0, 0, 0, 0.7));
	}
}

#body-login .logo {
	transition: filter 240ms ease, transform 240ms ease !important;
	animation: jocor-prestige-pulse 4.6s ease-in-out infinite;
}

#body-login .logo:hover {
	animation-duration: 2.4s;
	transform: translateY(-2px);
}

#body-login .jocor-hero-canvas {
	z-index: var(--jocor-z-canvas) !important;
}

/* Backdrop-filter is what makes a 0.16-alpha card legible. Where it is not
   supported the card must fall back to an opaque fill, not to unreadable
   text over a starfield. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	#body-login .guest-box:not(footer) {
		background-color: rgba(4, 7, 16, 0.93) !important;
	}
}

@media (prefers-reduced-motion: reduce) {
	#body-login .guest-box:not(footer),
	#body-login .guest-box h2,
	#body-login .logo {
		animation: none !important;
	}
}

@media (max-width: 480px) {
	#body-login {
		--jocor-card-pad: 26px;
	}

	#body-login .guest-box h2.login-form__headline,
	#body-login .guest-box h2.signup-form__heading,
	#body-login .guest-box h2 {
		font-size: 1.35rem !important;
		letter-spacing: 0.16em !important;
		text-indent: 0.16em !important;
	}
}

/* ==========================================================================
   Always-visible scrollbars
   --------------------------------------------------------------------------
   Nextcloud core ships `::-webkit-scrollbar { width:12px; height:12px }`
   and `scrollbar-color: var(--color-scrollbar)` on a transparent track
   (`::-webkit-scrollbar-track-piece { background: rgba(0,0,0,0) }`). On the
   dark jo-cor theme the `--color-scrollbar` token resolves to a low-contrast
   tint that disappears against the body, so the bar is technically drawn
   but invisible — looks like the scrollbar is missing.

   This block forces a visible bar on every real scroll container used in
   the Nextcloud layout (Vue app shell, Files sidebar, app navigation, the
   Talk chat, dialog bodies, the dashboard, and the file viewer). Width
   stays at 12px so the existing 12px core gutter does not reflow.

   Why this lives here and not in a browser extension: every page on
   cloud.jo-cor.com already loads jocor_hero.css (Application.php::boot()),
   so a single change here fixes the bar for every user on every device
   without requiring a per-browser extension.
   ========================================================================== */

/* 1. Firefox + Chromium 121+ — Firefox-style scrollbar-color on the root
      so any element that inherits `auto` for overflow gets the colour. */
:root {
	--color-scrollbar: rgba(180, 188, 204, 0.85) !important;
	scrollbar-color: rgba(180, 188, 204, 0.85) rgba(255, 255, 255, 0.04) !important;
}

/* 2. WebKit / Chromium / Edge / Brave — force the bar to render at the
      core's 12px width and give the track a faint fill so the gutter is
      visible even on long pages with no scroll thumb. */
::-webkit-scrollbar {
	width: 12px !important;
	height: 12px !important;
	-webkit-appearance: none !important;
	appearance: none !important;
}

::-webkit-scrollbar-track,
::-webkit-scrollbar-track-piece {
	background-color: rgba(255, 255, 255, 0.04) !important;
	border-radius: 8px !important;
}

::-webkit-scrollbar-thumb {
	background-color: rgba(180, 188, 204, 0.55) !important;
	background-clip: padding-box !important;
	border: 2px solid transparent !important;
	border-radius: 8px !important;
	min-height: 28px !important;
}

::-webkit-scrollbar-thumb:hover,
::-webkit-scrollbar-thumb:focus {
	background-color: rgba(180, 188, 204, 0.85) !important;
}

::-webkit-scrollbar-corner {
	background-color: rgba(0, 0, 0, 0) !important;
}

/* 3. Per-container — these are the scroll hosts used by Nextcloud's
      layout. Some of them (the Vue app shell, the Talk chat view) set
      `overflow: hidden` on parents and only scroll on a child; the
      ::-webkit-scrollbar rule above cascades into them, but we still
      explicitly opt-in `overflow: auto` containers so Firefox's
      `scrollbar-color` actually paints. */
html,
body,
#content,
#content-vue,
#app-content,
#app-content-vue,
#app-navigation,
.app-navigation,
.app-content-list,
.app-content-details,
.app-sidebar,
#app-sidebar,
.modal-mask .modal-wrapper .modal-container,
.dialog__content,
.oc-dialog .oc-dialog-content,
.v-popper__inner,
.v-popper__popper .v-popper__inner,
.chat-view,
#talk-chat,
#talk-list,
.app-files,
.app-files-list,
.files-list,
.files-table,
.dashboard {
	scrollbar-color: rgba(180, 188, 204, 0.85) rgba(255, 255, 255, 0.04) !important;
	scrollbar-width: thin !important;
}

/* 4. Layout-stable thumb — keep it 8px of usable area inside the 12px
      gutter so two side-by-side scrollers (Files + sidebar) do not crowd
      each other on 1280px-wide viewports. */
::-webkit-scrollbar-thumb:vertical {
	min-height: 40px !important;
}

/* Header flyouts (notifications, contacts, account) — same window as
   the apps launcher (.jl-panel): dark glass, 16px radius, teal edge. */
:is(
	#header .header-menu .header-menu__wrapper,
	#header-menu-notifications .header-menu__wrapper,
	#header-menu-contactsmenu .header-menu__wrapper,
	#header-menu-user-menu .header-menu__wrapper,
	body > .header-menu__wrapper,
	#contactsmenu .contacts-menu
) {
	color-scheme: dark;
	background: rgba(10, 14, 26, 0.94) !important;
	border: 1px solid rgba(19, 194, 192, 0.22) !important;
	border-radius: 16px !important;
	box-shadow:
		0 1px 2px rgb(0 0 0 / 20%),
		0 18px 48px -12px rgb(0 0 0 / 55%) !important;
	backdrop-filter: blur(24px) saturate(180%) !important;
	-webkit-backdrop-filter: blur(24px) saturate(180%) !important;
	color: #f1f7fb !important;
	overflow: hidden !important;
	filter: none !important;
}
#header .header-menu .header-menu__wrapper,
#header-menu-notifications .header-menu__wrapper,
#header-menu-contactsmenu .header-menu__wrapper,
#header-menu-user-menu .header-menu__wrapper,
#contactsmenu .contacts-menu {
	inline-size: min(400px, calc(100vw - 16px)) !important;
	min-width: min(400px, calc(100vw - 16px)) !important;
	max-width: min(400px, calc(100vw - 16px)) !important;
	padding: 16px !important;
}
#header .header-menu .header-menu__content,
#header-menu-notifications .header-menu__content,
#header-menu-contactsmenu .header-menu__content,
#header-menu-user-menu .header-menu__content,
#header .notification-container,
#header .notification-wrapper {
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
	backdrop-filter: none !important;
	-webkit-backdrop-filter: none !important;
	filter: none !important;
	padding: 0 !important;
	min-width: 0 !important;
	max-width: none !important;
	inline-size: auto !important;
	border-radius: 0 !important;
}
#header .header-menu__carret,
#header .header-menu__caret,
#header .header-menu .header-menu__carret,
.v-popper__arrow-container,
.v-popper__arrow-inner,
.v-popper__arrow-outer {
	display: none !important;
}
#header .notification-container,
#header .header-menu .empty-content,
#header .user-menu li,
#header .contactsmenu-contact,
#header .user-menu__nav,
.notification-wrapper,
.empty-content {
	background: transparent !important;
	color: #f1f7fb !important;
	box-shadow: none !important;
}
#header .header-menu a,
#header .header-menu button,
#header .notification,
#header .user-menu a,
#header .user-menu button,
#contactsmenu a,
#contactsmenu button {
	color: #f1f7fb !important;
	border-radius: 10px !important;
}
#header .header-menu a:hover,
#header .header-menu button:hover,
#header .notification:hover,
#header .user-menu a:hover,
#header .user-menu button:hover,
#contactsmenu a:hover {
	background: rgba(19, 194, 192, 0.14) !important;
}
#header .empty-content h2,
#header .empty-content p,
#header .notification-wrapper h2,
.user-menu__name {
	color: #f1f7fb !important;
}

/* ==========================================================================
   5. JO COR HOME (dashboard)
   Windows into the apps. No copy. Stock widget grid is hidden.
   ========================================================================== */
#app-dashboard {
	--jocor-60: #0b1120;
	--jocor-30: #f1f7fb;
	--jocor-10: #13c2c0;
	--jocor-gold: #c9a661;
	padding-inline: clamp(16px, 4vw, 40px) !important;
	padding-block-end: 48px !important;
}

#app-dashboard.jocor-home-on .panels,
#app-dashboard.jocor-home-on .button-vue:has(.pencil),
#app-dashboard.jocor-home-on button[aria-label*="Customize"],
#app-dashboard.jocor-home-on button[aria-label*="customise"],
#app-dashboard.jocor-home-on button[aria-label*="Edit"] {
	display: none !important;
}

.jocor-home {
	display: grid;
	grid-template-columns: 1fr 1fr 1fr;
	grid-template-areas:
		"talk osiris chat"
		"flix flix flix";
	gap: 16px;
	width: min(1240px, 100%);
	margin: 8px auto 0;
}

.jocor-win {
	position: relative;
	display: block;
	overflow: hidden;
	text-decoration: none;
	color: #f1f7fb;
	background: #070b16;
	border: 1px solid rgba(19, 194, 192, 0.22);
	border-radius: 22px;
	box-shadow: 0 18px 48px rgb(0 0 0 / 40%);
	color-scheme: dark;
	isolation: isolate;
	min-width: 0;
	transition: border-color var(--jocor-slow) var(--jocor-ease),
		box-shadow var(--jocor-slow) var(--jocor-ease);
}
.jocor-win--talk { grid-area: talk; }
.jocor-win--osiris { grid-area: osiris; }
.jocor-win--chat { grid-area: chat; }
.jocor-win--talk,
.jocor-win--osiris,
.jocor-win--chat {
	aspect-ratio: 1 / 1;
	height: auto;
}
.jocor-win--flix {
	grid-area: flix;
	aspect-ratio: 2.2 / 1;
	min-height: 340px;
	height: auto;
	border-color: rgba(201, 166, 97, 0.42);
}
.jocor-win::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-start: 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.22), transparent);
	z-index: 3;
	pointer-events: none;
}
.jocor-win:hover {
	border-color: rgba(19, 194, 192, 0.6);
	box-shadow: 0 22px 56px rgb(0 0 0 / 48%), 0 0 0 1px rgba(19, 194, 192, 0.12);
}
.jocor-win--flix:hover {
	border-color: rgba(201, 166, 97, 0.75);
	box-shadow: 0 22px 56px rgb(0 0 0 / 48%), 0 0 0 1px rgba(201, 166, 97, 0.16);
}
.jocor-win:focus-visible {
	outline: 2px solid #13c2c0;
	outline-offset: 3px;
}
.jocor-win__stage {
	position: absolute;
	inset: 0;
	overflow: hidden;
	background:
		radial-gradient(120% 80% at 18% 0%, rgba(19, 194, 192, 0.16), transparent 55%),
		#070b16;
}
.jocor-win--flix .jocor-win__stage {
	background: #070b16;
}
.jocor-win__live {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
	pointer-events: none;
	opacity: 0;
	z-index: 1;
	background: #070b16;
	transform: none;
	transform-origin: top left;
}
.jocor-win__live.is-on {
	opacity: 1;
}
.jocor-win__tag {
	position: absolute;
	z-index: 4;
	left: 12px;
	top: 12px;
	padding: 4px 10px;
	border-radius: 999px;
	font-size: 11px;
	font-weight: 650;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	background: rgb(4 6 15 / 72%);
	border: 1px solid rgba(19, 194, 192, 0.28);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
	pointer-events: none;
}
.jocor-win__tag--gold {
	border-color: rgba(201, 166, 97, 0.45);
	color: #e8d5a3;
}
.jocor-win--osiris .jocor-win__tag {
	display: none;
}

.jocor-inbox,
.jocor-desk {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 48px 12px 12px;
	overflow: hidden;
}
.jocor-inbox__empty,
.jocor-desk__lead {
	margin: 0;
	color: #f1f7fb;
	font-size: 18px;
	font-weight: 650;
	letter-spacing: -0.02em;
	text-align: center;
}
.jocor-inbox__empty {
	margin-block-start: auto;
}
.jocor-inbox__hint,
.jocor-desk__hint {
	margin: 0 0 auto;
	color: #9fb3c8;
	font-size: 13px;
	text-align: center;
}
.jocor-inbox__row,
.jocor-desk__row {
	display: grid;
	grid-template-columns: 40px minmax(0, 1fr) auto;
	gap: 10px;
	align-items: center;
	padding: 8px;
	border-radius: 14px;
	min-height: 52px;
}
.jocor-desk__row {
	grid-template-columns: minmax(0, 1fr);
	gap: 2px;
	padding: 10px 12px;
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid rgba(19, 194, 192, 0.1);
}
.jocor-inbox__row.is-unread {
	background: rgba(19, 194, 192, 0.1);
}
.jocor-inbox__av {
	position: relative;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	display: grid;
	place-items: center;
	background: #1a2438;
	border: 1px solid rgba(19, 194, 192, 0.28);
	font-size: 14px;
	font-weight: 700;
	color: #d7e6f0;
	overflow: hidden;
	flex-shrink: 0;
}
.jocor-inbox__av img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.jocor-inbox__body,
.jocor-desk__row {
	min-width: 0;
}
.jocor-inbox__name,
.jocor-desk__title {
	display: block;
	font-size: 13.5px;
	font-weight: 650;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.jocor-inbox__msg,
.jocor-desk__sub {
	display: block;
	font-size: 12px;
	color: #9fb3c8;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.jocor-inbox__meta {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 4px;
	flex: 0 0 auto;
}
.jocor-inbox__time {
	font-size: 11px;
	color: #7f93a8;
	font-variant-numeric: tabular-nums;
}
.jocor-inbox__badge {
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 999px;
	background: #13c2c0;
	color: #04120f;
	font-size: 10px;
	font-weight: 700;
	display: grid;
	place-items: center;
}

.jocor-desk--empty {
	align-items: center;
	text-align: center;
	padding-inline: 18px;
}
.jocor-desk__orb {
	display: block;
	width: 72px;
	height: 72px;
	margin: 8px auto 10px;
	border-radius: 50%;
	background:
		radial-gradient(circle at 35% 30%, #9ffbec, #36f1ce 28%, #13c2c0 55%, #0b3d48 78%, #071018 100%);
	box-shadow:
		0 0 40px rgba(19, 194, 192, 0.45),
		inset 0 0 16px rgba(255, 255, 255, 0.28);
}
.jocor-desk__chips {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 8px;
	padding: 4px 0 12px;
}
.jocor-desk__chips span {
	padding: 6px 12px;
	border-radius: 999px;
	border: 1px solid rgba(19, 194, 192, 0.28);
	background: rgba(19, 194, 192, 0.08);
	font-size: 12px;
	color: #d7e6f0;
}
.jocor-desk__composer {
	margin-top: auto;
	padding: 12px 14px;
	border-radius: 14px;
	border: 1px solid rgba(19, 194, 192, 0.28);
	background: rgb(4 6 15 / 55%);
	color: #9fb3c8;
	font-size: 13px;
	width: 100%;
	box-sizing: border-box;
	text-align: start;
}

.jocor-flix-hero {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	padding: 18px 20px 16px;
	background:
		radial-gradient(90% 80% at 8% 0%, rgba(201, 166, 97, 0.16), transparent 55%),
		#070b16;
}
.jocor-flix-brand {
	display: flex;
	align-items: baseline;
	gap: 14px;
	z-index: 2;
	margin: 0 0 14px;
	flex: 0 0 auto;
}
.jocor-flix-logo {
	font-size: clamp(1.6rem, 3vw, 2.4rem);
	font-weight: 800;
	letter-spacing: 0.18em;
	line-height: 1;
	color: #e8d5a3;
	text-shadow: 0 0 24px rgba(201, 166, 97, 0.35);
}
.jocor-flix-invite {
	color: #9fb3c8;
	font-size: 14px;
	letter-spacing: 0.04em;
}
.jocor-flix-hero__rail {
	position: relative;
	left: auto;
	right: auto;
	bottom: auto;
	z-index: 2;
	display: flex;
	gap: 14px;
	flex: 1 1 auto;
	min-height: 0;
	height: auto;
	max-height: none;
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: none;
	mask-image: linear-gradient(90deg, #000 0%, #000 92%, transparent 100%);
	padding-block-end: 4px;
}
.jocor-flix-hero__rail::-webkit-scrollbar {
	display: none;
}
.jocor-flix-hero__rail img {
	height: 100%;
	width: auto;
	aspect-ratio: 2 / 3;
	object-fit: cover;
	border-radius: 14px;
	box-shadow: 0 14px 32px rgb(0 0 0 / 55%);
	flex: 0 0 auto;
	border: 1px solid rgba(255, 255, 255, 0.12);
}
.jocor-flix-empty {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	color: #e8d5a3;
	font-size: 18px;
	letter-spacing: 0.04em;
}

#app-dashboard.jocor-home-on #nyx-stars-toggle-container {
	display: flex;
	justify-content: center;
	margin: 10px auto 8px;
}

@media (max-width: 980px) {
	.jocor-home {
		grid-template-columns: 1fr 1fr;
		grid-template-areas:
			"talk osiris"
			"chat chat"
			"flix flix";
	}
	.jocor-win--talk,
	.jocor-win--osiris,
	.jocor-win--chat {
		aspect-ratio: 1 / 1;
	}
	.jocor-win--chat {
		width: calc((100% - 16px) / 2);
		justify-self: center;
	}
	.jocor-flix-invite {
		display: none;
	}
}

@media (max-width: 720px) {
	#app-dashboard {
		padding-inline: 12px !important;
	}
	.jocor-home {
		grid-template-columns: 1fr;
		grid-template-areas:
			"talk"
			"osiris"
			"chat"
			"flix";
		gap: 12px;
	}
	.jocor-win--talk,
	.jocor-win--osiris,
	.jocor-win--chat {
		aspect-ratio: 1 / 1;
		max-height: none;
		width: auto;
		justify-self: stretch;
	}
	.jocor-win--flix {
		aspect-ratio: 4 / 5;
		min-height: 360px;
	}
	.jocor-flix-hero {
		padding: 14px 14px 12px;
	}
	.jocor-flix-hero__rail {
		gap: 10px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.jocor-win,
	.jocor-win:hover {
		transform: none;
	}
}

/* Framed app views on the dashboard — no nested Jo Cor chrome. */
html.jocor-embed #header,
html.jocor-embed .jocor-hero-canvas,
html.jocor-embed .jl-button,
html.jocor-embed .jl-panel,
html.jocor-embed .skip-navigation,
html.jocor-embed #skip-actions {
	display: none !important;
}
html.jocor-embed #content,
html.jocor-embed #content-vue,
html.jocor-embed #content-vue.content.app-talk {
	top: 0 !important;
	bottom: 0 !important;
	left: 0 !important;
	right: 0 !important;
	margin: 0 !important;
	height: 100% !important;
	max-height: none !important;
	inset: 0 !important;
}
html.jocor-embed,
html.jocor-embed body {
	overflow: hidden !important;
	color-scheme: only dark;
	background: #070b16 !important;
}
html.jocor-embed .notecard,
html.jocor-embed .toastify,
html.jocor-embed [class*="unsupported"],
html.jocor-embed .warning.notecard {
	display: none !important;
}
