Skip to content

PAM Native

PAM Native turns typed PHP components into real Android Views and UIKit controls. Rust owns validation, reconciliation, diffing, and layout; Kotlin and Swift apply compact mutation batches. There is no WebView, JavaScript runtime, or browser CSS engine.

PHP 8.5 first

Typed components, state, actions, routes, and generated contracts.

Native by construction

Input, scrolling, gestures, media, animation, and accessibility stay native.

One style compiler

CSS-like source, utilities, recipes, and typed styles lower to the same IR.

Explainable speed

Every property declares its layout, paint, or composition cost.
  1. Install PAM and verify the machine.

    Terminal window
    curl --proto '=https' --proto-redir '=https' --tlsv1.2 \
    --connect-timeout 15 --max-time 60 --max-filesize 1048576 \
    -fsSL https://github.com/push-in/pam/releases/latest/download/install.sh | sh
    pam doctor
  2. Create a complete mobile project. Android and iOS hosts come by default.

    Terminal window
    pam init my-app --template native
    cd my-app
    pam composer require pushinbr/pam-native
    pam doctor --fix
  3. Launch it.

    Terminal window
    pam dev
    # or: pam run android / pam run ios

Builds are project-clean by contract: PAM preserves declared APK/AAB/IPA/app outputs and evidence, then removes regenerable Gradle, Xcode, SwiftPM, Rust, and generated-host intermediates even when the command fails. Read the mandatory build hygiene contract for the exact retention boundary.

pam doctor --fix handles SDK licenses and installs required, checksum-verified runtime artifacts. Production builds do not require a local Rust toolchain.

Every PAM and PAM Native release is blocked until CI creates a disposable project with pam init --template mobile and successfully completes pam dev on a clean Android emulator. The same release gate covers the official Native UI starter and the server, HTTP, and Laravel templates. It verifies automatic Composer/Gradle/SDK/NDK/runtime setup, installation, process liveness, Logcat, and a captured frame. This is the exact public workflow, not a preassembled fixture.

If PAM can safely repair a missing tool or license, it does so. If the host cannot satisfy a requirement, pam doctor --fix reports the exact prerequisite and verification command; publication remains blocked.

<?php
declare(strict_types=1);
use Pam\Native\Attributes\Action;
use Pam\Native\Attributes\Prop;
final class ProductCard
{
public function __construct(
#[Prop] public readonly Product $product,
#[Prop] public bool $favorite = false,
) {}
#[Action]
public function toggleFavorite(): void
{
$this->favorite = !$this->favorite;
}
}
?>
<template language="2">
<Card class="product-card">
<Image :source="$product.cover" decorative="true" />
<Heading>{{ $product.name }}</Heading>
<Button on:press="toggleFavorite">Favorite</Button>
</Card>
</template>
<style scoped>
@tokens { color.surface: #10131a; space.card: 20px; }
.product-card {
gap: 12px;
padding: var(--space-card);
background: var(--color-surface);
border-radius: 20px;
}
.product-card > Button:pressed {
opacity: 72%;
transform: scale(0.98);
}
</style>

Use {{ }} for text, :property="$path" for native properties, and p-model for two-way input/toggle binding. PHP attributes remain the typed prop/action contract.

PAM Native is more than a renderer. It is a retained-native application platform: PHP describes typed intent, Rust validates and reconciles it, and Kotlin/Swift keep interaction, scrolling, media, animation, and platform work on the native side. The following catalog covers the complete supported surface.

Every core visual component has two first-class authoring forms. The typed tree is ideal for builders, libraries, generated UI, and explicit refactoring. Tags are ideal for application screens and keep PHP state/actions beside a concise template. They compile to the same retained tree, native node kinds, properties, events, style IR, and performance path; mixing both forms is supported.

use Pam\Native\Style;
use Pam\Native\UI\{Column, Row, SafeAreaView, Screen, Text, View};
return Screen::make(
SafeAreaView::make(
Column::make(
Text::make('Dashboard')->style(new Style(fontSize: 28)),
Row::make(
View::make(Text::make('Revenue'))->key('revenue'),
View::make(Text::make('Orders'))->key('orders'),
)->style(new Style(gap: 12)),
)->style(new Style(flexGrow: 1, padding: 24, gap: 16)),
),
);
use Pam\Native\KeyboardType;
use Pam\Native\UI\{Button, Column, Input, Toggle};
return Column::make(
Input::make($this->email)
->placeholder('you@example.com')
->keyboard(KeyboardType::Email)
->onChange(fn (string $value) => $this->email = $value),
Toggle::make($this->newsletter)
->onToggle(fn (bool $value) => $this->newsletter = $value),
Button::make('Continue')->onPress(fn () => $this->submit()),
);
use Pam\Native\ImageFit;
use Pam\Native\MediaCachePolicy;
use Pam\Native\UI\Image;
return Image::make($this->user->avatarUrl)
->fit(ImageFit::Cover)
->defaultSource('asset://avatar-placeholder.png')
->cache(MediaCachePolicy::StaleWhileRevalidate)
->cacheKey("avatar:{$this->user->id}")
->pinOffline()
->onError(fn ($event) => $this->report($event->error));
use Pam\Native\UI\VirtualizedList;
return VirtualizedList::make(
...array_map(
fn (Post $post) => PostCard::make($post)->key("post:{$post->id}"),
$this->posts,
),
)
->estimatedRowHeight(604)
->prefetch(6)
->onEndReached(fn () => $this->loadNextPage());
use Pam\Native\GestureDirection;
use Pam\Native\GestureType;
use Pam\Native\UI\GestureDetector;
return GestureDetector::make(GestureType::Pan, $card)
->direction(GestureDirection::Horizontal)
->minimumDistance(12)
->onUpdate(fn ($event) => $this->dragX = $event->translationX)
->onEnd(fn ($event) => $this->finishDrag($event->velocityX));
use App\UI\Filters;
use Pam\Native\BottomSheetKeyboardBehavior;
use Pam\Native\UI\BottomSheet;
return BottomSheet::make(
Filters::make(),
snapPoints: [0.35, 0.7, 1.0],
index: $this->sheetIndex,
)
->dismissible()
->keyboardBehavior(BottomSheetKeyboardBehavior::Interactive)
->onDismiss(fn () => $this->filtersOpen = false);
use Pam\Native\MediaCachePolicy;
use Pam\Native\MediaType;
use Pam\Native\UI\MediaPlayer;
return MediaPlayer::make($this->episodeUrl, MediaType::Video)
->controls()
->streamingCache()
->cache(MediaCachePolicy::Disk)
->onProgress(fn ($current, $duration) => $this->progress($current, $duration))
->onEnd(fn () => $this->playNext());
use Pam\Native\UI\WebView;
return WebView::make('https://app.example.com/embedded')
->allowedHosts(['app.example.com'])
->javaScriptEnabled()
->onMessage(fn (string $json) => $this->handleMessage($json));

Official visual packages provide a high-level typed Renderable. Templates can mount the same registered host view through the built-in CustomView tag. Keep the typed wrapper when you want package enums and decoded events; use the tag when the property map already belongs to declarative component state.

use Pam\Native\Camera\{CameraEventKind, CameraFacing, CameraMode, CameraView};
return CameraView::make()
->facing(CameraFacing::Back)
->mode(CameraMode::PhotoAndVideo)
->fps(60)
->pinchToZoom()
->onEvent(function ($event): void {
if ($event->kind === CameraEventKind::PhotoCaptured) {
$this->savePhoto($event->capture);
}
});

The same tag boundary mounts media.camera, video.player, scanner.camera, canvas.view, gpu.surface, three-d.scene, and maps.map. Their package wrappers remain the preferred typed tree API because they validate limits and decode native events before application code receives them.

Capability What you can build Complete reference
Three authoring styles Typed PHP trees, class components with templates, or single-file .pam components Components
Vue-like templates {{ expression }}, :prop, @event, on:event, p-model, conditionals, loops, slots, refs, and safe expressions Template syntax
Typed contracts #[Prop], #[State], #[Action], #[Computed], #[Watch], #[Effect], #[Expose], lifecycle hooks, context, and error boundaries Component runtime
Retained rendering Stable native identity, keyed reconciliation, compact mutation batches, and subtree invalidation State and lifecycle
Visual DOM Typed selectors, traversal, classList, attributes, dataset, inline/computed styles, atomic mutations, observers, focus, measurement, and motion Visual DOM
Scoped styling Scoped/module/global styles, imports, cascade, selectors, variables, tokens, recipes, responsive queries, keyframes, and strict diagnostics PAM Style Language
Responsive UI Flex, native grid, twelve-column layouts, breakpoints, safe areas, fold posture, TV/remote input, and container queries Responsive layout
Forms Typed fields, validation attributes, touched/dirty state, server errors, submission state, drafts, reset, and p-model Forms and validation

These are retained Android Views and UIKit controls—not HTML elements painted in a WebView.

Family Included surface Complete reference
Layout Screen, View, rows, columns, grids, safe areas, spacers, wrapping, clipping, and custom chrome Layout and views
Text and input Text, headings, rich text, packaged fonts, inputs, text areas, buttons, pressables, switches, checkboxes, radio controls, sliders, keyboard events, and accessories Text, input, and controls
Images and drawing Packaged/remote/authenticated images, resize modes, progressive loading, cache policy, prefetch, offline pinning, backgrounds, thumbnails, and drawing canvas Images and cache
Scrolling and large data Scroll views, recycled/virtualized lists, sections, grids, pagination, snapping, restoration, pull-to-refresh, and imperative jumps Scroll and lists
Interaction and motion Press feedback, taps, long press, pan, pinch, rotation, drag/drop, context menus, native-state selectors, and compositor animation Interaction and motion
Overlays and system UI Modals, bottom sheets, drawers, progress indicators, status/navigation bars, safe keyboard handling, and input accessories Overlays and system UI
Audio and video Native playback, controls, lifecycle events, streaming cache, bounded downloads, and offline pinning Video and audio
Web content Host-allowlisted WebView, bounded JavaScript injection, inline media, navigation policy, and native message bridge WebView
Design system Retained-native Material 3 components, themes, typed facades, directives, accessibility, and Android/iOS parity PAM Native UI · complete component catalog
App-owned controls Register application-owned Android Views and generated custom views without leaving the retained tree Custom native views
Capability Included surface Complete reference
Local and scoped state Typed local state, computed values, effects, watchers, context, persistence, memoization, and render control State and lifecycle
Global store Vuex-style actions, selectors, computed values, transactions, persistence/migrations, optimistic updates, undo, middleware, replicas, and DevTools Global store
Navigation Named stacks, tabs, top tabs, drawers, nested navigators, typed parameters, groups, deep links, notifications, shared content, persistence, transitions, shared elements, and predictive back Navigation
Networking Bounded GET/POST/PUT/PATCH/DELETE and JSON requests, typed responses, headers, cancellation, timeouts, and explicit transport failures HTTP networking
Files and galleries File, image, video, audio, and filtered mixed-gallery pickers Files and media picker
Platform runtime Typed IDL bridge, priority lanes, async work, native worklets, virtualization, background jobs, offline sync, Canvas, and bounded server-driven UI Platform runtime
Device capabilities Permissions, contacts, location, recording, files, links, notifications, background work, SQLite, sensors, and device state Platform capabilities

Install only what an application needs. Every package below is independently versioned, usable without a bundle such as “feed” or “social”, and talks to PAM Native through the same typed plugin contract.

Terminal window
pam composer require pushinbr/pam-native-camera
# Replace camera with any capability listed below.
Package Capability Reference
pushinbr/pam-native-camera Low-latency professional capture, devices, formats, focus, exposure, zoom, flash/torch, frame processors, photo, and video Camera
pushinbr/pam-native-media Sandboxed media probing, correctly oriented thumbnails, and lifecycle-aware photo/video capture Media
pushinbr/pam-native-video Adaptive HLS/DASH and local playback with Media3/AVPlayer, tracks, controls, seek, and progress Video
pushinbr/pam-native-media-editor Typed photo/video timelines, transforms, filters, audio, composition, progress, and native export Media Editor
pushinbr/pam-native-scanner Realtime QR/barcode scanning through CameraX/ML Kit and AVFoundation/Vision Scanner
pushinbr/pam-native-canvas Retained-mode native 2D scene graphs with bounded PHP commands Canvas
pushinbr/pam-native-gpu Programmable OpenGL ES 3 and Metal fragment rendering without a JavaScript bridge GPU
pushinbr/pam-native-3d GLB and USDZ scenes through Filament and RealityKit 3D

Device, proximity, health, and system surfaces

Section titled “Device, proximity, health, and system surfaces”
Package Capability Reference
pushinbr/pam-native-bluetooth BLE scan, connect, discovery, read, write, subscribe, opaque IDs, and lifecycle-safe events Bluetooth
pushinbr/pam-native-nfc Bounded NDEF read/write with Android reader mode and iOS system sessions NFC
pushinbr/pam-native-health Health Connect/HealthKit permissions and typed steps, heart rate, weight, calories, and sleep Health
pushinbr/pam-native-maps Google Maps/MapKit camera, styles, user location, gestures, markers, overlays, and events Maps
pushinbr/pam-native-intents Android Dynamic Shortcuts and Apple App Intents mapped to named PAM routes Intents
pushinbr/pam-native-live-activities ActivityKit Live Activities and Android ongoing notifications Live Activities
pushinbr/pam-native-widgets Android App Widgets and WidgetKit timelines with stable IDs and deep links Widgets
pushinbr/pam-native-share-extension Text, URL, and sandboxed-file intake from Android shares and iOS Share Extensions Share Extension
Package Capability Reference
pushinbr/pam-native-auth Keystore/Keychain encrypted credentials and OAuth 2.1 PKCE material Auth
pushinbr/pam-native-payments Stripe PaymentSheet, native wallets, and SCA/3DS with server-owned secrets Payments
pushinbr/pam-native-subscriptions StoreKit 2 and Play Billing products, purchase, restore, verification, acknowledgement, and entitlement safety Subscriptions
pushinbr/pam-native-firebase Firebase apps, Analytics, Remote Config, Messaging tokens, Installations, Crashlytics, and flag adapters Firebase
pushinbr/pam-native-realtime Native-owned RFC 6455 WebSockets that survive PHP renders/reloads with bounded queues Realtime
pushinbr/pam-native-background-transfer OS-scheduled durable HTTPS upload/download with constraints, progress, and relaunch recovery Background Transfer

Offline data, delivery, quality, and operations

Section titled “Offline data, delivery, quality, and operations”
Package Capability Reference
pushinbr/pam-native-nitro Model-driven, offline-first data flows on native SQLite workers Nitro
pushinbr/pam-native-sync Idempotent outbox, ordered batches, cursors, tombstones, retries, and deterministic conflicts Sync
pushinbr/pam-native-sync-laravel Authenticated Laravel push/pull API with signed cursors, idempotency, conflicts, and retention Laravel Sync
pushinbr/pam-native-feature-flags Typed targeting, deterministic rollouts, overrides, exposure events, and offline snapshots Feature Flags
pushinbr/pam-native-observability Vendor-neutral traces, logs, metrics, crash context, sampling, batching, and exporters Observability
pushinbr/pam-native-devtools Redacted snapshots, performance measures, errors, network recording, and deterministic diagnostics DevTools package
pushinbr/pam-native-testing Strict deterministic native-module fakes, deferred responses, recorded calls, and completion assertions Testing
pushinbr/pam-native-plugin-kit Package scaffolding, manifest validation, and IDL generation for PHP, Kotlin, and Swift Plugin Kit
Capability What it does Complete reference
One project console pam init, contextual Composer, pam dev, pam run android, pam run ios, tests, diagnostics, builds, and releases CLI and project console
Zero-setup doctor Detects and safely repairs PHP, Composer, Android SDK/NDK/licenses, Gradle, runtime artifacts, and project requirements Start here
Hot reload Atomic PHP source reload without frozen UI, stale processes, or duplicate server bindings Hot reload
Editor intelligence Formatting, completion, hover, diagnostics, go-to-definition, and navigation for .pam in LSP editors Editor setup
Runtime DevTools FPS, render/commit cost, native nodes, batches, heap, and device profiling DevTools
Style diagnostics Strict compiler, source maps, compatibility/render-cost reports, token generation, and machine-readable manifests Inspect and explain
Production certification Tests source/protocol, PHP 8.5, Rust, UIKit, Android API 26/36, official packages, clean starters, artifacts, and checksums Platform and verification
Automatic cleanup Preserves declared products/evidence and removes regenerable Gradle, Xcode, SwiftPM, Rust, and host intermediates Build hygiene
Surface Contract Complete reference
Composer-first plugins PHP components plus Android modules/views/resources/AAR/JNI/Maven and Swift packages through one manifest Plugin SDK
Typed cross-platform IDL One bounded schema generates deterministic PHP, Kotlin, and Swift contracts Plugin Kit
Wire protocol Versioned PNT1/PNP1 frames, compatibility negotiation, hard bounds, and fail-closed validation Protocol and limits
Public PHP surface Namespace-by-namespace index of runtime, rendering, state, navigation, capabilities, bridge, and style APIs PHP API index
Android Real Views, API 26–36 contract, generated Gradle host, emulator/device testing, APK and AAB Components
iOS UIKit controls, generated Xcode host, extensions, simulator/device diagnostics, signed IPA iOS runtime and host

PAM accepts familiar CSS spelling and compiles it into versioned PAMS bytecode and typed IR. Unsupported syntax is a build error—not a silent guess.

The compiler emits stable property IDs, scope ownership, cascade winners, query ASTs, granular invalidation dependencies, source maps, compatibility/render-cost data, UI-thread keyframes, and typed PHP/Kotlin/Swift token APIs.

<style scoped>/* default: this component subtree */</style>
<style module>/* stable hashed module scope */</style>
<style global>/* application design system */</style>

@import accepts relative .css files inside the Composer project root. Imports are cycle checked, depth limited, and size capped.

Feature Syntax Contract
Basic Button, *, .card, #checkout Compiled matcher; no runtime parsing
Compound Button.primary[disabled] All terms match one native node
Relationship .screen .title, .toolbar > Button Descendant and direct child
Attributes [role], [type="email"], ~=, ` =, ^=, $=, *=`
Lists .title, .subtitle Independent cascade entries
States :pressed, :focus, :focus-visible, :hover, :disabled, :checked, :selected, :active, :loading, :error, :empty See the exact state contract below
Priority specificity, source order, !important Deterministic per-property winner
Layers @layer components { … } Declared layer order

Inherited text properties are color, font family/size/style/weight, letter spacing, line height, alignment, decoration, and transformation. Geometry never inherits accidentally.

:pressed, :focus, :focus-visible, and :hover lower to a compact native state map. Opacity, scale, translation, background color, text color, and border color are applied by Android Views or UIKit; PHP is not called between pointer/focus frames. :disabled, :checked, :selected, :active, :loading, :error, and :empty are reconciled from typed component properties. :focus-visible follows the native focus system rather than browser keyboard heuristics.

Touch devices may never enter :hover. Android mouse/stylus/TV pointer events and the iOS pointer interaction do. Always keep the unqualified rule usable.

Family Supported
Native/absolute number, px, dp, sp, pt
Relative %, rem, vw, vh, vmin, vmax
Math calc(), min(), max(), clamp(), +, -, *, /
Variables --token, var(--token), fallback values
Environment env(safe-area-inset-top), -right, -bottom, -left

Expressions compile once to a typed tree. Only nodes depending on a changed variable, state, container, viewport, theme, or environment value invalidate.

Application variables can change without recompiling unrelated rules:

use Pam\Native\Style\StyleVariables;
StyleVariables::set('space-card', '24dp');
StyleVariables::set('color-surface', '#10131a');

Only declarations containing the changed var() binding are recompiled. A revision change requests one reconciler render; unchanged declarations keep their compiled representation.

Group Properties and shorthands
Size width, height, min-width, min-height, max-width, max-height, aspect-ratio
Spacing padding, padding-{top,right,bottom,left}, padding-inline, padding-block, the same margin forms, gap, row-gap, column-gap
Flex display: flex, flex, flex-grow, flex-shrink, flex-direction, flex-wrap, align-items, align-self, justify-content
Grid display: grid, grid-template-columns, grid-column: span N, place-items; 1–64 tracks
Position `position: relative
Surface background, background-color, opacity, elevation, box-shadow
Border border, border-{top,right,bottom,left}, per-edge width/color, `border-style: solid
Text color, font family/size/style/weight, letter spacing, line height, align, decoration, transform
Image `object-fit: contain
Transform transform with translateX, translateY, scale, scaleX, scaleY, rotate; direct translation-x and translation-y
Visibility `display: flex
Native colors -pam-native-background-color, -pam-native-text-color, -pam-native-border-color

Grid is native, not nested-view emulation. repeat(N, …) or explicit fr, auto, intrinsic, and minmax() tracks choose the column count; children use grid-column: span N.

@font-face accepts safe packaged asset:// TTF/OTF files, weights 100–900, and normal/italic faces.

All dimensions use native border-box geometry; box-sizing: border-box is accepted as an explicit assertion. content-box, floats, fixed/sticky positioning, subgrid, multiple/inset shadows, gradients, filters, CSS transitions, and browser-generated content are rejected. They are not silently approximated.

.surface {
background: #10131a; /* portable fallback */
-pam-native-background-color: colorSurface;
-pam-native-text-color: labelPrimary;
-pam-native-border-color: colorAccent;
}

On Android each name resolves from the application package’s R.color; night-qualified and theme-aware resources therefore follow the current configuration. On iOS the same name resolves with UIColor(named:in:compatibleWith:), including light/dark and high-contrast Asset Catalog variants. If a named resource is unavailable, keep a portable color declaration as the cross-platform fallback.

@media (width >= 840dp) {}
@media (orientation: landscape) {}
@media (prefers-color-scheme: dark) {}
@media (prefers-reduced-motion: reduce) {}
@media (pointer: coarse) {}
@media (device-type: tv) {}
@media (refresh-rate >= 90) {}
@media (dynamic-range: high) {}
@media (display-mode: standalone) {}
@media (fold-posture: half-opened) {}
@media (input-mode: remote) {}
@media (memory-class >= 256) {}
@media (performance-tier >= 2) {}
@container player (width >= 560dp) {
.controls { grid-template-columns: repeat(6, 1fr); }
}

Legacy min/max-width and min/max-height spelling remains valid. Media queries observe the native window; container queries observe the nearest measured container. Kinds, operators, and features are stable sequential integer enums in the public IR.

@tokens { color.brand: #7c5cff; radius.card: 20px; space.md: 16px; }
@recipe button {
base { padding: 12px 18px; border-radius: var(--radius-card); }
variant tone=primary { background: var(--color-brand); color: white; }
variant tone=quiet { background: transparent; color: var(--color-brand); }
}
<Button recipe="button" variant:tone="primary">Continue</Button>

Generate identical token constants for app PHP and custom native modules:

Terminal window
pam style tokens resources/styles/tokens.css generated/style
# Tokens.php · Tokens.kt · Tokens.swift
@keyframes enter {
from { opacity: 0; transform: translateY(12px) scale(0.98); }
to { opacity: 1; transform: translateY(0) scale(1); }
}

Opacity, translation, scale, and rotation keyframes are compile-time validated and played by Android/iOS compositor APIs. PHP is not consulted between frames. Reduced-motion queries can replace motion declaratively.

PAM utility classes are optional compiler input, not a JavaScript dependency. Utilities, recipes, component CSS, and typed styles lower to the same IR, cascade, property IDs, invalidation graph, and cost diagnostics.

The built-in, versioned utility grammar is deliberately small:

Family Syntax
Layout flex-1, w-full, h-full, items-start, items-center, items-end, items-stretch, items-baseline
Color bg-white, bg-black, text-white, text-black
Spacing/surface p-N, px-N, py-N, m-N, mx-N, my-N, gap-N, rounded-N, elevation-N; N × 4dp
Composition opacity-0 through opacity-100
Grid grid-N, col-N, col-{sm,md,lg,xl}-N, responsive offset-*, order-*, gutter-x-N, gutter-y-N

PAM does not claim the complete Tailwind browser catalog. Unknown utilities are ignored as ordinary component class names; supported utility grammar is visible in pam style manifest and produces the same PAMS IR as an equivalent CSS declaration.

Terminal window
pam style inspect resources/styles/app.css
pam style manifest

inspect reports strict validity, fingerprint, rule/query/keyframe counts, invalidation dependencies, source map, compatibility, and render cost. manifest prints the machine-readable property catalog used by tooling.

Strict mode rejects unknown properties, invalid values/units, unsafe imports, malformed selectors, circular variables, invalid keyframes, and ambiguous grid tracks with an actionable source location.

Cost Examples Behavior
Compose opacity, transform, z-order UI-thread/compositor; ideal for 60/90/120 Hz
Paint colors, border, shadow Redraws without relayout
Layout dimensions, spacing, flex/grid, typography Smallest affected subtree only

Production rendering consumes fingerprinted IR/bytecode; it does not parse CSS strings per frame.

Requirement Contract
PHP 8.5.x default
Android API 26–36, emulator and physical devices
iOS UIKit host, simulator, signed IPA, device diagnostics
Protocol PNT1/PNP1 v1; PAMS Style IR v1
Target Native Views/UIKit, never WebView

The shared surface includes layout, text, images, inputs, pressables, scrolling/recycled lists, grid, modals, bottom sheets, status/safe-area/keyboard behavior, refresh, gestures, animation, media, storage, HTTP, system APIs, accessibility, and generated custom views.

Terminal window
pam format --check resources
pam style inspect resources/styles/app.css
pam doctor
pam test
pam production:certify
pam release

Use the editor setup for completion, hover, diagnostics, formatting, and navigation.