/*
 * Staff page chrome: the sign-in card and the thin bar above the app.
 *
 * Everything inside the app itself is admin.css, unchanged — this file
 * only styles the two pieces that don't exist in wp-admin, plus the small
 * amount of resetting needed because these screens are now running inside
 * a theme's page rather than inside WordPress's admin shell.
 *
 * Scoped to .pb-staff-shell throughout, for the same reason booking.css
 * scopes to #pb-booking-root: this markup lands in the middle of whatever
 * theme the site runs, and a bare `.pb-staff-input` would be fair game for
 * any theme rule that felt like claiming it.
 */

.pb-staff-shell {
	--pb-staff-max: 420px;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	color: var(--pb-text, #1a1a1a);

	/*
	 * Full bleed. This shortcode lands inside whatever content column the
	 * theme gives a page — typically a centred one with a max-width and
	 * side padding — which is right for an article and wrong for an app:
	 * it leaves white gutters down both sides of a calendar that wants
	 * every pixel. There is no way to ask an ancestor to stop constraining
	 * us, so the shell steps out of the column instead: 100vw wide, pulled
	 * left by exactly half the difference between the column and the
	 * viewport. Works regardless of how deep the theme's wrappers go or
	 * how wide they are, because both halves of the calc resolve against
	 * the parent's own width.
	 */
	width: 100vw;
	max-width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
}

/* 100vw includes the classic scrollbar's width on desktop, so the breakout
   above overhangs the viewport by ~15px there. `clip` rather than `hidden`
   because hidden would make body a scroll container and break any
   position: sticky inside the app; hidden is left first as the fallback
   for browsers without clip. */
body:has(.pb-staff-shell) {
	overflow-x: hidden;
	overflow-x: clip;
}

/* The app bundle caps itself at 1360px for wp-admin, where it shares the
   page with WordPress's own sidebar. Out here it IS the page. */
.pb-staff-shell #pb-admin-root {
	max-width: none;
}

/* Full bleed is not the same as flush against the glass — the content
   still needs a gutter, it just shouldn't be the theme's. The touch
   override in admin.css narrows this to 16px on a phone. */
.pb-staff-app {
	padding: 0 24px;
}

/* ---------------- the first half-second ----------------

   While /staff/me is in flight the app's frame is already on screen (see
   resume() in staff.js), because the alternative was a blank white page
   for the length of a network round trip. Two things follow from that:
   the top bar has no name to show yet, so it is held back rather than
   flashing an empty chip; and the body shows the shape of a screen
   instead of nothing. */

.pb-staff-app.is-booting .pb-staff-bar > * {
	visibility: hidden;
}

.pb-boot-skeleton {
	padding: 8px 0 0;
}

.pb-skel {
	border-radius: 10px;
	background: var(--pb-fill, #f5f5f5);
	animation: pb-skel-pulse 1.3s ease-in-out infinite;
}

.pb-skel-title {
	width: 44%;
	max-width: 220px;
	height: 26px;
	margin-bottom: 20px;
}

.pb-skel-row {
	height: 72px;
	margin-bottom: 12px;
}

/* Staggered, so it reads as one surface breathing rather than three
   boxes blinking in unison. */
.pb-skel-row:nth-child(3) { animation-delay: 0.12s; }
.pb-skel-row:nth-child(4) { animation-delay: 0.24s; }

@keyframes pb-skel-pulse {
	0%, 100% { opacity: 1; }
	50% { opacity: 0.45; }
}

@media (prefers-reduced-motion: reduce) {
	.pb-skel {
		animation: none;
	}
}

/* Override the theme's body background. The staff shell lives inside a
   normal theme page — whatever the theme sets on body shows through unless
   we reset it here. #fff matches the admin SPA's own background. */
body:has(.pb-staff-shell) {
	background: #fff !important;
}

/* The admin bundle assumes wp-admin's own box-sizing reset. Inside a theme
   that isn't guaranteed, and without it every padded control in the app is
   a few pixels wider than the grid it sits in. */
.pb-staff-shell,
.pb-staff-shell *,
.pb-staff-shell *::before,
.pb-staff-shell *::after {
	box-sizing: border-box;
}

/* The HTML ships both the login card and the app, and staff.js hides one
   with the `hidden` attribute. That attribute is only `display: none` in
   the browser's own stylesheet, which ANY author rule with a display beats
   — including `.pb-staff-login { display: flex }` three lines below.
   Without this rule the login form stays on screen underneath the signed-in
   app. Found by screenshotting the real page; no unit test would have
   caught it, because the attribute was being set correctly all along. */
.pb-staff-shell [hidden] {
	display: none !important;
}

/* ---------------- sign-in ---------------- */

.pb-staff-login {
	display: flex;
	justify-content: center;
	padding: 48px 16px;
}

.pb-staff-login-card {
	width: 100%;
	max-width: var(--pb-staff-max);
	background: var(--pb-white, #fff);
	border: 1px solid var(--pb-border, #e3e3e3);
	border-radius: 14px;
	padding: 28px 24px 24px;
}

.pb-staff-login-title {
	margin: 0 0 2px;
	font-size: 20px;
	font-weight: 700;
	line-height: 1.2;
}

.pb-staff-login-sub {
	margin: 0 0 22px;
	font-size: 14px;
	color: var(--pb-text-muted, #6a6a6a);
}

.pb-staff-label {
	display: block;
	margin: 0 0 6px;
	font-size: 13px;
	font-weight: 600;
}

/* ---------------- the PIN keypad ---------------- */

/* Six dots standing in for a password field. Filled left to right as
   digits are pressed; see paintDots() in staff.js. */
.pb-staff-shell .pb-pin-dots {
	display: flex;
	justify-content: center;
	gap: 14px;
	margin: 4px 0 22px;
}

.pb-staff-shell .pb-pin-dot {
	width: 13px;
	height: 13px;
	border-radius: 50%;
	background: transparent;
	border: 1.5px solid var(--pb-border-strong, #c9c9c9);
	transition: transform 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}

.pb-staff-shell .pb-pin-dot.is-filled {
	background: var(--pb-black, #1a1a1a);
	border-color: var(--pb-black, #1a1a1a);
	transform: scale(1.12);
}

.pb-staff-shell .pb-keypad {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 12px;
}

.pb-staff-shell .pb-key {
	-webkit-appearance: none;
	appearance: none;
	display: flex;
	align-items: center;
	justify-content: center;
	/* Comfortably past the 44px Apple calls the minimum, because this is
	   the one control in the whole app that gets used with wet hands,
	   gloves on, or while holding a light stand. */
	min-height: 64px;
	font-size: 26px;
	font-weight: 500;
	font-variant-numeric: tabular-nums;
	color: var(--pb-text, #1a1a1a);
	background: var(--pb-fill, #f5f5f5);
	border: 0;
	border-radius: 16px;
	cursor: pointer;
	user-select: none;
	-webkit-user-select: none;
	/* Kills both the grey flash iOS paints over a tapped button and the
	   300ms wait it otherwise spends deciding whether this is a
	   double-tap-to-zoom. */
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: transform 0.08s ease, background-color 0.08s ease;
}

/* :active, not :hover — a finger has no hover state, and a key that stays
   highlighted after the finger lifts looks stuck. */
.pb-staff-shell .pb-key:active {
	background: var(--pb-fill-hover, #e9e9e9);
	transform: scale(0.95);
}

.pb-staff-shell .pb-key-soft {
	font-size: 15px;
	font-weight: 600;
	color: var(--pb-text-muted, #6a6a6a);
	background: transparent;
}

.pb-staff-shell .pb-key-soft:active {
	background: var(--pb-fill, #f5f5f5);
}

/* Waiting on the server: the pad stops accepting taps and the dots
   breathe, so a slow connection reads as "working" rather than "frozen". */
.pb-staff-shell .pb-staff-login-card.is-checking .pb-keypad {
	opacity: 0.45;
	pointer-events: none;
}

.pb-staff-shell .pb-staff-login-card.is-checking .pb-pin-dot.is-filled {
	animation: pb-pin-pulse 1s ease-in-out infinite;
}

@keyframes pb-pin-pulse {
	0%, 100% { opacity: 1; }
	50% { opacity: 0.3; }
}

/* Wrong PIN: the dots shake and empty. Recognisable enough from every
   phone lock screen that it needs no explaining. */
.pb-staff-shell .pb-staff-login-card.is-wrong .pb-pin-dots {
	animation: pb-pin-shake 0.4s ease;
}

@keyframes pb-pin-shake {
	0%, 100% { transform: translateX(0); }
	20% { transform: translateX(-9px); }
	40% { transform: translateX(8px); }
	60% { transform: translateX(-5px); }
	80% { transform: translateX(3px); }
}

@media (prefers-reduced-motion: reduce) {
	.pb-staff-shell .pb-pin-dot,
	.pb-staff-shell .pb-key {
		transition: none;
	}
	.pb-staff-shell .pb-staff-login-card.is-wrong .pb-pin-dots,
	.pb-staff-shell .pb-staff-login-card.is-checking .pb-pin-dot.is-filled {
		animation: none;
	}
}

/* On a real touch screen the card centres in the viewport and the keys
   grow — this is the whole screen at that point, not a form on a page. */
.pb-touch .pb-staff-login {
	align-items: center;
	min-height: 78vh;
	padding-top: calc(24px + env(safe-area-inset-top));
	padding-bottom: calc(24px + env(safe-area-inset-bottom));
}

.pb-touch .pb-staff-shell .pb-keypad {
	gap: 14px;
}

.pb-touch .pb-staff-shell .pb-key {
	min-height: 72px;
	font-size: 28px;
}

.pb-staff-error {
	margin: 0 0 14px;
	padding: 10px 12px;
	font-size: 13px;
	color: var(--pb-danger, #b3261e);
	background: var(--pb-danger-tint, #fdeceb);
	border: 1px solid var(--pb-danger-border, #f2c2be);
	border-radius: 8px;
}

.pb-staff-hint {
	margin: 14px 0 0;
	font-size: 12px;
	color: var(--pb-text-faint, #949494);
	text-align: center;
}

/* ---------------- signed in ---------------- */

.pb-staff-shell .pb-tabbar {
	/* The staff page has exactly six tabs and they fit comfortably, so
	   the horizontal scrollbar that appears on some OS themes is just
	   noise. Hide the track without disabling scrolling, in case someone
	   runs this on a very narrow screen. */
	scrollbar-width: none; /* Firefox */
}
.pb-staff-shell .pb-tabbar::-webkit-scrollbar {
	display: none; /* Chrome/Safari */
}

.pb-staff-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 0 14px;
	border-bottom: 1px solid var(--pb-hairline, #ececec);
	margin-bottom: 16px;
}

.pb-staff-who {
	font-size: 14px;
	font-weight: 600;
}

.pb-staff-shell .pb-staff-signout {
	padding: 7px 13px;
	font-size: 13px;
	font-weight: 600;
	color: var(--pb-text, #1a1a1a);
	background: var(--pb-fill, #f5f5f5);
	border: 1px solid var(--pb-border, #e3e3e3);
	border-radius: 8px;
	cursor: pointer;
}

.pb-staff-shell .pb-staff-signout:hover {
	background: var(--pb-fill-hover, #e9e9e9);
}

@media (max-width: 600px) {
	.pb-staff-login {
		padding: 24px 12px;
	}
}

/* The backspace key's drawn glyph — see PB_Staff_Shortcode::render(). */
.pb-staff-shell .pb-key-icon {
	width: 26px;
	height: 26px;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.7;
	stroke-linecap: round;
	stroke-linejoin: round;
	/* The icon is inside the button, so a tap can land on the path. The
	   click handler uses closest() for exactly that reason; this just
	   keeps the icon from swallowing the press state. */
	pointer-events: none;
}

/*
 * On a phone the sign-in card IS the screen, so it centres in the viewport
 * rather than sitting at the top of a page that has nothing else on it.
 * dvh, not vh: on mobile Safari `vh` is the height with the address bar
 * hidden, so a vh-centred card sits low and drifts as the bar collapses.
 */
@media (max-width: 640px) {
	.pb-staff-login {
		align-items: center;
		min-height: 88vh;
		min-height: 88dvh;
		padding: 20px 14px;
		padding-top: calc(20px + env(safe-area-inset-top));
		padding-bottom: calc(20px + env(safe-area-inset-bottom));
	}

	.pb-staff-login-card {
		padding: 24px 20px 20px;
	}

	.pb-staff-login-title {
		font-size: 19px;
	}
}

/* =========================================================================
   DESIGN — sign-in
   =========================================================================
   The brand's own colours, lifted from the logo: magenta into deep purple,
   with lavender and a pastel blue as the tints everything else sits on.
   Declared here on the shell so the app inherits them too (admin.css reads
   the same names inside its touch layer).
   ========================================================================= */

.pb-staff-shell {
	--pb-brand-a: #b42f71;
	--pb-brand-b: #5e369c;
	--pb-brand: linear-gradient(135deg, #b42f71 0%, #8a3590 52%, #5e369c 100%);
	--pb-plum: #4b2a7a;
	--pb-lilac: #efe6fb;
	--pb-lilac-deep: #dfd0f5;
	--pb-sky: #e4edff;
	--pb-sky-deep: #cbdcff;
	--pb-shadow-soft: 0 2px 6px rgba(75, 42, 122, 0.05), 0 12px 32px rgba(75, 42, 122, 0.08);
	--pb-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

/* A soft wash behind the card — lavender top-left, pastel blue bottom-
   right — instead of a flat white page. Fixed, so it stays put while the
   card animates in and the page never shows a seam on scroll. */
.pb-staff-login {
	position: relative;
	isolation: isolate;
}

.pb-staff-login::before {
	content: '';
	position: fixed;
	inset: 0;
	z-index: -1;
	background:
		radial-gradient(60% 50% at 12% 8%, var(--pb-lilac) 0%, transparent 70%),
		radial-gradient(55% 45% at 88% 92%, var(--pb-sky) 0%, transparent 70%),
		#fbfaff;
	pointer-events: none;
}

.pb-staff-shell .pb-staff-login-card {
	border: 0;
	border-radius: 26px;
	padding: 30px 26px 24px;
	background: rgba(255, 255, 255, 0.86);
	-webkit-backdrop-filter: blur(18px);
	backdrop-filter: blur(18px);
	box-shadow: var(--pb-shadow-soft);
	animation: pb-card-in 0.5s var(--pb-ease-out) both;
}

@keyframes pb-card-in {
	from { opacity: 0; transform: translateY(18px) scale(0.98); }
	to   { opacity: 1; transform: none; }
}

/* The logo mark above the title. */
.pb-staff-shell .pb-staff-logo {
	display: block;
	width: 58px;
	height: 58px;
	margin: 0 auto 16px;
	border-radius: 18px;
	box-shadow: 0 6px 18px rgba(94, 54, 156, 0.25);
}

.pb-staff-shell .pb-staff-login-title {
	text-align: center;
	font-size: 21px;
	letter-spacing: -0.02em;
	color: var(--pb-plum);
}

.pb-staff-shell .pb-staff-login-sub {
	text-align: center;
	margin-bottom: 26px;
	font-size: 14px;
	color: #7d6f99;
}

/* Dots: brand gradient when filled, with a soft halo so the newest one
   reads as "landed". */
.pb-staff-shell .pb-pin-dots {
	gap: 16px;
	margin: 0 0 26px;
}

.pb-staff-shell .pb-pin-dot {
	width: 14px;
	height: 14px;
	border: 1.5px solid var(--pb-lilac-deep);
	background: #fff;
	transition: transform 0.18s var(--pb-ease-out), background-color 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}

.pb-staff-shell .pb-pin-dot.is-filled {
	background: var(--pb-brand);
	border-color: transparent;
	transform: scale(1.15);
	box-shadow: 0 0 0 4px rgba(138, 53, 144, 0.14);
}

/* Keys: white cards on the wash, lavender hairline, lilac press. Each key
   rises in a beat after the one before it, so the pad assembles rather
   than appears. */
.pb-staff-shell .pb-keypad {
	gap: 12px;
}

.pb-staff-shell .pb-key {
	background: #fff;
	border: 1px solid var(--pb-lilac-deep);
	border-radius: 18px;
	color: var(--pb-plum);
	font-weight: 500;
	box-shadow: 0 1px 2px rgba(75, 42, 122, 0.05);
	transition: transform 0.12s var(--pb-ease-out), background-color 0.12s ease, box-shadow 0.12s ease;
	animation: pb-key-in 0.42s var(--pb-ease-out) both;
}

.pb-staff-shell .pb-key:active {
	background: var(--pb-lilac);
	transform: scale(0.94);
	box-shadow: none;
}

.pb-staff-shell .pb-key-soft {
	border-color: transparent;
	background: transparent;
	box-shadow: none;
	color: #7d6f99;
}

.pb-staff-shell .pb-key-soft:active {
	background: var(--pb-lilac);
}

@keyframes pb-key-in {
	from { opacity: 0; transform: translateY(10px); }
	to   { opacity: 1; transform: none; }
}

.pb-staff-shell .pb-key:nth-child(1)  { animation-delay: 0.05s; }
.pb-staff-shell .pb-key:nth-child(2)  { animation-delay: 0.08s; }
.pb-staff-shell .pb-key:nth-child(3)  { animation-delay: 0.11s; }
.pb-staff-shell .pb-key:nth-child(4)  { animation-delay: 0.14s; }
.pb-staff-shell .pb-key:nth-child(5)  { animation-delay: 0.17s; }
.pb-staff-shell .pb-key:nth-child(6)  { animation-delay: 0.20s; }
.pb-staff-shell .pb-key:nth-child(7)  { animation-delay: 0.23s; }
.pb-staff-shell .pb-key:nth-child(8)  { animation-delay: 0.26s; }
.pb-staff-shell .pb-key:nth-child(9)  { animation-delay: 0.29s; }
.pb-staff-shell .pb-key:nth-child(10) { animation-delay: 0.32s; }
.pb-staff-shell .pb-key:nth-child(11) { animation-delay: 0.35s; }
.pb-staff-shell .pb-key:nth-child(12) { animation-delay: 0.38s; }

.pb-staff-shell .pb-staff-hint {
	margin-top: 18px;
	color: #9a8fb3;
}

/* "Add to Home Screen" — shown by staff.js only to iPhone/iPad Safari
   that has NOT installed the app yet. Pastel blue so it reads as a tip,
   not a warning. */
.pb-staff-shell .pb-install-hint {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 18px 0 0;
	padding: 12px 14px;
	border-radius: 14px;
	background: var(--pb-sky);
	color: var(--pb-plum);
	font-size: 12.5px;
	line-height: 1.45;
	animation: pb-key-in 0.5s var(--pb-ease-out) 0.45s both;
}

.pb-staff-shell .pb-install-hint svg {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	margin-top: 1px;
	fill: none;
	stroke: var(--pb-brand-b);
	stroke-width: 1.8;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.pb-staff-shell .pb-install-hint strong {
	font-weight: 700;
}

/* The signed-in bar: an initials chip in the brand gradient, the name,
   and a ghost sign-out. Cleared of the notch when installed. */
.pb-touch .pb-staff-bar {
	padding-top: calc(12px + env(safe-area-inset-top));
	padding-bottom: 12px;
	border-bottom: 1px solid var(--pb-lilac-deep);
	margin-bottom: 18px;
}

.pb-staff-shell .pb-staff-who {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 15px;
	color: var(--pb-plum);
}

.pb-staff-shell .pb-staff-avatar {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border-radius: 12px;
	background: var(--pb-brand);
	color: #fff;
	font-size: 12.5px;
	font-weight: 700;
	letter-spacing: 0.02em;
	box-shadow: 0 4px 12px rgba(94, 54, 156, 0.25);
}

.pb-staff-shell .pb-staff-signout {
	border-color: var(--pb-lilac-deep);
	background: #fff;
	color: var(--pb-plum);
	border-radius: 999px;
	padding: 9px 16px;
}

.pb-staff-shell .pb-staff-signout:active {
	background: var(--pb-lilac);
}

@media (prefers-reduced-motion: reduce) {
	.pb-staff-shell .pb-staff-login-card,
	.pb-staff-shell .pb-key,
	.pb-staff-shell .pb-install-hint {
		animation: none;
	}
}
