---
id: seed:archetypes/contact
title: Contact section archetypes
source_type: seed_archetype
priority: warm
---

A contact section converts intent into an inbox message. Lower the friction. The conversion-killer is asking for 10 fields when 3 would do. Six working archetypes:

---

**Form + sidebar (default).** Form on the left, alternative contact methods (email, phone, address, hours) on the right. Form fields: Name, Email, Message — and nothing else unless you have a hard reason.

*Animation & Visual Details:*
- *Entrance*: Form fades in from left, sidebar from right, 0.15s stagger
- *Hover*: Input fields show gradient border on focus; submit button has glow on hover
- *Gradients*: Input focus has gradient border animation (left to right sweep); submit button has gradient background
- *Radial circles*: Small radial glow behind the submit button; radial accent behind sidebar contact methods
- *Scroll trigger*: IntersectionObserver at 20% threshold
- *JS interaction*: Floating labels, inline validation with shake on error / check on success

```html
<section data-amb-section="contact" class="contact-section">
  <div class="container">
    <div class="contact-layout">
      <div class="contact-info">
        <h2 class="contact-title">{outcome-led headline}</h2>
        <p class="contact-subtitle">{set expectations: response time}</p>
        <ul class="contact-methods">
          <li class="contact-method">
            <span class="contact-method-icon">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
            </span>
            <div class="contact-method-content">
              <span class="contact-method-label">Email</span>
              <a class="contact-method-value" href="mailto:hello@example.com">hello@example.com</a>
            </div>
          </li>
          <li class="contact-method">
            <span class="contact-method-icon">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
            </span>
            <div class="contact-method-content">
              <span class="contact-method-label">Phone</span>
              <span class="contact-method-value">+1 (555) 123-4567</span>
            </div>
          </li>
        </ul>
      </div>
      <form class="contact-form">
        <div class="contact-field">
          <label class="contact-label" for="contact-name">Name</label>
          <input class="contact-input" type="text" id="contact-name" name="name" required placeholder=" " />
          <span class="contact-field-error">Please enter your name</span>
        </div>
        <div class="contact-field">
          <label class="contact-label" for="contact-email">Email</label>
          <input class="contact-input" type="email" id="contact-email" name="email" required placeholder=" " />
          <span class="contact-field-error">Please enter a valid email</span>
        </div>
        <div class="contact-field">
          <label class="contact-label" for="contact-message">Message</label>
          <textarea class="contact-textarea" id="contact-message" name="message" rows="5" required placeholder=" "></textarea>
          <span class="contact-field-error">Please enter a message</span>
        </div>
        <button class="contact-submit" type="submit">
          <span class="contact-submit-text">Send message</span>
          <span class="contact-submit-loading">
            <svg class="spinner" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10" opacity="0.25"/><path d="M12 2a10 10 0 0 1 10 10" stroke-linecap="round"/></svg>
          </span>
        </button>
      </form>
    </div>
  </div>
</section>
```

```css
:root {
  --contact-enter-duration: 0.5s;
}

.contact-section {
  padding: clamp(64px, 8vw, 100px) 0;
}

.contact-layout {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: start;
}

.contact-info {
  opacity: 0;
  transform: translateX(-30px);
  transition: opacity var(--contact-enter-duration) ease, transform var(--contact-enter-duration) ease;
}

.contact-form {
  opacity: 0;
  transform: translateX(30px);
  transition: opacity var(--contact-enter-duration) ease, transform var(--contact-enter-duration) ease;
  transition-delay: 0.15s;
}

.contact-section.is-visible .contact-info,
.contact-section.is-visible .contact-form {
  opacity: 1;
  transform: translateX(0);
}

.contact-title {
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  font-weight: 700;
  color: var(--color-text, #1e293b);
  margin-bottom: 12px;
}

.contact-subtitle {
  font-size: 1rem;
  color: var(--color-text-muted, #64748b);
  margin-bottom: 32px;
}

.contact-methods {
  list-style: none;
  padding: 0;
  margin: 0;
}

.contact-method {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 16px 0;
  border-bottom: 1px solid #f1f5f9;
}

.contact-method:last-child {
  border-bottom: none;
}

.contact-method-icon {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle, rgba(99,102,241,0.08) 0%, transparent 70%);
  border-radius: 50%;
  flex-shrink: 0;
}

.contact-method-icon svg {
  width: 20px;
  height: 20px;
  color: var(--color-accent, #6366f1);
}

.contact-method-label {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-muted, #64748b);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 4px;
}

.contact-method-value {
  font-size: 0.95rem;
  color: var(--color-text, #1e293b);
  text-decoration: none;
  transition: color 0.2s ease;
}

a.contact-method-value:hover {
  color: var(--color-accent, #6366f1);
}

.contact-field {
  position: relative;
  margin-bottom: 20px;
}

.contact-label {
  position: absolute;
  top: 16px;
  left: 16px;
  font-size: 0.95rem;
  color: #64748b;
  pointer-events: none;
  transition: all 0.2s ease;
  background: #fff;
  padding: 0 4px;
}

.contact-input,
.contact-textarea {
  width: 100%;
  padding: 16px;
  border: 2px solid #e2e8f0;
  border-radius: 10px;
  font-size: 1rem;
  font-family: inherit;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  background: #fff;
}

.contact-input:focus,
.contact-textarea:focus {
  outline: none;
  border-color: var(--color-accent, #6366f1);
  box-shadow: 0 0 0 4px rgba(99,102,241,0.1);
}

.contact-input:focus + .contact-label,
.contact-input:not(:placeholder-shown) + .contact-label,
.contact-textarea:focus + .contact-label,
.contact-textarea:not(:placeholder-shown) + .contact-label {
  top: -8px;
  font-size: 0.75rem;
  color: var(--color-accent, #6366f1);
}

.contact-input::placeholder,
.contact-textarea::placeholder {
  color: transparent;
}

.contact-field-error {
  display: none;
  font-size: 0.8rem;
  color: #ef4444;
  margin-top: 6px;
  padding-left: 4px;
}

.contact-field.is-invalid .contact-input,
.contact-field.is-invalid .contact-textarea {
  border-color: #ef4444;
  animation: shake 0.4s ease;
}

.contact-field.is-invalid .contact-field-error {
  display: block;
}

.contact-field.is-valid .contact-input,
.contact-field.is-valid .contact-textarea {
  border-color: #22c55e;
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20%, 60% { transform: translateX(-5px); }
  40%, 80% { transform: translateX(5px); }
}

.contact-submit {
  position: relative;
  width: 100%;
  padding: 16px 32px;
  background: linear-gradient(135deg, #6366f1, #7c3aed);
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  box-shadow: 0 4px 16px rgba(99,102,241,0.3);
}

.contact-submit::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at center, rgba(255,255,255,0.15) 0%, transparent 70%);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.contact-submit:hover::before {
  opacity: 1;
}

.contact-submit:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(99,102,241,0.4);
}

.contact-submit-loading {
  display: none;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  background: inherit;
}

.contact-submit.is-loading .contact-submit-text {
  opacity: 0;
}

.contact-submit.is-loading .contact-submit-loading {
  display: flex;
}

.contact-submit.is-loading .contact-submit-loading .spinner {
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 768px) {
  .contact-layout {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .contact-info, .contact-form {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .contact-field.is-invalid .contact-input {
    animation: none;
  }
}
```

*JS behavior:*
```javascript
const contactSection = document.querySelector('.contact-section');
const form = contactSection.querySelector('.contact-form');
const fields = form.querySelectorAll('.contact-field input, .contact-field textarea');
const submitBtn = form.querySelector('.contact-submit');

// Floating label handled by CSS :focus + :not(:placeholder-shown)

// Validation
fields.forEach(field => {
  field.addEventListener('blur', () => {
    const fieldset = field.closest('.contact-field');
    if (field.validity.valid && field.value !== '') {
      fieldset.classList.remove('is-invalid');
      fieldset.classList.add('is-valid');
    } else if (field.value !== '') {
      fieldset.classList.remove('is-valid');
      fieldset.classList.add('is-invalid');
    }
  });
  field.addEventListener('input', () => {
    field.closest('.contact-field').classList.remove('is-invalid', 'is-valid');
  });
});

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  let isValid = true;
  fields.forEach(field => {
    if (!field.validity.valid) {
      field.closest('.contact-field').classList.add('is-invalid');
      isValid = false;
    }
  });
  if (!isValid) return;

  submitBtn.classList.add('is-loading');
  await new Promise(r => setTimeout(r, 1500));
  submitBtn.classList.remove('is-loading');
  // handle success
});

// Entrance observer
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('is-visible');
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.2 });
observer.observe(contactSection);
```

---

**Booking embed.** Replace the form with a calendar embed (Calendly, Cal.com). Use when the actual goal is a sales call, not a written reply.

*Animation & Visual Details:*
- *Entrance*: Calendar iframe fades in with scale 0.97 → 1
- *Hover*: Navigation arrows show; time slots highlight on hover
- *Gradients*: Calendar container has subtle gradient top border
- *Radial circles*: Radial glow behind the calendar
- *Scroll trigger*: IntersectionObserver at 20% threshold
- *JS interaction*: Prefetch calendar URL on link hover; calendar modal opens on mobile

```html
<section data-amb-section="contact" class="contact-section contact-section--booking">
  <div class="contact-booking-glow"></div>
  <div class="container">
    <div class="contact-layout contact-layout--centered">
      <div class="contact-info contact-info--centered">
        <h2 class="contact-title">Book a call</h2>
        <p class="contact-subtitle">30 minutes. No pitch. Just answers.</p>
      </div>
      <div class="contact-calendar-wrapper">
        <div class="contact-calendar-container">
          <iframe
            class="contact-calendar-iframe"
            src="https://calendly.com/demo/30min"
            frameborder="0"
            title="Schedule a meeting"
          ></iframe>
        </div>
      </div>
    </div>
  </div>
</section>
```

```css
.contact-booking-glow {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 600px;
  height: 400px;
  background: radial-gradient(ellipse, rgba(99,102,241,0.08) 0%, transparent 70%);
  pointer-events: none;
  z-index: 0;
}

.contact-layout--centered {
  grid-template-columns: 1fr;
  max-width: 800px;
  margin: 0 auto;
  text-align: center;
}

.contact-info--centered {
  transform: none;
  opacity: 1;
}

.contact-calendar-wrapper {
  position: relative;
  z-index: 1;
}

.contact-calendar-container {
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid #e2e8f0;
  background: #fff;
  opacity: 0;
  transform: scale(0.97);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.contact-calendar-container.is-visible {
  opacity: 1;
  transform: scale(1);
}

.contact-calendar-iframe {
  width: 100%;
  height: 700px;
  display: block;
}
```

---

**Multi-channel grid.** Three cards: Sales, Support, Press — each with a different email or form. Use when you actually triage on intent (most sites don't).

*Animation & Visual Details:*
- *Entrance*: Cards stagger in from translateY(30px), 0.1s between each
- *Hover*: Card lifts with radial glow intensification; icon scales slightly
- *Gradients*: Cards have gradient left border when hovered
- *Radial circles*: Radial glow behind each card's icon
- *Scroll trigger*: IntersectionObserver at 15% threshold
- *JS interaction*: None beyond entrance

```html
<section data-amb-section="contact" class="contact-section contact-section--multi">
  <div class="container">
    <h2 class="contact-title contact-title--centered">Get in touch with the right team</h2>
    <div class="contact-grid">
      <div class="contact-channel-card">
        <div class="contact-channel-icon">
          <div class="contact-channel-glow"></div>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
        </div>
        <h3 class="contact-channel-title">Sales</h3>
        <p class="contact-channel-desc">Talk to our team about pricing and enterprise plans.</p>
        <a class="contact-channel-link" href="mailto:sales@example.com">sales@example.com</a>
      </div>
      <div class="contact-channel-card">
        <div class="contact-channel-icon">
          <div class="contact-channel-glow"></div>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
        </div>
        <h3 class="contact-channel-title">Support</h3>
        <p class="contact-channel-desc">Help with setup, billing, or technical questions.</p>
        <a class="contact-channel-link" href="mailto:support@example.com">support@example.com</a>
      </div>
      <div class="contact-channel-card">
        <div class="contact-channel-icon">
          <div class="contact-channel-glow"></div>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
        </div>
        <h3 class="contact-channel-title">Press</h3>
        <p class="contact-channel-desc">Media inquiries, interview requests, and assets.</p>
        <a class="contact-channel-link" href="mailto:press@example.com">press@example.com</a>
      </div>
    </div>
  </div>
</section>
```

```css
.contact-section--multi {
  padding: clamp(64px, 8vw, 100px) 0;
  background: var(--color-bg-alt, #f8fafc);
}

.contact-title--centered {
  text-align: center;
  max-width: 480px;
  margin: 0 auto clamp(40px, 5vw, 60px);
}

.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 24px;
  max-width: 960px;
  margin: 0 auto;
}

.contact-channel-card {
  position: relative;
  background: #fff;
  border-radius: 16px;
  border: 1px solid #f1f5f9;
  padding: 32px;
  text-align: center;
  opacity: 0;
  transform: translateY(24px);
  transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.contact-channel-card.is-visible {
  animation: channel-enter 0.5s ease-out forwards;
}

.contact-channel-card:nth-child(1).is-visible { animation-delay: 0s; }
.contact-channel-card:nth-child(2).is-visible { animation-delay: 0.1s; }
.contact-channel-card:nth-child(3).is-visible { animation-delay: 0.2s; }

@keyframes channel-enter {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.contact-channel-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(0,0,0,0.08);
  border-color: var(--color-accent, #6366f1);
}

.contact-channel-icon {
  position: relative;
  width: 56px;
  height: 56px;
  margin: 0 auto 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.contact-channel-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle, rgba(99,102,241,0.1) 0%, transparent 70%);
  border-radius: 50%;
  transition: opacity 0.3s ease;
}

.contact-channel-card:hover .contact-channel-glow {
  opacity: 1.5;
}

.contact-channel-icon svg {
  position: relative;
  z-index: 1;
  width: 28px;
  height: 28px;
  color: var(--color-accent, #6366f1);
  transition: transform 0.2s ease;
}

.contact-channel-card:hover .contact-channel-icon svg {
  transform: scale(1.1);
}

.contact-channel-title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--color-text, #1e293b);
  margin-bottom: 8px;
}

.contact-channel-desc {
  font-size: 0.9rem;
  color: var(--color-text-muted, #64748b);
  margin-bottom: 16px;
  line-height: 1.5;
}

.contact-channel-link {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--color-accent, #6366f1);
  text-decoration: none;
}

.contact-channel-link:hover {
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
  .contact-channel-card {
    opacity: 1;
    transform: none;
  }
}
```

---

**Animated input focus.** Gradient border sweeps across input on focus. Focus states are the primary visual interaction.

*Animation & Visual Details:*
- *Entrance*: Form elements fade in with stagger
- *Hover*: Not applicable — focus is the interaction trigger
- *Gradients*: Focus triggers a gradient border that animates from left to right (width 0% → 100%)
- *Radial circles*: Radial glow behind each focused input field
- *Scroll trigger*: IntersectionObserver at 20% threshold
- *JS interaction*: Gradient sweep animation on :focus-within

```html
<section data-amb-section="contact" class="contact-section contact-section--animated-input">
  <div class="container">
    <div class="contact-layout">
      <div class="contact-info">
        <h2 class="contact-title">Send us a message</h2>
        <p class="contact-subtitle">We reply within one business day.</p>
      </div>
      <form class="contact-form contact-form--animated">
        <div class="contact-field contact-field--animated">
          <label class="contact-label" for="name">Name</label>
          <input class="contact-input" type="text" id="name" name="name" required placeholder=" " />
        </div>
        <div class="contact-field contact-field--animated">
          <label class="contact-label" for="email">Email</label>
          <input class="contact-input" type="email" id="email" name="email" required placeholder=" " />
        </div>
        <div class="contact-field contact-field--animated">
          <label class="contact-label" for="message">Message</label>
          <textarea class="contact-textarea" id="message" name="message" rows="5" required placeholder=" "></textarea>
        </div>
        <button class="contact-submit" type="submit">Send message</button>
      </form>
    </div>
  </div>
</section>
```

```css
.contact-form--animated .contact-field--animated {
  position: relative;
}

.contact-form--animated .contact-field--animated::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 12px;
  padding: 2px;
  background: linear-gradient(90deg, #6366f1, #7c3aed, #ec4899);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
  background-size: 200% 100%;
  animation: gradient-sweep 2s linear infinite;
}

.contact-form--animated .contact-field--animated:focus-within::before {
  opacity: 1;
}

@keyframes gradient-sweep {
  0% { background-position: 0% 0%; }
  100% { background-position: 200% 0%; }
}

.contact-input,
.contact-textarea {
  border: 2px solid #e2e8f0;
  background: #fff;
}

.contact-form--animated .contact-field--animated:focus-within .contact-input,
.contact-form--animated .contact-field--animated:focus-within .contact-textarea {
  border-color: transparent;
}

@media (prefers-reduced-motion: reduce) {
  .contact-form--animated .contact-field--animated::before {
    animation: none;
    opacity: 0.8;
  }
}
```

---

**Success state CTA.** Radial confirmation animation on submit, toast notification. After form submission, show a success state.

*Animation & Visual Details:*
- *Entrance*: Standard form entrance
- *Hover*: Not applicable (form state changes)
- *Gradients*: Success state uses gradient background (green tones)
- *Radial circles*: Radial ring "burst" animation on success state appearing
- *Scroll trigger*: Not applicable
- *JS interaction*: Form submit triggers success state replacement; radial burst animation; toast notification

```html
<section data-amb-section="contact" class="contact-section contact-section--success-state">
  <div class="container">
    <div class="contact-layout">
      <div class="contact-info">
        <h2 class="contact-title">Contact us</h2>
        <p class="contact-subtitle">We reply within one business day.</p>
      </div>
      <div class="contact-form-container">
        <form class="contact-form" id="contact-form-success">
          <div class="contact-field">
            <label class="contact-label" for="name">Name</label>
            <input class="contact-input" type="text" id="name" name="name" required placeholder=" " />
          </div>
          <div class="contact-field">
            <label class="contact-label" for="email">Email</label>
            <input class="contact-input" type="email" id="email" name="email" required placeholder=" " />
          </div>
          <div class="contact-field">
            <label class="contact-label" for="message">Message</label>
            <textarea class="contact-textarea" id="message" name="message" rows="5" required placeholder=" "></textarea>
          </div>
          <button class="contact-submit" type="submit">Send message</button>
        </form>
        <div class="contact-success" id="contact-success" hidden>
          <div class="contact-success-ring"></div>
          <div class="contact-success-icon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>
          </div>
          <h3 class="contact-success-title">Message sent!</h3>
          <p class="contact-success-text">We'll get back to you within one business day.</p>
        </div>
      </div>
    </div>
  </div>
</section>
```

```css
.contact-success {
  position: relative;
  text-align: center;
  padding: 48px 32px;
  background: #fff;
  border-radius: 16px;
  border: 1px solid #e2e8f0;
  display: none;
}

.contact-success.is-visible {
  display: block;
  animation: success-enter 0.5s ease-out;
}

@keyframes success-enter {
  0% { opacity: 0; transform: scale(0.9); }
  60% { transform: scale(1.02); }
  100% { opacity: 1; transform: scale(1); }
}

.contact-success-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 200px;
  height: 200px;
  border-radius: 50%;
  border: 2px solid rgba(34,197,94,0.2);
  opacity: 0;
  animation: ring-burst-success 0.8s ease-out 0.2s forwards;
}

@keyframes ring-burst-success {
  0% { transform: translate(-50%, -50%) scale(0.5); opacity: 0; }
  50% { opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 0.5; }
}

.contact-success-icon {
  position: relative;
  z-index: 1;
  width: 64px;
  height: 64px;
  margin: 0 auto 24px;
  background: linear-gradient(135deg, #22c55e, #16a34a);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.contact-success-icon svg {
  width: 32px;
  height: 32px;
  color: #fff;
}

.contact-success-title {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-text, #1e293b);
  margin-bottom: 8px;
}

.contact-success-text {
  font-size: 1rem;
  color: var(--color-text-muted, #64748b);
}
```

*JS behavior:*
```javascript
const form = document.getElementById('contact-form-success');
const successState = document.getElementById('contact-success');

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  const submitBtn = form.querySelector('.contact-submit');
  submitBtn.classList.add('is-loading');

  await new Promise(r => setTimeout(r, 1500));

  form.style.display = 'none';
  successState.hidden = false;
  successState.classList.add('is-visible');

  // Show toast
  showToast('Message sent successfully!', 'success');
});

function showToast(message, type) {
  const toast = document.createElement('div');
  toast.className = `toast toast--${type}`;
  toast.textContent = message;
  toast.style.cssText = 'position:fixed;bottom:24px;right:24px;padding:16px 24px;background:#1e293b;color:#fff;border-radius:8px;font-size:0.9rem;z-index:9999;animation:toast-in 0.3s ease';
  document.body.appendChild(toast);
  setTimeout(() => {
    toast.style.animation = 'toast-out 0.3s ease forwards';
    setTimeout(() => toast.remove(), 300);
  }, 3000);
}
```

---

**Gradient background contact.** Radial gradient section background. Contact form floats on the gradient.

*Animation & Visual Details:*
- *Entrance*: Form card scales from 0.96 → 1 with fade; background gradient animates in
- *Hover*: Input fields show gradient focus border; card lifts slightly
- *Gradients*: Section background has multi-stop radial gradient (coral, violet, cyan); card has white background
- *Radial circles*: Multi-layer radial gradient background with animated position
- *Scroll trigger*: IntersectionObserver at 20% threshold
- *JS interaction*: Background gradient position shifts slightly on mouse move

```html
<section data-amb-section="contact" class="contact-section contact-section--gradient-bg">
  <div class="contact-gradient-bg">
    <div class="contact-gradient-orb contact-gradient-orb--1"></div>
    <div class="contact-gradient-orb contact-gradient-orb--2"></div>
    <div class="contact-gradient-orb contact-gradient-orb--3"></div>
  </div>
  <div class="container">
    <div class="contact-card-wrapper">
      <div class="contact-card">
        <h2 class="contact-title">Get in touch</h2>
        <p class="contact-subtitle">We'd love to hear from you.</p>
        <form class="contact-form">
          <div class="contact-field">
            <label class="contact-label" for="name">Name</label>
            <input class="contact-input" type="text" id="name" name="name" required placeholder=" " />
          </div>
          <div class="contact-field">
            <label class="contact-label" for="email">Email</label>
            <input class="contact-input" type="email" id="email" name="email" required placeholder=" " />
          </div>
          <div class="contact-field">
            <label class="contact-label" for="message">Message</label>
            <textarea class="contact-textarea" id="message" name="message" rows="5" required placeholder=" "></textarea>
          </div>
          <button class="contact-submit" type="submit">Send message</button>
        </form>
      </div>
    </div>
  </div>
</section>
```

```css
.contact-section--gradient-bg {
  position: relative;
  padding: clamp(80px, 10vw, 120px) 0;
  overflow: hidden;
}

.contact-gradient-bg {
  position: absolute;
  inset: -20%;
  z-index: 0;
}

.contact-gradient-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  animation: orb-drift 15s ease-in-out infinite alternate;
}

.contact-gradient-orb--1 {
  width: 500px;
  height: 500px;
  top: -100px;
  left: -100px;
  background: radial-gradient(circle, rgba(255,107,107,0.4) 0%, transparent 70%);
}

.contact-gradient-orb--2 {
  width: 400px;
  height: 400px;
  top: 50%;
  right: -80px;
  background: radial-gradient(circle, rgba(168,85,247,0.35) 0%, transparent 70%);
  animation-duration: 18s;
}

.contact-gradient-orb--3 {
  width: 450px;
  height: 450px;
  bottom: -80px;
  left: 30%;
  background: radial-gradient(circle, rgba(72,219,251,0.3) 0%, transparent 70%);
  animation-duration: 12s;
}

@keyframes orb-drift {
  0% { transform: translate(0, 0); }
  100% { transform: translate(30px, -20px); }
}

.contact-card-wrapper {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
}

.contact-card {
  background: #fff;
  border-radius: 24px;
  padding: 48px;
  width: 100%;
  max-width: 520px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.08);
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 0.6s ease, transform 0.6s ease, box-shadow 0.3s ease;
}

.contact-section--gradient-bg.is-visible .contact-card {
  opacity: 1;
  transform: scale(1);
}

.contact-card:hover {
  box-shadow: 0 16px 48px rgba(0,0,0,0.12);
}

@media (prefers-reduced-motion: reduce) {
  .contact-gradient-orb {
    animation: none;
  }
}
```

---

Copy rules: tell the visitor when they'll hear back ("We reply within one business day"). Use sentence-case button text ("Send message", not "SEND MESSAGE"). Don't use CAPTCHA visually if you can use invisible/honeypot — friction kills replies.

Layout rules: inputs should be vertically stacked, not side-by-side, unless the form is over 6 fields. Labels go ABOVE inputs, not inside as placeholders.

CSS custom property summary:
```css
:root {
  --contact-enter-duration: 0.5s;
  --color-accent: #6366f1;
  --color-text: #1e293b;
  --color-text-muted: #64748b;
}
```