/* @platform/factory-booking — structural styles for the booking widget.
 *
 * Plain global CSS on purpose, not a Svelte <style> block. Three reasons:
 *   1. The widget renders in LIGHT DOM (spec 272 D3) so the consuming site can
 *      theme it. Svelte-scoped rules would carry a compiler hash the consumer
 *      cannot target.
 *   2. Every class is `lb-`-prefixed, which is what provides isolation instead.
 *   3. It keeps one stylesheet both consumers import, so cal.lynton.ai and an
 *      embedding site cannot drift visually.
 *
 * This file consumes design tokens and defines NONE. Import a theme alongside
 * it (`themes/lynton.css`, `themes/neutral.css`) or define the tokens yourself
 * — see README. Layout and visuals are otherwise verbatim from the approved
 * mockup (`prototypes/booking.html`, desktop spec 051 Part 0). */

/* Light-DOM guard. The original lived under the desktop app's global reset;
 * a consumer page has its own, and these rules assume border-box. Scoped to
 * the widget so it cannot touch anything else on the page. */
.lb-public,
.lb-public *,
.lb-public *::before,
.lb-public *::after {
	box-sizing: border-box;
}

/* The custom element host. An unregistered/unstyled custom element defaults to
 * `display: inline`, which gives the host no box: margins collapse oddly and
 * getBoundingClientRect() on <lynton-booking> reports zero height even while the
 * widget inside it renders. Found embedding on syncsmart.io.
 *
 * Harmless when the component is used directly in Svelte — the selector simply
 * matches nothing. */
lynton-booking {
	display: block;
}

/* ── Shared primitives ───────────────────────────────────────────────────────
 *
 * Buttons and icon-buttons. These lived in the booking service's OWN layout as
 * `:global(.btn)` etc., not in the component's <style> block, so the first
 * extraction left them behind entirely: the classes shipped, the rules did not,
 * and every button on a consuming site fell back to browser chrome. Invisible
 * on cal.lynton.ai, where the layout still supplies them — found the moment the
 * widget rendered anywhere else.
 *
 * Copied verbatim (bar the `lb-` prefix) so the two remain identical. */
.lb-btn {
	font-family: var(--font-sans);
	font-weight: var(--fw-med);
	border: 1px solid transparent;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 5px;
	white-space: nowrap;
	font-size: 12px;
	padding: 4px 10px;
	border-radius: var(--radius-sm);
	height: 28px;
	transition:
		background var(--duration-fast) ease-out,
		border-color var(--duration-fast) ease-out;
}
.lb-btn-lg {
	height: 36px;
	font-size: var(--text-base);
	padding: 0 16px;
}
.lb-btn-primary {
	background: var(--accent-500);
	color: #fff;
	border-color: var(--accent-500);
}
.lb-btn-primary:hover {
	background: var(--accent-600);
}
.lb-btn-primary:disabled {
	opacity: 0.55;
	cursor: not-allowed;
}
.lb-btn-secondary {
	background: var(--bg-raised);
	color: var(--fg-default);
	border-color: var(--bg-subtle);
}
.lb-btn-secondary:hover {
	background: var(--bg-hover);
	border-color: var(--fg-faint);
}
.lb-btn svg {
	width: 14px;
	height: 14px;
}
.lb-icon-btn {
	width: 28px;
	height: 28px;
	border-radius: var(--radius-sm);
	display: flex;
	align-items: center;
	justify-content: center;
	background: none;
	border: none;
	color: var(--fg-muted);
	cursor: pointer;
	transition:
		background var(--duration-fast) ease-out,
		color var(--duration-fast) ease-out;
}
.lb-icon-btn:hover {
	background: var(--bg-hover);
	color: var(--fg-default);
}
.lb-icon-btn:disabled {
	opacity: 0.4;
	cursor: not-allowed;
}
.lb-icon-btn svg {
	width: 16px;
	height: 16px;
}

	/* Layout + visuals copied from prototypes/booking.html (the approved
	   contract). Deviations are noted inline and recorded in spec 145. */
	.lb-public {
		/* Makes the widget's own width the reference for the @container query
		   below, so it lays out for the space it is GIVEN rather than for the
		   browser window. On cal.lynton.ai the two are the same; embedded in a
		   narrow column they are not, and the viewport version left an 880px card
		   overflowing a 512px slot (found on syncsmart.io). */
		container-type: inline-size;
		container-name: lb;
		min-height: 100vh;
		background:
			radial-gradient(
				1200px 600px at 50% -10%,
				color-mix(in srgb, var(--accent-500) 7%, transparent),
				transparent 60%
			),
			var(--bg-base);
		display: flex;
		flex-direction: column;
		align-items: center;
	}
	.lb-pub-brand {
		display: flex;
		align-items: center;
		gap: 8px;
		margin: 26px 0 14px;
		color: var(--fg-muted);
		font-weight: var(--fw-med);
	}
	.lb-pub-brand .lb-ws-mark {
		width: 22px;
		height: 22px;
		border-radius: 6px;
		background: linear-gradient(135deg, var(--accent-500), var(--accent-700));
		color: #fff;
		font-size: 12px;
		font-weight: var(--fw-strong);
		display: flex;
		align-items: center;
		justify-content: center;
	}
	.lb-pub-card {
		/* `100%`, not `100vw`: the card must fit its CONTAINER. With 100vw an
		   embed in a narrow column computed the full 880px and overflowed on
		   both sides. */
		width: min(880px, 100%);
		background: var(--bg-panel);
		border: 1px solid var(--bg-subtle);
		border-radius: var(--radius-lg);
		box-shadow: var(--shadow-panel);
		display: flex;
		min-height: 452px;
		/* The mockup's card sits in a fixed app frame, so its slot column scrolls
		   INSIDE a 452px card. Standing alone on a web page there is nothing to
		   bound it, and a busy day's slot list grew the card to ~710px — which
		   pushed the timezone selector below the fold. That selector is the one
		   element the brief calls "core" and the mockup keeps always visible, so
		   this bound is load-bearing, not cosmetic: it is what makes the slot list
		   scroll instead of the card. */
		max-height: max(452px, calc(100vh - 120px));
		overflow: hidden;
		margin-bottom: 40px;
	}

	/* Left: the meeting identity */
	.lb-pub-info {
		width: 300px;
		flex-shrink: 0;
		padding: 26px 24px;
		border-right: 1px solid var(--bg-subtle);
		display: flex;
		flex-direction: column;
	}
	.lb-pub-host {
		display: flex;
		align-items: center;
		gap: 9px;
		color: var(--fg-muted);
		font-size: var(--text-sm);
		font-weight: var(--fw-med);
	}
	.lb-pub-avatar {
		width: 30px;
		height: 30px;
		border-radius: 50%;
		background: var(--accent-600);
		color: #fff;
		font-size: 12px;
		font-weight: var(--fw-strong);
		display: flex;
		align-items: center;
		justify-content: center;
	}
	.lb-pub-title {
		font-size: var(--text-2xl);
		font-weight: var(--fw-strong);
		margin: 16px 0 12px;
		line-height: 1.15;
		letter-spacing: -0.01em;
	}
	.lb-pub-meta {
		display: flex;
		flex-direction: column;
		gap: 9px;
	}
	.lb-pub-meta .lb-row {
		display: flex;
		align-items: center;
		gap: 9px;
		color: var(--fg-muted);
		font-size: var(--text-sm);
	}
	.lb-pub-meta .lb-row svg {
		width: 15px;
		height: 15px;
		color: var(--fg-dim);
		flex-shrink: 0;
	}
	.lb-pub-info-foot {
		margin-top: auto;
		padding-top: 16px;
		color: var(--fg-faint);
		font-size: var(--text-xs);
	}

	/* Right: the scheduler */
	.lb-pub-sched {
		flex: 1;
		display: flex;
		flex-direction: column;
		min-width: 0;
	}
	.lb-pub-sched-head {
		padding: 22px 24px 10px;
		font-size: var(--text-lg);
		font-weight: var(--fw-strong);
	}
	.lb-pub-sched-body {
		flex: 1;
		display: flex;
		min-height: 0;
	}

	/* Month picker */
	.lb-pub-cal {
		flex: 1;
		padding: 4px 20px 12px;
		min-width: 0;
	}
	.lb-pub-cal-nav {
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-bottom: 8px;
	}
	.lb-pub-cal-nav .lb-mn {
		font-size: var(--text-base);
		font-weight: var(--fw-med);
	}
	.lb-pub-cal-grid {
		display: grid;
		grid-template-columns: repeat(7, 1fr);
		gap: 2px;
	}
	.lb-pub-dow {
		text-align: center;
		font-size: 10px;
		color: var(--fg-dim);
		padding-bottom: 4px;
		font-weight: var(--fw-med);
	}
	.lb-pub-day {
		aspect-ratio: 1;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: var(--text-sm);
		border-radius: var(--radius-full);
		color: var(--fg-faint);
		/* Available days are <button>s (the mockup used divs + onclick); reset the
		   UA chrome so they render identically. */
		border: none;
		background: none;
		font-family: var(--font-sans);
		padding: 0;
	}
	.lb-pub-day.lb-avail {
		color: var(--accent-400);
		font-weight: var(--fw-med);
		background: color-mix(in srgb, var(--accent-500) 10%, transparent);
		cursor: pointer;
	}
	.lb-pub-day.lb-avail:hover {
		background: color-mix(in srgb, var(--accent-500) 20%, transparent);
	}
	.lb-pub-day.lb-sel {
		background: var(--accent-500);
		color: #fff;
		font-weight: var(--fw-strong);
	}
	.lb-pub-day.lb-today {
		outline: 1px solid var(--fg-faint);
	}

	/* Time-slot column */
	.lb-pub-slots {
		width: 208px;
		flex-shrink: 0;
		border-left: 1px solid var(--bg-subtle);
		padding: 8px 16px 12px;
		display: flex;
		flex-direction: column;
		min-height: 0;
	}
	.lb-pub-slots-head {
		font-size: var(--text-sm);
		font-weight: var(--fw-med);
		color: var(--fg-muted);
		padding: 4px 2px 8px;
	}
	.lb-pub-slots-head b {
		color: var(--fg-default);
		font-weight: var(--fw-strong);
	}
	.lb-pub-slots-list {
		overflow-y: auto;
		display: flex;
		flex-direction: column;
		gap: 7px;
		padding-right: 2px;
	}
	.lb-pub-slots-list::-webkit-scrollbar {
		width: 4px;
	}
	.lb-pub-slots-list::-webkit-scrollbar-thumb {
		background: var(--bg-hover);
		border-radius: 2px;
	}
	.lb-slot {
		height: 40px;
		border: 1px solid var(--border-strong);
		border-radius: var(--radius-md);
		background: var(--bg-panel);
		color: var(--accent-400);
		font-weight: var(--fw-med);
		font-size: var(--text-base);
		font-family: var(--font-sans);
		display: flex;
		align-items: center;
		justify-content: center;
		cursor: pointer;
		flex-shrink: 0;
		letter-spacing: 0.01em;
		transition:
			border-color var(--duration-fast),
			background var(--duration-fast);
	}
	.lb-slot:hover {
		border-color: var(--accent-500);
		background: color-mix(in srgb, var(--accent-500) 7%, transparent);
	}
	.lb-slot.lb-pick2 {
		color: #fff;
		background: var(--accent-500);
		border-color: var(--accent-500);
	}
	.lb-slot.lb-pick2::after {
		content: 'Confirm →';
	}

	/* Timezone selector — the core UX element */
	.lb-pub-tz {
		border-top: 1px solid var(--bg-subtle);
		padding: 11px 24px;
		display: flex;
		align-items: center;
		gap: 8px;
		color: var(--fg-muted);
		font-size: var(--text-sm);
		margin-top: auto;
	}
	.lb-pub-tz > svg {
		width: 15px;
		height: 15px;
		color: var(--fg-dim);
		flex-shrink: 0;
	}
	.lb-tz-select {
		display: inline-flex;
		align-items: center;
		gap: 6px;
		margin-left: 2px;
		background: var(--bg-raised);
		border: 1px solid var(--bg-subtle);
		border-radius: var(--radius-sm);
		padding: 4px 9px;
		color: var(--fg-default);
		font-size: var(--text-sm);
		font-weight: var(--fw-med);
		cursor: pointer;
		min-width: 0;
	}
	.lb-tz-select:hover {
		border-color: var(--fg-faint);
	}
	.lb-tz-select svg {
		width: 12px;
		height: 12px;
		color: var(--fg-dim);
		flex-shrink: 0;
	}
	/* The mockup draws a static chip; a real page needs a real control. The
	   <select> is transparent and unstyled so the chip keeps its look, with the
	   mockup's chevron sitting beside it. */
	.lb-tz-select select {
		appearance: none;
		background: none;
		border: none;
		outline: none;
		color: inherit;
		font-family: var(--font-sans);
		font-size: var(--text-sm);
		font-weight: var(--fw-med);
		cursor: pointer;
		max-width: 260px;
		text-overflow: ellipsis;
	}
	.lb-tz-clock {
		margin-left: auto;
		color: var(--fg-dim);
		font-size: var(--text-xs);
		font-variant-numeric: tabular-nums;
		flex-shrink: 0;
	}

	/* Booking form */
	.lb-pub-form {
		flex: 1;
		padding: 22px 24px;
		display: flex;
		flex-direction: column;
	}
	.lb-pub-form h3 {
		font-size: var(--text-lg);
		font-weight: var(--fw-strong);
		margin-bottom: 4px;
	}
	.lb-form-field {
		margin-top: 14px;
	}
	.lb-form-field label {
		display: block;
		font-size: var(--text-sm);
		font-weight: var(--fw-med);
		color: var(--fg-muted);
		margin-bottom: 5px;
	}
	.lb-form-field label .lb-req {
		color: var(--red-text);
	}
	.lb-fin {
		width: 100%;
		height: 34px;
		padding: 0 10px;
		background: var(--bg-raised);
		border: 1px solid var(--bg-subtle);
		border-radius: var(--radius-sm);
		color: var(--fg-default);
		font-family: var(--font-sans);
		font-size: var(--text-base);
		outline: none;
	}
	textarea.lb-fin {
		height: 62px;
		padding: 8px 10px;
		resize: none;
	}
	.lb-fin:focus {
		border-color: var(--accent-500);
	}
	.lb-fin::placeholder {
		color: var(--fg-faint);
	}
	/* The mockup draws a STATIC "Verified — you're human" chip. The real widget
	   is rendered by Cloudflare's script into this host and brings its own
	   chrome, so the mockup's chip is replaced rather than wrapped around it. */
	/* Reserves the Managed widget's box so the buttons do not jump when the
	 * challenge finishes rendering.
	 *
	 * An INVISIBLE Turnstile widget draws nothing, and this would then be ~79px
	 * of blank space between the notes field and the buttons — "invisible" that
	 * looks broken. The component cannot detect the mode (it is a property of
	 * the sitekey, which the server chooses), so it is a token: set both to 0 in
	 * your theme when the widget is invisible. See the README. */
	.lb-turnstile-host {
		margin-top: var(--turnstile-gap, 14px);
		min-height: var(--turnstile-min-height, 65px);
	}
	.lb-form-error {
		margin-top: 12px;
		color: var(--red-text);
		background: var(--red-badge);
		border-radius: var(--radius-sm);
		padding: 8px 10px;
		font-size: var(--text-sm);
	}
	.lb-form-actions {
		margin-top: auto;
		padding-top: 18px;
		display: flex;
		gap: 8px;
	}

	/* Slot summary chip (form) */
	.lb-slot-summary {
		display: flex;
		flex-direction: column;
		gap: 8px;
		margin-top: 14px;
	}
	.lb-slot-summary .lb-sr {
		display: flex;
		align-items: center;
		gap: 9px;
		color: var(--fg-default);
		font-size: var(--text-sm);
	}
	.lb-slot-summary .lb-sr svg {
		width: 15px;
		height: 15px;
		color: var(--fg-dim);
		flex-shrink: 0;
	}
	.lb-slot-summary .lb-sr b {
		font-weight: var(--fw-strong);
	}

	/* Confirmed / empty — centered single column */
	.lb-pub-centered {
		flex: 1;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		text-align: center;
		padding: 40px 32px;
	}
	.lb-pub-centered .lb-ic {
		width: 52px;
		height: 52px;
		border-radius: 50%;
		display: flex;
		align-items: center;
		justify-content: center;
		margin-bottom: 16px;
	}
	.lb-ic.lb-ok {
		background: var(--green-badge);
		color: var(--green-text);
	}
	.lb-ic.lb-neutral {
		background: var(--bg-raised);
		color: var(--fg-dim);
	}
	.lb-ic svg {
		width: 26px;
		height: 26px;
	}
	.lb-pub-centered h2 {
		font-size: var(--text-xl);
		font-weight: var(--fw-strong);
	}
	.lb-pub-centered p {
		color: var(--fg-muted);
		font-size: var(--text-sm);
		margin-top: 6px;
		max-width: 340px;
		line-height: 1.55;
	}
	.lb-confirm-box {
		margin-top: 18px;
		width: min(420px, 100%);
		border: 1px solid var(--bg-subtle);
		border-radius: var(--radius-md);
		background: var(--bg-raised);
		padding: 14px 16px;
		text-align: left;
		display: flex;
		flex-direction: column;
		gap: 10px;
	}
	.lb-confirm-box .lb-cr {
		display: flex;
		align-items: center;
		gap: 10px;
		font-size: var(--text-sm);
		color: var(--fg-default);
	}
	.lb-confirm-box .lb-cr > svg {
		width: 15px;
		height: 15px;
		color: var(--fg-dim);
		flex-shrink: 0;
	}
	.lb-join-chip {
		display: flex;
		align-items: center;
		gap: 8px;
		background: color-mix(in srgb, var(--accent-500) 8%, transparent);
		border: 1px solid color-mix(in srgb, var(--accent-500) 25%, transparent);
		border-radius: var(--radius-sm);
		padding: 7px 10px;
	}
	.lb-join-chip svg {
		width: 15px;
		height: 15px;
		color: var(--accent-400);
		flex-shrink: 0;
	}
	.lb-join-chip .lb-lnk {
		font-family: var(--font-mono);
		font-size: var(--text-xs);
		color: var(--fg-muted);
		flex: 1;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
		text-decoration: none;
	}
	.lb-join-chip .lb-lnk:hover {
		color: var(--accent-400);
	}
	.lb-atc {
		display: flex;
		gap: 6px;
		margin-top: 4px;
	}
	.lb-atc .lb-btn {
		flex: 1;
		text-decoration: none;
	}

	/* The card is a two-column desktop layout; on a phone it stacks. The mockup
	   only drew the desktop case — a public page must survive a phone. */
	/* Was `@media (max-width: 720px)`. A viewport query is wrong for a widget:
	   embedded in a 512px column on a 1280px desktop it never fired, so the
	   two-column card never stacked. Keyed on the widget's own inline size it is
	   correct in both places — a phone and a narrow embed get the same stacked
	   layout, for the same reason. */
	@container lb (max-width: 720px) {
		.lb-pub-card {
			flex-direction: column;
			min-height: 0;
			/* Stacked on a phone the card SHOULD grow and the page scroll — the
			   desktop height bound would otherwise squeeze two stacked columns
			   into one screen. */
			max-height: none;
		}
		.lb-pub-info {
			width: 100%;
			border-right: none;
			border-bottom: 1px solid var(--bg-subtle);
		}
		.lb-pub-sched-body {
			flex-direction: column;
		}
		.lb-pub-slots {
			width: 100%;
			border-left: none;
			border-top: 1px solid var(--bg-subtle);
			max-height: 300px;
		}
		.lb-pub-tz {
			flex-wrap: wrap;
		}
	}
