/**
 * Preferred Sources for Publishers — front end.
 *
 * Written to sit inside somebody else's design without arguing with it:
 * inherits the theme's font and colours by default, sets nothing globally,
 * and exposes every value a publisher can change as a custom property that the
 * plugin prints on the element itself. Nothing here needs to be pasted into
 * Additional CSS, and nothing here can leak onto the rest of the page.
 */

.psfp-cta {
	--psfp-radius: 6px;
	--psfp-padding: 20px;
	--psfp-border: 1px solid;
	--psfp-border-color: rgba(128, 128, 128, 0.32);
	--psfp-bg: transparent;
	--psfp-color: inherit;
	--psfp-button-bg: #1a73e8;
	--psfp-button-color: #fff;
	--psfp-gap: 0.85em;

	box-sizing: border-box;
	margin: 1.75em 0;
	max-width: 100%;
	font-family: inherit;
	color: var(--psfp-color);
}

.psfp-cta *,
.psfp-cta *::before,
.psfp-cta *::after {
	box-sizing: inherit;
}

/*
 * Visibility.
 *
 * A suppressible invitation starts hidden and is revealed only once the tiny
 * inline script at the top of the page has confirmed this browser has not been
 * asked recently. Doing it this way round means a suppressed invitation never
 * flashes up and disappears, and the HTML stays byte-identical for every
 * visitor so full-page caching still works.
 *
 * If `psfp-ready` never arrives the bootstrap did not run — JavaScript is off,
 * or a content-security policy refused the inline script. Either way nothing
 * on the page will work, so every invitation drops to its <noscript> link:
 * the wrapper shows, its interactive contents do not, and the frame around it
 * goes too. Without that last part a site with a strict CSP is left with an
 * empty bordered box, because <noscript> content is not rendered when
 * scripting is merely blocked rather than switched off.
 *
 * This applies to every invitation, not only the suppressible ones. A CTA with
 * "hide it from readers who have used it" turned off is exactly as dead
 * without JavaScript as one with it turned on, and used to be left showing a
 * button that did nothing next to a link that worked.
 */
.psfp-cta[data-psfp-suppressible="1"] {
	display: none;
}

.psfp-fresh .psfp-cta[data-psfp-suppressible="1"] {
	display: block;
}

html:not(.psfp-ready) .psfp-cta[data-psfp-live] {
	display: block;
	padding: 0;
	border: 0;
	background: none;
}

html:not(.psfp-ready) .psfp-cta[data-psfp-live] .psfp-cta__inner {
	display: none;
}

.psfp-cta[hidden],
.psfp-cta__inner[hidden] {
	display: none !important;
}

/*
 * For a publisher's own markup: put this class on anything that should
 * disappear once a reader has used the invitation — a whole section, a menu
 * item, a card wrapping their own button.
 */
.psfp-asked .psfp-hide-when-asked {
	display: none !important;
}

.psfp-cta__heading {
	margin: 0 0 0.3em;
	font-size: 1.05em;
	font-weight: 700;
	line-height: 1.3;
	font-family: inherit;
	color: inherit;
}

.psfp-cta__text {
	margin: 0 0 var(--psfp-gap);
	line-height: 1.5;
	color: inherit;
}

.psfp-cta__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6em;
	align-items: center;
}

/*
 * The button.
 *
 * The selector is heavier than it looks like it needs to be, on purpose.
 * Themes style bare `button` elements with rules such as Twenty Twenty-One's
 * `button:not(:hover):not(:active):not(.has-background)` — three pseudo-classes
 * deep — and a single class loses to that. The result was a publisher choosing
 * a colour in the settings and getting the theme's instead, silently.
 *
 * Every part of this selector is an attribute or class the markup already
 * carries, so it costs nothing and adds no !important. A publisher who would
 * rather have their theme's own button look has a better route: build the
 * button with the Button block and tick "Open the preferred sources card".
 */
.psfp-cta[data-psfp-cta] .psfp-cta__button[data-psfp-fire],
.psfp-cta__button {
	font: inherit;
	font-weight: 600;
	line-height: 1.2;
	margin: 0;
	padding: 0.75em 1.35em;
	/* A comfortable tap target on a phone, which is where most of these are
	 * pressed. */
	min-height: 44px;
	width: auto;
	border: 0;
	border-radius: var(--psfp-radius);
	background: var(--psfp-button-bg);
	color: var(--psfp-button-color);
	text-decoration: none;
	text-transform: none;
	letter-spacing: normal;
	cursor: pointer;
	transition: filter 0.15s ease;
}

.psfp-cta[data-psfp-cta] .psfp-cta__button[data-psfp-fire]:hover {
	filter: brightness(0.92);
	background: var(--psfp-button-bg);
	color: var(--psfp-button-color);
}

.psfp-cta[data-psfp-cta] .psfp-cta__button[data-psfp-fire]:focus-visible {
	outline: 3px solid currentColor;
	outline-offset: 2px;
}

.psfp-cta__status {
	margin: 0.6em 0 0;
	font-size: 0.9em;
	line-height: 1.4;
	opacity: 0.85;
}

/*
 * The status line is a live region, so it has to be in the accessibility tree
 * *before* anything is written into it — a change inside a `display: none`
 * element is not announced. So it is clipped rather than removed: no visual
 * footprint, still spoken.
 */
.psfp-cta__status:not(.is-visible) {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.psfp-cta__fallback {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/* ------------------------------------------------------------- dismissal */

/*
 * The close control. Only drawn on the framed presentations, and only when
 * closing actually buys the reader something — see Renderer::close_control().
 */
.psfp-cta--card,
.psfp-cta--custom {
	position: relative;
}

.psfp-cta[data-psfp-cta] .psfp-cta__close[data-psfp-close] {
	position: absolute;
	top: 0;
	/* Logical, so it sits on the correct side in a right-to-left language
	 * rather than over the text. */
	inset-inline-end: 0;
	/* Comfortable on a phone, and clear of the card's own padding. */
	min-width: 44px;
	min-height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	margin: 0;
	border: 0;
	border-radius: var(--psfp-radius);
	background: none;
	color: inherit;
	font: inherit;
	font-size: 1.15em;
	line-height: 1;
	opacity: 0.6;
	cursor: pointer;
}

.psfp-cta[data-psfp-cta] .psfp-cta__close[data-psfp-close]:hover {
	opacity: 1;
	background: none;
	color: inherit;
}

.psfp-cta[data-psfp-cta] .psfp-cta__close[data-psfp-close]:focus-visible {
	outline: 3px solid currentColor;
	outline-offset: -3px;
	opacity: 1;
}

/* Room for it, so a long heading does not run underneath. */
.psfp-cta--card .psfp-cta__close ~ .psfp-cta__heading,
.psfp-cta--custom .psfp-cta__close ~ .psfp-cta__heading {
	padding-inline-end: 44px;
}

/*
 * A dismissed invitation keeps its place in the document so the reader's focus
 * is not thrown to the top of the page, but stops occupying any of it.
 */
.psfp-cta--dismissed[data-psfp-cta] {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
}

.psfp-cta--dismissed[data-psfp-cta]:focus {
	outline: none;
}

.psfp-cta__dismissed-note {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ---------------------------------------------------------------- styles */

/* Card — a bordered block. The default, and the one that reads as an
 * invitation rather than as part of the article. */
.psfp-cta--card,
.psfp-cta--custom {
	padding: var(--psfp-padding);
	border: var(--psfp-border) var(--psfp-border-color);
	border-radius: var(--psfp-radius);
	background: var(--psfp-bg);
}

.psfp-cta--borderless {
	border: 0;
}

/* Inline — the button on its own, no framing. */
.psfp-cta--inline .psfp-cta__text {
	margin-bottom: 0.6em;
}

/* Link — a quiet run of text, for a footer or a menu. */
.psfp-cta--link {
	margin: 0.75em 0;
}

.psfp-cta--link[data-psfp-cta] .psfp-cta__button[data-psfp-fire],
.psfp-cta--link[data-psfp-cta] .psfp-cta__button[data-psfp-fire]:hover {
	padding: 0;
	min-height: 0;
	background: none;
	color: inherit;
	font-weight: inherit;
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.psfp-cta--link[data-psfp-cta] .psfp-cta__button[data-psfp-fire]:hover {
	filter: none;
	opacity: 0.75;
}

/*
 * Google's own button. We draw the frame; everything inside is Google's.
 *
 * The slot stays a flex item rather than becoming a full-width block, so the
 * alignment rules below move the control itself. As a block box it filled the
 * row, and "centre" could then only centre whatever Google happened to draw
 * inline inside it — which is Google's business, changes between drawings
 * (an iframe in one, a shadow Material button in another), and left "centre"
 * and "right" doing nothing at all on the one presentation a publisher is
 * least able to restyle.
 */
.psfp-cta--google .psfp-cta__actions > [google-add-preferred-source-btn] {
	/* Shrink to whatever Google drew rather than to the width of the row. */
	flex: 0 0 auto;
	max-width: 100%;
}

/* ------------------------------------------------------- button variants */

.psfp-button--outline[data-psfp-cta] .psfp-cta__button[data-psfp-fire],
.psfp-button--outline[data-psfp-cta] .psfp-cta__button[data-psfp-fire]:hover {
	background: transparent;
	color: var(--psfp-button-bg);
	border: 2px solid var(--psfp-button-bg);
}

.psfp-button--text[data-psfp-cta] .psfp-cta__button[data-psfp-fire],
.psfp-button--text[data-psfp-cta] .psfp-cta__button[data-psfp-fire]:hover {
	padding: 0.2em 0;
	min-height: 0;
	background: none;
	color: var(--psfp-button-bg);
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/* ----------------------------------------------------------- alignment */

.psfp-align-center {
	text-align: center;
}

.psfp-align-center .psfp-cta__actions {
	justify-content: center;
}

.psfp-align-right {
	text-align: right;
}

.psfp-align-right .psfp-cta__actions {
	justify-content: flex-end;
}

/* Full width reads better on a phone, where a 200px button in the middle of a
 * 380px screen looks like an accident. */
.psfp-cta--full[data-psfp-cta] .psfp-cta__button[data-psfp-fire] {
	width: 100%;
	display: block;
}

.psfp-cta--full .psfp-cta__actions {
	display: block;
}

@media (prefers-reduced-motion: reduce) {
	.psfp-cta[data-psfp-cta] .psfp-cta__button[data-psfp-fire] {
		transition: none;
	}
}
