# Focused consultation completion and portal presentation correction > **Historical configuration superseded on 2026-10-30:** The default-live [Form A revision](phase-9-form-a-default-live-2026-10-30.md) replaces the former form approval/environment gates with optional live/off/mock mode on 16 placements. Earlier commands and results below describe their recorded checkpoint, not current startup requirements. No historical test result has been rerun or relabeled here. Date: 2026-10-30 UTC. Starting branch `faithful-astro-migration`, starting HEAD `e97f0ea9b475715a1ea58110a27cdf50a2b3cb19`. Tracked tree and index were clean; no untracked paths were reported at preflight. The checkpoint is the commit containing this report; no push, deployment, Jotform mutation or real submission is part of this correction. ## Completion contract and implementation [Jotform Support](https://www.jotform.com/answers/30198031-detect-succesfull-submission) and its linked screenshot were inspected. The screenshot shows an object containing `action: 'submission-completed'` and string `formID` emitted by the thank-you document. It is provider documentation, not a captured submission from AIA Form A. The earlier automated support response on the same thread does not describe this contract; the later human support reply does. The receiver is installed only for authorized consultation drawers. It requires: - Open, non-closing drawer with an activated consultation iframe. - `event.source` equal to that iframe's actual `contentWindow`. - Exact origin equal to the trusted server-rendered URL's origin: `https://form.jotform.com`. No suffix, substring or wildcard match. - Exact action and string Form A ID `262946078314059` matching that fixed URL. - No prior completion for this frame instance. Object envelopes and JSON strings of at most 4096 characters are supported. Malformed, numeric-ID, unrelated and untrusted envelopes are rejected. Extra fields are neither collected nor logged. The receiver uses the existing gated URL instead of embedding a production ID/origin in a shared off-mode bundle. No cross-origin DOM inspection, message forwarding, tracking or submission handler was introduced. The official resize helper remains absent. This trusted-window UI signal is not an independent server-side receipt audit. On acceptance, the current global key `aia:service-inquiry:auto-suppressed-until` immediately receives a 30-day expiry. The drawer reveals “Thank you! Your message has been received.” or “¡Gracias! Hemos recibido su mensaje.” above the iframe and scrolls it into view. The existing thank-you document remains untouched. The full 5000ms interval precedes the existing 500ms slide-out; reduced motion removes only the animation. Focus then returns through the existing close mechanism. Duplicates do not extend the timer or expiry. Manual close cancels the countdown and retains suppression; navigation removes listeners/timers. Completed state survives lifecycle reinitialization. A subsequent deliberate CTA replaces the completed frame with a fresh node, clears only its fallback/load state, and activates the same fixed URL. Old WindowProxy messages then fail source checks. Incomplete frames remain intact across ordinary close/reopen. Load, validation, clicks and timeout never count as completion. The four-second/half-scroll opening rules, manual override, shared suppression, bilingual text, no-JS fallback, sandbox, no-referrer and seven-production versus nine-consultation-test route boundaries are unchanged. ## Portal presentation and evidence limits Both streams use the same scoped presentation: blue section/subsection headings, vertical spacing, list indentation, directories, orange action buttons and visible focus. Only a narrow compatibility vocabulary maps to a local button class: `hs-button`, `content-button`, `portal-resource-button`, or an exact inline AIA orange background (`#ffbd59`/`#ff914d`). Styles themselves are never copied. Contact destinations receive a dark-orange `#a94600` underline treatment for readable contrast against white; buttons retain AIA orange/blue tokens. Table `scope` and numeric spans 1–99 preserve directory semantics. Arbitrary classes, inline style/event handlers, scripts, forms, remote styles, iframes/media and unsafe URLs remain removed. Crypto, access-code handling, ciphertext, resource mapping and publication gates are unchanged. The legitimate private footer was checked only for unencrypted stylesheet/class semantics; none were available. No real code was supplied and no actual stream was decrypted. Button tokens are narrow compatibility candidates, not verified real-view class inventory. Synthetic staff and management encrypted fixtures exercise both class-based and exact brand-fill mappings. Source-faithful restoration in the actual two views needs owner comparison; do not claim pixel parity or expose decrypted HTML to obtain that evidence. No employee resources, credentials, original HTML or real ciphertext were put in Git, screenshots or public static assets. ## Spanish dropdown diagnosis The owner observed five English service options and seven Spanish options, including `Pregunta general` and `Programar una visita guiada`. Generated URLs: | Locale | Exact consultation URL | |---|---| | EN | `https://form.jotform.com/262946078314059?formContext=consultation&language=en` | | ES | `https://form.jotform.com/262946078314059?formContext=consultation&language=es` | The three standalone and six drawer mappings use the same fixed form/context; only the locale differs. The parent does not create an extra intent question, preselect services, alter iframe fields or forward page queries. In test mode legacy drawer controls are absent from the active collection surface. Likely boundary: Jotform multilingual option translations or Update Options / show-hide conditions retaining inquiry choices in Spanish. This is an inference from source and owner observations, not a Builder audit. Owner should open the direct hosted ES consultation URL and compare with EN and the embedded form. If the direct ES version also shows seven choices, review translations of the correct service question and every condition that changes its options. Preserve contact/landing behavior and verify exactly five consultation choices in both languages. No Jotform configuration or client-side workaround was attempted. ## Verification - Focused unit/isolation/artifact suites: 31 passing tests (including two new tests for completion-envelope validation and narrow portal presentation). - Existing service/portal guarded browser suite: 47 grouped checks, 34 captures, all six service routes at 320/390/768/1440px plus completion lifecycle checks in EN/ES and both synthetic portal views. Evidence: `/tmp/aia-service-portal-eqwVDU/evidence.json`. - Browser environment: repository Nix browser shell, Playwright 1.61.1, Chromium `149.0.7827.55` (actual executable version, not the earlier report's Chromium 151 baseline). No new npm dependency or environment configuration. - Focused correction rerun: 14 overlapping grouped checks, 10 captures, `/tmp/aia-service-portal-CX1fu8/evidence.json`. This rerun adds explicit visible viewport bounds and viewport-only acknowledgment screenshots. CSS-transition time is allowed separately from virtual JavaScript timer time. Both checks passed; overlapping counts are not additional unique route coverage. - Desktop synthetic staff, mobile synthetic management and Spanish completion screenshots were visually inspected. Browser automation is not real screen-reader or fluent-language acceptance. - The full browser run recorded 37 Jotform GET attempts fulfilled by local fixtures; focused rerun recorded six. All non-loopback requests were intercepted before transmission. Zero POST/DELETE, WebSocket, production API, analytics or advertising requests were attempted. Zero external browser requests were sent. Reproduction from the existing browser development shell, after the isolated build, is `node tools/service-portal-browser.mjs --correction-only`; omit that flag to include existing timing/scroll/suppression regressions. Every external request is intercepted, service workers are blocked, and portal ciphertext is synthetic response injection. Screenshots remain outside Git. Evidence JSON SHA-256 values: - Full regression: `5ed8661fdec3a289f43aedeb17113586e4935542cf665ab94759d3aac8794d7a`. - Focused correction: `36bc4804e86fe1d59c9547b8a629a45bef8baac10e34799b845fa1e7642e69fd`. Final validation: | Check | Result | |---|---| | `npm run check` (also executed by builds) | 151 files; zero errors, warnings, hints | | `node --experimental-strip-types --test --test-concurrency=1 tools/*.test.mjs` | 202 passed, zero failed/skipped; includes Markdown, publication, SEO, Library, routes, campaign, Phase 8, form preview/isolation/artifact and service/portal suites | | `npm run audit:links` | Zero broken internal links | | `npm run audit:images` | Zero missing mapped page images | | `npm run audit:blog` | Zero content failures | | `git diff --check` | Passed | Documentation link review covered six changed documents. New links resolve. One preexisting migration-summary link targets the archived `route-reconciliation-2026-10-20-offline.json`; it is a historical reference already documented by the handoff archive inventory, not an active dependency. It remains preserved, and no archived report was read or modified. Every mode ran `npm run build` and the matching `node tools/phase10-artifact-verify.mjs --mode=...`: | Build | Routes | Sitemap URLs | Hreflang | Immediate Form A frames | Deferred frames | |---|---:|---:|---:|---:|---:| | Isolated test, all consultation flags approved | 128 | 0 | 0 | 10 | 6 | | Fully approved production artifact (local only) | 127 | 109 | 180 | 7 | 0 | | Indexing, forms off | 127 | 109 | 180 | 0 | 0 | | Mock (staging verifier) | 128 | 0 | 0 | 0 | 0 | | Final restored off staging | 128 | 0 | 0 | 0 | 0 | All artifact checks passed with zero active native form actions. Final staging has `noindex,nofollow` throughout. Production compilation never authorizes deployment. Temporary review `/lp` remains absent from indexing artifacts. Logs and sanitized artifact results are `/tmp/aia-correction-*.log` and `/tmp/aia-correction-*-artifact.json`; no historical reconciliation was overwritten. During development, the artifact verifier correctly rejected an early shared bundle containing the Form A ID. The receiver now derives expected origin/ID from the already authorized iframe URL; subsequent off/mock and gated artifact checks pass without weakening the verifier. Browser full-page captures were supplemented with viewport acknowledgment captures and visible-bounds assertions. For consultation testing, set the existing six required values: ```sh PUBLIC_AIA_FORMS_MODE=isolated-test \ PUBLIC_AIA_FORMS_ENVIRONMENT=isolated-test \ PUBLIC_AIA_FORMS_ISOLATED_TEST_APPROVED=true \ PUBLIC_AIA_FORMS_LIVE_APPROVED=false \ PUBLIC_AIA_FORMS_CONSULTATION_TEST_APPROVED=true \ PUBLIC_ALLOW_INDEXING=false npm run build ``` These settings are command-scoped; no local or deployed environment file changed. ## Changed files Implementation: - `src/utils/jotform-completion.ts` (new strict completion validator). - `src/scripts/service-inquiry.ts` (completion lifecycle and suppression). - `src/components/ServiceInquiryDrawer.astro` (localized acknowledgment). - `src/components/JotformIframe.astro` (controlled completed-frame reset). - `src/utils/portal-presentation.ts` (new narrow presentation mapper). - `src/scripts/employee-portal.ts` (passive presentation/semantic mapping). - `src/components/pages/EmployeePortal.astro` (scoped styles). Tests: `tools/service-portal.test.mjs`, `tools/service-portal-browser.mjs`. Documentation: this report, `reports/SESSION_HANDOFF.md`, `reports/phase-9-form-a-owner-acceptance-2026-10-28.md`, `reports/phase-9-two-form-integration-specification-2026-10-28.md`, `reports/migration-summary.md`, `integrations/employee-portal/README.md`. All paths above are relative to `www/`. ## Owner acceptance and remaining blockers 1. Perform one real synthetic consultation submission manually on the approved isolated preview. Confirm actual `action`, `formID` and sender origin without recording submitted answers; verify five seconds, native confirmation, suppression, focus restoration, and fresh manual reopening. If the provider changes origin/shape, the listener intentionally fails closed. Do not broaden trust based on an unverified message. Check both locales' presentation. 2. Resolve the Spanish dropdown in Builder after comparing the direct hosted form; confirm five choices, requiredness and language-specific validation. 3. Privately unlock both portal views and compare report buttons, directory spacing and focus on desktop/mobile. Supply only sanitized class semantics for any missing style mapping. Real resource access control/cutover remain separate decisions. Seven production-eligible Form A routes remain unchanged. Production consultation routes, portal cutover and site cutover remain unauthorized. No approval gate is closed by fixtures, static artifacts or this checkpoint.