/**
 * SCHB — the shared button state. Moved here from sch-course-blocks so both
 * plugins use one copy; CIS depends on nothing, and course blocks may depend
 * on CIS.
 *
 * ONLY THE BUTTON RULES CAME ACROSS. The catalogue's own tokens (--r, --t-ui,
 * --e-out, --navy, --white, --yellow …) did not: this sheet declares its own
 * fallbacks on .btn so it works on a page that has never heard of the
 * catalogue, and a host that HAS those tokens overrides them by setting the
 * same custom properties higher up. Nothing here was restyled — the disc, the
 * spinner, the tick and the cross are the same shapes, the same durations and
 * the same data URIs as v10.
 *
 * @package SCH_CIS
 */

.btn {
	position: relative;
	overflow: hidden;
	/* The disc's diameter IS the button's block-size, and SCHB measures the
	   button rather than being told — see size() in sch-schb.js, which sets this
	   property inline on the button it is about to run. 42px is the catalogue's
	   own button and stands only when there is nothing to measure: a button that
	   is not laid out at all. A host that wants a different disc sets this
	   property inline before the run. */
	--schb-disc: 42px;
	--schb-fold: calc(50% - var(--schb-disc) / 2);
	/* The catalogue reads these from :root. Declared here so a CIS screen that
	   has never loaded the catalogue still animates identically. */
	--schb-r: var(--r, 8px);
	--schb-t-ui: var(--t-ui, 160ms);
	--schb-e-out: var(--e-out, cubic-bezier(.2, .8, .2, 1));
	--schb-t-collapse: var(--t-collapse, 200ms);
	--schb-e-collapse: var(--e-collapse, cubic-bezier(.2, .8, .2, 1));
	--schb-navy: var(--navy, #122B46);
	--schb-white: var(--white, #fff);
	--schb-yellow: var(--yellow, #F2A81C);
}

/* The clip is installed only for the duration of a run, so an idle button
   paints exactly what it painted before — including its focus ring, which an
   always-on clip at inset(0) would cut away. */
.btn.is-morphing {
	clip-path: inset(0 0 0 0 round var(--schb-r));
	transition:
		background var(--schb-t-ui) var(--schb-e-out),
		color var(--schb-t-ui) var(--schb-e-out),
		clip-path var(--schb-t-collapse) var(--schb-e-collapse);
}
.btn.is-morphing.is-disc {
	clip-path: inset(0 var(--schb-fold) 0 var(--schb-fold) round calc(var(--schb-disc) / 2));
}
/* While it is a disc the outline WOULD be clipped away, so the disc carries its
   own ring inside its own edge — focus is visible in every phase. */
.btn.is-disc:focus-visible { outline-color: transparent; }
.btn.is-disc:focus-visible::after {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	translate: -50% -50%;
	inline-size: calc(var(--schb-disc) - 6px);
	block-size: calc(var(--schb-disc) - 6px);
	border: 2px solid var(--schb-white);
	border-radius: 999px;
	pointer-events: none;
}

/* The label leads the collapse out: 140ms against the clip's 200ms, so it has
   gone before the disc closes over where it was. */
.btn__lb {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	transition: opacity 140ms var(--schb-e-out), filter 140ms var(--schb-e-out);
}
.btn.is-pressed { transform: translateY(1px) scale(.985); transition: transform 100ms var(--schb-e-out); }
.btn.is-working, .btn.is-settled, .btn.is-failed { pointer-events: none; }
.btn.is-working .btn__lb, .btn.is-settled .btn__lb, .btn.is-failed .btn__lb { opacity: 0; filter: blur(2px); }

.btn__spin, .btn__ok, .btn__no {
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	translate: -50% -50%;
	opacity: 0;
	transition: opacity 140ms var(--schb-e-out);
	pointer-events: none;
}
.btn.is-working .btn__spin { opacity: 1; }
.btn.is-settled .btn__ok { opacity: 1; }
.btn.is-failed .btn__no { opacity: 1; }

.btn__spin {
	inline-size: 17px;
	block-size: 17px;
	border-radius: 99px;
	border: 2px solid rgba(255, 255, 255, .34);
	border-block-start-color: #fff;
	animation: schb-spin 620ms linear infinite;
}
@keyframes schb-spin { to { rotate: 360deg; } }

.btn__ok, .btn__no { inline-size: 17px; block-size: 17px; background-size: contain; background-repeat: no-repeat; }
.btn__ok { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l5 5L19 7'/%3E%3C/svg%3E"); }
/* The failing action answers in the disc too, with a mark of its own — the disc
   does not simply give up and reopen with nothing in it. */
.btn__no { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.5 6.5l11 11M17.5 6.5l-11 11'/%3E%3C/svg%3E"); }
.btn.is-failed { background: var(--schb-navy); }

.schb-err {
	margin: 6px 0 0;
	font-size: 12px;
	line-height: 1.4;
	color: var(--schb-navy);
	background: color-mix(in oklab, var(--schb-yellow) 34%, var(--schb-white));
	border-inline-start: 3px solid var(--schb-yellow);
	padding: 6px 9px;
	border-radius: 4px;
	opacity: 0;
	transition: opacity 140ms var(--schb-e-out);
}
.schb-err.is-in { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
	/* All three phases survive at FULL WIDTH, carried by opacity and colour
	   instead of motion: no collapse, no disc, no blur. The runtime never adds
	   the classes here, and these rules neutralise them anyway if the setting
	   is changed while a button is mid-run. */
	.btn.is-morphing, .btn.is-morphing.is-disc {
		clip-path: none;
		transition: background var(--schb-t-ui) var(--schb-e-out), color var(--schb-t-ui) var(--schb-e-out);
	}
	.btn.is-disc:focus-visible { outline-color: var(--schb-navy); }
	.btn.is-disc:focus-visible::after { content: none; }
	.btn__spin { animation: none; border-block-start-color: rgba(255, 255, 255, .8); }
	.btn.is-pressed { transform: none; opacity: .78; }
	.btn.is-working { opacity: .9; }
	.btn.is-settled { opacity: 1; }
	.btn.is-working .btn__lb, .btn.is-settled .btn__lb, .btn.is-failed .btn__lb { filter: none; }
	.btn__lb, .btn__spin, .btn__ok, .btn__no { transition: opacity 120ms var(--schb-e-out); }
}
