/* =============================================================================
	Dialogs, and the states between them.

	Each component here defines every state it has, reachable from markup rather than
	from a class name assembled in a template.

	A dialog gets `role="dialog"` and `aria-modal` from JavaScript, in one place. The
	backdrop is dimmed rather than blurred, since a blur on a full-screen overlay costs
	a compositing layer on every frame. Disclosure is a native `<details>`. Nothing
	here animates width, height, top or left, because that forces layout every frame.

	Depends on: tokens.css, base.css
	============================================================================= */

/* ── Dialog ────────────────────────────────────────────────────────────────── */

/* The dim layer: a flat tint, one compositing layer, no blur. */
.shiftora-modal-backdrop {
	position:         fixed;
	inset:            0;
	z-index:          var(--shiftora-z-overlay);
	display:          flex;
	align-items:      center;
	justify-content:  center;
	padding:          var(--shiftora-space-4);
	background:       rgba(12, 24, 60, 0.46);
	animation:        shiftora-fade-in var(--shiftora-duration-normal) var(--shiftora-ease-out);
}

@keyframes shiftora-fade-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}

/* The panel. The radius ceiling is `--shiftora-radius-xl`. */
.shiftora-modal {
	display:         flex;
	flex-direction:  column;
	inline-size:     100%;
	max-inline-size: 32rem;
	max-block-size:  min(90vh, 44rem);
	background:      var(--shiftora-color-bg-raised);
	border:          1px solid var(--shiftora-color-border);
	border-radius:   var(--shiftora-radius-xl);
	box-shadow:      var(--shiftora-shadow-lg);
	z-index:         var(--shiftora-z-modal);
	overflow:        hidden;
	animation:       shiftora-slide-up var(--shiftora-duration-normal) var(--shiftora-ease-out);
}

/* Wider variant for the support report, which has a body of prose. */
.shiftora-modal--lg {
	max-inline-size: 40rem;
}

@keyframes shiftora-slide-up {
	from { opacity: 0; transform: translateY(8px); }
	to   { opacity: 1; transform: translateY(0); }
}

.shiftora-modal__header {
	display:        flex;
	align-items:    flex-start;
	gap:            var(--shiftora-space-4);
	padding:        var(--shiftora-space-5) var(--shiftora-space-6) var(--shiftora-space-4);
	border-block-end: 1px solid var(--shiftora-color-border-light);
}

.shiftora-modal__header > div {
	min-inline-size: 0;
	flex:           1;
}

.shiftora-modal__title {
	margin:     0;
	font-size:   var(--shiftora-font-size-lg);
	font-weight: var(--shiftora-font-weight-semibold);
	color:      var(--shiftora-color-text);
}

/*
 * A dialog body is short. Scrolling belongs in the panel, and the footer stays
 * visible so the action is never below the fold.
 */
.shiftora-modal__body {
	padding:       var(--shiftora-space-5) var(--shiftora-space-6);
	overflow-y:    auto;
	font-size:     var(--shiftora-font-size-sm);
	line-height:   var(--shiftora-line-height-relaxed);
	color:         var(--shiftora-color-text-secondary);
	flex:          1;
}

.shiftora-modal__footer {
	display:        flex;
	align-items:    center;
	justify-content: flex-end;
	gap:            var(--shiftora-space-3);
	padding:        var(--shiftora-space-4) var(--shiftora-space-6);
	border-block-start: 1px solid var(--shiftora-color-border-light);
	background:     var(--shiftora-color-bg-surface);
	flex-wrap:      wrap;
}

.shiftora-modal__close {
	display:        flex;
	align-items:    center;
	justify-content: center;
	inline-size:    1.75rem;
	block-size:     1.75rem;
	flex:           none;
	padding:        0;
	border:         1px solid transparent;
	border-radius:  var(--shiftora-radius-sm);
	background:     transparent;
	color:          var(--shiftora-color-text-muted);
	font-size:      var(--shiftora-font-size-lg);
	line-height:    1;
	cursor:         pointer;
}

.shiftora-modal__close:hover {
	background: var(--shiftora-color-bg-surface-alt);
	color:      var(--shiftora-color-text);
}

/* On a phone a dialog is a sheet: full width and anchored to the bottom, within thumb reach. */
@media screen and (max-width: 600px) {
	.shiftora-modal-backdrop {
		align-items: flex-end;
		padding:     0;
	}

	.shiftora-modal {
		max-inline-size: none;
		max-block-size: 92vh;
		border-radius:   var(--shiftora-radius-xl) var(--shiftora-radius-xl) 0 0;
		animation:       shiftora-slide-up-sheet var(--shiftora-duration-slow) var(--shiftora-ease-out);
	}
}

@keyframes shiftora-slide-up-sheet {
	from { opacity: 0; transform: translateY(24px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* ── Accordion ─────────────────────────────────────────────────────────────── */

/*
 * A native `<details>` with a header that looks like a button. Open state, keyboard
 * operation and find-in-page come free. The chevron is CSS so it cannot desync.
 */
/* The rotation follows the element's own open state, not a class. */
/* ── Empty state ───────────────────────────────────────────────────────────── */

/*
 * Nothing here yet, and what to do about it. Never a blank panel or a spinner: a
 * heading in the second person and a sentence naming the next step.
 */
.shiftora-empty {
	display:         flex;
	flex-direction:  column;
	align-items:     center;
	text-align:      center;
	gap:             var(--shiftora-space-3);
	/*
	 * A larger step made a two-line message take a quarter of the screen, which reads
	 * as a section that failed to load.
	 */
	padding:         var(--shiftora-space-7) var(--shiftora-space-6);
	border:          1px dashed var(--shiftora-color-border-strong);
	border-radius:   var(--shiftora-radius-lg);
	background:      var(--shiftora-color-bg-surface);
}

.shiftora-empty__icon {
	display:        flex;
	align-items:    center;
	justify-content: center;
	inline-size:    2.5rem;
	block-size:     2.5rem;
	border-radius:  var(--shiftora-radius-full);
	background:     var(--shiftora-color-bg-inset);
	color:          var(--shiftora-color-text-muted);
}

.shiftora-empty__icon svg {
	inline-size: 1.25rem;
	block-size:  1.25rem;
}

.shiftora-empty__title {
	margin:     0;
	font-size:   var(--shiftora-font-size-base);
	font-weight: var(--shiftora-font-weight-semibold);
	color:      var(--shiftora-color-text);
}

.shiftora-empty__note {
	margin:     0;
	max-inline-size: 46ch;
	font-size:  var(--shiftora-font-size-sm);
	color:      var(--shiftora-color-text-secondary);
}

/* ── Loading ───────────────────────────────────────────────────────────────── */

/*
 * Loading says what is happening. The label sits beside the spinner, in reading
 * order, and not in a live region of its own so it is not announced twice.
 */
.shiftora-loading {
	display:     flex;
	align-items: center;
	gap:         var(--shiftora-space-3);
	padding:     var(--shiftora-space-6);
	font-size:   var(--shiftora-font-size-sm);
	color:      var(--shiftora-color-text-secondary);
}

.shiftora-loading--inline {
	padding: 0;
}

/* ── Figures ───────────────────────────────────────────────────────────────── */

/*
 * A number with its qualifier ("3.2 GB" versus "about 3.2 GB, measured at the
 * start"). Tabular figures keep the value from jittering while it counts.
 */
.shiftora-figure {
	display:        inline-flex;
	flex-direction: column;
	gap:            2px;
	min-inline-size: 0;
}

.shiftora-figure__value {
	font-size:      var(--shiftora-font-size-xl);
	font-weight:    var(--shiftora-font-weight-semibold);
	line-height:    var(--shiftora-line-height-tight);
	color:          var(--shiftora-color-text);
	font-variant-numeric: tabular-nums;
}

.shiftora-figure__label {
	font-size:  var(--shiftora-font-size-xs);
	color:      var(--shiftora-color-text-muted);
}

.shiftora-figure__note {
	font-size:  var(--shiftora-font-size-xs);
	color:      var(--shiftora-color-text-muted);
}

/* ── Definition rows ───────────────────────────────────────────────────────── */

/*
 * Label and value on one line, wrapping to a stack when there is no room. The
 * default for facts about a site, which are not a set of objects to put in cards.
 */
.shiftora-deflist {
	margin: 0;
	display: flex;
	flex-direction: column;
}

.shiftora-deflist__row {
	display:     grid;
	grid-template-columns: minmax(8rem, 14rem) minmax(0, 1fr);
	gap:         var(--shiftora-space-3);
	padding:     var(--shiftora-space-2) 0;
	font-size:   var(--shiftora-font-size-sm);
	border-block-start: 1px solid var(--shiftora-color-border-light);
}

.shiftora-deflist__row:first-child {
	border-block-start: 0;
}

.shiftora-deflist__row dt {
	color:       var(--shiftora-color-text-secondary);
}

.shiftora-deflist__row dd {
	margin:      0;
	color:       var(--shiftora-color-text);
	font-weight: var(--shiftora-font-weight-medium);
	min-inline-size: 0;
	overflow-wrap: anywhere;
}

@media screen and (max-width: 480px) {
	.shiftora-deflist__row {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.shiftora-deflist__row dd {
		font-weight: var(--shiftora-font-weight-regular);
	}
}

/* ── Table helpers ─────────────────────────────────────────────────────────── */

/*
 * A table that is read rather than scanned: dense rows and a muted header.
 */
.shiftora-table--compact th,
.shiftora-table--compact td {
	padding-block: var(--shiftora-space-2);
	font-size:     var(--shiftora-font-size-sm);
}

/* The row's primary cell carries two facts, so they stack rather than run together. */
.shiftora-table__primary {
	white-space: nowrap;
	font-weight: var(--shiftora-font-weight-medium);
}

.shiftora-table__sub {
	display:     block;
	font-size:   var(--shiftora-font-size-xs);
	font-weight: var(--shiftora-font-weight-regular);
	color:       var(--shiftora-color-text-muted);
}

/* ── The feature list's label ──────────────────────────────────────────────── */

/* The label wraps, so a long name is never truncated. */
.shiftora-checklist__label {
	min-inline-size: 0;
	overflow-wrap:   anywhere;
}

/* The moment under the name: its own line, body weight, never competing with the label. */
.shiftora-checklist__detail {
	display:     block;
	font-weight: 400;
}

/* ── An empty state inside a card ───────────────────────────────────────────── */

/*
 * Words, not an illustration. This empty state is a long paragraph because the
 * reader needs to know what happens without restore points, not merely that
 * there are none.
 */
.shiftora-empty-state {
	padding:            var(--shiftora-space-6) var(--shiftora-space-5);
	color:              var(--shiftora-color-text-muted);
	text-align:         start;
	background:         var(--shiftora-color-bg-subtle);
	border:             1px dashed var(--shiftora-color-border);
	border-radius:      var(--shiftora-radius-lg);
}

.shiftora-empty-state p {
	margin: 0;
	max-inline-size: 60ch;
}

/* ── The global banner ──────────────────────────────────────────────────────── */

/**
 * A live region for messages that arrive without the user asking. Sized by content
 * so an idle shell has no gap. `aria-live` stays on the element, since a region that
 * becomes polite at the same moment as its text is often not announced.
 */
.shiftora-banner:empty {
	display: none;
}

/*
 * Holding an alert, the banner is only a slot for it. Its own border and fill
 * would draw a box inside the alert's box.
 */
.shiftora-banner:has(> .shiftora-alert) {
	display:    block;
	padding:    0;
	border:     0;
	background: none;
}

.shiftora-banner:not(:empty) {
	display:       flex;
	align-items:   center;
	gap:           var(--shiftora-space-3);
	margin-block:  var(--shiftora-space-4);
	padding:       var(--shiftora-space-3) var(--shiftora-space-4);
	border:        1px solid var(--shiftora-color-border);
	border-radius: var(--shiftora-radius-md);
	background:    var(--shiftora-color-bg-subtle);
	font-size:     var(--shiftora-font-size-sm);
}

.shiftora-banner.is-success {
	border-color: var(--shiftora-color-success-border);
	background:   var(--shiftora-color-success-bg);
	color:        var(--shiftora-color-success-text);
}

.shiftora-banner.is-error {
	border-color: var(--shiftora-color-error-border);
	background:   var(--shiftora-color-error-bg);
	color:        var(--shiftora-color-error-text);
}

/* ── Button internals ───────────────────────────────────────────────────────── */

/**
 * The label inside a button, when something else is in there too. A span so the
 * arrow after "Connect & Continue" is not read aloud as part of the label.
 */
.shiftora-btn__text {
	display: inline-block;
}

/* ── The extra-small button ─────────────────────────────────────────────────── */

/**
 * For a row of many small actions, such as removing a find/replace rule. A
 * `--danger` icon button at this size is meant to feel cheap next to saving one.
 */
.shiftora-btn--xs {
	min-block-size: 1.75rem;
	padding:       0 var(--shiftora-space-2);
	font-size:     var(--shiftora-font-size-xs);
}

.shiftora-btn--xs .shiftora-btn__icon {
	inline-size: 0.875rem;
	block-size:  0.875rem;
}

/* ── A labeled checkbox or radio ───────────────────────────────────────────── */

.shiftora-check__title {
	display:       block;
	font-weight:   var(--shiftora-font-weight-semibold);
}

.shiftora-check__text {
	display: block;
	min-inline-size: 0;
}

/* ── A wider dialog ─────────────────────────────────────────────────────────── */

/**
 * The migration dialog holds a stage list, a progress figure and a live log at once.
 * Capped in vw: a log line is unreadable once it wraps, and a dialog wider than the
 * screen hides the backdrop used to dismiss it.
 */
.shiftora-modal--xl {
	max-inline-size: min(64rem, 94vw);
}
