description Pet Registration - Complex Form

Demonstrates model lists and nested forms Async

Your full name as the pet owner
Your contact email address
home
Your home address (optional)
person_alert
Someone to contact in case of emergency
The name of your pet
collections
What type of animal is your pet?
How old is your pet? (optional)
Weight in pounds (optional - enter 0.01 for tiny pets like birds)
Is your pet up to date with vaccinations?
Does your pet have a microchip?
Specific breed of your pet (optional)
#000000
Primary color of your pet (optional)
When was the last veterinary checkup? (optional)
Describe any special care requirements (optional)
The name of your pet
collections
What type of animal is your pet?
How old is your pet? (optional)
Weight in pounds (optional - enter 0.01 for tiny pets like birds)
Is your pet up to date with vaccinations?
Does your pet have a microchip?
Specific breed of your pet (optional)
#000000
Primary color of your pet (optional)
When was the last veterinary checkup? (optional)
Describe any special care requirements (optional)

Add information about each of your pets

Debug panel (development only)
<!-- Material Design 3 Self-Contained Form -->
<style>
/* Material Design 3 Self-Contained Styles - Using !important to override any conflicting styles */
.md-form-container {
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 20px !important;
    line-height: 1.5 !important;
    color: #1c1b1f !important;
    background: #fef7ff !important;
    border: none !important;
    box-sizing: border-box !important;
    position: relative !important;
}

.md-form {
    width: 100% !important;
    background: #ffffff !important;
    border-radius: 28px !important;
    padding: 32px !important;
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 2px 6px 2px rgba(0,0,0,0.15) !important;
    border: none !important;
    margin: 0 !important;
    box-sizing: border-box !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Reset any Bootstrap interference */
.md-form * {
    box-sizing: border-box !important;
}

/* Material Design Form Fields */
.md-field {
    margin-bottom: 32px !important;
    position: relative !important;
    width: 100% !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Model list container styling to blend with Material Design */
.md-model-list-container {
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    margin: 0 !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Override Bootstrap styles for model list items within Material Design */
.md-model-list-container .card {
    border: 1px solid #79747e !important;
    border-radius: 12px !important;
    box-shadow: none !important;
    margin-bottom: 16px !important;
    background: #ffffff !important;
}

.md-model-list-container .card-header {
    background: #f7f2fa !important;
    border-bottom: 1px solid #e7e0ec !important;
    border-radius: 12px 12px 0 0 !important;
    color: #1c1b1f !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    font-weight: 500 !important;
}

.md-model-list-container .btn {
    border-radius: 20px !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    font-weight: 500 !important;
    text-transform: none !important;
}

.md-model-list-container .btn-primary {
    background: #6750a4 !important;
    border-color: #6750a4 !important;
}

.md-model-list-container .btn-danger {
    background: #ba1a1a !important;
    border-color: #ba1a1a !important;
}

.md-model-list-wrapper {
    background: transparent !important;
    margin-bottom: 32px !important;
}

.md-model-list-container {
    border: 1px solid #e7e0ec !important;
    border-radius: 24px !important;
    padding: 16px 20px !important;
    background: #fff !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08) !important;
}

.md-model-list-items {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px !important;
}

.md-model-card {
    border: 1px solid #e7e0ec !important;
    border-radius: 20px !important;
    background: #ffffff !important;
    padding: 16px 20px !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08) !important;
}

.md-model-card__header {
    display: flex !important;
    justify-content: space-between !important;
    align-items: center !important;
    margin-bottom: 12px !important;
}

.md-model-card__body {
    padding: 0 !important;
}

.md-model-list-actions {
    margin-top: 12px !important;
    display: flex !important;
    justify-content: flex-end !important;
}

.md-button-tonal {
    background: #e8def8 !important;
    color: #1c1b1f !important;
}

.md-button-tonal:hover {
    background: #cdc2db !important;
}

.md-button__icon {
    margin-right: 8px !important;
    width: 20px !important;
    height: 20px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex: 0 0 20px !important;
    fill: currentColor !important;
}

.md-button__label {
    font-weight: 500 !important;
}

/* Layout card styling */
.md-layout-card {
    background: #ffffff !important;
    border-radius: 24px !important;
    padding: 24px 28px !important;
    margin-bottom: 32px !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2), 0 4px 8px rgba(0,0,0,0.1) !important;
    border: 1px solid #e7e0ec !important;
}

.md-layout-card__header {
    margin-bottom: 12px !important;
}

.md-layout-card__title {
    font-size: 18px !important;
    font-weight: 600 !important;
    color: #1c1b1f !important;
}

.md-layout-card__help {
    color: #49454f !important;
    font-size: 14px !important;
    margin-bottom: 12px !important;
}

.md-layout-card__content {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px !important;
}

.md-field-label {
    display: block !important;
    color: #49454f !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    margin-bottom: 8px !important;
    position: relative !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    line-height: 1.4 !important;
}

.md-field-label.required::after {
    content: ' *' !important;
    color: #ba1a1a !important;
}

/* Material Design Outlined Text Fields */
.md-text-field {
    position: relative;
    width: 100%;
}

/* Field container */
.md-field {
    margin: 16px 0;
}

/* Field with icon layout */
.md-field-with-icon {
    display: flex !important;
    align-items: flex-start !important;
    gap: 12px !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Input wrapper for proper label positioning */
.md-input-wrapper {
    position: relative !important;
    flex: 1 !important;
    width: 100% !important;
}

.md-input {
    width: 100% !important;
    padding: 16px !important;
    border: 1px solid #79747e !important;
    border-radius: 4px !important;
    background: transparent !important;
    color: #1c1b1f !important;
    font-size: 16px !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    outline: none !important;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
    box-sizing: border-box !important;
    line-height: 1.5 !important;
    margin: 0 !important;
}

.md-input:focus {
    border-color: #6750a4 !important;
    border-width: 2px !important;
    padding: 15px !important; /* Adjust for thicker border */
    box-shadow: none !important;
}

/* Icon styling - positioned outside to the left of input */
.md-icon {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 24px !important;
    height: 24px !important;
    margin-top: 16px !important; /* Align with input padding */
    color: #49454f !important;
    flex-shrink: 0 !important;
    transition: color 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
    fill: currentColor !important;
}

.md-field-with-icon:focus-within .md-icon {
    color: #6750a4 !important;
}

.md-input:focus + .md-floating-label,
.md-input:not(:placeholder-shown) + .md-floating-label,
.md-textarea:focus + .md-floating-label,
.md-textarea:not(:placeholder-shown) + .md-floating-label,
.md-select:focus + .md-floating-label {
    transform: translateY(-28px) scale(0.75) !important;
    color: #6750a4 !important;
    background: #ffffff !important;
    padding: 0 4px !important;
}

.md-floating-label {
    position: absolute !important;
    left: 16px !important;
    top: 16px !important;
    color: #49454f !important;
    font-size: 16px !important;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
    pointer-events: none !important;
    background: transparent !important;
    z-index: 1 !important;
    transform-origin: left top !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    font-weight: 400 !important;
    line-height: 1.4 !important;
}

.md-input:focus + .md-floating-label,
.md-input:not(:placeholder-shown) + .md-floating-label {
    transform: translateY(-28px) scale(0.75) !important;
    color: #6750a4;
    background: #ffffff;
    padding: 0 4px;
}

.md-input.error {
    border-color: #ba1a1a;
}

.md-input.error:focus {
    border-color: #ba1a1a;
}

.md-input.error + .md-floating-label {
    color: #ba1a1a;
}

/* Material Design Select */
.md-select {
    width: 100%;
    padding: 16px;
    border: 1px solid #79747e;
    border-radius: 4px;
    background: transparent;
    color: #1c1b1f;
    font-size: 16px;
    font-family: inherit;
    outline: none;
    cursor: pointer;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    box-sizing: border-box;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2349454f' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
    background-position: right 12px center;
    background-repeat: no-repeat;
    background-size: 16px;
    padding-right: 40px;
}

.md-select:focus {
    border-color: #6750a4;
    border-width: 2px;
    padding: 15px 39px 15px 15px; /* Adjust for thicker border */
}

.md-select:focus + .md-floating-label {
    transform: translateY(-28px) scale(0.75);
    color: #6750a4;
    background: #ffffff;
    padding: 0 4px;
}

/* Material Design Textarea */
.md-textarea {
    width: 100%;
    min-height: 120px;
    padding: 16px;
    border: 1px solid #79747e;
    border-radius: 4px;
    background: transparent;
    color: #1c1b1f;
    font-size: 16px;
    font-family: inherit;
    outline: none;
    resize: vertical;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    box-sizing: border-box;
}

.md-textarea:focus {
    border-color: #6750a4;
    border-width: 2px;
    padding: 15px; /* Adjust for thicker border */
}

.md-textarea:focus + .md-floating-label,
.md-textarea:not(:placeholder-shown) + .md-floating-label {
    transform: translateY(-28px) scale(0.75);
    color: #6750a4;
    background: #ffffff;
    padding: 0 4px;
}

/* Material Design Checkboxes */
.md-checkbox-container {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    margin: 16px 0;
    cursor: pointer;
}

.md-checkbox {
    width: 18px;
    height: 18px;
    border: 2px solid #79747e;
    border-radius: 2px;
    background: transparent;
    cursor: pointer;
    position: relative;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    margin-top: 2px; /* Align with text baseline */
    flex-shrink: 0;
}

.md-checkbox:checked {
    background: #6750a4;
    border-color: #6750a4;
}

.md-checkbox:checked::after {
    content: '';
    position: absolute;
    top: 1px;
    left: 4px;
    width: 6px;
    height: 10px;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.md-checkbox-label {
    color: #1c1b1f;
    font-size: 16px;
    cursor: pointer;
    line-height: 1.5;
}

/* Material Design Buttons */
.md-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10px 24px;
    border: none;
    border-radius: 20px;
    font-size: 14px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    text-decoration: none;
    box-sizing: border-box;
    min-width: 64px;
    height: 40px;
    position: relative;
    overflow: hidden;
}

.md-button-filled {
    background: #6750a4;
    color: #ffffff;
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 1px 3px 1px rgba(0,0,0,0.15);
}

.md-button-filled:hover {
    background: #5a43a0;
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 2px 6px 2px rgba(0,0,0,0.15);
    transform: translateY(-1px);
}

.md-button-filled:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 1px 3px 1px rgba(0,0,0,0.15);
}

/* Help Text */
.md-help-text {
    font-size: 12px;
    color: #49454f;
    margin-top: 4px;
    line-height: 1.33;
    padding-left: 16px;
}

/* Error Text */
.md-error-text {
    font-size: 12px;
    color: #ba1a1a;
    margin-top: 4px;
    line-height: 1.33;
    font-weight: 400;
    padding-left: 16px;
}

/* Number and Date Inputs */
.md-input[type="number"],
.md-input[type="date"],
.md-input[type="email"],
.md-input[type="password"],
.md-input[type="tel"],
.md-input[type="url"] {
    /* Inherit all md-input styles */
}

.md-input[type="color"] {
    height: 56px;
    padding: 8px;
    cursor: pointer;
}

.md-input[type="range"] {
    padding: 16px 8px;
}

/* Placeholder styling */
.md-input::placeholder {
    color: transparent;
}

.md-input:focus::placeholder {
    color: #49454f;
}

/* State layers for interactive elements */
.md-button-filled::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: currentColor;
    opacity: 0;
    transition: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    border-radius: inherit;
}

.md-button-filled:hover::before {
    opacity: 0.08;
}

.md-button-filled:focus::before {
    opacity: 0.12;
}

.md-button-filled:active::before {
    opacity: 0.16;
}

/* Responsive Design */
@media (max-width: 768px) {
    .md-form {
        padding: 24px 16px;
        border-radius: 28px;
    }

    .md-field {
        margin-bottom: 24px;
    }
}

/* Typography Scale */
.md-headline-small {
    font-size: 24px;
    font-weight: 400;
    line-height: 32px;
    color: #1c1b1f;
}

.md-body-large {
    font-size: 16px;
    font-weight: 400;
    line-height: 24px;
    color: #1c1b1f;
}

.md-body-medium {
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
    color: #49454f;
}

.md-label-large {
    font-size: 14px;
    font-weight: 500;
    line-height: 20px;
    color: #1c1b1f;
}

/* Surface colors and elevation */
.md-surface {
    background: #fef7ff;
    color: #1c1b1f;
}

.md-surface-container {
    background: #f3f0ff;
    color: #1c1b1f;
}

.md-surface-container-high {
    background: #e7e0ec;
    color: #1c1b1f;
}
</style>

<div class="md-form-container">

<form id=""
      class="pydantic-form md-form col s12"
      style=""
      method="POST"
      action="/pets"
      novalidate>
    
    
<div class="md-field">
    
<div class="md-field-with-icon">
    <svg class="material-icons md-icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" /></svg>
    
<div class="md-input-wrapper">
    
<input type="text"
       name="owner_name"
       id="owner_name"
       class="md-input"
       value="Sarah Mitchell"
        placeholder=" " >

    <label class="md-floating-label" for="owner_name">Owner Name *</label>
</div>

</div>

    
<div class="md-help-text">Your full name as the pet owner</div>

    
</div>


<div class="md-field">
    
<div class="md-field-with-icon">
    <svg class="material-icons md-icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4-8 5-8-5V6l8 5 8-5v2z" /></svg>
    
<div class="md-input-wrapper">
    
<input type="email"
       name="email"
       id="email"
       class="md-input"
       value="sarah.mitchell@example.com"
        placeholder=" " >

    <label class="md-floating-label" for="email">Email Address *</label>
</div>

</div>

    
<div class="md-help-text">Your contact email address</div>

    
</div>


<div class="md-field">
    
<div class="md-field-with-icon">
    <span class="material-icons md-icon">home</span>
    
<div class="md-input-wrapper">
    
<textarea name="address"
          id="address"
          class="md-textarea"
          placeholder=" ">123 Main Street
Apt 4B
Springfield, IL 62701</textarea>

    <label class="md-floating-label" for="address">Address</label>
</div>

</div>

    
<div class="md-help-text">Your home address (optional)</div>

    
</div>


<div class="md-field">
    
<div class="md-field-with-icon">
    <span class="material-icons md-icon">person_alert</span>
    
<div class="md-input-wrapper">
    
<input type="text"
       name="emergency_contact"
       id="emergency_contact"
       class="md-input"
       value="John Mitchell - (555) 123-4567"
        placeholder=" " >

    <label class="md-floating-label" for="emergency_contact">Emergency Contact</label>
</div>

</div>

    
<div class="md-help-text">Someone to contact in case of emergency</div>

    
</div>


<div class="md-field">
    <div class="md-model-list-container">
        <section class="md-model-list-wrapper">
  <label class="md-field-label required">Your Pets</label>
  <div class="model-list-container md-model-list-container" data-field-name="pets"        data-min-items="1" data-max-items="10">
    <div class="model-list-items md-model-list-items"          id="pets-items">
      
        <div class="model-list-item card border mb-3"
             data-index="0"
             data-title-template="Pet #{index}: {name}"
             data-field-name="pets">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h6 class="mb-0">
                    <button class="btn btn-link text-decoration-none p-0 text-start"
                            type="button"
                            data-bs-toggle="collapse"
                            data-bs-target="#pets_item_0_content"
                            aria-expanded="false"
                            aria-controls="pets_item_0_content">
                        <i class="bi bi-chevron-right me-2"></i>
                        <i class="bi bi-card-list me-2"></i>
                        Pet #1: Max
                    </button>
                </h6>
                <button type="button"
                        class="btn btn-outline-danger btn-sm remove-item-btn"
                        data-index="0"
                        data-field-name="pets"
                        title="Remove this item">
                    <i class="bi bi-trash"></i>
                </button>
            </div>
            <div class="collapse collapse show" id="pets_item_0_content">
                <div class="card-body"><div class="row">
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].name"><i class="material-icons">favorite_border</i> Pet&#x27;s Name</label>
<input name="pets[0].name" id="pets[0].name" class="validate" value="Max" minlength="1" maxlength="11" placeholder="Enter your pet's name" pattern="\d{3}-\d{2}-\d{4}" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">The name of your pet</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><div class="md-field">
<div class="md-field-with-icon">
<span class="md-icon material-icons">collections</span>
<div class="md-input-wrapper">
<select name="pets[0].species" id="pets[0].species" class="browser-default"><option value="Dog" selected>Dog 🐕</option>
<option value="Cat">Cat 🐱</option>
<option value="Bird">Bird 🐦</option>
<option value="Fish">Fish 🐠</option>
<option value="Rabbit">Rabbit 🐰</option>
<option value="Hamster">Hamster 🐹</option>
<option value="Reptile">Reptile 🦎</option>
<option value="Other">Other 🐾</option></select>
<label class="md-floating-label" for="pets[0].species">Species</label>
</div>
</div>
<div class="md-help-text">What type of animal is your pet?</div>
</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].age"><i class="material-icons">calendar_today</i> Age</label>
<input name="pets[0].age" id="pets[0].age" class="validate" value="3" placeholder="Pet's age in years%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">How old is your pet? (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].weight"><i class="material-icons">speed</i> Weight (lbs)</label>
<input name="pets[0].weight" id="pets[0].weight" class="validate" value="65.5" placeholder="Pet's weight%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">Weight in pounds (optional - enter 0.01 for tiny pets like birds)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].is_vaccinated"><i class="material-icons">verified_user</i> Vaccinated</label>
<input name="pets[0].is_vaccinated" id="pets[0].is_vaccinated" class="filled-in" value="1" type="checkbox" />
<div class="help-text">Is your pet up to date with vaccinations?</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].microchipped"><i class="material-icons">memory</i> Microchipped</label>
<input name="pets[0].microchipped" id="pets[0].microchipped" class="filled-in" checked="checked" value="1" type="checkbox" />
<div class="help-text">Does your pet have a microchip?</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].breed"><i class="material-icons">military_tech</i> Breed</label>
<input name="pets[0].breed" id="pets[0].breed" class="validate" value="Golden Retriever" placeholder="e.g., Golden Retriever, Persian Cat" pattern="\d{3}-\d{2}-\d{4}" maxlength="11" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">Specific breed of your pet (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].color"><i class="material-icons">palette</i> Primary Color</label>
<div class="color-input-group"><input name="pets[0].color" id="pets[0].color" class="validate" value="#000000" type="color" />
            <div class="color-value-display" style="display: inline-flex; align-items: center; margin-left: 10px;">
                <span id="pets[0].color_value" style="font-family: monospace;">#000000</span>
                <div id="pets[0].color_swatch" style="width: 20px; height: 20px; background-color: #000000; border: 1px solid #ccc; margin-left: 5px;"></div>
            </div>
            <script>
            document.addEventListener('DOMContentLoaded', function() {
                const colorInput = document.getElementById('pets[0].color');
                const valueSpan = document.getElementById('pets[0].color_value');
                const swatch = document.getElementById('pets[0].color_swatch');

                if (colorInput && valueSpan && swatch) {
                    colorInput.addEventListener('input', function() {
                        valueSpan.textContent = this.value;
                        swatch.style.backgroundColor = this.value;
                    });
                }
            });
            </script>
            </div>
<div class="help-text">Primary color of your pet (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].last_vet_visit"><i class="material-icons">event</i> Last Vet Visit</label>
<div class="birthdate-input-group"><input name="pets[0].last_vet_visit" id="pets[0].last_vet_visit" class="validate" value="2026-01-03" max="2026-01-07" min="1876-01-01" type="date" />
            <div class="age-display" id="pets[0].last_vet_visit_age" style="margin-top: 5px; font-size: 0.9em; color: #666;"></div>
            <script>
            document.addEventListener('DOMContentLoaded', function() {
                const birthdateField = document.getElementById('pets[0].last_vet_visit');
                const ageDisplay = document.getElementById('pets[0].last_vet_visit_age');

                function calculateAge() {
                    if (birthdateField.value && ageDisplay) {
                        const birthDate = new Date(birthdateField.value);
                        const today = new Date();
                        let age = today.getFullYear() - birthDate.getFullYear();
                        const monthDiff = today.getMonth() - birthDate.getMonth();

                        if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
                            age--;
                        }

                        ageDisplay.textContent = age >= 0 ? `Age: ${age} years` : '';
                    }
                }

                if (birthdateField) {
                    birthdateField.addEventListener('change', calculateAge);
                    calculateAge(); // Calculate on load if value is set
                }
            });
            </script>
            </div>
<div class="help-text">When was the last veterinary checkup? (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[0].special_needs"><i class="material-icons">monitor_heart</i> Special Needs</label>
<textarea name="pets[0].special_needs" id="pets[0].special_needs" class="validate" placeholder="Any special care requirements, medications, allergies, etc.">Allergic to chicken-based foods</textarea>
<div class="help-text">Describe any special care requirements (optional)</div></div>
                </div></div>
                </div>
            </div>
        </div>
        <div class="model-list-item card border mb-3"
             data-index="1"
             data-title-template="Pet #{index}: {name}"
             data-field-name="pets">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h6 class="mb-0">
                    <button class="btn btn-link text-decoration-none p-0 text-start"
                            type="button"
                            data-bs-toggle="collapse"
                            data-bs-target="#pets_item_1_content"
                            aria-expanded="false"
                            aria-controls="pets_item_1_content">
                        <i class="bi bi-chevron-right me-2"></i>
                        <i class="bi bi-card-list me-2"></i>
                        Pet #2: Luna
                    </button>
                </h6>
                <button type="button"
                        class="btn btn-outline-danger btn-sm remove-item-btn"
                        data-index="1"
                        data-field-name="pets"
                        title="Remove this item">
                    <i class="bi bi-trash"></i>
                </button>
            </div>
            <div class="collapse collapse show" id="pets_item_1_content">
                <div class="card-body"><div class="row">
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].name"><i class="material-icons">favorite_border</i> Pet&#x27;s Name</label>
<input name="pets[1].name" id="pets[1].name" class="validate" value="Luna" minlength="1" maxlength="11" placeholder="Enter your pet's name" pattern="\d{3}-\d{2}-\d{4}" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">The name of your pet</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><div class="md-field">
<div class="md-field-with-icon">
<span class="md-icon material-icons">collections</span>
<div class="md-input-wrapper">
<select name="pets[1].species" id="pets[1].species" class="browser-default"><option value="Dog" selected>Dog 🐕</option>
<option value="Cat">Cat 🐱</option>
<option value="Bird">Bird 🐦</option>
<option value="Fish">Fish 🐠</option>
<option value="Rabbit">Rabbit 🐰</option>
<option value="Hamster">Hamster 🐹</option>
<option value="Reptile">Reptile 🦎</option>
<option value="Other">Other 🐾</option></select>
<label class="md-floating-label" for="pets[1].species">Species</label>
</div>
</div>
<div class="md-help-text">What type of animal is your pet?</div>
</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].age"><i class="material-icons">calendar_today</i> Age</label>
<input name="pets[1].age" id="pets[1].age" class="validate" value="2" placeholder="Pet's age in years%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">How old is your pet? (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].weight"><i class="material-icons">speed</i> Weight (lbs)</label>
<input name="pets[1].weight" id="pets[1].weight" class="validate" value="8.5" placeholder="Pet's weight%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="help-text">Weight in pounds (optional - enter 0.01 for tiny pets like birds)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].is_vaccinated"><i class="material-icons">verified_user</i> Vaccinated</label>
<input name="pets[1].is_vaccinated" id="pets[1].is_vaccinated" class="filled-in" value="1" type="checkbox" />
<div class="help-text">Is your pet up to date with vaccinations?</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].microchipped"><i class="material-icons">memory</i> Microchipped</label>
<input name="pets[1].microchipped" id="pets[1].microchipped" class="filled-in" checked="checked" value="1" type="checkbox" />
<div class="help-text">Does your pet have a microchip?</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].breed"><i class="material-icons">military_tech</i> Breed</label>
<input name="pets[1].breed" id="pets[1].breed" class="validate" value="Siamese" placeholder="e.g., Golden Retriever, Persian Cat" pattern="\d{3}-\d{2}-\d{4}" maxlength="11" inputmode="numeric" autocomplete="off" type="text" />
<div class="help-text">Specific breed of your pet (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].color"><i class="material-icons">palette</i> Primary Color</label>
<div class="color-input-group"><input name="pets[1].color" id="pets[1].color" class="validate" value="#000000" type="color" />
            <div class="color-value-display" style="display: inline-flex; align-items: center; margin-left: 10px;">
                <span id="pets[1].color_value" style="font-family: monospace;">#000000</span>
                <div id="pets[1].color_swatch" style="width: 20px; height: 20px; background-color: #000000; border: 1px solid #ccc; margin-left: 5px;"></div>
            </div>
            <script>
            document.addEventListener('DOMContentLoaded', function() {
                const colorInput = document.getElementById('pets[1].color');
                const valueSpan = document.getElementById('pets[1].color_value');
                const swatch = document.getElementById('pets[1].color_swatch');

                if (colorInput && valueSpan && swatch) {
                    colorInput.addEventListener('input', function() {
                        valueSpan.textContent = this.value;
                        swatch.style.backgroundColor = this.value;
                    });
                }
            });
            </script>
            </div>
<div class="help-text">Primary color of your pet (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].last_vet_visit"><i class="material-icons">event</i> Last Vet Visit</label>
<div class="birthdate-input-group"><input name="pets[1].last_vet_visit" id="pets[1].last_vet_visit" class="validate" value="2026-01-04" max="2026-01-07" min="1876-01-01" type="date" />
            <div class="age-display" id="pets[1].last_vet_visit_age" style="margin-top: 5px; font-size: 0.9em; color: #666;"></div>
            <script>
            document.addEventListener('DOMContentLoaded', function() {
                const birthdateField = document.getElementById('pets[1].last_vet_visit');
                const ageDisplay = document.getElementById('pets[1].last_vet_visit_age');

                function calculateAge() {
                    if (birthdateField.value && ageDisplay) {
                        const birthDate = new Date(birthdateField.value);
                        const today = new Date();
                        let age = today.getFullYear() - birthDate.getFullYear();
                        const monthDiff = today.getMonth() - birthDate.getMonth();

                        if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
                            age--;
                        }

                        ageDisplay.textContent = age >= 0 ? `Age: ${age} years` : '';
                    }
                }

                if (birthdateField) {
                    birthdateField.addEventListener('change', calculateAge);
                    calculateAge(); // Calculate on load if value is set
                }
            });
            </script>
            </div>
<div class="help-text">When was the last veterinary checkup? (optional)</div></div>
                </div>
                <div class="col-lg-4 col-md-6">
                    <div class="input-field col s12"><label for="pets[1].special_needs"><i class="material-icons">monitor_heart</i> Special Needs</label>
<textarea name="pets[1].special_needs" id="pets[1].special_needs" class="validate" placeholder="Any special care requirements, medications, allergies, etc.">Indoor only, needs daily medication for thyroid</textarea>
<div class="help-text">Describe any special care requirements (optional)</div></div>
                </div></div>
                </div>
            </div>
        </div>
    </div>
    <div class="md-model-list-actions">
      <button type="button" class="md-button md-button-tonal add-item-btn"               data-target="pets">
        <svg class="material-icons md-button__icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M19 13H13v6h-2v-6H5v-2h6V5h2v6h6v2z" /></svg>
        <span class="md-button__label">Add Item</span>
      </button>
    </div>
  </div>
  <p class="md-help-text">Add information about each of your pets</p>
</section>
    </div>
</div>

    
<div class="md-field">
    <button type="submit" class="md-button md-button-filled">Submit</button>
</div>

</form>

</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
    // Material Design 3 form enhancements

    // Floating label functionality for outlined text fields
    function initializeFloatingLabels() {
        const textFields = document.querySelectorAll('.md-input, .md-textarea, .md-select');

        textFields.forEach(input => {
            const label = input.nextElementSibling;
            if (label && label.classList.contains('md-floating-label')) {

                // Check initial state
                function updateLabelState() {
                    const hasValue = input.value && input.value.trim() !== '';
                    const isFocused = document.activeElement === input;

                    if (hasValue || isFocused) {
                        label.style.transform = 'translateY(-28px) scale(0.75)';
                        label.style.color = isFocused ? '#6750a4' : '#49454f';
                        label.style.background = '#ffffff';
                        label.style.padding = '0 4px';
                    } else {
                        label.style.transform = 'translateY(0) scale(1)';
                        label.style.color = '#49454f';
                        label.style.background = 'transparent';
                        label.style.padding = '0';
                    }
                }

                // Set up event listeners
                input.addEventListener('focus', updateLabelState);
                input.addEventListener('blur', updateLabelState);
                input.addEventListener('input', updateLabelState);

                // Initial state check
                updateLabelState();
            }
        });
    }

    // Enhanced focus and blur effects
    const inputs = document.querySelectorAll('.md-input, .md-select, .md-textarea');
    inputs.forEach(input => {
        input.addEventListener('focus', function() {
            this.style.transform = 'scale(1.01)';
            this.style.transition = 'all 0.15s cubic-bezier(0.4, 0, 0.2, 1)';
        });

        input.addEventListener('blur', function() {
            this.style.transform = 'scale(1)';
        });
    });

    // Checkbox interactions with Material Design ripple effect
    const checkboxes = document.querySelectorAll('.md-checkbox');
    checkboxes.forEach(checkbox => {
        checkbox.addEventListener('change', function() {
            const container = this.closest('.md-checkbox-container');
            if (this.checked) {
                // Create ripple effect
                const ripple = document.createElement('div');
                ripple.style.position = 'absolute';
                ripple.style.borderRadius = '50%';
                ripple.style.background = 'rgba(103, 80, 164, 0.3)';
                ripple.style.width = '40px';
                ripple.style.height = '40px';
                ripple.style.left = '-11px';
                ripple.style.top = '-11px';
                ripple.style.pointerEvents = 'none';
                ripple.style.transform = 'scale(0)';
                ripple.style.transition = 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)';

                this.style.position = 'relative';
                this.appendChild(ripple);

                // Animate ripple
                setTimeout(() => {
                    ripple.style.transform = 'scale(1)';
                    setTimeout(() => {
                        ripple.style.opacity = '0';
                        setTimeout(() => {
                            if (ripple.parentNode) {
                                ripple.parentNode.removeChild(ripple);
                            }
                        }, 300);
                    }, 200);
                }, 10);
            }
        });
    });

    // Enhanced form validation with Material Design styling
    const form = document.querySelector('.md-form');
    if (form) {
        form.addEventListener('submit', function(e) {
            const requiredInputs = this.querySelectorAll('input[required], select[required], textarea[required]');
            let hasErrors = false;

            requiredInputs.forEach(input => {
                const value = input.type === 'checkbox' ? input.checked : input.value.trim();
                const fieldContainer = input.closest('.md-field');

                if (!value) {
                    input.classList.add('error');

                    // Add error styling to label
                    const label = input.nextElementSibling;
                    if (label && label.classList.contains('md-floating-label')) {
                        label.style.color = '#ba1a1a';
                    }

                    // Create or update error message
                    let errorDiv = fieldContainer.querySelector('.md-error-text');
                    if (!errorDiv) {
                        errorDiv = document.createElement('div');
                        errorDiv.className = 'md-error-text';
                        fieldContainer.appendChild(errorDiv);
                    }
                    errorDiv.textContent = 'This field is required';

                    hasErrors = true;
                } else {
                    input.classList.remove('error');

                    // Remove error styling from label
                    const label = input.nextElementSibling;
                    if (label && label.classList.contains('md-floating-label')) {
                        label.style.color = input === document.activeElement ? '#6750a4' : '#49454f';
                    }

                    // Remove error message if it was dynamically added
                    const errorDiv = fieldContainer.querySelector('.md-error-text');
                    if (errorDiv && errorDiv.textContent === 'This field is required') {
                        errorDiv.remove();
                    }
                }
            });

            if (hasErrors) {
                e.preventDefault();
                // Scroll to first error with smooth animation
                const firstError = this.querySelector('.error');
                if (firstError) {
                    firstError.scrollIntoView({
                        behavior: 'smooth',
                        block: 'center',
                        inline: 'nearest'
                    });
                    // Focus the field for better UX
                    setTimeout(() => {
                        firstError.focus();
                    }, 500);
                }
            }
        });

        // Real-time validation for better UX
        const allInputs = form.querySelectorAll('input, select, textarea');
        allInputs.forEach(input => {
            input.addEventListener('blur', function() {
                if (this.hasAttribute('required')) {
                    const value = this.type === 'checkbox' ? this.checked : this.value.trim();
                    const fieldContainer = this.closest('.md-field');

                    if (!value) {
                        this.classList.add('error');
                        const label = this.nextElementSibling;
                        if (label && label.classList.contains('md-floating-label')) {
                            label.style.color = '#ba1a1a';
                        }
                    } else {
                        this.classList.remove('error');
                        const label = this.nextElementSibling;
                        if (label && label.classList.contains('md-floating-label')) {
                            label.style.color = '#49454f';
                        }
                    }
                }
            });
        });
    }

    # Initialize floating labels
    initializeFloatingLabels();

    # Reinitialize for dynamically added content
    window.reinitializeMaterialForms = function() {
        initializeFloatingLabels();
    };
});
</script>


<script>
(function() {
    document.addEventListener('DOMContentLoaded', function() {
        // Prevent Enter key from submitting forms unless on submit button
        const forms = document.querySelectorAll('form.md-form, form.pydantic-form');
        forms.forEach(function(form) {
            form.addEventListener('keydown', function(e) {
                // Check if Enter key is pressed
                if (e.key === 'Enter' || e.keyCode === 13) {
                    const target = e.target;

                    // Allow Enter in textareas (for multi-line input)
                    if (target.tagName === 'TEXTAREA') {
                        return;
                    }

                    // Allow Enter on submit buttons
                    if (target.tagName === 'BUTTON' && target.type === 'submit') {
                        return;
                    }

                    // Allow Enter on input type="submit"
                    if (target.tagName === 'INPUT' && target.type === 'submit') {
                        return;
                    }

                    // Prevent form submission for all other cases
                    e.preventDefault();
                    return false;
                }
            });
        });
    });
})();
</script>


        <script>
        (function() {
            'use strict';

            // Ensure this runs after DOM is loaded
            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', initializeModelLists);
            } else {
                initializeModelLists();
            }

            function initializeModelLists() {
                // Add item functionality
                const addButtons = document.querySelectorAll('.add-item-btn');
                addButtons.forEach(button => {
                    if (!button.hasAttribute('data-initialized')) {
                        button.setAttribute('data-initialized', 'true');
                        button.addEventListener('click', handleAddItem);
                    }
                });

                // Remove item functionality - use direct event listeners
                const removeButtons = document.querySelectorAll('.remove-item-btn');
                removeButtons.forEach(button => {
                    if (!button.hasAttribute('data-initialized')) {
                        button.setAttribute('data-initialized', 'true');
                        button.addEventListener('click', handleRemoveItem);
                    }
                });

                // Also set up delegation for dynamically added buttons
                document.addEventListener('click', function(e) {
                    if (e.target.closest('.remove-item-btn') && !e.target.closest('.remove-item-btn').hasAttribute('data-initialized')) {
                        const button = e.target.closest('.remove-item-btn');
                        button.setAttribute('data-initialized', 'true');
                        handleRemoveItem.call(button, e);
                    }
                });
            }

            function handleAddItem(e) {
                e.preventDefault();
                e.stopPropagation();

                const fieldName = this.dataset.target;
                const container = document.querySelector(`[data-field-name="${fieldName}"]`);
                if (!container) return;

                const itemsContainer = container.querySelector('.model-list-items');
                const maxItems = parseInt(container.dataset.maxItems || '10');
                const currentItems = itemsContainer.querySelectorAll('.model-list-item').length;

                if (currentItems >= maxItems) {
                    alert(`Maximum ${maxItems} items allowed.`);
                    return;
                }

                addNewListItem(fieldName, currentItems);
                updateItemIndices(itemsContainer);
            }

            function handleRemoveItem(e) {
                e.preventDefault();
                e.stopPropagation();

                const button = e.currentTarget || this;
                const item = button.closest('.model-list-item');
                if (!item) return;

                const container = item.closest('.model-list-container');
                if (!container) return;

                const minItems = parseInt(container.dataset.minItems || '0');
                const itemsContainer = container.querySelector('.model-list-items');
                const currentItems = itemsContainer.querySelectorAll('.model-list-item').length;

                if (currentItems <= minItems) {
                    alert(`Minimum ${minItems} items required.`);
                    return;
                }

                // Check if item has data
                const hasData = Array.from(item.querySelectorAll('input, select, textarea')).some(input => {
                    if (input.type === 'checkbox' || input.type === 'radio') {
                        return input.checked;
                    }
                    return input.value && input.value.trim() !== '';
                });

                if (hasData) {
                    if (!confirm('Are you sure you want to remove this item? All data will be lost.')) {
                        return;
                    }
                }

                item.remove();
                updateItemIndices(itemsContainer);
            }

            // Update titles when input fields change
            document.addEventListener('input', function(e) {
                if (e.target.name && (e.target.name.includes('.name') || e.target.name.includes('.relationship'))) {
                    updateItemTitle(e.target);
                }
            });

            // Handle collapse icons
            document.addEventListener('click', function(e) {
                const collapseButton = e.target.closest('[data-bs-toggle="collapse"]');
                if (collapseButton) {
                    const icon = collapseButton.querySelector('.bi-chevron-down, .bi-chevron-right');
                    if (icon) {
                        setTimeout(() => {
                            const isExpanded = collapseButton.getAttribute('aria-expanded') === 'true';
                            icon.className = isExpanded ? 'bi bi-chevron-down me-2' : 'bi bi-chevron-right me-2';
                        }, 50);
                    }
                }
            });
        })();

        function addNewListItem(fieldName, index) {
            const container = document.querySelector(`[data-field-name="${fieldName}"]`);
            const itemsContainer = container.querySelector('.model-list-items');

            // Get the first item as a template if it exists
            const firstItem = itemsContainer.querySelector('.model-list-item');
            if (firstItem) {
                const newItem = firstItem.cloneNode(true);

                // Clear all input values
                newItem.querySelectorAll('input, select, textarea').forEach(input => {
                    if (input.type === 'checkbox' || input.type === 'radio') {
                        input.checked = false;
                    } else {
                        input.value = '';
                    }
                });

                // Update data-index
                newItem.dataset.index = index;

                // Update field names and IDs
                updateFieldNames(newItem, fieldName, index);

                // Update collapse IDs
                updateCollapseIds(newItem, fieldName, index);

                // Expand the new item
                const collapseDiv = newItem.querySelector('.collapse');
                if (collapseDiv) {
                    collapseDiv.classList.add('show');
                }

                // Update collapse button aria-expanded
                const collapseButton = newItem.querySelector('[data-bs-toggle="collapse"]');
                if (collapseButton) {
                    collapseButton.setAttribute('aria-expanded', 'true');
                    const icon = collapseButton.querySelector('.bi-chevron-down, .bi-chevron-right');
                    if (icon) {
                        icon.className = 'bi bi-chevron-down me-2';
                    }
                }

                itemsContainer.appendChild(newItem);
            }
        }

        function updateItemIndices(container) {
            const items = container.querySelectorAll('.model-list-item');
            items.forEach((item, index) => {
                item.dataset.index = index;

                // Update field names first
                const fieldName = container.closest('.model-list-container').dataset.fieldName;
                updateFieldNames(item, fieldName, index);
                updateCollapseIds(item, fieldName, index);

                // Update title using the dynamic template
                updateItemTitleFromData(item, index);
            });
        }

        function updateFieldNames(item, fieldName, index) {
            item.querySelectorAll('input, select, textarea').forEach(input => {
                if (input.name) {
                    // Update name attribute to use correct index
                    input.name = input.name.replace(/\[\d+\]/, `[${index}]`);
                }
                if (input.id) {
                    // Update id attribute
                    input.id = input.id.replace(/\[\d+\]/, `[${index}]`);
                }
            });

            item.querySelectorAll('label').forEach(label => {
                if (label.getAttribute('for')) {
                    label.setAttribute('for', label.getAttribute('for').replace(/\[\d+\]/, `[${index}]`));
                }
            });
        }

        function updateCollapseIds(item, fieldName, index) {
            const collapseDiv = item.querySelector('.collapse');
            const collapseButton = item.querySelector('[data-bs-toggle="collapse"]');

            if (collapseDiv && collapseButton) {
                const newId = `${fieldName}_item_${index}_content`;
                collapseDiv.id = newId;
                collapseButton.setAttribute('data-bs-target', `#${newId}`);
                collapseButton.setAttribute('aria-controls', newId);
            }
        }

        function updateItemTitle(inputElement) {
            const item = inputElement.closest('.model-list-item');
            if (!item) return;

            updateItemTitleFromData(item);
        }

        function updateItemTitleFromData(item, forceIndex = null) {
            const index = forceIndex !== null ? forceIndex : parseInt(item.dataset.index);
            const titleTemplate = item.dataset.titleTemplate || 'Item #{index}';
            const titleElement = item.querySelector('h6 button, h6 span');

            if (!titleElement) return;

            // Extract current form data from the item
            const formData = { index: index + 1 };
            item.querySelectorAll('input, select, textarea').forEach(input => {
                if (input.name) {
                    // Extract field name (e.g., "pets[0].name" -> "name")
                    const fieldMatch = input.name.match(/\.([^.]+)$/);
                    if (fieldMatch) {
                        const fieldName = fieldMatch[1];
                        if (input.type === 'checkbox') {
                            formData[fieldName] = input.checked;
                        } else {
                            formData[fieldName] = input.value || '';
                        }
                    }
                }
            });

            // Generate title from template
            let newTitle;
            try {
                newTitle = titleTemplate.replace(/\{([^}]+)\}/g, (match, key) => {
                    return formData[key] || '';
                });
            } catch (e) {
                newTitle = `Item #${index + 1}`;
            }

            // Update the title while preserving icons
            const cardIcon = '<i class="bi bi-card-list me-2"></i>';
            if (titleElement.tagName === 'BUTTON') {
                const chevronIcon = titleElement.querySelector('.bi-chevron-down, .bi-chevron-right');
                const chevronHtml = chevronIcon ? chevronIcon.outerHTML : '<i class="bi bi-chevron-down me-2"></i>';
                titleElement.innerHTML = `${chevronHtml}${cardIcon}${newTitle}`;
            } else {
                titleElement.innerHTML = `${cardIcon}${newTitle}`;
            }
        }
        </script>
        
class PetRegistrationForm(FormModel):
    """Complete pet registration form with owner information and pets list."""

    owner_name: str = FormField(
        title="Owner Name",
        input_type="text",
        placeholder="Enter your full name",
        help_text="Your full name as the pet owner",
        icon="person",
        min_length=2,
        max_length=100
    )

    email: EmailStr = FormField(
        title="Email Address",
        input_type="email",
        placeholder="your.email@example.com",
        help_text="Your contact email address",
        icon="envelope"
    )

    address: Optional[str] = FormField(
        None,
        title="Address",
        input_type="textarea",
        placeholder="Enter your full address...",
        help_text="Your home address (optional)",
        icon="house",
        max_length=500
    )

    emergency_contact: Optional[str] = FormField(
        None,
        title="Emergency Contact",
        input_type="text",
        placeholder="Emergency contact name and phone",
        help_text="Someone to contact in case of emergency",
        icon="person-exclamation",
        max_length=100
    )

    pets: List[PetModel] = FormField(
        default_factory=list,
        title="Your Pets",
        input_type="model_list",
        help_text="Add information about each of your pets",
        icon="heart",
        min_length=1,
        max_length=10,
        model_class=PetModel,
        add_button_text="Add Another Pet",
        remove_button_text="Remove Pet",
        collapsible_items=True,
        items_expanded=False,
        item_title_template="Pet #{index}: {name}",
        section_design={
            "section_title": "Pet Registry",
            "section_description": "Register each of your beloved pets with detailed information",
            "icon": "bi bi-heart-fill",
            "collapsible": True,
            "collapsed": False
        }
    )
{
  "$defs": {
    "PetModel": {
      "description": "Enhanced pet information model showcasing various input types.",
      "properties": {
        "name": {
          "autofocus": false,
          "description": "The name of your pet",
          "disabled": false,
          "help_text": "The name of your pet",
          "icon": "heart",
          "input_type": "text",
          "maxLength": 50,
          "minLength": 1,
          "placeholder": "Enter your pet's name",
          "readonly": false,
          "title": "Pet's Name",
          "type": "string"
        },
        "species": {
          "autofocus": false,
          "description": "What type of animal is your pet?",
          "disabled": false,
          "help_text": "What type of animal is your pet?",
          "icon": "collection",
          "input_type": "select",
          "options": [
            {
              "label": "Dog \ud83d\udc15",
              "value": "Dog"
            },
            {
              "label": "Cat \ud83d\udc31",
              "value": "Cat"
            },
            {
              "label": "Bird \ud83d\udc26",
              "value": "Bird"
            },
            {
              "label": "Fish \ud83d\udc20",
              "value": "Fish"
            },
            {
              "label": "Rabbit \ud83d\udc30",
              "value": "Rabbit"
            },
            {
              "label": "Hamster \ud83d\udc39",
              "value": "Hamster"
            },
            {
              "label": "Reptile \ud83e\udd8e",
              "value": "Reptile"
            },
            {
              "label": "Other \ud83d\udc3e",
              "value": "Other"
            }
          ],
          "readonly": false,
          "title": "Species",
          "type": "string"
        },
        "age": {
          "anyOf": [
            {
              "maximum": 50,
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "autofocus": false,
          "default": null,
          "description": "How old is your pet? (optional)",
          "disabled": false,
          "help_text": "How old is your pet? (optional)",
          "icon": "calendar",
          "input_type": "number",
          "placeholder": "Pet's age in years",
          "readonly": false,
          "title": "Age"
        },
        "weight": {
          "anyOf": [
            {
              "maximum": 500.0,
              "minimum": 0.01,
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "autofocus": false,
          "default": null,
          "description": "Weight in pounds (optional - enter 0.01 for tiny pets like birds)",
          "disabled": false,
          "help_text": "Weight in pounds (optional - enter 0.01 for tiny pets like birds)",
          "icon": "speedometer2",
          "input_type": "number",
          "placeholder": "Pet's weight",
          "readonly": false,
          "title": "Weight (lbs)"
        },
        "is_vaccinated": {
          "autofocus": false,
          "default": false,
          "description": "Is your pet up to date with vaccinations?",
          "disabled": false,
          "help_text": "Is your pet up to date with vaccinations?",
          "icon": "shield-check",
          "input_type": "checkbox",
          "readonly": false,
          "title": "Vaccinated",
          "type": "boolean"
        },
        "microchipped": {
          "autofocus": false,
          "default": false,
          "description": "Does your pet have a microchip?",
          "disabled": false,
          "help_text": "Does your pet have a microchip?",
          "icon": "cpu",
          "input_type": "checkbox",
          "readonly": false,
          "title": "Microchipped",
          "type": "boolean"
        },
        "breed": {
          "anyOf": [
            {
              "maxLength": 100,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "autofocus": false,
          "default": null,
          "description": "Specific breed of your pet (optional)",
          "disabled": false,
          "help_text": "Specific breed of your pet (optional)",
          "icon": "award",
          "input_type": "text",
          "placeholder": "e.g., Golden Retriever, Persian Cat",
          "readonly": false,
          "title": "Breed"
        },
        "color": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "autofocus": false,
          "default": null,
          "description": "Primary color of your pet (optional)",
          "disabled": false,
          "help_text": "Primary color of your pet (optional)",
          "icon": "palette",
          "input_type": "color",
          "readonly": false,
          "title": "Primary Color"
        },
        "last_vet_visit": {
          "anyOf": [
            {
              "format": "date",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "autofocus": false,
          "default": null,
          "description": "When was the last veterinary checkup? (optional)",
          "disabled": false,
          "help_text": "When was the last veterinary checkup? (optional)",
          "icon": "calendar-date",
          "input_type": "date",
          "readonly": false,
          "title": "Last Vet Visit"
        },
        "special_needs": {
          "anyOf": [
            {
              "maxLength": 500,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "autofocus": false,
          "default": null,
          "description": "Describe any special care requirements (optional)",
          "disabled": false,
          "help_text": "Describe any special care requirements (optional)",
          "icon": "heart-pulse",
          "input_type": "textarea",
          "placeholder": "Any special care requirements, medications, allergies, etc.",
          "readonly": false,
          "title": "Special Needs"
        }
      },
      "required": [
        "name",
        "species"
      ],
      "title": "PetModel",
      "type": "object"
    }
  },
  "description": "Complete pet registration form with owner information and pets list.",
  "properties": {
    "owner_name": {
      "autofocus": false,
      "description": "Your full name as the pet owner",
      "disabled": false,
      "help_text": "Your full name as the pet owner",
      "icon": "person",
      "input_type": "text",
      "maxLength": 100,
      "minLength": 2,
      "placeholder": "Enter your full name",
      "readonly": false,
      "title": "Owner Name",
      "type": "string"
    },
    "email": {
      "autofocus": false,
      "description": "Your contact email address",
      "disabled": false,
      "format": "email",
      "help_text": "Your contact email address",
      "icon": "envelope",
      "input_type": "email",
      "placeholder": "your.email@example.com",
      "readonly": false,
      "title": "Email Address",
      "type": "string"
    },
    "address": {
      "anyOf": [
        {
          "maxLength": 500,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "autofocus": false,
      "default": null,
      "description": "Your home address (optional)",
      "disabled": false,
      "help_text": "Your home address (optional)",
      "icon": "house",
      "input_type": "textarea",
      "placeholder": "Enter your full address...",
      "readonly": false,
      "title": "Address"
    },
    "emergency_contact": {
      "anyOf": [
        {
          "maxLength": 100,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "autofocus": false,
      "default": null,
      "description": "Someone to contact in case of emergency",
      "disabled": false,
      "help_text": "Someone to contact in case of emergency",
      "icon": "person-exclamation",
      "input_type": "text",
      "placeholder": "Emergency contact name and phone",
      "readonly": false,
      "title": "Emergency Contact"
    },
    "pets": {
      "add_button_text": "Add Another Pet",
      "autofocus": false,
      "collapsible_items": true,
      "default_factory": "builtins.list",
      "description": "Add information about each of your pets",
      "disabled": false,
      "help_text": "Add information about each of your pets",
      "icon": "heart",
      "input_type": "model_list",
      "item_title_template": "Pet #{index}: {name}",
      "items": {
        "$ref": "#/$defs/PetModel"
      },
      "items_expanded": false,
      "maxItems": 10,
      "minItems": 1,
      "model_class": "src.models.PetModel",
      "readonly": false,
      "remove_button_text": "Remove Pet",
      "section_design": {
        "collapsed": false,
        "collapsible": true,
        "icon": "bi bi-heart-fill",
        "section_description": "Register each of your beloved pets with detailed information",
        "section_title": "Pet Registry"
      },
      "title": "Your Pets",
      "type": "array"
    }
  },
  "required": [
    "owner_name",
    "email",
    "pets"
  ],
  "title": "PetRegistrationForm",
  "type": "object"
}
{
  "owner_name": {
    "required": true,
    "type": "string",
    "minLength": 2,
    "maxLength": 100
  },
  "email": {
    "required": true,
    "type": "string",
    "format": "email"
  },
  "address": {
    "required": false
  },
  "emergency_contact": {
    "required": false
  },
  "pets": {
    "required": true,
    "type": "array"
  }
}
{
  "errors": {},
  "data": {
    "owner_name": "Sarah Mitchell",
    "email": "sarah.mitchell@example.com",
    "address": "123 Main Street\r\nApt 4B\r\nSpringfield, IL 62701",
    "emergency_contact": "John Mitchell - (555) 123-4567",
    "pets": [
      {
        "name": "Max",
        "species": "Dog",
        "age": 3,
        "weight": 65.5,
        "is_vaccinated": false,
        "microchipped": true,
        "breed": "Golden Retriever",
        "color": "#000000",
        "last_vet_visit": "2026-01-03",
        "special_needs": "Allergic to chicken-based foods"
      },
      {
        "name": "Luna",
        "species": "Dog",
        "age": 2,
        "weight": 8.5,
        "is_vaccinated": false,
        "microchipped": true,
        "breed": "Siamese",
        "color": "#000000",
        "last_vet_visit": "2026-01-04",
        "special_needs": "Indoor only, needs daily medication for thyroid"
      }
    ]
  }
}
Try Different Styles
API Endpoints Available
Schema: GET /api/forms/pets/schema
Render: GET /api/forms/pets/render
Submit: POST /api/forms/pets/submit