Add booking bands, offices, official favicon and logo in light mode

- Drop a Start a Conversation band between sections on every page, since
  there were no calls to action while scrolling
- Add the AiGT offices to the contact page, with the new Dubai address
- Serve favicon.ico, PNG icons and an apple-touch icon made from the official
  DA monogram, replacing the hand-drawn SVG
- Show the official logo in light mode too
- Spanish and Arabic translations for the new copy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Alejandro Veras
2026-10-20 16:58:40 -04:00
parent daf95278a7
commit 53e3e7bf81
12 changed files with 134 additions and 9 deletions
+23 -1
View File
@@ -1312,5 +1312,27 @@
"Send the form above and you’ll pick a time that works right after, no back-and-forth.": "أرسل النموذج أعلاه وستختار مباشرة بعده الوقت الذي يناسبك، دون مراسلات متبادلة.", "Send the form above and you’ll pick a time that works right after, no back-and-forth.": "أرسل النموذج أعلاه وستختار مباشرة بعده الوقت الذي يناسبك، دون مراسلات متبادلة.",
"Tell Me a Bit About You First.": "أخبرني قليلًا عن نفسك أولًا.", "Tell Me a Bit About You First.": "أخبرني قليلًا عن نفسك أولًا.",
"Send the short form on the contact page and you’ll pick a time for your call right after.": "أرسل النموذج القصير في صفحة التواصل وستختار موعد مكالمتك مباشرة بعده.", "Send the short form on the contact page and you’ll pick a time for your call right after.": "أرسل النموذج القصير في صفحة التواصل وستختار موعد مكالمتك مباشرة بعده.",
"GO TO THE FORM": "انتقل إلى النموذج" "GO TO THE FORM": "انتقل إلى النموذج",
"Start a conversation": "ابدأ محادثة",
"Have Something Worth Talking About?": "هل لديك ما يستحق الحديث عنه؟",
"Book a call with my team or with me directly. It starts with understanding where your business stands.": "احجز مكالمة مع فريقي أو معي مباشرة. كل شيء يبدأ بفهم الوضع الحالي لعملك.",
"GLOBAL PRESENCE": "حضور عالمي",
"Wherever You’re Growing, Start the Conversation Here.": "أينما كنت تنمو، ابدأ المحادثة من هنا.",
"Global HQ": "المقر العالمي",
"Our global headquarters and innovation hub in the MENA region.": "مقرنا العالمي ومركز الابتكار لدينا في منطقة الشرق الأوسط وشمال أفريقيا.",
"<em>Phone</em>": "<em>الهاتف</em>",
"<em>Email</em>": "<em>البريد الإلكتروني</em>",
"Houston": "هيوستن",
"Partner Office": "مكتب شريك",
"A US point of contact for businesses across Texas and beyond.": "نقطة تواصل في الولايات المتحدة للشركات في تكساس وخارجها.",
"Miami": "ميامي",
"A US point of contact based in South Florida.": "نقطة تواصل في الولايات المتحدة مقرها جنوب فلوريدا.",
"New York City": "مدينة نيويورك",
"A US point of contact in one of the world’s leading business markets.": "نقطة تواصل في الولايات المتحدة في أحد أبرز أسواق الأعمال في العالم.",
"Blue Bay Tower, Office 312, 3rd Floor": "Blue Bay Tower, Office 312, 3rd Floor",
"Marasi Drive Street, Business Bay": "Marasi Drive Street, Business Bay",
"Dubai, UAE": "Dubai, UAE",
"Downtown Houston, TX, USA": "Downtown Houston, TX, USA",
"Brickell Avenue, FL, USA": "Brickell Avenue, FL, USA",
"Manhattan Financial District, NY, USA": "Manhattan Financial District, NY, USA"
} }
+23 -1
View File
@@ -1312,5 +1312,27 @@
"Send the form above and you’ll pick a time that works right after, no back-and-forth.": "Envía el formulario de arriba y justo después eliges el horario que te funcione, sin mensajes de ida y vuelta.", "Send the form above and you’ll pick a time that works right after, no back-and-forth.": "Envía el formulario de arriba y justo después eliges el horario que te funcione, sin mensajes de ida y vuelta.",
"Tell Me a Bit About You First.": "Primero cuéntame un poco sobre ti.", "Tell Me a Bit About You First.": "Primero cuéntame un poco sobre ti.",
"Send the short form on the contact page and you’ll pick a time for your call right after.": "Envía el formulario corto de la página de contacto y justo después eliges el horario de tu llamada.", "Send the short form on the contact page and you’ll pick a time for your call right after.": "Envía el formulario corto de la página de contacto y justo después eliges el horario de tu llamada.",
"GO TO THE FORM": "IR AL FORMULARIO" "GO TO THE FORM": "IR AL FORMULARIO",
"Start a conversation": "Inicia una conversación",
"Have Something Worth Talking About?": "¿Tienes algo que valga la pena conversar?",
"Book a call with my team or with me directly. It starts with understanding where your business stands.": "Agenda una llamada con mi equipo o directamente conmigo. Todo empieza por entender en qué punto está tu negocio.",
"GLOBAL PRESENCE": "PRESENCIA GLOBAL",
"Wherever You’re Growing, Start the Conversation Here.": "Dondequiera que estés creciendo, empieza la conversación aquí.",
"Global HQ": "Sede global",
"Our global headquarters and innovation hub in the MENA region.": "Nuestra sede global y centro de innovación en la región MENA.",
"<em>Phone</em>": "<em>Teléfono</em>",
"<em>Email</em>": "<em>Correo</em>",
"Houston": "Houston",
"Partner Office": "Oficina asociada",
"A US point of contact for businesses across Texas and beyond.": "Un punto de contacto en EE. UU. para empresas de Texas y más allá.",
"Miami": "Miami",
"A US point of contact based in South Florida.": "Un punto de contacto en EE. UU. ubicado en el sur de Florida.",
"New York City": "Nueva York",
"A US point of contact in one of the world’s leading business markets.": "Un punto de contacto en EE. UU. en uno de los mercados de negocios más importantes del mundo.",
"Blue Bay Tower, Office 312, 3rd Floor": "Blue Bay Tower, Office 312, 3rd Floor",
"Marasi Drive Street, Business Bay": "Marasi Drive Street, Business Bay",
"Dubai, UAE": "Dubai, UAE",
"Downtown Houston, TX, USA": "Downtown Houston, TX, USA",
"Brickell Avenue, FL, USA": "Brickell Avenue, FL, USA",
"Manhattan Financial District, NY, USA": "Manhattan Financial District, NY, USA"
} }
+58 -3
View File
@@ -13,6 +13,13 @@ export const SITE = {
freeCalendar: '81JqpCRit6APOwavApzh', // Free 15-min intro call with Dylan's team freeCalendar: '81JqpCRit6APOwavApzh', // Free 15-min intro call with Dylan's team
vipCalendar: 'lK9IYtCRGIuA7W93WjMF', // 15-min 1:1 with Dylan ($400) vipCalendar: 'lK9IYtCRGIuA7W93WjMF', // 15-min 1:1 with Dylan ($400)
}, },
// Same offices as aigrowthtechnologies.com/contact.
offices: [
{ city: 'Dubai', tag: 'Global HQ', desc: 'Our global headquarters and innovation hub in the MENA region.', address: ['Blue Bay Tower, Office 312, 3rd Floor', 'Marasi Drive Street, Business Bay', 'Dubai, UAE'], phone: '+971 55 647 0342' },
{ city: 'Houston', tag: 'Partner Office', desc: 'A US point of contact for businesses across Texas and beyond.', address: ['Downtown Houston, TX, USA'], phone: '+1 832-350-0465' },
{ city: 'Miami', tag: 'Partner Office', desc: 'A US point of contact based in South Florida.', address: ['Brickell Avenue, FL, USA'], phone: '+1 954-235-4974' },
{ city: 'New York City', tag: 'Partner Office', desc: 'A US point of contact in one of the world’s leading business markets.', address: ['Manhattan Financial District, NY, USA'], phone: '+1 713-289-4577' },
],
}; };
const ICONS = { const ICONS = {
@@ -210,7 +217,7 @@ function footer() {
</footer>`; </footer>`;
} }
export function page({ path, title, description, body, schema = [], head = '', scripts = '', noindex = false }, locale = 'en') { export function page({ path, title, description, body, schema = [], head = '', scripts = '', noindex = false, ctaBands = true }, locale = 'en') {
const canonical = SITE.url + localize(path, locale); const canonical = SITE.url + localize(path, locale);
const alternates = noindex ? '' : [...LOCALES.map((l) => [l, l]), ['x-default', 'en']] const alternates = noindex ? '' : [...LOCALES.map((l) => [l, l]), ['x-default', 'en']]
.map(([hl, l]) => `\n<link rel="alternate" hreflang="${hl}" href="${SITE.url + localize(path, l)}">`).join(''); .map(([hl, l]) => `\n<link rel="alternate" hreflang="${hl}" href="${SITE.url + localize(path, l)}">`).join('');
@@ -247,7 +254,9 @@ export function page({ path, title, description, body, schema = [], head = '', s
<meta name="twitter:title" content="${title}"> <meta name="twitter:title" content="${title}">
<meta name="twitter:description" content="${description}"> <meta name="twitter:description" content="${description}">
<meta name="twitter:image" content="${SITE.url}/assets/og.jpg"> <meta name="twitter:image" content="${SITE.url}/assets/og.jpg">
<link rel="icon" href="/favicon.svg" type="image/svg+xml"> <link rel="icon" href="/favicon.ico" sizes="48x48">
<link rel="icon" href="/icon-192.png" type="image/png" sizes="192x192">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@500&family=Unbounded:wght@700&display=swap"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@500&family=Unbounded:wght@700&display=swap">
@@ -264,7 +273,7 @@ ${ld}
<div class="progress" id="progress" aria-hidden="true"></div> <div class="progress" id="progress" aria-hidden="true"></div>
${nav(path, locale)} ${nav(path, locale)}
<main id="main"> <main id="main">
${body} ${ctaBands === false ? body : withCtaBands(body)}
</main> </main>
${footer()} ${footer()}
${langSwitch(path, locale)} ${langSwitch(path, locale)}
@@ -281,3 +290,49 @@ export const ghlForm = (id, name) =>
`<iframe class="ghl-frame" src="https://api.leadconnectorhq.com/widget/form/${id}" id="inline-${id}" title="${name}" data-layout="{'id':'INLINE'}" data-trigger-type="alwaysShow" data-trigger-value="" data-activation-type="alwaysActivated" data-activation-value="" data-deactivation-type="neverDeactivate" data-deactivation-value="" data-form-name="${name}" data-layout-iframe-id="inline-${id}" data-form-id="${id}"></iframe>`; `<iframe class="ghl-frame" src="https://api.leadconnectorhq.com/widget/form/${id}" id="inline-${id}" title="${name}" data-layout="{'id':'INLINE'}" data-trigger-type="alwaysShow" data-trigger-value="" data-activation-type="alwaysActivated" data-activation-value="" data-deactivation-type="neverDeactivate" data-deactivation-value="" data-form-name="${name}" data-layout-iframe-id="inline-${id}" data-form-id="${id}"></iframe>`;
export const ghlCalendar = (id, title) => export const ghlCalendar = (id, title) =>
`<iframe class="ghl-frame ghl-cal" src="https://api.leadconnectorhq.com/widget/booking/${id}" id="${id}_cal" title="${title}" scrolling="no"></iframe>`; `<iframe class="ghl-frame ghl-cal" src="https://api.leadconnectorhq.com/widget/booking/${id}" id="${id}_cal" title="${title}" scrolling="no"></iframe>`;
// Call-to-action band dropped between sections so a booking link is always close while scrolling.
export const ctaBand = () => `
<aside class="cta-band" aria-label="Start a conversation">
<div class="wrap cta-band-inner reveal">
<div class="cta-band-copy">
<p class="cta-band-title">Have Something Worth Talking About?</p>
<p class="cta-band-body">Book a call with my team or with me directly. It starts with understanding where your business stands.</p>
</div>
<div class="btn-row">${btn('START A CONVERSATION', '/contact/')}</div>
</div>
</aside>
`;
/** Insert a band after the 2nd top-level section and every 3rd after that, keeping clear of the closing sections. */
function withCtaBands(body) {
const parts = body.split(/(?<=\n<\/section>\n)/);
if (parts.length < 4) return body;
return parts.map((part, i) => (i % 3 === 1 && i < parts.length - 3 ? part + ctaBand() : part)).join('');
}
/** Office cards, mirroring the offices section on aigrowthtechnologies.com/contact. */
export const officesSection = () => `
<section class="section" aria-labelledby="offices-title">
<div class="wrap">
<div class="sec-head reveal">
<div class="stack-sm">${eyebrow('GLOBAL PRESENCE')}<h2 id="offices-title" class="h-display">Wherever You’re Growing, Start the Conversation Here.</h2></div>
</div>
<div class="offices reveal">
${SITE.offices
.map(
(o) => `<article class="office">
<div class="office-head"><h3 class="h-md">${o.city}</h3><span class="tag tag-line">${o.tag}</span></div>
<p class="office-desc">${o.desc}</p>
<address class="office-address">
${o.address.map((l) => `<span>${l}</span>`).join('')}
<span><em>Phone</em><a href="tel:${o.phone.replace(/[^\d+]/g, '')}">${o.phone}</a></span>
<span><em>Email</em><a href="mailto:${SITE.email}">${SITE.email}</a></span>
</address>
</article>`
)
.join('')}
</div>
</div>
</section>
`;
+1
View File
@@ -12,6 +12,7 @@ const calls = [
export default { export default {
path: '/contact/book/', path: '/contact/book/',
ctaBands: false,
noindex: true, noindex: true,
head: `<script> head: `<script>
(function () { (function () {
+3 -1
View File
@@ -1,9 +1,10 @@
import { icon, eyebrow, btn, SITE, ghlForm, GHL_SCRIPT } from '../layout.mjs'; import { icon, eyebrow, btn, SITE, ghlForm, GHL_SCRIPT, officesSection } from '../layout.mjs';
export default { export default {
path: '/contact/', path: '/contact/',
title: 'Contact Dylan Mazzei | Business &amp; Partnerships', title: 'Contact Dylan Mazzei | Business &amp; Partnerships',
scripts: GHL_SCRIPT, scripts: GHL_SCRIPT,
ctaBands: false,
description: 'Contact Dylan Mazzei about business opportunities, strategic partnerships, consulting, media inquiries, or other conversations worth having.', description: 'Contact Dylan Mazzei about business opportunities, strategic partnerships, consulting, media inquiries, or other conversations worth having.',
body: ` body: `
<section class="page-hero" aria-labelledby="ct-hero"> <section class="page-hero" aria-labelledby="ct-hero">
@@ -46,6 +47,7 @@ export default {
</div> </div>
</section> </section>
${officesSection()}
<section class="section" aria-labelledby="where"> <section class="section" aria-labelledby="where">
<div class="wrap"> <div class="wrap">
<div class="showcase reveal"> <div class="showcase reveal">
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

+26 -2
View File
@@ -902,8 +902,9 @@ h1, h2, h3, h4 { font-weight: 600; }
/* Real logo on dark, vector recreation on light */ /* Real logo on dark, vector recreation on light */
.logo-img { display: none; height: 30px; width: auto; } .logo-img { display: none; height: 30px; width: auto; }
:root[data-theme="dark"] .brand .logo-img { display: block; } /* The official logo in both themes: its dark outline keeps it readable on light backgrounds. */
:root[data-theme="dark"] .brand .logo-mark, :root[data-theme="dark"] .brand .brand-word { display: none; } .brand .logo-img { display: block; }
.brand .logo-mark, .brand .brand-word { display: none; }
.footer { border-top: 1px solid var(--bd); } .footer { border-top: 1px solid var(--bd); }
@@ -1063,3 +1064,26 @@ h1, h2, h3, h4 { font-weight: 600; }
.cal-panel[data-off] { position: absolute; left: -10000px; top: 0; width: min(980px, 100%); visibility: hidden; pointer-events: none; } .cal-panel[data-off] { position: absolute; left: -10000px; top: 0; width: min(980px, 100%); visibility: hidden; pointer-events: none; }
.ghl-wrap-form { min-height: 340px; } .ghl-wrap-form { min-height: 340px; }
.ghl-wrap-cal { min-height: 720px; } .ghl-wrap-cal { min-height: 720px; }
/* Call-to-action band between sections */
.cta-band { position: relative; z-index: 2; padding-block: clamp(28px, 4vw, 44px); border-block: 1px solid var(--bd);
background: radial-gradient(ellipse at 85% 50%, var(--glow), transparent 60%), var(--cloud); }
.cta-band-inner { display: flex; align-items: center; justify-content: space-between; gap: 32px; }
.cta-band-copy { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.cta-band-title { font-size: clamp(20px, 2.2vw, 28px); font-weight: 500; letter-spacing: -0.03em; line-height: 1.2; color: var(--ink); text-wrap: balance; }
.cta-band-body { max-width: 62ch; color: var(--slate); }
.cta-band .btn-row { flex: none; }
@media (max-width: 760px) { .cta-band-inner { flex-direction: column; align-items: flex-start; } }
/* Offices (same as aigrowthtechnologies.com/contact) */
.offices { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-top: 1px solid var(--bd); }
.office { display: flex; flex-direction: column; gap: 16px; padding: 28px 24px 8px; border-inline-start: 1px solid var(--bd); min-width: 0; }
.office:first-child { padding-inline-start: 0; border-inline-start: 0; }
.office-head { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.office-desc { color: var(--slate); font-size: 15px; }
.office-address { display: flex; flex-direction: column; gap: 8px; margin-top: auto; padding-top: 18px; border-top: 1px solid var(--bd); font-style: normal; font-size: 14px; color: var(--graphite); }
.office-address em { display: block; font-style: normal; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--smoke); }
.office-address a { color: var(--ink); overflow-wrap: anywhere; }
.office-address a:hover { color: var(--accent); }
@media (max-width: 1023px) { .offices { grid-template-columns: repeat(2, minmax(0, 1fr)); } .office:nth-child(3) { padding-inline-start: 0; border-inline-start: 0; } .office:nth-child(n + 3) { border-top: 1px solid var(--bd); } }
@media (max-width: 640px) { .offices { grid-template-columns: 1fr; } .office, .office:nth-child(3) { padding: 24px 0; border-inline-start: 0; } .office + .office { border-top: 1px solid var(--bd); } }
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="16" fill="#0b0b0d"/><g transform="translate(6 15) scale(.5)"><path fill="#fff" fill-rule="evenodd" d="M9 4h55c10 0 13 7 9 14L58 46c-3 6-8 8-15 8.5L3 57zM21.5 15.5 18.3 45.8 40 44.5c4-.3 6-1.5 7.5-4.3l12-21.4c1.2-2.2.3-3.3-2-3.3z"/><path fill="#33b9ff" d="M24 59 102 1 91 52 72 54.5 79 33z"/><path fill="#8fdcff" d="M24 59 102 1 79 33z"/></g></svg>

Before

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB