Who we are

One of the World's Most Inclusive HIIT Workouts

A workout operates across three zones - Treadmills, Resistance, and Intensity (TRI) - with live heart-rate tracking and expert coaching, TRIB3 has been designed to deliver a truly inclusive workout experience.

Contact Us to Franchise
Our Story

One TRIB3. One community. Worldwide.

TRIB3, founded in Sheffield, United Kingdom, is a uniquely inclusive boutique fitness franchise with a vision to build a global fitness community where anyone can belong. Passionate about creating amazing communities who sweat together, achieve together and have fun together, TRIB3 is active in multiple markets, including the UK, Spain, Portugal, Finland, Ireland, Netherlands and Panama.

Studio Experience

We sweat together

<iframe src="https://vr.unit360.pt/tribe/" height="657" width="100%" loading="lazy"></iframe>
iframe {
  border-radius: 32px;
  border: 1px solid transparent;
}

@media(max-width: 768px) {
  iframe {
    height: 500px;
  }
}
const iframe = document.querySelector('iframe[data-src]');

const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      iframe.src = iframe.dataset.src;
      observer.disconnect();
    }
  });
});

observer.observe(iframe);
our studios

Find Studios Nearby

TRIB3 Chamberi

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

C. de Joaquín María López, 22, Chamberí, 28015 Madrid, Spain

Visit StudioView in map

TRIB3 Palma

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Carrer de la Indústria, 5, Ponent, 07013 Palma, Illes Balears, Spain

Visit StudioView in map

TRIB3 San Gervasi

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Carrer de Moragas, 11, Sarrià-Sant Gervasi, 08022 Barcelona, Spain

Visit StudioView in map

TRIB3 Costa del Este

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Ph Times Square Center, Panamá, Provincia de Panamá, Panama

Visit StudioView in map

TRIB3 EDAN

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Carrer de Balmes, 28, Eixample, 08007 Barcelona, Spain

Visit StudioView in map

TRIB3 Las Tablas

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

C. del Puerto de Somport, 1, Fuencarral-El Pardo, 28050 Madrid, Spain

Visit StudioView in map

TRIB3 Aravaca

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Calle Dr. Balmis, 36, Moncloa – Aravaca, 28023 Madrid, Spain

Visit StudioView in map

TRIB3 Leeds

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

68A Wellington St, Leeds LS1 2EE, United Kingdom

Visit StudioView in map

TRIB3 Sheffield

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

557 Ecclesall Rd, Sharrow, Sheffield S11 8PR, United Kingdom

Visit StudioView in map

TRIB3 Koninginneweg

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Koninginneweg 29-31, 1075 CG Amsterdam, Netherlands

Visit StudioView in map

TRIB3 Haarlem

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Maerten van Heemskerckstraat 69A, 2021 ZH Haarlem, Netherlands

Visit StudioView in map

TRIB3 Valdebebas

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

C. de Gustavo Pérez Puig, 61, Hortaleza, 28055 Madrid, Spain

Visit StudioView in map

TRIB3 Sandyford

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

1 Plaza Level, Beacon South Quarter, Bracken Rd, Sandyford, Dublin, D18 K258, Ireland

Visit StudioView in map

TRIB3 Oeiras

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Rua Coro de Santo Amaro de Oeiras 8, 2780-379 Oeiras

Visit StudioView in map

TRIB3 Adlon

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Runeberginkatu 44, 00260 Helsinki, Finland

Visit StudioView in map

TRIB3 Valencia

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Av. de Jacinto Benavente, 2, L’Eixample, 46005 València, Valencia, Spain

Visit StudioView in map

TRIB3 Cherrywood

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Unit C2.04, Cherrywood Town Centre, The Galvin Building, Grand Parade, Cherrywood, Co. Dublin, D18 TF8C, Ireland

Visit StudioView in map

TRIB3 Middenweg

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Middenweg 10, 1097 BM Amsterdam, Netherlands

Visit StudioView in map

TRIB3 Amigo

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Carrer d’Amigó, 14, Sarrià-Sant Gervasi, 08021 Barcelona, Spain

Visit StudioView in map

TRIB3 Cuzco

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

P.º de la Castellana, 141, Tetuán, 28046 Madrid, Spain

Visit StudioView in map

TRIB3 Les Corts

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Carrer de Joan Güell, 113, Les Corts, 08028 Barcelona, Spain

Visit StudioView in map

TRIB3 Sagrada Família

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Carrer de València, 395, Eixample, 08013 Barcelona, Spain

Visit StudioView in map

TRIB3 Poblenou

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

Carrer de Bilbao, 133-135, Sant Martí, 08018 Barcelona, Spain

Visit StudioView in map

TRIB3 Deansgate/TRIB3 Manchester – The Ultimate HIIT Workout

<?php
$terms = get_the_terms(get_the_ID(), 'category_studio');

if ($terms && !is_wp_error($terms)) {
    $term = $terms[0]; // pega a primeira categoria associada ao estúdio
    $img = get_field('image_category', $term);

    if ($img) {
        echo '<img class="studio-category-image" src="' . esc_url($img['url']) . '" alt="' . esc_attr($term->name) . '">';
    }
}
?>
Trib3

6 John Dalton St, Manchester M2 6JP, United Kingdom

Visit StudioView in map
<!-- Mapbox CSS -->
<link href="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css" rel="stylesheet">
<!-- Mapbox JS -->
<script src="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js"></script>

<style>
/* ===== FONTE TT NORMS PRO ===== */
@font-face {
  font-family: 'TT Norms Pro';
  src: url('https://chv.slx.mybluehost.me/website_baaba2b9/wp-content/uploads/2025/04/TypeType-TT-Norms-Pro-Normal.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'TT Norms Pro';
  src: url('https://chv.slx.mybluehost.me/website_baaba2b9/wp-content/uploads/2025/04/TypeType-TT-Norms-Pro-Medium.ttf') format('truetype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'TT Norms Pro';
  src: url('https://chv.slx.mybluehost.me/website_baaba2b9/wp-content/uploads/2025/04/TypeType-TT-Norms-Pro-Light.ttf') format('truetype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

:root {
  --brown-dark: #201B1B;
  --white: #FFF;
  --button-color: #2d4f63;
}

/* ===== APLICANDO FONT EM TODOS OS ELEMENTOS DO POPUP ===== */
.mapboxgl-popup-content,
.popup-content,
.popup-title,
.popup-address,
.popup-button {
  font-family: 'TT Norms Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif !important;
}

.custom-marker {
  cursor: pointer;
}

.custom-marker svg {
  width: 50px;
  height: 50px;
}

@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.15); }
  100% { transform: scale(1); }
}

.marker-pulse svg {
  animation: pulse 1.4s infinite ease-in-out;
}

/* ----- ESTILO DO POPUP ----- */
.mapboxgl-popup-content {
  border-radius: 14px !important;
  padding: 0 !important;
  width: 435px !important;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
}

.popup-content {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
}

/* ===== BOTÃO FECHAR NO CANTO SUPERIOR DIREITO ===== */
.popup-close-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 24px;
  right: 24px;
  z-index: 10;
}

.popup-close-btn:hover {
  opacity: 0.7;
}

/* ===== TAG ACIMA DO TÍTULO ===== */
.popup-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--button-color) !important;
  padding: 8px;
  border-radius: 8px;
  width: fit-content;
  height: fit-content;
  margin-bottom: 8px;
}

/* ===== IMAGEM IGUAL AO CARD ===== */
.popup-tag img.studio-category-image {
  height: auto;
  max-width: 100%;
  outline: none;
  vertical-align: middle;
  width: auto;
  max-height: 32px;
  object-fit: contain;
  display: block;
}

.popup-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  margin-right: 32px;
}

.popup-title {
  font-size: 20px;
  font-style: normal;
  font-weight: 500 !important;
  line-height: normal;
  color: var(--brown-dark);
  margin: 0;
  flex: 1;
}

.popup-address {
  font-size: 16px;
  font-style: normal;
  font-weight: 300 !important;
  line-height: 24px;
  color: var(--brown-dark);
  margin: 0;
}

.popup-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--button-color);
  color: var(--white) !important;
  text-decoration: none;
  padding: 12px 20px;
  border-radius: 30px;
  font-size: 14px;
  font-style: normal;
  font-weight: 500 !important;
  line-height: 16px;
  text-transform: uppercase;
  border: none;
  cursor: pointer;
  transition: background-color 0.3s ease;
  width: 50%;
  text-align: center;
  margin-top: 8px;
}

.popup-button:hover {
  background: #1a3544;
}

/* Esconder botão de fechar do Mapbox */
.mapboxgl-popup-close-button {
  display: none !important;
}

/* Responsivo */
@media (max-width: 768px) {
  .mapboxgl-popup {
    max-width: 90vw !important;
    left: 5vw !important;
  }
  
  .mapboxgl-popup-content {
    max-width: 90vw !important;
    width: 90vw !important;
    margin: 0 auto !important;
  }
  
  .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip {
    align-self: center !important;
    margin-top: -1px !important;
  }
  
  .popup-content {
    padding: 20px;
  }
  
  .popup-close-btn {
    top: 20px;
    right: 20px;
  }
  
  .popup-title {
    font-size: 18px;
  }
  
  .popup-address {
    font-size: 14px;
    line-height: 20px;
  }
  
  .popup-button {
    padding: 10px 20px;
    font-size: 13px;
    width: 100%;
  }
  
  .popup-header {
    margin-right: 28px;
  }
}

@media (max-width: 480px) {
  .popup-content {
    padding: 16px;
  }
  
  .popup-close-btn {
    top: 16px;
    right: 16px;
  }
  
  .popup-title {
    font-size: 16px;
  }
  
  .popup-address {
    font-size: 13px;
    line-height: 18px;
  }
  
  .popup-button {
    padding: 10px 16px;
    font-size: 12px;
  }
  
  .popup-tag img.studio-category-image {
    max-height: 24px;
  }
  
  .popup-header {
    margin-right: 24px;
  }
}
</style>

<div id="map-container" style="height: 620px; width: 100%; position: relative; border-radius: 0 24px 24px 0; overflow: hidden;">
    <div id="map" style="height: 100%; width: 100%;"></div>
</div>

<script>
// SVG icons
const markerSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" fill="none">
  <circle opacity="0.25" cx="36" cy="36" r="36" fill="#37536A"/>
  <circle opacity="0.5" cx="35" cy="36" r="24" fill="#37536A"/>
  <g>
    <circle cx="34.9994" cy="35.9999" r="13.7143" fill="#37536A"/>
    <circle cx="34.9994" cy="35.9999" r="11.2143" stroke="white" stroke-width="5"/>
  </g>
</svg>`;

const closeSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
  <path d="M15 5L5 15" stroke="#201B1B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
  <path d="M5 5L15 15" stroke="#201B1B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>`;

const buttonArrowSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
  <path d="M17.25 12H6.75" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
  <path d="M13.5 15.75L17.25 12" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
  <path d="M13.5 8.25L17.25 12" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>`;

document.addEventListener('DOMContentLoaded', function() {
    'use strict';
    
    console.log('🚀 Script do mapa iniciado');
    
    mapboxgl.accessToken = 'pk.eyJ1IjoianAtZXZvIiwiYSI6ImNtbDVndTQ0bjAzbnMzZW9nN2xzMmpqd2gifQ.T7qCtaSzy6EYVqxZC9P-jg';
    
    const map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v12',
        center: [10, 50],
        zoom: 1.5
    });
    
    let markers = [];
    let currentPopup = null;
    let zoomTimeout = null;
    
    // Store ALL card data permanently
    const studiosData = [];
    
    const ANIMATION_DURATION = 2500;
    
    function isMobile() {
        return window.innerWidth <= 768;
    }
    
    function isMapView() {
        return document.body.classList.contains('map-view-mobile');
    }
    
    function getCoordsFromCard(card) {
        const coords = card.getAttribute('data-coords');
        if (!coords) return null;
        const [lat, lng] = coords.split(',').map(coord => parseFloat(coord.trim()));
        return [lng, lat];
    }
    
    // Extract ALL data from ALL cards ONCE and store permanently
    function extractAllStudiosData() {
        console.log('📊 Extraindo dados dos estúdios...');
        
        document.querySelectorAll('.Card-map').forEach((card, index) => {
            // Get coordinates
            const coords = getCoordsFromCard(card);
            if (!coords) return;
            
            // Get title
            const titleElement = card.querySelector('.card-map-tittle') || 
                                 card.querySelector('h2') || 
                                 card.querySelector('.brxe-heading');
            const title = titleElement ? titleElement.innerText.trim() : 'Studio';
            
            // Get address
            const addressElement = card.querySelector('.card-map-text') || 
                                   card.querySelector('p') ||
                                   card.querySelector('.brxe-heading:not(.card-map-tittle)');
            const address = addressElement ? addressElement.innerText.trim() : '';
            
            // Get category image
            const categoryImgElement = card.querySelector('.studio-category-image');
            let categoryImg = null;
            if (categoryImgElement) {
                categoryImg = {
                    src: categoryImgElement.getAttribute('src'),
                    alt: categoryImgElement.getAttribute('alt') || 'Studio'
                };
            }
            
            // Get link
            const buttonElement = card.querySelector('.brxe-button.button-white.bricks-button, a.brxe-button');
            const link = buttonElement ? buttonElement.getAttribute('href') : '#';
            
            // Store in our permanent array
            studiosData.push({
                id: `${coords[0]}-${coords[1]}`,
                title: title,
                address: address,
                categoryImg: categoryImg,
                link: link,
                coords: coords,
                cardId: card.id || `card-${index}`
            });
            
            console.log(`✅ Estúdio extraído: ${title}`);
        });
        
        console.log(`📊 Total de estúdios: ${studiosData.length}`);
    }
    
    // Find studio data by coordinates
    function findStudioByCoords(coords) {
        if (!coords || coords.length < 2) return null;
        
        const [lng, lat] = coords;
        
        return studiosData.find(studio => 
            Math.abs(studio.coords[0] - lng) < 0.001 && 
            Math.abs(studio.coords[1] - lat) < 0.001
        );
    }
    
    function createMarker(coords, studioData) {
        const el = document.createElement('div');
        el.className = 'custom-marker marker-pulse';
        el.innerHTML = markerSVG;
        
        // Store studio data directly on marker
        el.studioData = studioData;

        const marker = new mapboxgl.Marker({ element: el, anchor: 'center' })
            .setLngLat(coords)
            .addTo(map);

        el.addEventListener('click', function(e) {
            e.stopPropagation();
            e.preventDefault();
            handleMarkerClick(coords, this.studioData);
        });

        return marker;
    }
    
    function handleMarkerClick(coords, studioData) {
        console.log('📍 handleMarkerClick chamado para:', studioData.title);
        
        if (currentPopup) {
            currentPopup.remove();
            currentPopup = null;
        }

        if (zoomTimeout) {
            clearTimeout(zoomTimeout);
            zoomTimeout = null;
        }

        map.flyTo({
            center: coords,
            zoom: 13,
            duration: ANIMATION_DURATION
        });

        zoomTimeout = setTimeout(() => {
            openPopup(coords, studioData);
            zoomTimeout = null;
        }, ANIMATION_DURATION);
    }
    
    function openPopup(coords, studioData) {
        console.log('💬 Abrindo popup para:', studioData.title);
        
        if (currentPopup) {
            currentPopup.remove();
            currentPopup = null;
        }

        const title = studioData.title || "Studio";
        const address = studioData.address || "";
        const link = studioData.link || '#';
        
        let categoryImage = '';
        if (studioData.categoryImg && studioData.categoryImg.src) {
            categoryImage = `<img class="studio-category-image" src="${studioData.categoryImg.src}" alt="${studioData.categoryImg.alt}">`;
        }

        const popupHTML = `
            <div class="popup-content">
                <button class="popup-close-btn" id="popup-close">${closeSVG}</button>
                <div class="popup-tag">${categoryImage}</div>
                <div class="popup-header">
                    <div class="popup-title">${title}</div>
                </div>
                <div class="popup-address">${address}</div>
                <a href="${link}" class="popup-button" target="_blank" rel="noopener noreferrer">
                    VIEW STUDIO ${buttonArrowSVG}
                </a>
            </div>
        `;

        const popupOffset = isMobile() ? 40 : 20;

        const popup = new mapboxgl.Popup({
            offset: popupOffset,
            closeButton: false,
            maxWidth: isMobile() ? '90vw' : '435px',
            closeOnClick: false,
            anchor: 'bottom'
        })
        .setLngLat(coords)
        .setHTML(popupHTML)
        .addTo(map);

        setTimeout(() => {
            const closeBtn = document.getElementById('popup-close');
            if (closeBtn) {
                closeBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    popup.remove();
                    currentPopup = null;
                    document.querySelectorAll('.custom-marker').forEach(marker => {
                        marker.classList.add('marker-pulse');
                    });
                });
            }
        }, 100);

        currentPopup = popup;
        
        document.querySelectorAll('.custom-marker').forEach(marker => {
            marker.classList.remove('marker-pulse');
        });
    }
    
    function updateMarkers() {
        console.log('🔄 Atualizando marcadores...');
        markers.forEach(marker => marker.remove());
        markers = [];
        
        studiosData.forEach(studio => {
            markers.push(createMarker(studio.coords, studio));
        });
        console.log(`✅ ${markers.length} marcadores criados`);
    }
    
    // FUNÇÃO PRINCIPAL CORRIGIDA - ESCUTA O BOTÃO "VIEW IN MAP"
    function setupCardClicks() {
        console.log('🔧 Configurando clique nos botões View in map');
        
        // Verifica se os botões existem
        const botoes = document.querySelectorAll('.brxe-842f21.brxe-button');
        console.log(`🔍 Encontrados ${botoes.length} botões "View in map"`);
        
        // Adiciona clique em CADA botão individualmente (mais confiável)
        botoes.forEach((botao, index) => {
            botao.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                
                console.log(`✅ Botão View in map ${index} clicado!`);
                
                const card = this.closest('.Card-map');
                console.log('📇 Card encontrado:', card);
                
                if (!card) {
                    console.log('❌ Card não encontrado');
                    return;
                }

                // Pega coordenadas
                const coords = getCoordsFromCard(card);
                console.log('📍 Coordenadas:', coords);
                
                // Busca dados do estúdio
                const studioData = findStudioByCoords(coords);
                console.log('🏢 Dados do estúdio:', studioData);
                
                if (!coords || !studioData) {
                    console.log('❌ Dados não encontrados');
                    return;
                }

                // Abre no mapa
                handleMarkerClick(coords, studioData);
            });
        });
    }
    
    function setupFilterDetection() {
        const container = document.querySelector('.brxe-container') || document.body;
        
        const observer = new MutationObserver(function() {
            setTimeout(() => {
                updateMarkers();
                setupCardClicks(); // Reconfigura os botões após filtros
            }, 300);
        });
        
        observer.observe(container, {
            childList: true,
            subtree: true
        });
    }
    
    // Extract data when map loads
    map.on('load', function() {
        console.log('🗺️ Mapa carregado');
        
        // Extract all studio data FIRST
        extractAllStudiosData();
        
        // Then create markers
        updateMarkers();
        setupCardClicks(); // Configura os botões
        setupFilterDetection();
        map.addControl(new mapboxgl.NavigationControl());
    });
    
    map.on('click', function(e) {
        const isMarker = e.originalEvent.target.closest('.custom-marker');
        const isPopupContent = e.originalEvent.target.closest('.mapboxgl-popup-content');
        
        if (currentPopup && !isMarker && !isPopupContent) {
            currentPopup.remove();
            currentPopup = null;
            document.querySelectorAll('.custom-marker').forEach(marker => {
                marker.classList.add('marker-pulse');
            });
        }
    });
    
    map.on('popupclose', function() {
        currentPopup = null;
        document.querySelectorAll('.custom-marker').forEach(marker => {
            marker.classList.add('marker-pulse');
        });
    });
    
    // Reconfigurar botões quando mudar de view
    const listBtn = document.getElementById('brxe-list-btn');
    const mapBtn = document.getElementById('brxe-map-btn');
    
    if (listBtn) {
        listBtn.addEventListener('click', function() {
            setTimeout(() => {
                if (studiosData.length === 0) extractAllStudiosData();
                setupCardClicks(); // Reconfigura botões
            }, 500);
        });
    }
    
    if (mapBtn) {
        mapBtn.addEventListener('click', function() {
            setTimeout(() => {
                if (studiosData.length === 0) extractAllStudiosData();
                updateMarkers();
                setupCardClicks(); // Reconfigura botões
            }, 500);
        });
    }
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
    'use strict';
    
    /* ===== ELEMENTOS ===== */
    const icon = document.getElementById('brxe-ab0dd6');
    const filtersContainer = document.getElementById('brxe-3a65f8');
    
    /* ===== INJEÇÃO DE CSS ===== */
    const style = document.createElement('style');
    style.textContent = `
        /* Container dos filtros - animação suave */
        #brxe-3a65f8 {
            display: flex !important;
            opacity: 0;
            visibility: hidden;
            transform: translateY(-10px);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            pointer-events: none;
            margin: 0 !important;
            padding: 0 !important;
            height: 0;
            overflow: hidden;
        }
        
        /* Estado visível */
        #brxe-3a65f8.filters-visible {
            opacity: 1;
            visibility: visible;
            transform: translateY(0);
            pointer-events: all;
            height: auto;
            margin-bottom: 20px !important;
            padding: 0 !important;
            overflow: visible;
        }
        
        /* ÍCONE NORMAL */
        #brxe-ab0dd6 {
            cursor: pointer;
        }
        
        /* QUANDO ATIVO (filtro aparecendo) - SÓ O RECT FILL #666262 */
        #brxe-ab0dd6.filters-visible rect {
            fill: #666262 !important;
        }
        
        /* Ajuste no container pai */
        .brxe-block:has(#brxe-3a65f8) {
            margin-bottom: 0 !important;
            padding-bottom: 0 !important;
        }
        
        /* ===== SCROLL CUSTOMIZADO SOMENTE PARA OS CARDS ===== */
        /* Container principal dos cards */
        #brxe-a70ebe {
            scrollbar-width: thin;
            scrollbar-color: #FFFFFF #332D2D;
            overflow-y: auto;
            
        }
        
        /* Webkit (Chrome, Safari, etc) */
        #brxe-a70ebe::-webkit-scrollbar {
            width: 6px;
            height: 6px;
        }
        
        #brxe-a70ebe::-webkit-scrollbar-track {
            background: #332D2D;
            border-radius: 10px;
        }
        
        #brxe-a70ebe::-webkit-scrollbar-thumb {
            background: #FFFFFF;
            border-radius: 10px;
            border: 1px solid #332D2D;
        }
        
        #brxe-a70ebe::-webkit-scrollbar-thumb:hover {
            background: #f0f0f0;
        }
        
        /* Garantir que o mapa NÃO tenha scroll customizado */
        .brxe-code:has(.mapboxgl-map),
        .brxe-code iframe,
        [class*="mapbox"] {
            scrollbar-width: auto !important;
            scrollbar-color: auto !important;
        }
        
        .brxe-code:has(.mapboxgl-map)::-webkit-scrollbar,
        .brxe-code iframe::-webkit-scrollbar,
        [class*="mapbox"]::-webkit-scrollbar {
            width: auto !important;
            height: auto !important;
        }
    `;
    document.head.appendChild(style);
    
    /* ===== FUNÇÕES ===== */
    function toggleFilters(e) {
        e.preventDefault();
        e.stopPropagation();
        
        filtersContainer.classList.toggle('filters-visible');
        icon.classList.toggle('filters-visible');
    }
    
    /* ===== EVENTOS ===== */
    if (icon && filtersContainer) {
        icon.addEventListener('click', toggleFilters);
        icon.style.cursor = 'pointer';
    }
    
    if (filtersContainer) {
        filtersContainer.addEventListener('click', function(e) {
            e.stopPropagation();
        });
    }
});
</script>

Own a Business

Phone number
+34 630 177 183
Connect with us:
Tribute Brands - Franchising redefined. Your success is our Tribute.
<div id="zf_div_0qNMEcGneJPQHSw1PLEXF1cucleZZ1oe6nL7VurAcfk">
</div>
<script type="text/javascript">
(function() {
	try{
		var f = document.createElement("iframe");
		
			var ifrmSrc = 'https://forms.zohopublic.eu/tributebrands/form/ownabusiness3/formperma/0qNMEcGneJPQHSw1PLEXF1cucleZZ1oe6nL7VurAcfk?zf_rszfm=1';
		
		
        try{
			if ( typeof ZFAdvLead != "undefined" && typeof zfutm_zfAdvLead != "undefined" ) {
				for( var prmIdx = 0 ; prmIdx < ZFAdvLead.utmPNameArr.length ; prmIdx ++ ) {
				    var utmPm = ZFAdvLead.utmPNameArr[ prmIdx ];
				    utmPm = ( ZFAdvLead.isSameDomian && ( ZFAdvLead.utmcustPNameArr.indexOf(utmPm) == -1 ) ) ? "zf_" + utmPm : utmPm;
				    var utmVal = zfutm_zfAdvLead.zfautm_gC_enc( ZFAdvLead.utmPNameArr[ prmIdx ] );
				    if ( typeof utmVal !== "undefined" ) {
				      if ( utmVal != "" ) {
				        if(ifrmSrc.indexOf('?') > 0){
				             ifrmSrc = ifrmSrc+'&'+utmPm+'='+utmVal;
				        }else{
				            ifrmSrc = ifrmSrc+'?'+utmPm+'='+utmVal;
				        }
				      }
				    }
				}
			}
			if ( typeof ZFLead !== "undefined" && typeof zfutm_zfLead !== "undefined" ) {
				for( var prmIdx = 0 ; prmIdx < ZFLead.utmPNameArr.length ; prmIdx ++ ) {
		        	var utmPm = ZFLead.utmPNameArr[ prmIdx ];
		        	var utmVal = zfutm_zfLead.zfutm_gC_enc( ZFLead.utmPNameArr[ prmIdx ] );
			        if ( typeof utmVal !== "undefined" ) {
			          if ( utmVal != "" ){
			            if(ifrmSrc.indexOf('?') > 0){
			              ifrmSrc = ifrmSrc+'&'+utmPm+'='+utmVal;//No I18N
			            }else{
			              ifrmSrc = ifrmSrc+'?'+utmPm+'='+utmVal;//No I18N
			            }
			          }
			        }
		      	}
			}
		}catch(e){}
		
		f.src = ifrmSrc;
		f.style.border="none";
		f.style.height="800px";
		f.style.width="100%";
		f.style.transition="all 0.5s ease";
		f.setAttribute("aria-label", 'ownabusiness');
		
		var d = document.getElementById("zf_div_0qNMEcGneJPQHSw1PLEXF1cucleZZ1oe6nL7VurAcfk");
		d.appendChild(f);
		window.addEventListener('message', function (){
			var evntData = event.data;
			if( evntData && evntData.constructor == String ){
				var zf_ifrm_data = evntData.split("|");
				if ( zf_ifrm_data.length == 2 || zf_ifrm_data.length == 3 ) {
					var zf_perma = zf_ifrm_data[0];
					var zf_ifrm_ht_nw = ( parseInt(zf_ifrm_data[1], 10) + 15 ) + "px";
					var iframe = document.getElementById("zf_div_0qNMEcGneJPQHSw1PLEXF1cucleZZ1oe6nL7VurAcfk").getElementsByTagName("iframe")[0];
					if ( (iframe.src).indexOf('formperma') > 0 && (iframe.src).indexOf(zf_perma) > 0 ) {
						var prevIframeHeight = iframe.style.height;
						var zf_tout = false;
						if( zf_ifrm_data.length == 3 ) {
						    iframe.scrollIntoView();
						    zf_tout = true;
						}

						if ( prevIframeHeight != zf_ifrm_ht_nw ) {
							if( zf_tout ) {
							    setTimeout(function(){
							        iframe.style.height = zf_ifrm_ht_nw;
							    },500);
							} else {
							    iframe.style.height = zf_ifrm_ht_nw;
							}
						}
					}
				}
			}
		}, false);
    }catch(e){}
})();
</script>
Featured partner

Franchise Partner, TRIB3 Sagrada Familia

Meet Carlos Barletta, whose dedication and strategic operations resulted in his studio achieving a remarkable break-even in just two months. Check out the full story, where we delve into his background and TRIB3 journey as a Franchise Partner.

Read more
Tribute Brands - A Tribute to entrepreneurs turning dreams into reality. Franchise Opportunity. Carlos Barletta