Compare commits

..

1 Commits

Author SHA1 Message Date
96f94fd571 docs: remove TDD focus, emphasize DRY and YAGNI 2026-08-11 22:38:39 -03:00
37 changed files with 234 additions and 449 deletions

View File

@@ -24,12 +24,6 @@ class WeddingPackageForm
->label('Número / tipo (ex.: 01 / COMPLETA)') ->label('Número / tipo (ex.: 01 / COMPLETA)')
->required() ->required()
->maxLength(255), ->maxLength(255),
TextInput::make('tag')
->label('Etiqueta curta (ex.: Assessoria completa)')
->maxLength(255),
TextInput::make('subtitle')
->label('Frase de apoio')
->maxLength(255),
Textarea::make('summary') Textarea::make('summary')
->label('Resumo') ->label('Resumo')
->required() ->required()
@@ -50,12 +44,6 @@ class WeddingPackageForm
->label('Texto do botão') ->label('Texto do botão')
->required() ->required()
->maxLength(255), ->maxLength(255),
TextInput::make('compare_heading')
->label('Comparação — título (leitura rápida)')
->maxLength(255),
TextInput::make('compare_summary')
->label('Comparação — resumo (leitura rápida)')
->maxLength(255),
TextInput::make('sort_order') TextInput::make('sort_order')
->label('Ordem') ->label('Ordem')
->numeric() ->numeric()

View File

@@ -16,17 +16,13 @@ use Illuminate\Support\Carbon;
/** /**
* @property string $name * @property string $name
* @property string $level * @property string $level
* @property string|null $tag
* @property string|null $subtitle
* @property string $summary * @property string $summary
* @property list<string> $scope_items * @property list<string> $scope_items
* @property string $cta_label * @property string $cta_label
* @property string|null $compare_heading
* @property string|null $compare_summary
* @property int $sort_order * @property int $sort_order
* @property Carbon|null $published_at * @property Carbon|null $published_at
*/ */
#[Fillable(['name', 'level', 'tag', 'subtitle', 'summary', 'scope_items', 'cta_label', 'compare_heading', 'compare_summary', 'sort_order', 'published_at'])] #[Fillable(['name', 'level', 'summary', 'scope_items', 'cta_label', 'sort_order', 'published_at'])]
#[UsePolicy(WeddingPackagePolicy::class)] #[UsePolicy(WeddingPackagePolicy::class)]
class WeddingPackage extends Model class WeddingPackage extends Model
{ {

View File

@@ -18,13 +18,9 @@ class WeddingPackageFactory extends Factory
return [ return [
'name' => fake()->unique()->words(2, true), 'name' => fake()->unique()->words(2, true),
'level' => 'Assessoria', 'level' => 'Assessoria',
'tag' => fake()->words(2, true),
'subtitle' => fake()->sentence(),
'summary' => fake()->sentence(), 'summary' => fake()->sentence(),
'scope_items' => [fake()->sentence()], 'scope_items' => [fake()->sentence()],
'cta_label' => 'Conversar sobre esta modalidade', 'cta_label' => 'Conversar sobre esta modalidade',
'compare_heading' => fake()->words(3, true),
'compare_summary' => fake()->sentence(),
'sort_order' => 0, 'sort_order' => 0,
'published_at' => null, 'published_at' => null,
]; ];

View File

@@ -1,27 +0,0 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('wedding_packages', function (Blueprint $table): void {
$table->string('tag')->nullable();
$table->string('subtitle')->nullable();
$table->string('compare_heading')->nullable();
$table->string('compare_summary')->nullable();
});
}
public function down(): void
{
Schema::table('wedding_packages', function (Blueprint $table): void {
$table->dropColumn(['tag', 'subtitle', 'compare_heading', 'compare_summary']);
});
}
};

View File

@@ -9,9 +9,9 @@ use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
/** /**
* Wedding package modalities shown on the home page (03 Amare Casamentos) * Wedding package modalities shown on the home page (03 Amare Casamentos).
* and the services page. Copy is approved from the structural model preview * Copy is approved from the structural model preview (preview(1).html) and
* (preview(2).html) and remains editable via the Filament resource. * remains editable via the Filament resource.
*/ */
class WeddingPackagesSeeder extends Seeder class WeddingPackagesSeeder extends Seeder
{ {
@@ -23,55 +23,40 @@ class WeddingPackagesSeeder extends Seeder
[ [
'name' => 'Essenza', 'name' => 'Essenza',
'level' => '01 / COMPLETA', 'level' => '01 / COMPLETA',
'tag' => 'Assessoria completa', 'summary' => 'Para casais que desejam contar com a Amare desde o planejamento até a realização do casamento.',
'subtitle' => 'Do planejamento ao grande dia.',
'summary' => 'Para casais que desejam contar com a Amare desde o início ou ainda estão estruturando etapas importantes.',
'scope_items' => [ 'scope_items' => [
'Estruturação do planejamento', 'Planejamento e organização',
'Cronogramas, prazos e prioridades', 'Gestão de etapas e prioridades',
'Orientação e gestão de fornecedores', 'Acompanhamento de fornecedores',
'Alinhamento entre os envolvidos', 'Coordenação do grande dia',
'Coordenação da execução',
], ],
'cta_label' => 'Quero conhecer a Essenza', 'cta_label' => 'Quero conhecer a Essenza',
'compare_heading' => 'Começar com a Amare',
'compare_summary' => 'Acompanhamento mais amplo ao longo do planejamento.',
'sort_order' => 1, 'sort_order' => 1,
], ],
[ [
'name' => 'Conduzione', 'name' => 'Conduzione',
'level' => '02 / PARCIAL', 'level' => '02 / PARCIAL',
'tag' => 'Assessoria parcial', 'summary' => 'Para quem já começou e deseja estruturar o que falta, organizar fornecedores e seguir com acompanhamento profissional.',
'subtitle' => 'Para quem já começou e quer seguir acompanhado.',
'summary' => 'Para casais que já tomaram decisões e contrataram parte dos fornecedores, mas precisam estruturar o que falta.',
'scope_items' => [ 'scope_items' => [
'Diagnóstico do planejamento existente', 'Diagnóstico do planejamento',
'Organização das pendências', 'Organização das pendências',
'Gestão dos fornecedores contratados', 'Gestão dos próximos passos',
'Orientação para próximas decisões', 'Coordenação do grande dia',
'Coordenação da execução',
], ],
'cta_label' => 'Quero conhecer a Conduzione', 'cta_label' => 'Quero conhecer a Conduzione',
'compare_heading' => 'Trazer a Amare para o caminho',
'compare_summary' => 'O planejamento existe, mas ainda há decisões e gestão pela frente.',
'sort_order' => 2, 'sort_order' => 2,
], ],
[ [
'name' => 'Grand Jour', 'name' => 'Grand Jour',
'level' => '03 / FINAL', 'level' => '03 / FINAL',
'tag' => 'Assessoria final', 'summary' => 'Para casais que já planejaram o casamento e precisam de uma equipe para assumir alinhamentos e operação na reta final.',
'subtitle' => 'O planejamento está pronto. Agora é hora de viver.',
'summary' => 'Para casais na reta final que precisam de uma equipe para assumir alinhamentos, cronograma e operação.',
'scope_items' => [ 'scope_items' => [
'Imersão no planejamento existente', 'Imersão no planejamento existente',
'Conferência das informações', 'Alinhamento de fornecedores',
'Alinhamento dos fornecedores', 'Cronograma final',
'Organização do cronograma final',
'Gestão da operação do evento', 'Gestão da operação do evento',
], ],
'cta_label' => 'Quero conhecer a Grand Jour', 'cta_label' => 'Quero conhecer a Grand Jour',
'compare_heading' => 'Entregar a operação para a Amare',
'compare_summary' => 'O projeto está pronto e o foco passa a ser alinhamento e execução.',
'sort_order' => 3, 'sort_order' => 3,
], ],
]; ];

View File

@@ -67,13 +67,10 @@ The home page SHALL render, in order: header/navigation, hero, manifesto, featur
### Requirement: Listing and detail pages exist for catalog content ### Requirement: Listing and detail pages exist for catalog content
The system SHALL render a services listing (WEB-02) and a portfolio listing plus case detail (WEB-03) using the Heritage Editorial visual language. The case detail MUST present summary, event type, optional city/venue/date, challenge, solution, optional result, cover image and the ordered gallery. Portfolio listings and galleries MUST use alternating editorial image proportions on desktop while retaining DOM order and a single-column readable sequence on mobile. The system SHALL render a services listing (WEB-02) and a portfolio listing plus case detail (WEB-03) using the Heritage Editorial visual language. The case detail MUST present summary, event type, optional city/venue/date, challenge, solution, optional result, cover image and the ordered gallery. Portfolio listings and galleries MUST use alternating editorial image proportions on desktop while retaining DOM order and a single-column readable sequence on mobile.
#### Scenario: Services listing renders editorial sections with published modalities #### Scenario: Services listing shows published services
- **WHEN** a visitor loads `/servicos` - **WHEN** a visitor loads `/servicos`
- **THEN** the page MUST present the two vertentes (Amare Casamentos and Amare Corporate) with CTAs to their sections - **THEN** every published service MUST be listed with title and summary in `sort_order`
- **AND** every published wedding modality MUST be rendered in `sort_order` with tag, name, subtitle, summary and scope
- **AND** a quick-read comparison of the modalities MUST use each modality's `compare_heading` and `compare_summary`
- **AND** unpublished modalities MUST NOT be rendered
- **AND** the listing MUST use the public editorial layout (not an unrelated visual system) - **AND** the listing MUST use the public editorial layout (not an unrelated visual system)
#### Scenario: Gallery respects stored order #### Scenario: Gallery respects stored order

13
package-lock.json generated
View File

@@ -1,5 +1,5 @@
{ {
"name": "daisyui", "name": "site-amare",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
@@ -7,7 +7,6 @@
"devDependencies": { "devDependencies": {
"@tailwindcss/vite": "^4.0.0", "@tailwindcss/vite": "^4.0.0",
"concurrently": "^9.0.1", "concurrently": "^9.0.1",
"daisyui": "^5.7.16",
"husky": "^9.1.7", "husky": "^9.1.7",
"laravel-vite-plugin": "^3.1", "laravel-vite-plugin": "^3.1",
"playwright": "^1.62.0", "playwright": "^1.62.0",
@@ -791,16 +790,6 @@
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1" "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
} }
}, },
"node_modules/daisyui": {
"version": "5.7.16",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.7.16.tgz",
"integrity": "sha512-V9CJxvrWIXTDuP/0tpijjWaKaKJNYo2IrULJfTWs3/DjW9rPqswk1n8NCLQRLrTutmlG2Ech7nkJDpCnF+6Dzw==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/saadeghi/daisyui?sponsor=1"
}
},
"node_modules/detect-libc": { "node_modules/detect-libc": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",

View File

@@ -10,7 +10,6 @@
"devDependencies": { "devDependencies": {
"@tailwindcss/vite": "^4.0.0", "@tailwindcss/vite": "^4.0.0",
"concurrently": "^9.0.1", "concurrently": "^9.0.1",
"daisyui": "^5.7.16",
"husky": "^9.1.7", "husky": "^9.1.7",
"laravel-vite-plugin": "^3.1", "laravel-vite-plugin": "^3.1",
"playwright": "^1.62.0", "playwright": "^1.62.0",

View File

@@ -1,46 +1,6 @@
@import 'tailwindcss'; @import 'tailwindcss';
@import './tokens.css'; @import './tokens.css';
@plugin "daisyui" {
themes: false;
}
@plugin "daisyui/theme" {
name: "amare";
default: true;
color-scheme: light;
--color-base-100: var(--amare-color-bg);
--color-base-200: var(--amare-color-bg-deep);
--color-base-300: var(--amare-color-bg-archive);
--color-base-content: var(--amare-color-text);
--color-primary: var(--amare-color-accent);
--color-primary-content: var(--amare-color-accent-text);
--color-secondary: var(--amare-color-sage);
--color-secondary-content: var(--amare-color-text);
--color-accent: var(--amare-color-accent-deep);
--color-accent-content: var(--amare-color-accent-text);
--color-neutral: var(--amare-color-muted);
--color-neutral-content: var(--amare-color-accent-text);
--color-info: #2563eb;
--color-info-content: #ffffff;
--color-success: var(--amare-color-success);
--color-success-content: var(--amare-color-accent-text);
--color-warning: var(--amare-color-warning);
--color-warning-content: var(--amare-color-accent-text);
--color-error: var(--amare-color-error);
--color-error-content: var(--amare-color-accent-text);
--radius-selector: 0;
--radius-field: 0;
--radius-box: 0;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 0;
--noise: 0;
}
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; @source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php'; @source '../../storage/framework/views/*.php';
@source '../views/**/*.blade.php'; @source '../views/**/*.blade.php';
@@ -267,11 +227,3 @@
} }
} }
} }
/* daisyUI emits unlayered; match focus ring to the amare accent. */
.input:focus,
.select:focus,
.textarea:focus,
.checkbox:focus-visible {
--input-color: var(--amare-color-accent);
}

View File

@@ -32,7 +32,7 @@
</div> </div>
@if ($errors->any()) @if ($errors->any())
<div role="alert" class="alert alert-error border border-amare-error/40"> <div role="alert" class="border border-amare-error/40 bg-amare-error/5 px-6 py-5">
<p class="font-semibold text-amare-error">Não foi possível enviar.</p> <p class="font-semibold text-amare-error">Não foi possível enviar.</p>
<p class="mt-1 text-sm text-amare-muted">Revise os campos destacados abaixo e tente novamente.</p> <p class="mt-1 text-sm text-amare-muted">Revise os campos destacados abaixo e tente novamente.</p>
</div> </div>
@@ -50,7 +50,7 @@
autocomplete="name" autocomplete="name"
maxlength="120" maxlength="120"
placeholder="Seu nome" placeholder="Seu nome"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('nome') border-amare-error @enderror"
@error('nome') aria-invalid="true" aria-describedby="briefing-nome-error" @enderror @error('nome') aria-invalid="true" aria-describedby="briefing-nome-error" @enderror
> >
@error('nome') @error('nome')
@@ -69,7 +69,7 @@
autocomplete="email" autocomplete="email"
maxlength="254" maxlength="254"
placeholder="voce@email.com" placeholder="voce@email.com"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('email') border-amare-error @enderror"
@error('email') aria-invalid="true" aria-describedby="briefing-email-error" @enderror @error('email') aria-invalid="true" aria-describedby="briefing-email-error" @enderror
> >
@error('email') @error('email')
@@ -88,7 +88,7 @@
autocomplete="tel" autocomplete="tel"
maxlength="40" maxlength="40"
placeholder="(11) 90000-0000" placeholder="(11) 90000-0000"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('telefone') border-amare-error @enderror"
@error('telefone') aria-invalid="true" aria-describedby="briefing-telefone-error" @enderror @error('telefone') aria-invalid="true" aria-describedby="briefing-telefone-error" @enderror
> >
@error('telefone') @error('telefone')
@@ -102,7 +102,7 @@
id="briefing-tipo_evento" id="briefing-tipo_evento"
name="tipo_evento" name="tipo_evento"
required required
class="select w-full text-amare-text @error('tipo_evento') select-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors focus:border-amare-accent focus:outline-none @error('tipo_evento') border-amare-error @enderror"
@error('tipo_evento') aria-invalid="true" aria-describedby="briefing-tipo_evento-error" @enderror @error('tipo_evento') aria-invalid="true" aria-describedby="briefing-tipo_evento-error" @enderror
> >
<option value="" selected disabled>Selecione...</option> <option value="" selected disabled>Selecione...</option>
@@ -125,7 +125,7 @@
value="{{ old('data_periodo') }}" value="{{ old('data_periodo') }}"
maxlength="80" maxlength="80"
placeholder="Ex.: novembro de 2027" placeholder="Ex.: novembro de 2027"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('data_periodo') border-amare-error @enderror"
@error('data_periodo') aria-invalid="true" aria-describedby="briefing-data_periodo-error" @enderror @error('data_periodo') aria-invalid="true" aria-describedby="briefing-data_periodo-error" @enderror
> >
@error('data_periodo') @error('data_periodo')
@@ -143,7 +143,7 @@
required required
maxlength="80" maxlength="80"
placeholder="Ex.: São Paulo" placeholder="Ex.: São Paulo"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('cidade') border-amare-error @enderror"
@error('cidade') aria-invalid="true" aria-describedby="briefing-cidade-error" @enderror @error('cidade') aria-invalid="true" aria-describedby="briefing-cidade-error" @enderror
> >
@error('cidade') @error('cidade')
@@ -163,7 +163,7 @@
inputmode="numeric" inputmode="numeric"
autocomplete="off" autocomplete="off"
placeholder="Ex.: 120" placeholder="Ex.: 120"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('convidados') border-amare-error @enderror"
@error('convidados') aria-invalid="true" aria-describedby="briefing-convidados-error" @enderror @error('convidados') aria-invalid="true" aria-describedby="briefing-convidados-error" @enderror
> >
@error('convidados') @error('convidados')
@@ -180,7 +180,7 @@
value="{{ old('servico_interesse') }}" value="{{ old('servico_interesse') }}"
maxlength="120" maxlength="120"
placeholder="Ex.: planejamento completo" placeholder="Ex.: planejamento completo"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('servico_interesse') border-amare-error @enderror"
@error('servico_interesse') aria-invalid="true" aria-describedby="briefing-servico_interesse-error" @enderror @error('servico_interesse') aria-invalid="true" aria-describedby="briefing-servico_interesse-error" @enderror
> >
@error('servico_interesse') @error('servico_interesse')
@@ -198,7 +198,7 @@
rows="5" rows="5"
maxlength="3000" maxlength="3000"
placeholder="O que já está definido? Em que ponto você precisa de ajuda?" placeholder="O que já está definido? Em que ponto você precisa de ajuda?"
class="textarea w-full min-h-[110px] text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-error @enderror" class="w-full min-h-[110px] border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('mensagem') border-amare-error @enderror"
@error('mensagem') aria-invalid="true" aria-describedby="briefing-mensagem-error" @enderror @error('mensagem') aria-invalid="true" aria-describedby="briefing-mensagem-error" @enderror
>{{ old('mensagem') }}</textarea> >{{ old('mensagem') }}</textarea>
@error('mensagem') @error('mensagem')
@@ -215,7 +215,7 @@
value="1" value="1"
required required
@checked(old('privacidade')) @checked(old('privacidade'))
class="checkbox checkbox-primary mt-1 shrink-0" class="mt-1 h-5 w-5 shrink-0 accent-amare-accent"
@error('privacidade') aria-invalid="true" aria-describedby="briefing-privacidade-error" @enderror @error('privacidade') aria-invalid="true" aria-describedby="briefing-privacidade-error" @enderror
> >
<span class="text-sm text-amare-muted"> <span class="text-sm text-amare-muted">
@@ -233,7 +233,7 @@
<button <button
type="submit" type="submit"
data-submit-button data-submit-button
class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]" class="inline-flex min-h-[48px] items-center justify-center border border-transparent bg-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep"
> >
Enviar briefing Enviar briefing
</button> </button>

View File

@@ -1,40 +1,26 @@
@props([ @props([
'settings', 'settings',
'eyebrow' => '04 — Amare Corporate',
'heading' => 'Projetos corporativos tratados como experiência, não apenas operação.',
'meta' => 'No MVP, esta frente pode apresentar claramente o que a Amare oferece mesmo sem inventar um portfólio corporativo que ainda não existe.',
'steps' => null,
'showMeta' => true,
'ctaLabel' => 'Falar sobre um evento corporativo',
'ctaHref' => '#contato',
'showAside' => true,
]) ])
@php
$steps = $steps ?? ($settings->corporate_steps ?? []);
@endphp
<section <section
aria-labelledby="corporate-heading" aria-labelledby="corporate-heading"
class="home-chapter border-b border-amare-border bg-amare-bg" class="home-chapter border-b border-amare-border bg-amare-bg"
data-chapter="corporate" data-chapter="corporate"
id="corporate" id="corporate"
> >
<div class="container-amare grid gap-12 py-16 md:py-24 @if ($showAside) lg:grid-cols-2 lg:gap-[70px] @endif" data-reveal-group> <div class="container-amare grid gap-12 py-16 md:py-24 lg:grid-cols-2 lg:gap-[70px]" data-reveal-group>
<div class="flex flex-col gap-8"> <div class="flex flex-col gap-8">
<div class="space-y-4" data-reveal data-reveal-from="up"> <div class="space-y-4" data-reveal data-reveal-from="up">
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $eyebrow }}</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">04 Amare Corporate</p>
<h2 id="corporate-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">{{ $heading }}</h2> <h2 id="corporate-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">Projetos corporativos tratados como experiência, não apenas operação.</h2>
</div> </div>
@if ($showMeta && filled($meta)) <p class="max-w-[760px] text-[clamp(1.1875rem,2vw,1.5rem)] leading-[1.55] text-amare-text-muted" data-reveal data-reveal-from="up">
<p class="max-w-[760px] text-[clamp(1.1875rem,2vw,1.5rem)] leading-[1.55] text-amare-text-muted" data-reveal data-reveal-from="up"> No MVP, esta frente pode apresentar claramente o que a Amare oferece mesmo sem inventar um portfólio corporativo que ainda não existe.
{{ $meta }} </p>
</p>
@endif
<div class="border-t border-amare-border" data-reveal data-reveal-from="up"> <div class="border-t border-amare-border" data-reveal data-reveal-from="up">
@foreach ($steps as $index => $step) @foreach ($settings->corporate_steps ?? [] as $index => $step)
<div class="flex gap-8 border-b border-amare-border py-[23px]"> <div class="flex gap-8 border-b border-amare-border py-[23px]">
<p class="w-[44px] shrink-0 text-xs font-bold uppercase tracking-[0.16em] text-amare-accent">{{ str_pad((string) ($index + 1), 2, '0', STR_PAD_LEFT) }}</p> <p class="w-[44px] shrink-0 text-xs font-bold uppercase tracking-[0.16em] text-amare-accent">{{ str_pad((string) ($index + 1), 2, '0', STR_PAD_LEFT) }}</p>
<div class="space-y-1"> <div class="space-y-1">
@@ -45,17 +31,15 @@
@endforeach @endforeach
</div> </div>
<a href="{{ $ctaHref }}" class="btn btn-primary mt-7 self-start text-xs font-bold uppercase tracking-[0.09em]" data-reveal data-reveal-from="up"> <a href="#contato" class="mt-7 inline-flex min-h-[48px] items-center justify-center self-start border border-transparent bg-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep" data-reveal data-reveal-from="up">
{{ $ctaLabel }} Falar sobre um evento corporativo
</a> </a>
</div> </div>
@if ($showAside) <div class="flex min-h-[420px] flex-col items-center justify-center gap-4 bg-amare-bg-deep p-10 text-center" data-reveal data-reveal-from="up">
<div class="flex min-h-[420px] flex-col items-center justify-center gap-4 bg-amare-bg-deep p-10 text-center" data-reveal data-reveal-from="up"> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Portfólio Corporate</p>
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Portfólio Corporate</p> <h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">Conteúdo em construção</h3>
<h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">Conteúdo em construção</h3> <p class="max-w-sm text-amare-text-muted">Em vez de usar fotografias genéricas como se fossem cases, a página assume com elegância que o portfólio será construído com projetos reais.</p>
<p class="max-w-sm text-amare-text-muted">Em vez de usar fotografias genéricas como se fossem cases, a página assume com elegância que o portfólio será construído com projetos reais.</p> </div>
</div>
@endif
</div> </div>
</section> </section>

View File

@@ -1,7 +1,6 @@
@props([ @props([
'settings', 'settings',
'editorial' => false, 'editorial' => false,
'ctaHref' => null,
]) ])
<section aria-labelledby="final-cta-heading" @class([ <section aria-labelledby="final-cta-heading" @class([
@@ -18,8 +17,8 @@
</p> </p>
<div> <div>
<a <a
href="{{ $ctaHref ?? route('briefing') }}" href="{{ route('briefing') }}"
class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]" class="inline-flex min-h-11 items-center bg-amare-accent px-5 py-3 text-sm font-semibold uppercase tracking-[0.12em] text-amare-accent-text transition-colors duration-(--amare-duration-normal) ease-(--amare-ease-standard) hover:bg-amare-accent-deep"
> >
{{ $settings->hero_cta_label ?: 'Solicitar proposta' }} {{ $settings->hero_cta_label ?: 'Solicitar proposta' }}
</a> </a>

View File

@@ -2,29 +2,48 @@
'settings', 'settings',
]) ])
<x-public.photo-hero <section
@class(['home-chapter']) aria-labelledby="hero-heading"
class="home-chapter border-b border-amare-border bg-amare-bg"
data-chapter="hero" data-chapter="hero"
:image-path="$settings->hero_image_path" data-motion="page-open"
:image-alt="$settings->hero_image_alt ?: $settings->brand_name"
:eyebrow="$settings->hero_eyebrow"
:title="$settings->hero_title ?: 'Celebrações com propósito'"
:summary="$settings->hero_subtitle"
brand-mark
> >
<div class="flex flex-wrap items-center gap-4"> <div class="container-amare grid items-end gap-12 pb-12 pt-16 md:grid-cols-[1.1fr_0.9fr] md:gap-[clamp(3rem,6vw,7rem)] md:pb-[72px] md:pt-24">
<a href="{{ route('contact') }}" data-testid="home-primary-cta" class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]"> <div data-hero-content data-reveal-group class="flex flex-col gap-8">
{{ $settings->hero_cta_label ?: 'Solicitar proposta' }} <div data-motion-beat="eyebrow">
</a> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Assessoria &amp; produção de eventos &bull; São Paulo</p>
</div>
@if (filled($settings->hero_secondary_cta_label)) <h1 id="hero-heading" data-motion-beat="title" class="text-[clamp(3rem,8vw,5.75rem)] font-medium leading-[0.95] tracking-[-0.04em] text-amare-text">
<a href="{{ route('portfolio.index') }}" class="btn btn-ghost min-h-0 px-0 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"> Eventos com intenção, cuidado e presença.
<span class="border-b border-amare-accent pb-1">{{ $settings->hero_secondary_cta_label }}</span> </h1>
</a>
@endif <p class="max-w-[760px] text-[clamp(1.1875rem,2vw,1.5rem)] leading-[1.55] text-amare-text-muted">
Uma boutique de assessoria que une sensibilidade, organização e condução profissional para transformar cada projeto em uma experiência bem cuidada.
</p>
<div data-motion-beat="cta" class="flex flex-wrap items-center gap-4">
<a href="#sobre" data-testid="home-primary-cta" class="inline-flex min-h-[48px] items-center justify-center border border-transparent bg-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep">
Conhecer a Amare
</a>
<a href="#contato" class="inline-flex min-h-[48px] items-center justify-center border border-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-deep transition-colors hover:bg-amare-accent hover:text-amare-accent-text">
Enviar briefing
</a>
</div>
</div>
<div
data-split-hero
data-motion-beat="media"
class="min-h-[320px] overflow-hidden bg-amare-bg-deep md:min-h-[520px]"
>
@if (filled($settings->hero_image_path))
<x-media.image :path="$settings->hero_image_path" :alt="$settings->hero_image_alt ?: $settings->brand_name" loading="eager" fetchpriority="high" sizes="(max-width: 1023px) 100vw, 45vw" class="img-editorial h-full w-full object-cover" />
@else
<div data-tonal-hero class="flex h-full min-h-[320px] items-center justify-center bg-gradient-to-br from-amare-bg-deep to-amare-bg-archive md:min-h-[520px]">
<p class="text-xs font-semibold uppercase tracking-[0.16em] text-amare-muted">Fotografia hero</p>
</div>
@endif
</div>
</div> </div>
</section>
@if (filled($settings->hero_note))
<p class="mt-4 max-w-xl text-sm text-amare-text-muted">{{ $settings->hero_note }}</p>
@endif
</x-public.photo-hero>

View File

@@ -1,23 +1,11 @@
@props([ @props([
'packages', 'packages',
'settings', 'settings',
'eyebrow' => '03 — Amare Casamentos',
'heading' => 'Um acompanhamento para cada momento.',
'intro' => 'As modalidades são pontos de partida. O site apresenta o conceito e ajuda o casal a reconhecer seu momento; detalhes operacionais e comerciais ficam para a conversa e proposta.',
'kicker' => 'level',
'showSubtitle' => false,
'showIntro' => true,
'showNote' => true,
'ctaRoute' => null,
'bandCtaHref' => null,
'bandBody' => 'Conte um pouco sobre o seu casamento. A Amare entende o momento de vocês e orienta o melhor formato de acompanhamento sem depender de um quiz automático.',
'note' => 'Nomenclaturas exibidas conforme materiais/reunião; confirmar versão final antes da publicação.',
]) ])
@php @php
$whatsappDigits = preg_replace('/\D/', '', (string) $settings->whatsapp_number); $whatsappDigits = preg_replace('/\D/', '', (string) $settings->whatsapp_number);
$hasWhatsapp = strlen($whatsappDigits) >= 10; $hasWhatsapp = strlen($whatsappDigits) >= 10;
$bandHref = $bandCtaHref ?? route('briefing');
@endphp @endphp
<section <section
@@ -29,12 +17,10 @@
<div class="container-amare py-16 md:py-24" data-reveal-group> <div class="container-amare py-16 md:py-24" data-reveal-group>
<div class="flex flex-col gap-6 md:flex-row md:items-end md:justify-between" data-reveal data-reveal-from="up"> <div class="flex flex-col gap-6 md:flex-row md:items-end md:justify-between" data-reveal data-reveal-from="up">
<div class="max-w-2xl space-y-4"> <div class="max-w-2xl space-y-4">
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $eyebrow }}</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">03 Amare Casamentos</p>
<h2 id="packages-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">{{ $heading }}</h2> <h2 id="packages-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">Um acompanhamento para cada momento.</h2>
</div> </div>
@if ($showIntro && filled($intro)) <p class="max-w-[600px] text-amare-text-muted">As modalidades são pontos de partida. O site apresenta o conceito e ajuda o casal a reconhecer seu momento; detalhes operacionais e comerciais ficam para a conversa e proposta.</p>
<p class="max-w-[600px] text-amare-text-muted">{{ $intro }}</p>
@endif
</div> </div>
@if ($packages->isNotEmpty()) @if ($packages->isNotEmpty())
@@ -42,11 +28,8 @@
@foreach ($packages as $package) @foreach ($packages as $package)
<article class="flex min-h-[480px] flex-col justify-between gap-8 border-b border-r border-amare-border p-8 md:p-10" data-reveal data-reveal-from="up"> <article class="flex min-h-[480px] flex-col justify-between gap-8 border-b border-r border-amare-border p-8 md:p-10" data-reveal data-reveal-from="up">
<div class="space-y-5"> <div class="space-y-5">
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent">{{ $kicker === 'tag' ? $package->tag : $package->level }}</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent">{{ $package->level }}</p>
<h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">{{ $package->name }}</h3> <h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">{{ $package->name }}</h3>
@if ($showSubtitle && filled($package->subtitle))
<p class="text-[clamp(1.0625rem,1.7vw,1.25rem)] font-medium leading-snug text-amare-text">{{ $package->subtitle }}</p>
@endif
<p class="text-amare-text-muted">{{ $package->summary }}</p> <p class="text-amare-text-muted">{{ $package->summary }}</p>
<ul class="space-y-3 text-amare-text-muted"> <ul class="space-y-3 text-amare-text-muted">
@foreach ($package->scope_items as $item) @foreach ($package->scope_items as $item)
@@ -58,14 +41,11 @@
$waLink = $hasWhatsapp $waLink = $hasWhatsapp
? 'https://wa.me/'.$whatsappDigits.'?text='.rawurlencode('Olá, gostaria de conversar sobre a modalidade '.$package->name.' para meu casamento.') ? 'https://wa.me/'.$whatsappDigits.'?text='.rawurlencode('Olá, gostaria de conversar sobre a modalidade '.$package->name.' para meu casamento.')
: route('briefing', ['servico_interesse' => $package->name]); : route('briefing', ['servico_interesse' => $package->name]);
$href = $ctaRoute
? route($ctaRoute)
: $waLink;
@endphp @endphp
<a <a
href="{{ $href }}" href="{{ $waLink }}"
@if ($ctaRoute === null && $hasWhatsapp) target="_blank" rel="noopener noreferrer" @endif @if ($hasWhatsapp) target="_blank" rel="noopener noreferrer" @endif
class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]" class="inline-flex min-h-[48px] items-center justify-center border border-transparent bg-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep"
> >
{{ $package->cta_label }} {{ $package->cta_label }}
</a> </a>
@@ -77,15 +57,13 @@
<div class="mt-6 flex flex-col justify-between gap-8 bg-amare-accent-deep p-8 text-amare-accent-text md:flex-row md:items-center md:p-12" data-reveal data-reveal-from="up"> <div class="mt-6 flex flex-col justify-between gap-8 bg-amare-accent-deep p-8 text-amare-accent-text md:flex-row md:items-center md:p-12" data-reveal data-reveal-from="up">
<div class="max-w-xl space-y-3"> <div class="max-w-xl space-y-3">
<h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight">Ainda não sabe qual modalidade é ideal?</h3> <h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight">Ainda não sabe qual modalidade é ideal?</h3>
<p class="text-amare-accent-text/80">{{ $bandBody }}</p> <p class="text-amare-accent-text/80">Conte um pouco sobre o seu casamento. A Amare entende o momento de vocês e orienta o melhor formato de acompanhamento sem depender de um quiz automático.</p>
</div> </div>
<a href="{{ $bandHref }}" class="inline-flex min-h-[48px] items-center justify-center self-start border border-amare-accent-text px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-text hover:text-amare-accent-deep md:self-auto"> <a href="{{ route('briefing') }}" class="inline-flex min-h-[48px] items-center justify-center self-start border border-amare-accent-text px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-text hover:text-amare-accent-deep md:self-auto">
Conversar com a Amare Conversar com a Amare
</a> </a>
</div> </div>
@if ($showNote && filled($note)) <p class="mt-6 text-sm text-amare-muted">Nomenclaturas exibidas conforme materiais/reunião; confirmar versão final antes da publicação.</p>
<p class="mt-6 text-sm text-amare-muted">{{ $note }}</p>
@endif
</div> </div>
</section> </section>

View File

@@ -34,7 +34,7 @@
@endforeach @endforeach
</ul> </ul>
<p> <p>
<a href="{{ route('about') }}" class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"> <a href="{{ route('about') }}" class="inline-flex min-h-11 items-center text-sm font-semibold text-amare-accent transition-colors hover:text-amare-accent-deep">
<span class="border-b border-amare-accent pb-1">Conhecer a Amare</span> <span class="border-b border-amare-accent pb-1">Conhecer a Amare</span>
</a> </a>
</p> </p>

View File

@@ -26,7 +26,7 @@
</ol> </ol>
<p> <p>
<a href="{{ route('services.index') }}" class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"> <a href="{{ route('services.index') }}" class="inline-flex min-h-11 items-center text-sm font-semibold text-amare-accent transition-colors hover:text-amare-accent-deep">
<span class="border-b border-amare-accent pb-1">Ver todos os serviços</span> <span class="border-b border-amare-accent pb-1">Ver todos os serviços</span>
</a> </a>
</p> </p>

View File

@@ -1,23 +1,4 @@
@props([ @props([])
'eyebrow' => '02 — Duas vertentes, uma mesma forma de cuidar',
'heading' => 'Como podemos acompanhar você?',
'cards' => [
[
'label' => 'Amare Casamentos',
'title' => 'Planejamento e condução para viver o processo com mais leveza.',
'body' => 'Do início da organização à reta final, modalidades pensadas para diferentes momentos do casal.',
'href' => '#casamentos',
'cta' => 'Conhecer casamentos',
],
[
'label' => 'Amare Corporate',
'title' => 'Eventos empresariais com organização, intenção e execução segura.',
'body' => 'Uma frente própria para projetos corporativos, com linguagem e necessidades diferentes das celebrações sociais.',
'href' => '#corporate',
'cta' => 'Conhecer Corporate',
],
],
])
<section <section
aria-labelledby="vertentes-heading" aria-labelledby="vertentes-heading"
@@ -27,24 +8,34 @@
> >
<div class="container-amare py-16 md:py-24" data-reveal-group> <div class="container-amare py-16 md:py-24" data-reveal-group>
<div class="max-w-3xl space-y-4" data-reveal data-reveal-from="up"> <div class="max-w-3xl space-y-4" data-reveal data-reveal-from="up">
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $eyebrow }}</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">02 Duas vertentes, uma mesma forma de cuidar</p>
<h2 id="vertentes-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">{{ $heading }}</h2> <h2 id="vertentes-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">Como podemos acompanhar você?</h2>
</div> </div>
<div class="mt-12 grid gap-6 md:mt-16 md:grid-cols-2 md:gap-[24px]"> <div class="mt-12 grid gap-6 md:mt-16 md:grid-cols-2 md:gap-[24px]">
@foreach ($cards as $card) <article class="relative flex min-h-[420px] flex-col justify-end bg-amare-bg-deep p-8 md:p-10" data-reveal data-reveal-from="up">
<article class="relative flex min-h-[420px] flex-col justify-end bg-amare-bg-deep p-8 md:p-10" data-reveal data-reveal-from="up"> <div aria-hidden="true" class="pointer-events-none absolute inset-x-0 top-0 h-[43%] bg-gradient-to-b from-amare-bg to-transparent"></div>
<div aria-hidden="true" class="pointer-events-none absolute inset-x-0 top-0 h-[43%] bg-gradient-to-b from-amare-bg to-transparent"></div> <div class="relative flex flex-col gap-5">
<div class="relative flex flex-col gap-5"> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Amare Casamentos</p>
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $card['label'] }}</p> <h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">Planejamento e condução para viver o processo com mais leveza.</h3>
<h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">{{ $card['title'] }}</h3> <p class="text-amare-text-muted">Do início da organização à reta final, modalidades pensadas para diferentes momentos do casal.</p>
<p class="text-amare-text-muted">{{ $card['body'] }}</p> <a href="#casamentos" class="mt-2 inline-flex min-h-[48px] items-center justify-center self-start border border-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-deep transition-colors hover:bg-amare-accent hover:text-amare-accent-text">
<a href="{{ $card['href'] }}" class="btn btn-outline mt-2 self-start text-xs font-bold uppercase tracking-[0.09em]"> Conhecer casamentos
{{ $card['cta'] }} </a>
</a> </div>
</div> </article>
</article>
@endforeach <article class="relative flex min-h-[420px] flex-col justify-end bg-amare-bg-deep p-8 md:p-10" data-reveal data-reveal-from="up">
<div aria-hidden="true" class="pointer-events-none absolute inset-x-0 top-0 h-[43%] bg-gradient-to-b from-amare-bg to-transparent"></div>
<div class="relative flex flex-col gap-5">
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Amare Corporate</p>
<h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">Eventos empresariais com organização, intenção e execução segura.</h3>
<p class="text-amare-text-muted">Uma frente própria para projetos corporativos, com linguagem e necessidades diferentes das celebrações sociais.</p>
<a href="#corporate" class="mt-2 inline-flex min-h-[48px] items-center justify-center self-start border border-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-deep transition-colors hover:bg-amare-accent hover:text-amare-accent-text">
Conhecer Corporate
</a>
</div>
</article>
</div> </div>
</div> </div>
</section> </section>

View File

@@ -10,7 +10,7 @@
@foreach ($packages as $package) @foreach ($packages as $package)
@php($digits = preg_replace('/\D/', '', (string) $settings->whatsapp_number)) @php($digits = preg_replace('/\D/', '', (string) $settings->whatsapp_number))
@php($href = strlen((string) $digits) >= 10 ? 'https://wa.me/'.$digits.'?text='.rawurlencode('Olá, gostaria de conversar sobre a modalidade '.$package->name.' para meu casamento.') : route('briefing', ['servico_interesse' => $package->name])) @php($href = strlen((string) $digits) >= 10 ? 'https://wa.me/'.$digits.'?text='.rawurlencode('Olá, gostaria de conversar sobre a modalidade '.$package->name.' para meu casamento.') : route('briefing', ['servico_interesse' => $package->name]))
<li class="space-y-5 border-t border-amare-border pt-4" data-reveal data-reveal-from="up"><p class="text-xs font-semibold uppercase tracking-[.14em] text-amare-accent">{{ $package->level }}</p><h3 class="text-3xl font-medium">{{ $package->name }}</h3><p class="text-amare-muted">{{ $package->summary }}</p><ul class="space-y-2 text-sm text-amare-text-muted">@foreach ($package->scope_items as $item)<li class="border-l border-amare-border pl-3">{{ $item }}</li>@endforeach</ul><a href="{{ $href }}" @if (str_starts_with($href, 'https://wa.me/')) target="_blank" rel="noopener" @endif class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"><span class="border-b border-amare-accent pb-1">{{ $package->cta_label }}</span></a></li> <li class="space-y-5 border-t border-amare-border pt-4" data-reveal data-reveal-from="up"><p class="text-xs font-semibold uppercase tracking-[.14em] text-amare-accent">{{ $package->level }}</p><h3 class="text-3xl font-medium">{{ $package->name }}</h3><p class="text-amare-muted">{{ $package->summary }}</p><ul class="space-y-2 text-sm text-amare-text-muted">@foreach ($package->scope_items as $item)<li class="border-l border-amare-border pl-3">{{ $item }}</li>@endforeach</ul><a href="{{ $href }}" @if (str_starts_with($href, 'https://wa.me/')) target="_blank" rel="noopener" @endif class="inline-flex min-h-11 items-center text-sm font-semibold text-amare-accent hover:text-amare-accent-deep"><span class="border-b border-amare-accent pb-1">{{ $package->cta_label }}</span></a></li>
@endforeach @endforeach
</ol> </ol>
@endif @endif

View File

@@ -20,7 +20,7 @@
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Página não encontrada</h1> <h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Página não encontrada</h1>
<p class="text-amare-muted" data-reveal data-reveal-from="up">O endereço que você tentou abrir não existe ou foi movido.</p> <p class="text-amare-muted" data-reveal data-reveal-from="up">O endereço que você tentou abrir não existe ou foi movido.</p>
<p data-reveal data-reveal-from="up"> <p data-reveal data-reveal-from="up">
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]"> <a href="{{ route('home') }}" class="inline-flex min-h-11 items-center bg-amare-accent px-5 py-3 text-sm font-semibold uppercase tracking-[0.12em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep">
Voltar para a home Voltar para a home
</a> </a>
</p> </p>

View File

@@ -20,7 +20,7 @@
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Sessão expirada</h1> <h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Sessão expirada</h1>
<p class="text-amare-muted" data-reveal data-reveal-from="up">Sua sessão expirou. Volte e tente enviar novamente.</p> <p class="text-amare-muted" data-reveal data-reveal-from="up">Sua sessão expirou. Volte e tente enviar novamente.</p>
<p data-reveal data-reveal-from="up"> <p data-reveal data-reveal-from="up">
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]"> <a href="{{ route('home') }}" class="inline-flex min-h-11 items-center bg-amare-accent px-5 py-3 text-sm font-semibold uppercase tracking-[0.12em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep">
Voltar para a home Voltar para a home
</a> </a>
</p> </p>

View File

@@ -20,7 +20,7 @@
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Muitas solicitações</h1> <h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Muitas solicitações</h1>
<p class="text-amare-muted" data-reveal data-reveal-from="up">Você enviou muitas solicitações em pouco tempo. Aguarde um instante e tente novamente.</p> <p class="text-amare-muted" data-reveal data-reveal-from="up">Você enviou muitas solicitações em pouco tempo. Aguarde um instante e tente novamente.</p>
<p data-reveal data-reveal-from="up"> <p data-reveal data-reveal-from="up">
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]"> <a href="{{ route('home') }}" class="inline-flex min-h-11 items-center bg-amare-accent px-5 py-3 text-sm font-semibold uppercase tracking-[0.12em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep">
Voltar para a home Voltar para a home
</a> </a>
</p> </p>

View File

@@ -20,7 +20,7 @@
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Algo deu errado</h1> <h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Algo deu errado</h1>
<p class="text-amare-muted" data-reveal data-reveal-from="up">Não foi possível concluir o pedido agora. Tente novamente em instantes.</p> <p class="text-amare-muted" data-reveal data-reveal-from="up">Não foi possível concluir o pedido agora. Tente novamente em instantes.</p>
<p data-reveal data-reveal-from="up"> <p data-reveal data-reveal-from="up">
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]"> <a href="{{ route('home') }}" class="inline-flex min-h-11 items-center bg-amare-accent px-5 py-3 text-sm font-semibold uppercase tracking-[0.12em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep">
Voltar para a home Voltar para a home
</a> </a>
</p> </p>

View File

@@ -20,7 +20,7 @@
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Em manutenção</h1> <h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Em manutenção</h1>
<p class="text-amare-muted" data-reveal data-reveal-from="up">Estamos realizando uma breve manutenção. Tente novamente em instantes.</p> <p class="text-amare-muted" data-reveal data-reveal-from="up">Estamos realizando uma breve manutenção. Tente novamente em instantes.</p>
<p data-reveal data-reveal-from="up"> <p data-reveal data-reveal-from="up">
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]"> <a href="{{ route('home') }}" class="inline-flex min-h-11 items-center bg-amare-accent px-5 py-3 text-sm font-semibold uppercase tracking-[0.12em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep">
Voltar para a home Voltar para a home
</a> </a>
</p> </p>

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" data-theme="amare"> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -58,11 +58,11 @@
<header class="site-header sticky top-0 z-40 border-b border-amare-border bg-amare-bg/95 backdrop-blur-sm"> <header class="site-header sticky top-0 z-40 border-b border-amare-border bg-amare-bg/95 backdrop-blur-sm">
<div class="container-amare grid grid-cols-[auto_1fr_auto] items-center gap-4 py-4 md:grid-cols-[1fr_auto_1fr] md:h-[74px] md:py-0"> <div class="container-amare grid grid-cols-[auto_1fr_auto] items-center gap-4 py-4 md:grid-cols-[1fr_auto_1fr] md:h-[74px] md:py-0">
<nav id="main-nav" class="main-nav order-3 col-span-3 hidden flex-col gap-4 border-t border-amare-border pt-4 md:order-1 md:col-span-1 md:flex md:flex-row md:items-center md:gap-1 md:border-0 md:pt-0" aria-label="Principal" data-main-nav> <nav id="main-nav" class="main-nav order-3 col-span-3 hidden flex-col gap-4 border-t border-amare-border pt-4 md:order-1 md:col-span-1 md:flex md:flex-row md:items-center md:gap-1 md:border-0 md:pt-0" aria-label="Principal" data-main-nav>
<a href="{{ route('home') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Início</a> <a href="{{ route('home') }}" class="inline-flex items-center py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted transition-colors hover:text-amare-accent md:px-3">Início</a>
<a href="{{ route('services.index') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Serviços</a> <a href="{{ route('services.index') }}" class="inline-flex items-center py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted transition-colors hover:text-amare-accent md:px-3">Serviços</a>
<a href="{{ route('portfolio.index') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Portfólio</a> <a href="{{ route('portfolio.index') }}" class="inline-flex items-center py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted transition-colors hover:text-amare-accent md:px-3">Portfólio</a>
<a href="{{ route('about') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Amare</a> <a href="{{ route('about') }}" class="inline-flex items-center py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted transition-colors hover:text-amare-accent md:px-3">Amare</a>
<a href="{{ route('briefing') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:hidden">Solicitar proposta</a> <a href="{{ route('briefing') }}" class="inline-flex items-center py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted transition-colors hover:text-amare-accent md:hidden">Solicitar proposta</a>
</nav> </nav>
<a href="{{ route('home') }}" class="order-1 justify-self-start md:order-2 md:justify-self-center" aria-label="{{ $siteSettings->brand_name }} — página inicial"> <a href="{{ route('home') }}" class="order-1 justify-self-start md:order-2 md:justify-self-center" aria-label="{{ $siteSettings->brand_name }} — página inicial">
@@ -70,14 +70,13 @@
</a> </a>
<div class="order-2 flex items-center justify-end gap-3 md:order-3"> <div class="order-2 flex items-center justify-end gap-3 md:order-3">
<a href="{{ route('briefing') }}" class="btn btn-outline hidden min-h-0 px-6 text-xs font-bold uppercase tracking-[0.09em] md:inline-flex"> <a href="{{ route('briefing') }}" class="hidden items-center justify-center border border-amare-accent px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-deep transition-colors hover:bg-amare-accent hover:text-amare-accent-text md:inline-flex min-h-[48px]">
Conte seu evento Conte seu evento
</a> </a>
</a>
<button <button
type="button" type="button"
class="menu-button btn btn-square btn-ghost border border-amare-border text-amare-text md:hidden" class="menu-button inline-flex h-11 w-11 items-center justify-center border border-amare-border text-amare-text md:hidden"
aria-label="Abrir menu" aria-label="Abrir menu"
aria-controls="main-nav" aria-controls="main-nav"
aria-expanded="false" aria-expanded="false"

View File

@@ -42,7 +42,7 @@
</p> </p>
@if (session('status') === 'briefing-sent') @if (session('status') === 'briefing-sent')
<div role="status" class="alert mt-8 border border-amare-border bg-amare-bg-deep"> <div role="status" class="mt-8 border border-amare-border bg-amare-bg-deep px-6 py-5">
<p class="font-semibold text-amare-text">Mensagem enviada.</p> <p class="font-semibold text-amare-text">Mensagem enviada.</p>
<p class="mt-1 text-amare-muted">Recebemos seu briefing e retornaremos em breve pelo canal informado.</p> <p class="mt-1 text-amare-muted">Recebemos seu briefing e retornaremos em breve pelo canal informado.</p>
</div> </div>
@@ -61,7 +61,7 @@
</div> </div>
@if ($errors->any()) @if ($errors->any())
<div role="alert" class="alert alert-error border border-amare-error/40"> <div role="alert" class="border border-amare-error/40 bg-amare-error/5 px-6 py-5">
<p class="font-semibold text-amare-error">Não foi possível enviar.</p> <p class="font-semibold text-amare-error">Não foi possível enviar.</p>
<p class="mt-1 text-sm text-amare-muted">Revise os campos destacados abaixo e tente novamente.</p> <p class="mt-1 text-sm text-amare-muted">Revise os campos destacados abaixo e tente novamente.</p>
</div> </div>
@@ -79,7 +79,7 @@
autocomplete="name" autocomplete="name"
maxlength="120" maxlength="120"
placeholder="Seu nome" placeholder="Seu nome"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('nome') border-amare-error @enderror"
@error('nome') aria-invalid="true" aria-describedby="nome-error" @enderror @error('nome') aria-invalid="true" aria-describedby="nome-error" @enderror
> >
@error('nome') @error('nome')
@@ -98,7 +98,7 @@
autocomplete="email" autocomplete="email"
maxlength="254" maxlength="254"
placeholder="voce@email.com" placeholder="voce@email.com"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('email') border-amare-error @enderror"
@error('email') aria-invalid="true" aria-describedby="email-error" @enderror @error('email') aria-invalid="true" aria-describedby="email-error" @enderror
> >
@error('email') @error('email')
@@ -117,7 +117,7 @@
autocomplete="tel" autocomplete="tel"
maxlength="40" maxlength="40"
placeholder="(11) 90000-0000" placeholder="(11) 90000-0000"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('telefone') border-amare-error @enderror"
@error('telefone') aria-invalid="true" aria-describedby="telefone-error" @enderror @error('telefone') aria-invalid="true" aria-describedby="telefone-error" @enderror
> >
@error('telefone') @error('telefone')
@@ -131,7 +131,7 @@
id="tipo_evento" id="tipo_evento"
name="tipo_evento" name="tipo_evento"
required required
class="select w-full text-amare-text @error('tipo_evento') select-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors focus:border-amare-accent focus:outline-none @error('tipo_evento') border-amare-error @enderror"
@error('tipo_evento') aria-invalid="true" aria-describedby="tipo_evento-error" @enderror @error('tipo_evento') aria-invalid="true" aria-describedby="tipo_evento-error" @enderror
> >
<option value="" selected disabled>Selecione...</option> <option value="" selected disabled>Selecione...</option>
@@ -154,7 +154,7 @@
value="{{ old('data_periodo') }}" value="{{ old('data_periodo') }}"
maxlength="80" maxlength="80"
placeholder="Ex.: novembro de 2027" placeholder="Ex.: novembro de 2027"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('data_periodo') border-amare-error @enderror"
@error('data_periodo') aria-invalid="true" aria-describedby="data_periodo-error" @enderror @error('data_periodo') aria-invalid="true" aria-describedby="data_periodo-error" @enderror
> >
@error('data_periodo') @error('data_periodo')
@@ -172,7 +172,7 @@
required required
maxlength="80" maxlength="80"
placeholder="Ex.: São Paulo" placeholder="Ex.: São Paulo"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('cidade') border-amare-error @enderror"
@error('cidade') aria-invalid="true" aria-describedby="cidade-error" @enderror @error('cidade') aria-invalid="true" aria-describedby="cidade-error" @enderror
> >
@error('cidade') @error('cidade')
@@ -192,7 +192,7 @@
inputmode="numeric" inputmode="numeric"
autocomplete="off" autocomplete="off"
placeholder="Ex.: 120" placeholder="Ex.: 120"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('convidados') border-amare-error @enderror"
@error('convidados') aria-invalid="true" aria-describedby="convidados-error" @enderror @error('convidados') aria-invalid="true" aria-describedby="convidados-error" @enderror
> >
@error('convidados') @error('convidados')
@@ -209,7 +209,7 @@
value="{{ old('servico_interesse', request('servico_interesse')) }}" value="{{ old('servico_interesse', request('servico_interesse')) }}"
maxlength="120" maxlength="120"
placeholder="Ex.: planejamento completo" placeholder="Ex.: planejamento completo"
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('servico_interesse') border-amare-error @enderror"
@error('servico_interesse') aria-invalid="true" aria-describedby="servico_interesse-error" @enderror @error('servico_interesse') aria-invalid="true" aria-describedby="servico_interesse-error" @enderror
> >
@error('servico_interesse') @error('servico_interesse')
@@ -227,7 +227,7 @@
rows="6" rows="6"
maxlength="3000" maxlength="3000"
placeholder="Conte sobre o seu evento, expectativas e principais preocupações." placeholder="Conte sobre o seu evento, expectativas e principais preocupações."
class="textarea w-full text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-error @enderror" class="w-full border-0 border-b border-amare-border bg-transparent py-3 text-amare-text transition-colors placeholder:text-amare-muted/60 focus:border-amare-accent focus:outline-none @error('mensagem') border-amare-error @enderror"
@error('mensagem') aria-invalid="true" aria-describedby="mensagem-error" @enderror @error('mensagem') aria-invalid="true" aria-describedby="mensagem-error" @enderror
>{{ old('mensagem') }}</textarea> >{{ old('mensagem') }}</textarea>
@error('mensagem') @error('mensagem')
@@ -244,7 +244,7 @@
value="1" value="1"
required required
@checked(old('privacidade')) @checked(old('privacidade'))
class="checkbox checkbox-primary mt-1 shrink-0" class="mt-1 h-5 w-5 shrink-0 accent-amare-accent"
@error('privacidade') aria-invalid="true" aria-describedby="privacidade-error" @enderror @error('privacidade') aria-invalid="true" aria-describedby="privacidade-error" @enderror
> >
<span class="text-sm text-amare-muted"> <span class="text-sm text-amare-muted">
@@ -262,7 +262,7 @@
<button <button
type="submit" type="submit"
data-submit-button data-submit-button
class="btn btn-primary min-h-11 px-8 text-sm font-semibold uppercase tracking-[0.12em]" class="inline-flex min-h-[44px] items-center justify-center bg-amare-accent px-8 py-3 text-sm font-semibold uppercase tracking-[0.12em] text-amare-accent-text transition-colors hover:bg-amare-accent-deep"
> >
Enviar briefing Enviar briefing
</button> </button>

View File

@@ -33,7 +33,7 @@
</div> </div>
<div><label class="mb-2 block text-xs font-semibold uppercase tracking-[.14em]" for="mensagem">Mensagem *</label><textarea class="w-full border border-amare-border bg-transparent p-3 focus:border-amare-accent focus:outline-none" id="mensagem" name="mensagem" rows="6" required maxlength="3000">{{ old('mensagem') }}</textarea>@error('mensagem')<p class="mt-2 text-sm text-amare-error">{{ $message }}</p>@enderror</div> <div><label class="mb-2 block text-xs font-semibold uppercase tracking-[.14em]" for="mensagem">Mensagem *</label><textarea class="w-full border border-amare-border bg-transparent p-3 focus:border-amare-accent focus:outline-none" id="mensagem" name="mensagem" rows="6" required maxlength="3000">{{ old('mensagem') }}</textarea>@error('mensagem')<p class="mt-2 text-sm text-amare-error">{{ $message }}</p>@enderror</div>
<p class="max-w-2xl text-sm text-amare-muted">Ao enviar, você reconhece o uso destes dados exclusivamente para analisar uma possível parceria, conforme a <a class="text-amare-accent underline" href="{{ route('privacy') }}">política de privacidade</a>.</p> <p class="max-w-2xl text-sm text-amare-muted">Ao enviar, você reconhece o uso destes dados exclusivamente para analisar uma possível parceria, conforme a <a class="text-amare-accent underline" href="{{ route('privacy') }}">política de privacidade</a>.</p>
<button type="submit" data-submit-button class="btn btn-primary text-sm font-semibold uppercase tracking-[.12em]">Enviar apresentação</button> <button type="submit" data-submit-button class="inline-flex min-h-11 bg-amare-accent px-6 py-3 text-sm font-semibold uppercase tracking-[.12em] text-amare-accent-text hover:bg-amare-accent-deep">Enviar apresentação</button>
</form> </form>
@endif @endif
</div> </div>

View File

@@ -1,92 +1,55 @@
@extends('layouts.public') @extends('layouts.public')
@section('content') @section('content')
<x-public.photo-hero <x-public.photo-hero :image-path="$siteSettings->services_hero_image_path" :image-alt="$siteSettings->services_hero_image_alt" eyebrow="Serviços" title="Uma mesma excelência, diferentes ocasiões." summary="O escopo é construído de acordo com o momento do projeto, o nível de apoio necessário e a complexidade de cada evento." />
:image-path="$siteSettings->services_hero_image_path"
:image-alt="$siteSettings->services_hero_image_alt"
eyebrow="Serviços"
title="O cuidado certo para cada tipo de evento."
summary="A Amare acompanha projetos sociais e corporativos com planejamento, organização e condução profissional. O formato muda conforme o momento, o evento e a necessidade de cada cliente."
>
<div class="flex flex-wrap items-center gap-4">
<a href="#vertentes" class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]">
Conhecer os serviços
</a>
<a href="{{ route('contact') }}" class="btn btn-ghost min-h-0 px-0 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep">
<span class="border-b border-amare-accent pb-1">Tenho um evento em mente</span>
</a>
</div>
</x-public.photo-hero>
<x-home.vertentes <div class="border-b border-amare-border bg-amare-bg">
eyebrow="Duas vertentes" <div class="container-amare space-y-10 py-16 md:py-24">
heading="Escolha por contexto, não por uma lista de pacotes."
:cards="[
[
'label' => 'Amare Casamentos',
'title' => 'Acompanhamento para diferentes momentos do planejamento.',
'body' => 'Três modalidades para casais que estão começando, já avançaram ou precisam de apoio na reta final.',
'href' => '#casamentos',
'cta' => 'Ver modalidades',
],
[
'label' => 'Amare Corporate',
'title' => 'Planejamento e execução para eventos empresariais.',
'body' => 'Uma frente própria, com linguagem profissional e estrutura adequada a projetos corporativos.',
'href' => '#corporate',
'cta' => 'Ver Corporate',
],
]"
/>
<x-home.packages @if ($services->isEmpty())
:packages="$weddingPackages" <p class="text-amare-muted">O catálogo de serviços está em organização. Enquanto isso, fale conosco para uma primeira conversa.</p>
:settings="$siteSettings" @else
eyebrow="Amare Casamentos" @php($hasPrioritizedImage = false)
heading="Três formas de ter a Amare ao lado." <div class="divide-y divide-amare-border border-y border-amare-border" data-editorial-service-list data-reveal-group>
:show-intro="false" @foreach ($services as $index => $service)
kicker="tag" <article @class([
:show-subtitle="true" 'grid gap-4 py-8 md:grid-cols-[5rem_minmax(0,1fr)_minmax(0,1.2fr)] md:items-start',
cta-route="contact" 'md:translate-x-8' => $loop->even,
:band-cta-href="route('contact')" ]) data-reveal data-reveal-from="up">
band-body="Conte um pouco sobre o casamento. A Amare entende o momento de vocês e orienta o melhor formato de acompanhamento sem depender de um quiz automático." <span class="text-sm font-semibold uppercase tracking-[0.14em] text-amare-accent">{{ str_pad((string) ($index + 1), 2, '0', STR_PAD_LEFT) }}</span>
:show-note="false" <div class="space-y-3">
/> <h2 class="text-2xl font-medium text-amare-text md:text-3xl">{{ $service->title }}</h2>
<p class="text-amare-muted">{{ $service->summary }}</p>
@if ($weddingPackages->isNotEmpty()) </div>
<section aria-label="Comparação rápida entre as modalidades" class="border-b border-amare-border bg-amare-bg"> <div class="space-y-4">
<div class="container-amare py-16 md:py-24" data-reveal-group> @if (filled($service->cover_image_path))
<div class="grid border-l border-t border-amare-border md:grid-cols-3"> @php($prioritizeImage = ! $hasPrioritizedImage)
@foreach ($weddingPackages as $package) <x-media.image
@if (filled($package->compare_heading)) :path="$service->cover_image_path"
<article class="flex min-h-[300px] flex-col justify-between gap-6 border-b border-r border-amare-border p-8 md:p-10" data-reveal data-reveal-from="up"> :alt="$service->cover_image_alt ?: $service->title"
<div class="space-y-4"> :loading="$prioritizeImage ? 'eager' : 'lazy'"
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent">{{ $package->name }}</p> :fetchpriority="$prioritizeImage ? 'high' : null"
<h3 class="text-[clamp(1.25rem,2vw,1.5rem)] font-medium leading-tight text-amare-text">{{ $package->compare_heading }}</h3> sizes="(max-width: 768px) calc(100vw - 3rem), 40vw"
<p class="text-amare-text-muted">{{ $package->compare_summary }}</p> class="img-editorial aspect-[16/10] w-full object-cover"
</div> />
</article> @php($hasPrioritizedImage = true)
@endif @endif
@if (filled($service->description))
<div class="text-amare-muted">
{!! nl2br(e($service->description)) !!}
</div>
@endif
</div>
</article>
@endforeach @endforeach
</div> </div>
</div> @endif
</section> </div>
</div>
@if ($weddingPackages->isNotEmpty())
<section class="border-b border-amare-border bg-amare-bg-deep py-16 md:py-24" aria-labelledby="wedding-packages-heading"><div class="container-amare"><p class="text-xs font-semibold uppercase tracking-[.14em] text-amare-accent">Casamentos</p><h2 id="wedding-packages-heading" class="mt-3 text-3xl font-medium">Modalidades de assessoria</h2><div class="mt-8 grid gap-6 md:grid-cols-3">@foreach ($weddingPackages as $package)<article class="border-t border-amare-border pt-4"><p class="text-sm text-amare-accent">{{ $package->level }}</p><h3 class="mt-2 text-2xl font-medium">{{ $package->name }}</h3><p class="mt-2 text-amare-muted">{{ $package->summary }}</p><ul class="mt-4 space-y-2 text-sm text-amare-text-muted">@foreach ($package->scope_items as $item)<li>{{ $item }}</li>@endforeach</ul></article>@endforeach</div></div></section>
@endif @endif
<x-home.corporate <x-home.final-cta :settings="$siteSettings" />
:settings="$siteSettings"
eyebrow="Amare Corporate"
heading="Organização, produção e condução com linguagem empresarial."
:show-meta="false"
:steps="[
['title' => 'Planejamento', 'body' => 'Estruturação do evento, escopo, prioridades e cronograma.'],
['title' => 'Produção', 'body' => 'Coordenação dos elementos e fornecedores necessários ao projeto.'],
['title' => 'Execução', 'body' => 'Acompanhamento e condução do evento conforme o planejamento aprovado.'],
]"
cta-label="Falar sobre um evento Corporate"
:cta-href="route('contact')"
:show-aside="false"
/>
<x-home.final-cta :settings="$siteSettings" :cta-href="route('contact')" />
@endsection @endsection

View File

@@ -93,7 +93,8 @@ it('reaches the primary CTA by keyboard and activates it', function (): void {
$page->keys('[data-testid="home-primary-cta"]', 'Enter'); $page->keys('[data-testid="home-primary-cta"]', 'Enter');
$page->assertPathIs('/contato'); $hash = $page->script('() => window.location.hash');
expect($hash)->toBe('#sobre');
}); });
it('disables transitions when prefers-reduced-motion is reduce', function (): void { it('disables transitions when prefers-reduced-motion is reduce', function (): void {

View File

@@ -38,7 +38,7 @@ it('keeps the hero asymmetric on desktop and stacked through md and mobile', fun
startsBelowHeader: Math.abs((heroRect?.top ?? -1) - (headerRect?.bottom ?? -2)) <= 1, startsBelowHeader: Math.abs((heroRect?.top ?? -1) - (headerRect?.bottom ?? -2)) <= 1,
mediaBesideContent: (mediaRect?.left ?? 0) >= (contentRect?.right ?? Number.POSITIVE_INFINITY) - 1, mediaBesideContent: (mediaRect?.left ?? 0) >= (contentRect?.right ?? Number.POSITIVE_INFINITY) - 1,
mediaMinHeight: Math.round(mediaRect?.height ?? 0) >= 519, mediaMinHeight: Math.round(mediaRect?.height ?? 0) >= 519,
mediaTouchesViewportRight: (mediaRect?.right ?? 0) >= window.innerWidth - 4, mediaInsideContainer: (mediaRect?.right ?? 0) < window.innerWidth - 100,
horizontalOverflow: document.documentElement.scrollWidth > window.innerWidth, horizontalOverflow: document.documentElement.scrollWidth > window.innerWidth,
}; };
} }
@@ -49,7 +49,7 @@ it('keeps the hero asymmetric on desktop and stacked through md and mobile', fun
'startsBelowHeader' => true, 'startsBelowHeader' => true,
'mediaBesideContent' => true, 'mediaBesideContent' => true,
'mediaMinHeight' => true, 'mediaMinHeight' => true,
'mediaTouchesViewportRight' => true, 'mediaInsideContainer' => true,
'horizontalOverflow' => false, 'horizontalOverflow' => false,
]); ]);

View File

@@ -158,7 +158,7 @@ it('opens home motion, reveals once, and allows CTA during open', function (): v
$page->click('[data-testid="home-primary-cta"]'); $page->click('[data-testid="home-primary-cta"]');
$page->assertPathIs('/contato'); expect($page->script('() => window.location.hash'))->toBe('#sobre');
}); });
it('keeps content and navigation usable without javascript', function (): void { it('keeps content and navigation usable without javascript', function (): void {
@@ -171,7 +171,7 @@ it('keeps content and navigation usable without javascript', function (): void {
->assertVisible('[data-testid="home-primary-cta"]') ->assertVisible('[data-testid="home-primary-cta"]')
->click('[data-testid="home-primary-cta"]'); ->click('[data-testid="home-primary-cta"]');
$page->assertPathIs('/contato'); expect($page->script('() => window.location.hash'))->toBe('#sobre');
}); });
it('keeps targets final when intersection observer is unavailable', function (): void { it('keeps targets final when intersection observer is unavailable', function (): void {

View File

@@ -8,7 +8,7 @@ it('renders the public home page', function (): void {
$settings = SiteSetting::instance(); $settings = SiteSetting::instance();
$this->visit('/') $this->visit('/')
->assertSee($settings->hero_title) ->assertSee('Eventos com intenção, cuidado e presença.')
->assertSee($settings->brand_name); ->assertSee($settings->brand_name);
}); });

View File

@@ -20,7 +20,7 @@ class HomePageTest extends TestCase
$response $response
->assertOk() ->assertOk()
->assertSee('Celebrações com propósito') ->assertSee('Eventos com intenção, cuidado e presença.')
->assertSee($settings->brand_name); ->assertSee($settings->brand_name);
} }
} }

View File

@@ -105,18 +105,18 @@ class HomePageContentTest extends TestCase
'id="testimonials-heading"', 'id="testimonials-heading"',
'id="briefing-heading"', 'id="briefing-heading"',
], false) ], false)
->assertSee('Fotografia hero')
->assertSee('FOTO DE CASAMENTO 01') ->assertSee('FOTO DE CASAMENTO 01')
->assertSee('Nome e data reais — aguardando autorização') ->assertSee('Nome e data reais — aguardando autorização')
->assertSee('Conteúdo em construção') ->assertSee('Conteúdo em construção')
->assertSee('Fornecedores e parcerias — pós-MVP'); ->assertSee('Fornecedores e parcerias — pós-MVP');
} }
public function test_hero_falls_back_to_default_copy_when_fields_are_empty(): void public function test_hero_uses_fixed_editorial_copy_regardless_of_settings(): void
{ {
SiteSetting::instance()->update([ SiteSetting::instance()->update([
'hero_title' => '', 'hero_title' => '',
'hero_subtitle' => '', 'hero_subtitle' => '',
'hero_cta_label' => '',
'hero_image_path' => null, 'hero_image_path' => null,
]); ]);
@@ -124,8 +124,11 @@ class HomePageContentTest extends TestCase
$response $response
->assertOk() ->assertOk()
->assertSeeInOrder(['id="hero-heading"', 'Celebrações com propósito'], false) ->assertSee('Eventos com intenção, cuidado e presença.')
->assertSeeInOrder(['data-testid="home-primary-cta"', 'Solicitar proposta'], false); ->assertSee('Uma boutique de assessoria que une sensibilidade, organização e condução profissional para transformar cada projeto em uma experiência bem cuidada.')
->assertSee('Conhecer a Amare')
->assertSee('Enviar briefing')
->assertSeeInOrder(['href="#sobre"', 'data-testid="home-primary-cta"'], false);
} }
public function test_home_hero_uses_its_own_cms_image_instead_of_the_social_og_image(): void public function test_home_hero_uses_its_own_cms_image_instead_of_the_social_og_image(): void
@@ -157,11 +160,12 @@ class HomePageContentTest extends TestCase
$this->get(route('home')) $this->get(route('home'))
->assertOk() ->assertOk()
->assertSee('data-tonal-hero', false) ->assertSee('min-h-[320px]', false)
->assertSee('md:min-h-[520px]', false)
->assertSee('Fotografia hero')
->assertSee('id="hero-heading"', false) ->assertSee('id="hero-heading"', false)
->assertSee('data-testid="home-primary-cta"', false) ->assertSee('data-testid="home-primary-cta"', false)
->assertDontSee('data-photo-hero', false) ->assertSee('data-motion-beat="media"', false)
->assertDontSee('data-motion-beat="media"', false)
->assertDontSee('content/home/hero.jpg', false); ->assertDontSee('content/home/hero.jpg', false);
} }

View File

@@ -37,16 +37,15 @@ class ImmersivePhotoHeroTest extends TestCase
->assertOk() ->assertOk()
->assertSee('data-chapter="hero"', false) ->assertSee('data-chapter="hero"', false)
->assertSee('data-motion="page-open"', false) ->assertSee('data-motion="page-open"', false)
->assertSee('data-photo-hero', false) ->assertSee('md:min-h-[520px]', false)
->assertSee('min-h-[calc(100dvh-5rem)]', false)
->assertSee('data-hero-content', false) ->assertSee('data-hero-content', false)
->assertSee('data-split-hero', false) ->assertSee('data-split-hero', false)
->assertSee('data-motion-beat="media"', false) ->assertSee('data-motion-beat="media"', false)
->assertSee('lg:grid-cols-12', false) ->assertSee('md:grid-cols-[1.1fr_0.9fr]', false)
->assertSee('content/heroes/home.jpg', false) ->assertSee('content/heroes/home.jpg', false)
->assertSee('loading="eager"', false) ->assertSee('loading="eager"', false)
->assertSee('fetchpriority="high"', false) ->assertSee('fetchpriority="high"', false)
->assertSee('sizes="(max-width: 1023px) 100vw, 58vw"', false) ->assertSee('sizes="(max-width: 1023px) 100vw, 45vw"', false)
->assertDontSee('data-tonal-hero', false) ->assertDontSee('data-tonal-hero', false)
->assertSee('content="http://localhost/storage/content/og/social.jpg"', false); ->assertSee('content="http://localhost/storage/content/og/social.jpg"', false);
} }
@@ -76,8 +75,9 @@ class ImmersivePhotoHeroTest extends TestCase
->assertSee('data-motion="page-open"', false) ->assertSee('data-motion="page-open"', false)
->assertSee('id="hero-heading"', false) ->assertSee('id="hero-heading"', false)
->assertSee('data-testid="home-primary-cta"', false) ->assertSee('data-testid="home-primary-cta"', false)
->assertDontSee('data-photo-hero', false) ->assertSee('data-split-hero', false)
->assertDontSee('data-split-hero', false) ->assertSee('data-tonal-hero', false)
->assertSee('Fotografia hero')
->assertDontSee('content/heroes/home.jpg', false); ->assertDontSee('content/heroes/home.jpg', false);
} }
} }

View File

@@ -42,8 +42,8 @@ class MediaPerformanceTest extends TestCase
$about = $this->get(route('about'))->assertOk()->getContent(); $about = $this->get(route('about'))->assertOk()->getContent();
$detail = $this->get(route('portfolio.show', $firstCase->slug))->assertOk()->getContent(); $detail = $this->get(route('portfolio.show', $firstCase->slug))->assertOk()->getContent();
$this->assertStringNotContainsString('service-first.jpg', $services); $this->assertMatchesRegularExpression('/service-first\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $services);
$this->assertStringNotContainsString('service-later.jpg', $services); $this->assertMatchesRegularExpression('/service-later\.jpg"[^>]*loading="lazy"(?![^>]*fetchpriority)/', $services);
$this->assertMatchesRegularExpression('/case-first\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio); $this->assertMatchesRegularExpression('/case-first\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio);
$this->assertMatchesRegularExpression('/case-later\.jpg"[^>]*loading="lazy"(?![^>]*fetchpriority)/', $portfolio); $this->assertMatchesRegularExpression('/case-later\.jpg"[^>]*loading="lazy"(?![^>]*fetchpriority)/', $portfolio);
$this->assertMatchesRegularExpression('/about\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $about); $this->assertMatchesRegularExpression('/about\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $about);
@@ -89,7 +89,7 @@ class MediaPerformanceTest extends TestCase
$services = $this->get(route('services.index'))->assertOk()->getContent(); $services = $this->get(route('services.index'))->assertOk()->getContent();
$portfolio = $this->get(route('portfolio.index'))->assertOk()->getContent(); $portfolio = $this->get(route('portfolio.index'))->assertOk()->getContent();
$this->assertStringNotContainsString('visible-service.jpg', $services); $this->assertMatchesRegularExpression('/visible-service\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $services);
$this->assertMatchesRegularExpression('/visible-case\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio); $this->assertMatchesRegularExpression('/visible-case\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio);
} }
} }

View File

@@ -36,7 +36,7 @@ class MotionMarkupTest extends TestCase
$response $response
->assertOk() ->assertOk()
->assertSee('data-motion="page-open"', false) ->assertSee('data-motion="page-open"', false)
->assertSee('data-motion-beat="seal"', false) ->assertSee('data-motion-beat="eyebrow"', false)
->assertSee('data-motion-beat="title"', false) ->assertSee('data-motion-beat="title"', false)
->assertSee('data-motion-beat="media"', false) ->assertSee('data-motion-beat="media"', false)
->assertSee('data-motion-beat="cta"', false) ->assertSee('data-motion-beat="cta"', false)

View File

@@ -6,8 +6,8 @@ namespace Tests\Feature\PublicSite;
use App\Models\PortfolioCase; use App\Models\PortfolioCase;
use App\Models\PortfolioImage; use App\Models\PortfolioImage;
use App\Models\Service;
use App\Models\SiteSetting; use App\Models\SiteSetting;
use App\Models\WeddingPackage;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@@ -18,45 +18,17 @@ class PublicPagesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
public function test_services_index_renders_editorial_sections_with_published_modalities_only(): void public function test_services_index_lists_published_services_in_sort_order(): void
{ {
SiteSetting::instance(); SiteSetting::instance();
WeddingPackage::factory()->create(['name' => 'Rascunho', 'published_at' => null]); Service::factory()->create(['title' => 'Rascunho', 'published_at' => null]);
WeddingPackage::factory()->published()->create([ Service::factory()->published()->create(['title' => 'Serviço B', 'sort_order' => 20]);
'name' => 'Essenza', Service::factory()->published()->create(['title' => 'Serviço A', 'sort_order' => 10]);
'level' => '01 / COMPLETA',
'tag' => 'Assessoria completa',
'subtitle' => 'Do planejamento ao grande dia.',
'summary' => 'Para casais que desejam contar com a Amare desde o início.',
'scope_items' => ['Estruturação do planejamento', 'Coordenação da execução'],
'cta_label' => 'Quero conhecer a Essenza',
'compare_heading' => 'Começar com a Amare',
'compare_summary' => 'Acompanhamento mais amplo ao longo do planejamento.',
'sort_order' => 10,
]);
$this->get(route('services.index')) $this->get(route('services.index'))
->assertOk() ->assertOk()
->assertSee('O cuidado certo para cada tipo de evento.') ->assertSeeInOrder(['Serviço A', 'Serviço B'])
->assertSee('Conhecer os serviços')
->assertSee('Tenho um evento em mente')
->assertSee('Duas vertentes')
->assertSee('Escolha por contexto, não por uma lista de pacotes.')
->assertSee('Amare Casamentos')
->assertSee('Acompanhamento para diferentes momentos do planejamento.')
->assertSee('Amare Corporate')
->assertSee('Planejamento e execução para eventos empresariais.')
->assertSee('Três formas de ter a Amare ao lado.')
->assertSee('Assessoria completa')
->assertSee('Essenza')
->assertSee('Do planejamento ao grande dia.')
->assertSee('Quero conhecer a Essenza')
->assertSee('Começar com a Amare')
->assertSee('Organização, produção e condução com linguagem empresarial.')
->assertSee('Estruturação do evento, escopo, prioridades e cronograma.')
->assertSee('Falar sobre um evento Corporate')
->assertSee('Do casamento ao evento corporativo, tudo começa com uma boa conversa.')
->assertDontSee('Rascunho'); ->assertDontSee('Rascunho');
} }