{{ $title }}
@if ($metaLine !== ''){{ $metaLine }}
@endif@props([ 'project' => null, 'photo' => null, 'photoIndex' => 0, 'categoryLabel' => null, ]) @php /* | Image-first obra tile (owner request): the PHOTO is the protagonist and | the grid reads as a GALLERY, not a catalogue. There is no always-visible | caption block on hover-capable devices — the caption (title + the single | uso · tipo · ubicación line) reveals over the photo through a dark scrim | ONLY on hover. On touch devices (no hover capability) the same caption | stays VISIBLE below the photo. There is NO per-tile "Quiero algo así" | button (the client removed it): the single action lives inside the work's | full-screen dialog. The reveal decision is made by POINTER | (`@media (hover: hover)`), never by viewport width. */ $isModel = $project instanceof \App\Models\Project; $hasPhoto = $photo instanceof \App\Models\Media; $title = data_get($project, 'title', 'Obra'); $slug = data_get($project, 'slug'); $location = data_get($project, 'location'); $typeLabel = $isModel ? (filled($project->type) ? $project->typeLabel() : null) : (filled(data_get($project, 'type')) ? (data_get($project, 'type') === 'comercial' ? 'Comercial' : 'Residencial') : null); $useLabel = $isModel ? $project->useLabel() : (\App\Models\Project::USES[data_get($project, 'use')] ?? null); // The section passes the administrable category; on the uncategorized // "Otras obras" section the caption keeps the legacy `use` label, so a work // only loses its meta line when category, type AND location are all absent // (never an empty/dangling separator). $classificationLabel = filled($categoryLabel) ? $categoryLabel : $useLabel; $metaLine = collect([$classificationLabel, $typeLabel, $location])->filter()->join(' · '); $image = $isModel ? $project->image : data_get($project, 'image', \App\Models\Media::placeholderUrl()); // Each tile renders ONE of the work's photos when one is supplied (the // gallery now shows every photo up front); otherwise it falls back to the // cover image (or the branded placeholder for a photo-less work). $tileImage = $hasPhoto ? (string) $photo->url : $image; $tileAlt = $hasPhoto && filled($photo->alt_text) ? (string) $photo->alt_text : ('Obra '.$title.' en piedra laja'); $year = $isModel ? $project->completed_at?->format('Y') : null; // Unique per tile (a work may render several photo tiles sharing its title). $titleId = 'obra-title-'.($isModel ? $project->id : (string) $slug).($hasPhoto ? '-'.$photo->id : ''); /* | Variable-height mosaic: each obra gets a deterministic portrait/landscape | aspect from a short cycle (seeded by the id, or the slug hash for array | shapes) so the masonry heights stay stable across filter/pagination | re-renders while still varying from tile to tile. */ $aspects = ['aspect-[3/4]', 'aspect-[4/3]', 'aspect-[1/1]', 'aspect-[3/2]', 'aspect-[4/5]', 'aspect-[2/3]']; $seed = $isModel ? ($hasPhoto ? (int) $photo->id : (int) $project->id) : abs(crc32((string) $slug)); $aspect = $aspects[$seed % count($aspects)]; /* | Dialog data: the work's photos (gallery media, never the before/after | pair), the stones used and a WhatsApp deep link for the single dominant | action. A work with no photos degrades to the branded placeholder panel. */ $stones = $isModel ? $project->products : collect(); $photos = ($isModel ? $project->galleryMedia() : collect()) ->map(fn ($media): array => [ 'url' => (string) $media->url, 'alt' => filled($media->alt_text) ? (string) $media->alt_text : $title, ]) ->values() ->all(); $photoCount = count($photos); $whatsappUrl = app(\App\Services\WhatsappService::class)->link( null, 'Hola Piedra Total Perú, vi la obra "'.$title.'" en la galería y quiero algo así. ¿Me cotizan por m² y flete?', ); /* | Hover-vs-touch classes. The reveal and the action's clickability are both | guarded by `@media (hover: hover)`, so a touch device can never trigger | the overlay and the below-photo action can never disappear there. */ $touchBlockClasses = 'pt-4 [@media(hover:hover)]:hidden'; $overlayClasses = 'pointer-events-none absolute inset-0 z-10 flex flex-col justify-end bg-gradient-to-t from-brand-950/95 via-brand-950/45 to-transparent p-5 opacity-0 transition-opacity duration-base ease-out-soft [@media(hover:hover)]:group-hover:opacity-100'; @endphp
{{ $metaLine }}
@endifObra · Piedra natural