# Oxara loading and splash usage

Status: normative for new Oxara products and deliberate migrations of existing products.

This contract separates operating-system launch surfaces from loading states owned by the application. The animated OX loader communicates active work after an application can render its own interface. It does not replace the platform launch screen.

## Surface matrix

| Surface | Required treatment | Animation rule |
| --- | --- | --- |
| Web page or WebView | `assets/logo/svg/oxara-loader.svg` on light surfaces or `assets/logo/svg/oxara-loader-on-dark.svg` on Ink and Graphite surfaces, copied into the consumer at build time | Use one instance at `48–96 px`. Mount only while work is active and remove it when work finishes. |
| Native application after the first frame | Product-owned native vector implementation derived from the approved motion contract | Do not add Lottie, Rive or another runtime only for this loader. Use the platform renderer already owned by the product. |
| iOS system launch screen | Static approved OX mark in `UILaunchScreen` or the launch storyboard | No loader animation. If startup work continues, transition to an app-owned loading view after the first frame. |
| Android 12+ system splash screen | Product-owned `AnimatedVectorDrawable` derived from the approved mark | One non-looping animation, at most `1000 ms`. Use a static icon fallback where animated splash icons are unavailable. |
| Desktop application startup | Static platform splash or the first application window | Start animation only after the application owns the rendered window. |

Apple limits launch screens to basic platform views without application code or custom runtime behavior. See [Specifying your app's launch screen](https://developer.apple.com/documentation/xcode/specifying-your-apps-launch-screen/). Android requires an `AnimatedVectorDrawable` for an animated splash icon and recommends a duration no longer than 1000 ms. See [Splash screens](https://developer.android.com/develop/ui/views/launch/splash-screen).

## Web loader contract

- Intrinsic size: `96 × 96 px`.
- Normal rendered range: `48–96 px`.
- Maximum without a specific product review: `128 px`.
- Active instances: one per visible loading region and normally one per view.
- Display threshold: wait `300 ms` before mounting the loader to avoid flashing it for fast operations.
- Surface: keep the SVG background transparent. Place the loader over the product-owned content surface; do not bake a panel, card or full-screen background into the asset.
- Blocking work: cover only the affected region with a subtle translucent scrim, prevent interaction in that region and set `aria-busy="true"`. Do not hide the content behind an opaque fill.
- Non-blocking refresh: do not use a scrim. Keep unaffected content interactive and place the loader next to the region being refreshed.
- Completion: remove the loader immediately when content is ready. Never delay content to finish a cycle.
- Long-running work: after `10 s`, add a plain-language status and a recovery action when recovery is possible.
- Hidden state: remove the element from the document. Do not hide an active instance with opacity or off-screen positioning.
- Reduced motion: show the static primary OX mark with textual loading status when the consumer detects `prefers-reduced-motion: reduce`.

The SVG uses one shared path morph, one group rotation and one scale animation. Its source must remain within the repository's `8 KiB` performance budget. Full-viewport rendering is not an approved use.

The light-surface loader uses Turquoise + Graphite. The dark-surface loader uses Turquoise + Cloud. Consumers select the file from the actual surface and do not recolor either loader with CSS.

## Approved motion

- The four colored modules move clockwise and keep their assigned colors.
- Geometry changes between X and O while the modules move.
- Each quarter turn overshoots by `5°`, settles, and then holds for `416 ms`.
- Scale changes only during travel: normal size, a slight reduction to `0.988`, then normal size.
- The app-owned loop lasts `5.2 s`.
- No 3D rotation, glow, blur, shadow, gradient or color swapping.

The native system splash variants do not reproduce the full 5.2-second loop. They follow the platform limits in the surface matrix.

## Accessibility

The loader is decorative when adjacent status text already names the operation. In that case, use an empty alternative text and expose the status through the application's live-region or native accessibility API. When the loader is the only loading indicator, provide an accessible label such as `Loading` in the product language. Never rely on motion alone to explain failure, progress or completion.

## Distribution and lifecycle

Consumers receive the loader through a reviewed, versioned build-time export. Production products must not hot-link the SVG from a mutable branch or runtime CDN. Cache the local asset with the consumer release and preserve its provenance.

GIF, animated WebP and video are not canonical loader formats. They add raster frames, lose vector scaling and do not remove per-frame decoding or painting. The approved SVG remains the web source. Platform-owned native exports are created only when a product adopts the loader and must pass that product's review and release gates.
