/* ============================================================================
   PARITY UI group CSS — all U batches (u01–u06) consolidated.
   ----------------------------------------------------------------------------
   Mirrors src/components/ui/ — controls, overlays, display, smart fields,
   chart/map/theme, and magic primitives. Each batch's rules are kept in the
   original order (u01 before u02 before u03 …), so the cascade is identical
   to the old per-batch imports. The old components keep their Tailwind
   classes verbatim (served via /themes/tailwind.css); this file holds only
   the rules the shared bundle cannot express (dynamic data-[…] faces,
   vendored keyframes, scoped demo stages, missing utilities).
   ========================================================================== */

/* ── u01.css (1/6) ──────────────────────────────────────────── */

/* ui/button — the reference's default-size face carries `px-4`; the app's base
   button (0,0,1) already defers to the (0,1,0) utilities, and the (0,1,1) faces
   in forms.css (button.accent-grad / button.b13-outline) own default/outline. */

/* ui/switch + ui/checkbox — the reference controls have no gap / justify
   utilities (the switch floats its thumb, the checkbox is a 16px box), so the
   app's base button `gap: .4rem` + `justify-content: center` must be neutralised
   back to the initial value. (For the checkbox, display is block via the
   `block` utility, but the base button's specified gap/justify still surface in
   computed style.) */
button[data-slot="switch"],
button[data-slot="checkbox"] {
  gap: normal;
  justify-content: normal;
}

/* ui/switch — off/on track faces. The reference's data-[state=…] utilities sit
   in the 2nd+ `cn()` arguments of switch.tsx, so the fleet bundle's candidate
   scan may not emit them on a fresh checkout; define them here against the
   app's tokens so the port is self-sufficient. (On a worktree with the rebuilt
   bundle these duplicate the utilities harmlessly.) */
button[data-slot="switch"][data-state="unchecked"] {
  background-color: var(--ta-surface-2);
  border-color: var(--ta-border-strong);
}

button[data-slot="switch"][data-state="checked"] {
  background-color: var(--ta-accent);
}

/* ui/switch — thumb travel (the reference's `data-[state=checked]:translate-x-4`). */
[data-slot="switch-thumb"][data-state="checked"] {
  translate: 1rem 0;
}

[data-slot="switch-thumb"][data-state="unchecked"] {
  translate: 0 0;
}

/* ui/select — trigger height (the reference's `data-[size=default]:h-(--h-control)`). */
button[data-slot="select-trigger"][data-size="default"],
button[data-slot="select-trigger"][data-size="sm"] {
  height: var(--h-control);
}


/* ── u02.css (2/6) ──────────────────────────────────────────── */

/* Demo-page stage: the overlay components (dialog/sheet/command/confirm/sonner)
   are `position: fixed`, so this in-flow spacer gives the parity page a real
   height — the screenshot viewport then captures the full-height overlay. */
.u02-stage {
  min-height: 720px;
  padding-top: 1.5rem;
}

/* The parity block's `enter-stack` rise would fade the fixed overlays in over
   560ms (a partially-transparent scrim in a screenshot). These are static
   first-paint demos — paint them immediately, full strength. */
.enter-stack>.u02-stage,
.enter-stack>[data-slot="dialog-overlay"],
.enter-stack>[data-slot="sheet-overlay"],
.enter-stack>[data-slot="dialog-content"],
.enter-stack>[data-slot="sheet-content"] {
  animation: none;
}

/* ── Popover tier ─────────────────────────────────────────────────────────
   The old component floats `z-[60]` (above the z-50 overlay tier) via the
   `Z_POPOVER` token; that arbitrary utility isn't in the shared bundle. */
[data-slot="popover-content"] {
  z-index: 60;
}

/* ── Menu destructive face ────────────────────────────────────────────────
   `data-[variant=destructive]:text-destructive` (dropdown-menu.tsx +
   context-menu.tsx) — red text on the destructive item. */
[data-slot="dropdown-menu-item"][data-variant="destructive"],
[data-slot="context-menu-item"][data-variant="destructive"] {
  color: var(--ta-err);
}

/* ── Open sub-trigger face ────────────────────────────────────────────────
   `data-[state=open]:bg-accent data-[state=open]:text-accent-foreground`
   on the sub-trigger when its submenu is open. */
[data-slot="dropdown-menu-sub-trigger"][data-state="open"],
[data-slot="context-menu-sub-trigger"][data-state="open"] {
  background: var(--ta-accent-soft);
  color: var(--ta-accent-hover);
}

/* ── Command palette (ui/command.tsx) ─────────────────────────────────────
   cmdk is a virtual-DOM tree, so command.tsx styles it through
   `[&_[cmdk-group-heading]]:…` arbitrary variants the shared bundle doesn't
   emit. These rules reproduce them for the static render. */
[data-slot="command"] [cmdk-group-heading] {
  padding: 0.375rem 0.625rem;
  /* py-1.5 px-2.5 */
  font-size: 0.75rem;
  /* text-xs */
  font-weight: 500;
  /* font-medium */
  color: var(--ta-muted);
  /* text-muted-foreground */
}

/* `data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground`
   on the currently highlighted command item. */
[data-slot="command-item"][data-selected="true"] {
  background: var(--ta-accent-soft);
  color: var(--ta-accent-hover);
}

/* `h-(--h-control)` on the input wrapper (34px control height). */
[data-slot="command-input-wrapper"] {
  height: var(--h-control, 34px);
}

/* CommandDialog's `[&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3` override. */
[data-slot="command"] [data-slot="command-item"] {
  padding: 0.75rem 0.5rem;
}

/* ── Confirm host (ui/confirm.tsx) ────────────────────────────────────────
   The destructive icon-chip's `ring-destructive/15` ring colour — the
   `ring-1 ring-inset` utilities are present; only the colour class isn't. */
.u02-confirm-chip--destructive {
  --tw-ring-color: color-mix(in oklab, var(--ta-err) 15%, transparent);
}

/* ── Sonner toasts (ui/sonner.tsx) ────────────────────────────────────────
   The app's <Toaster> hosts the `sonner` library bottom-right with
   richColors + closeButton and boxShadow:none. Toasts are runtime-raised, so
   the parity page renders a static stack in sonner's emitted
   `data-sonner-toast` structure with the library's face mapped onto the
   app's tokens (the old component's own `--normal-bg/--normal-text/
   --normal-border` style overrides are the same tokens). */
.u02-toaster {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 999999999;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: min(356px, calc(100vw - 2rem));
  font-family: var(--ta-font);
  pointer-events: none;
}

.u02-toaster .sonner-toast {
  pointer-events: auto;
  display: flex;
  width: 100%;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.625rem;
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--ta-border);
  border-radius: var(--ta-r);
  background: var(--ta-popover);
  color: var(--ta-text);
  box-shadow: none;
  /* toastOptions style boxShadow:"none" */
  font-size: 0.875rem;
  line-height: 1.4;
  animation: u02-toast-in 0.35s var(--ta-ease) both;
}

.u02-toaster .sonner-toast-content {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  min-width: 0;
}

.u02-toaster [data-icon] {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
}

.u02-toast-icon {
  width: 1.25rem;
  height: 1.25rem;
}

.u02-toaster [data-title] {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ta-text);
}

.u02-toaster [data-description] {
  margin-top: 0.125rem;
  font-size: 0.8125rem;
  color: var(--ta-muted);
}

/* richColors per-type paint. */
.u02-toaster .sonner-toast[data-type="success"] {
  border-color: color-mix(in oklab, var(--ta-ok) 35%, var(--ta-border));
  background: color-mix(in oklab, var(--ta-ok) 8%, var(--ta-popover));
}

.u02-toaster .sonner-toast[data-type="success"] [data-icon] {
  color: var(--ta-ok);
}

.u02-toaster .sonner-toast[data-type="error"] {
  border-color: color-mix(in oklab, var(--ta-err) 35%, var(--ta-border));
  background: color-mix(in oklab, var(--ta-err) 8%, var(--ta-popover));
}

.u02-toaster .sonner-toast[data-type="error"] [data-icon] {
  color: var(--ta-err);
}

.u02-toaster .sonner-toast[data-type="default"] [data-icon] {
  color: var(--ta-muted);
}

/* Loading toast spins its icon. */
.u02-toaster .sonner-toast[data-type="default"] .u02-toast-icon {
  animation: u02-spin 1s linear infinite;
}

.u02-toaster .sonner-toast-close-button {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  margin-left: 0.375rem;
  border-radius: var(--ta-r-sm);
  color: var(--ta-muted);
  transition: color 140ms ease-out, background-color 140ms ease-out;
}

.u02-toaster .sonner-toast-close-button:hover {
  color: var(--ta-text);
  background: var(--ta-surface-2);
}

.u02-toast-close-x {
  width: 0.875rem;
  height: 0.875rem;
}

@keyframes u02-toast-in {
  from {
    opacity: 0;
    transform: translateY(0.5rem);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

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

@media (prefers-reduced-motion: reduce) {
  .u02-toaster .sonner-toast {
    animation: none;
  }
}


/* ── u03.css (3/6) ──────────────────────────────────────────── */

/* ui/table.tsx — row height. The reference fixes 38px explicitly so a
   skeleton row and a real row are the same height. */
.h-\[38px\] {
  height: 38px;
}

/* ui/skeleton.tsx — `bg-accent` resolved to the reference's neutral
   `--accent` (a light gray-blue, oklch 0.955 0.008 262); the new app's
   `--ta-accent` is the brand blue, which would tint the shimmer. Keep the
   reference's neutral shimmer fill. Element+attr out-specifies the bundle's
   `.bg-accent` (which loads after this file). */
div[data-slot="skeleton"] {
  background-color: oklch(0.955 0.008 262);
}

/* ui/avatar.tsx — AvatarGroup overlap (`-space-x-2`). The reference's
   Tailwind emits the sibling selector; reproduce the negative 0.5rem. */
.-space-x-2> :not([hidden])~ :not([hidden]) {
  margin-inline-start: -0.5rem;
}

/* ui/breadcrumb.tsx — crumb truncation cap. */
.max-w-\[22ch\] {
  max-width: 22ch;
}

/* ui/status-dot.tsx — the live pulse is `motion-safe:animate-pulse`, which
   only runs when the user hasn't asked for reduced motion. Reuse the
   bundle's own `pulse` keyframes. */
@media (prefers-reduced-motion: no-preference) {
  .motion-safe\:animate-pulse {
    animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  }
}

/* ui/badge-select.tsx — trigger hover lift (closed pill). */
.hover\:brightness-95:hover {
  filter: brightness(0.95);
}

.dark\:hover\:brightness-110:hover {
  filter: brightness(1.1);
}

/* ui/table.tsx — row selected / aria-expanded emphasis (not exercised by the
   demo's static rows, kept so the face is complete). */
.data-\[state=selected\]\:bg-muted[data-state="selected"] {
  background-color: var(--ta-muted);
}

.has-aria-expanded\:bg-muted:has([aria-expanded="true"]) {
  background-color: var(--ta-muted);
}

/* ui/button.tsx — `has-[>svg]:px-3` narrows an icon-bearing button. The
   demo buttons carry no svg, so this only matters for real call sites. */
.has-\[\>svg\]\:px-3:has(> svg) {
  padding-inline: 0.75rem;
}

/* ui/badge.tsx — `[&>svg]` sizing/pointer rules on a badge's icon. The
   date-badge's calendar is already sized by its own `size-3` class; these
   complete the face for any other icon-bearing badge. */
.\[\&>svg\]\:pointer-events-none>svg {
  pointer-events: none;
}

.\[\&>svg\]\:size-3>svg {
  width: 0.75rem;
  height: 0.75rem;
}

/* ui/badge-select.tsx — open-trigger ring (never visible in a static
   screenshot; the radix menu is out of scope). Kept minimal. */
.data-\[state=open\]\:ring-2[data-state="open"] {
  box-shadow: 0 0 0 2px var(--ta-accent);
}

.data-\[state=open\]\:ring-ring\/40[data-state="open"] {
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--ta-accent) 40%, transparent);
}

/* ui/stat-grid.tsx — the wrapper composes `.glass-card` for its material but
   owns its box (the hairline grid + `p-4` cells), so the app glass-card's
   default 1.25rem padding must not leak around the frame. */
div.glass-card.overflow-hidden.rounded-xl.border {
  padding: 0;
}

/* ----------------------------------------------------------------------------
   2. Base-rule neutralisation.

   The app's own unlayered base rules (base.css / buttons.css / tables.css)
   add things the reference's Tailwind preflight reset to zero, so every
   ported ui component must restore the reference face. Scoped to this batch's
   own data-slot / demo markup; app chrome is untouched.
   ------------------------------------------------------------------------- */

/* The app `button {}` base adds 8px vertical padding, a 1px border and
   line-height 1.2 — the reference preflight zeroed those on buttons, and the
   ported trigger/button utilities own the face. `button.accent-grad`
   (forms.css) already re-paints the default button, so this covers the bare
   triggers and the outline face. */
button[data-slot="select-trigger"],
button[data-slot="tabs-trigger"],
button[data-slot="button"] {
  padding-block: 0;
}

/* Zero the app base border only where the face carries none of its own — the
   outline button keeps its 1px `border` and re-asserts the border token. */
button[data-slot="button"]:not(.border) {
  border-width: 0;
}

button[data-slot="select-trigger"],
button[data-slot="tabs-trigger"] {
  border-width: 0;
}

/* The closed BadgeSelect pill inherits its line-height (the reference button
   had none of its own); `text-[11px]` sets no leading, so restore inherit. */
button[data-slot="select-trigger"] {
  line-height: inherit;
}

/* ui/button.tsx size-sm resolves to gap-1.5 (6px); the app base gap is 8px
   and the bundle orders gap-2 later, so force the reference value. */
button[data-slot="button"] {
  gap: 0.375rem;
}

/* Outline faces (badge + button) carry `border-border`; the bundle orders
   `border-transparent` after it, so the reference's muted border would be
   lost. Re-assert the border token at higher specificity. */
[data-slot="badge"].border-border {
  border-color: var(--ta-border);
}

button[data-slot="button"].border {
  border-color: var(--ta-border);
}

/* The app data-table base (tables.css) paints `table`/`th`/`td` as a card —
   fill, outer border, radius, uppercase heads, 0.95rem cells. ui/table.tsx is
   a flat hairline grid: transparent fill, no frame, cell padding from the
   utilities. */
table[data-slot="table"] {
  background: transparent;
  border: 0;
  border-radius: 0;
}

thead[data-slot="table-header"] th {
  padding-block: 0;
  border-bottom-width: 0;
  background: transparent;
}

tbody[data-slot="table-body"] td {
  padding-block: 0;
  border-bottom-width: 0;
  font-size: inherit;
  line-height: inherit;
}

/* base.css `p { margin: 0 0 1em }` and `ul, ol { margin; padding-left }` —
   the reference preflight zeroed these; the ported components (card body,
   tabs content, empty-state copy, breadcrumb trail) need the same. */
[data-slot="card"] p,
[data-slot="tabs-content"] p,
div.mx-auto.flex.max-w-sm p {
  margin: 0;
}

ol[data-slot="breadcrumb-list"] {
  margin: 0;
  padding-left: 0;
}

/* ui/breadcrumb.tsx: the reference gallery's Tailwind build does not compile
   the custom `text-label` / `text-mono-label` utilities, so the old trail
   renders at the body face (16px/400/1.5). Match that here. */
ol[data-slot="breadcrumb-list"],
ol[data-slot="breadcrumb-list"] a,
ol[data-slot="breadcrumb-list"] [data-slot="breadcrumb-page"] {
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  letter-spacing: inherit;
}

ol[data-slot="breadcrumb-list"] .text-mono-label {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  font-weight: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  color: inherit;
  font-variant-numeric: inherit;
}


/* ── u04.css (4/6) ──────────────────────────────────────────── */

.u04-demo {
  max-width: 40rem;
}

#currency[data-size] {
  height: var(--h-control);
}


/* ── u05.css (5/6) ──────────────────────────────────────────── */

/* ── AI signifier (old app.css `.ai-rainbow-*`) ──────────────────────────── */
.ai-rainbow-fill {
  background-image: linear-gradient(180deg,
      color-mix(in oklab, var(--ta-accent) 86%, white) 0%,
      var(--ta-accent) 100%);
  color: #ffffff;
}

.ai-rainbow-text {
  color: var(--ta-accent);
}

/* The retired halo — kept for compatibility, renders nothing (see app.css). */
.ai-rainbow-glow::after {
  content: none;
}

/* ── Operations map — night surface + pin lights (old app.css `.opsmap-*`) ─ */
/* Near-black ground behind the tiles — the same ground Carto's dark basemap
   draws, shown while they load (or if they fail to, or before the Leaflet
   bundle lands). Scoped one level deeper than `.leaflet-container`, whose own
   light-grey default would otherwise win: its stylesheet is injected into the
   head at runtime, so it always sorts after ours at equal specificity. */
.u05-opsmap .u05-opsmap-surface {
  background: #0b0f19;
  /* The surface carries the edge vignette (z-index 500) and Leaflet panes
     (z-index up to 700). Without a stacking context of its own those leak
     into the page and paint OVER dropdowns/modals (which sit at 20–70).
     isolation keeps them inside the map, so the map is one unit at
     z-index 0 in the page and overlays always win. */
  isolation: isolate;
}

/* Leaflet's divIcon chrome, reset — the pin draws its own light. */
.opsmap-icon {
  background: transparent;
  border: 0;
}

.opsmap-marker {
  position: relative;
  display: block;
  width: 16px;
  height: 16px;
  cursor: pointer;
}

.opsmap-dot {
  position: absolute;
  inset: 5px;
  border-radius: 9999px;
  background: #7dd3fc;
  box-shadow: 0 0 6px 1px rgba(125, 211, 252, 0.55);
}

.opsmap-halo {
  position: absolute;
  inset: 0;
  border-radius: 9999px;
  border: 1.5px solid transparent;
}

/* An open alarm burns red and rings outward until someone resolves it. */
.opsmap-marker.is-alarm .opsmap-dot {
  background: #f87171;
  box-shadow:
    0 0 10px 2px rgba(248, 113, 113, 0.85),
    0 0 28px 8px rgba(248, 113, 113, 0.35);
}

.opsmap-marker.is-alarm .opsmap-halo {
  border-color: rgba(248, 113, 113, 0.8);
  animation: opsmap-ping 1.6s cubic-bezier(0.16, 1, 0.3, 1) infinite;
}

/* A freshly-resolved alarm holds an amber ember for half an hour. */
.opsmap-marker.is-ember .opsmap-dot {
  background: #fbbf24;
  box-shadow: 0 0 9px 2px rgba(251, 191, 36, 0.6);
}

/* A detection just now: the site's light flashes cyan. */
.opsmap-marker.is-active .opsmap-dot {
  background: #38bdf8;
  box-shadow:
    0 0 9px 2px rgba(56, 189, 248, 0.8),
    0 0 22px 6px rgba(56, 189, 248, 0.3);
}

.opsmap-marker.is-active .opsmap-halo {
  border-color: rgba(56, 189, 248, 0.75);
  animation: opsmap-ping 2s cubic-bezier(0.16, 1, 0.3, 1) infinite;
}

@keyframes opsmap-ping {
  0% {
    transform: scale(0.5);
    opacity: 0.9;
  }

  100% {
    transform: scale(2.8);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {

  .opsmap-marker.is-alarm .opsmap-halo,
  .opsmap-marker.is-active .opsmap-halo {
    animation: none;
    transform: scale(1.4);
    opacity: 0.7;
  }
}

/* Site labels: quiet call-signs, not paper tooltips. Parked beside the
   marker rather than in the icon's flow, so the 16px icon box stays centred
   on the site's true point however long the name runs (the reference's
   permanent tooltip at offset [10, 0]). */
.u05-opsmap .opsmap-label {
  position: absolute;
  left: 26px;
  top: 50%;
  transform: translateY(-50%);
  white-space: nowrap;
  /* Pins are click-throughs now — the call-sign is part of the hit area. */
  pointer-events: auto;
  cursor: pointer;
  background: rgba(8, 12, 22, 0.72);
  border: 1px solid rgba(125, 211, 252, 0.22);
  border-radius: 4px;
  color: rgba(226, 236, 248, 0.92);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 6px;
}


/* ── u06.css (6/6) ──────────────────────────────────────────── */

/* Stage: sized, positioned host the effects paint over on the parity page. */
.u06-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  min-height: 280px;
  padding: 24px;
  border-radius: 16px;
  overflow: hidden;
}

/* Dark host for the white-tinted patterns (grid/dots), mirroring the dark
   hero sections the old landing painted them over. */
.u06-stage-dark {
  background-color: #0b0e14;
}

/* Left-aligned stage used by marquee / terminal. */
.u06-stage-left {
  align-items: stretch;
  justify-content: flex-start;
}

/* Caption documenting a retired effect on the parity page. */
.u06-note {
  position: relative;
  z-index: 1;
  max-width: 440px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted-foreground, #64748b);
}

.u06-stage-dark .u06-note {
  color: rgba(255, 255, 255, 0.5);
}

.u06-stage-left .u06-note {
  margin-top: 4px;
}

/* "Clean surface" panel for the components that return null (BorderBeam,
   Meteors, Particles, RetroGrid, Ripple): a quiet bordered panel with a
   caption, matching the docs ("sections that request X get a clean surface"). */
.u06-null {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 360px;
  padding: 40px 24px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
  text-align: center;
}

.u06-null-label {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
}

.u06-null-sub {
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
}

/* Orbit stage: a 280px box holding the fixed-position orbit chips. */
.u06-orbit {
  position: relative;
  width: 280px;
  height: 280px;
}

/* ---------------------------------------------------------------------------
 * Vendored `mu-*` keyframes from old/core/app/app.css (Magic UI, MIT). The
 * retired components don't emit these classes, but Terminal references
 * `mu-fade-up` inline so it must exist; the rest are kept for parity with the
 * old stylesheet. The global reduced-motion guard at the bottom freezes them.
 * ------------------------------------------------------------------------- */

/* Meteors — a shooting streak travels down-left along its rotation. */
@keyframes mu-meteor {
  0% {
    transform: rotate(var(--mu-angle, 215deg)) translateX(0);
    opacity: 1;
  }

  70% {
    opacity: 1;
  }

  100% {
    transform: rotate(var(--mu-angle, 215deg)) translateX(-500px);
    opacity: 0;
  }
}

/* Retro grid — the perspective floor scrolls toward the viewer forever. */
@keyframes mu-grid {
  0% {
    transform: translateY(-50%);
  }

  100% {
    transform: translateY(0);
  }
}

/* Ripple — a ring breathes outward then dissolves. */
@keyframes mu-ripple {

  0%,
  100% {
    transform: translate(-50%, -50%) scale(1);
  }

  50% {
    transform: translate(-50%, -50%) scale(0.9);
  }
}

/* Border beam — a bright dot runs the section's border path. */
@keyframes mu-border-beam {
  to {
    offset-distance: 100%;
  }
}

/* Marquee — one seamless track slides a full copy-width, then repeats. */
@keyframes mu-marquee {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(calc(-100% - var(--mu-gap, 1rem)));
  }
}

/* Instrument: no marquees. The track stands still; the duplicated copies a
   marquee renders for seamless looping are hidden so a logo rail reads as one
   static row. */
.mu-marquee-track {
  animation: none;
}

.mu-marquee-track[aria-hidden="true"] {
  display: none;
}

/* Orbit — a child rides a circle of `--mu-radius` at offset `--mu-angle`,
   counter-rotating so its own content stays upright. */
@keyframes mu-orbit {
  0% {
    transform: rotate(calc(var(--mu-angle, 0) * 1deg)) translateY(calc(var(--mu-radius, 80) * -1px)) rotate(calc(var(--mu-angle, 0) * -1deg));
  }

  100% {
    transform: rotate(calc(var(--mu-angle, 0) * 1deg + 360deg)) translateY(calc(var(--mu-radius, 80) * -1px)) rotate(calc(var(--mu-angle, 0) * -1deg - 360deg));
  }
}

/* Staggered reveal — a line/row fades up into place (Terminal, Activity feed).
   Each element sets its own `animation-delay` inline so they cascade. Paused
   at the start via `both` fill so nothing flashes before its turn. */
@keyframes mu-fade-up {
  from {
    opacity: 0;
    transform: translateY(8px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Aurora text — retired: gradient text is forbidden. Glyphs render in solid
   ink whatever background-image the component passes. */
.mu-aurora-text {
  background-image: none !important;
  color: inherit;
  animation: none;
}

/* Particles — a mote drifts up and dissolves (Particles background). */
@keyframes mu-drift {
  0% {
    transform: translateY(0);
    opacity: 0;
  }

  15% {
    opacity: var(--mu-mote-opacity, 0.5);
  }

  100% {
    transform: translateY(-42px);
    opacity: 0;
  }
}

/* Animated grid — a single cell breathes on and off (AnimatedGridPattern). */
@keyframes mu-cell {

  0%,
  100% {
    opacity: 0;
  }

  50% {
    opacity: 1;
  }
}

/* Word rotate — the outgoing word lifts out, the next drops in (WordRotate). */
@keyframes mu-word-in {
  from {
    opacity: 0;
    transform: translateY(0.6em);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ---------------------------------------------------------------------------
 * Reduced motion — freeze every `mu-*` animation to its resting frame,
 * mirroring the old app's global prefers-reduced-motion rule (app.css).
 * ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {

  .u06-stage *,
  .u06-stage *::before,
  .u06-stage *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------------------------------------------------------------------------
 * Copy-on-click (ui/field_cell::copyable) — readonly, engine-minted values
 * (alarm inbox aliases, keys) copy to the clipboard on click. The copy icon
 * swaps for a transient "Copied" label while the `.copied` state is set.
 * ------------------------------------------------------------------------- */
.field-cell.copyable {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  cursor: pointer;
  border-radius: 0.375rem;
  padding: 0.125rem 0.375rem;
  margin: -0.125rem -0.375rem;
  outline: none;
  max-width: 100%;
}

.field-cell.copyable:hover,
.field-cell.copyable:focus-visible {
  background: var(--ta-surface-2);
}

.field-cell.copyable:focus-visible {
  outline: 2px solid var(--ta-accent);
  outline-offset: 1px;
}

.field-cell.copyable svg {
  width: 0.875rem;
  height: 0.875rem;
  flex: none;
  color: var(--ta-faint);
}

.field-cell.copyable:hover svg {
  color: var(--ta-accent);
}

.field-cell.copyable .copy-ok {
  display: none;
  font-size: 0.625rem;
  font-weight: 600;
  color: var(--ta-accent);
  white-space: nowrap;
}

.field-cell.copyable.copied svg {
  display: none;
}

.field-cell.copyable.copied .copy-ok {
  display: inline;
}
}