Compare commits

..

11 Commits

Author SHA1 Message Date
623e45cbea test: Serviços — cobertura da nova página e atualização da spec 2026-08-12 08:55:29 -03:00
455bc4b7d8 feat: Serviços — página conforme preview com componentes reutilizáveis 2026-08-12 08:55:24 -03:00
3f55180b73 feat: Modalidades — novos campos de preview (tag, subtitle, comparação) 2026-08-12 08:55:20 -03:00
1425d7aaa1 fix: alinhar testes browser ao contrato de CTA home (#57) 2026-08-11 23:19:47 -03:00
62a19147ad Merge pull request #56 from manoel-freitas/feature/daisyui
feat: adota daisyUI 5 com tema amare
2026-08-11 22:54:03 -03:00
90632ada88 Merge remote-tracking branch 'origin/main' into feature/daisyui
# Conflicts:
#	resources/views/components/home/hero.blade.php
2026-08-11 22:45:45 -03:00
ce90cedb18 Merge remote-tracking branch 'origin/main' into feature/daisyui
# Conflicts:
#	resources/views/components/home/final-cta.blade.php
#	resources/views/components/home/hero.blade.php
#	resources/views/layouts/public.blade.php
2026-08-11 22:45:04 -03:00
a7d72f3756 Merge pull request #54 from manoel-freitas/feat/home-photo-hero
feat(home): normalizar hero com componente photo-hero compartilhado
2026-08-11 22:44:31 -03:00
0e0724c1cc test: alinhar contratos de hero ao photo-hero pos-rebase 2026-08-11 22:43:50 -03:00
ad29ce54d8 feat(home): normalizar hero com componente photo-hero compartilhado 2026-08-11 22:41:53 -03:00
0d1ca40c11 feat: adota daisyUI 5 com tema amare nos componentes públicos 2026-08-11 22:39:20 -03:00
37 changed files with 450 additions and 235 deletions

View File

@@ -24,6 +24,12 @@ 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()
@@ -44,6 +50,12 @@ 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,13 +16,17 @@ 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', 'summary', 'scope_items', 'cta_label', 'sort_order', 'published_at'])] #[Fillable(['name', 'level', 'tag', 'subtitle', 'summary', 'scope_items', 'cta_label', 'compare_heading', 'compare_summary', 'sort_order', 'published_at'])]
#[UsePolicy(WeddingPackagePolicy::class)] #[UsePolicy(WeddingPackagePolicy::class)]
class WeddingPackage extends Model class WeddingPackage extends Model
{ {

View File

@@ -18,9 +18,13 @@ 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

@@ -0,0 +1,27 @@
<?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)
* Copy is approved from the structural model preview (preview(1).html) and * and the services page. Copy is approved from the structural model preview
* remains editable via the Filament resource. * (preview(2).html) and remains editable via the Filament resource.
*/ */
class WeddingPackagesSeeder extends Seeder class WeddingPackagesSeeder extends Seeder
{ {
@@ -23,40 +23,55 @@ class WeddingPackagesSeeder extends Seeder
[ [
'name' => 'Essenza', 'name' => 'Essenza',
'level' => '01 / COMPLETA', 'level' => '01 / COMPLETA',
'summary' => 'Para casais que desejam contar com a Amare desde o planejamento até a realização do casamento.', 'tag' => 'Assessoria completa',
'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' => [
'Planejamento e organização', 'Estruturação do planejamento',
'Gestão de etapas e prioridades', 'Cronogramas, prazos e prioridades',
'Acompanhamento de fornecedores', 'Orientação e gestão de fornecedores',
'Coordenação do grande dia', 'Alinhamento entre os envolvidos',
'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',
'summary' => 'Para quem já começou e deseja estruturar o que falta, organizar fornecedores e seguir com acompanhamento profissional.', 'tag' => 'Assessoria parcial',
'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', 'Diagnóstico do planejamento existente',
'Organização das pendências', 'Organização das pendências',
'Gestão dos próximos passos', 'Gestão dos fornecedores contratados',
'Coordenação do grande dia', 'Orientação para próximas decisões',
'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',
'summary' => 'Para casais que já planejaram o casamento e precisam de uma equipe para assumir alinhamentos e operação na reta final.', 'tag' => 'Assessoria 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',
'Alinhamento de fornecedores', 'Conferência das informações',
'Cronograma final', 'Alinhamento dos fornecedores',
'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,10 +67,13 @@ 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 shows published services #### Scenario: Services listing renders editorial sections with published modalities
- **WHEN** a visitor loads `/servicos` - **WHEN** a visitor loads `/servicos`
- **THEN** every published service MUST be listed with title and summary in `sort_order` - **THEN** the page MUST present the two vertentes (Amare Casamentos and Amare Corporate) with CTAs to their sections
- **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": "site-amare", "name": "daisyui",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
@@ -7,6 +7,7 @@
"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",
@@ -790,6 +791,16 @@
"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,6 +10,7 @@
"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,6 +1,46 @@
@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';
@@ -227,3 +267,11 @@
} }
} }
} }
/* 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="border border-amare-error/40 bg-amare-error/5 px-6 py-5"> <div role="alert" class="alert alert-error border border-amare-error/40">
<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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-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="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" class="select w-full text-amare-text @error('tipo_evento') select-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-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="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" class="textarea w-full min-h-[110px] text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-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="mt-1 h-5 w-5 shrink-0 accent-amare-accent" class="checkbox checkbox-primary mt-1 shrink-0"
@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="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" class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]"
> >
Enviar briefing Enviar briefing
</button> </button>

View File

@@ -1,26 +1,40 @@
@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 lg:grid-cols-2 lg:gap-[70px]" data-reveal-group> <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="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">04 Amare Corporate</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $eyebrow }}</p>
<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> <h2 id="corporate-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">{{ $heading }}</h2>
</div> </div>
<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"> @if ($showMeta && filled($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. <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> {{ $meta }}
</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 ($settings->corporate_steps ?? [] as $index => $step) @foreach ($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">
@@ -31,15 +45,17 @@
@endforeach @endforeach
</div> </div>
<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"> <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">
Falar sobre um evento corporativo {{ $ctaLabel }}
</a> </a>
</div> </div>
<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"> @if ($showAside)
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Portfólio Corporate</p> <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">
<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="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Portfólio Corporate</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> <h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">Conteúdo em construção</h3>
</div> <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>
@endif
</div> </div>
</section> </section>

View File

@@ -1,6 +1,7 @@
@props([ @props([
'settings', 'settings',
'editorial' => false, 'editorial' => false,
'ctaHref' => null,
]) ])
<section aria-labelledby="final-cta-heading" @class([ <section aria-labelledby="final-cta-heading" @class([
@@ -17,8 +18,8 @@
</p> </p>
<div> <div>
<a <a
href="{{ route('briefing') }}" href="{{ $ctaHref ?? route('briefing') }}"
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" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]"
> >
{{ $settings->hero_cta_label ?: 'Solicitar proposta' }} {{ $settings->hero_cta_label ?: 'Solicitar proposta' }}
</a> </a>

View File

@@ -2,48 +2,29 @@
'settings', 'settings',
]) ])
<section <x-public.photo-hero
aria-labelledby="hero-heading" @class(['home-chapter'])
class="home-chapter border-b border-amare-border bg-amare-bg"
data-chapter="hero" data-chapter="hero"
data-motion="page-open" :image-path="$settings->hero_image_path"
: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="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"> <div class="flex flex-wrap items-center gap-4">
<div data-hero-content data-reveal-group class="flex flex-col gap-8"> <a href="{{ route('contact') }}" data-testid="home-primary-cta" class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]">
<div data-motion-beat="eyebrow"> {{ $settings->hero_cta_label ?: 'Solicitar proposta' }}
<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> </a>
</div>
<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"> @if (filled($settings->hero_secondary_cta_label))
Eventos com intenção, cuidado e presença. <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">
</h1> <span class="border-b border-amare-accent pb-1">{{ $settings->hero_secondary_cta_label }}</span>
</a>
<p class="max-w-[760px] text-[clamp(1.1875rem,2vw,1.5rem)] leading-[1.55] text-amare-text-muted"> @endif
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,11 +1,23 @@
@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
@@ -17,10 +29,12 @@
<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">03 Amare Casamentos</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $eyebrow }}</p>
<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> <h2 id="packages-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">{{ $heading }}</h2>
</div> </div>
<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> @if ($showIntro && filled($intro))
<p class="max-w-[600px] text-amare-text-muted">{{ $intro }}</p>
@endif
</div> </div>
@if ($packages->isNotEmpty()) @if ($packages->isNotEmpty())
@@ -28,8 +42,11 @@
@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">{{ $package->level }}</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent">{{ $kicker === 'tag' ? $package->tag : $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)
@@ -41,11 +58,14 @@
$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="{{ $waLink }}" href="{{ $href }}"
@if ($hasWhatsapp) target="_blank" rel="noopener noreferrer" @endif @if ($ctaRoute === null && $hasWhatsapp) target="_blank" rel="noopener noreferrer" @endif
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" class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]"
> >
{{ $package->cta_label }} {{ $package->cta_label }}
</a> </a>
@@ -57,13 +77,15 @@
<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">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> <p class="text-amare-accent-text/80">{{ $bandBody }}</p>
</div> </div>
<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"> <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">
Conversar com a Amare Conversar com a Amare
</a> </a>
</div> </div>
<p class="mt-6 text-sm text-amare-muted">Nomenclaturas exibidas conforme materiais/reunião; confirmar versão final antes da publicação.</p> @if ($showNote && filled($note))
<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="inline-flex min-h-11 items-center text-sm font-semibold text-amare-accent transition-colors hover:text-amare-accent-deep"> <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">
<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="inline-flex min-h-11 items-center text-sm font-semibold text-amare-accent transition-colors hover:text-amare-accent-deep"> <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">
<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,4 +1,23 @@
@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"
@@ -8,34 +27,24 @@
> >
<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">02 Duas vertentes, uma mesma forma de cuidar</p> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $eyebrow }}</p>
<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> <h2 id="vertentes-heading" class="text-[clamp(2.375rem,5vw,4rem)] font-medium leading-[1.05] tracking-[-0.02em] text-amare-text">{{ $heading }}</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]">
<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"> @foreach ($cards as $card)
<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> <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 class="relative flex flex-col gap-5"> <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>
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Amare Casamentos</p> <div class="relative flex flex-col gap-5">
<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> <p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $card['label'] }}</p>
<p class="text-amare-text-muted">Do início da organização à reta final, modalidades pensadas para diferentes momentos do casal.</p> <h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">{{ $card['title'] }}</h3>
<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"> <p class="text-amare-text-muted">{{ $card['body'] }}</p>
Conhecer casamentos <a href="{{ $card['href'] }}" class="btn btn-outline mt-2 self-start text-xs font-bold uppercase tracking-[0.09em]">
</a> {{ $card['cta'] }}
</div> </a>
</article> </div>
</article>
<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"> @endforeach
<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="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> <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>
@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="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"> <a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
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="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"> <a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
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="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"> <a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
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="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"> <a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
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="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"> <a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
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()) }}"> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}" data-theme="amare">
<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="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('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('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('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('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('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('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('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('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> <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>
</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,13 +70,14 @@
</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="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]"> <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">
Conte seu evento Conte seu evento
</a> </a>
</a>
<button <button
type="button" type="button"
class="menu-button inline-flex h-11 w-11 items-center justify-center border border-amare-border text-amare-text md:hidden" class="menu-button btn btn-square btn-ghost 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="mt-8 border border-amare-border bg-amare-bg-deep px-6 py-5"> <div role="status" class="alert mt-8 border border-amare-border bg-amare-bg-deep">
<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="border border-amare-error/40 bg-amare-error/5 px-6 py-5"> <div role="alert" class="alert alert-error border border-amare-error/40">
<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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-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="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" class="select w-full text-amare-text @error('tipo_evento') select-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-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="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" class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-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="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" class="textarea w-full text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-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="mt-1 h-5 w-5 shrink-0 accent-amare-accent" class="checkbox checkbox-primary mt-1 shrink-0"
@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="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" class="btn btn-primary min-h-11 px-8 text-sm font-semibold uppercase tracking-[0.12em]"
> >
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="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> <button type="submit" data-submit-button class="btn btn-primary text-sm font-semibold uppercase tracking-[.12em]">Enviar apresentação</button>
</form> </form>
@endif @endif
</div> </div>

View File

@@ -1,55 +1,92 @@
@extends('layouts.public') @extends('layouts.public')
@section('content') @section('content')
<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." /> <x-public.photo-hero
:image-path="$siteSettings->services_hero_image_path"
<div class="border-b border-amare-border bg-amare-bg"> :image-alt="$siteSettings->services_hero_image_alt"
<div class="container-amare space-y-10 py-16 md:py-24"> eyebrow="Serviços"
title="O cuidado certo para cada tipo de evento."
@if ($services->isEmpty()) 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."
<p class="text-amare-muted">O catálogo de serviços está em organização. Enquanto isso, fale conosco para uma primeira conversa.</p> >
@else <div class="flex flex-wrap items-center gap-4">
@php($hasPrioritizedImage = false) <a href="#vertentes" class="btn btn-primary text-xs font-bold uppercase tracking-[0.09em]">
<div class="divide-y divide-amare-border border-y border-amare-border" data-editorial-service-list data-reveal-group> Conhecer os serviços
@foreach ($services as $index => $service) </a>
<article @class([ <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">
'grid gap-4 py-8 md:grid-cols-[5rem_minmax(0,1fr)_minmax(0,1.2fr)] md:items-start', <span class="border-b border-amare-accent pb-1">Tenho um evento em mente</span>
'md:translate-x-8' => $loop->even, </a>
]) data-reveal data-reveal-from="up">
<span class="text-sm font-semibold uppercase tracking-[0.14em] text-amare-accent">{{ str_pad((string) ($index + 1), 2, '0', STR_PAD_LEFT) }}</span>
<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>
</div>
<div class="space-y-4">
@if (filled($service->cover_image_path))
@php($prioritizeImage = ! $hasPrioritizedImage)
<x-media.image
:path="$service->cover_image_path"
:alt="$service->cover_image_alt ?: $service->title"
:loading="$prioritizeImage ? 'eager' : 'lazy'"
:fetchpriority="$prioritizeImage ? 'high' : null"
sizes="(max-width: 768px) calc(100vw - 3rem), 40vw"
class="img-editorial aspect-[16/10] w-full object-cover"
/>
@php($hasPrioritizedImage = true)
@endif
@if (filled($service->description))
<div class="text-amare-muted">
{!! nl2br(e($service->description)) !!}
</div>
@endif
</div>
</article>
@endforeach
</div>
@endif
</div> </div>
</div> </x-public.photo-hero>
<x-home.vertentes
eyebrow="Duas vertentes"
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
:packages="$weddingPackages"
:settings="$siteSettings"
eyebrow="Amare Casamentos"
heading="Três formas de ter a Amare ao lado."
:show-intro="false"
kicker="tag"
:show-subtitle="true"
cta-route="contact"
:band-cta-href="route('contact')"
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."
:show-note="false"
/>
@if ($weddingPackages->isNotEmpty()) @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> <section aria-label="Comparação rápida entre as modalidades" class="border-b border-amare-border bg-amare-bg">
<div class="container-amare py-16 md:py-24" data-reveal-group>
<div class="grid border-l border-t border-amare-border md:grid-cols-3">
@foreach ($weddingPackages as $package)
@if (filled($package->compare_heading))
<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">
<div class="space-y-4">
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent">{{ $package->name }}</p>
<h3 class="text-[clamp(1.25rem,2vw,1.5rem)] font-medium leading-tight text-amare-text">{{ $package->compare_heading }}</h3>
<p class="text-amare-text-muted">{{ $package->compare_summary }}</p>
</div>
</article>
@endif
@endforeach
</div>
</div>
</section>
@endif @endif
<x-home.final-cta :settings="$siteSettings" /> <x-home.corporate
: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,8 +93,7 @@ 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');
$hash = $page->script('() => window.location.hash'); $page->assertPathIs('/contato');
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,
mediaInsideContainer: (mediaRect?.right ?? 0) < window.innerWidth - 100, mediaTouchesViewportRight: (mediaRect?.right ?? 0) >= window.innerWidth - 4,
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,
'mediaInsideContainer' => true, 'mediaTouchesViewportRight' => 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"]');
expect($page->script('() => window.location.hash'))->toBe('#sobre'); $page->assertPathIs('/contato');
}); });
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"]');
expect($page->script('() => window.location.hash'))->toBe('#sobre'); $page->assertPathIs('/contato');
}); });
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('Eventos com intenção, cuidado e presença.') ->assertSee($settings->hero_title)
->assertSee($settings->brand_name); ->assertSee($settings->brand_name);
}); });

View File

@@ -20,7 +20,7 @@ class HomePageTest extends TestCase
$response $response
->assertOk() ->assertOk()
->assertSee('Eventos com intenção, cuidado e presença.') ->assertSee('Celebrações com propósito')
->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_uses_fixed_editorial_copy_regardless_of_settings(): void public function test_hero_falls_back_to_default_copy_when_fields_are_empty(): 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,11 +124,8 @@ class HomePageContentTest extends TestCase
$response $response
->assertOk() ->assertOk()
->assertSee('Eventos com intenção, cuidado e presença.') ->assertSeeInOrder(['id="hero-heading"', 'Celebrações com propósito'], 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.') ->assertSeeInOrder(['data-testid="home-primary-cta"', 'Solicitar proposta'], false);
->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
@@ -160,12 +157,11 @@ class HomePageContentTest extends TestCase
$this->get(route('home')) $this->get(route('home'))
->assertOk() ->assertOk()
->assertSee('min-h-[320px]', false) ->assertSee('data-tonal-hero', 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)
->assertSee('data-motion-beat="media"', false) ->assertDontSee('data-photo-hero', false)
->assertDontSee('data-motion-beat="media"', false)
->assertDontSee('content/home/hero.jpg', false); ->assertDontSee('content/home/hero.jpg', false);
} }

View File

@@ -37,15 +37,16 @@ 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('md:min-h-[520px]', false) ->assertSee('data-photo-hero', 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('md:grid-cols-[1.1fr_0.9fr]', false) ->assertSee('lg:grid-cols-12', 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, 45vw"', false) ->assertSee('sizes="(max-width: 1023px) 100vw, 58vw"', 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);
} }
@@ -75,9 +76,8 @@ 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)
->assertSee('data-split-hero', false) ->assertDontSee('data-photo-hero', false)
->assertSee('data-tonal-hero', false) ->assertDontSee('data-split-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->assertMatchesRegularExpression('/service-first\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $services); $this->assertStringNotContainsString('service-first.jpg', $services);
$this->assertMatchesRegularExpression('/service-later\.jpg"[^>]*loading="lazy"(?![^>]*fetchpriority)/', $services); $this->assertStringNotContainsString('service-later.jpg', $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->assertMatchesRegularExpression('/visible-service\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $services); $this->assertStringNotContainsString('visible-service.jpg', $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="eyebrow"', false) ->assertSee('data-motion-beat="seal"', 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,17 +18,45 @@ class PublicPagesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
public function test_services_index_lists_published_services_in_sort_order(): void public function test_services_index_renders_editorial_sections_with_published_modalities_only(): void
{ {
SiteSetting::instance(); SiteSetting::instance();
Service::factory()->create(['title' => 'Rascunho', 'published_at' => null]); WeddingPackage::factory()->create(['name' => 'Rascunho', 'published_at' => null]);
Service::factory()->published()->create(['title' => 'Serviço B', 'sort_order' => 20]); WeddingPackage::factory()->published()->create([
Service::factory()->published()->create(['title' => 'Serviço A', 'sort_order' => 10]); 'name' => 'Essenza',
'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()
->assertSeeInOrder(['Serviço A', 'Serviço B']) ->assertSee('O cuidado certo para cada tipo de evento.')
->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');
} }