Author SHA1 Message Date
DeCentN2Madness 0ab08131d6 style(portal): remove underline text decoration from links 2026-11-01 14:12:29 -07:00
AIAMarketing b0cf2d7119 docs(portal): staff button and Management Templates layout parity 2026-11-01 14:05:35 -07:00
AIAMarketing 3e05458944 test(portal): staff buttons, management-template grid, isolated management view 2026-11-01 14:05:35 -07:00
AIAMarketing 4d7955fb48 test(portal): pin staff-template styling and safe resource rules 2026-11-01 14:05:35 -07:00
AIAMarketing 81d1f21236 style(portal): two-column management template buttons on desktop 2026-11-01 14:05:35 -07:00
AIAMarketing aa406e623d fix(portal): restore staff resource buttons and tag template list 2026-11-01 14:05:35 -07:00
AIAMarketing 5d6d4af8bd docs(portal): record screenshot-driven styling corrections 2026-10-30 15:40:57 -07:00
AIAMarketing d944cb0afe test(portal): exercise live-style report buttons and orange markers 2026-10-30 15:40:57 -07:00
AIAMarketing 9d6e0b982e test(portal): cover legacy report labels without class inheritance 2026-10-30 15:40:57 -07:00
AIAMarketing 167277b037 style(portal): restore orange list markers in unlocked views 2026-10-30 15:40:57 -07:00
AIAMarketing db8d90f579 fix(portal): classify sanitized report anchors by visible label 2026-10-30 15:40:57 -07:00
AIAMarketing 16a72caa00 fix(portal): recognize legacy lineup report links as resource buttons 2026-10-30 15:40:57 -07:00
DeCentN2Madness 95c5f229f5 refactor(forms): enable approved Form A placements by default 2026-10-30 15:08:02 -07:00
DeCentN2Madness 55adb79705 fix(forms): close completed drawers and restore portal styling 2026-10-30 14:21:27 -07:00
DeCentN2Madness e97f0ea9b4 feat(portal): add service drawers and employee portal preview 2026-10-30 00:03:21 -07:00
DeCentN2Madness ff80ee516f feat(forms): add isolated Form A consultation testing 2026-10-29 10:21:45 -07:00
DeCentN2Madness 6a5e54e130 docs(forms): adopt two-form consultation architecture 2026-10-28 18:51:42 -07:00
DeCentN2Madness ebc99c0f36 chore(reports): archive superseded reconciliation evidence 2026-10-28 18:45:02 -07:00
DeCentN2Madness 0eb3fcc3f6 feat(forms): gate Form A production embedding 2026-10-28 18:29:32 -07:00
DeCentN2Madness 1a56cd7603 feat(forms): add Form A iframe fallback safeguards 2026-10-28 18:29:32 -07:00
DeCentN2Madness 7cdf209032 test(routing): cover nginx slashless serving template 2026-10-28 17:19:56 -07:00
DeCentN2Madness eecb582665 docs(forms): record Form A privacy verification 2026-10-28 17:19:56 -07:00
DeCentN2Madness 61b2bd0f1e feat(forms): add isolated Form A iframe adapter 2026-10-28 17:19:56 -07:00
AIAMarketing a635a5f55c docs(forms): link Form A runtime evidence from P9-03 plan 2026-10-25 13:37:01 -07:00
AIAMarketing 63806f106c docs(forms): record Form A unique-name and locale verification 2026-10-25 13:37:01 -07:00
DeCentN2Madness f41af1966e fix(routing): enforce slashless public URLs 2026-10-25 13:13:46 -07:00
DeCentN2Madness 7a6cab29db feat(forms): add local Form A presentation preview 2026-10-25 13:04:00 -07:00
DeCentN2Madness b102a061fe fix(landing): remove inactive-form availability copy 2026-10-25 12:52:38 -07:00
DeCentN2Madness 356282f61c fix(landing): align early intervention campaign header 2026-10-25 12:38:03 -07:00
DeCentN2Madness ce17728e0b docs(phase10): record technical QA and release readiness 2026-10-21 23:02:35 -07:00
DeCentN2Madness 704c8d27c9 fix(phase10): harden responsive layouts and release validation 2026-10-21 23:02:25 -07:00
DeCentN2Madness d20372fe33 feat(phase9): isolate forms and counters for nonproduction 2026-10-21 23:02:13 -07:00
DeCentN2Madness e874b26bb9 docs(forms): adopt new Jotform form architecture 2026-10-21 20:31:08 -07:00
DeCentN2Madness 08612d97e6 fix(landing): reconcile inactive forms and release copy 2026-10-21 20:31:01 -07:00
DeCentN2Madness f98576f3ae feat(landing): integrate campaign and early intervention pages 2026-10-20 17:50:56 -07:00
DeCentN2Madness 537f9864a0 docs(forms): record P9-03 Jotform integration contract and inventory 2026-10-18 13:30:46 -07:00
DeCentN2Madness 59911eb929 fix(a11y): reconcile responsive layouts and multilingual UI 2026-10-15 12:18:44 -07:00
DeCentN2Madness 8e64d32209 feat(i18n): reconcile multilingual pages and shared forms 2026-10-13 23:01:38 -07:00
DeCentN2Madness b5bc95bc2b feat(library): complete multilingual content parity reconciliation 2026-10-13 14:18:24 -07:00
DeCentN2Madness a699d467f1 feat(i18n): reconcile multilingual navigation and RTL rendering 2026-10-10 20:15:25 -07:00
DeCentN2Madness 8192ea71c4 feat(seo): reconcile URLs and author page-one redirects 2026-10-11 00:43:45 +00:00
DeCentN2Madness 8646792d46 feat(library): add multilingual author archives and linked bylines 2026-10-10 00:17:25 -07:00
AIAMarketing 0957c06a18 docs(migration): add living handoff after Phase 6B.2 2026-10-09 20:15:34 -07:00
DeCentN2Madness 6f5ac3c0d2 feat(library): add static pagination and page-one redirects 2026-10-09 20:00:26 -07:00
DeCentN2Madness b20c253383 feat(library): implement multilingual static search 2026-10-09 19:26:58 -07:00
DeCentN2Madness 76a035424d docs(migration): propose Phase 6A Library architecture 2026-10-09 12:31:25 -07:00
DeCentN2Madness 34d5394b3c fix(content): reconcile published team roster and assets 2026-10-09 10:40:08 -07:00
DeCentN2Madness bc399b43b6 feat(content): reconcile homepages and restore HSA/FSA section 2026-10-08 23:23:23 -07:00
DeCentN2Madness 051fb7c108 fix(content): reconcile service eligibility and consultation pages 2026-10-08 20:43:25 -07:00
DeCentN2Madness 4079156776 feat(seo): add validated article and FAQ structured data 2026-10-08 17:38:06 -07:00
DeCentN2Madness 4ed01d7d28 feat(seo): separate display headings and improve social metadata 2026-10-08 14:50:54 -07:00
AIAMarketing c720917627 docs: link Ads conversion implementation handoff from Astro README 2026-10-08 14:23:47 -07:00
AIAMarketing 2ce8c849c0 docs: record Google Ads consultation conversion configuration and privacy-gated Astro handoff 2026-10-08 14:23:35 -07:00
DeCentN2Madness 32112edbde feat(seo): validate translation relationships and generate hreflang 2026-10-08 13:53:31 -07:00
AIAMarketing f28bf9ad06 docs: record employee portal migration requirements and access decision 2026-10-08 11:30:26 -07:00
DeCentN2Madness 1e1aafa27a docs: preserve migration conversation transcript 2026-10-07 12:59:51 -07:00
DeCentN2Madness cd097d0e76 feat(publication): share policy for manifest routes, canonicals, indexing and sitemap 2026-10-07 12:09:06 -07:00
DeCentN2Madness ea2f1eaa05 fix(markdown): disable directive parsing and add regression coverage 2026-10-06 19:39:41 -07:00
DeCentN2Madness 60c534d4a2 feat(audit): add repeatable migration route reconciliation 2026-10-06 19:15:56 -07:00
DeCentN2Madness 147b55c586 fix(sitemap): include MDX content routes 2026-08-28 04:17:40 +00:00
DeCentN2Madness 6e0ff0c596 feat(markdown): enable Satteri authoring features 2026-08-28 04:17:35 +00:00
DeCentN2Madness 21b0ad7461 fix(giveback): restore source page layout 2026-08-28 03:05:39 +00:00
DeCentN2Madness 6db91105da refactor(insurance): consolidate page content in MDX 2026-08-20 21:17:59 +00:00
DeCentN2Madness cc8e861b33 feat(faq): unify accordion behavior 2026-08-20 21:17:49 +00:00
DeCentN2Madness d127309a13 fix(insurance): unify carrier logo rows 2026-08-19 18:12:18 +00:00
DeCentN2Madness b592524204 fix(insurance): restore source page styling 2026-08-19 17:55:18 +00:00
DeCentN2Madness 5c89f10e9f fix(content): restore client forms source formatting 2026-08-19 08:54:37 -07:00
DeCentN2Madness cfd6e630a3 feat(forms): add service inquiry drawers 2026-08-18 18:49:59 -07:00
DeCentN2Madness ac43ae3669 fix(content): restore social club source formatting 2026-08-18 17:40:23 -07:00
DeCentN2Madness 5554489d70 fix(contact): center map popup logo 2026-08-18 16:56:05 -07:00
DeCentN2Madness ae6ab88e19 build(astro): upgrade site to Astro 7.1
Adopt Astro 7.1.5 and MDX 7.0.5, retain HTML-aware compression for output fidelity, preserve the legacy plain-text contact URL under the new Markdown pipeline, and refresh transitive dependencies to clear npm audit.
2026-07-28 22:00:12 -07:00
DeCentN2Madness a0cbcc7e71 build(astro): migrate site to Astro 6 2026-07-28 20:34:29 -07:00
DeCentN2Madness 679731d3e2 chore: modernize Astro Nix development shell 2026-07-28 20:17:04 -07:00
DeCentN2Madness 96d3c138f6 refactor(migration): remove obsolete mirror extraction tooling
- delete extraction scripts that depended on the removed local mirror
- remove stale extract npm scripts and migration-brief references
- drop the old mirror ignore rule from .gitignore
- update reports and redirect reasons to use live-source wording
2026-07-13 12:49:58 -07:00
DeCentN2Madness 6648d1d7d5 fix(seo): noindex staging builds by default
- add PUBLIC_ALLOW_INDEXING as an explicit production indexing opt-in
- emit robots meta noindex,nofollow unless indexing is enabled
- generate robots.txt from the same indexing flag
- document staging SEO behavior for migration preview hosts
2026-07-13 12:48:14 -07:00
DeCentN2Madness 9c391c8c05 refactor(component): rename contact obfuscation component 2026-07-02 15:14:51 -07:00
DeCentN2Madness 77b83f5d21 feat(page): match live contact page layout 2026-07-02 15:13:52 -07:00
DeCentN2Madness 8c9c581cc0 feat(brand): add and switch to cog favicon 2026-07-02 13:31:04 -07:00
DeCentN2Madness 46090e9159 chore(docs): remove local mirror references, use live site only
Deleted the www.azinstitute4autism.com mirror directory and scrubbed all
references to it from AGENTS.md, MIGRATION_BRIEF.md, www/README.md, and
www/original/README.md. The live public site is now the sole source of
truth with no local mirror fallback.
2026-07-02 13:31:04 -07:00
DeCentN2Madness fd8e12f925 feat(component): add email obfuscation component 2026-07-02 13:31:04 -07:00
DeCentN2Madness b73e92a8a4 chore(img): add higher resolution image to social club page 2026-06-30 20:20:34 -07:00
DeCentN2Madness a3f7f90fdc fix(layout): allow images up to 300x300 in services page contents 2026-06-30 20:14:17 -07:00
DeCentN2Madness a39caf1a34 fix(content): clarify aba therapy section heading 2026-06-30 15:31:53 -07:00
DeCentN2Madness 38c1f78d4f chore(ai): 🔨 move codex command flag to --profile from --profile-2 2026-06-30 15:11:30 -07:00
DeCentN2Madness 5cbe055c34 fix(styles): adjust service page image margin and prose heading spacing
Removes bottom margin from floated service page images (pages.css) and
tightens h2/h3 top margin in prose from 2em to 1.75em (blog.css).
2026-06-25 20:59:40 -07:00
DeCentN2Madness 2f208aa6e4 fix(content): add center prop to MDX page buttons
Adds center to every <Button> in content MDX files that previously relied
on the removed .button-center global class. Also includes minor content
cleanups in the same files: eyebrow markup for section labels in
aba-therapy.mdx, and removal of extra blank lines between list items in
learner-social-club.mdx.
2026-06-25 20:59:11 -07:00
DeCentN2Madness c6202d2ac6 refactor(button): consolidate button styles into Button.astro
Extends Button.astro with a center prop, native <button> element support
(type, disabled, aria-describedby), harmonised padding (.65rem), and
transition. Removes global .button, .button-small, .button-light, and
.button-center rules from components.css, layout.css, and typography.css.
Converts all inline class="button" usages across Header, HomeHero,
HomeFinancialHelp, HomeServicesIntro, FormShell, TeamPage, CareersPage,
and FaqPage to the <Button> component. Updates three scoped style
selectors to :global() to reach the child component's elements.
2026-06-25 20:59:02 -07:00
DeCentN2Madness a3f666c974 refactor(styles): move service-page rules into a dedicated pages stylesheet
- keep blog.css focused on blog/article styling only
- move the existing .service-page rules unchanged into pages.css
- import pages.css from the shared global stylesheet
- preserve the current service-page layout and responsive behavior
2026-06-22 11:08:22 -07:00
DeCentN2Madness 4a7045a1cb refactor(cleanup): remove unused components and stale docs
- delete components that no longer have any references in the current source tree
- remove the stale Link component example from the README
- drop the leftover service-page heading rule from the blog stylesheet
- keep the repo aligned with the current component graph instead of historical leftovers
2026-06-20 12:07:06 -07:00
DeCentN2Madness a048d395f7 refactor(typography): standardize eyebrow labels across page shells
- consolidate the shared eyebrow label styling into the global typography layer
- replace the old script-label usage in page hero, home hero, FAQ, and team shells
- keep the next heading flush under the label across all affected page types
2026-06-20 12:05:24 -07:00
DeCentN2Madness 9398321fac refactor(components): separate page shells from reusable components
Additional info:
  - move page-specific shells into src/components/pages/
  - keep reusable building blocks and home sections in their existing component folders
  - update PageLayout and the home route imports to the new page-shell paths
  - preserve current page behavior while making the component tree easier to navigate
2026-06-19 21:03:27 -07:00
DeCentN2Madness d348174f95 fix(typography): improve global link colour and hover state
Changes the base link rule from a plain blue primary colour to the
site's accent orange (--color-accent-strong) with no underline, matching
the live site's link treatment. Adds a :hover/:active state that shifts
to the lighter accent, and carves out a.button so CTA buttons keep their
primary-colour label text.
2026-06-17 14:22:47 -07:00
DeCentN2Madness d0d8222e40 feat(faqs): wire FaqPage component and reformat faqs.mdx content
PageLayout now imports FaqPage and routes the faqs slug through it,
passing the page content as a slot (accordion and search are handled by
the component). Also passes subtitle="FAQs" to PageHero for the split
title/subtitle hero treatment.

faqs.mdx is cleaned up to match what FaqPage.astro expects as input:
- removes the old Button import and the duplicate h2 headings that are
  now rendered by the component itself
- reformats all answers from loose markdown text to explicit HTML
  elements (p, ul, ol, h4, h5) so the accordion parser receives
  well-formed nodes rather than flat text runs
2026-06-17 14:22:37 -07:00
DeCentN2Madness ed2bda5c02 feat(page-hero): add optional subtitle prop with mobile heading backdrop
Extends PageHero with a subtitle?: string prop rendered as an h2 beneath
the h1. On image-backed heroes the heading group gets a semi-transparent
white backdrop (display: inline-block; background: #fffb) so the text
stays readable against busy photography at mobile widths. Subtitle h2
inherits the page-hero heading font at a slightly smaller fluid size.
2026-06-17 14:21:28 -07:00
DeCentN2Madness 96d829accb fix(faqs): add orange focus ring to search input matching live site
The live site applies border-color #ffbd59 (--color-accent) to the
search input on focus with no additional outline. Adds:

  .hs-search-field__input:focus { border-color: var(--color-accent); outline: none; }

Also applies button-center to the secondary CTA button and removes the
now-redundant text-align/max-width rules from .faq-cta-secondary
(centering is handled by the button-center utility).
2026-06-17 14:17:59 -07:00
DeCentN2Madness 67951fa031 refactor(faqs): replace decorative search icon with live site button-inline form
The original search field used a decorative <div> with an outline SVG
icon floating outside the <form> — a HubSpot pattern that made the icon
non-interactive and the label invisible only by luck.

Replaces it with the structure the live site actually uses:
- hs-search-field__bar--button-inline with a real <button type="button">
  containing the filled FA-style magnifying-glass SVG from the live page
- Flexbox form so the input and button are proper flex siblings rather
  than one element positioned over another
- Rectangular 4px-radius border matching the live widget (was pill 999px)
- Defines .sr-only locally so the label is correctly hidden
- Changes name from "term" to "q" and placeholder to "Search" to match
2026-06-17 14:16:57 -07:00
DeCentN2Madness c98a51795d feat(faqs): add FaqPage component with accordion, search, and CTA sections
Introduces FaqPage.astro, a client-side component that:
- Parses MDX-sourced h3/answer pairs into animated <details> accordions
  (single-open, smooth height transitions)
- Provides a live text filter that hides non-matching questions as the
  user types
- Includes a pill-shaped HubSpot-style search field with decorative icon
- Closes with two CTA bands (primary blue and secondary white)
2026-06-17 14:12:38 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 95d78c22eb refactor(ar): replace Hero with HomeHero on Arabic homepage and delete Hero.astro
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 17:29:23 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 05f5c59721 feat(careers): add structured CareersPage component and wire it into PageLayout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 17:29:16 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 a498dc59d7 feat(styles): remove cream-section alias, add button-center utility, make h3 font-size fluid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 17:29:08 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 4a2087d4e3 refactor(styles): replace cream-section with section-tint in home components and TeamPage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 17:29:02 -07:00
DeCentN2Madness 5e75ace58d feat(team): add tinted band and tagline to ABA Clinic Management section
- move --color-tint background from Employment Opportunities to ABA Clinic Management
- restructure group template so section (not inner container) carries background, allowing it to span full width
- add live site italic tagline "Applied Behavior Analysis '(ABA) at your service'" from source markup
2026-06-16 11:06:32 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 562109f207 feat(team): restyle cards to match live site and add image hover effect
Remove the bordered, aspect-ratio-constrained card style and replace
with a plain flex-wrap grid of 227px cards using the live site's
4px-radius, borderless image treatment and smaller body-font labels.
Wrap each image in a .team-thumb overflow container and add a
scale(1.1)→scale(1.05) zoom-out transition on hover, matching the
Growmeda plugin behavior on the live page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 01:24:21 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 f5c715f5c0 fix(team): restore HR contact email in Employment Opportunities
The live site's second paragraph ends with a contact sentence that was
missing from the Astro component.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 01:23:49 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 496744471a fix(typography): increase script-label size and collapse gap to following h2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 01:23:15 -07:00
DeCentN2Madness 4675809911 feat(library): restore live-site intro copy above post listings
- add the two live intro paragraphs between the hero and article grid
- keep the library listing cards in the live two-column layout
- restore the 4:3 cropped article thumbnails and card spacing via library-scoped selectors
- avoid leaking the card-grid overrides into unrelated pages
- add likes/views from api to library article cards
2026-06-15 17:34:38 -07:00
DeCentN2Madness f64c535971 fix(homepage): move section rendering into the Astro template
- keep homepage section data driven from structured frontmatter
- render typed section components inside the template map instead of frontmatter helper code
- resolve the Astro parse error in HomePage.astro
- preserve the existing homepage section order and component split
2026-06-15 17:34:38 -07:00
DeCentN2Madness 79e9e08464 refactor(styles): move component-specific CSS into Astro components
- relocate header, footer, nav, hero, and page-hero styles into their owning components
- move blog index, blog post, team, video, insurance, CTA, and home-section styles out of the global sheet
- keep  focused on shared primitives such as buttons, cards, links, and list styling
- preserve existing layout and responsive behavior while reducing global CSS scope
2026-06-15 17:34:38 -07:00
DeCentN2Madness 7ef8b3a585 docs(migration): document homepage content model and refresh reports
- document the homepage frontmatter workflow in README.md
- note the new section-oriented homepage structure in migration-summary.md
- update cleanup and link reports to match the current implementation
- keep the repo docs aligned with the content-driven homepage model
2026-06-11 13:17:32 -07:00
DeCentN2Madness 1be3ad0410 refactor(homepage): drive homepage from structured frontmatter
- replace the flat homepage sections array with a named home: block
- validate homepage sections with typed Zod schemas
- make HomePage.astro render the structured content file data
- keep English and Spanish homepage copy easier to scan and edit
2026-06-11 13:16:36 -07:00
DeCentN2Madness 36f82a9a76 feat(layout): add reusable page hero and services page shells
- replace bespoke page and library banners with PageHero.astro
- add ServicesPage.astro for the live-style English services landing page
- restyle shared hero/container measurements for the new layout shell
- add self-hosted services card images
2026-06-11 13:15:05 -07:00
DeCentN2Madness 0db10a04d8 fix(home): equalize process cards after fonts load
- deferred height-equalization script in `HomeProcess.astro` to `document.fonts.ready`
- card heights now measured with correct web fonts in all environments, not just Vite dev server
2026-06-10 01:54:40 -07:00
DeCentN2Madness 3003a68e39 feat(dev): add ai coding tools python3 and fd 2026-06-10 01:27:23 -07:00
DeCentN2Madness 266137ff5f feat(nav): center top header nav menu 2026-06-10 00:18:51 -07:00
DeCentN2Madness cd5a3c6868 fix(services): remove erroneous breadcrumbs 2026-06-10 00:05:41 -07:00
DeCentN2Madness 785c2ccaf7 feat(about): replace prose article with sectioned AboutPage component
- break the /about page out of the generic prose layout into a dedicated AboutPage.astro component
- three separate <section> elements matching the live site's alternating white/cream backgrounds
— Our Story (white), Our Mission (var(--color-tint)), Our Commitment (white)
— format the commitment list with bolded value names and accent left-border styling
2026-06-09 21:14:02 -07:00
DeCentN2Madness 6c4ac504da feat(footer): restyle site footer contact and social sections
- replace plain contact text with icon-backed contact rows
- swap social glyphs for SVG social icons with external links
- tighten footer spacing and hover states to match the live design
2026-06-09 18:23:01 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 26db9e76e1 fix(style): add transition to .button hover state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 17:20:03 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 796bc223af feat(header): replace flat language links with globe-icon dropdown
Rewrites LanguageSwitcher to match the live site: a trigger showing the
active language code and a Bootstrap Icons globe SVG reveals a hover/
focus-within dropdown with full language names (English, Español, عربي).
Fixes hover gap by moving visual spacing into menu padding-top so the
hover zone is continuous from trigger to menu items.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 17:10:20 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 626f1b7f37 refactor(styles): move component-specific CSS into Astro component style blocks
Relocates HomeHero, HomeServicesIntro, HomeBenefits, HomeSkills,
HomeInsurance, HomeEsa, and HomeDirector styles from the global
components.css into each component's own <style> block. Removes the
now-empty 480px media query and trims the 760px media query to only
global rules. Build verified at 97 pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 16:56:41 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 1eeb5a6820 feat(testimonials): replace static quote with 11-item Swiper carousel
Installs swiper, rewrites HomeTestimonials with loop, 6400ms autoplay,
clickable pagination bullets, and prev/next navigation. Extracts all 11
testimonials from the live site into both EN and ES content files. Styles
bullets and arrows with accent colour tokens to match the live site.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 16:32:00 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 5f4fbd5e05 fix(director): align layout and typography with live site
Narrows the photo column to match the live site's ~1:3.6 split,
stacks photo above name as an h3, italicises the quote, and styles
the name line with body font at caption scale.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 15:14:22 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 1bc0224f76 feat(process): equal-height cards with hover scale effect
Equalizes all six process cards to the tallest card's height via a
resize-aware script. Adds scale(1.05) hover transition matching the
live site. Adjusts card padding and icon sizing; shortens two step
labels for better card balance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 14:47:36 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 ce5e53c71f feat(video): add YouTube lightbox to benefits section
Replaces static video link with a self-contained VideoCard component
that opens a native <dialog> lightbox with autoplay on open and
iframe src teardown on close. Includes pulsing ring animation on the
play button and a rounded-triangle SVG icon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 14:16:00 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 615412c880 fix(home): match live site skills grid layout and icon sizing
Changes skills grid from 6 columns to 3 (desktop), 2 (≤760px), and 1
(≤480px). Scales skill icons with vw units so they fill each column
proportionally across breakpoints. Adjusts logo-row spacing to match
live site.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 12:53:44 -07:00
DeCentN2MadnessandClaude Sonnet 4.6 c2b49e66d9 refactor(home): move page content into per-language YAML sections
All visible text, lists, image refs, and CTAs for the home page now live
in en/index.md and es/index.md as a typed `sections:` frontmatter array.
HomePage.astro is reduced to a thin router; each section type is rendered
by a dedicated component in src/components/home/. Adds .no-balance utility
class to suppress text-wrap: balance on the commitments heading.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 12:06:23 -07:00
DeCentN2Madness ef13d4a6e6 fix(style): normalize lists to live site style 2026-06-09 00:43:18 -07:00
DeCentN2Madness 1ec59b0c07 fix: align article byline elements 2026-06-09 00:15:54 -07:00
DeCentN2Madness e1023b5d50 fix(blog): restore source-faithful article emphasis
- synchronize bold and italic formatting across multilingual blog articles
- restore emphasized headings, list labels, links, quotes, and table content
- fix malformed nested emphasis around Markdown links
- match rendered emphasis counts across all 63 indexed live articles
2026-06-09 00:03:41 -07:00
DeCentN2Madness 4bbd58b361 fix(layout): reverse library blog listing and aside order to match live site 2026-06-08 23:34:06 -07:00
DeCentN2Madness 5a66284bb5 fix(design): remove circular frames from images 2026-06-08 23:31:49 -07:00
DeCentN2Madness 0b276e7b32 feat(blog): recreate article footer navigation and related posts
- add reusable live-site-faithful blog footer component
- extract previous, next, and related post data from article content
- remove duplicated footer fragments from multilingual articles
- document the repeatable footer extraction workflow
2026-06-08 20:08:21 -07:00
DeCentN2Madness e51f2133ef fix(content): distinguish prose links from CTA buttons
- add reusable Link and Button MDX components
- convert source-verified page CTAs to explicit buttons
- match live-site prose link styling and CTA destinations
- document link, button, and extraction authoring rules
2026-06-08 19:50:07 -07:00
DeCentN2Madness 4b23bff789 fix(blog): restore live-site tables in migrated articles
- restore semantic table markup across English, Spanish, and Arabic posts
- match live-site table styling and caption formatting
- preserve tables and normalize contained links and assets during extraction
2026-06-08 19:25:00 -07:00
DeCentN2Madness e44b95db2e fix(blog): change blog headings color 2026-06-08 16:41:36 -07:00
DeCentN2Madness bb4cee97a8 fix(blog): restore live blockquote styling and quote-mark SVG
- restores the migrated blog blockquotes to the live site’s visual treatment
- adds the self-hosted quote-mark SVG and matches its live positioning
- updates the extractor, audit scripts, and migration reports to reflect the blockquote work
2026-06-08 16:23:35 -07:00
DeCentN2Madness 826d5e8c7d feat: migrate blog FAQs to reusable MDX accordion
- add Astro MDX support and convert FAQ-bearing posts to MDX
- centralize FAQ markup, scoped styling, behavior, and JSON-LD
- preserve FAQ content and links across English and Spanish posts
- extend blog audits and document the MDX editing workflow
- remove obsolete global FAQ styles
- ignore Front Matter CMS generated state
2026-06-08 15:46:20 -07:00
DeCentN2Madness 9678fc9a3c chore: add .frontmatter to .gitignore 2026-06-08 15:43:18 -07:00
DeCentN2Madness e4e6f15e9a fix: remove duplicated headers from blog post bodies
- remove extracted title, byline, date, avatar, and featured image preambles
- prevent both extraction scripts from recreating duplicated headers
- add blog content duplication auditing
- update migration documentation
2026-06-08 13:26:00 -07:00
DeCentN2Madness bfed3bee15 fix: restore missing live-site page imagery
- recover and self-host HubSpot-injected page hero assets
- map source heroes to page and library layouts
- restore the consultation form background
- add page imagery auditing
- update asset inventory and migration documentation
2026-06-08 13:17:27 -07:00
DeCentN2Madness 96edc6e538 fix: point front matter cms at content directories 2026-06-08 11:24:47 -07:00
DeCentN2Madness 33e78ff8a5 feat: convert site to astro via codex 2026-06-08 11:17:39 -07:00
DeCentN2Madness f3d3562cec chore: enable autonomous MCP tool execution 2026-06-07 10:45:10 -07:00
DeCentN2Madness d8a0016dba docs: require fidelity-first Astro migration 2026-06-07 10:16:35 -07:00
679 changed files with 121180 additions and 144 deletions

No files matched your search

+8 -2
View File
@@ -38,6 +38,7 @@ temp/
# Editor and IDE state
.idea/
.vscode/
.frontmatter/
*.code-workspace
# Local AI-agent state
@@ -47,11 +48,16 @@ temp/
.cursor/
.continue/
.windsurf/
/.playwright-mcp/
# Local visual-comparison captures
/live-*.png
/live-*-snapshot.md
# Operating-system metadata
.DS_Store
Thumbs.db
Desktop.ini
# Read-only wget mirror used as migration source material
/www.azinstitute4autism.com/
# Private portal collection, mappings and ciphertext; never a public asset source.
/www/private/employee-portal/
+73 -22
View File
@@ -1,34 +1,43 @@
# AGENTS.md
## Instruction precedence
This file is the authoritative project policy for all editors and AI agents.
`MIGRATION_BRIEF.md` supplies detailed implementation guidance and must be read
with this file. If the two files appear to conflict, follow `AGENTS.md` and
update the conflicting documentation before continuing.
The `migration-foundation` branch is a reference and recovery point only. It is
not the visual or architectural source of truth. Reuse its nonvisual tooling or
content only after verifying it against the live public site.
## Project
This repository contains a mirrored copy of the Arizona Institute for Autism website.
Raw mirror source:
```txt
./www.azinstitute4autism.com
```
New Astro site target:
```txt
./www
```
The mirror was created with:
The live public website is the single source of truth:
```sh
wget --mirror --page-requisites --adjust-extension --convert-links --no-parent https://www.azinstitute4autism.com
```txt
https://www.azinstitute4autism.com
```
Do not modify, move, rename, or delete `./www.azinstitute4autism.com`.
Treat the mirror as read-only raw source material.
Verify content, design, URLs, metadata, assets, and responsive behavior against
the live public site before treating them as authoritative.
## Primary goal
Create a clean, maintainable Astro + TypeScript site in `./www` that reproduces the current public site as faithfully as practical while replacing HubSpot-generated structure with a future-friendly static site architecture.
Create a clean, maintainable Astro + TypeScript site in `./www` that faithfully
reproduces the current public site's content, visual design, page structure, and
responsive behavior while replacing HubSpot-generated implementation details
with a future-friendly static site architecture.
This is a fidelity-first migration, not a redesign. The live public site is the
source of truth for both content and presentation. Maintainability must improve
the implementation without materially changing what visitors see.
The new site should be suitable for:
@@ -149,13 +158,31 @@ Do not invent large Arabic or Spanish translations unless source content is avai
## Design rules
The new design should be mostly faithful to the current site while becoming more maintainable.
The new site must remain visually faithful to the live public site. Do not
reinterpret, modernize, simplify, or genericize the design unless a specific
change is required for accessibility or reliable responsive behavior.
Preserve each source page's:
- section order and visible content
- typography, font weights, and text hierarchy
- colors, backgrounds, and decorative treatments
- container widths, spacing, alignment, and proportions
- imagery, crops, icons, borders, radii, and shadows
- header, navigation, footer, calls to action, and forms
- desktop and mobile responsive behavior
Reuse exact source assets and locally available fonts wherever practical.
Do not replace distinctive source sections with generic cards, generic heroes,
or a new site-wide layout merely to make component reuse easier.
Use plain CSS with design tokens.
Create reusable Astro components for repeated layout sections.
Do not create a messy page-by-page clone of HubSpot output.
Component boundaries must follow genuinely repeated source patterns. Distinctive
pages and sections may retain page-specific markup and CSS when abstraction
would reduce fidelity. Do not copy HubSpot's generated DOM or CSS wholesale.
Favor:
@@ -163,10 +190,30 @@ Favor:
- reusable components
- organized CSS
- clear data files
- consistent spacing
- source-faithful spacing
- accessible markup
- predictable file structure
### Visual validation
Before implementing a page family or shared component:
1. Inspect the live page and its HTML, CSS, assets, and responsive behavior.
2. Resolve any discrepancy in favor of the live public site.
3. Record the source structure and important visual details.
4. Identify which patterns are truly shared and which are page-specific.
After implementation, compare the Astro output with the live public site at
representative desktop and mobile viewport widths. Check the full page, not
only the header or first viewport. Fix material differences before treating the
page as complete.
Document intentional visual deviations and their reasons in:
```txt
reports/migration-summary.md
```
## URL and SEO rules
Preserve existing public URL paths whenever possible.
@@ -294,9 +341,10 @@ reports/migration-summary.md
Before large filesystem changes:
1. Inspect the mirror.
2. Summarize the implementation plan.
3. Proceed methodically.
1. Inspect the live public site.
2. Inspect the relevant source HTML, CSS, and assets in detail.
3. Summarize the implementation and visual-validation plan.
4. Proceed methodically.
At the end of a task, summarize:
@@ -307,4 +355,7 @@ At the end of a task, summarize:
- audit results
- unresolved issues
Prioritize a clean, maintainable foundation over a pixel-perfect but messy clone.
Prioritize visual fidelity and content correctness while implementing them with
clean, maintainable Astro code. Do not trade away visible source design for a
generic foundation, and do not copy HubSpot-generated implementation merely to
obtain fidelity.
+57
View File
@@ -23,6 +23,7 @@ workspace even when Codex cannot discover its Git metadata.
The profile:
- never pauses for approval
- automatically permits configured Playwright and OpenAI documentation MCP tools
- limits filesystem access to minimal runtime files plus this project
- allows writes in this project
- keeps `.codex` and `www.azinstitute4autism.com` read-only
@@ -42,6 +43,27 @@ The profile is stored outside the workspace at:
Do not add `--sandbox`; legacy sandbox flags override the custom permission
profile. Do not use `--dangerously-bypass-approvals-and-sandbox`.
The launcher also applies these session overrides:
```txt
approval_policy="never"
mcp_servers.playwright.default_tools_approval_mode="approve"
mcp_servers.playwright.tool_timeout_sec=300
mcp_servers.openaiDeveloperDocs.default_tools_approval_mode="approve"
mcp_servers.openaiDeveloperDocs.tool_timeout_sec=300
```
The server-level `approve` settings pre-approve MCP tools without writing
incompatible per-tool approval tables into the profile. These settings allow
MCP tools to run without approval prompts and give
long-running browser operations up to five minutes. An MCP server may still
fail or time out. MCP elicitations that inherently require user input are
rejected rather than shown as unattended prompts.
Do not persist an individual MCP tool approval when prompted by an older or
misconfigured session. Codex CLI 0.133.0 may write a per-tool table that the
profile-v2 parser rejects on the next launch.
## Verification
The nested setup smoke test confirmed that the project is readable and
@@ -60,6 +82,35 @@ sandboxed command-line tools may fail HTTPS certificate verification. Do not
disable certificate verification for package installation or sensitive
retrievals; use live web search or review the retrieval from the host instead.
## Optional local browser environment
The repository now provides a Linux-only `browser` development shell, separate
from the default content-editing shell. In a normal host terminal, from the
repository root:
```sh
nix --extra-experimental-features "nix-command flakes" develop .#browser
```
It supplies a lockfile-matched Playwright driver, Chromium, headless shell and
font configuration. New processes launched inside this shell inherit
`PLAYWRIGHT_MODULE` and `PLAYWRIGHT_BROWSERS_PATH`; existing sessions do not.
For a guarded real-page smoke test, run from `www`:
```sh
TMPDIR=/tmp npm run build
TMPDIR=/tmp node tools/playwright-smoke.mjs
```
Preview and browser run in the same process environment, avoiding dependence on
remote MCP transport or cross-execution loopback access. All non-loopback and
non-GET/HEAD browser requests are blocked. Results/screenshots stay in `/tmp`.
The tool does not grant access to files or sockets denied by the autonomous
profile. If Nix realization, Chromium startup or loopback access is denied, keep
that result as an environment limitation and use the normal host terminal;
do not weaken TLS, identity, signing or sandbox configuration. No global MCP
configuration or launcher permissions were changed for this setup.
## Git limitation
Codex always protects `.git` recursively in its `workspace-write` sandbox.
@@ -79,3 +130,9 @@ Check the startup banner before assigning work. It should report:
approval: never
sandbox: workspace-write ... (network access enabled)
```
Then check the MCP configuration:
```txt
/mcp verbose
```
+28 -14
View File
@@ -36,19 +36,24 @@ For the migration task:
1. Read `AGENTS.md`.
2. Read `MIGRATION_BRIEF.md`.
3. Inspect the local mirror.
4. Provide a concise implementation plan.
5. Scaffold or update the Astro project in `./www`.
6. Build extraction, crawl, audit, sitemap, and redirect tools.
7. Extract content, media, metadata, navigation, and forms.
8. Refactor into reusable Astro components.
9. Configure Astro content collections and Front Matter CMS.
10. Add English, Arabic, and Spanish structure.
11. Add RTL CSS for Arabic.
12. Add SEO, sitemap, robots, redirects, and reports.
13. Run build and audits.
14. Fix practical errors.
15. Document incomplete items in `reports/migration-summary.md`.
3. Inspect the live public site as the single source of truth.
4. Inspect the local mirror as a convenient extraction aid and identify
relevant discrepancies.
5. Inspect the relevant live HTML, CSS, assets, and responsive behavior.
6. Provide a concise implementation and visual-validation plan.
7. Scaffold or update the Astro project in `./www`.
8. Build extraction, crawl, audit, sitemap, and redirect tools.
9. Extract content, media, metadata, navigation, and forms.
10. Refactor genuinely repeated patterns into reusable Astro components.
11. Compare rendered pages with the live site at desktop and mobile widths.
12. Configure Astro content collections and Front Matter CMS.
13. Add English, Arabic, and Spanish structure.
14. Add RTL CSS for Arabic.
15. Add SEO, sitemap, robots, redirects, and reports.
16. Run build and audits.
17. Fix practical errors.
18. Document incomplete items and intentional visual deviations in
`reports/migration-summary.md`.
## Important Claude-specific behavior
@@ -60,6 +65,15 @@ When asked to begin migration, first read the relevant project files, then work
Treat `./www.azinstitute4autism.com` as read-only source material.
Treat the live public site as the single content and visual source of truth.
Use the mirror only as a convenient local extraction and inspection aid. When
the live site and mirror disagree, follow the live site and document material
discrepancies. This migration is not a redesign. Do not substitute a generic
visual system for the live design.
Treat the `migration-foundation` branch as reference-only. Do not use it as the
visual baseline.
Do not delete or overwrite raw source assets.
Do not remove files unless you are certain they are generated output in `./www`.
@@ -105,4 +119,4 @@ When finished, report:
- redirect status
- build status
- audit status
- manual review items
- manual review items
+75 -81
View File
@@ -1,14 +1,21 @@
# MIGRATION_BRIEF.md
## Authority and interpretation
Read and follow `AGENTS.md` first. It is the authoritative project policy; this
brief provides detailed implementation guidance. If any wording here appears
to conflict with `AGENTS.md`, follow `AGENTS.md` and correct this brief before
continuing.
This is a fidelity-first migration, not a redesign. The live public site is the
single content and visual source of truth. The `migration-foundation` branch
may be consulted for nonvisual tooling and recovered content, but it must not
be used as the visual baseline.
## Task
Migrate the public Arizona Institute for Autism website from a mirrored HubSpot-generated static copy into a clean, maintainable Astro + TypeScript site.
Raw mirrored source:
```txt
./www.azinstitute4autism.com
```
Migrate the public Arizona Institute for Autism website into a clean,
maintainable Astro + TypeScript site.
New Astro project target:
@@ -16,23 +23,17 @@ New Astro project target:
./www
```
The raw mirror was created with:
```sh
wget --mirror --page-requisites --adjust-extension --convert-links --no-parent https://www.azinstitute4autism.com
```
There is no HubSpot export, no HubSpot CLI access, and no HubSpot API access.
Use the local mirror as the primary source.
If internet access is available, also crawl the live public website to catch missing URLs or assets:
Use the live public website as the single source of truth:
```txt
https://www.azinstitute4autism.com
```
The live crawl is only for comparison and gap-filling. The local mirror remains the source of truth.
Verify content, design, URLs, metadata, assets, and responsive behavior against
the live site. If the live site is temporarily unavailable, work that depends
on its authority must remain explicitly unverified.
## High-level goal
@@ -49,7 +50,7 @@ Create a new Astro site in `./www` that is:
- SEO-conscious
- accessible
- maintainable
- mostly faithful to the current design
- faithful to the current design, layout, and responsive behavior
- free of unnecessary HubSpot-generated structure
- prepared for future development and publishing
@@ -57,10 +58,6 @@ Create a new Astro site in `./www` that is:
Do not modify or delete:
```txt
./www.azinstitute4autism.com
```
Do not depend on:
- HubSpot CLI
@@ -238,11 +235,20 @@ Do not invent extensive translations.
### Design direction
The new site should be more maintainable while remaining mostly faithful to the current design.
The new site must faithfully reproduce the live public site's visible design,
layout, content hierarchy, and responsive behavior. Do not redesign,
reinterpret, modernize, simplify, or genericize source pages.
Do not create a messy clone of HubSpot output.
Preserve typography, colors, backgrounds, spacing, proportions, imagery,
section order, decorative treatments, navigation, calls to action, forms, and
page-specific distinctions. Reuse exact source assets and fonts wherever
practical.
Refactor repeated sections into reusable components.
Do not copy HubSpot-generated DOM or CSS wholesale.
Refactor genuinely repeated sections into reusable components. Do not force
distinctive source sections into generic components when doing so changes their
appearance or structure.
Use semantic markup.
@@ -250,6 +256,21 @@ Use plain CSS with design tokens.
Do not use Tailwind.
### Fidelity workflow
For each page family or shared component:
1. Inspect the live page, HTML, CSS, assets, and responsive behavior.
2. Resolve discrepancies in favor of the live public site.
3. Record important visual details and identify genuine shared patterns.
4. Implement the page or component in maintainable Astro code.
5. Compare the complete rendered page with the live public site at representative
desktop and mobile viewport widths.
6. Fix material visual differences before marking it complete.
Document intentional visual deviations and their reasons in
`reports/migration-summary.md`.
## Required target structure
Create this project structure in `./www`:
@@ -362,15 +383,11 @@ www/
rtl.css
tools/
extract-site.mjs
crawl-live-site.mjs
audit-links.mjs
generate-redirects.mjs
generate-sitemap.mjs
original/
README.md
reports/
url-inventory.csv
asset-inventory.csv
@@ -383,17 +400,10 @@ www/
migration-summary.md
```
The `original/README.md` file should explain that the raw source mirror lives outside the Astro project at:
```txt
../www.azinstitute4autism.com
```
Do not duplicate the entire raw mirror inside `./www` unless there is a specific reason.
## Initial inspection
Before creating or modifying files, inspect the mirror.
Before creating or modifying files, inspect the live public site and current
project sources.
Look for:
@@ -643,7 +653,9 @@ src/styles/rtl.css
src/styles/global.css
```
Infer the current site’s visual language from the mirrored CSS and HTML.
Extract the current site's visual language from the live public site. Tokens
must encode source values; they must not introduce a replacement visual
system.
Use design tokens such as:
@@ -790,7 +802,7 @@ It should support:
- hreflang links where translation relationships are known
- JSON-LD/schema when extracted
Preserve metadata from the mirror wherever possible.
Preserve metadata from the live site wherever possible.
Generate:
@@ -843,49 +855,27 @@ src/pages/es/[...slug].astro
Implement routing in a clean, maintainable way.
## Extraction scripts
## Migration utility scripts
Create:
```txt
tools/extract-site.mjs
tools/crawl-live-site.mjs
tools/audit-links.mjs
tools/generate-redirects.mjs
tools/generate-sitemap.mjs
```
### `extract-site.mjs`
This script should:
- scan the mirror
- identify HTML files
- infer URL paths
- identify page type
- identify blog posts
- identify listing pages
- extract title/meta/H1/body/main content
- extract canonical and Open Graph metadata
- extract schema/JSON-LD where present
- convert blog posts to Markdown where feasible
- create page Markdown where useful
- copy/normalize assets
- rewrite local asset references
- create initial reports
The script does not need to be perfect, but it should be useful and documented.
### `crawl-live-site.mjs`
This script should:
- attempt to crawl the live site if internet is available
- discover URLs from sitemap and internal links
- compare discovered URLs against the mirror
- compare discovered URLs against the current site source and generated output
- document missing URLs/assets
- avoid aggressive crawling
- respect the scope of `www.azinstitute4autism.com`
- respect the live-site scope
### `audit-links.mjs`
@@ -1096,7 +1086,6 @@ Add scripts similar to:
"dev": "astro dev",
"build": "astro check && astro build",
"preview": "astro preview",
"extract": "node tools/extract-site.mjs",
"crawl": "node tools/crawl-live-site.mjs",
"audit:links": "node tools/audit-links.mjs",
"generate:sitemap": "node tools/generate-sitemap.mjs",
@@ -1118,7 +1107,6 @@ www/README.md
It should explain:
- what the project is
- where the raw mirror lives
- how the migration was performed
- how to install dependencies
- how to run local dev
@@ -1168,6 +1156,8 @@ The migration is successful when:
- `./www` contains a working Astro project
- `npm run build` succeeds or unresolved build issues are clearly documented
- main public pages render locally
- main public pages have been compared with the live site at desktop and mobile
widths and have no undocumented material visual differences
- blog posts are migrated into file-based Markdown where feasible
- Markdown files work with Front Matter CMS
- MDX is available but not overused
@@ -1191,18 +1181,22 @@ Proceed methodically:
1. Read `AGENTS.md`.
2. Read `CLAUDE.md`, if using Claude Code.
3. Read this `MIGRATION_BRIEF.md`.
4. Inspect `./www.azinstitute4autism.com`.
5. Summarize a concise implementation plan.
6. Scaffold Astro in `./www`.
7. Build extraction/reporting scripts.
8. Extract pages, blog posts, assets, metadata, navigation, and forms.
9. Refactor repeated sections into Astro components.
10. Configure content collections and Front Matter CMS.
11. Add multilingual structure.
12. Add SEO, sitemap, robots, and redirects.
13. Add reports.
14. Run build and audits.
15. Fix errors.
16. Summarize what changed and what still needs manual review.
4. Inspect the live public site.
5. Inspect the relevant live public site pages and identify discrepancies.
6. Summarize a concise implementation plan.
7. Scaffold Astro in `./www`.
8. Build extraction/reporting scripts.
9. Extract pages, blog posts, assets, metadata, navigation, and forms.
10. Refactor repeated sections into Astro components.
11. Configure content collections and Front Matter CMS.
12. Add multilingual structure.
13. Add SEO, sitemap, robots, and redirects.
14. Add reports.
15. Run build and audits.
16. Fix errors.
17. Summarize what changed and what still needs manual review.
Prioritize a clean, maintainable foundation over a messy pixel-perfect clone.
Prioritize visual fidelity and content correctness while implementing them with
clean, maintainable Astro code. Do not trade away visible source design for a
generic foundation, and do not copy HubSpot-generated implementation merely to
obtain fidelity.
+6 -1
View File
@@ -9,7 +9,12 @@ if [[ "${1:-}" == "exec" ]]; then
fi
exec codex \
--profile-v2 azi4a2-autonomous \
--profile azi4a2-autonomous \
--strict-config \
--config 'approval_policy="never"' \
--config 'mcp_servers.playwright.default_tools_approval_mode="approve"' \
--config 'mcp_servers.playwright.tool_timeout_sec=300' \
--config 'mcp_servers.openaiDeveloperDocs.default_tools_approval_mode="approve"' \
--config 'mcp_servers.openaiDeveloperDocs.tool_timeout_sec=300' \
--cd "$repo_root" \
"$@"
Generated
+10 -8
View File
@@ -2,16 +2,18 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1728018373,
"narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=",
"rev": "bc947f541ae55e999ffdb4013441347d83b00feb",
"revCount": 688563,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.688563%2Brev-bc947f541ae55e999ffdb4013441347d83b00feb/01925b66-3b70-71bd-b277-924a6c208ba7/source.tar.gz"
"lastModified": 1785090369,
"narHash": "sha256-m0pDuRJG7EDo9ri+4Ksu83VsI+PlxNC9lNBfydejce4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "624af665418d3c65d544145b4d34ad696439570e",
"type": "github"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.%2A.tar.gz"
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
+54 -16
View File
@@ -1,25 +1,63 @@
{
description = "A Nix-flake-based Node.js development environment";
description = "Arizona Institute for Autism Astro development environment";
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }:
outputs =
{ nixpkgs, ... }:
let
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
pkgs = import nixpkgs { inherit system; overlays = [ self.overlays.default ]; };
});
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
];
forAllSystems =
function: nixpkgs.lib.genAttrs supportedSystems (system: function nixpkgs.legacyPackages.${system});
in
{
overlays.default = final: prev: rec {
nodejs = prev.nodejs;
yarn = (prev.yarn.override { inherit nodejs; });
};
devShells = forAllSystems (
pkgs:
let
developmentPackages = with pkgs; [
nodejs_24
git
curl
jq
ripgrep
fd
python3
];
in
{
default = pkgs.mkShell { packages = developmentPackages; };
}
// pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
# Keep driver and browser revisions paired through the existing lockfile.
# Opt-in so ordinary content editing does not require browser downloads.
browser = pkgs.mkShell {
packages = developmentPackages ++ [ pkgs.playwright-driver ];
PLAYWRIGHT_MODULE = "${pkgs.playwright-driver}/index.mjs";
PLAYWRIGHT_BROWSERS_PATH = pkgs.playwright-driver.selectBrowsers {
withFirefox = false;
withWebkit = false;
withFfmpeg = false;
};
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "1";
# Nix supplies browser libraries via patched runtime paths, not apt.
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = "true";
FONTCONFIG_FILE = pkgs.makeFontsConf {
fontDirectories = with pkgs; [
dejavu_fonts
liberation_ttf
noto-fonts
];
};
ASTRO_TELEMETRY_DISABLED = "1";
};
}
);
devShells = forEachSupportedSystem ({ pkgs }: {
default = pkgs.mkShell {
packages = with pkgs; [ node2nix nodejs nodePackages.pnpm yarn ];
};
});
formatter = forAllSystems (pkgs: pkgs.nixfmt);
};
}
+16
View File
@@ -0,0 +1,16 @@
PUBLIC_AIA_API_BASE=https://api.azinstitute4autism.com
PUBLIC_COUNTERS_MODE=off
PUBLIC_COUNTERS_LIVE_APPROVED=false
PUBLIC_COUNTERS_MOCK_RESULT=success
# Optional override only: absent/empty means live on exactly 16 approved routes.
# PUBLIC_AIA_FORMS_MODE=off
# PUBLIC_AIA_FORMS_MODE=mock
PUBLIC_AIA_FORMS_MOCK_RESULT=success
# Explicit, local-only Form A meeting preview; requires PUBLIC_AIA_FORMS_MODE=mock.
PUBLIC_AIA_FORM_A_PREVIEW=false
PUBLIC_ALLOW_INDEXING=false
# Employee portal ciphertext is an opt-in local compatibility preview only.
# Never supply a passphrase through environment variables or build arguments.
AIA_PORTAL_LOCAL_PREVIEW_APPROVED=false
# AIA_PORTAL_CIPHERTEXT_FILE=/owner-controlled/private/ciphertext.json
+8
View File
@@ -0,0 +1,8 @@
node_modules/
dist/
.astro/
.env
.env.*
!.env.example
reports/live-crawl.json
reports/*.png
+648
View File
@@ -0,0 +1,648 @@
# Arizona Institute for Autism Astro Site
Static Astro + TypeScript migration of the public Arizona Institute for Autism
website.
## Quick Start
Run commands from this directory:
```sh
cd www
npm install
npm run dev
```
Astro prints the local development URL, normally:
```txt
http://localhost:4321
```
The development server watches source files and refreshes the browser after
edits. Stop it with `Ctrl+C`.
## Environment Setup
Requirements:
- Node.js 22.12 or newer (see `package.json`); the Nix shell supplies Node.js 24
- npm
This repository also has a Nix development shell at the repository root:
```sh
cd ..
nix --extra-experimental-features "nix-command flakes" develop
cd www
npm install
```
### Local Playwright environment (Linux)
From the repository root, enter the opt-in browser shell:
```sh
nix --extra-experimental-features "nix-command flakes" develop .#browser
cd www
TMPDIR=/tmp npm run build
TMPDIR=/tmp node tools/playwright-smoke.mjs
```
The existing `flake.lock` pairs the Nix Playwright driver and Chromium/headless
shell. `PLAYWRIGHT_MODULE` points directly to that driver; `PLAYWRIGHT_BROWSERS_PATH`
selects its matching browsers. Fontconfig supplies Latin/Arabic fallback fonts.
The ordinary development shell and npm dependencies remain unchanged. This
browser shell is offered on Linux; the existing Darwin development shell is
unchanged. Do not run `npx playwright install` or mix an unrelated npm Playwright
version with these browser revisions.
The smoke test starts Astro preview and Chromium in the **same execution** on an
ephemeral `127.0.0.1` port. It blocks external and non-GET/HEAD requests, loads the
real Spanish privacy and Library pages, verifies staging robots/title/H1, captures
two full-page screenshots in a new `/tmp/aia-playwright-smoke-*` directory, and
closes browser/preview. It does not submit forms or exercise production APIs.
Success establishes browser transport only, not Phase 8 visual or human acceptance.
Use the [Phase 8 guarded browser procedure](reports/phase-8-host-browser-verification-2026-10-14.md)
for full review. Entering the Nix shell does not repair an already-running remote
MCP transport or relax sandbox permissions. If the autonomous environment cannot
access the Nix store, trusted certificates, sockets or browser runtime files, run
the same smoke test from the host terminal. Do not disable TLS verification or
bypass the sandbox. The Nix environment needs host validation before browser
availability can be claimed.
Copy the example environment file when testing the like/view counter or staging
SEO behavior:
```sh
cp .env.example .env
```
The default values are:
```txt
PUBLIC_AIA_API_BASE=https://api.azinstitute4autism.com
PUBLIC_ALLOW_INDEXING=false
```
The site still renders when the AIA API is unavailable. Migration and staging
builds emit `noindex,nofollow` by default. `PUBLIC_ALLOW_INDEXING=true` enables
production publication policy, including per-page noindex exceptions. Exercise
that mode locally with `PUBLIC_ALLOW_INDEXING=true npm run build`; this does
not deploy anything or change environment files. Run `npm run build` afterward
to restore staging output. Only explicitly authorized production deployments
should publish indexing-enabled artifacts.
## View And Build
### Development Server
Use this while editing:
```sh
npm run dev
```
Useful development URLs include:
```txt
/
/aba-therapy
/autism-evaluations
/learner-social-club
/client-consultation
/library
/es
/es/library
/ar/library
```
### Static Build
Generate the static site with staging indexing protection:
```sh
npm run build
```
The autonomous Codex sandbox denies `/etc/hosts`, so its Node runtime cannot
resolve `localhost`. Use this equivalent validation command only inside that
sandbox:
```sh
npm run build:sandbox
```
Build output is written to:
```txt
dist/
```
### Preview Production Output
After a successful build:
```sh
npm run preview
```
Astro prints the preview URL, normally `http://localhost:4321`.
### Validate Before Committing
```sh
npm run build
npm run audit:links
npm run audit:images
npm run audit:blog
```
The link audit reads `dist/` after a successful build. If rendered output is
unavailable, it audits generated source routes, relative and root-relative
Markdown links, and public assets instead. It writes:
```txt
reports/broken-links.md
```
## Editing Content
Normal content editing happens in Markdown:
```txt
src/content/pages/en
src/content/pages/es
src/content/pages/ar
src/content/blog/en
src/content/blog/es
src/content/blog/ar
src/content/authors/en
src/content/authors/es
src/content/authors/ar
```
Page and post frontmatter is validated by `src/content.config.ts`.
Example:
```md
---
title: "Example Article"
description: "Short search and social description."
slug: "example-article"
canonical: "https://www.azinstitute4autism.com/library/example-article"
lang: "en"
translationKey: "example-article"
featuredImage: "/assets/images/example.webp"
alt: "Descriptive image alt text"
date: "2026-06-07"
author: "rula-diab"
category: "Library"
tags:
- ABA Therapy
draft: false
---
Article content goes here.
```
Set `draft: true` while preparing unpublished content.
### Display Headings and Social Metadata
Pages and articles may supply an optional plain-text `displayH1` in frontmatter:
```yaml
title: "The existing SEO title"
displayH1: "The source-supported visible heading"
```
The override changes only the visible H1. It does not change the document or
social title, article cards, navigation labels, or related-post text. Empty,
whitespace-only and non-string overrides fail content validation. Without an
override, articles keep `title`, regular pages keep their existing service/page
heading mappings and title-derived fallback, and homepage/Library components
keep their existing headings. Homepage heading markup stays intact unless a
plain-text override is explicitly supplied. Library template SEO titles remain
unchanged. Front Matter CMS exposes the optional field for pages and blog posts.
Existing featured images and page banner fallbacks supply `og:image` and
`twitter:image`. Relative paths resolve against the public origin in
`src/data/site.json`, never a preview host or an external canonical. Existing
`alt` text supplies both image-alt metadata tags only when it describes the
selected featured image; no descriptions are invented for banner fallbacks.
Pages without a selected image omit image tags and retain the `summary` card;
image pages retain `summary_large_image`.
`og:locale` is omitted: the content languages `en`, `es` and `ar` do not establish
the regional `language_TERRITORY` values required by the
[Open Graph protocol](https://ogp.me/). Regional targeting remains a human
localization decision. HTML language/direction and hreflang are unchanged.
Run `npm run test:seo` for isolated real-Astro builds covering heading defaults,
overrides, schema rejection, image metadata and shared publication invariants
in staging and indexing modes. Fixtures never modify the working content or
the project's `dist/`. See the dated Phase 4A section of
[`reports/migration-summary.md`](reports/migration-summary.md) for source evidence.
### Publication, Canonicals, and Sitemap
`src/utils/publication-policy.ts` owns route eligibility, normalized public
URLs, canonical validation, robots values, and sitemap eligibility.
`src/utils/publication.ts` loads the Astro collections into that manifest.
`src/pages/[...slug].astro` generates every content route from eligible entries,
including home and Library indexes; their existing presentation components are
under `src/components/pages/`. Shared SEO and the generated sitemap use that
same manifest. The route and source-link audits also reuse the policy.
- `draft: true` means unpublished: no generated HTML route in either build mode.
The Arabic homepage `/ar` remains a draft; published Arabic Library routes
remain available. Navigation does not link to the unpublished homepage.
- `noindex: true` keeps a published route accessible, emits `noindex,follow`
in indexing-enabled builds, and excludes it from the sitemap. It defaults
to `false`. Staging always overrides this with `noindex,nofollow`.
- An omitted `canonical` gets the normalized public URL from `site.json` and
its local route. A supplied local canonical must match that route. Invalid
canonicals, duplicate canonical targets, and route collisions fail validation.
- Verified syndicated articles use their existing `canonical` field for the
external publisher URL. External-canonical routes are excluded from the
sitemap even when they are not marked noindex. Do not use canonical values
to create local routes or sitemap locations.
- `src/pages/sitemap.xml.ts` generates `dist/sitemap.xml` on every build.
Staging emits an empty sitemap and does not advertise it in `robots.txt`.
Indexing-enabled builds include only eligible, indexable, self-canonical
local routes. There is no hand-maintained `public/sitemap.xml`.
- `npm run generate:sitemap` is a compatibility command that runs the Astro
build; it no longer writes a separate public sitemap from frontmatter strings.
The verified noindex exceptions are `/schedule-consultation`, `/employee-portal`,
`/library/community-highlight-meet-rula-diab`, and
`/library/new-aia-scottsdale-office`. The last two also retain their verified
external canonicals. The dated evidence is in `reports/migration-summary.md`.
Run `npm run test:publication` for policy tests and isolated builds of the
actual application in staging and indexing-enabled modes. Fixtures test draft
content, draft home/Library indexes, missing and external canonicals, and
generated head/sitemap consistency without modifying the working site's output.
The policy is TypeScript; Node audit/test commands use `--experimental-strip-types`
for compatibility with the declared Node 22.12 minimum. Dependencies are unchanged.
After publication changes, build and run `npm run audit:routes -- --offline`
before `npm run audit:routes -- --check`. This creates a newly dated local
reconciliation using saved production observations, preserving earlier evidence.
Saved rendered metadata is specific to its build mode: after restoring the
normal staging build, reconcile that output again before checking it.
### Links And Buttons
Use normal Markdown links for links within prose:
```md
Read the [ABA therapy guide](/aba-therapy) for more information.
```
Prose links render as the live site's orange inline links. Do not place an
ordinary Markdown link on its own line merely to make it look like a button.
Use `.mdx` and the `Button` component only for a source-verified call to action:
```mdx
import Button from '../../../components/Button.astro';
<Button href="/client-consultation">Request an Appointment</Button>
<Button href="/services" variant="outlined">Explore Services</Button>
<Button href="https://example.com" target="_blank">External Action</Button>
```
Available `Button` variants are `filled` (default), `outlined`, and `light`.
Available sizes are `default` and `small`. A `_blank` target automatically adds
`rel="noopener noreferrer"`.
Normal Markdown links remain preferred for ordinary page and article content.
### Stable Heading Links
Astro automatically generates an ID for each Markdown heading. In `.md` files,
when a section needs a stable, editorially controlled fragment link, add an
explicit ID with Sätteri heading-attribute syntax:
```md
## Accepted Insurance Carriers {#accepted-insurance-heading}
```
Link to it with the resulting fragment URL:
```md
[View accepted carriers](/insurance#accepted-insurance-heading)
```
Keep explicit IDs unique within the page, lowercase, and hyphenated. Treat a
published ID as permanent so inbound links do not break when heading text is
edited. The installed MDX parser rejects this shorthand, independently of
directive parsing. In `.mdx` files, use an explicit HTML heading instead:
```mdx
<h2 id="accepted-insurance-heading">Accepted Insurance Carriers</h2>
```
### Markdown Directives
Sätteri directive parsing is disabled. The content corpus has no intentional
container (`:::name`), leaf (`::name`), or text (`:name`) directives, and no
directive transformation plugins are registered. Enabling parsing silently
removed literal text such as `:1` in `1:1`, `:00` in times, and `:Plan` after
an adjacent colon. Heading attributes remain enabled.
Run `npm run test:markdown` after changing the Markdown/MDX configuration. It
builds temporary fixtures and the affected content through the actual Astro
configuration, checking ratios, punctuation, times, URLs, code, and explicit
heading IDs. It makes no production requests and leaves no fixture routes in
the site. Any future directive feature needs compatible rendering and must
preserve these literal-content checks.
### Front Matter CMS
The project includes `frontmatter.json` for the Front Matter CMS VS Code
extension. Open the `www` folder as the editor workspace so its content folders
and media paths resolve correctly.
### Edit The Homepage
The English and Spanish homepages are driven from the structured `home:`
frontmatter block in:
```txt
src/content/pages/en/index.md
src/content/pages/es/index.md
```
`HomePage.astro` renders those named sections in order. Use the section names
as the editing surface:
```txt
hero
servicesIntro
benefits
skills
insurance
esa
hsaFsa (optional; English only where published)
financialHelp
process
director
testimonials
logos (optional)
```
Keep homepage copy in those named blocks so the page remains easy to scan in
Front Matter CMS and VS Code. `src/content.config.ts` validates the structure.
`hsaFsa` uses `heading`, `body`, `image`, and `imageAlt`; omit the whole block
where no section is published. It renders between ESA and financial help.
`logos.items` holds `file`/`alt` pairs after testimonials. Process steps accept
an optional `href`; use an existing intake route and section ID in the same
language. Steps without a destination remain plain content.
### Edit The Team Page
The English Team page uses the validated `team:` frontmatter block in
`src/content/pages/en/team.md`. That block is the single source for the intro,
ordered clinical groups, ABA care team, member names/roles/images, and careers
content. The Markdown body contains no second roster. Update the structured
frontmatter rather than hardcoding people in `TeamPage.astro`; image filenames
refer to `public/assets/images`.
### Images And Downloads
Store content-referenced assets in:
```txt
public/assets/images
public/assets/downloads
public/assets/media
```
Reference public assets from Markdown using root-relative paths:
```md
![Descriptive alt text](/assets/images/example.webp)
```
Use `src/assets/images` for images imported directly by Astro components and
processed by Astro.
### Components And Styling
Reusable page sections are in:
```txt
src/components
src/layouts
```
Global styles and design tokens are in:
```txt
src/styles/variables.css
src/styles/global.css
src/styles/rtl.css
```
Navigation, services, redirects, and site details are in:
```txt
src/data
```
## Adding Content
### Add An English Blog Post
1. Create `src/content/blog/en/post-slug.md`.
2. Add valid frontmatter and article Markdown.
3. Place referenced images in `public/assets/images`.
4. Run `npm run dev` and view `/library/post-slug`.
5. Run the production validation commands before committing.
### Add A Translation
Use the same nonempty `translationKey` across genuine translated entries in
the **same collection**. The key is an explicit equivalence declaration, not a
URL or an entry reference. Slugs may differ; similar slugs alone never create a
relationship. Do not change keys to manufacture translation pairs.
```txt
src/content/blog/en/post-slug.md
src/content/blog/es/post-slug.md
src/content/blog/ar/post-slug.md
```
The URLs become:
```txt
/library/post-slug
/es/library/post-slug
/ar/library/post-slug
```
Arabic routes automatically render with `lang="ar"` and `dir="rtl"`.
The shared publication manifest supplies both the language switcher and SEO
alternates. A translation set needs at least two eligible members. Drafts,
unpublished placeholders, noindex pages, and external-canonical pages do not
participate. Mark placeholders `draft: true`; `/ar` remains unpublished.
Author records have no generated routes yet and cannot participate.
One member per language per collection/key is allowed, including draft members;
duplicates and blank/whitespace-padded keys fail validation. A lone key is valid
and emits no alternate: it does not assert that a particular missing language
exists. Dangling graph references, wrong-family targets, ineligible targets,
and nonreciprocal links fail validation. The rendered-output regression checks
also fail if an alternate target has no generated HTML file.
Indexing-enabled builds emit the same absolute hreflang links on every member,
including its own language. `x-default` points to the eligible English member
only; sets without one omit it. Staging suppresses hreflang while retaining the
eligible language menu and global `noindex,nofollow`. Unpaired/excluded pages
retain their current-language label without an empty interactive menu.
Run `npm run test:publication`, `npm run build`, and
`PUBLIC_ALLOW_INDEXING=true npm run build` to validate both modes. Finish with
`npm run build` to restore staging. See `reports/migration-summary.md` for
Phase 3B's exact route sets, evidence, and route-audit refresh commands.
Do not publish unreviewed machine translations. Do not invent translations;
substantive translation changes require human language review.
### Edit A Blog FAQ
Posts with live-style FAQ sections use `.mdx` and import:
```mdx
import FAQAccordion from '../../../components/FAQAccordion.astro';
```
Edit the component's `label`, `heading`, and `items` data in the post. Keep
`answer` and `answerHtml` consistent. JSON-LD derives its answer text from the
actual visible `answerHtml` when supplied, otherwise from the rendered `answer`
fallback. Shared FAQ markup, styling, interaction, and schema generation remain
in `src/components/FAQAccordion.astro`, using `src/utils/structured-data.ts`.
The standalone FAQ page passes its rendered Markdown/MDX slot as `sourceHtml`
to the same component. Its server schema describes the direct H3 questions and
following answer nodes that the existing browser code turns into accordions.
Runtime-only sources without server content emit no invented FAQ schema. Do
not mix `items` with `sourceSelector`. Duplicate questions, multiple schema
producing accordions on one page, empty answers and conflicting canonical
props fail validation; consolidate questions into one accordion per page.
### Article and FAQ Structured Data
Article JSON-LD uses the existing SEO `title`, description, featured image,
language, `date`, optional `updatedDate`, and the exact locale/slug match in the
authors collection. Dates use calendar-day precision; article/card bylines
format that day in UTC to avoid shifting it on the build host. Missing
modification dates are omitted. Missing or ambiguous author references fail validation.
No author archive URL or publisher is invented. `displayH1` does not change
the schema headline. No new frontmatter fields are required.
BlogPosting and FAQPage emission reuse the manifest's `sitemapEligible` record
gate: drafts, noindex records and external-canonical records are excluded.
This gate is independent of the build's global indexing switch, so staging
can exercise schema while retaining its global noindex, empty sitemap and
absent hreflang. The existing site organization block remains unchanged.
These schemas describe the rendered local records; they do not certify that
older article dates or FAQ answers have been reconciled with production.
Phase 6C drift observations and validation results are recorded in
`reports/migration-summary.md`. Run `npm run test:seo` and
`npm run test:publication`, and validate both build modes before publication.
## Reports And Utilities
For the current migration checkpoint, next Codex phase, ratified decisions,
and outstanding cutover blockers, begin with the
**[living session handoff](reports/SESSION_HANDOFF.md)**. Update that short
handoff at each accepted milestone transition; detailed historical evidence
remains in `reports/migration-summary.md`.
Migration reports are stored in `reports/`.
Useful commands:
```sh
npm run crawl:live
npm run generate:sitemap
npm run generate:redirects
npm run audit:links
```
The live crawl is optional and may fail in restricted network environments.
## Forms
As of the owner decision on 2026-10-30, `npm run dev` and `npm run build`
use live Jotform Form A on exactly 16 approved placements: 10 immediate frames
and six deferred bilingual service drawers. No Form A flags are required.
Public development-host forms are owner-authorized. This does not authorize cutover.
Use `PUBLIC_AIA_FORMS_MODE=off npm run build` for an offline artifact, or
`PUBLIC_AIA_FORMS_MODE=mock npm run dev` for synthetic fixtures. Missing/empty
mode means live; obsolete `isolated-test` and other invalid values produce an
explicit configuration error. Remove old approval/environment variables from
local settings. Indexing is independent of forms; counters remain off by default.
See the [current Form A guide](integrations/jotform/README.md) for the exact
registry, safeguards, rollback and owner acceptance requirements. Form C remains
inactive. Employee-portal private input retains its own separate gates.
Verify matching output with
`node tools/phase10-artifact-verify.mjs --mode=staging --forms=live`;
use `--mode=indexing` for indexing output and `--forms=off` or `--forms=mock`
for those explicit builds. No actual submissions run in automated tests.
### Google Ads consultation-form conversion handoff
The Google Ads conversion ID, label, and privacy-gated Astro integration
instructions are in
[`reports/google-ads-consultation-conversion.md`](reports/google-ads-consultation-conversion.md).
This is documentation only: **do not install Google tags or conversion snippets**
on health-service pages or turn on enhanced conversions until AIA's
privacy/HIPAA and advertising-policy review explicitly approves the complete
data flow. Any future measurement needs separately approved success and privacy semantics; the former API-success premise is historical and no tracking is active.
## Troubleshooting
### `astro: command not found`
Dependencies are not installed:
```sh
npm install
```
### npm TLS or certificate errors
Do not disable npm certificate verification. Run `npm install` from a normal
host terminal or trusted development environment with working CA certificates.
### Link audit says build output is unavailable
Build first:
```sh
npm run build
npm run audit:links
npm run audit:images
npm run audit:blog
```
### A content page is missing
Check:
- its Markdown file is in the correct language/content folder
- `draft` is `false`
- `slug` is unique within that language and content type
- frontmatter satisfies `src/content.config.ts`
+21
View File
@@ -0,0 +1,21 @@
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import { satteri } from '@astrojs/markdown-satteri';
import site from './src/data/site.json' with { type: 'json' };
export default defineConfig({
site: site.url,
trailingSlash: 'never',
compressHTML: true,
integrations: [mdx()],
markdown: {
processor: satteri({
features: {
headingAttributes: true,
// No directive consumers: parsing them drops literal ratios and times.
directive: false
}
}),
shikiConfig: { theme: 'github-light' }
}
});
+61
View File
@@ -0,0 +1,61 @@
{
"$schema": "https://frontmatter.codes/frontmatter.schema.json",
"frontMatter.framework.id": "astro",
"frontMatter.content.publicFolder": "public",
"frontMatter.content.pageFolders": [
{ "title": "Pages", "path": "[[workspace]]/www/src/content/pages" },
{ "title": "Blog", "path": "[[workspace]]/www/src/content/blog" },
{ "title": "Authors", "path": "[[workspace]]/www/src/content/authors" }
],
"frontMatter.taxonomy.contentTypes": [
{
"name": "page",
"pageBundle": false,
"fields": [
{ "title": "Title", "name": "title", "type": "string", "required": true },
{ "title": "Display H1", "name": "displayH1", "type": "string" },
{ "title": "Description", "name": "description", "type": "string" },
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
{ "title": "Language", "name": "lang", "type": "choice", "choices": ["en", "ar", "es"] },
{ "title": "Canonical", "name": "canonical", "type": "string" },
{ "title": "Featured image", "name": "featuredImage", "type": "image" },
{ "title": "Alt text", "name": "alt", "type": "string" },
{ "title": "Translation key", "name": "translationKey", "type": "string" },
{ "title": "Draft", "name": "draft", "type": "boolean", "default": false }
]
},
{
"name": "blog",
"pageBundle": false,
"fields": [
{ "title": "Title", "name": "title", "type": "string", "required": true },
{ "title": "Display H1", "name": "displayH1", "type": "string" },
{ "title": "Description", "name": "description", "type": "string" },
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
{ "title": "Date", "name": "date", "type": "datetime", "required": true },
{ "title": "Author", "name": "author", "type": "string", "default": "rula-diab" },
{ "title": "Category", "name": "category", "type": "string" },
{ "title": "Tags", "name": "tags", "type": "tags" },
{ "title": "Language", "name": "lang", "type": "choice", "choices": ["en", "ar", "es"] },
{ "title": "Featured image", "name": "featuredImage", "type": "image" },
{ "title": "Alt text", "name": "alt", "type": "string" },
{ "title": "Canonical", "name": "canonical", "type": "string" },
{ "title": "Translation key", "name": "translationKey", "type": "string" },
{ "title": "Draft", "name": "draft", "type": "boolean", "default": false }
]
},
{
"name": "author",
"pageBundle": false,
"fields": [
{ "title": "Name", "name": "name", "type": "string", "required": true },
{ "title": "Display name (published heading/byline)", "name": "displayName", "type": "string" },
{ "title": "Slug", "name": "slug", "type": "string", "required": true },
{ "title": "Description", "name": "description", "type": "string" },
{ "title": "Avatar", "name": "avatar", "type": "image" },
{ "title": "Language", "name": "lang", "type": "choice", "choices": ["en", "ar", "es"] },
{ "title": "Translation key", "name": "translationKey", "type": "string" }
]
}
]
}
+144
View File
@@ -0,0 +1,144 @@
# Employee portal compatibility and private migration
Recorded 2026-10-30. Browser-side shared-code decryption is approved only for
local compatibility development. It is not authentication, individual revocation,
a secure session or a HIPAA compliance determination. Resources need separate
server authorization before cutover.
## Source and private collection
Read-only legacy footer source:
`/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt`.
The original stays outside Git as rollback evidence. No access code was available
to the agent. The exact resource count and real content compatibility remain
unverified. Do not infer the earlier approximate 43 links as a measured count.
From `www`, in the owner's private interactive terminal:
```sh
node tools/employee-portal-migrate.mjs collect \
/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt
```
Enter each legitimate view code at its hidden prompt. Never place codes in
arguments, environment variables, shell history or reports. The utility checks
both streams, keeps plaintext in memory, and collects only referenced `/hubfs/`
resources from the verified source origin. Other origins require explicit
review/code allowlisting; redirects are bounded and never inherit credentials.
No Jotform, Google or other vendor forms are fetched.
Private output is `private/employee-portal/`: directories 0700, manifests and
binary resources 0600. This exact subtree is gitignored and outside Astro's
public directory. Filenames are SHA-256 hashes of source URLs, independently
verified by content hashes. The manifest retains original references, labels,
view membership, MIME, bytes, status and delivery/classification decisions.
All new resources default to UNRESOLVED. Publicly reachable does not mean public
approved. Resuming verifies an existing file's content hash; mismatches are not
overwritten. HTML error documents, executable responses, invalid known signatures,
redirects outside approved destinations and resources over 50 MiB are rejected.
The first pass allows only the verified site origin. If a legitimate `/hubfs/`
response redirects to a HubSpot CDN, inspect that exact HTTPS origin first, then
add its origin to the private manifest's `approvedOrigins` list and rerun. Never
approve a redirect based only on a failed download or a broadly shared vendor
domain. Failures remain private review items. The utility prints counts only.
Before every artifact transfer, verify that only `dist` is copied and that it
contains no private manifest, document or real ciphertext unless that ciphertext
has separately been authorized for the local preview. Never archive the whole
working directory as a deployable artifact.
## Approved rewriting
The owner classifies records as PUBLIC-APPROVED, STAFF-INTERNAL,
MANAGEMENT-INTERNAL or UNRESOLVED in the private manifest. Set `deliveryPath`,
`rewriteApproved`, `destinationImplemented`, `destinationVerified`, and (for
internal documents) `destinationAccessControlled` only with actual evidence.
The utility does not create those destinations or infer their approval.
```sh
node tools/employee-portal-migrate.mjs rewrite \
/home/alice/projects/wrk/aia/local-archives/aia-employee-portal-hubspot-footer-source.txt
```
It reauthenticates both views, changes approved quoted href/src attributes only,
preserves unrelated HTML/labels, and re-encrypts with fresh salts and IVs. It
verifies round-trip decryption and distinct codes before writing new ciphertext
with exclusive filenames. The original source is untouched. CSS/srcset mappings
require separate review and are rejected rather than silently rewritten.
Unresolved links retain their original destination as a recorded dependency,
not a claim of verified destination health. A changed manifest alone never
changes links in the encrypted stream.
## Local preview and content safety
Use a private ciphertext file generated by `collect` or `rewrite`:
```sh
AIA_PORTAL_LOCAL_PREVIEW_APPROVED=true \
AIA_PORTAL_CIPHERTEXT_FILE=/absolute/private/ciphertext-TIMESTAMP.json \
PUBLIC_AIA_FORMS_MODE=off PUBLIC_ALLOW_INDEXING=false \
npm run dev -- --host 127.0.0.1
```
The 2026-10-30 revision removes dependence on the retired Form A environment role. Form mode is independent; `off` above is optional for local testing and cannot grant portal approval. The page defaults to locked/unavailable without its own explicit approval and valid private input. Indexing
builds cannot include it. The codes never go to a server, storage or URL. No
native form submits; Enter and Unlock use local WebCrypto. Only the matching
stream is displayed; refresh or leaving the page locks it again.
The passive DOM renderer preserves headings, lists, text, tables and safe
HTTPS/mailto/tel links, with no referrer on links. It rejects scripts, inline
handlers, styles, media, embedded forms and unknown tags. Real portal markup
has not been decrypted or reviewed; any removed behavior must be reviewed with
the owner before claiming fidelity. It must not silently become arbitrary
script execution. No real encrypted stream or plaintext is in Git.
### Scoped presentation correction, 2026-10-30
The renderer now maps only `hs-button`, `content-button`, or
`portal-resource-button` anchor tokens, or exact inline AIA orange background
colors (`#ffbd59` / `#ff914d`), to the local `portal-resource-button` class.
It does not copy the original style or arbitrary classes. These are narrow
compatibility candidates, not a claim that encrypted real views have been
inspected. HTTPS/mailto/tel links retain the existing safe URL checks; contact
links receive a local dark-orange accent for readable contrast. Table scope
and bounded numeric row/column spans are preserved. All other executable or
unapproved attributes remain removed.
The follow-up styling correction recognizes the live portal's `Daily Lineup
Report` and `Monthly Lineup Report` link labels, even when their original
HubSpot classes or inline fills are absent. It maps only those links to the
existing orange resource-button style; arbitrary anchors remain ordinary links.
Both unlocked views now use the site's orange accent for list-item markers.
The source classes and styles still do not reach the passive DOM.
### Staff resources and Management Templates, 2026-11-01
The owner observed that the non-management (general-staff) portal still lost
HubSpot's resource-button presentation. After **sanitizing** the decrypted DOM,
a headed `Management Templates` section identifies the general-staff resource
view. Valid HTTP(S) resource links in that view receive only the local
`portal-resource-button` class; `mailto:` and `tel:` retain contact-link
styling. Neither destination validation nor removed legacy classes/styles,
scripts, media or HTML attributes are relaxed.
The `Management Templates` unordered list receives a local
`portal-template-grid` class: two columns at desktop widths (768px+),
one column on smaller screens. Semantic list order and keyboard tab order
are retained, with responsive full-width buttons. This is a presentation
change only: it does not infer or approve employee resource access.
Synthetic staff/management browser fixtures check the distinction and
responsive columns. The actual decrypted staff source remains private;
owner should confirm layout and links in the local preview before merging.
Scoped typography, spacing, lists, table rules and keyboard focus apply to both
unlocked streams. Synthetic staff/management fixtures exercise these mappings
at 320/390/768/1440px. Owner must inspect the real views privately to confirm
legacy button recognition and source fidelity; if a different class is used,
provide sanitized class semantics rather than decrypted content or credentials.
Before owner acceptance: validate two real view codes privately, inspect every
resource/category, responsive directories, focus, link semantics and sanitization
impact. Check wrong-code feedback, keyboard unlock, no-JS explanation and refresh.
Production must use a separately reviewed runtime ciphertext delivery mechanism;
this batch intentionally provides only a gated local build input. Browser-delivered
ciphertext is publicly downloadable by anyone able to reach that preview.
+144
View File
@@ -0,0 +1,144 @@
# AIA Form A Jotform styling and conditional-button guide
This directory contains the accepted CSS backup and integration guidance for AIA Form A. [`aia-form-a.css`](./aia-form-a.css) is intended for Jotform Classic Forms' **Form Designer → Styles → Inject Custom CSS** under owner-controlled configuration review. The existing repository CSS is the accepted backup; do not regenerate it from Astro styles.
The CSS translates the existing AIA form treatment: Rubik typography, blue labels and text, `#fcf9f5` inputs with `#edeef3` borders, the `#ffbd59` filled button, the `#ff914d` hover/focus border, four-pixel corners, visible validation errors, and strong keyboard focus. The Astro page supplies the heading, introduction, privacy-policy link, and surrounding card. The stylesheet therefore removes the Jotform surface rather than adding another header, footer, or nested card.
The selectors target Jotform Classic Forms identifiers such as `#form`, `.form-all`, `.form-line`, `.form-label`, `.form-sub-label`, `.form-required`, `.form-textbox`, `.form-dropdown`, `.form-textarea`, `.form-error-message`, and `.form-submit-button`. Jotform's final generated DOM must be checked in the account before relying on pixel-level parity. The stylesheet does not hide required indicators, error messages, honeypots, or focus outlines, and it does not request fonts or other external assets.
The current Builder theme reconciliation adds narrowly scoped `!important` declarations to the outer surface, labels, inputs, and submit-button treatments that Jotform's generated theme otherwise overrides. Error, required-indicator, and focus rules remain visible and are deliberately not reset. The account owner must still confirm the final generated DOM and rendered form after any Jotform theme or field change.
## Installation and comparison
1. Open the approved Form A in AIA's HIPAA-enabled Jotform account. Do not change its fields or settings from this repository workflow.
2. Preserve the approved account configuration; account changes and site cutover require their separate authorization.
3. Paste the contents of `aia-form-a.css` into Jotform's custom CSS area.
4. Compare the Jotform preview with the Astro Form A mock at 390px and 1440px. Check the form surface, label rhythm, input height, button fill, outlined hover/focus state, error state, and mobile reflow.
5. Check both English and Spanish configurations. Confirm translated labels, required indicators, validation messages, confirmation copy, and the accessible iframe title supplied by the parent Astro integration.
6. Test the form in a real embedded iframe and on the direct hosted-form fallback. Confirm the iframe has a practical mobile height, does not create horizontal overflow, and does not trap keyboard focus.
The optional Astro meeting preview requires `PUBLIC_AIA_FORMS_MODE=mock` and `PUBLIC_AIA_FORM_A_PREVIEW=true` in a non-indexing build. It does not load Jotform and is not a live submission test.
## Current Form A operation — superseding decision, 2026-10-30
The owner authorizes real Form A on the publicly reachable development host
`https://aia.web3app.dev/`. Normal development and static builds use **live** Form A
without environment flags. This intentionally supersedes the former isolated-test
and seven-route production approval gates. It is not site-cutover authorization.
From `www/`:
```sh
npm run dev
npm run build
# Optional offline/restricted artifact:
PUBLIC_AIA_FORMS_MODE=off npm run build
# Optional synthetic fixtures:
PUBLIC_AIA_FORMS_MODE=mock npm run dev
```
`PUBLIC_AIA_FORMS_MODE` is optional; missing/empty means `live`. The only accepted
values are `live`, `off`, and `mock`. Remove obsolete `isolated-test` settings from
local environment files; invalid explicit values stop the build with actionable
guidance. The former live/isolated/consultation/production approvals and form
environment role are removed, with no replacement gates. `PUBLIC_ALLOW_INDEXING`
controls publication independently: both staging and indexing builds use the same
16 placements. Explicit off/mock builds contain no real Form A iframe.
One typed registry in `src/utils/form-integration.ts` fixes every route, locale
and context. No visitor query, referrer, arbitrary URL or option preselection is
forwarded. The only origin/ID is `https://form.jotform.com/262946078314059`.
Every URL has exactly `formContext` and `language` parameters:
| Context | Routes | Loading |
|---|---|---|
| contact | `/contact` (en), `/es/contact` (es) | Immediate, 2 |
| landing | `/lp/aba-therapy`, `/lp/aba-insurance`, `/lp/aba-ahcccs`, `/lp/aba-private-pay`, `/lp/early-intervention` (en) | Immediate, 5 |
| consultation | `/client-consultation` (en), `/es/client-consultation` (es), `/schedule-consultation` (en) | Immediate, 3 |
| consultation | `/aba-therapy`, `/autism-evaluations`, `/learner-social-club` (en), and their `/es/` counterparts (es) | Deferred, 6 |
The context is presentation-only. Physical Form B is retired. Form C and
`/referrals` remain inactive; other routes cannot acquire Form A by setting a mode.
The typed future Academy service copy does not publish another page.
Live service drawers open at four seconds OR 50% scroll, canceling the unused
trigger. Dismissal or verified completion sets the existing shared 30-day
suppression timestamp. The existing service CTA overrides automatic suppression;
without JavaScript it remains a normal consultation-page link. Jotform loads only
when the drawer opens. Off mode never automatically opens an inactive drawer.
Mock mode retains the existing synthetic fixture workflow.
A verified `submission-completed` message must match the exact approved origin,
actual activated/open iframe window, approved form ID and action. It displays a
localized acknowledgment, waits five seconds, then uses the existing slide-out.
Duplicate messages cannot restart the countdown. Manual close/navigation cancels
it; suppression remains. Deliberate reopening after completion creates a fresh
iframe. Provider-envelope acceptance still requires the owner-controlled real
submission check; synthetic browser messages are not that acceptance.
The shared iframe preserves fixed responsive heights, accessible EN/ES titles,
`referrerpolicy="no-referrer"`, and
`sandbox="allow-forms allow-scripts allow-same-origin"`. No popup, top-navigation,
camera, microphone, payment or geolocation permissions are added. The hosted
fallback is outside the iframe and hidden without layout space until a 15-second
missing-load timeout. Late load hides it; disposal cancels timers. A localized
`noscript` fallback remains. Load does not prove application health or submission.
No helper script, cross-origin DOM inspection, arbitrary messaging or submission
forwarding is introduced. The official resize handler remains unimplemented and
conditionally acceptable only after its separate security/browser review.
Owner-reported direct EN/ES synthetic acceptance and sampled embedded acceptance
(English contact, Spanish contact and one ABA landing page) remain recorded as
owner evidence. This change does not independently verify Jotform or resolve its
Spanish consultation dropdown discrepancy, runtime telemetry, fluent-language,
screen-reader, final HTTPS-host or operational recipient review.
For form rollback, explicitly set `PUBLIC_AIA_FORMS_MODE=off`, rebuild, verify
`--forms=off`, and use the separately authorized artifact-switch procedure.
Removing that override restores live, so removing settings is **not** rollback.
Do not change the Jotform account as part of an Astro rollback.
Artifact checks (build matching output first):
```sh
node tools/phase10-artifact-verify.mjs --mode=staging --forms=live
# For PUBLIC_ALLOW_INDEXING=true output:
node tools/phase10-artifact-verify.mjs --mode=indexing --forms=live
# For explicit off or mock output, select the matching --forms value.
```
Employee-portal ciphertext remains separately gated by its own approval, private
input and non-indexing preview requirement. Form A modes cannot authorize it.
## Form context and button labels
The current Form A design uses a hidden `formContext` value with fixed, approved values such as `contact` and `landing`. Jotform does not provide a native conditional rule that changes one Submit button's accessible label safely in every context. If owner-approved context-specific labels are required, use multiple native Jotform Submit buttons and Jotform's conditional visibility rules:
- Add one native Submit button for each approved context/language label.
- Show exactly one intended Submit button for the current, validated `formContext`.
- Keep every button a real Jotform Submit control; do not use CSS `::before`/`::after` text as a label.
- Verify that every visible variant submits through the same approved form and preserves the honeypot and validation behavior.
- Make the no-context and invalid-context states fail closed: no ambiguous extra button and no unintended submission path.
- Verify keyboard order, focus visibility, screen-reader names, English/Spanish labels, and mobile layout for every variant.
All five landing routes use Form A's fixed `landing` context. The nine consultation
placements use its fixed `consultation` context. Jotform owns native Submit labels
and conditions. Do not add an external Astro button that attempts to submit a
cross-origin iframe.
## Verification checklist
- [x] Direct English/Spanish Form A language handling, conditional email requirement, synthetic submission and native thank-you were owner-verified; this is not embedded-iframe acceptance.
- [x] Direct staff-notification/autoresponder delivery, generic no-answer/no-PDF content, fixed Reply-To, recipient access/retention, and absent webhooks/integrations were owner-verified for Form A.
- [ ] Exact remaining Form A consultation question properties, choices, conditional routing and availability, plus future Form C configuration, are approved.
- [ ] English and Spanish embedded-iframe labels, validation, confirmation, and button variants are reviewed by fluent-language owners.
- [ ] The hidden honeypot remains present, effective, and excluded from user-facing visual changes.
- [ ] Exactly one native Submit button is visible for every valid context.
- [ ] Invalid or missing context does not expose an unintended submission path.
- [ ] No PHI-bearing answer, PDF, recipient, redirect, webhook, or HTTP POST forwarding is inherited without privacy/security approval.
- [x] Owner-reported embedded synthetic submission and confirmation passed on English contact, Spanish contact and one ABA landing placement; record the exact ABA path in the owner test log before release.
- [ ] All sixteen placements have final responsive, keyboard, screen-reader and fluent-language acceptance, including timeout/fallback and error expansion.
- [ ] Jotform runtime requests, telemetry and cross-origin failure behavior are reviewed with privacy/security owners.
- [ ] No Jotform, Contabo, analytics, advertising, or production API request is made by off/mock builds.
Existing owner-verification scopes remain recorded in the contract/checklist. Outstanding consultation configuration acceptance, runtime/privacy, accessibility, fluent-language and site-release gates remain open. Default-live Form A is owner-authorized; this guide does not authorize Jotform account changes or site deployment.
+252
View File
@@ -0,0 +1,252 @@
/* ==========================================================
AIA FORM A — JOTFORM CUSTOM CSS
Form ID: 262946078314059
Maximum form width: 640px
========================================================== */
/* Document and language selector */
html.supernova,
html.supernova body,
body.supernova {
background: #fff !important;
background-image: none !important;
}
/* Avoid horizontal overflow, including on the thank-you page */
body {
margin: 0 !important;
}
/* Confirmation page styling */
body.thankyou,
body.thankyou #stage {
background: #fff !important;
background-image: none !important;
}
.jfLangDd.jfLangDd--match-form {
padding: 12px 0 !important;
}
/* Form container */
form[id="262946078314059"] {
width: 100% !important;
max-width: 640px !important;
margin: 8px auto !important;
box-sizing: border-box;
}
.form-all {
width: 100% !important;
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
background: #fff !important;
border: 0 !important;
box-shadow: none !important;
color: #254080;
font-family: Rubik, Arial, sans-serif;
}
.form-all .form-section {
margin: 0 !important;
padding: 0 !important;
}
/* Field layout */
.form-all .form-line {
margin: 0 !important;
padding: 0 0 21px !important;
background: transparent !important;
border: 0 !important;
}
.form-all .form-input-wide {
margin-top: 0 !important;
padding-top: 0 !important;
}
/* Labels and sublabels */
.form-all .form-label,
.form-all .form-label-left,
.form-all .form-label-right,
.form-all .form-label-top {
color: #254080 !important;
font-size: .875rem;
font-weight: 700;
line-height: 1.35 !important;
margin: 0 0 6px !important;
padding: 0 !important;
}
.form-all .form-sub-label {
color: #254080;
font-size: .75rem;
line-height: 1.3 !important;
margin: 4px 0 0 !important;
padding: 0 !important;
}
.form-all .form-sub-label-container {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
.form-all .form-required {
color: #a21c28 !important;
margin-left: .2rem;
visibility: visible;
}
/* Inputs */
.form-all input.form-textbox,
.form-all select.form-dropdown,
.form-all textarea.form-textarea {
background: #fcf9f5 !important;
background-image: none !important;
border: 1px solid #edeef3 !important;
border-radius: 4px !important;
box-shadow: none !important;
box-sizing: border-box;
color: #254080 !important;
font-family: inherit;
font-size: 1rem;
line-height: 1.4;
min-height: 2.75rem;
padding: .55rem .7rem;
max-width: 100%;
}
/* Preserve two-column name fields */
.form-all .form-sub-label-container input.form-textbox {
width: 100% !important;
max-width: 100% !important;
}
/* Full-width phone and email fields */
.form-all
.form-line:is(
[data-type="control_phone"],
[data-type="control_email"]
)
:is(.form-input, .form-input-wide, input.form-textbox) {
width: 100% !important;
max-width: 100% !important;
}
/* Message field */
.form-all textarea.form-textarea {
width: 100% !important;
min-height: 5.5rem !important;
resize: vertical;
}
/* Radio buttons and checkboxes */
.form-all .form-radio-item,
.form-all .form-checkbox-item {
color: #254080;
line-height: 1.4;
margin: 0 .75rem .2rem 0 !important;
padding: 0;
}
.form-all .form-radio,
.form-all .form-checkbox {
accent-color: #254080;
}
/* Submit button and wrapper */
.form-all .jf-form-buttons,
.form-all .form-buttons-wrapper {
box-sizing: border-box;
width: 100% !important;
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
background: transparent !important;
border: 0 !important;
}
.form-all .form-submit-button,
.form-all button[type="submit"] {
width: 100%;
box-sizing: border-box;
min-height: 3rem;
padding: .65rem 1.2rem;
background: #ffbd59 !important;
background-image: none !important;
border: 2px solid #ffbd59 !important;
border-radius: 4px !important;
box-shadow: none !important;
color: #254080 !important;
cursor: pointer;
font-family: inherit;
font-size: 1rem;
font-weight: 400;
line-height: 1.4;
text-shadow: none !important;
transition: background .3s linear, border-color .3s linear;
}
.form-all .form-submit-button:hover,
.form-all button[type="submit"]:hover {
background: transparent !important;
border-color: #ff914d !important;
color: #254080 !important;
}
.form-all .form-submit-button:disabled,
.form-all button[type="submit"]:disabled {
cursor: not-allowed;
opacity: .65;
}
/* Keyboard focus */
.form-all input.form-textbox:focus-visible,
.form-all select.form-dropdown:focus-visible,
.form-all textarea.form-textarea:focus-visible,
.form-all input[type="radio"]:focus-visible,
.form-all input[type="checkbox"]:focus-visible,
.form-all .form-submit-button:focus-visible {
outline: 3px solid #115bbd !important;
outline-offset: -3px;
}
/* Validation */
.form-all .form-line-error input.form-textbox,
.form-all .form-line-error select.form-dropdown,
.form-all .form-line-error textarea.form-textarea,
.form-all input.form-validation-error {
border-color: #a21c28 !important;
}
.form-all .form-error-message,
.form-all .form-line-error .form-error-message {
color: #a21c28 !important;
font-size: .8rem;
font-weight: 700;
line-height: 1.4;
margin: .3rem 0 0 !important;
visibility: visible;
}
/* Accessibility: reduced motion */
@media (prefers-reduced-motion: reduce) {
.form-all .form-submit-button,
.form-all button[type="submit"] {
transition: none;
}
}
+72
View File
@@ -0,0 +1,72 @@
# Inactive SOPS/age preparation, 2026-10-30
The owner selected SOPS, age and sops-nix. This directory is a template, not a
host configuration. The development flake remains unchanged. No real recipient,
key, encrypted secret or server user is supplied. No module is deployed.
Official references inspected for this pass:
- [SOPS documentation](https://getsops.io/docs/)
- [sops-nix installation and secret permissions](https://github.com/Mic92/sops-nix)
SOPS encrypts configuration at rest. sops-nix can supply decrypted values at
runtime under `/run/secrets` with explicit owners and modes. This does not make
browser ciphertext or publicly served documents private.
## Owner setup before activation
1. Supply the actual NixOS topology, host flake, deploy user, persisted key
location, backup owner, HTTPS termination and resource-service identity.
2. Pin a reviewed `github:Mic92/sops-nix` input in that host flake; import
`inputs.sops-nix.nixosModules.sops` and the reviewed template. Do not add the
input to the Astro development flake just to evaluate a deployment sketch.
3. The owner generates independent developer/recovery and VPS age identities in
private terminals. Record only public recipients in the reviewed SOPS
creation rule. Use distinct recipients, never a placeholder recipient. Keep
the VPS private identity on persistent root-controlled storage (0600), outside
`/nix/store`, Git, the public static root and CI artifacts.
4. Encrypt the approved credential material using SOPS with both recipients.
Review recipient access, least privilege and an offline recovery copy. SOPS
encrypted files may enter a deployment repository only after owner approval.
5. Set `aia.portalSecrets` options explicitly, then evaluate the complete host
configuration and test decryption on authorized nonproduction infrastructure.
Runtime consumers use the generated `.path`, not Nix evaluation of plaintext.
6. Decide which service reloads after rotation. Rotate application credentials
as well as SOPS recipients when revoking access: rewrapping alone does not
invalidate an already copied password. Test recovery and key restoration.
## Separate staff and management resource authorization
Keep original documents outside Astro `public`, `dist`, release archives and
CDN roots. Proposed delivery namespaces are `/staff-resources/` and
`/management-resources/`; neither is implemented or considered working here.
Use nginx `auth_request` to an approved authorization service or an equivalent
server-enforced policy with individually revocable identities and staff and
management roles. Staff credentials must not authorize management resources;
management access to staff resources must be an explicit policy. Backend file
locations must be internal, inaccessible through static aliases or alternate
paths. Never trust a browser-provided role header.
A separate shared Basic Auth credential file per namespace can be considered
only as an explicitly approved weaker interim model, not identity management or
automatic role inheritance. The template prepares separate secret inputs without
selecting that access model or installing an identity provider.
Use HTTPS, `Cache-Control: private, no-store`, no shared/CDN caching, and
`Referrer-Policy: no-referrer` for protected delivery. Avoid credentials and
sensitive resource paths in access/error logs; review monitoring and backups.
Authorization failures must fail closed, including at proxy/cache boundaries.
Test direct requests, alternate encodings, role crossover and rollback.
## Distinct boundaries and release checks
- SOPS: deployment secrets at rest and controlled runtime access.
- Portal HTML: shared-code browser decryption, offline-guessable access friction.
- Documents: require server authorization even if URLs are encrypted in the UI.
The compatibility preview cannot grant production portal access. Before cutover,
classify every document, implement and verify its delivery destination, rewrite
and re-encrypt links, test two-view separation, rotate shared codes privately,
check the public artifact for private files, and obtain owner/security approval.
Back up encrypted configuration and documents separately from keys; rehearse
restore and rollback. Revoking a static release cannot retract ciphertext or
files already downloaded by visitors. Site cutover is still unauthorized.
+26
View File
@@ -0,0 +1,26 @@
# INACTIVE TEMPLATE. Not imported by the development flake or any deployed host.
# Requires an owner-reviewed sops-nix NixOS module import in the host flake.
{ config, lib, ... }:
let cfg = config.aia.portalSecrets;
in {
options.aia.portalSecrets = {
enable = lib.mkEnableOption "owner-reviewed portal deployment secrets";
encryptedFile = lib.mkOption { type = lib.types.path; description = "SOPS-encrypted YAML only; never a plaintext file"; };
ageKeyFile = lib.mkOption { type = lib.types.str; description = "Private persisted host age key path outside the Nix store"; };
readerUser = lib.mkOption { type = lib.types.str; description = "Approved resource authorization service user"; };
};
config = lib.mkIf cfg.enable {
assertions = [{ assertion = lib.hasPrefix "/" cfg.ageKeyFile && !(lib.hasPrefix "/nix/store/" cfg.ageKeyFile);
message = "The host age identity must be an absolute runtime path outside the Nix store."; }];
sops.defaultSopsFile = cfg.encryptedFile;
sops.age.keyFile = cfg.ageKeyFile;
sops.age.generateKey = false;
sops.age.sshKeyPaths = [];
sops.gnupg.sshKeyPaths = [];
sops.secrets."portal/staff-credentials" = { owner = cfg.readerUser; mode = "0400"; };
sops.secrets."portal/management-credentials" = { owner = cfg.readerUser; mode = "0400"; };
# Consumers reference config.sops.secrets.<name>.path at runtime.
# Do not use builtins.readFile on a decrypted secret, environment.etc.text,
# PUBLIC_* values, or Astro/Vite imports to transport secrets.
};
}
+7772
View File
File diff suppressed because it is too large. Load diff
+44
View File
@@ -0,0 +1,44 @@
{
"name": "arizona-institute-for-autism",
"private": true,
"type": "module",
"engines": {
"node": ">=22.12.0"
},
"scripts": {
"dev": "astro dev",
"check": "astro check",
"build": "astro check && astro build",
"build:sandbox": "NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro check && NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro build",
"preview": "astro preview",
"extract:blog-footers": "node tools/extract-blog-footers.mjs",
"crawl:live": "node tools/crawl-live-site.mjs",
"audit:links": "node --experimental-strip-types tools/audit-links.mjs",
"audit:images": "node tools/audit-page-imagery.mjs",
"audit:blog": "node tools/audit-blog-content.mjs",
"audit:routes": "node --experimental-strip-types tools/audit-routes.mjs",
"test:routes": "node --experimental-strip-types --test tools/audit-routes.test.mjs",
"test:markdown": "node --test tools/markdown.test.mjs",
"test:publication": "node --experimental-strip-types --test tools/publication.test.mjs",
"test:seo": "node --experimental-strip-types --test tools/seo.test.mjs",
"test:library": "node --experimental-strip-types --test tools/library.test.mjs",
"test:campaign": "node --test tools/campaign.test.mjs",
"verify:campaign": "node tools/campaign-browser.mjs",
"generate:sitemap": "node tools/generate-sitemap.mjs",
"generate:redirects": "node tools/generate-redirects.mjs"
},
"dependencies": {
"@astrojs/markdown-satteri": "^0.3.5",
"@astrojs/mdx": "^7.0.5",
"astro": "^7.1.5",
"cheerio": "^1.1.0",
"fast-glob": "^3.3.3",
"gray-matter": "^4.0.3",
"swiper": "^12.2.0",
"turndown": "^7.2.0"
},
"devDependencies": {
"@astrojs/check": "^0.9.10",
"typescript": "^6.0.3"
}
}
@@ -0,0 +1,93 @@
Copyright 2017 The Playfair Display Project Authors (https://github.com/clauseggers/Playfair-Display), with Reserved Font Name "Playfair Display"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2015 The Rubik Project Authors (https://github.com/googlefonts/rubik)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

@@ -0,0 +1 @@
<svg viewBox="113.85996 134.2596 679.2 315.6" xmlns="http://www.w3.org/2000/svg" id="Layer_1" style="max-height: 500px" width="679.2" height="315.6"><defs><style>.cls-1,.cls-2,.cls-3,.cls-4,.cls-5,.cls-6{stroke-width:0px;}.cls-2{fill:#27417f;}.cls-3{fill:#554f62;}.cls-4{fill:#254080;}.cls-5{fill:#aea990;}.cls-6{fill:#f2b85b;}</style></defs><path d="m176.47,162.76l22.18,57.09c.85,2.24,1.83,3.76,2.95,4.54,1.12.79,2.17,1.21,3.14,1.27v1.82c-1.46-.12-3.17-.2-5.14-.22-1.97-.03-3.95-.05-5.95-.05-2.54,0-4.91.01-7.09.05-2.18.03-3.94.11-5.28.22v-1.82c3.09-.12,5.05-.65,5.87-1.59.82-.94.62-2.95-.59-6.04l-16.36-44.17,1.46-1.64-15.09,39.45c-1.09,2.73-1.74,5-1.95,6.82-.22,1.82-.06,3.24.45,4.27.52,1.03,1.41,1.76,2.68,2.18,1.27.43,2.85.67,4.73.73v1.82c-1.82-.12-3.65-.2-5.5-.22-1.85-.03-3.59-.05-5.23-.05-1.46,0-2.74.01-3.86.05-1.12.03-2.14.11-3.05.22v-1.82c1.27-.3,2.55-1.06,3.82-2.27,1.27-1.21,2.48-3.27,3.63-6.18l21.09-54.45h3.09Zm9.54,38.54v1.82h-27.08l.91-1.82h26.18Z" class="cls-2"/><path d="m235.82,179.3c1.76,0,3.26.37,4.5,1.09,1.24.73,2.18,1.65,2.82,2.77.64,1.12.96,2.38.96,3.77,0,1.76-.53,3.26-1.59,4.5-1.06,1.24-2.47,1.86-4.23,1.86-1.51,0-2.8-.46-3.86-1.36-1.06-.91-1.59-2.15-1.59-3.73,0-1.33.35-2.47,1.04-3.41.7-.94,1.5-1.68,2.41-2.22-.6-.49-1.33-.7-2.18-.64-1.64.06-3.15.59-4.55,1.59-1.39,1-2.58,2.27-3.54,3.82-.97,1.54-1.73,3.19-2.27,4.95-.54,1.76-.82,3.4-.82,4.91v20.91c0,2.97.82,4.96,2.46,5.95,1.63,1,3.91,1.5,6.81,1.5v1.91c-1.39-.06-3.38-.14-5.95-.22-2.58-.09-5.28-.14-8.14-.14-2.18,0-4.36.05-6.54.14-2.18.09-3.85.16-5,.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96v10.46c.73-1.76,1.7-3.45,2.91-5.09,1.21-1.63,2.66-2.98,4.36-4.04,1.7-1.06,3.58-1.59,5.64-1.59Z" class="cls-2"/><path d="m264,179.57v39.45c0,2.54.5,4.27,1.5,5.18,1,.91,2.68,1.36,5.05,1.36v1.91c-1.03-.06-2.62-.14-4.77-.22-2.16-.09-4.35-.14-6.59-.14s-4.38.05-6.59.14c-2.21.09-3.86.16-4.96.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96Zm-5.45-21.91c1.88,0,3.45.59,4.73,1.78,1.27,1.18,1.91,2.65,1.91,4.41s-.64,3.23-1.91,4.41c-1.27,1.18-2.85,1.77-4.73,1.77s-3.45-.59-4.73-1.77c-1.27-1.18-1.91-2.65-1.91-4.41s.64-3.23,1.91-4.41c1.27-1.18,2.85-1.78,4.73-1.78Z" class="cls-2"/><path d="m312.54,180.12l-25.09,45.99h8.18c2.42,0,4.58-.49,6.45-1.46,1.88-.97,3.42-2.57,4.64-4.81,1.21-2.24,1.94-5.21,2.18-8.91h2.09c0,4.06.03,7.45.09,10.18s.15,4.97.27,6.73c-2.72-.12-5.54-.22-8.45-.27-2.91-.06-5.79-.09-8.63-.09-3.09,0-6.23.05-9.41.14-3.18.09-6.23.2-9.14.32l25.09-45.99h-8.36c-2.6,0-4.85.5-6.73,1.5-1.88,1-3.35,2.61-4.41,4.82-1.06,2.21-1.74,5.17-2.05,8.86h-2c0-4.12-.03-7.51-.09-10.18-.06-2.66-.15-4.91-.27-6.73,2.67.12,5.45.22,8.36.27,2.91.06,5.82.09,8.73.09s6.14-.05,9.32-.14c3.18-.09,6.26-.2,9.23-.32Z" class="cls-2"/><path d="m340.81,179.3c4.06,0,7.66.85,10.82,2.55,3.15,1.7,5.66,4.36,7.55,8,1.88,3.64,2.81,8.39,2.81,14.27s-.94,10.62-2.81,14.23c-1.88,3.61-4.4,6.24-7.55,7.91-3.15,1.67-6.76,2.5-10.82,2.5s-7.6-.83-10.82-2.5c-3.21-1.67-5.74-4.3-7.59-7.91-1.85-3.61-2.77-8.35-2.77-14.23s.92-10.63,2.77-14.27c1.85-3.64,4.38-6.3,7.59-8,3.21-1.7,6.82-2.55,10.82-2.55Zm0,1.82c-3.15,0-5.73,1.8-7.73,5.41-2,3.61-3,9.47-3,17.59s1,13.95,3,17.5c2,3.55,4.58,5.32,7.73,5.32s5.65-1.77,7.68-5.32c2.03-3.55,3.05-9.38,3.05-17.5s-1.02-13.98-3.05-17.59c-2.03-3.61-4.59-5.41-7.68-5.41Z" class="cls-2"/><path d="m400.07,179.3c2.42,0,4.41.32,5.95.96,1.55.64,2.83,1.5,3.86,2.59,1.09,1.15,1.86,2.64,2.32,4.46.45,1.82.68,4.27.68,7.36v24.36c0,2.54.5,4.27,1.5,5.18,1,.91,2.68,1.36,5.05,1.36v1.91c-1.03-.06-2.64-.14-4.82-.22-2.18-.09-4.33-.14-6.45-.14s-4.11.05-6.14.14c-2.03.09-3.56.16-4.59.22v-1.91c2.06,0,3.51-.45,4.37-1.36.85-.91,1.27-2.64,1.27-5.18v-26.9c0-1.76-.15-3.35-.45-4.77-.31-1.42-.94-2.58-1.91-3.45-.97-.88-2.43-1.32-4.37-1.32-2.24,0-4.23.64-5.95,1.91-1.73,1.27-3.09,3.02-4.09,5.23-1,2.21-1.5,4.68-1.5,7.41v21.91c0,2.54.44,4.27,1.32,5.18.88.91,2.32,1.36,4.32,1.36v1.91c-.97-.06-2.44-.14-4.41-.22-1.97-.09-4.01-.14-6.14-.14s-4.21.05-6.45.14c-2.24.09-3.91.16-5,.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96v9.91c1.57-3.76,3.74-6.39,6.5-7.91,2.75-1.51,5.68-2.27,8.77-2.27Z" class="cls-2"/><path d="m436.06,228.11c-2.54,0-4.73-.49-6.54-1.46-1.82-.97-3.18-2.3-4.09-4-.91-1.69-1.36-3.63-1.36-5.82,0-2.67.6-4.83,1.82-6.5,1.21-1.67,2.77-3.02,4.69-4.04,1.91-1.03,3.94-1.89,6.09-2.59,2.15-.7,4.18-1.36,6.09-2,1.91-.64,3.48-1.38,4.73-2.22,1.24-.85,1.86-1.97,1.86-3.36v-6.18c0-2.18-.35-3.93-1.05-5.23-.7-1.3-1.63-2.22-2.81-2.77-1.19-.55-2.59-.82-4.23-.82-1.4,0-2.88.2-4.46.59-1.57.39-2.81,1.17-3.72,2.32,1.33.37,2.44,1.08,3.32,2.14.88,1.06,1.32,2.38,1.32,3.95,0,1.7-.56,3.03-1.68,4s-2.53,1.45-4.Line truncated

After

Width:  |  Height:  |  Size: 33 KiB

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" fill="none" stroke="#E5AE56" stroke-width="2">
<path d="m67 13 2-10h22l2 10 13 5 9-6 16 16-6 9 5 13 10 2v22l-10 2-5 13 6 9-16 16-9-6-13 5-2 10H69l-2-10-13-5-9 6-16-16 6-9-5-13-10-2V52l10-2 5-13-6-9 16-16 9 6Z" transform="translate(0 17)"/>
<circle cx="80" cy="80" r="26"/>
</svg>

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

+1
View File
@@ -0,0 +1 @@
<svg viewBox="113.85996 134.2596 679.2 315.6" xmlns="http://www.w3.org/2000/svg" id="Layer_1" style="max-height: 500px" width="679.2" height="315.6"><defs><style>.cls-1,.cls-2,.cls-3,.cls-4,.cls-5,.cls-6{stroke-width:0px;}.cls-2{fill:#27417f;}.cls-3{fill:#554f62;}.cls-4{fill:#254080;}.cls-5{fill:#aea990;}.cls-6{fill:#f2b85b;}</style></defs><path d="m176.47,162.76l22.18,57.09c.85,2.24,1.83,3.76,2.95,4.54,1.12.79,2.17,1.21,3.14,1.27v1.82c-1.46-.12-3.17-.2-5.14-.22-1.97-.03-3.95-.05-5.95-.05-2.54,0-4.91.01-7.09.05-2.18.03-3.94.11-5.28.22v-1.82c3.09-.12,5.05-.65,5.87-1.59.82-.94.62-2.95-.59-6.04l-16.36-44.17,1.46-1.64-15.09,39.45c-1.09,2.73-1.74,5-1.95,6.82-.22,1.82-.06,3.24.45,4.27.52,1.03,1.41,1.76,2.68,2.18,1.27.43,2.85.67,4.73.73v1.82c-1.82-.12-3.65-.2-5.5-.22-1.85-.03-3.59-.05-5.23-.05-1.46,0-2.74.01-3.86.05-1.12.03-2.14.11-3.05.22v-1.82c1.27-.3,2.55-1.06,3.82-2.27,1.27-1.21,2.48-3.27,3.63-6.18l21.09-54.45h3.09Zm9.54,38.54v1.82h-27.08l.91-1.82h26.18Z" class="cls-2"/><path d="m235.82,179.3c1.76,0,3.26.37,4.5,1.09,1.24.73,2.18,1.65,2.82,2.77.64,1.12.96,2.38.96,3.77,0,1.76-.53,3.26-1.59,4.5-1.06,1.24-2.47,1.86-4.23,1.86-1.51,0-2.8-.46-3.86-1.36-1.06-.91-1.59-2.15-1.59-3.73,0-1.33.35-2.47,1.04-3.41.7-.94,1.5-1.68,2.41-2.22-.6-.49-1.33-.7-2.18-.64-1.64.06-3.15.59-4.55,1.59-1.39,1-2.58,2.27-3.54,3.82-.97,1.54-1.73,3.19-2.27,4.95-.54,1.76-.82,3.4-.82,4.91v20.91c0,2.97.82,4.96,2.46,5.95,1.63,1,3.91,1.5,6.81,1.5v1.91c-1.39-.06-3.38-.14-5.95-.22-2.58-.09-5.28-.14-8.14-.14-2.18,0-4.36.05-6.54.14-2.18.09-3.85.16-5,.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96v10.46c.73-1.76,1.7-3.45,2.91-5.09,1.21-1.63,2.66-2.98,4.36-4.04,1.7-1.06,3.58-1.59,5.64-1.59Z" class="cls-2"/><path d="m264,179.57v39.45c0,2.54.5,4.27,1.5,5.18,1,.91,2.68,1.36,5.05,1.36v1.91c-1.03-.06-2.62-.14-4.77-.22-2.16-.09-4.35-.14-6.59-.14s-4.38.05-6.59.14c-2.21.09-3.86.16-4.96.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96Zm-5.45-21.91c1.88,0,3.45.59,4.73,1.78,1.27,1.18,1.91,2.65,1.91,4.41s-.64,3.23-1.91,4.41c-1.27,1.18-2.85,1.77-4.73,1.77s-3.45-.59-4.73-1.77c-1.27-1.18-1.91-2.65-1.91-4.41s.64-3.23,1.91-4.41c1.27-1.18,2.85-1.78,4.73-1.78Z" class="cls-2"/><path d="m312.54,180.12l-25.09,45.99h8.18c2.42,0,4.58-.49,6.45-1.46,1.88-.97,3.42-2.57,4.64-4.81,1.21-2.24,1.94-5.21,2.18-8.91h2.09c0,4.06.03,7.45.09,10.18s.15,4.97.27,6.73c-2.72-.12-5.54-.22-8.45-.27-2.91-.06-5.79-.09-8.63-.09-3.09,0-6.23.05-9.41.14-3.18.09-6.23.2-9.14.32l25.09-45.99h-8.36c-2.6,0-4.85.5-6.73,1.5-1.88,1-3.35,2.61-4.41,4.82-1.06,2.21-1.74,5.17-2.05,8.86h-2c0-4.12-.03-7.51-.09-10.18-.06-2.66-.15-4.91-.27-6.73,2.67.12,5.45.22,8.36.27,2.91.06,5.82.09,8.73.09s6.14-.05,9.32-.14c3.18-.09,6.26-.2,9.23-.32Z" class="cls-2"/><path d="m340.81,179.3c4.06,0,7.66.85,10.82,2.55,3.15,1.7,5.66,4.36,7.55,8,1.88,3.64,2.81,8.39,2.81,14.27s-.94,10.62-2.81,14.23c-1.88,3.61-4.4,6.24-7.55,7.91-3.15,1.67-6.76,2.5-10.82,2.5s-7.6-.83-10.82-2.5c-3.21-1.67-5.74-4.3-7.59-7.91-1.85-3.61-2.77-8.35-2.77-14.23s.92-10.63,2.77-14.27c1.85-3.64,4.38-6.3,7.59-8,3.21-1.7,6.82-2.55,10.82-2.55Zm0,1.82c-3.15,0-5.73,1.8-7.73,5.41-2,3.61-3,9.47-3,17.59s1,13.95,3,17.5c2,3.55,4.58,5.32,7.73,5.32s5.65-1.77,7.68-5.32c2.03-3.55,3.05-9.38,3.05-17.5s-1.02-13.98-3.05-17.59c-2.03-3.61-4.59-5.41-7.68-5.41Z" class="cls-2"/><path d="m400.07,179.3c2.42,0,4.41.32,5.95.96,1.55.64,2.83,1.5,3.86,2.59,1.09,1.15,1.86,2.64,2.32,4.46.45,1.82.68,4.27.68,7.36v24.36c0,2.54.5,4.27,1.5,5.18,1,.91,2.68,1.36,5.05,1.36v1.91c-1.03-.06-2.64-.14-4.82-.22-2.18-.09-4.33-.14-6.45-.14s-4.11.05-6.14.14c-2.03.09-3.56.16-4.59.22v-1.91c2.06,0,3.51-.45,4.37-1.36.85-.91,1.27-2.64,1.27-5.18v-26.9c0-1.76-.15-3.35-.45-4.77-.31-1.42-.94-2.58-1.91-3.45-.97-.88-2.43-1.32-4.37-1.32-2.24,0-4.23.64-5.95,1.91-1.73,1.27-3.09,3.02-4.09,5.23-1,2.21-1.5,4.68-1.5,7.41v21.91c0,2.54.44,4.27,1.32,5.18.88.91,2.32,1.36,4.32,1.36v1.91c-.97-.06-2.44-.14-4.41-.22-1.97-.09-4.01-.14-6.14-.14s-4.21.05-6.45.14c-2.24.09-3.91.16-5,.22v-1.91c2.37,0,4.04-.45,5.05-1.36,1-.91,1.5-2.64,1.5-5.18v-28.54c0-2.73-.46-4.74-1.36-6.04-.91-1.3-2.64-1.95-5.18-1.95v-1.91c1.94.18,3.82.27,5.64.27,2.06,0,3.99-.11,5.77-.32,1.78-.22,3.44-.53,4.95-.96v9.91c1.57-3.76,3.74-6.39,6.5-7.91,2.75-1.51,5.68-2.27,8.77-2.27Z" class="cls-2"/><path d="m436.06,228.11c-2.54,0-4.73-.49-6.54-1.46-1.82-.97-3.18-2.3-4.09-4-.91-1.69-1.36-3.63-1.36-5.82,0-2.67.6-4.83,1.82-6.5,1.21-1.67,2.77-3.02,4.69-4.04,1.91-1.03,3.94-1.89,6.09-2.59,2.15-.7,4.18-1.36,6.09-2,1.91-.64,3.48-1.38,4.73-2.22,1.24-.85,1.86-1.97,1.86-3.36v-6.18c0-2.18-.35-3.93-1.05-5.23-.7-1.3-1.63-2.22-2.81-2.77-1.19-.55-2.59-.82-4.23-.82-1.4,0-2.88.2-4.46.59-1.57.39-2.81,1.17-3.72,2.32,1.33.37,2.44,1.08,3.32,2.14.88,1.06,1.32,2.38,1.32,3.95,0,1.7-.56,3.03-1.68,4s-2.53,1.45-4.Line truncated

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

@@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="450" viewBox="0 0 800 450">
<title>نموذج المقدمة والسلوك والنتيجة اللاحقة</title>
<image href="data:image/webp;base64,UklGRqqoAABXRUJQVlA4IJ6oAACQlgKdASogA8IBPpE+mkoloyIhp7FMkLASCWNu0atuo+8/hc72vn/l2SXST+W89GyhV23khTWeu5Lez2L9Q/u9qvK/yf+36EPIvir8//Fet3/n8DPgP/B5wD5X/g9aH9Z/3nsM/1Do4+aDzdPT1/dvUe/yv+49cz1oPRC6aH+3ecpnGX+1/1/ox+efxn+78Qfzf7Z/ef379zfiF/e8zfwf+r5qfcx+V/kfa1/gf+r/OeUv67/R/9f1DvzL+o/671YOSviA8P+9P+r9g722+2/9n/MflT8TH6H/t9Kf4b/X/+X3Af1x/4fsj/4/Hp/J/9f2CP6F/i//P93X1D/7P/2/4/pd+wf/n7h/9B/wX/l/zXt5///3a/vR///dw/dT//oDY+ZlmGz0aurLMNno0wobo7evPt0FDdHbsSKEbpWYbPRpfGdegq7sgIyQddLHyeE1E+dff2k5GMjfvtugobortGfJ+m0JAPReL3Cux8zLMLsk66IAKK3r6kForL4yMq7h8RGPM2N6HxQd+3O676CToBfiaMPUQXSd9fYRTv8nj/+pLeptrihK71mSB/pvDFxxkwEZdYletgvowIer5iRsG3C5HGHv9kbQAvWJqr0ocqUft/OfBN1Ap91BX9KoXPfB3/8BU5k2BXVrQCtNKGAU1FkQZYXiwSnxCAtWk7mBm4QqD4hww0rYerXIjRw/BLsLDZ9KmRB6GN9SHTUWWwGP23X541M360l1EiWdWFrUonM8FeUUHTm0QGGqDYoWh9fPX8Oh5KD4uEEthsveAgqwXPG7A60+Xzt2JXPcojUWGyIHoT5u+X/t2rwO0oH3fBIro1nWuwwCOwdRK9Cg2c2qeBCbrKOSHvexq5fz/wLUCL/PQTiLq34v9qDAeAxKFmpny7QDHycQo4zz89R/hss3SR7/+KM/17eCKnRVzsIJsezet7HUXglrcbVrUohbYEDQv0uPRly6m6W2YQ/HblOm6Xc9vIMKGsXSJgQOv/iiYmq7hetYde5gF2ZiF6fd50xrebMJstfkB664BPxw7ehmYO12uRS35iX5npdM5i7Ga9h3LkITUuKIxOJHpdZMqthzz5YCllzGGl1Z1kDMN08j8/9wdMuoHbnjwnfcqovTEi75p+kUKhPYxdwcLXLZOIag6UWTUVcoGAZbIeZlzUgKxSxPa9AaSDZO8MhqYTQSVI8B7EJ6j3M2NXyRX3j8n5Qn9LBB0xwQHfXnwTh6WWWEQ5Z3j0FWygnqC4N09zETtCulsn8OPa5xm/s4n5Mng54fLL0CxzhlGOFaDKZLHxD20iaqbKKF60BQF/1RrpgxxRQeo6hsrduqLQdOW4abv6spEQTeFSj3p4XbLWuuI05Jh7CUnwajLoiqiPUs8omnWmdLHdQ7AKyd+vGVBu4YGstAJF/bFAl+gxNYI3GkEqu4HkSKcoVwg6HMXk7kvy2uvM1OV0N7mbhSbH/XTDokarECyQmH2m0jJ4EzQjvKi+YoJpeZTIZhqYOntNxOEqNWujN15qh7Desf61WLwAoz8MY4Lz19PbF7ZGNFD1Xl/JqE5O7/uhv+KJpsbJszLK53AF76z/dRknxsFQzikbRkpOQTxZoPczG+9FtGO6bEKuYTZb++t4JFj+H4DPPUbwSPlMobbbTcYlDIt3HzNYF+Hbv89rDXAxNUzdsSdPFAY4DRzvCtd+U1oBM70YtcyOrd4t9vX5KzQjMIp5rr8bgNNFc76lxIcif/mDuVwExUSlAoEtgg75zD+aNy/u/dpIi06DtwjB3Em0d6kTdOsgkQ/UHXsD3QlPpT//JvWt+iuL6Ou5YSI6mnzgJ6Sgtc+q3Ittv0MO6zbf09HoQhM/5DCLNyE4lKM75sc/Xn2MrdZds8kfSi1VWayPK3z8+9I8adQUdqQga6ZGtrAaSmjDGR6OFv17WMIRPL+3b80oJ0GPz946ICFR4INi9Iz0XuHu0GLHDreJAspUtSPPosi35CPd8lD2RBWewm+7hvLJPdnPddP0zxMLyA8iBjyKVHdEZIaxxmXK88OI1x4ZWGNPs8rEKr1bmfkrP/G9wdbNqlK7eRgQ0skIR4o9lp6XYJUhiPfFRqLQUtrQKeNRMi+9uXKrhRBDc12eQ32itzsuOEzq24zn1RqXGphrMGpUgJO9AY/9U7vUyjXIs8D1VzbomF7VjXRUlk77QnMXlO9FFB8WmaQtYfXq7+lEj8bt/ZakDXK4vhs2B+Ab2ZGHP6M+4efj/yIOcH9uzluP5Jda5Afi5VAQsy2iF4If+aJGz22I3bGs9uKYjs5VjCOdOhFY5+658k/dUmW8ylI93vibK3Naj2QyyUBSFBYKPcwKI7p+SJZUDbeYTHuAORWyiO+0BgsQS/bKtWNfNaM/vccEDOvE9LJaaAqe7v8aqDIB+1GpL7ncH4iDrHH230+tkVQ4KTLhliUe4YZNjZjOuMfvOGCuPDNFlZRPxMrLO+P2Vd8GKdg0yRWvKZ/MdPOeyVmND/bYv3mH7f+Iz3ydxZZQrosyzd+m176MYxlEN6n2aF9V8Aggfbl5Z8FSlt0dfzHcrYwYW0qVvOxGNwBqlu9v63GDW/6MuveAAd5yKra0jvAYDgxLL1xWTA/TmUXBm2Pm+Slze72GgY3YRaf4dDiY+fRIbTA/WNNy2Wng6h/l4aquGZpF0xkL4pUBYbuhfAm7y2BX/NXngigr7THksys99j67E4v+NexXwtCS0ooRoG1EHvbLn+HRY+Br5939x1tnHJWA2V7IhPizqrinmRmZzsScphZSpPih0eeyCECM1ot+M67PpVkMof0dR+3Nki0ZnU+MFNXRbUZWumweCuAajDiz+z/9Ja2Gz+MuqDq2JkbT2tmCdSn/ZTQJkFFUGaGYtpni+ELrDze1Od4UXh4WdhG5wnArXYH7unz+OfWaLm6Wv1rDMizVnZnh+gxsp1vjcnBdKvl930neLhW/Xk9cztUf2ZFa0GnR1yND+wWz+dWruxR1RvdoiMsHHy15Ju2+QcVgmIovYu3DtPx0HlfPrYo0oZ4OkOAAl+d5w1sh159JzuU1z9CZvqGuhYI09srYi/XEmaNoUSe82e3Z25YoaUqDABfT9qkdEHOZOmD+9rlnZI2hEDD3cNRmyS+sJi/dWFRMXnkQvg5P4bOXmaTAs7Trnp0Lj/k9zWeTbFXrAH3XNkwmOREM0PbnhfS2hgPq1CTQ0AsfuT45Vdys4nZ/LSaLHNxEHh9Es3I6aNjsFRCg9VDDZgNTw9SjjnRA+nc/2rcV0oStfA8hSyqcFzjUdpwDMw2IIiZHnFa0FfGTpV4OiUsMPO/gpe150Wu3xBSoRwYeHZjToqLYc/LGjEWyFHEt4QDRPhT0RiwYn5C8uuWXVmWB+b07FYtdNnWLSnVFD2/ZFKPE5irx7hDEnlRF2ZiEv4N+bHgnK1o87E6cCtoM4D449irGQ0Hc4rPByJOurJz9HBiIqNI3YH6/QzXlEqj/Z3WB+Aa92LOVhEgW/l3lyBjMd8KDZMU0pceZjQaJFdQnShtyvBYjsVSes3MO5dGDWgKSOOkbus7AeydOWKKxC25zo0lDiXyt0cMBqzAjdBFe8/6b8d1zwhXS/sSSYHh8syTA6ChrNLWheltfRtL9B8Diz6aICd5ezZn/CeHHXd9+I4PhKsOsaXebFMlYCYvjoahEJBbFvdH/6z8+1hEhqMAtPyweRe4WrJOM/KXK0gZjhuXBrhPJ3q6GHNiiOuzyoe62gr5dtlB0R4rhMX/5MDfDFswuOO5wG2H+3ryj+s40STZB62HZg5G8DidKA5xJ1rqqurzNncj1ZfwxQ+Vs5WXlbxsKNfinNwVqh0Or8Qts7PK54FJXTjqp2Ibj7ksNGD0tJTIRq7JK4hbIbq+o2zwd3jjRpqVIeSBwVOuoxY1MLvW63AZJVPOvRqNVP4MOo0RAtyfk4MnB7iJbGI0j/J+CJa5UqsBdqiQ1eUKg4G8+36iLbxe5KYgxIL4P9928ec+A54R2b1FDI8TUZUStwKbR2LqSoPalTE7Xt7n1pDT07VgrKVwIn/nM2T/51KU/g4j7pF1XqaxbpGKjuBV+68TPKQ3AI/sHKg5FWoNsf8qUylPXZ2d1LV6LvO3Ji9IwFhysDbCK+mUM95f+1LzRukdm81ZpzBZFzibpuXQR8IbLM5MjdRJRnQE2zXij4RumDQVOXJr+Cy1aY1poRijDqdzZ/6jWP1D8YEtHlgAUTew+llgFOz/88h9wNYEBljb2FBjKlWwolsrtBwRC9ylJm0zCrpmLp0VDpirnZ1OLIhCFYrqTDKcfCl6ydNr9zV2ByLjJaTadGc4OK6p95MeY88k0g4epE3lm04aU9ffQU4LnkVOI3mGpJMOoKn0hO9vlS9oRtac+D+zpZHmoK+HC97/NZN9confX8WGSEaFneyUbPRwrcdVWMfAqf3bXRfWzlMum3KV96yU9XeSdifJW2nBEkF9siNExDYDQLVKCnIaaT5NrjICVcwIeQf8ZuqNO1qdtm2LemRYSx/bu+gSX6SIduQ5zrSngTpb50fyo0TvuOkTq7e2p/dpOwFwlISvnskJcx8eNz5dUQ8f+MgEzhmQiwtBTJtnrYft/J3lCvszHr5q01ctOXxbEn1K/lJezzC/6H089+OLFsICiUAQsyKydG+46wWF7bGNo8jD7fiv24ALvTiwbY71dDZ0NdvM3gVxS/0fSnmVGk2IRTUgWW7bR1eAKPtCjw88CGnuZ/Mc4hdxD/enxL8tBolZ0jtL5PF1/nSfZ1cH/yk2hpXu1yDNCH0c+6n7ji4FkcxyNpklnRV8yJj2w3i9KW1/fwvihu/RCKPPftoMlPuzg1ri9Q3yPYBTr/4AEKtM2bJW+vv0SmtCMTGkmuzThYgTBTPIsYUuEU8TR2nC8EcsUAXTKcHKMKBXpgzVjcz1X2AkpH9yigwTlbo7Line truncated
<rect width="800" height="64" fill="#fbf8ef" />
<g fill="#082f55" font-family="Arial, sans-serif" font-size="25" font-weight="700" text-anchor="middle" direction="rtl">
<text x="132" y="43">المُقدِّمة</text>
<text x="400" y="43">السلوك</text>
<text x="668" y="43">النتيجة اللاحقة</text>
</g>
<g fill="none" stroke="#082f55" stroke-linecap="round" stroke-linejoin="round" stroke-width="4">
<path d="M235 37h60m-12-11 12 11-12 11" />
<path d="M507 37h57m-12-11 12 11-12 11" />
</g>
<rect x="381" y="190" width="50" height="24" rx="3" fill="#fff" opacity=".98" />
<text x="406" y="206" fill="#1f2933" font-family="Arial, sans-serif" font-size="9" text-anchor="middle" direction="rtl">المزيد</text>
<rect x="611" y="190" width="65" height="24" rx="3" fill="#fff" opacity=".98" />
<text x="643" y="205" fill="#1f2933" font-family="Arial, sans-serif" font-size="7" text-anchor="middle" direction="rtl">دقيقتان إضافيتان</text>
<rect x="531" y="351" width="255" height="91" rx="12" fill="#e8efe8" />
<g fill="#082f55" font-family="Arial, sans-serif" font-size="14" direction="rtl" text-anchor="middle">
<text x="658" y="374">◷ حصلتَ على دقيقتين إضافيتين.</text>
<text x="658" y="399">← ثم ينتهي الوقت.</text>
<text x="658" y="424">▣ تستمر خطة «أولًا/ثم».</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Loaded 100 of 679 files, more files were not shown because too many files have changed in this diff. Show more