Compare commits

...

13 Commits

Author SHA1 Message Date
DeCentN2Madness 4a6b8a20e5 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-11 19:08:48 -07:00
DeCentN2Madness 965c090782 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-11 14:26:02 -07:00
DeCentN2Madness a163ff98c9 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-11 13:56:25 -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
DeCentN2Madness 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
39 changed files with 731 additions and 281 deletions
+5 -1
View File
@@ -18,7 +18,11 @@
devShells = forEachSupportedSystem ({ pkgs }: { devShells = forEachSupportedSystem ({ pkgs }: {
default = pkgs.mkShell { default = pkgs.mkShell {
packages = with pkgs; [ node2nix nodejs nodePackages.pnpm yarn ]; packages = with pkgs; [
node2nix nodejs nodePackages.pnpm yarn
python3
fd
];
}; };
}); });
}; };
+29
View File
@@ -215,6 +215,35 @@ 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 extension. Open the `www` folder as the editor workspace so its content folders
and media paths resolve correctly. 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
financialHelp
process
director
testimonials
```
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.
### Images And Downloads ### Images And Downloads
Store content-referenced assets in: Store content-referenced assets in:
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+1 -1
View File
@@ -1,3 +1,3 @@
# Broken Links # Broken Links
Rendered output is unavailable in the sandbox; source routes and public assets were audited. No broken internal source links were detected. No broken internal build links detected.
+2
View File
@@ -18,6 +18,8 @@
- Rebuilt the homepage in the live section order and rebuilt shared service, - Rebuilt the homepage in the live section order and rebuilt shared service,
library-index, and blog-post families against live public references. library-index, and blog-post families against live public references.
- Reused the same complete live-derived homepage layout for English and Spanish. - Reused the same complete live-derived homepage layout for English and Spanish.
- Reorganized the homepage source into named `home:` frontmatter blocks so the
content is easier to inspect and edit without changing the rendered layout.
- Replaced the extracted linear team article with a dedicated live-derived team grid. - Replaced the extracted linear team article with a dedicated live-derived team grid.
- Repaired mirror-rewritten PDF, lightbox, CTA, and relative content links. - Repaired mirror-rewritten PDF, lightbox, CTA, and relative content links.
- Limited language-switcher choices to translations that have generated routes. - Limited language-switcher choices to translations that have generated routes.
+2
View File
@@ -35,6 +35,8 @@ Implemented fidelity work includes:
utility links, footer columns, and contact information. utility links, footer columns, and contact information.
- Rebuilt the complete English and Spanish homepages in their live section - Rebuilt the complete English and Spanish homepages in their live section
order using one reusable Astro component and self-hosted source assets. order using one reusable Astro component and self-hosted source assets.
- Moved the English and Spanish homepage copy into section-oriented `home:`
frontmatter blocks so the page is easier to edit in Front Matter CMS.
- Rebuilt service pages around the live compact title banner and editorial - Rebuilt service pages around the live compact title banner and editorial
presentation, with current visible headings and working calls to action. presentation, with current visible headings and working calls to action.
- Recovered and restored the live decorative hero imagery for all mapped - Recovered and restored the live decorative hero imagery for all mapped
+39
View File
@@ -0,0 +1,39 @@
---
---
<div class="about-page">
<section class="about-section section">
<div class="container">
<h2>Our Story</h2>
<p>The Arizona Institute for Autism (AIA) was founded in 2018 by Clinical Director Rula Diab, M.Ed, BCBA, LBA. Ms. Diab is an industry expert with over 15 years of experience in the field of Special Education and Behavioral Analysis.</p>
<p>As the founder and Clinical Director, Rula Diab, leads the Arizona Institute for Autism's clinical efforts, community outreach, and managing network programming with current local businesses including Arizona State University and Phoenix School District. As a Special Education expert, Ms. Diab works with practitioners, academics, policymakers, teachers, families, and, most importantly, children with developmental disabilities throughout Arizona. After noticing gaps in the way practitioners applied ABA principles, Rula pioneered the AIA model of education, a model centered on recognizing each child's individuality and dignity by cultivating their natural interests, preferences, and motivators. Education doesn't have to be boring, and that should be the case for all children.</p>
</div>
</section>
<section class="about-section section section-tint">
<div class="container">
<h2>Our Mission</h2>
<p>At AIA, our mission is to improve special education and strengthen communities throughout Arizona. Every day, our team of highly trained clinicians, paraprofessionals, educators, and consultants works with one goal in mind: to support the behavioral and educational development of our 'kiddos' in every way possible.</p>
<p>We accomplish this by delivering clinical treatments, including ABA therapy services, and educational support to children with Autism Spectrum Disorder and other developmental disorders. And since every child is unique, we work with each family differently to understand their individual needs before we apply our insights through customized programs.</p>
<p>We also bring our 'can-do' mentality to the classroom. AIA works hand-in-hand with SPED teachers and school leaders to address their unique challenges and enhance the classroom environment for their students. Our staff believes that, with the right resources &amp; support, every child can achieve their potential. So, every day, we do everything we can to support each one of our 'kiddos' in the pursuit of their individual potential.</p>
</div>
</section>
<section class="about-section section">
<div class="container">
<h2>Our Commitment</h2>
<ul class="commitment-list">
<li><strong>Integrity</strong> — Integrity is the essence of who we are and at the foundation of everything we do. We approach our relationships with integrity and always adhere to the highest ethical principles.</li>
<li><strong>Empowerment</strong> — A heart that serves and empowers others is essential to our success. We are passionate about motivating and encouraging our kiddos and learners for success.</li>
<li><strong>Excellence</strong> — At AIA, we strive for excellence in everything we do. We go above and beyond in providing results to support our community partners, customers, kiddos, and everyone in the AIA family.</li>
</ul>
</div>
</section>
</div>
<style>
.about-section h2 { margin-top: 0; }
.about-section p { max-width: 820px; }
.commitment-list { list-style: none; max-width: 820px; padding: 0; }
.commitment-list li { border-left: 4px solid var(--color-accent); margin-bottom: 1.5rem; padding-left: 1.25rem; }
.commitment-list li:last-child { margin-bottom: 0; }
</style>
+27 -1
View File
@@ -1,4 +1,5 @@
--- ---
import LikeViewCounter from './LikeViewCounter.astro';
const { post, prefix = '' } = Astro.props; const { post, prefix = '' } = Astro.props;
const href = `${prefix}/library/${post.data.slug}`.replace('//', '/'); const href = `${prefix}/library/${post.data.slug}`.replace('//', '/');
const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد' }[post.data.lang] || 'Read More'; const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد' }[post.data.lang] || 'Read More';
@@ -9,6 +10,31 @@ const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد'
<div class="blog-card-meta"><img src="/assets/images/rula-diab-avatar.jpg" alt="" /><p>Rula Diab, Clinical Director, M.Ed, BCBA, LBA<br /><time datetime={post.data.date.toISOString()}>{post.data.date.toLocaleDateString(post.data.lang, { day: 'numeric', month: 'long', year: 'numeric' })}</time></p></div> <div class="blog-card-meta"><img src="/assets/images/rula-diab-avatar.jpg" alt="" /><p>Rula Diab, Clinical Director, M.Ed, BCBA, LBA<br /><time datetime={post.data.date.toISOString()}>{post.data.date.toLocaleDateString(post.data.lang, { day: 'numeric', month: 'long', year: 'numeric' })}</time></p></div>
<h3><a href={href}>{post.data.title}</a></h3> <h3><a href={href}>{post.data.title}</a></h3>
<p>{post.data.description}</p> <p>{post.data.description}</p>
<a class="text-link" href={href}>{readMore}</a> <div class="blog-card-footer" style="align-items:center;display:flex;justify-content:space-between;gap:var(--space-lg);margin-top:auto;">
<a class="text-link" href={href}>{readMore}</a>
<LikeViewCounter slug={post.data.slug} />
</div>
</div> </div>
</article> </article>
<style>
.blog-card-meta { align-items: center; display: flex; font-size: .78rem; gap: .75rem; }
.blog-card-meta img { aspect-ratio: 1; border-radius: 50%; height: 42px; width: 42px; }
.blog-card { background: white; border: 0; border-radius: 4px; box-shadow: rgba(54, 48, 48, 0.28) 0 0 12px 0; display: flex; margin-bottom: 40px; overflow: hidden; }
.blog-card > a { flex: 0 0 232px; display: block; margin: .75rem; }
.blog-card > a img { aspect-ratio: auto; display: block; height: 100%; object-fit: cover; width: 100%; }
.blog-card .card-body { display: flex; flex: 1; flex-direction: column; gap: 0; padding: 20px; }
.blog-card .card-body h3 { font-family: var(--font-body); }
.blog-card-footer { align-items: center; display: flex; justify-content: space-between; gap: var(--space-lg); margin-top: auto; }
:global(.blog-card .like-view-counter) { border-top: 0; justify-content: space-between; margin-block: 0; padding-top: 0; width: auto; }
.blog-card h3 { font-size: 1.35rem; margin-bottom: 1rem; }
.blog-card p { margin-bottom: 1rem; }
.blog-card .text-link { margin: 0; }
@media (max-width: 760px) {
.blog-card { flex-direction: column; }
.blog-card > a { flex-basis: auto; }
.blog-card > a img { height: auto; aspect-ratio: 4 / 3; }
.blog-card-footer { align-items: flex-start; flex-direction: column; }
}
</style>
+5
View File
@@ -4,3 +4,8 @@
<a class="button button-light" href="/client-consultation">Schedule a Free Consultation</a> <a class="button button-light" href="/client-consultation">Schedule a Free Consultation</a>
</div> </div>
</section> </section>
<style>
.cta-band { background: var(--color-primary); color: white; padding-block: var(--space-xl); }
.cta-band h2, .cta-band .eyebrow { color: white; margin: 0; }
</style>
+53 -7
View File
@@ -28,13 +28,34 @@ const labels = lang === 'es'
</div> </div>
<div> <div>
<h2>{labels.contact}</h2> <h2>{labels.contact}</h2>
<p><a href={`tel:${site.phone.replace(/\D/g, '')}`}>{site.phone}</a><br /><a href={`mailto:${site.email}`}>{site.email}</a><br />{site.address}</p> <div class="footer-contact">
<p class="social-links"> <div class="footer-contact-item">
<a href={site.social.facebook} aria-label="Facebook">f</a> <img src="/assets/images/phone-blue.svg" alt="" aria-hidden="true" width="24" height="24" />
<a href={site.social.instagram} aria-label="Instagram">◎</a> <a href={`tel:${site.phone.replace(/\D/g, '')}`}>{site.phone}</a>
<a href={site.social.linkedin} aria-label="LinkedIn">in</a> </div>
<a href={site.social.youtube} aria-label="YouTube">▶</a> <div class="footer-contact-item">
</p> <img src="/assets/images/envelope-blue.svg" alt="" aria-hidden="true" width="24" height="24" />
<a href={`mailto:${site.email}`}>{site.email}</a>
</div>
<div class="footer-contact-item">
<img src="/assets/images/location-blue.svg" alt="" aria-hidden="true" width="24" height="24" />
<address>{site.address}</address>
</div>
</div>
<div class="social-links">
<a href={site.social.facebook} target="_blank" rel="noopener" aria-label="Facebook">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="30" height="30" fill="var(--color-accent)" aria-hidden="true"><path d="M448 56.7v398.5c0 13.7-11.1 24.7-24.7 24.7H309.1V306.5h58.2l8.7-67.6h-67v-43.2c0-19.6 5.4-32.9 33.5-32.9h35.8v-60.5c-6.2-.8-27.4-2.7-52.2-2.7-51.6 0-87 31.5-87 89.4v49.9h-58.4v67.6h58.4V480H24.7C11.1 480 0 468.9 0 455.3V56.7C0 43.1 11.1 32 24.7 32h398.5c13.7 0 24.8 11.1 24.8 24.7z"/></svg>
</a>
<a href={site.social.instagram} target="_blank" rel="noopener" aria-label="Instagram">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="30" height="30" fill="var(--color-accent)" aria-hidden="true"><path d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"/></svg>
</a>
<a href={site.social.linkedin} target="_blank" rel="noopener" aria-label="LinkedIn">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="30" height="30" fill="var(--color-accent)" aria-hidden="true"><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/></svg>
</a>
<a href={site.social.youtube} target="_blank" rel="noopener" aria-label="YouTube">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="30" height="30" fill="var(--color-accent)" aria-hidden="true"><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
</a>
</div>
</div> </div>
</div> </div>
<div class="container footer-bottom"> <div class="container footer-bottom">
@@ -42,3 +63,28 @@ const labels = lang === 'es'
<p><a href="/privacy-policy">Privacy Policy</a> | <a href="/faqs">FAQ</a></p> <p><a href="/privacy-policy">Privacy Policy</a> | <a href="/faqs">FAQ</a></p>
</div> </div>
</footer> </footer>
<style>
.site-footer { background: var(--color-primary-dark); color: white; padding-block: var(--space-xl) var(--space-md); }
.footer-grid { display: grid; gap: var(--space-xl); grid-template-columns: 1fr 1fr 1.5fr; }
.site-footer h2, .site-footer a { color: white; text-decoration: none; }
.site-footer h2 { font-size: 1.25rem; letter-spacing: .3px; margin-bottom: 1.2rem; }
.site-footer a:hover { color: var(--color-accent); }
.site-footer ul { list-style: none; padding: 0; }
.site-footer li { line-height: 2.6; margin-bottom: 0; }
.site-footer p { line-height: 2.6; }
.footer-contact { display: flex; flex-direction: column; gap: 1rem; margin-bottom: 2rem; margin-top: 2rem; }
.footer-contact-item { align-items: flex-start; display: flex; gap: .6rem; line-height: 1.5; }
.footer-contact-item img { flex-shrink: 0; }
.footer-contact-item address { font-style: normal; }
.social-links { display: flex; gap: .85rem; margin-left: 1.6rem; margin-top: .25rem; }
.social-links a { align-items: center; color: white; display: flex; opacity: .85; }
.social-links a:hover { color: var(--color-accent); opacity: 1; }
.footer-bottom { border-top: 1px solid rgb(255 255 255 / 20%); display: flex; justify-content: space-between; margin-top: var(--space-lg); padding-top: var(--space-md); }
@media (max-width: 950px) {
.footer-grid { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
.footer-bottom { align-items: flex-start; flex-direction: column; }
}
</style>
+17
View File
@@ -24,3 +24,20 @@ const utility = lang === 'es'
<a class="button button-small" href="/tour">Tour AIA</a> <a class="button button-small" href="/tour">Tour AIA</a>
</div> </div>
</header> </header>
<style>
.utility-bar { background: var(--color-primary); color: white; font-size: .85rem; }
.utility-inner { align-items: center; display: flex; gap: var(--space-md); justify-content: flex-end; min-height: 38px; }
.utility-bar a { color: white; text-decoration: none; }
.site-header { background: white; box-shadow: var(--shadow-sm); position: relative; z-index: 5; }
.header-inner { align-items: center; display: flex; gap: 1.4rem; min-height: 110px; }
.brand img { width: 150px; }
@media (max-width: 950px) {
.header-inner > .button { display: none; }
}
@media (max-width: 760px) {
.utility-inner { justify-content: center; }
.header-inner { min-height: 88px; }
.header-inner .lang-switcher { margin-left: auto; }
}
</style>
+9
View File
@@ -13,3 +13,12 @@ const { title, eyebrow, description, image, alt = '' } = Astro.props;
{image && <img src={image} alt={alt} loading="eager" />} {image && <img src={image} alt={alt} loading="eager" />}
</div> </div>
</section> </section>
<style>
.hero { background: var(--color-tint); overflow: hidden; padding-block: clamp(3rem, 7vw, 5rem); }
.hero-grid { align-items: center; display: grid; gap: var(--space-xl); grid-template-columns: 1.05fr .95fr; }
.hero img { max-height: 430px; object-fit: contain; width: 100%; }
@media (max-width: 950px) {
.hero-grid { grid-template-columns: 1fr; }
}
</style>
+46 -13
View File
@@ -11,26 +11,59 @@ import HomeProcess from './home/HomeProcess.astro';
import HomeServicesIntro from './home/HomeServicesIntro.astro'; import HomeServicesIntro from './home/HomeServicesIntro.astro';
import HomeSkills from './home/HomeSkills.astro'; import HomeSkills from './home/HomeSkills.astro';
import HomeTestimonials from './home/HomeTestimonials.astro'; import HomeTestimonials from './home/HomeTestimonials.astro';
import type { HomeSection } from '../types/home-sections'; import type { HomePageContent, HomeSection } from '../types/home-sections';
interface Props { lang?: string } interface Props { lang?: string }
const { lang = 'en' } = Astro.props; const { lang = 'en' } = Astro.props;
const es = lang === 'es'; const es = lang === 'es';
const entry = await getEntry('pages', es ? 'es/index' : 'en/index'); const entry = await getEntry('pages', es ? 'es/index' : 'en/index');
if (!entry) throw new Error(`[HomePage] Content entry not found for lang="${lang}". If running in dev, restart the dev server to rebuild the content layer cache.`); if (!entry) throw new Error(`[HomePage] Content entry not found for lang="${lang}". If running in dev, restart the dev server to rebuild the content layer cache.`);
const { title, description, canonical, sections = [] } = entry.data; const { title, description, canonical } = entry.data;
function fromHomeContent(home: HomePageContent): HomeSection[] {
return [
{ type: 'hero', ...home.hero },
{ type: 'services-intro', ...home.servicesIntro },
{ type: 'benefits', ...home.benefits },
{ type: 'skills', ...home.skills },
{ type: 'insurance', ...home.insurance },
{ type: 'esa', ...home.esa },
{ type: 'financial-help', ...home.financialHelp },
{ type: 'process', ...home.process },
{ type: 'director', ...home.director },
{ type: 'testimonials', ...home.testimonials },
];
}
const sections: HomeSection[] = entry.data.home
? fromHomeContent(entry.data.home)
: ((entry.data.sections ?? []) as HomeSection[]);
--- ---
<BaseLayout {title} {description} {canonical} {lang}> <BaseLayout {title} {description} {canonical} {lang}>
{(sections as HomeSection[]).map((section) => { {sections.map((section) => {
if (section.type === 'hero') return <HomeHero section={section} />; switch (section.type) {
if (section.type === 'services-intro') return <HomeServicesIntro section={section} />; case 'hero':
if (section.type === 'benefits') return <HomeBenefits section={section} />; return <HomeHero section={section} />;
if (section.type === 'skills') return <HomeSkills section={section} />; case 'services-intro':
if (section.type === 'insurance') return <HomeInsurance section={section} />; return <HomeServicesIntro section={section} />;
if (section.type === 'esa') return <HomeEsa section={section} />; case 'benefits':
if (section.type === 'financial-help') return <HomeFinancialHelp section={section} />; return <HomeBenefits section={section} />;
if (section.type === 'process') return <HomeProcess section={section} />; case 'skills':
if (section.type === 'director') return <HomeDirector section={section} />; return <HomeSkills section={section} />;
if (section.type === 'testimonials') return <HomeTestimonials section={section} />; case 'insurance':
return <HomeInsurance section={section} />;
case 'esa':
return <HomeEsa section={section} />;
case 'financial-help':
return <HomeFinancialHelp section={section} />;
case 'process':
return <HomeProcess section={section} />;
case 'director':
return <HomeDirector section={section} />;
case 'testimonials':
return <HomeTestimonials section={section} />;
default:
return null;
}
})} })}
</BaseLayout> </BaseLayout>
+7
View File
@@ -4,3 +4,10 @@ const logos = ['aetna.png', 'bluecrossblueshield-logo-1.webp', 'logo-ahcccs.webp
<section class="insurance-strip" aria-labelledby="insurance-title"> <section class="insurance-strip" aria-labelledby="insurance-title">
<div class="container"><h2 id="insurance-title">Insurance partners</h2><div class="logo-row">{logos.map((logo) => <img src={`/assets/images/${logo}`} alt="" loading="lazy" />)}</div></div> <div class="container"><h2 id="insurance-title">Insurance partners</h2><div class="logo-row">{logos.map((logo) => <img src={`/assets/images/${logo}`} alt="" loading="lazy" />)}</div></div>
</section> </section>
<style>
.insurance-strip { background: white; border-block: 1px solid var(--color-border); padding-block: var(--space-lg); text-align: center; }
.insurance-strip h2 { font-size: 1.4rem; }
.logo-row { align-items: center; display: flex; flex-wrap: wrap; justify-content: space-around; }
.logo-row img { filter: grayscale(1); max-height: 55px; max-width: 130px; }
</style>
+12
View File
@@ -51,3 +51,15 @@ const activeShort = langMeta[activeCode]?.short ?? 'EN';
))} ))}
</ul> </ul>
</nav> </nav>
<style>
.lang-switcher { position: relative; }
.lang-switcher__trigger { align-items: center; color: var(--color-primary); cursor: pointer; display: flex; font-size: .85rem; font-weight: 700; gap: .35rem; }
.lang-switcher__trigger svg { flex-shrink: 0; }
.lang-switcher__menu { background: white; box-shadow: var(--shadow-md); display: none; left: 50%; list-style: none; margin: 0; min-width: 110px; padding: .5rem 0 .4rem; position: absolute; top: 100%; transform: translateX(-50%); z-index: 10; }
.lang-switcher__menu a { color: rgb(83 83 91); display: block; font-size: .85rem; padding: .4rem .9rem; text-decoration: none; white-space: nowrap; }
.lang-switcher__menu a:hover { background: var(--color-primary); color: white; }
.lang-switcher__menu a[aria-current="page"] { color: var(--color-accent); font-weight: 700; }
.lang-switcher:hover .lang-switcher__menu,
.lang-switcher:focus-within .lang-switcher__menu { display: block; }
</style>
+30 -6
View File
@@ -1,11 +1,16 @@
--- ---
const { slug } = Astro.props; const { slug } = Astro.props;
--- ---
<div class="like-view-counter likes-views" data-counter> <div class="like-view-counter" data-counter>
<button class="like-button" type="button" data-like data-slug={slug} aria-label="Like this article" aria-pressed="false"> <span aria-label="Article views"><span class="view-count" data-views>0</span> views</span>
<span aria-hidden="true">♡</span> <span class="like-count" data-likes>—</span> <span class="like-group">
</button> <span class="like-count" data-likes>—</span>
<span aria-label="Article views">Views: <span class="view-count" data-views>—</span></span> <button class="like-button" type="button" data-like data-slug={slug} aria-label="Like this article" aria-pressed="false">
<svg aria-hidden="true" viewBox="0 0 12 10" width="20" height="20" focusable="false" class="like-icon">
<path d="m1 4.4c-1-4 2.5-5 4.5-2.5l.5 .6l.5-.6c2-2.5 6-1.5 4.5 2.5q-1 3-5 5q-4-2-5-5z"></path>
</svg>
</button>
</span>
</div> </div>
<script> <script>
const apiBase = import.meta.env.PUBLIC_AIA_API_BASE || 'https://api.azinstitute4autism.com'; const apiBase = import.meta.env.PUBLIC_AIA_API_BASE || 'https://api.azinstitute4autism.com';
@@ -44,6 +49,14 @@ const { slug } = Astro.props;
const views = counter.querySelector<HTMLElement>('[data-views]'); const views = counter.querySelector<HTMLElement>('[data-views]');
if (!button || !slug) return; if (!button || !slug) return;
const isLocalhost = ['localhost', '127.0.0.1', '::1'].includes(window.location.hostname);
if (isLocalhost) {
counter.dataset.unavailable = 'true';
if (likes) likes.textContent = '0';
if (views) views.textContent = '0';
return;
}
const cookieName = `liked_${slug}`; const cookieName = `liked_${slug}`;
const renderLiked = (liked: boolean) => { const renderLiked = (liked: boolean) => {
button.classList.toggle('liked', liked); button.classList.toggle('liked', liked);
@@ -66,7 +79,7 @@ const { slug } = Astro.props;
} catch { } catch {
counter.dataset.unavailable = 'true'; counter.dataset.unavailable = 'true';
if (likes) likes.textContent = '0'; if (likes) likes.textContent = '0';
if (views) views.textContent = ''; if (views) views.textContent = '0';
} }
button.addEventListener('click', async () => { button.addEventListener('click', async () => {
@@ -96,3 +109,14 @@ const { slug } = Astro.props;
}); });
}); });
</script> </script>
<style>
.like-view-counter { align-items: center; border-top: 1px solid var(--color-border); display: flex; gap: var(--space-lg); font-size: .75rem; margin-block: var(--space-xl); padding-top: var(--space-md); }
.like-view-counter { font-size: .8rem; }
.like-group { align-items: center; display: inline-flex; gap: .35rem; }
.like-view-counter button { align-items: center; background: white; border: none; color: inherit; display: inline-flex; gap: 0; padding: 0; }
.like-view-counter .like-count { color: var(--color-text); min-width: 1ch; }
.like-view-counter .like-icon { fill: none; flex: 0 0 auto; stroke: #d92d20; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.6; }
.like-view-counter button.liked .like-icon { fill: #d92d20; stroke: #d92d20; }
.like-view-counter button:disabled { cursor: wait; opacity: .65; }
</style>
+4
View File
@@ -2,3 +2,7 @@
const { title = 'Scottsdale', address = '8901 E Raintree Dr Ste 160, Scottsdale, AZ 85260' } = Astro.props; const { title = 'Scottsdale', address = '8901 E Raintree Dr Ste 160, Scottsdale, AZ 85260' } = Astro.props;
--- ---
<article class="card location-card"><h3>{title}</h3><p>{address}</p><a class="text-link" href={`https://maps.google.com/?q=${encodeURIComponent(address)}`}>Get directions</a></article> <article class="card location-card"><h3>{title}</h3><p>{address}</p><a class="text-link" href={`https://maps.google.com/?q=${encodeURIComponent(address)}`}>Get directions</a></article>
<style>
.location-card { padding: var(--space-lg); }
</style>
+16
View File
@@ -22,3 +22,19 @@ const aboutLinks = lang === 'es'
))} ))}
</ul> </ul>
</nav> </nav>
<style>
.main-nav { margin-inline: auto; }
.main-nav ul { display: flex; gap: 1.4rem; list-style: none; margin: 0; padding: 0; }
.main-nav li { position: relative; }
.main-nav a { color: var(--color-primary); font-size: .9rem; text-decoration: none; }
.main-nav a:hover { color: var(--color-accent-strong); }
.main-nav .submenu { background: white; box-shadow: var(--shadow-md); display: none; gap: 0; left: -1rem; min-width: 180px; padding: .75rem 0; position: absolute; top: 100%; }
.main-nav .submenu a { display: block; padding: .45rem 1rem; }
.main-nav li:hover > .submenu, .main-nav li:focus-within > .submenu { display: block; }
@media (max-width: 950px) {
.main-nav { display: none; }
:global(.mobile-nav) .main-nav { display: block; }
:global(.mobile-nav) .main-nav ul { align-items: flex-start; flex-direction: column; padding: var(--space-md); }
}
</style>
+7
View File
@@ -6,3 +6,10 @@ const { lang = 'en' } = Astro.props;
<summary>Menu</summary> <summary>Menu</summary>
<MainNav lang={lang} /> <MainNav lang={lang} />
</details> </details>
<style>
.mobile-nav { display: none; }
@media (max-width: 950px) {
.mobile-nav { display: block; }
}
</style>
+33
View File
@@ -0,0 +1,33 @@
---
interface Props {
title: string;
image?: string;
eyebrow?: string;
constrain?: boolean;
}
const { title, image, eyebrow, constrain = false } = Astro.props;
---
<header class:list={['page-hero', { 'page-hero--image': image, 'page-hero--constrained': image && constrain }]} style={image ? `--hero-image: url("${image}")` : undefined}>
<div class="container">
{eyebrow
? <div class="page-hero__copy"><p class="script-label">{eyebrow}</p><h1>{title}</h1></div>
: <h1>{title}</h1>
}
</div>
</header>
<style>
.page-hero { background: var(--color-tint); padding-block: 4rem; text-align: center; }
.page-hero h1 { margin: 0; }
.page-hero--image { background-image: var(--hero-image); background-position: center; background-repeat: no-repeat; background-size: cover; max-height: 420px; padding-block: 0; text-align: left; }
.page-hero--image > .container { padding-block: 10rem; }
.page-hero--image h1 { max-width: 600px; }
.page-hero__copy { max-width: 600px; }
.page-hero--constrained { background-image: var(--hero-image), linear-gradient(var(--color-tint), var(--color-tint)); background-clip: content-box, border-box; background-origin: content-box, border-box; background-position: center, center; background-repeat: no-repeat, repeat; background-size: cover, auto; padding-inline: max(0px, calc((100% - var(--container-w)) / 2)); }
@media (max-width: 760px) {
.page-hero--image > .container { padding-block: 6.25rem; }
.page-hero--image { text-align: center; }
.page-hero--image h1, .page-hero__copy { margin-inline: auto; }
}
</style>
+78
View File
@@ -0,0 +1,78 @@
---
import Button from './Button.astro';
---
<style>
.services-intro { padding-block: 5rem 1.25rem; }
.services-intro-cta { margin-top: 2rem; text-align: center; }
.services-cards-section { background: var(--color-primary); padding-block: 3rem; }
.services-cards-section h2 { color: white; margin-top: 0; text-align: center; }
.services-cards-desc { color: white; margin-bottom: 2rem; }
.service-cards-grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
.service-card-link { background-color: var(--color-accent); background-position: center; background-repeat: no-repeat; background-size: cover; border-radius: 6px; display: block; padding: 20% 2rem 2rem; text-align: center; text-decoration: none; transition: all .3s ease-in-out; }
.service-card-link:hover { transform: scale(1.05); }
.service-card-link:hover .service-card-title { background: #fffc; border-color: var(--color-accent-strong); color: var(--color-primary) !important; }
.service-card-title { background: var(--color-accent); border: 2px solid var(--color-accent); border-radius: var(--radius-sm); color: var(--color-primary) !important; display: inline-block; font-family: var(--font-body); font-size: 1rem; font-weight: 600; line-height: 1.5; margin: 0; padding: .65rem 1.2rem; position: relative; top: .15rem; white-space: nowrap; }
.services-diagnosis-section { margin-block: 6rem; }
.services-diagnosis-card { background: var(--color-tint); border-radius: 6px; padding: 2rem 1.25rem; }
.services-diagnosis-inner { align-items: center; display: flex; flex-direction: column; gap: 2rem; justify-content: space-between; }
.services-diagnosis-text h2 { margin-top: 0; }
.services-diagnosis-text p { margin-bottom: 0; }
.services-diagnosis-btn { min-width: fit-content; }
@media (min-width: 768px) { .service-cards-grid { gap: 30px; grid-template-columns: repeat(2, 1fr); } .services-diagnosis-card { padding: 4.375rem; } .services-diagnosis-inner { flex-direction: row; } }
@media (min-width: 768px) and (max-width: 1023px) { .service-card-link:last-child { grid-column: 1 / -1; margin-inline: auto; padding-top: calc(10% - 3px); width: calc(50% - 15px); } }
@media (min-width: 1024px) { .service-cards-grid { grid-template-columns: repeat(3, 1fr); } .service-card-link { padding-top: 42%; } }
</style>
<section class="services-intro">
<div class="container">
<h2>Autism Spectrum Disorder Services</h2>
<p>Autism Spectrum Disorder (ASD) refers to a group of complex brain development disorders and is characterized by difficulties with social interaction, verbal and non-verbal communication, and emotional control.</p>
<p>The Arizona Institute for Autism helps with Autism Evaluations and Diagnostic Screenings, Applied Behavior Analysis (ABA) Therapy, and Educational Programming tailored to each learner's needs. To support meaningful skill development, we design integrative ABA programs for children diagnosed with autism. We offer both individualized and group ABA Therapy, along with educational services that reflect each child's unique strengths and goals.</p>
<h3>AIA ABA &amp; Educational Options</h3>
<ul>
<li>In-Center</li>
<li>In-School</li>
<li>In-Home</li>
<li>Early Intervention</li>
<li>Academic Readiness</li>
<li>Clinical Supervision</li>
<li>Parent Consultation</li>
</ul>
<h3>Does My Learner Have Autism?</h3>
<p>Approximately 1 in 36 children in the United States will receive an autism diagnosis each year. If your child exhibits any of the behaviors listed above, it is possible that he or she may be diagnosed on the autism spectrum. Diagnosing children with Autism Spectrum Disorder can be challenging and complex. The most important thing you can do is consult a professional if you think your child is displaying atypical behavior.</p>
<p class="services-intro-cta"><Button href="/client-consultation">Consult with a Client Advocate</Button></p>
</div>
</section>
<section class="services-cards-section">
<div class="container">
<h2>Our Services</h2>
<p class="services-cards-desc">Arizona Institute for Autism (AIA) offers a comprehensive range of services tailored to individuals with Autism Spectrum Disorder (ASD). Our programs include early intervention for young children, Applied Behavior Analysis (ABA) therapy, social skills groups, and educational support services. AIA is committed to providing personalized care plans to enhance the quality of life for children with autism and their families.</p>
<div class="service-cards-grid">
<a href="/aba-therapy" class="service-card-link" style="background-image:url('/assets/images/services-card-behavioral.jpg')"><h3 class="service-card-title">Behavioral Services</h3></a>
<a href="/autism-evaluations" class="service-card-link" style="background-image:url('/assets/images/services-card-psychological.jpg')"><h3 class="service-card-title">Psychological Services</h3></a>
<a href="/learner-social-club" class="service-card-link" style="background-image:url('/assets/images/services-card-sociological.jpg')"><h3 class="service-card-title">Sociological Services</h3></a>
</div>
</div>
</section>
<section class="services-diagnosis-section">
<div class="container container-w">
<div class="services-diagnosis-card">
<div class="services-diagnosis-inner">
<div class="services-diagnosis-text">
<h2>Need Autism Diagnosis Support?</h2>
<p>To meet diagnostic criteria for ASD, a child must have persistent deficits in each of three areas of social communication and interaction plus at least two of four types of restricted repetitive behaviors. Consult with a Client Advocate today to receive individual and family support!</p>
</div>
<div class="services-diagnosis-btn">
<Button href="/client-consultation">Get a Free Consultation</Button>
</div>
</div>
</div>
</div>
</section>
+18
View File
@@ -65,3 +65,21 @@ const groups = [
</div> </div>
</section> </section>
</article> </article>
<style>
.team-intro { padding-block: 4rem; text-align: center; }
.team-intro .script-label { font-size: 1.8rem; }
.team-group { padding-block: 2rem 4rem; text-align: center; }
.team-group > h2 { margin: 0 auto 2.5rem; max-width: 760px; }
.team-grid { display: grid; gap: 2rem 1.5rem; grid-template-columns: repeat(4, minmax(0, 1fr)); justify-content: center; }
.team-member img { aspect-ratio: 1 / 1.08; border: 5px solid var(--color-primary-dark); border-radius: 15px; object-fit: cover; width: 100%; }
.team-member h3 { font-size: 1.1rem; margin-bottom: .25rem; }
.team-member p { margin: 0; }
.team-careers { background: var(--color-tint); padding-block: 5rem; text-align: center; }
@media (max-width: 950px) {
.team-grid { grid-template-columns: 1fr; }
}
@media (min-width: 761px) and (max-width: 1050px) {
.team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
</style>
+15
View File
@@ -49,3 +49,18 @@ const { image, alt, videoUrl, videoTitle } = Astro.props;
}); });
}); });
</script> </script>
<style>
.video-card { background: none; border: none; cursor: pointer; display: block; padding: 0; position: relative; }
.video-card img { width: 100%; }
.video-card span { align-items: center; background: var(--color-accent); border-radius: 50%; color: white; display: flex; height: 64px; justify-content: center; left: 50%; position: absolute; top: 50%; transform: translate(-50%, -50%); width: 64px; z-index: 1; }
.video-card::before, .video-card::after { animation-duration: 3s; animation-iteration-count: infinite; animation-name: video-ripple; animation-timing-function: cubic-bezier(.65, 0, .34, 1); border: 8px solid var(--color-accent); border-radius: 50%; content: ""; height: 64px; left: 50%; opacity: 0; position: absolute; top: 50%; width: 64px; }
.video-card::before { animation-delay: .5s; }
.video-dialog { background: none; border: none; box-sizing: border-box; max-width: min(90vw, 900px); padding: 1rem 1rem 0 0; width: 100%; }
.video-dialog::backdrop { background: rgba(0, 0, 0, .85); }
.video-dialog-inner { position: relative; }
.video-dialog-frame { aspect-ratio: 16 / 9; width: 100%; }
.video-dialog-frame iframe { border: none; height: 100%; width: 100%; }
.video-dialog-close { background: white; border: none; border-radius: 50%; cursor: pointer; font-size: 1rem; height: 2rem; line-height: 2rem; position: absolute; right: -1rem; top: -1rem; width: 2rem; }
@keyframes video-ripple { 0% { opacity: 1; transform: translate(-50%, -50%) scale3d(.75, .75, 1); } to { opacity: 0; transform: translate(-50%, -50%) scale3d(1.5, 1.5, 1); } }
</style>
+15 -2
View File
@@ -17,6 +17,17 @@ const { section } = Astro.props;
</div> </div>
</section> </section>
<style>
.process-section h2 { text-align: center; }
.process-grid { display: grid; gap: 1rem; grid-template-columns: repeat(3, 1fr); margin-top: 2.5rem; }
.process-grid div { background: white; min-height: 190px; padding: 3.2rem 1rem; position: relative; text-align: center; transition: transform .3s ease-in-out; }
.process-grid div:hover { transform: scale(1.05); z-index: 1; }
.process-grid img { margin: 0 auto 1rem; width: 42%; }
@media (max-width: 760px) {
.process-grid { grid-template-columns: 1fr 1fr; }
}
</style>
<script> <script>
function equalizeProcessCards() { function equalizeProcessCards() {
const cards = [...document.querySelectorAll('.process-grid > div')] as HTMLElement[]; const cards = [...document.querySelectorAll('.process-grid > div')] as HTMLElement[];
@@ -24,6 +35,8 @@ const { section } = Astro.props;
const max = Math.max(...cards.map(c => c.offsetHeight)); const max = Math.max(...cards.map(c => c.offsetHeight));
if (max > 0) cards.forEach(c => (c.style.height = `${max}px`)); if (max > 0) cards.forEach(c => (c.style.height = `${max}px`));
} }
equalizeProcessCards(); document.fonts.ready.then(() => {
window.addEventListener('resize', equalizeProcessCards); equalizeProcessCards();
window.addEventListener('resize', equalizeProcessCards);
});
</script> </script>
@@ -50,3 +50,14 @@ const { section } = Astro.props;
}, },
}); });
</script> </script>
<style>
.testimonial-section h2 { text-align: center; }
.testimonial-section blockquote { margin: 0 auto; max-width: 720px; padding: 0 2rem; text-align: center; }
.testimonial-author { font-size: 1.25rem; font-weight: 700; margin-bottom: .5rem; }
.testimonial-swiper { --swiper-pagination-bullet-horizontal-gap: 1vw; padding-bottom: 3rem !important; }
.testimonial-swiper .swiper-pagination-bullet { background-color: var(--color-accent); opacity: 1; }
.testimonial-swiper .swiper-pagination-bullet-active { background-color: var(--color-accent-strong); }
.testimonial-swiper .swiper-button-next, .testimonial-swiper .swiper-button-prev { color: var(--color-accent); }
.testimonial-swiper .swiper-button-next:hover, .testimonial-swiper .swiper-button-prev:hover { color: var(--color-accent-strong); }
</style>
+3 -1
View File
@@ -1,5 +1,6 @@
import { defineCollection, z } from 'astro:content'; import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders'; import { glob } from 'astro/loaders';
import { homePageSchema, homeSectionsSchema } from './types/home-sections';
const language = z.enum(['en', 'ar', 'es']); const language = z.enum(['en', 'ar', 'es']);
const shared = { const shared = {
@@ -12,7 +13,8 @@ const shared = {
lang: language, lang: language,
translationKey: z.string().optional(), translationKey: z.string().optional(),
draft: z.boolean().default(false), draft: z.boolean().default(false),
sections: z.array(z.record(z.unknown())).optional() home: homePageSchema.optional(),
sections: homeSectionsSchema.optional()
}; };
const pages = defineCollection({ const pages = defineCollection({
+21 -11
View File
@@ -6,8 +6,9 @@ canonical: "https://www.azinstitute4autism.com/"
lang: "en" lang: "en"
translationKey: "index" translationKey: "index"
draft: false draft: false
sections: home:
- type: hero # Hero
hero:
eyebrow: "Arizona's Leading Experts" eyebrow: "Arizona's Leading Experts"
heading: "Behavioral Health<br />&amp; Special<br />Education" heading: "Behavioral Health<br />&amp; Special<br />Education"
body: "Here at the Arizona Institute for Autism (AIA), we provide expert clinical care for children and teens who have an autism diagnosis. We currently serve families in Scottsdale, Gilbert, Mesa, Tempe, and Phoenix Metropolitan areas." body: "Here at the Arizona Institute for Autism (AIA), we provide expert clinical care for children and teens who have an autism diagnosis. We currently serve families in Scottsdale, Gilbert, Mesa, Tempe, and Phoenix Metropolitan areas."
@@ -17,7 +18,8 @@ sections:
image: bcba-with-happy-toddler.webp image: bcba-with-happy-toddler.webp
imageAlt: BCBA therapist with happy toddler imageAlt: BCBA therapist with happy toddler
- type: services-intro # Services and commitments
servicesIntro:
servicesHeading: ABA Therapy Services for Children and Teens Diagnosed with Autism Spectrum Disorder servicesHeading: ABA Therapy Services for Children and Teens Diagnosed with Autism Spectrum Disorder
services: services:
- Autism Advocacy Support - Autism Advocacy Support
@@ -42,7 +44,8 @@ sections:
commitmentsImage: playing-boy.webp commitmentsImage: playing-boy.webp
commitmentsImageAlt: Boy playing while learning commitmentsImageAlt: Boy playing while learning
- type: benefits # Benefits
benefits:
heading: Benefits that go Beyond a Typical Integrated Therapy Provider heading: Benefits that go Beyond a Typical Integrated Therapy Provider
subheading: The AIA Difference subheading: The AIA Difference
items: items:
@@ -55,7 +58,8 @@ sections:
videoImage: learner-journey.webp videoImage: learner-journey.webp
videoImageAlt: Learner journey for children with autism video videoImageAlt: Learner journey for children with autism video
- type: skills # Skills
skills:
heading: Does Your Learner Struggle With These Skills? heading: Does Your Learner Struggle With These Skills?
skills: skills:
- icon: icon-Social_Engagement.png - icon: icon-Social_Engagement.png
@@ -71,7 +75,8 @@ sections:
- icon: icon-Speach.png - icon: icon-Speach.png
label: Speech label: Speech
- type: insurance # Insurance
insurance:
heading: "Yes, We Take Insurance" heading: "Yes, We Take Insurance"
body: "An all-in-one integrated service for your kiddo's special education needs, the Arizona Institute for Autism (AIA) offers and accepts most insurance plans that cover ABA therapy. These include BCBS AZ, Aetna, Optum, Tricare, United Healthcare AHCCCS, and UnitedHealth." body: "An all-in-one integrated service for your kiddo's special education needs, the Arizona Institute for Autism (AIA) offers and accepts most insurance plans that cover ABA therapy. These include BCBS AZ, Aetna, Optum, Tricare, United Healthcare AHCCCS, and UnitedHealth."
logos: logos:
@@ -88,7 +93,8 @@ sections:
- file: united-healthcare-logo-1.webp - file: united-healthcare-logo-1.webp
alt: United Healthcare alt: United Healthcare
- type: esa # ESA
esa:
heading: Arizona Scholarship Account (ESA) heading: Arizona Scholarship Account (ESA)
body: >- body: >-
Thousands of Arizona learners are currently eligible for the state funded ESA, Thousands of Arizona learners are currently eligible for the state funded ESA,
@@ -100,14 +106,16 @@ sections:
image: logo-az-dept-of-education.webp image: logo-az-dept-of-education.webp
imageAlt: Arizona Department of Education imageAlt: Arizona Department of Education
- type: financial-help # Financial help
financialHelp:
heading: Need Help Paying for Your Care? heading: Need Help Paying for Your Care?
body: The Arizona Institute for Autism offers flexible financial assistance to the uninsured. Get the care you want or need and pay over time. body: The Arizona Institute for Autism offers flexible financial assistance to the uninsured. Get the care you want or need and pay over time.
cta: cta:
label: Request an Appointment label: Request an Appointment
href: /client-consultation href: /client-consultation
- type: process # Process
process:
heading: Our Process heading: Our Process
steps: steps:
- icon: learner-journey-step-1a.svg - icon: learner-journey-step-1a.svg
@@ -123,7 +131,8 @@ sections:
- icon: learner-journey-step-6.svg - icon: learner-journey-step-6.svg
label: Collaborate on a Care Plan label: Collaborate on a Care Plan
- type: director # Director
director:
heading: An Extension of Your Family heading: An Extension of Your Family
quote: '"At AIA, We strive to provide excellent and compassionate care to all communities we serve. We could not accomplish that without excellent, passionate, and committed staff and families. We look forward to our collaboration with you as we continue to grow, serve and support our Learners in the pursuit of their individual potential."' quote: '"At AIA, We strive to provide excellent and compassionate care to all communities we serve. We could not accomplish that without excellent, passionate, and committed staff and families. We look forward to our collaboration with you as we continue to grow, serve and support our Learners in the pursuit of their individual potential."'
photo: rula-diab.webp photo: rula-diab.webp
@@ -133,7 +142,8 @@ sections:
signature: clinical-director-rula-diab.png signature: clinical-director-rula-diab.png
signatureAlt: Clinical Director Rula Diab signatureAlt: Clinical Director Rula Diab
- type: testimonials # Testimonials
testimonials:
heading: What Clients Are Saying heading: What Clients Are Saying
items: items:
- author: Claudia - author: Claudia
-4
View File
@@ -10,10 +10,6 @@ draft: false
import Button from '../../../components/Button.astro'; import Button from '../../../components/Button.astro';
- [Home](/)
- Services
## Autism Spectrum Disorder Services ## Autism Spectrum Disorder Services
Autism Spectrum Disorder (ASD) refers to a group of complex brain development disorders and is characterized by difficulties with social interaction, verbal and non-verbal communication, and emotional control. Autism Spectrum Disorder (ASD) refers to a group of complex brain development disorders and is characterized by difficulties with social interaction, verbal and non-verbal communication, and emotional control.
+21 -11
View File
@@ -6,8 +6,9 @@ canonical: "https://www.azinstitute4autism.com/es"
lang: "es" lang: "es"
translationKey: "index" translationKey: "index"
draft: false draft: false
sections: home:
- type: hero # Hero
hero:
eyebrow: Los principales expertos de Arizona eyebrow: Los principales expertos de Arizona
heading: "Salud Mental y<br />Educación Especial" heading: "Salud Mental y<br />Educación Especial"
body: "Aquí en el Instituto de Autismo de Arizona (AIA), brindamos atención clínica experta para niños y adolescentes con diagnóstico de autismo. Actualmente atendemos a familias en las áreas metropolitanas de Scottsdale, Gilbert, Mesa, Tempe y Phoenix." body: "Aquí en el Instituto de Autismo de Arizona (AIA), brindamos atención clínica experta para niños y adolescentes con diagnóstico de autismo. Actualmente atendemos a familias en las áreas metropolitanas de Scottsdale, Gilbert, Mesa, Tempe y Phoenix."
@@ -17,7 +18,8 @@ sections:
image: bcba-with-happy-toddler.webp image: bcba-with-happy-toddler.webp
imageAlt: Terapeuta BCBA con niño feliz imageAlt: Terapeuta BCBA con niño feliz
- type: services-intro # Servicios y compromisos
servicesIntro:
servicesHeading: Servicios de terapia ABA para niños y adolescentes diagnosticados con TEA servicesHeading: Servicios de terapia ABA para niños y adolescentes diagnosticados con TEA
services: services:
- Apoyo a la defensa del autismo - Apoyo a la defensa del autismo
@@ -42,7 +44,8 @@ sections:
commitmentsImage: playing-boy.webp commitmentsImage: playing-boy.webp
commitmentsImageAlt: Niño jugando mientras aprende commitmentsImageAlt: Niño jugando mientras aprende
- type: benefits # Beneficios
benefits:
heading: Beneficios que van más allá de un proveedor de terapia integrada típico heading: Beneficios que van más allá de un proveedor de terapia integrada típico
subheading: La Diferencia AIA subheading: La Diferencia AIA
items: items:
@@ -55,7 +58,8 @@ sections:
videoImage: learner-journey.webp videoImage: learner-journey.webp
videoImageAlt: Video del recorrido del estudiante videoImageAlt: Video del recorrido del estudiante
- type: skills # Habilidades
skills:
heading: ¿Su alumno tiene dificultades con estas habilidades? heading: ¿Su alumno tiene dificultades con estas habilidades?
skills: skills:
- icon: icon-Social_Engagement.png - icon: icon-Social_Engagement.png
@@ -71,7 +75,8 @@ sections:
- icon: icon-Speach.png - icon: icon-Speach.png
label: Discurso label: Discurso
- type: insurance # Seguros
insurance:
heading: "Sí, aceptamos seguros." heading: "Sí, aceptamos seguros."
body: "Un servicio integrado todo en uno para las necesidades de educación especial de su hijo, el Instituto de Autismo de Arizona (AIA) ofrece y acepta la mayoría de los planes de seguro que cubren la terapia ABA. Estos incluyen BCBS AZ, Aetna, Optum, Tricare, United Healthcare AHCCCS y UnitedHealth." body: "Un servicio integrado todo en uno para las necesidades de educación especial de su hijo, el Instituto de Autismo de Arizona (AIA) ofrece y acepta la mayoría de los planes de seguro que cubren la terapia ABA. Estos incluyen BCBS AZ, Aetna, Optum, Tricare, United Healthcare AHCCCS y UnitedHealth."
logos: logos:
@@ -88,7 +93,8 @@ sections:
- file: united-healthcare-logo-1.webp - file: united-healthcare-logo-1.webp
alt: United Healthcare alt: United Healthcare
- type: esa # ESA
esa:
heading: Cuenta de Becas de Arizona (ESA) heading: Cuenta de Becas de Arizona (ESA)
body: >- body: >-
Miles de estudiantes de Arizona son actualmente elegibles para la ESA financiada Miles de estudiantes de Arizona son actualmente elegibles para la ESA financiada
@@ -101,14 +107,16 @@ sections:
image: logo-az-dept-of-education.webp image: logo-az-dept-of-education.webp
imageAlt: Departamento de Educación de Arizona imageAlt: Departamento de Educación de Arizona
- type: financial-help # Ayuda financiera
financialHelp:
heading: ¿Necesita ayuda para pagar su atención? heading: ¿Necesita ayuda para pagar su atención?
body: El Instituto de Autismo de Arizona ofrece asistencia financiera flexible a las personas sin seguro. Obtén la atención que deseas o necesitas y paga a plazos. body: El Instituto de Autismo de Arizona ofrece asistencia financiera flexible a las personas sin seguro. Obtén la atención que deseas o necesitas y paga a plazos.
cta: cta:
label: Solicitar cita label: Solicitar cita
href: /es/client-consultation href: /es/client-consultation
- type: process # Proceso
process:
heading: Nuestro proceso heading: Nuestro proceso
steps: steps:
- icon: learner-journey-step-1a.svg - icon: learner-journey-step-1a.svg
@@ -124,7 +132,8 @@ sections:
- icon: learner-journey-step-6.svg - icon: learner-journey-step-6.svg
label: Colaborar en un Plan de Cuidados label: Colaborar en un Plan de Cuidados
- type: director # Directora
director:
heading: Una extensión de tu familia heading: Una extensión de tu familia
quote: '"En AIA, nos esforzamos por brindar atención excelente y compasiva a todas las comunidades a las que servimos. No podríamos lograr eso sin un personal y familias excelentes, apasionados y comprometidos. Esperamos con ansias nuestra colaboración con usted a medida que continuamos creciendo, sirviendo y apoyando a nuestros estudiantes en la búsqueda de su potencial individual."' quote: '"En AIA, nos esforzamos por brindar atención excelente y compasiva a todas las comunidades a las que servimos. No podríamos lograr eso sin un personal y familias excelentes, apasionados y comprometidos. Esperamos con ansias nuestra colaboración con usted a medida que continuamos creciendo, sirviendo y apoyando a nuestros estudiantes en la búsqueda de su potencial individual."'
photo: rula-diab.webp photo: rula-diab.webp
@@ -134,7 +143,8 @@ sections:
signature: clinical-director-rula-diab.png signature: clinical-director-rula-diab.png
signatureAlt: Directora Clínica Rula Diab signatureAlt: Directora Clínica Rula Diab
- type: testimonials # Testimonios
testimonials:
heading: Lo que dicen los clientes heading: Lo que dicen los clientes
items: items:
- author: Claudia - author: Claudia
+27 -3
View File
@@ -1,11 +1,35 @@
--- ---
import BaseLayout from './BaseLayout.astro'; import BaseLayout from './BaseLayout.astro';
const { title, description, lang = 'en' } = Astro.props; import PageHero from '../components/PageHero.astro';
const { title, description, intro = [], lang = 'en' } = Astro.props;
const languagePrefix = lang === 'en' ? '' : `/${lang}`; const languagePrefix = lang === 'en' ? '' : `/${lang}`;
const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`; const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`;
--- ---
<BaseLayout title={title} description={description} canonical={canonical} lang={lang}> <BaseLayout title={title} description={description} canonical={canonical} lang={lang}>
<header class="library-banner"><div class="container"><div class="library-banner-copy"><p class="script-label">Welcome to</p><h1>{title}</h1></div></div></header> <PageHero title={title} image="/assets/images/hero-library-index.webp" eyebrow="Welcome to" constrain />
<section class="library-intro"><div class="container"><h2>Library</h2><p>{description}</p></div></section> <section class="library-intro">
<div class="container">
<h2>Library</h2>
{intro.length ? intro.map((paragraph) => <p>{paragraph}</p>) : <p>{description}</p>}
</div>
</section>
<div class="container section library-layout"><slot /></div> <div class="container section library-layout"><slot /></div>
</BaseLayout> </BaseLayout>
<style>
:global(.library-intro) { background: var(--color-primary); color: white; padding-block: 3rem; }
:global(.library-intro h2) { color: white; }
:global(.library-layout) { align-items: start; display: grid; gap: 3rem; grid-template-columns: 1fr 240px; }
:global(.library-sidebar) { position: sticky; top: 1rem; }
:global(.library-sidebar label) { display: block; font-weight: 700; margin-bottom: .4rem; }
:global(.library-sidebar input) { border: 1px solid var(--color-border); border-radius: 4px; font: inherit; padding: .7rem; width: 100%; }
:global(.library-sidebar h2) { font-size: 1.1rem; margin-top: 2rem; }
:global(.library-sidebar ul) { list-style: none; padding: 0; }
:global(.library-sidebar li) { border-bottom: 1px solid var(--color-border); padding-block: .65rem; }
:global(.library-sidebar a) { color: var(--color-primary); font-size: .9rem; }
:global(.blog-list) { display: block; }
@media (max-width: 760px) {
:global(.library-layout) { grid-template-columns: 1fr; }
:global(.library-sidebar) { position: static; }
}
</style>
+12
View File
@@ -19,3 +19,15 @@ const { entry } = Astro.props;
</article> </article>
<BlogPostFooter entryId={entry.id} /> <BlogPostFooter entryId={entry.id} />
</BaseLayout> </BaseLayout>
<style>
.article-header { padding-block: 4.5rem 0; text-align: left; }
.article-header h1 { font-size: clamp(2.3rem, 5vw, 3rem); max-width: 900px; }
.article-byline { align-items: center; display: flex; font-size: .9rem; gap: 1rem; }
.article-byline img { margin-top: 0; height: 52px; width: 52px; }
.article-featured { height: 480px; margin: 3rem auto 0; max-width: 800px; overflow: hidden; }
.article-featured img { height: 100%; margin: 0; object-fit: cover; width: 100%; }
@media (max-width: 760px) {
.article-featured { height: auto; }
}
</style>
+8 -3
View File
@@ -2,6 +2,9 @@
import BaseLayout from './BaseLayout.astro'; import BaseLayout from './BaseLayout.astro';
import FormShell from '../components/FormShell.astro'; import FormShell from '../components/FormShell.astro';
import TeamPage from '../components/TeamPage.astro'; import TeamPage from '../components/TeamPage.astro';
import AboutPage from '../components/AboutPage.astro';
import ServicesPage from '../components/ServicesPage.astro';
import PageHero from '../components/PageHero.astro';
import { pageHeroImages } from '../data/page-visuals'; import { pageHeroImages } from '../data/page-visuals';
const { entry } = Astro.props; const { entry } = Astro.props;
const showForm = ['client-consultation', 'contact', 'schedule-consultation', 'referrals'].includes(entry.data.slug); const showForm = ['client-consultation', 'contact', 'schedule-consultation', 'referrals'].includes(entry.data.slug);
@@ -48,11 +51,13 @@ const isService = Boolean(serviceTitles[entry.data.lang]?.[entry.data.slug]);
const heroImage = pageHeroImages[entry.data.slug]; const heroImage = pageHeroImages[entry.data.slug];
--- ---
<BaseLayout title={entry.data.title} description={entry.data.description} canonical={entry.data.canonical} image={entry.data.featuredImage || heroImage} lang={entry.data.lang}> <BaseLayout title={entry.data.title} description={entry.data.description} canonical={entry.data.canonical} image={entry.data.featuredImage || heroImage} lang={entry.data.lang}>
<header class:list={['source-page-banner', { 'has-source-image': heroImage, 'service-banner': isService }]} style={heroImage ? `background-image: url("${heroImage}")` : undefined}> <PageHero title={bannerTitle} image={heroImage} constrain />
<div class="container"><h1>{bannerTitle}</h1></div>
</header>
{entry.data.slug === 'team' && entry.data.lang === 'en' {entry.data.slug === 'team' && entry.data.lang === 'en'
? <TeamPage /> ? <TeamPage />
: entry.data.slug === 'about' && entry.data.lang === 'en'
? <AboutPage />
: entry.data.slug === 'services' && entry.data.lang === 'en'
? <ServicesPage />
: <article class:list={['prose', 'source-page', 'container', { 'service-page': isService }]}><slot /></article>} : <article class:list={['prose', 'source-page', 'container', { 'service-page': isService }]}><slot /></article>}
{showForm && <FormShell title={bannerTitle} showBackground={entry.data.slug === 'client-consultation'} />} {showForm && <FormShell title={bannerTitle} showBackground={entry.data.slug === 'client-consultation'} />}
</BaseLayout> </BaseLayout>
+8 -1
View File
@@ -5,7 +5,14 @@ import BlogCard from '../../components/BlogCard.astro';
const posts = (await getCollection('blog', ({ data }) => data.lang === 'en' && !data.draft)).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); const posts = (await getCollection('blog', ({ data }) => data.lang === 'en' && !data.draft)).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
const popular = posts.slice(0, 5); const popular = posts.slice(0, 5);
--- ---
<BlogIndexLayout title="The Library at AZ Institute for Autism" description="Welcome to the Library at AIA, where we share valuable insights, strategies, and resources to support individuals with autism, their families, and professionals in the field. Our articles explore key topics in Applied Behavior Analysis (ABA) therapy, community events, success stories, and expert guidance."> <BlogIndexLayout
title="The Library at AZ Institute for Autism"
description="Welcome to the Library at AIA, where we share valuable insights, strategies, and resources to support individuals with autism, their families, and professionals in the field. Our articles explore key topics in Applied Behavior Analysis (ABA) therapy, community events, success stories, and expert guidance."
intro={[
"Welcome to the Library at AIA, where we share valuable insights, strategies, and resources to support individuals with autism, their families, and professionals in the field. Our articles explore key topics in Applied Behavior Analysis (ABA) therapy, including teaching self-advocacy, proactive and reactive strategies, and innovative intervention techniques.",
"We also highlight community events, success stories, and expert guidance to foster understanding and empowerment. Whether you're a parent, caregiver, educator, or advocate, our goal is to provide meaningful content that helps children with autism reach their highest potential in a compassionate and supportive environment. Stay connected with us as we continue to share knowledge and celebrate progress!",
]}
>
<div class="blog-list">{posts.map((post) => <BlogCard post={post} />)}</div> <div class="blog-list">{posts.map((post) => <BlogCard post={post} />)}</div>
<aside class="library-sidebar"> <aside class="library-sidebar">
<label for="library-search">Search</label> <label for="library-search">Search</label>
+2 -129
View File
@@ -1,141 +1,14 @@
.utility-bar { background: var(--color-primary); color: white; font-size: .85rem; } .button { background: var(--color-accent); border: 2px solid var(--color-accent); border-radius: 4px; color: var(--color-primary); display: inline-block; padding: .65rem 1.2rem; text-decoration: none; transition: .3s linear all; }
.utility-inner { align-items: center; display: flex; gap: var(--space-md); justify-content: flex-end; min-height: 38px; }
.utility-bar a { color: white; text-decoration: none; }
.lang-switcher { position: relative; }
.lang-switcher__trigger { align-items: center; color: var(--color-primary); cursor: pointer; display: flex; font-size: .85rem; font-weight: 700; gap: .35rem; }
.lang-switcher__trigger svg { flex-shrink: 0; }
.lang-switcher__menu { background: white; box-shadow: var(--shadow-md); display: none; left: 50%; list-style: none; margin: 0; min-width: 110px; padding: .5rem 0 .4rem; position: absolute; top: 100%; transform: translateX(-50%); z-index: 10; }
.lang-switcher__menu a { color: rgb(83 83 91); display: block; font-size: .85rem; padding: .4rem .9rem; text-decoration: none; white-space: nowrap; }
.lang-switcher__menu a:hover { background: var(--color-primary); color: white; }
.lang-switcher__menu a[aria-current="page"] { color: var(--color-accent); font-weight: 700; }
.lang-switcher:hover .lang-switcher__menu,
.lang-switcher:focus-within .lang-switcher__menu { display: block; }
.site-header { background: white; box-shadow: var(--shadow-sm); position: relative; z-index: 5; }
.header-inner { align-items: center; display: flex; gap: 1.4rem; min-height: 110px; }
.brand { margin-right: auto; }
.brand img { width: 150px; }
.main-nav ul { display: flex; gap: 1.4rem; list-style: none; margin: 0; padding: 0; }
.main-nav li { position: relative; }
.main-nav a { color: var(--color-primary); font-size: .9rem; text-decoration: none; }
.main-nav a:hover { color: var(--color-accent-strong); }
.main-nav .submenu { background: white; box-shadow: var(--shadow-md); display: none; gap: 0; left: -1rem; min-width: 180px; padding: .75rem 0; position: absolute; top: 100%; }
.main-nav .submenu a { display: block; padding: .45rem 1rem; }
.main-nav li:hover > .submenu, .main-nav li:focus-within > .submenu { display: block; }
.mobile-nav { display: none; }
.button { background: var(--color-accent); border: 2px solid var(--color-accent); border-radius: 4px; color: var(--color-primary); display: inline-block; padding: .65rem 1.2rem; text-decoration: none; }
.button:hover { background: transparent; border-color: var(--color-accent-strong); color: var(--color-primary); } .button:hover { background: transparent; border-color: var(--color-accent-strong); color: var(--color-primary); }
.button-small { font-size: .9rem; } .button-small { font-size: .9rem; }
.button-light { background: white; color: var(--color-primary-dark); } .button-light { background: white; color: var(--color-primary-dark); }
.hero { background: var(--color-tint); overflow: hidden; padding-block: clamp(3rem, 7vw, 5rem); }
.hero-grid { align-items: center; display: grid; gap: var(--space-xl); grid-template-columns: 1.05fr .95fr; }
.hero img { max-height: 430px; object-fit: contain; width: 100%; }
.card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; } .card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.card img { aspect-ratio: 16/10; object-fit: cover; width: 100%; } .card img { aspect-ratio: 16/10; object-fit: cover; width: 100%; }
.card-body, .location-card { padding: var(--space-lg); } .card-body { padding: var(--space-lg); }
.card h2, .card h3 { margin-top: 0; } .card h2, .card h3 { margin-top: 0; }
.card h2 a, .card h3 a { color: inherit; text-decoration: none; } .card h2 a, .card h3 a { color: inherit; text-decoration: none; }
.text-link { font-weight: 700; } .text-link { font-weight: 700; }
.insurance-strip { background: white; border-block: 1px solid var(--color-border); padding-block: var(--space-lg); text-align: center; }
.insurance-strip h2 { font-size: 1.4rem; }
.logo-row { align-items: center; display: flex; flex-wrap: wrap; justify-content: space-around; }
.logo-row img { filter: grayscale(1); max-height: 55px; max-width: 130px; }
.cta-band { background: var(--color-primary); color: white; padding-block: var(--space-xl); }
.cta-band h2, .cta-band .eyebrow { color: white; margin: 0; }
.site-footer { background: var(--color-primary-dark); color: white; padding-block: var(--space-xl) var(--space-md); }
.footer-grid { display: grid; gap: var(--space-xl); grid-template-columns: 1fr 1fr 1.5fr; }
.site-footer h2, .site-footer a { color: white; }
.site-footer h2 { font-size: 1.25rem; }
.site-footer ul { list-style: none; padding: 0; }
.site-footer li { margin-bottom: .35rem; }
.social-links { display: flex; gap: .75rem; }
.social-links a { color: var(--color-accent); font-weight: 700; }
.footer-bottom { border-top: 1px solid rgb(255 255 255 / 20%); display: flex; justify-content: space-between; margin-top: var(--space-lg); padding-top: var(--space-md); }
.article-header { padding-block: var(--space-xl) var(--space-lg); text-align: center; }
.article-header h1 { font-size: clamp(2.3rem, 6vw, 4.6rem); }
.article-header img { border-radius: var(--radius-lg); margin-top: var(--space-lg); width: 100%; }
.like-view-counter { align-items: center; border-top: 1px solid var(--color-border); display: flex; gap: var(--space-lg); margin-block: var(--space-xl); padding-top: var(--space-md); }
.like-view-counter button { background: white; border: 1px solid var(--color-border); border-radius: 999px; padding: .6rem 1rem; }
.like-view-counter button.liked { background: var(--color-primary-dark); border-color: var(--color-primary-dark); color: white; }
.like-view-counter button:disabled { cursor: wait; opacity: .65; }
.source-page-banner { background: var(--color-tint); padding-block: 4rem; text-align: center; }
.source-page-banner h1 { margin: 0; }
.source-page-banner.has-source-image { background-color: var(--color-tint); background-position: center; background-repeat: no-repeat; background-size: cover; padding-block: 10rem; text-align: left; }
.source-page-banner.has-source-image h1 { max-width: 600px; }
.library-banner { background-color: var(--color-tint); background-image: url('/assets/images/hero-library-index.webp'); background-position: center; background-repeat: no-repeat; background-size: cover; padding-block: 10rem; text-align: left; }
.library-banner-copy { max-width: 600px; }
.library-banner h1 { margin: 0; }
.library-intro { background: var(--color-primary); color: white; padding-block: 3rem; }
.library-intro h2 { color: white; }
.library-layout { align-items: start; display: grid; gap: 3rem; grid-template-columns: 1fr 240px; }
.library-sidebar { position: sticky; top: 1rem; }
.library-sidebar label { display: block; font-weight: 700; margin-bottom: .4rem; }
.library-sidebar input { border: 1px solid var(--color-border); border-radius: 4px; font: inherit; padding: .7rem; width: 100%; }
.library-sidebar h2 { font-size: 1.1rem; margin-top: 2rem; }
.library-sidebar ul { list-style: none; padding: 0; }
.library-sidebar li { border-bottom: 1px solid var(--color-border); padding-block: .65rem; }
.library-sidebar a { color: var(--color-primary); font-size: .9rem; }
.blog-list { display: grid; gap: 2rem; }
.blog-list .blog-card { box-shadow: none; display: grid; grid-template-columns: 240px 1fr; }
.blog-list .blog-card > a img { aspect-ratio: 4 / 3; height: 100%; }
.blog-card-meta { align-items: center; display: flex; font-size: .78rem; gap: .75rem; }
.blog-card-meta img { aspect-ratio: 1; border-radius: 50%; height: 42px; width: 42px; }
.blog-card h3 { font-size: 1.35rem; }
.article-header { padding-block: 4.5rem 0; text-align: left; }
.article-header h1 { font-size: clamp(2.3rem, 5vw, 3rem); max-width: 900px; }
.article-byline { align-items: center; display: flex; font-size: .9rem; gap: 1rem; }
.article-byline img { margin-top: 0; height: 52px; width: 52px; }
.article-featured { height: 480px; margin: 3rem auto 0; max-width: 800px; overflow: hidden; }
.article-featured img { height: 100%; margin: 0; object-fit: cover; width: 100%; }
.team-intro { padding-block: 4rem; text-align: center; }
.team-intro .script-label { font-size: 1.8rem; }
.team-group { padding-block: 2rem 4rem; text-align: center; }
.team-group > h2 { margin: 0 auto 2.5rem; max-width: 760px; }
.team-grid { display: grid; gap: 2rem 1.5rem; grid-template-columns: repeat(4, minmax(0, 1fr)); justify-content: center; }
.team-member img { aspect-ratio: 1 / 1.08; border: 5px solid var(--color-primary-dark); border-radius: 15px; object-fit: cover; width: 100%; }
.team-member h3 { font-size: 1.1rem; margin-bottom: .25rem; }
.team-member p { margin: 0; }
.team-careers { background: var(--color-tint); padding-block: 5rem; text-align: center; }
@media (max-width: 950px) { .main-nav, .header-inner > .button { display: none; } .mobile-nav { display: block; } .mobile-nav .main-nav { display: block; } .mobile-nav .main-nav ul { align-items: flex-start; flex-direction: column; padding: var(--space-md); } .hero-grid, .footer-grid { grid-template-columns: 1fr; } }
.source-list { margin-block: 0 1.5rem; padding-inline-start: 2.5rem; } .source-list { margin-block: 0 1.5rem; padding-inline-start: 2.5rem; }
.source-list li { line-height: 1.625; margin: 0; padding-inline-start: .15rem; } .source-list li { line-height: 1.625; margin: 0; padding-inline-start: .15rem; }
.source-list li::marker { color: var(--color-accent); } .source-list li::marker { color: var(--color-accent); }
.source-list li > p { margin-block: 0; } .source-list li > p { margin-block: 0; }
.video-card { background: none; border: none; cursor: pointer; display: block; padding: 0; position: relative; }
.video-card img { width: 100%; }
.video-card span { align-items: center; background: var(--color-accent); border-radius: 50%; color: white; display: flex; height: 64px; justify-content: center; left: 50%; position: absolute; top: 50%; transform: translate(-50%, -50%); width: 64px; z-index: 1; }
.video-card::before, .video-card::after { animation-duration: 3s; animation-iteration-count: infinite; animation-name: video-ripple; animation-timing-function: cubic-bezier(.65, 0, .34, 1); border: 8px solid var(--color-accent); border-radius: 50%; content: ""; height: 64px; left: 50%; opacity: 0; position: absolute; top: 50%; width: 64px; }
.video-card::before { animation-delay: .5s; }
@keyframes video-ripple { 0% { opacity: 1; transform: translate(-50%, -50%) scale3d(.75, .75, 1); } to { opacity: 0; transform: translate(-50%, -50%) scale3d(1.5, 1.5, 1); } }
.video-dialog { background: none; border: none; box-sizing: border-box; max-width: min(90vw, 900px); padding: 1rem 1rem 0 0; width: 100%; }
.video-dialog::backdrop { background: rgba(0, 0, 0, .85); }
.video-dialog-inner { position: relative; }
.video-dialog-frame { aspect-ratio: 16 / 9; width: 100%; }
.video-dialog-frame iframe { border: none; height: 100%; width: 100%; }
.video-dialog-close { background: white; border: none; border-radius: 50%; cursor: pointer; font-size: 1rem; height: 2rem; line-height: 2rem; position: absolute; right: -1rem; top: -1rem; width: 2rem; }
.process-section h2, .testimonial-section h2 { text-align: center; }
.process-grid { display: grid; gap: 1rem; grid-template-columns: repeat(3, 1fr); margin-top: 2.5rem; }
.process-grid div { background: white; min-height: 190px; padding: 3.2rem 1rem; position: relative; text-align: center; transition: transform .3s ease-in-out; }
.process-grid div:hover { transform: scale(1.05); z-index: 1; }
.process-grid img { margin: 0 auto 1rem; width: 42%; }
.testimonial-section blockquote { margin: 0 auto; max-width: 720px; padding: 0 2rem; text-align: center; }
.testimonial-author { font-size: 1.25rem; font-weight: 700; margin-bottom: .5rem; }
.testimonial-swiper { --swiper-pagination-bullet-horizontal-gap: 1vw; padding-bottom: 3rem !important; }
.testimonial-swiper .swiper-pagination-bullet { background-color: var(--color-accent); opacity: 1; }
.testimonial-swiper .swiper-pagination-bullet-active { background-color: var(--color-accent-strong); }
.testimonial-swiper .swiper-button-next, .testimonial-swiper .swiper-button-prev { color: var(--color-accent); }
.testimonial-swiper .swiper-button-next:hover, .testimonial-swiper .swiper-button-prev:hover { color: var(--color-accent-strong); }
@media (max-width: 760px) {
.utility-inner { justify-content: center; }
.header-inner { min-height: 88px; }
.header-inner .lang-switcher { margin-left: auto; }
.process-grid { grid-template-columns: 1fr 1fr; }
.footer-bottom { align-items: flex-start; flex-direction: column; }
.library-layout { grid-template-columns: 1fr; }
.library-sidebar { position: static; }
.blog-list .blog-card { grid-template-columns: 1fr; }
.article-featured { height: auto; }
.team-grid { grid-template-columns: 1fr; }
.source-page-banner.has-source-image, .library-banner { padding-block: 6.25rem; text-align: center; }
.source-page-banner.has-source-image h1, .library-banner-copy { margin-inline: auto; }
}
@media (min-width: 761px) and (max-width: 1050px) { .team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
+1
View File
@@ -3,6 +3,7 @@ html { scroll-behavior: smooth; }
body { background: var(--color-background); margin: 0; overflow-x: hidden; } body { background: var(--color-background); margin: 0; overflow-x: hidden; }
img { display: block; height: auto; max-width: 100%; } img { display: block; height: auto; max-width: 100%; }
.container, .container-narrow { margin-inline: auto; padding-inline: 20px; width: min(100%, var(--container)); } .container, .container-narrow { margin-inline: auto; padding-inline: 20px; width: min(100%, var(--container)); }
.container-w { width: min(100%, var(--container-w)); }
.container-narrow { width: min(100%, 820px); } .container-narrow { width: min(100%, 820px); }
.section { padding-block: clamp(3rem, 7vw, 5rem); } .section { padding-block: clamp(3rem, 7vw, 5rem); }
.section-tint, .page-header { background: var(--color-tint); } .section-tint, .page-header { background: var(--color-tint); }
+1
View File
@@ -24,4 +24,5 @@
--shadow-sm: 0 2px 8px rgb(37 64 128 / 10%); --shadow-sm: 0 2px 8px rgb(37 64 128 / 10%);
--shadow-md: 0 8px 24px rgb(37 64 128 / 14%); --shadow-md: 0 8px 24px rgb(37 64 128 / 14%);
--container: 1020px; --container: 1020px;
--container-w: 1208px;
} }
+146 -87
View File
@@ -1,97 +1,156 @@
export interface HeroSection { import { z } from 'astro:content';
type: 'hero';
eyebrow: string;
heading: string;
body: string;
cta: { label: string; href: string };
image: string;
imageAlt: string;
}
export interface ServicesIntroSection { const ctaSchema = z.object({
type: 'services-intro'; label: z.string(),
servicesHeading: string; href: z.string(),
services: string[]; });
servicesImage: string;
servicesImageAlt: string;
commitmentsHeading: string;
commitments: string[];
commitmentsCta: { label: string; href: string };
commitmentsImage: string;
commitmentsImageAlt: string;
}
export interface BenefitsSection { const heroSectionSchema = z.object({
type: 'benefits'; type: z.literal('hero'),
heading: string; eyebrow: z.string(),
subheading: string; heading: z.string(),
items: string[]; body: z.string(),
videoUrl: string; cta: ctaSchema,
videoTitle: string; image: z.string(),
videoImage: string; imageAlt: z.string(),
videoImageAlt: string; });
}
export interface SkillsSection { const servicesIntroSectionSchema = z.object({
type: 'skills'; type: z.literal('services-intro'),
heading: string; servicesHeading: z.string(),
skills: { icon: string; label: string }[]; services: z.array(z.string()),
} servicesImage: z.string(),
servicesImageAlt: z.string(),
commitmentsHeading: z.string(),
commitments: z.array(z.string()),
commitmentsCta: ctaSchema,
commitmentsImage: z.string(),
commitmentsImageAlt: z.string(),
});
export interface InsuranceSection { const benefitsSectionSchema = z.object({
type: 'insurance'; type: z.literal('benefits'),
heading: string; heading: z.string(),
body: string; subheading: z.string(),
logos: { file: string; alt: string }[]; items: z.array(z.string()),
} videoUrl: z.string(),
videoTitle: z.string(),
videoImage: z.string(),
videoImageAlt: z.string(),
});
export interface EsaSection { const skillsSectionSchema = z.object({
type: 'esa'; type: z.literal('skills'),
heading: string; heading: z.string(),
body: string; skills: z.array(z.object({
image: string; icon: z.string(),
imageAlt: string; label: z.string(),
} })),
});
export interface FinancialHelpSection { const insuranceSectionSchema = z.object({
type: 'financial-help'; type: z.literal('insurance'),
heading: string; heading: z.string(),
body: string; body: z.string(),
cta: { label: string; href: string }; logos: z.array(z.object({
} file: z.string(),
alt: z.string(),
})),
});
export interface ProcessSection { const esaSectionSchema = z.object({
type: 'process'; type: z.literal('esa'),
heading: string; heading: z.string(),
steps: { icon: string; label: string }[]; body: z.string(),
} image: z.string(),
imageAlt: z.string(),
});
export interface DirectorSection { const financialHelpSectionSchema = z.object({
type: 'director'; type: z.literal('financial-help'),
heading: string; heading: z.string(),
quote: string; body: z.string(),
photo: string; cta: ctaSchema,
photoAlt: string; });
name: string;
credentials: string;
signature: string;
signatureAlt: string;
}
export interface TestimonialsSection { const processSectionSchema = z.object({
type: 'testimonials'; type: z.literal('process'),
heading: string; heading: z.string(),
items: { author: string; text: string }[]; steps: z.array(z.object({
} icon: z.string(),
label: z.string(),
})),
});
export type HomeSection = const directorSectionSchema = z.object({
| HeroSection type: z.literal('director'),
| ServicesIntroSection heading: z.string(),
| BenefitsSection quote: z.string(),
| SkillsSection photo: z.string(),
| InsuranceSection photoAlt: z.string(),
| EsaSection name: z.string(),
| FinancialHelpSection credentials: z.string(),
| ProcessSection signature: z.string(),
| DirectorSection signatureAlt: z.string(),
| TestimonialsSection; });
const testimonialsSectionSchema = z.object({
type: z.literal('testimonials'),
heading: z.string(),
items: z.array(z.object({
author: z.string(),
text: z.string(),
})),
});
export const homeSectionSchema = z.discriminatedUnion('type', [
heroSectionSchema,
servicesIntroSectionSchema,
benefitsSectionSchema,
skillsSectionSchema,
insuranceSectionSchema,
esaSectionSchema,
financialHelpSectionSchema,
processSectionSchema,
directorSectionSchema,
testimonialsSectionSchema,
]);
export const homeSectionsSchema = z.array(homeSectionSchema);
const homeHeroSchema = heroSectionSchema.omit({ type: true });
const homeServicesIntroSchema = servicesIntroSectionSchema.omit({ type: true });
const homeBenefitsSchema = benefitsSectionSchema.omit({ type: true });
const homeSkillsSchema = skillsSectionSchema.omit({ type: true });
const homeInsuranceSchema = insuranceSectionSchema.omit({ type: true });
const homeEsaSchema = esaSectionSchema.omit({ type: true });
const homeFinancialHelpSchema = financialHelpSectionSchema.omit({ type: true });
const homeProcessSchema = processSectionSchema.omit({ type: true });
const homeDirectorSchema = directorSectionSchema.omit({ type: true });
const homeTestimonialsSchema = testimonialsSectionSchema.omit({ type: true });
export const homePageSchema = z.object({
hero: homeHeroSchema,
servicesIntro: homeServicesIntroSchema,
benefits: homeBenefitsSchema,
skills: homeSkillsSchema,
insurance: homeInsuranceSchema,
esa: homeEsaSchema,
financialHelp: homeFinancialHelpSchema,
process: homeProcessSchema,
director: homeDirectorSchema,
testimonials: homeTestimonialsSchema,
});
export type HomeSection = z.infer<typeof homeSectionSchema>;
export type HeroSection = z.infer<typeof heroSectionSchema>;
export type ServicesIntroSection = z.infer<typeof servicesIntroSectionSchema>;
export type BenefitsSection = z.infer<typeof benefitsSectionSchema>;
export type SkillsSection = z.infer<typeof skillsSectionSchema>;
export type InsuranceSection = z.infer<typeof insuranceSectionSchema>;
export type EsaSection = z.infer<typeof esaSectionSchema>;
export type FinancialHelpSection = z.infer<typeof financialHelpSectionSchema>;
export type ProcessSection = z.infer<typeof processSectionSchema>;
export type DirectorSection = z.infer<typeof directorSectionSchema>;
export type TestimonialsSection = z.infer<typeof testimonialsSectionSchema>;
export type HomePageContent = z.infer<typeof homePageSchema>;