# Aion Chat Implementation Manual

**Aion API/runtime:** 2.6.1  
**Playbook revision:** 021 (fullscreen + third-party theme API)  
**Project:** Aion  
**Purpose:** Source-of-truth implementation context for Chat/AI assistants and developers integrating the externally hosted Infinis Aion temporal interface API.

## Read this manual efficiently

**For developers:** Start with sections 3–6 for setup, 7–10 for presentation and visual branding, 11–16 for modes and publishing, and 34 onward for working complete-page recipes, validation, troubleshooting, and deployment. **For ChatGPT:** attach the full downloaded Markdown manual and copy the integration prompt in section 28. The `?asset=chatcontext` endpoint supplies a smaller machine-readable summary.

**New in Playbook 021:** guidance for the redesigned visual-viewport-safe fullscreen Date/Time/Range experience; all ten color tokens and blue/violet/pink gradient inheritance; Studio color controls, site-wide defaults, per-picker overrides and published-design precedence; accurately sequenced hosted-script integration; and a searchable manual reader directly in **Studio → Integrate → Aion playbook**. Runtime version remains 2.6.1; this is a documentation/Studio update.

## Portable deployment and automatic path discovery

Aion is location-independent. The deployment folder may be renamed, moved to another folder depth, served from another domain, or placed behind a reverse proxy. Do not hard-code a server name or project folder into client integrations.

The running `aionApi.php` derives its public endpoint from the request that reached it, including the current host, protocol, and script path. Its PHP runtime searches its own directory and ancestor directories for Aion assets, logs, docs, and published configuration storage. Studio assets are also served through `aionApi.php`, so the Studio does not depend on a fixed `assets/` URL.

Client rule: use the exact endpoint from the deployed Aion instance or from its capability response. If Aion moves, use the endpoint at its new location; no internal source path needs to be rewritten.

### Download-time endpoint injection

This manual is generated when it is downloaded from Aion. The API replaces the endpoint tokens in this source file with the **exact public endpoint that served the download**. That means the examples below already point at the correct host, protocol, port (when present), and folder depth for that deployment.

Aion is intended to be hosted at **https://aion.infiniscorp.com** in the current production setup. When this manual is downloaded from that deployment, every endpoint example is generated with the live `aionApi.php` location served by `aion.infiniscorp.com`. If the same Aion deployment is later moved or mirrored to another server/path, the downloaded manual automatically uses that server/path instead.

Do not manually replace the generated endpoint with a relative client-site path. External clients must call the Aion host that served the manual.


## 1. What Aion is

Aion is a **hosted public temporal interface API** for selecting dates, times, and date/time ranges. The Aion owner hosts the API on one canonical domain. Client websites do **not** download, copy, fork, or locally recreate Aion. They load the hosted JavaScript endpoint and call the public `window.InfinisAion` controller.

Core integration model:

1. The Aion owner deploys this ICT to a public HTTPS host.
2. A client loads `https://aion.infiniscorp.com/aionApi.php?asset=js`.
3. The hosted script exposes `window.InfinisAion`.
4. The client calls `openDate()`, `openTime()`, `openRange()`, or `openPublished()`.
5. Aion loads its CSS from the same canonical Aion endpoint and renders the selected interface on the client page.
6. Aion activity and runtime errors report back to the canonical Aion host.

There is currently **no API key, token, account, or authentication requirement** to use the public Aion picker API.

## 2. Non-negotiable integration rules for Chat

When implementing Aion, Chat should follow these rules:

- Do not copy Aion's internal JavaScript or CSS into the client project.
- Do not rebuild the picker UI locally.
- Do not replace Aion with the browser's native date picker unless explicitly requested.
- Do not invent an API key or token requirement.
- Use the canonical hosted Aion endpoint supplied by the user/deployment.
- Load Aion once per page with the hosted `?asset=js` URL.
- Call the `InfinisAion` controller only after the hosted script has loaded.
- For `presentation: "inline"`, provide a real existing target element or DOM node through `target`.
- Preserve Aion's public option names exactly as documented in this manual.
- Prefer `theme: "auto"` unless the client explicitly requires light or dark.
- Prefer `presentation: "sheet"` for ordinary mobile-first flows unless another presentation is better for the product experience.
- Treat `fullscreen` as the only presentation intended to occupy the entire visible viewport. In fullscreen, the header and action rail remain visible while the picker workspace scrolls where necessary.
- For color customization, override only the tokens the client wants to change; omitted tokens continue using the selected Aion preset.
- When a published configuration is supplied, prefer `openPublished()` instead of duplicating its complete option object in the client.

## 3. Canonical endpoint

The canonical endpoint is the deployed `aionApi.php` URL, for example:

```text
https://aion.infiniscorp.com/aionApi.php
```

Public resources:

```text
GET  https://aion.infiniscorp.com/aionApi.php                 API capabilities as JSON
GET  https://aion.infiniscorp.com/aionApi.php?asset=js        Hosted JavaScript controller
GET  https://aion.infiniscorp.com/aionApi.php?asset=css       Hosted Aion stylesheet
GET  https://aion.infiniscorp.com/aionApi.php?asset=chatmanual  This Chat implementation manual
GET  https://aion.infiniscorp.com/aionApi.php?asset=chatcontext Machine-readable Chat context JSON
POST https://aion.infiniscorp.com/aionApi.php?action=publish  Publish an immutable Aion configuration
GET  https://aion.infiniscorp.com/aionApi.php?config={id}     Read a published configuration
GET  https://aion.infiniscorp.com/aionApi.php?asset=js&config={id} Load Aion with a published configuration attached
```

## 4. Minimal external integration

Load Aion from the host:

```html
<script src="https://aion.infiniscorp.com/aionApi.php?asset=js" defer></script>
```

Then call Aion after the script has loaded:

```html
<button id="chooseDate" type="button">Choose date</button>
<script>
window.addEventListener('infinisAionReady', function () {
  document.getElementById('chooseDate').addEventListener('click', function () {
    InfinisAion.openDate({
      theme: 'auto',
      presentation: 'sheet',
      onSelect: function (value) {
        // value is YYYY-MM-DD, or an empty string when cleared
      }
    });
  });
});
</script>
```

The script also exposes the controller directly once loaded, so a standard `defer` script placed before a deferred client script is sufficient.

## 5. Controller namespace

Aion exposes:

```javascript
window.InfinisAion
```

Current controller members:

```javascript
InfinisAion.version
InfinisAion.openDate(options)
InfinisAion.openTime(options)
InfinisAion.openRange(options)
InfinisAion.openPublished(extraOptions)
InfinisAion.bind(root)
InfinisAion.close()
InfinisAion.setDefaults(options)
InfinisAion.getDefaults()
InfinisAion.published
InfinisAion.themes
InfinisAion.calendarLayouts
InfinisAion.presentations
InfinisAion.styles
InfinisAion.colorTokens
```

## 6. Shared options

These options are shared by multiple picker modes.

| Option | Type | Purpose |
|---|---|---|
| `title` | string | Main picker heading. |
| `eyebrow` | string | Small Aion heading above the title. |
| `clearLabel` | string | Clear/reset button label where supported. |
| `confirmLabel` | string | Primary confirmation button label. |
| `presentation` | string | `sheet`, `modal`, `fullscreen`, `popover`, or `inline`. |
| `style` | string | `aion`, `glass`, `minimal`, or `soft`. |
| `theme` | string | `auto`, `light`, or `dark`. |
| `colors` | object | Selective color-token overrides. |
| `target` | string or Element | Required for inline presentation; identifies the inline mount host. |
| `onSelect` | function | Receives the selected result. |

For Date, `calendarLayout` controls the calendar design. It does not apply to Time or Range. Aion accepts a `calendarLayout: 'auto'` choice that follows the selected presentation; the initial global default is `compact`, so **explicitly use `auto` or `expanded` if you want an expanded fullscreen calendar**.

Default system values:

```javascript
{
  presentation: 'sheet',
  style: 'aion',
  theme: 'auto',
  calendarLayout: 'compact',
  colors: {}
}
```

## 7. Presentation modes

### `sheet`
Mobile-first bottom sheet. Recommended default for phone-oriented forms and ordinary date/time selection.

### `modal`
Centered dialog. Useful on tablets and desktop or when the surrounding page should remain visually present.

### `fullscreen`
Uses the available visual viewport instead of behaving like an enlarged bottom sheet. The header remains in the upper safe area, the primary actions (or Year/Month/Day step rail) stay above the bottom safe area, and only the middle picker content scrolls when needed. This works for Date, Time, and Range, including small phones and landscape. For a fullscreen date with the larger calendar, pass `calendarLayout: 'auto'` or `calendarLayout: 'expanded'`; the global default calendar layout is `compact`. The `colors.background` token controls the fullscreen canvas.

### `popover`
Compact floating presentation. Use where the surrounding UI provides an obvious anchor/context and there is sufficient room.

### `inline`
Embeds Aion inside a supplied target element. The target must already exist and must have usable dimensions.

Example:

```html
<div id="schedulePicker"></div>
<script>
InfinisAion.openDate({
  presentation: 'inline',
  target: '#schedulePicker'
});
</script>
```

Do not treat inline as an overlay. It is an embedded component and should be given a stable container in the client layout.

## 8. Visual styles

Aion includes four built-in style presets:

- `aion` — signature Aion visual language.
- `glass` — airy translucent treatment.
- `minimal` — quieter reduced visual treatment.
- `soft` — friendly softer surfaces.

Use:

```javascript
style: 'aion'
```

## 9. Theme/environment behavior

Supported values:

```javascript
theme: 'auto'
theme: 'light'
theme: 'dark'
```

`auto` follows the client's current `prefers-color-scheme` environment. `light` and `dark` force the picker theme regardless of the client device setting.

## 10. Selective color system

Aion supports token-level overrides. A client can change only selected colors and leave everything else on the chosen style/theme preset. **The full-screen view uses a fixed header and a safe-area-aware bottom action bar; only the middle picker workspace scrolls.** The same responsive view applies to Date, Time, and Range. All built-in gradient fills are computed from `accentBlue`, `accentViolet`, and `accentPink` at render time, so client palette overrides also recolor selected buttons, badges, and the primary action gradient.

Supported color tokens:

```text
accentBlue
accentViolet
accentPink
background
surface
surfaceStrong
text
muted
line
danger
```

Example:

```javascript
InfinisAion.openDate({
  style: 'aion',
  theme: 'auto',
  colors: {
    accentBlue: '#3f7cff',
    accentPink: '#e761ba',
    surfaceStrong: '#ffffff',
    text: '#11182b'
  }
});
```

Direct JavaScript color options must be valid CSS colors (`CSS.supports('color', value)` where available); **published configurations only retain valid six-digit hex values** such as `#2375ff`. For reliable cross-browser behavior, prefer six-digit hex for every token. Unknown color token keys are ignored.

| Token | Affects |
|---|---|
| `accentBlue` | Blue gradient stop and selected accents. |
| `accentViolet` | Middle gradient stop, intermediate accent. |
| `accentPink` | Pink gradient stop and highlighted accents. |
| `background` | Fullscreen/picker background canvas. |
| `surface` | Supporting cards/surfaces. |
| `surfaceStrong` | Main controls and raised surfaces. |
| `text` | Primary foreground text. |
| `muted` | Secondary/assistive text. |
| `line` | Borders and separators. |
| `danger` | Error/destructive emphasis. |

Contrast is the integrating site's responsibility: test text readability in both light and dark themes after overriding `text`, `muted`, and surfaces.

### Host website branding

Override selected tokens per picker call, or establish site-wide defaults after loading the hosted script:

```javascript
// The third-party website decides its own colors; Aion stays hosted by Infinis.
InfinisAion.setDefaults({
  theme: 'light',
  colors: {
    accentBlue: '#007a75',
    accentViolet: '#16a085',
    accentPink: '#efad52',
    background: '#f4faf8',
    surfaceStrong: '#ffffff',
    text: '#102b2a',
    line: '#d5e9e4'
  }
});
// Calls to openDate/openTime/openRange now inherit the overrides.
```

A single `openDate({colors: {accentPink: '#...' }})` replaces just that color for the current picker. All published configurations use the same color tokens and can still accept per-call overrides with `openPublished({colors: {...}})`. The `background` token controls the full-screen canvas; `surface` and `surfaceStrong` control the applicable card and control surfaces. The hosted API never requires a client to copy its stylesheets.

## 11. Date picker

Call:

```javascript
InfinisAion.openDate(options)
```

Date result:

```text
YYYY-MM-DD
```

Clearing returns an empty string.

Date options:

| Option | Type | Meaning |
|---|---|---|
| `value` | string | Initial `YYYY-MM-DD` value. |
| `minDate` | string | Minimum selectable `YYYY-MM-DD`. |
| `maxDate` | string | Maximum selectable `YYYY-MM-DD`. |
| `minimumAge` | integer | Automatic age restriction. Example: `18` or `21`. Aion calculates the latest eligible birth date for you. |
| `ageReferenceDate` | string | Optional `YYYY-MM-DD` date on which the person must meet `minimumAge`; defaults to today. |
| `disabledDates` | string[] | Exact date keys that cannot be selected. |
| `allowedWeekdays` | number[] | Allowed JS weekday numbers: Sunday `0` through Saturday `6`. Empty means all weekdays. |
| `calendarLayout` | string | `auto`, `compact`, `expanded`, `dropdown`, `monthfirst`, or `yearfirst`. |
| `selectedLabel` | string | Label shown over the selected date. |
| shared options | — | Presentation/style/theme/colors/copy/target/onSelect. |

Example:

```javascript
InfinisAion.openDate({
  minDate: '2026-08-01',
  maxDate: '2026-12-31',
  disabledDates: ['2026-09-07'],
  allowedWeekdays: [1,2,3,4,5],
  calendarLayout: 'compact',
  presentation: 'sheet',
  theme: 'auto',
  onSelect: function (date) {
    const output = document.querySelector('#selectedDate');
    if (output) output.textContent = date || 'Cleared';
  }
});
```

### Automatic minimum-age restrictions

Aion can calculate age eligibility itself. Client sites do **not** need to calculate a birth-date cutoff before calling the API.

```js
InfinisAion.openDate({
  minimumAge: 18,
  calendarLayout: 'yearfirst'
});
```

For a 21+ flow:

```js
InfinisAion.openDate({
  minimumAge: 21,
  calendarLayout: 'yearfirst'
});
```

By default, Aion measures the age against the current date. For an event, reservation, or future eligibility date, provide `ageReferenceDate`:

```js
InfinisAion.openDate({
  minimumAge: 21,
  ageReferenceDate: '2026-12-31',
  calendarLayout: 'yearfirst'
});
```

Aion converts the age rule into an effective maximum birth date. If `maxDate` is also provided, Aion keeps the **earlier / more restrictive** cutoff. In Year First, years outside that effective range are omitted entirely rather than displayed as disabled choices. The same effective range also limits months and days.


### Date calendar layouts

- `compact` — days are primary. The month/year button opens month/year navigation as needed.
- `expanded` — deliberately shows month navigation and the day calendar in a more exposed combined layout, sized responsively.
- `dropdown` — dedicated month and year selectors remain available above the day grid.
- `monthfirst` — begins from month/year selection before day selection; useful for birthdays and distant dates.
- `yearfirst` — a guided three-stage flow: select a year, Aion automatically advances to month, then automatically advances to day. The normal month/year header and Clear/Confirm actions are removed; a persistent Year / Month / Day step rail provides navigation back to completed steps, and choosing the day completes the selection. This is ideal for birthdays, historical dates, and other distant-date workflows.
- `auto` — Aion chooses based on presentation: expanded for fullscreen, dropdown for inline, and compact otherwise. This happens when `calendarLayout: 'auto'` is supplied or established through `setDefaults({calendarLayout: 'auto'})`; `compact` is the factory default.

## 12. Time picker

Call:

```javascript
InfinisAion.openTime(options)
```

Time result uses 24-hour `HH:MM` format, for example `14:30` (2:30 pm).

Time options:

| Option | Type | Meaning |
|---|---|---|
| `value` | string | Initial `HH:MM`. |
| `minuteStep` | number | Minute interval, normally 1–60. |
| `minTime` | string | Earliest `HH:MM`. |
| `maxTime` | string | Latest `HH:MM`. |
| shared options | — | Presentation/style/theme/colors/copy/target/onSelect. |

Example:

```javascript
InfinisAion.openTime({
  value: '14:30',
  minTime: '09:00',
  maxTime: '21:00',
  minuteStep: 15,
  onSelect: function (time) {
    // Example: "14:30"
  }
});
```

## 13. Range picker

Call:

```javascript
InfinisAion.openRange(options)
```

Range result: the start/end strings are local date-time values with **no timezone offset**. They look like ISO strings but must not be assumed UTC. When storing on a server or comparing across timezones, capture the intended timezone in your own application and convert as needed.


```javascript
{
  from: 'YYYY-MM-DDTHH:MM:00',
  to: 'YYYY-MM-DDTHH:MM:00'
}
```

Range options:

| Option | Type | Meaning |
|---|---|---|
| `from` | string | Initial start date/time. |
| `to` | string | Initial end date/time. |
| `min` | string | Earliest allowed range date/time. |
| `minimumHours` | number | Minimum required duration between start and end. |
| `minuteStep` | number | Time minute interval. |
| `disabledDates` | string[] | Exact date keys that cannot be selected. |
| `allowedWeekdays` | number[] | Allowed weekday numbers. |
| shared options | — | Presentation/style/theme/colors/copy/target/onSelect. |

Example:

```javascript
InfinisAion.openRange({
  minimumHours: 4,
  minuteStep: 15,
  presentation: 'sheet',
  onSelect: function (range) {
    // range.from and range.to are local ISO-like strings
  }
});
```

## 14. Enhanced input binding

Aion can attach itself to ordinary inputs.

```html
<input
  id="bookingDate"
  data-infinis-aion="date"
  data-aion-presentation="sheet"
  data-aion-style="aion"
  data-aion-theme="auto"
  data-aion-calendar-layout="compact">

<script>
InfinisAion.bind();
</script>
```

`bind(root)` scans `input[data-infinis-aion]` and `input[data-aion-enhance]` inside the supplied root/document. Inputs are made read-only so the Aion UI owns selection. The selected result is written to `input.value`, followed by bubbling `input` and `change` events. Aion does not call `bind()` automatically: wait until the external script has loaded, then call `bind()`; call `bind(container)` again for inputs inserted later by AJAX. Bound `data-infinis-aion="time"` inputs open the Time picker; other bound inputs open the Date picker. **Range must use `openRange()` directly**. Prefer `type="text" readonly` for a non-native input experience. The input's `min`/`max` attributes become the date/time restrictions only when appropriate.

For an HTML input with `type="time"`, Aion uses the input's native `min` and `max` values as `minTime` and `maxTime`. Other bound inputs use `min` and `max` as date limits.

## 15. Global defaults

Set defaults once:

```javascript
InfinisAion.setDefaults({
  presentation: 'sheet',
  style: 'aion',
  theme: 'auto',
  colors: {
    accentBlue: '#357cff'
  }
});
```

Read them:

```javascript
const current = InfinisAion.getDefaults();
```

Options passed directly to an `open*()` call override defaults for that call.

## 16. Published configurations

Aion Studio can publish an exact configuration. Publishing stores that configuration on the Aion host and returns a new immutable ID plus a hosted JavaScript asset URL. Publishing can be repeated; each result is a separate ID rather than an update to the previous one. A published record contains validated serializable design/restriction options, not callback functions or a client page's DOM `target`. Attach callbacks and inline targets at runtime through `openPublished(extraOptions)`.

Publish request:

```http
POST https://aion.infiniscorp.com/aionApi.php?action=publish
Content-Type: application/json
```

Example payload:

```json
{
  "mode": "date",
  "options": {
    "presentation": "sheet",
    "style": "aion",
    "theme": "auto",
    "calendarLayout": "compact",
    "title": "Choose a date"
  }
}
```

Example response shape:

```json
{
  "ok": true,
  "id": "published-id",
  "configEndpoint": "https://aion.infiniscorp.com/aionApi.php?config=published-id",
  "assetEndpoint": "https://aion.infiniscorp.com/aionApi.php?asset=js&config=published-id"
}
```

Client usage:

```html
<script src="https://aion.infiniscorp.com/aionApi.php?asset=js&config=PUBLISHED_ID" defer></script>
<script>
window.addEventListener('infinisAionReady', function () {
  InfinisAion.openPublished({
    onSelect: function (value) {
      // consume the published picker result
    }
  });
});
</script>
```

`openPublished(extraOptions)` opens the mode saved in the published configuration. `extraOptions` can supply runtime-only behavior such as `onSelect`, a client-specific inline `target`, or selective overrides.

## 17. Published configuration security model

The public publishing system is currently unauthenticated because Aion is a free public API. The server allows a defined set of fields and checks supported values (including strict `#RRGGBB` validation for published colors). Published configurations are stored under `data/published/` and do not contain executable client code. **Important for the operator:** a public, unauthenticated publish endpoint can accept requests from third parties; plan server-side rate limits, abuse protection, storage quotas, and monitoring before broad public production exposure. These are deployment controls, not API keys the client must invent.

Chat should not introduce token validation unless the user explicitly changes the Aion product requirements.

## 18. Events

Aion dispatches these browser events:

### `infinisAionReady`
Dispatched when the hosted Aion controller has loaded and is ready.

```javascript
document.addEventListener('infinisAionReady', function (event) {
  // event.detail contains controller version information when provided by the runtime
});
```

### `infinisAionClosed`
Dispatched when a picker closes through an Aion UI close/select/clear flow. Calling `InfinisAion.close()` removes the currently active picker directly; do not rely on a closed event from that method.

```javascript
document.addEventListener('infinisAionClosed', function (event) {
  // event.detail includes presentation/style/theme for the closed picker
});
```

## 19. Closing Aion

Programmatic close:

```javascript
InfinisAion.close();
```

Aion maintains one active `.infinisAion` picker root at a time. Opening a new picker closes/removes the current Aion picker before rendering the next one.

## 20. External-host behavior

The hosted JS sets its canonical API endpoint from the server that served `aionApi.php`. Runtime CSS, client activity, and client error reports therefore continue to go back to the Aion host even when the script is running on a different domain. Aion also loads Bootstrap Icons from `https://cdn.jsdelivr.net` if the host page does not already include an icon stylesheet. Strict Content Security Policies may need to allow Aion's JS/CSS and fetch origin, and that icon stylesheet/font origin. Do not add new client runtime packages.

The API currently sends permissive public CORS headers and does not use credentialed cookies for the picker API.

## 21. Logging

Aion uses append-only runtime logs:

```text
logs/.activity.log
logs/.error.log
```

Normal API calls, asset delivery, picker opens/closes, inline mounts, published configuration actions, and studio activity append to `.activity.log`.

PHP errors, fatal errors, missing assets, client runtime errors, missing inline targets, and failed publishing actions append to `.error.log`.

A log file is never meant to be replaced during an active deployment session; entries build over time.

## 22. Client error reporting

Hosted Aion JavaScript reports browser errors/unhandled promise rejections to:

```text
POST /aionApi.php?action=clientError
```

Activity is sent to:

```text
POST /aionApi.php?action=activity
```

The client site does not need to call those manually for ordinary usage.

## 23. Mobile, tablet, and desktop guidance

Aion is mobile-first but responsive.

Recommended defaults:

| Context | Suggested presentation | Suggested calendar layout |
|---|---|---|
| Phone form | `sheet` | `compact` |
| Phone dedicated date task | `fullscreen` | `expanded` or `auto` |
| Tablet form | `modal` or `sheet` | `compact` |
| Desktop form | `modal` or `popover` | `compact`/`dropdown` |
| Embedded panel | `inline` | `dropdown` or `auto` |

Do not infer that desktop presentation should drive the phone experience. Mobile UX is the baseline.

## 24. Common implementation mistakes

### Mistake: copying the Aion files into the client project
Wrong. Aion is externally hosted. Load the canonical JS endpoint.

### Mistake: using inline without a stable target
Inline requires a real target element or selector that exists before `open*()` runs.

### Mistake: mounting inline into a zero-height decorative div
Give the inline host a sensible layout area or let its content establish height. Do not collapse the host with `display:none`, `height:0`, or a transition that measures as unusable at mount time.

### Mistake: inventing unsupported enums
Use only the presentations, styles, themes, layouts, and color tokens listed by the current API/controller.

### Mistake: hard-coding the user's current Aion host when they asked for portable code
Ask for or use the deployment's canonical Aion endpoint. In generated examples, expose the endpoint as one obvious constant when portability matters.

### Mistake: treating published configurations as downloaded themes
A published configuration remains hosted by Aion. The client loads `?asset=js&config=...` and calls `openPublished()`.

## 25. Full direct-date integration example

```html
<label for="eventDate">Event date</label>
<input id="eventDate" type="text" readonly>
<button id="eventDateButton" type="button">Choose date</button>

<script src="https://aion.infiniscorp.com/aionApi.php?asset=js" defer></script>
<script defer>
document.addEventListener('infinisAionReady', function () {
  const input = document.getElementById('eventDate');
  document.getElementById('eventDateButton').addEventListener('click', function () {
    InfinisAion.openDate({
      value: input.value,
      presentation: 'sheet',
      style: 'aion',
      theme: 'auto',
      calendarLayout: 'compact',
      minDate: '2026-10-01',
      onSelect: function (value) {
        input.value = value;
        input.dispatchEvent(new Event('change', { bubbles: true }));
      }
    });
  });
});
</script>
```

## 26. Full inline example

```html
<div id="aionInlineSchedule" style="min-height: 420px"></div>

<script src="https://aion.infiniscorp.com/aionApi.php?asset=js" defer></script>
<script defer>
document.addEventListener('infinisAionReady', function () {
  InfinisAion.openDate({
    presentation: 'inline',
    target: '#aionInlineSchedule',
    calendarLayout: 'dropdown',
    style: 'aion',
    theme: 'auto',
    onSelect: function (date) {
      // use selected date
    }
  });
});
</script>
```

## 27. Full published-design example

```html
<script src="https://aion.infiniscorp.com/aionApi.php?asset=js&config=PUBLISHED_ID" defer></script>
<script defer>
document.addEventListener('infinisAionReady', function () {
  InfinisAion.openPublished({
    onSelect: function (value) {
      // Aion uses the published mode and design automatically.
    }
  });
});
</script>
```

## 28. Prompt to give Chat with this manual

Use this prompt when attaching this manual to Chat:

> Use the attached **Aion Chat Implementation Manual** as the source of truth. I am integrating the externally hosted Infinis Aion temporal API into my site. Do not download, copy, or recreate the Aion picker locally. Use my canonical `aionApi.php?asset=js` endpoint and the documented `window.InfinisAion` controller. First identify whether my flow needs Date, Time, or Range; then choose the most appropriate presentation, style, theme, calendar layout, restrictions, and optional color tokens for my UI. Preserve mobile-first behavior. For inline implementations, mount into a real stable target element. If I give you a published Aion configuration endpoint, use `openPublished()` instead of rebuilding the design options. Only use options and enums supported by the manual. Show me the exact external integration code required for my existing page.

## 29. Short prompt when Chat already has the manual in context

> Integrate Aion into this page using the attached manual as the source of truth. Use the hosted external API, do not recreate Aion locally, choose the best mobile-first mode/presentation for this flow, and wire the selection result into the existing UI without page reloads.

## 30. How Chat should decide which Aion mode to use

- Ask for/select **Date** when only one calendar date is needed.
- Ask for/select **Time** when only a time-of-day value is needed.
- Ask for/select **Range** when the user must choose a start and end date/time or minimum duration.
- Do not substitute two separate Date pickers for Range unless the user explicitly wants that UX.

## 31. How Chat should decide presentation

- Prefer **Sheet** for the default mobile experience.
- Prefer **Modal** for tablet/desktop forms and focused confirmations.
- Prefer **Fullscreen** for complex date navigation or a dedicated scheduling step.
- Prefer **Popover** for compact desktop/tablet contexts with sufficient room.
- Prefer **Inline** when the date/time UI is intentionally part of the surrounding layout at all times.

## 32. API introspection

If Chat is operating in an environment where it can request the deployed API, it can read:

```text
GET https://aion.infiniscorp.com/aionApi.php
```

The response lists current version, modes, presentations, styles, themes, color tokens, and supported option names. Use this as the live machine-readable capability source when it differs from an older copy of this manual.

## 33. Source-of-truth hierarchy

When integrating Aion, use this precedence:

1. The user's explicit current request.
2. The live deployed `aionApi.php` capability response.
3. A published configuration attached through `?config=...`.
4. This manual matching the current Aion ICT version.
5. Do not invent missing capabilities from general date-picker libraries.

---

End of main reference. Additional practical chapters follow below.

## 34. Full branded integration — one hosted API, your own color palette

Copy this example into the **client website**. Replace the deployment URL with the actual `?asset=js` URL shown in Aion Studio. The picker files themselves remain on the Aion host.

```html
<label for="appointmentDate">Appointment date</label>
<input id="appointmentDate" type="text" readonly placeholder="Choose a date">
<button id="chooseAppointment" type="button">Choose date</button>

<script src="https://aion.infiniscorp.com/aionApi.php?asset=js" defer></script>
<script>
(function () {
  function configureAion() {
    const aion = window.InfinisAion;
    if (!aion || document.getElementById('chooseAppointment').dataset.ready) return;
    document.getElementById('chooseAppointment').dataset.ready = '1';
    aion.setDefaults({
      presentation: 'fullscreen',
      style: 'soft',
      theme: 'light',
      colors: {
        accentBlue: '#167D9D',
        accentViolet: '#7580C9',
        accentPink: '#E48CAF',
        background: '#F3F9FC',
        surface: '#EDF3F7',
        surfaceStrong: '#FFFFFF',
        text: '#15273C',
        muted: '#64758D',
        line: '#DAE5EE',
        danger: '#C6446D'
      }
    });
    const input = document.getElementById('appointmentDate');
    document.getElementById('chooseAppointment').addEventListener('click', () => {
      aion.openDate({
        value: input.value,
        calendarLayout: 'auto',
        minDate: '2026-10-01',
        onSelect(value) {
          input.value = value;
          input.dispatchEvent(new Event('input', { bubbles: true }));
          input.dispatchEvent(new Event('change', { bubbles: true }));
        }
      });
    });
  }
  document.addEventListener('infinisAionReady', configureAion);
  if (window.InfinisAion) configureAion();
}());
</script>
```

**Precedence:** preset/style + chosen theme → Aion default options from `setDefaults()` → per-call options (including a shallow merge of `colors`). Each picker gets the final resolved palette and gradients without copying CSS. `getDefaults()` lets you inspect the current defaults. A color override changes Aion's component tokens, not the parent site's global CSS variables.

## 35. Branded published configuration — external site overrides

Publishing a design from **Design → Publish** gives a URL such as `https://aion.infiniscorp.com/aionApi.php?asset=js&config=PUBLISHED_ID` which embeds the stored mode and visual configuration. On the consuming site:

```html
<script src="https://aion.infiniscorp.com/aionApi.php?asset=js&config=PUBLISHED_ID" defer></script>
<script>
window.addEventListener('infinisAionReady', function () {
  InfinisAion.openPublished({
    colors: { accentBlue: '#165A83', accentPink: '#D47FA6' },
    onSelect: function (selection) {
      const result = document.getElementById('pickedValue');
      if (result) result.textContent = typeof selection === 'string'
        ? selection : JSON.stringify(selection);
    }
  });
});
</script>
```

`openPublished()` returns `null` if no published configuration was attached to the hosted asset. Check `InfinisAion.published` when diagnosing a missing or invalid published ID. Use a published asset URL for that saved design, not a bare `?config=...` JSON response as a JavaScript script. The attached configuration can still be overridden by runtime `extraOptions`; do not publish a `target` or `onSelect` function, as these belong to the consuming page.

## 36. Responsive fullscreen setup and safe-area behavior

Aion's **fullscreen** presentation places the header at the top, the date/time/range selection workspace in the center, and the confirmation controls at the bottom. It computes viewport height from `visualViewport.height` when available and accounts for device safe areas. The calendar/content area scrolls if the viewport is too short; the entire document does not need to scroll. It supports portrait, landscape, tablets, and desktop widths.

```javascript
InfinisAion.openDate({
  presentation: 'fullscreen',
  calendarLayout: 'auto',  // expanded calendar in fullscreen
  style: 'aion',
  theme: 'auto',
  colors: {
    accentBlue: '#3F7CFF',
    accentViolet: '#8569EE',
    accentPink: '#E761BA',
    background: '#F6F8FF'
  },
  onSelect: function (date) { /* consume YYYY-MM-DD */ }
});
```

For Year First in fullscreen, the bottom bar becomes the **Year / Month / Day** stage rail; picking a day completes the selection directly. Avoid wrapping Aion in another fixed-height overflow container. Only `presentation: 'inline'` uses `target` to mount inside a page element. For standard fullscreen, do **not** set `target`.

## 37. Selecting a time and keeping the format predictable

The Time controller returns a 24-hour `HH:MM` value; e.g. `14:30` (2:30 pm). Aion's user-facing picker displays hour, minute and AM/PM selections, but your form should store the returned 24-hour string. `minuteStep` sets the available minute increments; `minTime` and `maxTime` bound the selection.

```javascript
InfinisAion.openTime({
  presentation: 'modal',
  value: '14:30',
  minTime: '09:00',
  maxTime: '21:00',
  minuteStep: 15,
  onSelect: function (time) {
    const field = document.getElementById('appointmentTime');
    if (field) field.value = time; // '' when Clear is selected
  }
});
```

Aion does not accept timezone names in `openTime()` and does not convert a local time-of-day into UTC. Apply timezone policy in your own booking/application backend as needed. If a custom minute step does not divide 60 evenly, verify the exact resulting options before adopting it.

## 38. Range selection, minimum duration, and storage

Use one `openRange()` flow for a start and end. Unless supplied, `min` is **the current local date/time**, and `minimumHours` defaults to `4`. For historical scheduling, provide an explicit earlier `min`.

```javascript
InfinisAion.openRange({
  presentation: 'fullscreen',
  min: '2026-10-01T00:00:00',
  minimumHours: 2,
  minuteStep: 15,
  disabledDates: ['2026-10-15'],
  allowedWeekdays: [1, 2, 3, 4, 5],
  onSelect: function (range) {
    const fromField = document.getElementById('bookingFrom');
    const toField = document.getElementById('bookingTo');
    if (fromField) fromField.value = range.from;
    if (toField) toField.value = range.to;
  }
});
```

The start is confirmed first, then the end; the result is `{ from, to }`. `minimumHours` affects the earliest allowable end. Returned strings are **local date-times without an offset**, e.g. `2026-10-11T14:30:00` (1430 / 2:30 pm locally); retain the intended timezone separately before server storage. There is no public `max` range option in API 2.6.1, and `calendarLayout` is for Date only.

## 39. Bound input recipes and AJAX-created fields

Input enhancement is opt-in: `bind()` scans existing inputs once and marks each field bound to prevent duplicate handlers. For an AJAX-inserted form, call it again on the new DOM subtree.

```html
<input id="birthday" type="text" data-infinis-aion="date"
       data-aion-calendar-layout="yearfirst"
       data-aion-presentation="fullscreen"
       data-aion-minimum-age="18">
<input id="checkInTime" type="text" data-infinis-aion="time"
       data-aion-presentation="sheet" min="09:00" max="17:00">
<script src="https://aion.infiniscorp.com/aionApi.php?asset=js" defer></script>
<script>
function activateAionInputs() { window.InfinisAion?.bind(document); }
document.addEventListener('infinisAionReady', activateAionInputs);
if (window.InfinisAion) activateAionInputs();
// After your AJAX request inserts additional inputs:
// InfinisAion.bind(document.getElementById('newFormSection'));
</script>
```

For enhanced date inputs, the `min` and `max` attributes apply to calendar dates. For time inputs, they apply to local time-of-day. Bound inputs emit both `input` and `change` on selection. **Do not use `data-infinis-aion="range"`**—the binder currently falls back to a Date picker for that value. For Range, attach a normal button listener and call `openRange()`.

## 40. Studio workflow and which files to give ChatGPT

1. Go to **Preview** to test Date, Time or Range. Change Sheet, Modal, Full, Popover, or Inline and see the actual picker.
2. In **Design → Appearance**, select Light/Dark/Auto, calendar layout (Date only), presentation and visual style.
3. In **Design → Rules**, set available dates/times, disabled dates, allowed weekdays, minimum age and reference date, step or duration requirements.
4. In **Design → Colors**, choose any of the ten tokens. Unmodified tokens inherit the Aion theme; reset clears local color overrides.
5. Use **Design → Publish** for an immutable hosted design. The resulting asset URL can be handed to any website.
6. Open **Integrate → Aion playbook**, read/search sections here or download the Chat manual and context JSON. The ready-to-copy Chat instruction tells an assistant how to integrate Aion without recreating the picker.
7. Give ChatGPT **(a)** the manual Markdown, **(b)** your client's existing HTML/PHP file if it should modify an existing page, and **(c)** the published asset URL or canonical `?asset=js` URL. The context JSON is useful when the model needs compact machine-readable facts.

The manual and context downloads automatically reflect the endpoint of the Aion host serving them; they are not client-site source files.

## 41. API endpoint reference and example requests

| Endpoint | Method | Returns |
|---|---|---|
| `https://aion.infiniscorp.com/aionApi.php` | `GET` | Current capabilities and option names. |
| `https://aion.infiniscorp.com/aionApi.php?asset=js` | `GET` | Hosted controller and CSS initialization. |
| `https://aion.infiniscorp.com/aionApi.php?asset=css` | `GET` | Hosted CSS (loaded automatically by JS). |
| `https://aion.infiniscorp.com/aionApi.php?asset=chatmanual` | `GET` | Full deployment-aware Markdown playbook. |
| `https://aion.infiniscorp.com/aionApi.php?asset=chatcontext` | `GET` | Machine-readable guide JSON. |
| `https://aion.infiniscorp.com/aionApi.php?action=publish` | `POST` | Publish configuration as JSON. |
| `https://aion.infiniscorp.com/aionApi.php?config=PUBLISHED_ID` | `GET` | Published record in JSON, if found. |
| `https://aion.infiniscorp.com/aionApi.php?asset=js&config=PUBLISHED_ID` | `GET` | Hosted JS with saved configuration injected. |
| `https://aion.infiniscorp.com/aionApi.php?action=activity` | `POST` | Browser activity telemetry (runtime handles this). |
| `https://aion.infiniscorp.com/aionApi.php?action=clientError` | `POST` | Browser error reporting (runtime handles this). |

For publishing, send an `application/json` body of `{ "mode": "date", "options": { ... } }` and check both HTTP status and `ok`. The `configEndpoint` and `assetEndpoint` returned by this API are absolute URLs on that Aion server (not relative to the consuming website). The public API supports CORS and does not rely on client cookies for these operations.

## 42. Returned handles, close behavior, and events

`openDate(options)`, `openTime(options)`, and `openRange(options)` return `{ close, root }`, where `close()` closes that particular picker and `root` is the created DOM section. `openPublished()` returns the same handle when a published configuration is attached, or `null` otherwise. For normal usage, simply consume `onSelect`.

`infinisAionReady` is dispatched on `document` when the hosted controller is defined. If a script might have loaded before you attach a listener, check `window.InfinisAion` as a fallback. `infinisAionClosed` is dispatched by the picker on its own close/clear/selection path with presentation/style/theme in `event.detail`. Direct `InfinisAion.close()` is an emergency close of all active roots and does **not** currently dispatch the same event. For integration lifecycle, rely on `onSelect` for chosen values rather than closing events.

Opening a second picker removes the existing one. Do not attach persistent user-data state or important event listeners directly to elements inside `root`, since the picker DOM is transient.

## 43. Limits, defaults, and known capability boundaries

| Feature | Supported in runtime 2.6.1 | Notes |
|---|---|---|
| Authentication | No public API key | Protect the publish endpoint operationally if needed. |
| Date minimum/maximum | `minDate`, `maxDate` | Strings in `YYYY-MM-DD`. |
| Age validation | `minimumAge`, `ageReferenceDate` | Latest eligible birth date is computed by Aion. |
| Disabled dates | `disabledDates` | Exact date strings. |
| Allowed weekdays | `allowedWeekdays` | Numbers 0–6; empty permits every day. |
| Date calendar layouts | Six options | Only Date; use `auto` explicitly for automatic fullscreen expansion. |
| Time bounds | `minTime`, `maxTime` | Local `HH:MM` strings; current runtime does not accept named zones. |
| Time intervals | `minuteStep` | Normal range 1–60 for Time; test unusual steps for Range. |
| Range start threshold | `min` | Defaults to the current local moment. |
| Range minimum duration | `minimumHours` | Default 4 hours; callback returns local date-time strings. |
| Range upper bound | Not exposed | Do not invent `maxRange`, `max`, or other undocumented keys. |
| Clear result | Date/Time empty string | Range has a two-step start/end confirmation flow, no Clear button. |
| Bind inputs | Date and Time | Range requires a direct controller call. |
| Palette controls | Ten color tokens | JS accepts valid CSS colors, publishing stores only `#RRGGBB`. |
| Fullscreen | Fixed header/action rail | Middle workspace scrolls on compact viewports. |
| Published design | Saved server-side JSON + hosted JS | Functions/DOM nodes must be added at runtime. |

## 44. Troubleshooting and verification

| Symptom | Check |
|---|---|
| `InfinisAion` is undefined | Confirm the `?asset=js` response, hostname, HTTPS, and script load order. |
| Aion styles/icons look missing | Check `?asset=css`, network/CSP; icon font may come from `cdn.jsdelivr.net`. |
| The wrong picker opens | Use the correct `openDate`, `openTime`, `openRange`, or a correctly published mode. |
| Fullscreen calendar looks compact | Pass `calendarLayout: 'auto'` or `expanded` for Date. Default is compact. |
| Fullscreen actions inaccessible | Ensure the latest Aion CSS/JS are served together; check browser viewport zoom and any host CSS conflicts. |
| Your website's colors are not used | Set `colors` on the call or `setDefaults`; global CSS variables on the parent website do not automatically override Aion's scoped theme tokens. |
| Published colors do not save | Publish strict six-digit `#RRGGBB` values for supported tokens. |
| `openPublished()` does nothing | Load a `?asset=js&config=ID` asset and check `InfinisAion.published`. |
| Inline view not showing | Provide a real visible `target` with useful dimensions before calling the picker. |
| Date cannot be selected | Review min/max, age cutoff, disabled dates and allowed weekdays for conflicts. |
| Time cannot be confirmed | Review 24-hour min/max and minute interval. |
| End of range is unavailable | `minimumHours` may push the earliest end later than selected time. |
| Picker event not seen | Subscribe on `document`, and use the ready-state fallback for late listeners. |
| Existing input not opening | Call `bind()` after the Aion script loads; for AJAX-inserted fields call `bind(root)` again. |
| Manual examples show wrong domain | Download the manual from the deployment actually serving Aion; its server injects that endpoint. |

To verify a newly deployed package, inspect `GET https://aion.infiniscorp.com/aionApi.php`, open the Studio, test all three modes in fullscreen and sheet, override 2–3 colors, read/download the Playbook, publish a test configuration, then open its hosted asset URL from a client page. Server logging is available in `logs/.activity.log` and `logs/.error.log`; client errors should not require browser `console.log` statements.

## 45. ChatGPT integration prompt — current complete instruction

> Use the attached Aion Chat Implementation Manual (Playbook 021) and, when possible, the live Aion capability endpoint as source of truth. Integrate the externally hosted Infinis Aion API into my existing page; do not copy Aion source or replace it with an improvised date picker. First decide whether the task is Date, Time, or Range. Load the actual `?asset=js` asset once, wait for `infinisAionReady` (or check `window.InfinisAion`), then call the correct `open*` method or `openPublished()` for an attached saved configuration. Use the right presentation, including safe-area-aware fullscreen where needed; explicitly choose `calendarLayout: 'auto'` when fullscreen Date should expand. Match my site's branding with all ten supported color tokens, using `setDefaults({colors: ...})` for global branding and per-call `colors` overrides when necessary. Preserve date/time validation rules and callback formats, update my site's input and state through events/AJAX without refreshing, and do not invent missing methods/options, authentication, dependencies, or unsupported Range input binding. Give me the precise working integration code for my existing file.

---

**End of Aion Chat Implementation Manual · Playbook revision 021 · API runtime 2.6.1.**
