/*
 * Component library.
 *
 * Every component is rendered from the matching PHP partial in parts/components/.
 * If a style is needed in two places it belongs here, never inline.
 */

/* ======================================================================
   Logo mark
   ======================================================================
   Lives in the shared component sheet, not the app shell: the auth screens
   and the marketing header need it too. */

.um-logo {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--logo-size, 26px);
	height: var(--logo-size, 26px);
	border: 2.5px solid var(--logo-colour, var(--brand));
	border-radius: var(--radius-full);
	flex-shrink: 0;
}

.um-logo__dot {
	width: 35%;
	height: 35%;
	border-radius: var(--radius-full);
	background: var(--logo-colour, var(--brand));
}

/* ======================================================================
   Buttons
   ====================================================================== */

.um-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	height: 40px;
	padding-inline: var(--space-4);
	border: 1px solid transparent;
	border-radius: var(--radius-md);
	background: var(--brand);
	color: var(--text-inverse);
	font-size: var(--fs-body);
	font-weight: 500;
	white-space: nowrap;
	cursor: pointer;
	transition: background var(--duration-fast) var(--ease),
	            border-color var(--duration-fast) var(--ease),
	            color var(--duration-fast) var(--ease);
}

.um-btn:hover { background: var(--brand-hover); color: var(--text-inverse); text-decoration: none; }
.um-btn:active { transform: translateY(1px); }

.um-btn[disabled],
.um-btn[aria-disabled="true"] {
	opacity: .55;
	cursor: not-allowed;
	pointer-events: none;
}

.um-btn--secondary {
	background: var(--surface);
	border-color: var(--border-strong);
	color: var(--text);
}

.um-btn--secondary:hover { background: var(--bg-subtle); color: var(--text); }

.um-btn--ghost {
	background: transparent;
	border-color: transparent;
	color: var(--text-secondary);
}

.um-btn--ghost:hover { background: var(--bg-subtle); color: var(--text); }

.um-btn--danger { background: var(--down); }
.um-btn--danger:hover { background: #D92D20; }

.um-btn--sm { height: 32px; padding-inline: var(--space-3); font-size: var(--fs-small); }
.um-btn--lg { height: 48px; padding-inline: var(--space-6); }
.um-btn--block { width: 100%; }

.um-btn--icon {
	width: 40px;
	padding: 0;
	flex-shrink: 0;
}

.um-btn--icon.um-btn--sm { width: 32px; }

/* The label swaps to a spinner in place so the button keeps its width and the
   layout does not jump while a request is in flight. */
.um-btn.is-loading {
	position: relative;
	color: transparent;
	pointer-events: none;
}

.um-btn.is-loading::after {
	content: "";
	position: absolute;
	width: 16px;
	height: 16px;
	border: 2px solid currentColor;
	border-top-color: transparent;
	border-radius: var(--radius-full);
	color: var(--text-inverse);
	animation: um-spin 700ms linear infinite;
}

.um-btn--secondary.is-loading::after,
.um-btn--ghost.is-loading::after { color: var(--text); }

@keyframes um-spin { to { transform: rotate(360deg); } }

/* ======================================================================
   Forms
   ====================================================================== */

.um-field { display: block; margin-block-end: var(--space-4); }

.um-label {
	display: block;
	font-size: var(--fs-small);
	font-weight: 500;
	margin-block-end: var(--space-2);
}

.um-input,
.um-select,
.um-textarea {
	width: 100%;
	height: 40px;
	padding-inline: var(--space-3);
	border: 1px solid var(--border-strong);
	border-radius: var(--radius-sm);
	background: var(--surface);
	color: var(--text);
	font-size: 0.875rem;
	transition: border-color var(--duration-fast) var(--ease),
	            box-shadow var(--duration-fast) var(--ease);
}

.um-textarea {
	height: auto;
	min-height: 96px;
	padding-block: var(--space-2);
	resize: vertical;
}

.um-input:focus,
.um-select:focus,
.um-textarea:focus {
	border-color: var(--brand);
	outline: none;
	box-shadow: 0 0 0 3px var(--brand-subtle);
}

.um-input::placeholder,
.um-textarea::placeholder { color: var(--text-muted); }

.um-input[aria-invalid="true"],
.um-input.has-error {
	border-color: var(--down);
}

.um-input[disabled],
.um-select[disabled] {
	background: var(--bg-subtle);
	color: var(--text-muted);
	cursor: not-allowed;
}

.um-input--mono { font-family: var(--mono); }

.um-hint {
	display: block;
	margin-block-start: var(--space-2);
	font-size: var(--fs-small);
	color: var(--text-secondary);
}

.um-error-text {
	display: block;
	margin-block-start: var(--space-2);
	font-size: var(--fs-small);
	color: var(--down);
}

/* Affix group: the https:// prefix and the "sec" suffix read as part of the
   field rather than as separate controls. */
.um-affix {
	display: flex;
	align-items: stretch;
	border: 1px solid var(--border-strong);
	border-radius: var(--radius-sm);
	background: var(--surface);
	overflow: hidden;
}

.um-affix:focus-within {
	border-color: var(--brand);
	box-shadow: 0 0 0 3px var(--brand-subtle);
}

.um-affix__text {
	display: flex;
	align-items: center;
	padding-inline: var(--space-3);
	background: var(--bg-subtle);
	border-inline-end: 1px solid var(--border);
	color: var(--text-muted);
	font-family: var(--mono);
	font-size: var(--fs-small);
	white-space: nowrap;
}

.um-affix__text--end {
	border-inline-end: 0;
	border-inline-start: 1px solid var(--border);
}

.um-affix .um-input {
	border: 0;
	border-radius: 0;
	box-shadow: none;
	flex: 1;
	min-width: 0;
}

.um-affix .um-input:focus { box-shadow: none; }

.um-affix__button {
	flex-shrink: 0;
	padding-inline: var(--space-4);
	border: 0;
	border-inline-start: 1px solid var(--border);
	background: var(--bg-subtle);
	color: var(--text-secondary);
	font-size: var(--fs-micro);
	font-weight: 500;
	cursor: pointer;
}

.um-affix__button:hover { color: var(--text); }

.um-check {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	cursor: pointer;
	font-size: 0.875rem;
}

.um-check input[type="checkbox"],
.um-check input[type="radio"] {
	width: 18px;
	height: 18px;
	margin: 0;
	accent-color: var(--brand);
	cursor: pointer;
	flex-shrink: 0;
}

.um-toggle {
	position: relative;
	display: inline-flex;
	width: 40px;
	height: 22px;
	flex-shrink: 0;
}

.um-toggle input {
	position: absolute;
	opacity: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	cursor: pointer;
}

.um-toggle__track {
	width: 100%;
	height: 100%;
	border-radius: var(--radius-full);
	background: var(--border-strong);
	transition: background var(--duration-fast) var(--ease);
	pointer-events: none;
}

.um-toggle__track::after {
	content: "";
	position: absolute;
	inset-block-start: 3px;
	inset-inline-start: 3px;
	width: 16px;
	height: 16px;
	border-radius: var(--radius-full);
	background: #fff;
	box-shadow: var(--shadow-sm);
	transition: transform var(--duration-fast) var(--ease);
}

.um-toggle input:checked + .um-toggle__track { background: var(--brand); }
.um-toggle input:checked + .um-toggle__track::after { transform: translateX(18px); }
.um-toggle input:focus-visible + .um-toggle__track { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Honeypot: invisible to people, irresistible to naive bots. Kept out of the
   accessibility tree so screen readers do not offer it either. */
.um-hp {
	position: absolute !important;
	left: -9999px !important;
	opacity: 0;
	height: 0;
	width: 0;
	pointer-events: none;
}

/* ======================================================================
   Cards and panels
   ====================================================================== */

.um-card {
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-sm);
}

.um-card__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-3);
	padding: var(--space-4) var(--space-6);
	border-block-end: 1px solid var(--border);
}

.um-card__title { font-size: var(--fs-h3); line-height: var(--lh-h3); font-weight: 600; }
.um-card__body { padding: var(--space-6); }
.um-card__body--flush { padding: 0; }
.um-card__footer {
	padding: var(--space-4) var(--space-6);
	border-block-start: 1px solid var(--border);
	background: var(--bg-subtle);
	border-end-start-radius: var(--radius-lg);
	border-end-end-radius: var(--radius-lg);
}

/* ======================================================================
   Status badge
   ====================================================================== */

.um-status {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	padding: 3px 10px 3px 8px;
	border-radius: var(--radius-full);
	font-size: var(--fs-small);
	font-weight: 500;
	white-space: nowrap;
}

/* The dot is decorative; the word beside it carries the meaning, so status is
   never communicated by colour alone. */
.um-status__dot {
	width: 8px;
	height: 8px;
	border-radius: var(--radius-full);
	flex-shrink: 0;
}

.um-status--up { background: var(--up-bg); color: var(--up); }
.um-status--up .um-status__dot { background: var(--up); }

.um-status--down { background: var(--down-bg); color: var(--down); }
.um-status--down .um-status__dot { background: var(--down); }

.um-status--degraded { background: var(--degraded-bg); color: var(--degraded); }
.um-status--degraded .um-status__dot { background: var(--degraded); }

.um-status--maintenance { background: var(--maintenance-bg); color: var(--maintenance); }
.um-status--maintenance .um-status__dot { background: var(--maintenance); }

.um-status--paused { background: var(--paused-bg); color: var(--text-secondary); }
.um-status--paused .um-status__dot { background: var(--paused); }

.um-status--pending { background: var(--pending-bg); color: var(--pending); }
.um-status--pending .um-status__dot { background: var(--pending); }

/* A bare dot for dense table rows, with a ring that keeps it visible against
   both surfaces. */
.um-dot {
	width: 8px;
	height: 8px;
	border-radius: var(--radius-full);
	flex-shrink: 0;
	display: inline-block;
}

.um-dot--up { background: var(--up); box-shadow: 0 0 0 3px var(--up-bg); }
.um-dot--down { background: var(--down); box-shadow: 0 0 0 3px var(--down-bg); }
.um-dot--degraded { background: var(--degraded); box-shadow: 0 0 0 3px var(--degraded-bg); }
.um-dot--maintenance { background: var(--maintenance); box-shadow: 0 0 0 3px var(--maintenance-bg); }
.um-dot--paused { background: var(--paused); box-shadow: 0 0 0 3px var(--paused-bg); }
.um-dot--pending { background: var(--pending); box-shadow: 0 0 0 3px var(--pending-bg); }

/* Pulse only on an open outage, and only for users who accept motion. */
@media (prefers-reduced-motion: no-preference) {
	.um-dot--down { animation: um-pulse 2s var(--ease) infinite; }
}

@keyframes um-pulse {
	0%, 100% { box-shadow: 0 0 0 3px var(--down-bg); }
	50% { box-shadow: 0 0 0 6px var(--down-bg); }
}

/* ======================================================================
   Uptime bar - one segment per day, 90 days
   ====================================================================== */

.um-uptime {
	display: flex;
	gap: 2px;
	height: 32px;
	align-items: stretch;
}

.um-uptime__seg {
	flex: 1;
	min-width: 2px;
	border-radius: 2px;
	background: var(--nodata);
	position: relative;
	cursor: default;
	transition: transform var(--duration-fast) var(--ease);
}

.um-uptime__seg--up { background: var(--up); }
.um-uptime__seg--down { background: var(--down); }
.um-uptime__seg--degraded { background: var(--degraded); }
.um-uptime__seg--maintenance { background: var(--maintenance); }

.um-uptime__seg:hover { transform: scaleY(1.12); }

.um-uptime__legend {
	display: flex;
	justify-content: space-between;
	margin-block-start: var(--space-2);
	font-size: var(--fs-micro);
	color: var(--text-muted);
}

/* ======================================================================
   Metric card
   ====================================================================== */

.um-metric {
	padding: var(--space-6);
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
}

.um-metric__label {
	font-size: var(--fs-micro);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--text-muted);
}

.um-metric__value {
	margin-block-start: var(--space-2);
	font-size: var(--fs-metric);
	line-height: var(--lh-metric);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	letter-spacing: -0.02em;
}

.um-metric__delta {
	display: inline-flex;
	align-items: center;
	gap: var(--space-1);
	margin-block-start: var(--space-2);
	font-size: var(--fs-small);
	font-variant-numeric: tabular-nums;
}

.um-metric__delta--up { color: var(--up); }
.um-metric__delta--down { color: var(--down); }
.um-metric__delta--flat { color: var(--text-muted); }

/* ======================================================================
   Tables
   ====================================================================== */

.um-table { width: 100%; font-size: 0.875rem; }

.um-table th {
	padding: var(--space-3) var(--space-4);
	text-align: start;
	font-size: var(--fs-micro);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--text-muted);
	border-block-end: 1px solid var(--border);
	white-space: nowrap;
}

.um-table td {
	padding: var(--space-3) var(--space-4);
	border-block-end: 1px solid var(--border);
	vertical-align: middle;
}

.um-table tbody tr:last-child td { border-block-end: 0; }
.um-table tbody tr:hover { background: var(--bg-subtle); }

.um-table__sort {
	display: inline-flex;
	align-items: center;
	gap: var(--space-1);
	background: none;
	border: 0;
	padding: 0;
	color: inherit;
	font: inherit;
	text-transform: inherit;
	letter-spacing: inherit;
	cursor: pointer;
}

.um-table__sort:hover { color: var(--text); }
.um-table__sort[aria-sort="ascending"] .um-table__caret { transform: rotate(180deg); }
.um-table__caret { transition: transform var(--duration-fast) var(--ease); }

.um-table__num { text-align: end; font-variant-numeric: tabular-nums; }

/* Below the tablet breakpoint each row becomes its own card; a 12-column table
   is unusable on a 375px screen and a customer reading an alert on their phone
   is the single most common mobile session we get. */
@media (max-width: 767px) {
	.um-table--cards thead { display: none; }
	.um-table--cards tbody tr {
		display: grid;
		grid-template-columns: auto 1fr;
		gap: var(--space-2) var(--space-3);
		padding: var(--space-4);
		border: 1px solid var(--border);
		border-radius: var(--radius-md);
		margin-block-end: var(--space-3);
		background: var(--surface);
	}
	.um-table--cards tbody td { border: 0; padding: 0; }
	.um-table--cards tbody td[data-label]::before {
		content: attr(data-label);
		display: block;
		font-size: var(--fs-micro);
		text-transform: uppercase;
		letter-spacing: .04em;
		color: var(--text-muted);
	}
}

/* ======================================================================
   Usage meter
   ====================================================================== */

.um-meter__head {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: var(--space-3);
	margin-block-end: var(--space-2);
	font-size: var(--fs-small);
}

.um-meter__track {
	height: 6px;
	border-radius: var(--radius-full);
	background: var(--border);
	overflow: hidden;
}

.um-meter__fill {
	height: 100%;
	border-radius: var(--radius-full);
	background: var(--brand);
	transition: width var(--duration-slow) var(--ease);
}

.um-meter--warn .um-meter__fill { background: var(--degraded); }
.um-meter--full .um-meter__fill { background: var(--down); }

/* ======================================================================
   Alerts, toasts, empty states, skeletons
   ====================================================================== */

.um-alert {
	display: flex;
	align-items: flex-start;
	gap: var(--space-3);
	padding: var(--space-3) var(--space-4);
	border: 1px solid;
	border-radius: var(--radius-md);
	font-size: 0.875rem;
}

.um-alert--error { background: var(--down-bg); border-color: var(--down); }
.um-alert--warn { background: var(--degraded-bg); border-color: var(--degraded); }
.um-alert--success { background: var(--up-bg); border-color: var(--up); }
.um-alert--info { background: var(--pending-bg); border-color: var(--pending); }

.um-alert__icon { flex-shrink: 0; margin-block-start: 2px; }
.um-alert--error .um-alert__icon { color: var(--down); }
.um-alert--warn .um-alert__icon { color: var(--degraded); }
.um-alert--success .um-alert__icon { color: var(--up); }
.um-alert--info .um-alert__icon { color: var(--pending); }

.um-toasts {
	position: fixed;
	inset-block-end: var(--space-6);
	inset-inline-end: var(--space-6);
	z-index: 60;
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
	pointer-events: none;
}

.um-toast {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	min-width: 280px;
	max-width: 380px;
	padding: var(--space-3) var(--space-4);
	background: var(--surface-raised);
	border: 1px solid var(--border);
	border-radius: var(--radius-md);
	box-shadow: var(--shadow-lg);
	font-size: 0.875rem;
	pointer-events: auto;
	animation: um-toast-in var(--duration-base) var(--ease);
}

.um-toast--success { border-inline-start: 3px solid var(--up); }
.um-toast--error { border-inline-start: 3px solid var(--down); }

@keyframes um-toast-in {
	from { opacity: 0; transform: translateY(8px); }
	to { opacity: 1; transform: none; }
}

.um-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding: var(--space-16) var(--space-6);
	gap: var(--space-3);
}

.um-empty__icon { color: var(--text-muted); }
.um-empty__title { font-size: var(--fs-h3); font-weight: 600; }
.um-empty__text { color: var(--text-secondary); max-width: 42ch; }

.um-skeleton {
	background: linear-gradient(90deg, var(--border) 25%, var(--bg-subtle) 50%, var(--border) 75%);
	background-size: 200% 100%;
	border-radius: var(--radius-sm);
	animation: um-shimmer 1.4s linear infinite;
}

@keyframes um-shimmer {
	from { background-position: 200% 0; }
	to { background-position: -200% 0; }
}

/* ======================================================================
   Modal and drawer
   ====================================================================== */

.um-overlay {
	position: fixed;
	inset: 0;
	z-index: 50;
	background: rgba(16, 24, 40, .5);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-4);
	animation: um-fade var(--duration-base) var(--ease);
}

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

.um-modal {
	width: 100%;
	max-width: 480px;
	background: var(--surface);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lg);
	animation: um-modal-in var(--duration-slow) var(--ease);
}

@keyframes um-modal-in {
	from { opacity: 0; transform: translateY(12px) scale(.98); }
	to { opacity: 1; transform: none; }
}

.um-drawer {
	position: fixed;
	inset-block: 0;
	inset-inline-end: 0;
	width: min(560px, 100vw);
	background: var(--surface);
	border-inline-start: 1px solid var(--border);
	box-shadow: var(--shadow-lg);
	display: flex;
	flex-direction: column;
	animation: um-drawer-in var(--duration-slow) var(--ease);
}

@keyframes um-drawer-in {
	from { transform: translateX(100%); }
	to { transform: none; }
}

.um-drawer__body { flex: 1; overflow-y: auto; padding: var(--space-6); }

.um-drawer__footer,
.um-modal__footer {
	display: flex;
	justify-content: flex-end;
	gap: var(--space-3);
	padding: var(--space-4) var(--space-6);
	border-block-start: 1px solid var(--border);
	background: var(--bg-subtle);
}

/* ======================================================================
   Tabs, pagination, tooltip
   ====================================================================== */

.um-tabs {
	display: flex;
	gap: var(--space-1);
	border-block-end: 1px solid var(--border);
	overflow-x: auto;
}

.um-tab {
	padding: var(--space-3) var(--space-4);
	border: 0;
	border-block-end: 2px solid transparent;
	background: none;
	color: var(--text-secondary);
	font-size: 0.875rem;
	font-weight: 500;
	white-space: nowrap;
	cursor: pointer;
	margin-block-end: -1px;
}

.um-tab:hover { color: var(--text); }
.um-tab[aria-selected="true"] { color: var(--brand); border-block-end-color: var(--brand); }

.um-segmented {
	display: inline-flex;
	padding: 3px;
	background: var(--bg-subtle);
	border: 1px solid var(--border);
	border-radius: var(--radius-md);
	gap: 2px;
}

.um-segmented__item {
	padding: 5px var(--space-3);
	border: 0;
	border-radius: var(--radius-sm);
	background: none;
	color: var(--text-secondary);
	font-size: var(--fs-small);
	font-weight: 500;
	cursor: pointer;
	white-space: nowrap;
}

/* :has() keeps the highlight on whichever radio was just clicked. is-active is
   only correct at render time, so without this the control looks frozen on its
   initial value - which reads as "this cannot be changed". */
.um-segmented__item[aria-pressed="true"],
.um-segmented__item:has(input:checked),
.um-segmented__item.is-active {
	background: var(--surface);
	color: var(--text);
	box-shadow: var(--shadow-sm);
}

/* A locked option must never look chosen, whatever the markup says. */
.um-segmented__item.is-locked,
.um-segmented__item:has(input:disabled) {
	background: none;
	box-shadow: none;
	color: var(--text-muted);
}

.um-segmented__item[disabled] { color: var(--text-muted); cursor: not-allowed; }

.um-tooltip {
	position: absolute;
	z-index: 70;
	padding: var(--space-2) var(--space-3);
	background: var(--text);
	color: var(--bg);
	border-radius: var(--radius-sm);
	font-size: var(--fs-micro);
	line-height: 1.4;
	white-space: nowrap;
	box-shadow: var(--shadow-md);
	pointer-events: none;
}

.um-pagination {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-3);
	padding: var(--space-3) var(--space-4);
	border-block-start: 1px solid var(--border);
	font-size: var(--fs-small);
	color: var(--text-secondary);
}
