/* ═══════════════════════════════════════════════════════════════════════════
   SOBRE L'ESBART — bundle (shared components + page).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── EsbartNav — loaded via shared/components/Nav.jsx ───────────────────── */
const EsbartNav = window.EsbartNav;

/* ─── EsbartFooter ───────────────────────────────────────────────────────── */
const EsbartFooter = window.EsbartFooter; /* unified shared footer */

/* ─── Tweaks — loaded via shared/components/TweaksPanel.jsx ─── */
const useEsbartTweaks = window.EsbartTweaks.useTweaks;
const EsbartTweaksPanel = window.EsbartTweaksPanel;

/* ═══════════════════════════════════════════════════════════════════════════
   SOBRE L'ESBART — page-specific app
   ═══════════════════════════════════════════════════════════════════════════ */

const { useState, useEffect } = React;

const ESBART_TWEAKS = /*EDITMODE-BEGIN*/{
  "accentHue": 350,
  "typeScale": 1
}/*EDITMODE-END*/;
window.ESBART_TWEAKS = ESBART_TWEAKS;

/* ─── Dades compartides: Mestres (noms iguals a totes les llengües) ─────────
   Cada secció té id + items[]. Les traduccions dels títols van als strings.
   ─────────────────────────────────────────────────────────────────────────── */
const MASTERS_SECTIONS_ITEMS = [
  {
    id: "presidents",
    items: [
      { span: "1908 — 1909", name: "Joan B. Soler Bru" },
      { span: "1909 — 1914", name: "Antoni Casalí Ferran" },
      { span: "1914 — 1916", name: "Joan B. Soler Bru" },
      { span: "1917 — 1921", name: "Joan Bel Vilalta" },
      { span: "1921 — 1924", name: "Antoni Casalí Ferran" },
      { span: "1924 — 1926", name: "Joan Amades Gelats" },
      { span: "1926 — 1928", name: "Ricard Llansà Uliart" },
      { span: "1928 — 1937", name: "Antoni Casalí Ferran" },
      { span: "1934",        name: "Ricard Llansà Uliart", note: "en funcions" },
      { span: "1937 — 1949", name: "Josep Ventura Llates" },
      { span: "1950 — 1951", name: "Lluís Llobet Sánchez" },
      { span: "1951",        name: "Josep Ventura Llates", note: "en funcions" },
      { span: "1951 — 1956", name: "Joan Farrarons Graupera" },
      { span: "1956 — 1964", name: "Josep Palouzié Carrera" },
      { span: "1964 — 1977", name: "Fèlix Sarrat Royo" },
      { span: "1977 — 1978", name: "Joaquim Aicart Martí" },
      { span: "1978",        name: "Jaume Simón Pujol", note: "en funcions" },
      { span: "1979",        name: "Cecili Jaime Porqueras", note: "en funcions" },
      { span: "1979 — 1987", name: "Josep Palouzié Carrera" },
      { span: "1987 — 1991", name: "Mª Rosa Alonso Solanes" },
      { span: "1991 — 1997", name: "Josep Palouzié Carrera" },
      { span: "1997 — 2019", name: "Jordi Bartolomé Antonés" },
      { span: "2019 — actualitat", name: "Daniel Trullols i Ruau" },
    ]
  },
  {
    id: "mestres-cos",
    items: [
      { span: "1908 — 1909", name: "Rafel Tudó Duran" },
      { span: "1909 — 1917", name: "Aureli Capmany Farrés" },
      { span: "1917 — 1955", name: "Felip Blasco Anglès" },
      { span: "1948 — 1955", name: "Josep Ventura Llates", note: "en funcions" },
      { span: "1955 — 1959", name: "Jaume Simon Pujol" },
      { span: "1956",        name: "Felip Blasco Anglès", note: "en funcions" },
      { span: "1959 — 1963", name: "Francesc Passapera López" },
      { span: "1963 — 1965", name: "Josep Ventura Llates" },
      { span: "1963 — 1978", name: "Ignasi Viñolas Roig" },
      { span: "1965",        name: "Jaume Simon Pujol" },
      { span: "1965 — 1988", name: "Mª Rosa Alonso Solanes" },
      { span: "1988",        name: "Carles Mas Garcia" },
      { span: "1988 — 1989", name: "Carles d'Abàsolo Hernàndez" },
      { span: "1989 — 1992", name: "Montserrat Garrich Ribera" },
      { span: "1992 — 1993", name: "Mª Rosa Alonso Solanes", note: "en funcions" },
      { span: "1993 — 1994", name: "Ramon Batalla Vila" },
      { span: "1993 — 2026", name: "Anna Bigas Puig" },
      { span: "2026 — actualitat", name: "Guillem Amorós Bigas" },
    ]
  },
  {
    id: "mestres-juv",
    items: [
      { span: "1947 — 1950", name: "Roser Blasco Soler" },
      { span: "1964",        name: "Ramon Ferran Tolosa Torrebella" },
      { span: "1964 — 1965", name: "Mª Carme Lasaosa Puértolas" },
      { span: "1965",        name: "Carme Simon Pujol" },
      { span: "1965 — 1982", name: "Cecili Jaime Porqueres" },
      { span: "1976",        name: "Núria Coll Roig" },
      { span: "1976 — 1977", name: "Montserrat Roca Juncosa" },
      { span: "1976 — 1977", name: "Jordi Pérez Bravo" },
      { span: "1976 — 1978", name: "Montserrat Delgado Baldrich" },
      { span: "1976 — 1982", name: "Anna Bigas Puig" },
      { span: "1982 — 1984", name: "Jordi Bartolomé Antonés" },
      { span: "1983 — 1985", name: "Montserrat Garrich Ribera" },
      { span: "1986 — 1987", name: "Encarna Ariza Escobar" },
      { span: "1987 — 1988", name: "Laura Barberà Filló" },
      { span: "1988",        name: "Margarita Aniorte Lafuente" },
      { span: "1989 — 1990", name: "Núria Sauné Corral" },
      { span: "1989 — 1990", name: "Sílvia Martín Ferrer" },
      { span: "1990",        name: "Miquel Batalla Pérez" },
      { span: "1991 — 1998", name: "Oriol Fonollosa Duch" },
      { span: "1992 — 2000", name: "Elisabet Viladrich Fernández" },
      { span: "1994 — 2001", name: "Núria Vinyoles Insa" },
      { span: "1996 — 1997", name: "Yolanda Rodríguez Anadón" },
      { span: "2000 — 2003", name: "Ester Barceló Bonet" },
      { span: "2001 — 2024", name: "Montserrat Garrich Ribera" },
      { span: "2001 — 2002", name: "Marta Parra Albiach" },
      { span: "2002 — 2003", name: "Alba Anguela Aymamí" },
      { span: "2003 — 2004", name: "Pompili Massa Pujol" },
      { span: "2002 — 2024", name: "Anna Vinyoles Insa" },
      { span: "2004 — actualitat", name: "Mònica Amorós Bigas" },
      { span: "2006 — actualitat", name: "Oriol Fonollosa Duch" },
      { span: "2009 — 2013", name: "Raquel Díaz Muñoz" },
      { span: "2011 — actualitat", name: "Anna Jordana Moreso" },
      { span: "2013 — 2026", name: "Cèlia Bartolomé" },
      { span: "2015 — 2024", name: "Albert Viñolas i Vilà" },
      { span: "2017 — actualitat", name: "Biel Fonollosa Guasch" },
    ]
  },
  {
    id: "directors-musicals",
    items: [
      { span: "1909 — 1917", name: "Cèsar Canals Roges" },
      { span: "1917 — 1919", name: "Pascual Segura" },
      { span: "1919 — 1920", name: "Joan Tomàs Parés" },
      { span: "1920 — 1921", name: "Màrius Escofet Molist" },
      { span: "1922",        name: "Martí Olivella" },
      { span: "1922",        name: "Màrius Escofet Molist" },
      { span: "1922 — 1949", name: "Ricard Llansà Uliart" },
      { span: "1950",        name: "Lluís Albert Rivas" },
      { span: "1964 — 1975", name: "Agustí Cohí Grau" },
      { span: "1968 — 1969", name: "Mª Eugenia Ayala" },
      { span: "1975 — 1988", name: "Mª Rosa Alonso Solanes" },
      { span: "1988",        name: "Carles Mas Garcia" },
      { span: "1992 — 1993", name: "Mª Rosa Alonso Solanes" },
      { span: "1993 — 2025", name: "Joan Gómez Soriano" },
      { span: "2025 — actualitat", name: "Albert Montcada" },
    ]
  },
  {
    id: "pianistes",
    items: [
      { span: "1908",        name: "Eusebi Bosch Humet" },
      { span: "1909 — 1911", name: "Cèsar Canals" },
      { span: "1914",        name: "Ezequiel Martín" },
      { span: "1933 — 1935", name: "Ricard Llansà Claramunt" },
      { span: "1947 — 1951", name: "Maria Blasco Soler" },
      { span: "1953 — 1965", name: "Carme Gonzalo" },
      { span: "1957",        name: "Agustí Cohí Grau", note: "per vacances de C. Gonzalo" },
      { span: "1965",        name: "Eugènia Ayala Lacas" },
      { span: "1965 — 1967", name: "M. Francesca Ubach Llansà" },
      { span: "1971 — 1972", name: "Ismael Giménez Vicente" },
      { span: "1972",        name: "David Bartolomé Antonés" },
      { span: "1972 — 1988", name: "Mª Rosa Alonso Solanes" },
      { span: "1982 — 1984", name: "Josep Bayé Blanch" },
      { span: "1989",        name: "Urbez Santana Roma" },
      { span: "1992 — 1993", name: "Mª Rosa Alonso Solanes" },
      { span: "2009 — actualitat", name: "Anna Jordana Moreso" },
    ]
  },
  {
    id: "auxiliars",
    items: [
      { span: "1920",        name: "Joan Brunet" },
      { span: "1926",        name: "Ramon Sesé Salvat" },
      { span: "1940",        name: "Josep Ventura Llates" },
      { span: "1950 — 1954", name: "Jaume Simón Pujol" },
      { span: "1954",        name: "Jordi Serra Bafalluí" },
      { span: "1955",        name: "Maurici Palouzié Carrera" },
      { span: "1955",        name: "M. Rosa Alonso Solanes" },
      { span: "1956 — 1962", name: "Cecili Jaime Porqueras" },
      { span: "1956 — 1962", name: "Jaume Simon Pujol" },
      { span: "1972",        name: "Cecili Jaime Porqueres" },
      { span: "1975 — 1976", name: "Montserrat Sentís Masgoret" },
      { span: "1976 — 1982", name: "Anna Bigas Puig" },
      { span: "1982 — 1987", name: "Carles Mas Garcia" },
      { span: "1988 — 1992", name: "Montserrat Garrich Ribera" },
      { span: "1992 — 1993", name: "Ramon Batalla Vila" },
      { span: "1997 — 1999", name: "Ramon Trullols Ruau" },
      { span: "1999 — 2006", name: "Carles d'Abàsolo Hernández" },
      { span: "2007 — 2010", name: "Ramon Trullols Ruau" },
      { span: "2010 — 2012", name: "Daniel Trullols Ruau" },
    ]
  },
  {
    id: "majordomia",
    items: [
      { span: "1916 — 1949", name: "Ramon Sesé Salvat" },
      { span: "1949",        name: "Montserrat Vilaresau Bisbal" },
      { span: "1962 — 1963", name: "Enric Solà Cabane" },
      { span: "1964 — 1970", name: "Carme Lasaosa Puértolas" },
      { span: "1970 — 1979", name: "Isabel Villar Mora" },
      { span: "1975 — 1985", name: "Núria Roig Bueno" },
      { span: "1975 — 1983", name: "Elena Pou Freixa" },
      { span: "1976 — 1985", name: "Rosa Serra Barbo" },
      { span: "1984",        name: "Dolors Rich" },
      { span: "1985 — 1990", name: "Rosa Castillo Vilaplana" },
      { span: "1986 — 1993", name: "Núria Pérez Borràs" },
      { span: "1990 — actualitat", name: "Joana Duch Salcedo" },
      { span: "1994 — 1998", name: "Helena Filló" },
      { span: "1996 — 2004", name: "Antònia Vilarrubla" },
      { span: "2000 — actualitat", name: "Montserrat Garrich Ribera" },
      { span: "2002 — 2005", name: "Josefina Flamerich" },
      { span: "2002 — 2006", name: "Rosa Flotats Bertran" },
      { span: "2006 — 2010", name: "Rosa Pérez Sisternas" },
      { span: "2007 — actualitat", name: "Xavier Olaria Villar" },
      { span: "2009 — actualitat", name: "Carme Bertran Prades" },
      { span: "2018 — 2020", name: "Montserrat Ferrando" },
      { span: "2019 — actualitat", name: "Núria Fabra" },
      { span: "2019 — actualitat", name: "Mireia Planas" },
      { span: "2021 — actualitat", name: "Genoveva Jiménez" },
      { span: "2021 — actualitat", name: "Soledad Abejon" },
      { span: "2021 — actualitat", name: "Guillem Amorós" },
    ]
  },
  {
    id: "ball-divendres",
    items: [
      { span: "1998 — 2006",     name: "Anna Vinyoles Insa" },
      { span: "2006 — 2026",     name: "Montserrat Garrich Ribera" },
      { span: "2006 — actualitat", name: "Anna Bigas Puig" },
    ]
  },
];

/* ─────────────────────────────────────────────────────────────────────────
   SOCIS DE MÈRIT, D'HONOR I HOMENATJATS — dades
   ─────────────────────────────────────────────────────────────────────────
   · Els títols estan ESTANDARDITZATS via claus canòniques (HONOR_TITLES).
     S'han corregit variants tipogràfiques de l'original sense barrejar
     conceptes únics: "Homentatge"→Homenatge, "Spocia"→Sòcia,
     "50e"→50è. Soci d'Honor / Soci Honorari / Soci de Mèrit es mantenen
     com a reconeixements DIFERENTS.
   · Cada persona té gènere (g) per resoldre la forma del títol (m/f).
   · Els qualificadors d'homenatge van a HONOR_NOTES.
   · Per AFEGIR-NE més: només cal afegir un objecte a HONOR_PEOPLE amb
     recs:[{t:<clau>, y:<any>, q:<clau-nota?>}]. La línia del temps i les
     estadístiques es recalculen soles.
   ───────────────────────────────────────────────────────────────────────── */
const HONOR_TITLES = {
  // clau:        { cat, [ca m,f], [es m,f], [en m,f] }
  merit:         { cat: "merit",     ca: ["Soci de Mèrit", "Sòcia de Mèrit"],         es: ["Socio de Mérito", "Socia de Mérito"],       en: ["Member of Merit", "Member of Merit"] },
  dansaire:      { cat: "dansaire",  ca: ["Dansaire de Mèrit", "Dansaire de Mèrit"],  es: ["Bailarín de Mérito", "Bailarina de Mérito"], en: ["Dancer of Merit", "Dancer of Merit"] },
  honor:         { cat: "honor",     ca: ["Soci d’Honor", "Sòcia d’Honor"],           es: ["Socio de Honor", "Socia de Honor"],         en: ["Member of Honour", "Member of Honour"] },
  honorari:      { cat: "honorari",  ca: ["Soci Honorari", "Sòcia Honorària"],        es: ["Socio Honorario", "Socia Honoraria"],       en: ["Honorary Member", "Honorary Member"] },
  vitalici:      { cat: "vitalici",  ca: ["Soci Vitalici", "Sòcia Vitalícia"],        es: ["Socio Vitalicio", "Socia Vitalicia"],       en: ["Life Member", "Life Member"] },
  dir_honorari:  { cat: "director",  ca: ["Director Honorari", "Directora Honorària"], es: ["Director Honorario", "Directora Honoraria"], en: ["Honorary Director", "Honorary Director"] },
  dir_honorific: { cat: "director",  ca: ["Director Honorífic", "Directora Honorífica"], es: ["Director Honorífico", "Directora Honorífica"], en: ["Honorific Director", "Honorific Director"] },
  dir_perpetu:   { cat: "director",  ca: ["Director Perpetu", "Directora Perpètua"],  es: ["Director Perpetuo", "Directora Perpetua"],  en: ["Perpetual Director", "Perpetual Director"] },
  fidel:         { cat: "fidel",     ca: ["Fidel Comportament", "Fidel Comportament"], es: ["Fiel Comportamiento", "Fiel Comportamiento"], en: ["Faithful Service", "Faithful Service"] },
  homenatge:     { cat: "homenatge", ca: ["Homenatge", "Homenatge"],                  es: ["Homenaje", "Homenaje"],                     en: ["Tribute", "Tribute"] },
};

// Qualificadors (sufixos) per a reconeixements concrets
const HONOR_NOTES = {
  president_honorari: { ca: "President Honorari",            es: "Presidente Honorario",            en: "Honorary President" },
  per_la_tasca:       { ca: "per la tasca",                 es: "por la labor",                    en: "for their work" },
  postum:             { ca: "a títol pòstum",               es: "a título póstumo",                en: "posthumous" },
  aniv_50_traspas:    { ca: "50è aniversari del traspàs",   es: "50º aniversario del fallecimiento", en: "50th anniversary of passing" },
  aniv_150_naixement: { ca: "150è aniversari del naixement", es: "150º aniversario del nacimiento",  en: "150th anniversary of birth" },
  vocal_vitalici:     { ca: "Vocal Vitalici",               es: "Vocal Vitalicio",                 en: "Life Board Member" },
};

const HONOR_PEOPLE = [
  { n: "Lluís Albert Rivas",          g: "m", recs: [{ t: "merit", y: 2002 }, { t: "homenatge", y: 2019 }] },
  { n: "Joan Amades Gelats",          g: "m", recs: [{ t: "merit", y: 1936 }] },
  { n: "Anna Arbolí Sanahuja",        g: "f", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Pilar Arbolí Sanahuja",       g: "f", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Lluís Bartomeu Bonet",        g: "m", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Joan Bel Vilalta",            g: "m", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Antoni Bigas Canals",         g: "m", recs: [{ t: "merit", y: 1986 }] },
  { n: "Anna Maria Bigas Puig",       g: "f", recs: [{ t: "merit", y: 2026 }] },
  { n: "Felip Blasco Anglès",         g: "m", recs: [{ t: "homenatge", y: 1934 }, { t: "dir_honorific", y: 1954 }, { t: "homenatge", y: 1967, q: "president_honorari" }, { t: "honorari", y: 1980 }] },
  { n: "Josep Bòria Amer",            g: "m", recs: [{ t: "dansaire", y: 1936 }, { t: "dansaire", y: 1966 }, { t: "honorari", y: 1980 }] },
  { n: "Eusebi Bosch Humet",          g: "m", recs: [{ t: "honor", y: 1911 }] },
  { n: "Joan Brunet Gómez",           g: "m", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Cèsar Canals Rogés",          g: "m", recs: [{ t: "merit", y: 1911 }] },
  { n: "Aureli Capmany Farrés",       g: "m", recs: [{ t: "homenatge", y: 1917, q: "per_la_tasca" }, { t: "dir_honorari", y: 1926 }, { t: "dir_perpetu", y: 1948 }, { t: "homenatge", y: 1948, q: "per_la_tasca" }, { t: "homenatge", y: 1954, q: "postum" }, { t: "homenatge", y: 2004, q: "aniv_50_traspas" }, { t: "homenatge", y: 2018, q: "aniv_150_naixement" }] },
  { n: "Antoni Casalí Ferran",        g: "m", recs: [{ t: "homenatge", y: 1935 }, { t: "dansaire", y: 1936 }] },
  { n: "Agustí Cohí-Grau",            g: "m", recs: [{ t: "merit", y: 2002 }, { t: "homenatge", y: 2019 }] },
  { n: "Joana Duch Saucedo",          g: "f", recs: [{ t: "merit", y: 2026 }] },
  { n: "Montserrat Farrarons Bori",   g: "f", recs: [{ t: "merit", y: 1993 }] },
  { n: "Ramon Feliu Codina",          g: "m", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Rosa Flotats Bertran",        g: "f", recs: [{ t: "merit", y: 1988 }] },
  { n: "Montserrat Garrich Ribera",   g: "f", recs: [{ t: "merit", y: 2026 }] },
  { n: "Rafael Ginés Llemosí",        g: "m", recs: [{ t: "honorari", y: 1980 }] },
  { n: "Carme Guàrdia Torruella",     g: "f", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Ignasi Iglesias Pujadas",     g: "m", recs: [{ t: "honor", y: 1911 }] },
  { n: "Carme Lasaosa Puértolas",     g: "f", recs: [{ t: "merit", y: 1988 }] },
  { n: "Ricard Llansà Claramunt",     g: "m", recs: [{ t: "fidel", y: 1933 }, { t: "merit", y: 1936 }] },
  { n: "Lluís Llobet Sánchez",        g: "m", recs: [{ t: "homenatge", y: 1970 }, { t: "honorari", y: 1980 }] },
  { n: "Joan Magrinyà",               g: "m", recs: [{ t: "honor", y: 1971 }] },
  { n: "Consol Mallofré",             g: "f", recs: [{ t: "merit", y: 1990 }] },
  { n: "Apel·les Mestres Oñós",       g: "m", recs: [{ t: "merit", y: 1910 }] },
  { n: "Enric Morera Viura",          g: "m", recs: [{ t: "honor", y: 1911 }] },
  { n: "Francesc Passapera",          g: "m", recs: [{ t: "merit", y: 1964, q: "postum" }] },
  { n: "Maurici Palouzié Carrera",    g: "m", recs: [{ t: "merit", y: 1993 }] },
  { n: "Josep Palouzié Carrera",      g: "m", recs: [{ t: "homenatge", y: 1991, q: "per_la_tasca" }, { t: "merit", y: 1993 }] },
  { n: "Elena Pou Freixa",            g: "f", recs: [{ t: "merit", y: 1986 }] },
  { n: "Maria Pruns Casadesús",       g: "f", recs: [{ t: "merit", y: 2001 }] },
  { n: "Miquel Roca Junyent",         g: "m", recs: [{ t: "honor", y: 1995 }] },
  { n: "Joaquima Sarrat Garcia",      g: "f", recs: [{ t: "merit", y: 1995 }] },
  { n: "Fèlix Sarrat Royo",           g: "m", recs: [{ t: "merit", y: 1986 }] },
  { n: "Jordi Serra Bafalluí",        g: "m", recs: [{ t: "merit", y: 1993 }] },
  { n: "Marisol Sesé Saltó",          g: "f", recs: [{ t: "vitalici", y: 1990 }, { t: "merit", y: 1993 }] },
  { n: "Ramon Sesé Salvat",           g: "m", recs: [{ t: "dansaire", y: 1936 }, { t: "homenatge", y: 1969 }, { t: "honorari", y: 1980 }] },
  { n: "Carme Simon Pujol",           g: "f", recs: [{ t: "merit", y: 1993 }] },
  { n: "Jaume Simon Pujol",           g: "m", recs: [{ t: "merit", y: 1993 }] },
  { n: "Joan B. Soler Bru",           g: "m", recs: [{ t: "merit", y: 1936 }] },
  { n: "Manuel Terron Cusí",          g: "m", recs: [{ t: "honorari", y: 2013 }] },
  { n: "Francesc Terron Merodio",     g: "m", recs: [{ t: "merit", y: 1995 }] },
  { n: "Maria Vallverdú Busquets",    g: "f", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Miquel Vallverdú Busquets",   g: "m", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Montserrat Vallverdú Busquets", g: "f", recs: [{ t: "dansaire", y: 1936 }] },
  { n: "Josep Ventura Llates",        g: "m", recs: [{ t: "dansaire", y: 1936 }, { t: "homenatge", y: 1968, q: "vocal_vitalici" }] },
];

// ── Derivats (memoïtzables): inicials, etiqueta de títol, agrupació per any ──
function honorInitials(name) {
  const parts = name.replace(/[·.]/g, " ").split(/\s+/).filter(Boolean);
  const first = parts[0] ? parts[0][0] : "";
  const second = parts[1] ? parts[1][0] : "";
  return (first + second).toUpperCase();
}
function honorTitleLabel(rec, g, lang) {
  const def = HONOR_TITLES[rec.t];
  if (!def) return rec.t;
  const base = (def[lang] || def.ca)[g === "f" ? 1 : 0];
  if (rec.q && HONOR_NOTES[rec.q]) {
    const note = HONOR_NOTES[rec.q][lang] || HONOR_NOTES[rec.q].ca;
    return base + " · " + note;
  }
  return base;
}
function honorCategory(rec) {
  return (HONOR_TITLES[rec.t] || {}).cat || "merit";
}
// Construeix les estacions-any: [{ year, people:[{name,g,initials,titles:[{label,cat}]}] }]
function buildHonorStations(lang) {
  const byYear = {};
  HONOR_PEOPLE.forEach((p) => {
    const init = honorInitials(p.n);
    p.recs.forEach((rec) => {
      if (!byYear[rec.y]) byYear[rec.y] = {};
      if (!byYear[rec.y][p.n]) byYear[rec.y][p.n] = { name: p.n, g: p.g, initials: init, titles: [] };
      byYear[rec.y][p.n].titles.push({ label: honorTitleLabel(rec, p.g, lang), cat: honorCategory(rec) });
    });
  });
  return Object.keys(byYear)
    .map(Number)
    .sort((a, b) => a - b)
    .map((year) => ({
      year,
      people: Object.values(byYear[year]).sort((a, b) => a.name.localeCompare(b.name, "ca")),
    }));
}
// Recorregut complet d'una persona pel modal: [{year, label, cat}] ordenat per any
function honorPersonRecord(name, lang) {
  const p = HONOR_PEOPLE.find((x) => x.n === name);
  if (!p) return [];
  return p.recs
    .map((rec) => ({ year: rec.y, label: honorTitleLabel(rec, p.g, lang), cat: honorCategory(rec) }))
    .sort((a, b) => a.year - b.year);
}
const HONOR_STATS = (() => {
  const years = HONOR_PEOPLE.flatMap((p) => p.recs.map((r) => r.y));
  return {
    people: HONOR_PEOPLE.length,
    recs: HONOR_PEOPLE.reduce((n, p) => n + p.recs.length, 0),
    first: Math.min(...years),
    last: Math.max(...years),
  };
})();

/* ─── Strings (CA / ES / EN) ─────────────────────────────────────────────── */
const SOBRE_STRINGS = {
  ca: {
    pageTitle: "Sobre l'Esbart",

    // Hero
    heroEyebrow: "Sobre l'entitat · Fundació 1908",
    heroTitle: ["Una entitat ", "centenària", " dedicada a la ", "dansa", " tradicional catalana."],
    heroLead: "Investiguem, preservem i compartim el patrimoni immaterial d'un poble. Som una de les entitats culturals més antigues encara en actiu de Catalunya, i una de les principals referències en dansa tradicional, amb seu a la Casa dels Entremesos al cor de Ciutat Vella.",
    heroMeta: [
      { num: ["1908"], label: "Any de fundació" },
      { num: ["120", "+"], label: "Socis i sòcies actives" },
      { num: ["80", "+"], label: "Danses al repertori" },
    ],
    heroScroll: "Descobreix",

    // Manifest
    manifestQuote: ["Investiguem amb ", { strong: "rigor" }, ", preservem amb ", { strong: "cura" }, " i compartim amb ", { strong: "alegria" }, "."],
    manifestAttr: "Manifest · Esbart Català de Dansaires",

    // History
    histEyebrow: "Història",
    histTitle: ["Més d'un segle ", "ballant la tradició."],
    histSub: "L'any 1908, al carrer Més Baix de Sant Pere de Barcelona, una colla d'amics signava els Estatuts de l'Esbart Català de Dansaires. D'això fa més de cent anys. Selecciona un període per llegir-ne la història.",
    histPdfLabel: "Descarregar PDF complet",
    histPrev: "Període anterior",
    histNext: "Període següent",
    histProgress: "de",
    eras: [
      {
        range: "1908—1914", start: "1908", end: "1914",
        kicker: "Els inicis",
        title: "Modernisme, fundació i primera identitat",
        lead: "Al carrer Més Baix de Sant Pere de Barcelona, una colla d'amics interessats per la dansa redacta i signa els Estatuts d'una nova entitat: l'Esbart Català de Dansaires.",
        body: [
          "Eren temps d'efervescència cultural. A tota Europa, arquitectes agosarats aixecaven edificis de formes sinuoses, i pintors i escultors copsaven realitats quotidianes amb els gestos d'una nova sensibilitat. L'època d'esplendor de les arts decoratives posava petites meravelles a l'abast de la burgesia.",
          "Era l'època del modernisme. Els artistes cercaven tot allò que fos nou, innovador, que permetés trencar amb el record d'èpoques passades. La creació era una fi.",
          "Els fundadors comparteixen la voluntat de recollir, estudiar i divulgar les danses tradicionals catalanes — la cultura del poble com a matèria primera d'una identitat col·lectiva en construcció.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201908%20-%201914.pdf",
      },
      {
        range: "1915—1929", start: "1915", end: "1929",
        kicker: "La gran embranzida",
        title: "Capmany, Canals i la consolidació d'un calendari",
        lead: "L'arribada d'Aureli Capmany com a Director Artístic i Cèsar Canals com a Director Musical consolida la trajectòria de l'entitat.",
        body: [
          "L'any 1915 porta canvis a la Junta Directiva. Joan B. Soler Bru substitueix Antoni Casalí, però acaba dimitint al·legant manca de cohesió al Consell. Malgrat els vaivens, l'activitat es manté.",
          "El dia 30 de gener de 1915 se celebra una vetllada a la seu de l'Ateneu Obrer del Districte (carrer del Bisbe Caçador). L'endemà, una audició de sardanes. La Festa del Soci es consolida com a cita anual i estructura el calendari intern.",
          "L'Esbart pren posicions com a referent de la dansa catalana a la ciutat i comença a teixir la xarxa d'aliances amb altres entitats culturals que el definirà durant dècades.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201915%20-%201929.pdf",
      },
      {
        range: "1930—1938", start: "1930", end: "1938",
        kicker: "Esplendor i creativitat",
        title: "25è aniversari, recuperacions clau i Guerra Civil",
        lead: "Una dècada d'activitat intensa marcada per fets importants: l'Esbart celebra el 25è aniversari, i l'esclat de la Guerra Civil capgira la trajectòria.",
        body: [
          "Sota la direcció d'Antoni Casalí, l'entitat ja és coneguda arreu de Catalunya. La participació en festes majors, actes culturals i solidaris és més que habitual.",
          "D'aquesta època daten recuperacions cabdals: la Quadrilla de Granollers i el Ballet de Sant Vicenç de Montalt (1930); el Ball de Nans d'Olot, el Ball de Cavallets d'Olot i el Ball de Nans de Berga (1932); el Ball Pla de Sant Vicenç (1933); i el Ball de Gitanes d'Argentona (1935).",
          "L'esclat de la Guerra Civil obliga a continuar la tasca en la clandestinitat per mantenir viva la feina iniciada a començaments de segle.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201930%20-%201938.pdf",
      },
      {
        range: "1939—1948", start: "1939", end: "1948",
        kicker: "De la postguerra a la recuperació",
        title: "Resistència silenciosa i nova Junta",
        lead: "Pocs dies abans de la Batalla de l'Ebre s'escriuen les darreres paraules al Llibre d'Actes 1923-1938, que quedarà sense acabar.",
        body: [
          "Un cop la desfeta republicana és una realitat, la Junta decideix mantenir momentàniament inactiu l'Esbart. Josep Ventura assumeix la presidència després dels vint anys que Antoni Casalí l'havia ocupada en tres etapes.",
          "La nova Junta — Carles Gàllego (vicepresident), Manuel Vidal (secretari), Pere Villes (sotssecretari), Francesc X. Vilaresau (vocal de propaganda) i Ramon Sesé (vocal administrador) — encara l'etapa fosca amb Felip Blasco com a mestre de dansa i Ricard Llansà com a director musical.",
          "L'activitat es recupera lentament, sempre buscant esquerdes per mantenir viva la dansa tradicional en un context hostil.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201939%20-%201948.pdf",
      },
      {
        range: "1949—1958", start: "1949", end: "1958",
        kicker: "La represa de l'activitat pública",
        title: "Aplecs, ballades i el retorn a l'esfera pública",
        lead: "L'Esbart aixeca el cap. Qualsevol motiu és bo per organitzar una activitat, una ballada de col·laboració o un acte social.",
        body: [
          "El 1949 acull la sessió dedicada a José de Udaeta i Susanne Anderson (febrer), un sopar de germanor (maig) i la participació en l'acte de final de curs de l'Ateneu Obrer (juliol).",
          "Al febrer es comença a parlar d'una diada que es celebrarà al juliol: el segon Aplec de l'Esbart Català de Dansaires a la Vila Llobet de Valldoreix, propietat del soci Lluís Llobet, que torna a posar mitjans perquè tothom es trobi a gust a casa seva.",
          "Els jocs i activitats — trencar l'olla, curses de sacs, recerca de tresors als plats amb cendra, concurs de ganyotes, salts de corda — refermen el vincle social que ha estat sempre nucli de l'entitat.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201949%20-%201958.pdf",
      },
      {
        range: "1959—1975", start: "1959", end: "1975",
        kicker: "Després del cinquantenari",
        title: "Relleus, dols i el Ballet de Muntanya al Camp Nou",
        lead: "L'any que segueix el cinquantè aniversari arriba amb la dimissió de Jaume Simon com a mestre de dansa per motius de salut. Francesc Passapera accepta el càrrec.",
        body: [
          "Es rep la notícia del traspàs de Joan Amades, soci i expresident de l'entitat entre 1924 i 1926. La Junta Directiva l'acomiada amb tots els honors.",
          "Pel cinquantenari del Palau de la Música Catalana, dues-centes parelles ballen el Ballet de Muntanya a l'estadi del Futbol Club Barcelona, sota la coordinació del Català. És un dels actes més multitudinaris de la història de l'entitat.",
          "Els anys següents són de consolidació coreogràfica i d'obertura a noves generacions de balladors i mestres.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201959%20-%201975.pdf",
      },
      {
        range: "1976—1992", start: "1976", end: "1992",
        kicker: "L'etapa postfranquista i els nous ajuntaments",
        title: "Transició, recels i seccions infantils",
        lead: "La nova etapa política no canvia immediatament la vida de l'entitat. L'Esbart inicia 1976 sense saber exactament què passarà.",
        body: [
          "L'encara activa Sección Femenina proposa un homenatge a l'Esbart com a esbart dansaire més antic. Sarrat, com a President, trasllada la proposta a la Junta: tots els components en recelen i la deixen sense resposta.",
          "L'activitat es centra molt en les seccions Infantil i Juvenil. El 13 de març s'organitza una primera trobada d'esbarts; el 31 de juliol, una festa infantil a la Penya Cultural Barcelonesa. Entre una i altra, els petits assisteixen al XX Aplec d'Esbarts de Montserrat.",
          "L'arribada dels nous ajuntaments democràtics obre, a poc a poc, una etapa de col·laboració institucional inèdita.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201976%20-%201992.pdf",
      },
      {
        range: "1993—2009", start: "1993", end: "2009",
        kicker: "Encarant el nou segle",
        title: "Casa dels Entremesos, Mercè i centenari",
        lead: "L'any postolímpic és un any de gran activitat. Una nova relació amb l'administració municipal i canvis interns marcaran l'etapa.",
        body: [
          "El Districte de Ciutat Vella i, més tard, l'Institut Municipal Barcelona Espectacles — que esdevindrà el Departament de Festes — formalitzen una col·laboració que neix del premi Fes-ta teva la Mercè concedit a un projecte de l'Esbart.",
          "Es produeixen canvis substancials en la responsabilitat musical i coreogràfica de l'entitat, obrint una nova etapa de la ja llarga història de l'Esbart Català de Dansaires.",
          "Es consolida la seu a la Casa dels Entremesos, a la Plaça de les Beates, en un equipament compartit amb altres entitats de cultura popular. L'etapa culminarà amb el centenari de 2008.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201993%20-%202009.pdf",
      },
    ],

    // Mission
    missionEyebrow: "Què fem",
    missionTitle: ["Tres compromisos, ", "una missió."],
    missionCols: [
      {
        num: "01",
        title: ["Investiguem.", ""],
        p: "Estudiem, documentem i transcrivim el patrimoni de la dansa tradicional catalana amb rigor històric i etnocientífic.",
        list: ["Treball de camp", "Centre de Documentació", "Premi Rafel Tudó", "Publicacions"],
      },
      {
        num: "02",
        title: ["Preservem.", ""],
        p: "Custodiem un arxiu únic — el fons Aureli Capmany, la biblioteca, el fons fotogràfic i la fonoteca — i el posem a disposició de la recerca.",
        list: ["Arxiu i Biblioteca", "Fons fotogràfic", "Fonoteca", "Indumentària"],
      },
      {
        num: "03",
        title: ["Compartim.", ""],
        p: "Donem a conèixer la tradició mitjançant espectacles, formació, ballades obertes i activitats educatives a aules i barris.",
        list: ["Cos de Dansa", "Ballades obertes", "Ballem a l'aula", "Tallers"],
      },
    ],

    // Team
    teamEyebrow: "Junta directiva",
    teamTitle: ["Les persones que ", "fan l'Esbart."],
    teamSub: "Una junta voluntària, escollida en assemblea cada quatre anys, que vetlla per la bona marxa de l'entitat.",
    teamPrev: "Membre anterior",
    teamNext: "Membre següent",
    teamMembers: [
      { name: "Daniel Trullols i Ruau",  role: "President",       initials: "DT" },
      { name: "Anna Bigas i Puig",       role: "Sots-Presidenta", initials: "AB" },
      { name: "Anna Jordana i Moreso",   role: "Secretària",      initials: "AJ" },
      { name: "Manel Rubio i Arbós",     role: "Tresorer",        initials: "MR" },
      { name: "Albert Montcada i Ribera",role: "Vocal",           initials: "AM" },
      { name: "Jordi Lleras i Gòrriz",   role: "Vocal",           initials: "JL" },
      { name: "Joana Pedreira Font",     role: "Vocal",           initials: "JP" },
      { name: "Alba Manteca i Esteve",   role: "Vocal",           initials: "AL" },
      { name: "Enric Poch i Giró",       role: "Vocal",           initials: "EP" },
    ],

    // Masters explorer
    mastersEyebrow: "Directori · 1908 — actualitat",
    mastersTitle: ["Qui ha fet ", "l'Esbart."],
    mastersSub: "Presidents, mestres, directors musicals, pianistes i totes les persones que han dedicat el seu temps a mantenir viva la dansa tradicional catalana des de 1908.",
    mastersPrev: "Secció anterior",
    mastersNext: "Secció següent",
    mastersSections: MASTERS_SECTIONS_ITEMS.map((s, i) => ({
      ...s,
      title: ["Presidents","Mestres del Cos de Dansa","Mestres Juvenils i Infantils","Directors Musicals","Pianistes","Auxiliars del Cos de Dansa","Majordomia i Vestuari","Ball dels Divendres"][i]
    })),

    // Bodies
    bodiesEyebrow: "Cos de Dansa i seccions",
    bodiesTitle: ["L'entitat es forma ", "des de tres seccions."],
    bodies: [
      { num: "01", name: ["Cos de ", "Dansa"], desc: "Formació adulta sense límit d'edat. Practiquen danses catalanes, balls de bastons i balls històrics barcelonins dels segles XVIII–XIX, i son els encarregats dels Cavallets Cotoners de Barcelona. Ofereixen mostres itinerants —cercaviles, seguicis, processons— i espectacles de 30 a 90 minuts. Assaig: dimarts i divendres 20:30–22:30 h.", count: "32", lbl: "Membres" },
      { num: "02", name: ["Grup ", "Juvenil"], desc: "Obert a tothom que vulgui dansar i treballar en equip. S'aprenen danses catalanes tot treballant el control del cos i la coordinació amb elements —cavallets, bastons, cintes, mocadors. Unas deu ballades a l'any. Assaig: divendres 18:30–20:00 h.", count: "18", lbl: "Membres" },
      { num: "03", name: ["Secció ", "Infantil"], desc: "A partir dels quatre anys, tres grups per franja d'edat. Els més petits combinen cançó, rítmica i jocs amb moviment; els grans treballen coreografies més complexes. Tots aprenen balls de bastons i participen a les festes de la Mercè, Santa Eulàlia i Carnaval. Assaig: divendres 18:30–20:00 h.", count: "44", lbl: "Membres" },
    ],
    bodiesCta: "Vine a ballar",

    // Seat
    seatEyebrow: "La nostra seu",
    seatTitle: ["La Casa dels ", "Entremesos."],
    seatP1: "Compartim seu amb altres entitats de cultura popular i tradicional al cor de Ciutat Vella, en un edifici emblemàtic dedicat al món dels entremesos i les festes catalanes.",
    seatP2: "Hi tenim sala d'assaig, l'arxiu i la biblioteca especialitzada, i és el nostre punt de trobada setmanal.",
    seatLabel1: "Adreça", seatVal1: "Plaça de les Beates, 2 · 08003 Barcelona",
    seatLabel2: "Metro", seatVal2: "L4 Jaume I · L1/L4 Urquinaona",
    seatLabel3: "Horaris", seatVal3: "Dimarts a divendres · 18:00 — 22:30h",
    seatLabel4: "Contacte", seatVal4: "93 412 51 11 · info@esbartcatala.org",
    seatYear: "2009",
    seatYearCap: "Any d'establiment a la Casa dels Entremesos",
    seatSeusBtn: "Antigues seus",
    seatCta: "Com arribar",

    // Honors — Socis de mèrit, d'honor i homenatjats (fris daurat)
    honorsEyebrow: "Honor i memòria · 1910 — actualitat",
    honorsTitle: ["Socis de mèrit, d’honor ", "i homenatjats."],
    honorsSub: "Més d’un segle distingint les persones que han fet gran l’Esbart. Recorre la línia del temps i obre qualsevol nom per veure’n el recorregut complet.",
    honorsHint: "Desplaça’t per recórrer els anys",
    honorsClickHint: "Fes clic en un nom per veure’l",
    honorsPeopleLbl: "persones distingides",
    honorsRecsLbl: "reconeixements",
    honorsSpanLbl: "més d’un segle",
    honorsHonoredLbl: "distingits aquest any",
    honorsNavHint: "Llisca o clica per recórrer els anys",
    honorsPrev: "Any anterior",
    honorsNext: "Any següent",
    honorsModalEyebrow: "Recorregut de reconeixements",
    honorsModalRecsLbl: "reconeixements",
    honorsClose: "Tancar",
    honorsSkip: "Saltar la secció",

    // Recognitions
    recogEyebrow: "Reconeixements i aliances",
    recogTitle: ["Una trajectòria ", "reconeguda."],
    recogAwards: [
      { yr:"1980", title:"Almorratxa d'Or", inst:"Obra del Ballet Popular", desc:"Atorgada per primera vegada per l'Obra del Ballet Popular." },
      { yr:"1983", title:"Reconeixement Dept. de Cultura", inst:"Generalitat de Catalunya", desc:"En reconeixement de la intensa tasca de fidelitat a les danses tradicionals, en ocasió del 75è Aniversari (1908–1983)." },
      { yr:"1992", title:"Fes-te teva la Mercè", inst:"Ajuntament de Barcelona", desc:"Al projecte MercèDansa: millor iniciativa de dansa popular catalana per a les Festes de la Mercè." },
      { yr:"1993", title:"Premi Ateneu a la Creativitat Artística", inst:"Federació d'Ateneus de Catalunya", desc:"A la iniciativa de La Cafetera." },
      { yr:"1998", title:"Reconeixement Institut de Cultura", inst:"Institut de Cultura de Barcelona", desc:"" },
      { yr:"1999", title:"Entitat d'Interès Cultural", inst:"Generalitat de Catalunya", desc:"Declaració oficial de l'Esbart Català de Dansaires com a Entitat d'Interès Cultural." },
      { yr:"2001", title:"Medalla al Mèrit en Dansa Catalana", inst:"Obra del Ballet Popular", desc:"Atorgada per primera vegada." },
      { yr:"2008", title:"Medalla d'Honor de la Ciutat", inst:"Ajuntament de Barcelona", desc:"" },
      { yr:"2008", title:"Trofeu Centenari", inst:"Agrupament d'Esbarts Dansaires", desc:"" },
      { yr:"2008", title:"Trofeu Continuïtat", inst:"Obra del Ballet Popular", desc:"" },
      { yr:"2008", title:"Trofeu El Grupet", inst:"El Grupet", desc:"" },
      { yr:"2009", title:"Trofeu Rosa de Plata", inst:"BarnaCentre", desc:"" },
      { yr:"2010", title:"Creu de Sant Jordi", inst:"Generalitat de Catalunya", desc:"" },
      { yr:"2012", title:"Premi Ciutat de Barcelona 2012", inst:"Ajuntament de Barcelona", desc:"Apartat Cultura Popular. Projecte Apel·les Mestres, artista complet i home polièdric." },
      { yr:"2013", title:"Guardó Firaire d'Honor", inst:"Associació Fira de Santa Llúcia", desc:"" },
      { yr:"2015", title:"Premi Best · Millor Projecte Estratègic", inst:"Agrupació del Bestiari Festiu a Catalunya", desc:"Pel projecte L'Any dels Cavallets Cotoners." },
      { yr:"2015", title:"Diploma d'Associació d'Interès Cultural", inst:"Generalitat de Catalunya", desc:"" },
      { yr:"2018", title:"Premi Capital de la Sardana a la Difusió Musical", inst:"Obra del Ballet Popular", desc:"Per la publicació dels discs amb músiques de balls populars catalans." },
      { yr:"2020", title:"Premi Josep Anselm Clavé 2020", inst:"Federació de Cors de Clavé", desc:"Millor producció-espectacle no coral de cultura popular. Concedit l'any 2021." },
    ],
    recogCountLabel: "distincions · 1980–2020",
    recogPartnersLbl: "Amb el suport de",
    recogPartners: ["Generalitat de Catalunya", "Diputació de Barcelona", "Ajuntament de Barcelona", "ICUB", "Fundació la Caixa", "ESMUC"],

    // Transparency
    transpEyebrow: "Transparència",
    transpTitle: ["Documents ", "públics."],
    transpSub: "Memòries, comptes anuals, estatuts i polítiques internes a disposició dels socis i la ciutadania.",
    transpCta: "Obre el Portal de Transparència",
    transpDocs: [
      { ext: "PDF", yr: "2025", title: ["Memòria ", "anual"], desc: "Resum d'activitats, espectacles, programació i recerca de l'any en curs." },
      { ext: "PDF", yr: "2025", title: ["Comptes ", "anuals"], desc: "Balanç econòmic auditat de l'exercici, ingressos i despeses detallats." },
      { ext: "PDF", yr: "2024", title: ["Estatuts de ", "l'entitat"], desc: "Marc jurídic i organitzatiu de l'Esbart, aprovat en assemblea general." },
      { ext: "PDF", yr: "2024", title: ["Codi ètic i ", "de conducta"], desc: "Principis i normes que regeixen la convivència i el funcionament intern." },
      { ext: "PDF", yr: "2024", title: ["Protecció ", "de menors"], desc: "Política i protocols de prevenció en activitats amb infants i joves." },
      { ext: "PDF", yr: "2024", title: ["Composició de ", "la junta"], desc: "Acta de l'última assemblea de renovació de càrrecs i organigrama vigent." },
    ],
    transpRead: "Descarregar",

    // Closing
    closingQuote: "Sense memòria no hi ha tradició; sense tradició no hi ha futur.",
    closingAttr: "Aureli Capmany · Folklorista",
    closingCta1: "Vine a ballar",
    closingCta2: "Centre de Documentació",
  },

  es: {
    pageTitle: "Sobre el Esbart",
    heroEyebrow: "Sobre la entidad · Fundación 1908",
    heroTitle: ["Una entidad ", "centenaria", " dedicada a la ", "danza", " tradicional catalana."],
    heroLead: "Investigamos, preservamos y compartimos el patrimonio inmaterial de un pueblo. Somos una de las entidades culturales más antiguas en activo de Catalunya, y una de las principales referencias en danza tradicional, con sede en la Casa dels Entremesos en el corazón de Ciutat Vella.",
    heroMeta: [
      { num: ["1908"], label: "Año de fundación" },
      { num: ["120", "+"], label: "Socios y socias activas" },
      { num: ["80", "+"], label: "Danzas en repertorio" },
    ],
    heroScroll: "Descubre",
    manifestQuote: ["Investigamos con ", { strong: "rigor" }, ", preservamos con ", { strong: "cuidado" }, " y compartimos con ", { strong: "alegría" }, "."],
    manifestAttr: "Manifiesto · Esbart Català de Dansaires",
    histEyebrow: "Historia",
    histTitle: ["Más de un siglo ", "bailando la tradición."],
    histSub: "En 1908, en la calle Més Baix de Sant Pere de Barcelona, un grupo de amigos firmaba los Estatutos del Esbart Català de Dansaires. De eso hace más de cien años. Selecciona un período para leer su historia.",
    histPdfLabel: "Descargar PDF completo",
    histPrev: "Período anterior",
    histNext: "Período siguiente",
    histProgress: "de",
    eras: [
      {
        range: "1908—1914", start: "1908", end: "1914",
        kicker: "Los inicios",
        title: "Modernismo, fundación y primera identidad",
        lead: "En la calle Més Baix de Sant Pere de Barcelona, un grupo de amigos interesados por la danza redacta y firma los Estatutos de una nueva entidad: el Esbart Català de Dansaires.",
        body: [
          "Eran tiempos de efervescencia cultural. En toda Europa, arquitectos audaces levantaban edificios de formas sinuosas, y pintores y escultores captaban realidades cotidianas con los gestos de una nueva sensibilidad. La época de esplendor de las artes decorativas ponía pequeñas maravillas al alcance de la burguesía.",
          "Era la época del modernismo. Los artistas buscaban todo aquello que fuese nuevo, innovador, que permitiese romper con el recuerdo de épocas pasadas. La creación era un fin en sí misma.",
          "Los fundadores comparten la voluntad de recoger, estudiar y divulgar las danzas tradicionales catalanas — la cultura del pueblo como materia prima de una identidad colectiva en construcción.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201908%20-%201914.pdf",
      },
      {
        range: "1915—1929", start: "1915", end: "1929",
        kicker: "El gran impulso",
        title: "Capmany, Canals y la consolidación de un calendario",
        lead: "La llegada de Aureli Capmany como Director Artístico y Cèsar Canals como Director Musical consolida la trayectoria de la entidad.",
        body: [
          "En 1915 se producen cambios en la Junta Directiva. Joan B. Soler Bru sustituye a Antoni Casalí, pero acaba dimitiendo alegando falta de cohesión en el Consejo. A pesar de los vaivenes, la actividad se mantiene.",
          "El 30 de enero de 1915 se celebra una velada en la sede del Ateneo Obrero del Distrito (calle del Bisbe Caçador). Al día siguiente, una audición de sardanas. La Festa del Soci se consolida como cita anual y vertebra el calendario interno.",
          "El Esbart se posiciona como referente de la danza catalana en la ciudad y empieza a tejer la red de alianzas con otras entidades culturales que lo definirá durante décadas.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201915%20-%201929.pdf",
      },
      {
        range: "1930—1938", start: "1930", end: "1938",
        kicker: "Esplendor y creatividad",
        title: "25º aniversario, recuperaciones clave y Guerra Civil",
        lead: "Una década de actividad intensa marcada por hechos importantes: el Esbart celebra su 25º aniversario, y el estallido de la Guerra Civil trastoca la trayectoria.",
        body: [
          "Bajo la dirección de Antoni Casalí, la entidad ya es conocida en toda Cataluña. La participación en fiestas mayores, actos culturales y solidarios es más que habitual.",
          "De esta época datan recuperaciones cruciales: la Quadrilla de Granollers y el Ballet de Sant Vicenç de Montalt (1930); el Ball de Nans de Olot, el Ball de Cavallets de Olot y el Ball de Nans de Berga (1932); el Ball Pla de Sant Vicenç (1933); y el Ball de Gitanes de Argentona (1935).",
          "El estallido de la Guerra Civil obliga a continuar la tarea en la clandestinidad para mantener viva la labor iniciada a principios de siglo.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201930%20-%201938.pdf",
      },
      {
        range: "1939—1948", start: "1939", end: "1948",
        kicker: "De la posguerra a la recuperación",
        title: "Resistencia silenciosa y nueva Junta",
        lead: "Pocos días antes de la Batalla del Ebro se escriben las últimas palabras en el Llibre d'Actes 1923-1938, que quedará sin terminar.",
        body: [
          "Una vez la derrota republicana es una realidad, la Junta decide mantener momentáneamente inactivo el Esbart. Josep Ventura asume la presidencia tras los veinte años en que Antoni Casalí la había ocupado en tres etapas.",
          "La nueva Junta — Carles Gàllego (vicepresidente), Manuel Vidal (secretario), Pere Villes (subsecretario), Francesc X. Vilaresau (vocal de propaganda) y Ramon Sesé (vocal administrador) — afronta la etapa oscura con Felip Blasco como maestro de danza y Ricard Llansà como director musical.",
          "La actividad se recupera lentamente, siempre buscando rendijas para mantener viva la danza tradicional en un contexto hostil.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201939%20-%201948.pdf",
      },
      {
        range: "1949—1958", start: "1949", end: "1958",
        kicker: "La reanudación de la actividad pública",
        title: "Aplecs, ballades y vuelta a la esfera pública",
        lead: "El Esbart levanta cabeza. Cualquier motivo es bueno para organizar una actividad, una ballada de colaboración o un acto social.",
        body: [
          "En 1949 se realiza la sesión dedicada a José de Udaeta y Susanne Anderson (febrero), una cena de hermandad (mayo) y la participación en el acto de fin de curso del Ateneo Obrero (julio).",
          "En febrero se empieza a hablar de una jornada que se celebrará en julio: el segundo Aplec del Esbart Català de Dansaires en la Vila Llobet de Valldoreix, propiedad del socio Lluís Llobet, que vuelve a poner medios para que todos se sientan a gusto en su casa.",
          "Los juegos y actividades — romper la olla, carreras de sacos, búsqueda de tesoros en platos con ceniza, concurso de muecas, saltos de cuerda — afianzan el vínculo social que ha sido siempre núcleo de la entidad.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201949%20-%201958.pdf",
      },
      {
        range: "1959—1975", start: "1959", end: "1975",
        kicker: "Después del cincuentenario",
        title: "Relevos, duelos y el Ballet de Muntanya en el Camp Nou",
        lead: "El año posterior al cincuenta aniversario llega con la dimisión de Jaume Simon como maestro de danza por motivos de salud. Francesc Passapera acepta el cargo.",
        body: [
          "Se recibe la noticia del fallecimiento de Joan Amades, socio y expresidente de la entidad entre 1924 y 1926. La Junta Directiva lo despide con todos los honores.",
          "Por el cincuentenario del Palau de la Música Catalana, doscientas parejas bailan el Ballet de Muntanya en el estadio del Fútbol Club Barcelona, bajo la coordinación del Català. Es uno de los actos más multitudinarios de la historia de la entidad.",
          "Los años siguientes son de consolidación coreográfica y de apertura a nuevas generaciones de bailadores y maestros.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201959%20-%201975.pdf",
      },
      {
        range: "1976—1992", start: "1976", end: "1992",
        kicker: "La etapa postfranquista y los nuevos ayuntamientos",
        title: "Transición, recelos y secciones infantiles",
        lead: "La nueva etapa política no cambia inmediatamente la vida de la entidad. El Esbart inicia 1976 sin saber exactamente qué pasará.",
        body: [
          "La todavía activa Sección Femenina propone un homenaje al Esbart como esbart bailador más antiguo. Sarrat, como Presidente, traslada la propuesta a la Junta: todos los componentes recelan y la dejan sin respuesta.",
          "La actividad se centra mucho en las secciones Infantil y Juvenil. El 13 de marzo se organiza un primer encuentro de esbarts; el 31 de julio, una fiesta infantil en la Penya Cultural Barcelonesa. Entre una y otra, los más pequeños asisten al XX Aplec de Esbarts de Montserrat.",
          "La llegada de los nuevos ayuntamientos democráticos abre, poco a poco, una etapa de colaboración institucional inédita.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201976%20-%201992.pdf",
      },
      {
        range: "1993—2009", start: "1993", end: "2009",
        kicker: "Encarando el nuevo siglo",
        title: "Casa dels Entremesos, Mercè y centenario",
        lead: "El año postolímpico es un año de gran actividad. Una nueva relación con la administración municipal y cambios internos marcarán la etapa.",
        body: [
          "El Distrito de Ciutat Vella y, más tarde, el Institut Municipal Barcelona Espectacles — que se convertirá en el Departament de Festes — formalizan una colaboración que nace del premio Fes-ta teva la Mercè concedido a un proyecto del Esbart.",
          "Se producen cambios sustanciales en la responsabilidad musical y coreográfica de la entidad, abriendo una nueva etapa de la ya larga historia del Esbart Català de Dansaires.",
          "Se consolida la sede en la Casa dels Entremesos, en la Plaça de les Beates, en un equipamiento compartido con otras entidades de cultura popular. La etapa culminará con el centenario de 2008.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201993%20-%202009.pdf",
      },
    ],
    missionEyebrow: "Qué hacemos",
    missionTitle: ["Tres compromisos, ", "una misión."],
    missionCols: [
      { num: "01", title: ["Investigamos.", ""], p: "Estudiamos, documentamos y transcribimos el patrimonio de la danza tradicional catalana con rigor histórico y etnocientífico.", list: ["Trabajo de campo", "Centro de Documentación", "Premio Rafel Tudó", "Publicaciones"] },
      { num: "02", title: ["Preservamos.", ""], p: "Custodiamos un archivo único — el fondo Aureli Capmany, la biblioteca, el fondo fotográfico y la fonoteca — y lo ponemos a disposición de la investigación.", list: ["Archivo y Biblioteca", "Fondo fotográfico", "Fonoteca", "Indumentaria"] },
      { num: "03", title: ["Compartimos.", ""], p: "Damos a conocer la tradición mediante espectáculos, formación, bailes abiertos y actividades educativas en aulas y barrios.", list: ["Cuerpo de Danza", "Bailes abiertos", "Bailamos en el aula", "Talleres"] },
    ],
    teamEyebrow: "Junta directiva",
    teamTitle: ["Las personas que ", "hacen el Esbart."],
    teamSub: "Una junta voluntaria, elegida en asamblea cada cuatro años, que vela por la buena marcha de la entidad.",
    teamPrev: "Miembro anterior",
    teamNext: "Miembro siguiente",
    teamMembers: [
      { name: "Daniel Trullols i Ruau",  role: "Presidente",      initials: "DT" },
      { name: "Anna Bigas i Puig",       role: "Vicepresidenta",  initials: "AB" },
      { name: "Anna Jordana i Moreso",   role: "Secretaria",      initials: "AJ" },
      { name: "Manel Rubio i Arbós",     role: "Tesorero",        initials: "MR" },
      { name: "Albert Montcada i Ribera",role: "Vocal",           initials: "AM" },
      { name: "Jordi Lleras i Gòrriz",   role: "Vocal",           initials: "JL" },
      { name: "Joana Pedreira Font",     role: "Vocal",           initials: "JP" },
      { name: "Alba Manteca i Esteve",   role: "Vocal",           initials: "AL" },
      { name: "Enric Poch i Giró",       role: "Vocal",           initials: "EP" },
    ],
    mastersEyebrow: "Directorio · 1908 — actualidad",
    mastersTitle: ["Quiénes han hecho ", "el Esbart."],
    mastersSub: "Presidentes, maestros, directores musicales, pianistas y todas las personas que han dedicado su tiempo a mantener viva la danza tradicional catalana desde 1908.",
    mastersPrev: "Sección anterior",
    mastersNext: "Sección siguiente",
    mastersSections: MASTERS_SECTIONS_ITEMS.map((s, i) => ({
      ...s,
      title: ["Presidentes","Maestros del Cuerpo de Danza","Maestros de Jóvenes e Infantiles","Directores Musicales","Pianistas","Auxiliares del Cuerpo de Danza","Mayordomía y Vestuario","Baile de los Viernes"][i]
    })),
    bodiesEyebrow: "Cuerpo de Danza y secciones",
    bodiesTitle: ["La entidad se forma ", "desde tres secciones."],
    bodies: [
      { num: "01", name: ["Cuerpo de ", "Danza"], desc: "Formación adulta sin límite de edad. Practican danzas catalanas, bailes de palos y bailes históricos barceloneses de los siglos XVIII–XIX, y son los responsables de los Cavallets Cotoners de Barcelona. Ofrecen muestras itinerantes y espectáculos de 30 a 90 minutos. Ensayo: martes y viernes 20:30–22:30 h.", count: "32", lbl: "Miembros" },
      { num: "02", name: ["Grupo ", "Juvenil"], desc: "Abierto a quienes quieran danzar y trabajar en equipo. Se aprenden danzas catalanas trabajando el control corporal y la coordinación con elementos —caballitos, bastones, cintas, pañuelos. Unas diez ballades al año. Ensayo: viernes 18:30–20:00 h.", count: "18", lbl: "Miembros" },
      { num: "03", name: ["Sección ", "Infantil"], desc: "A partir de los cuatro años, tres grupos por franja de edad. Los más pequeños combinan canción, rítmica y juegos; los mayores trabajan coreografías más complejas. Todos aprenden bailes de palos y participan en las fiestas de la Mercè, Santa Eulàlia y Carnaval. Ensayo: viernes 18:30–20:00 h.", count: "44", lbl: "Miembros" },
    ],
    bodiesCta: "Ven a bailar",
    seatEyebrow: "Nuestra sede",
    seatTitle: ["La Casa dels ", "Entremesos."],
    seatP1: "Compartimos sede con otras entidades de cultura popular y tradicional en el corazón de Ciutat Vella, en un edificio emblemático dedicado al mundo de los entremeses y las fiestas catalanas.",
    seatP2: "Aquí tenemos sala de ensayo, archivo y biblioteca especializada, y es nuestro punto de encuentro semanal.",
    seatLabel1: "Dirección", seatVal1: "Plaça de les Beates, 2 · 08003 Barcelona",
    seatLabel2: "Metro", seatVal2: "L4 Jaume I · L1/L4 Urquinaona",
    seatLabel3: "Horarios", seatVal3: "Martes a viernes · 18:00 — 22:30h",
    seatLabel4: "Contacto", seatVal4: "93 412 51 11 · info@esbartcatala.org",
    seatYear: "2009",
    seatYearCap: "Año de establecimiento en la Casa dels Entremesos",
    seatSeusBtn: "Sedes anteriores",
    seatCta: "Cómo llegar",

    // Honors
    honorsEyebrow: "Honor y memoria · 1910 — actualidad",
    honorsTitle: ["Socios de mérito, de honor ", "y homenajeados."],
    honorsSub: "Más de un siglo distinguiendo a las personas que han hecho grande el Esbart. Recorre la línea del tiempo y abre cualquier nombre para ver su trayectoria completa.",
    honorsHint: "Desplázate para recorrer los años",
    honorsClickHint: "Haz clic en un nombre para verlo",
    honorsPeopleLbl: "personas distinguidas",
    honorsRecsLbl: "reconocimientos",
    honorsSpanLbl: "más de un siglo",
    honorsHonoredLbl: "distinguidos este año",
    honorsNavHint: "Desliza o haz clic para recorrer los años",
    honorsPrev: "Año anterior",
    honorsNext: "Año siguiente",
    honorsModalEyebrow: "Trayectoria de reconocimientos",
    honorsModalRecsLbl: "reconocimientos",
    honorsClose: "Cerrar",
    honorsSkip: "Saltar la sección",
    recogEyebrow: "Reconocimientos y alianzas",
    recogTitle: ["Una trayectoria ", "reconocida."],
    recogAwards: [
      { yr:"1980", title:"Almorratxa d'Or", inst:"Obra del Ballet Popular", desc:"Concedida por primera vez por la Obra del Ballet Popular." },
      { yr:"1983", title:"Reconocimiento Dept. de Cultura", inst:"Generalitat de Catalunya", desc:"En reconocimiento de la intensa labor de fidelidad a las danzas tradicionales, con motivo del 75º Aniversario (1908–1983)." },
      { yr:"1992", title:"Fes-te teva la Mercè", inst:"Ajuntament de Barcelona", desc:"Al proyecto MercèDansa: mejor iniciativa de danza popular catalana para las Fiestas de la Mercè." },
      { yr:"1993", title:"Premio Ateneu a la Creatividad Artística", inst:"Federació d'Ateneus de Catalunya", desc:"A la iniciativa de La Cafetera." },
      { yr:"1998", title:"Reconocimiento Institut de Cultura", inst:"Institut de Cultura de Barcelona", desc:"" },
      { yr:"1999", title:"Entidad de Interés Cultural", inst:"Generalitat de Catalunya", desc:"Declaración oficial del Esbart Català de Dansaires como Entidad de Interés Cultural." },
      { yr:"2001", title:"Medalla al Mérito en Danza Catalana", inst:"Obra del Ballet Popular", desc:"Concedida por primera vez." },
      { yr:"2008", title:"Medalla de Honor de la Ciudad", inst:"Ajuntament de Barcelona", desc:"" },
      { yr:"2008", title:"Trofeo Centenario", inst:"Agrupament d'Esbarts Dansaires", desc:"" },
      { yr:"2008", title:"Trofeo Continuidad", inst:"Obra del Ballet Popular", desc:"" },
      { yr:"2008", title:"Trofeo El Grupet", inst:"El Grupet", desc:"" },
      { yr:"2009", title:"Trofeo Rosa de Plata", inst:"BarnaCentre", desc:"" },
      { yr:"2010", title:"Creu de Sant Jordi", inst:"Generalitat de Catalunya", desc:"" },
      { yr:"2012", title:"Premio Ciudad de Barcelona 2012", inst:"Ajuntament de Barcelona", desc:"Apartado Cultura Popular. Proyecto Apel·les Mestres, artista completo y hombre poliédrico." },
      { yr:"2013", title:"Guardó Firaire d'Honor", inst:"Associació Fira de Santa Llúcia", desc:"" },
      { yr:"2015", title:"Premio Best · Mejor Proyecto Estratégico", inst:"Agrupació del Bestiari Festiu a Catalunya", desc:"Por el proyecto L'Any dels Cavallets Cotoners." },
      { yr:"2015", title:"Diploma de Asociación de Interés Cultural", inst:"Generalitat de Catalunya", desc:"" },
      { yr:"2018", title:"Premio Capital de la Sardana a la Difusión Musical", inst:"Obra del Ballet Popular", desc:"Por la publicación de los discos con músicas de bailes populares catalanes." },
      { yr:"2020", title:"Premio Josep Anselm Clavé 2020", inst:"Federació de Cors de Clavé", desc:"Mejor producción-espectáculo no coral de cultura popular. Concedido en 2021." },
    ],
    recogCountLabel: "distinciones · 1980–2020",
    recogPartnersLbl: "Con el apoyo de",
    recogPartners: ["Generalitat de Catalunya", "Diputació de Barcelona", "Ajuntament de Barcelona", "ICUB", "Fundación la Caixa", "ESMUC"],
    transpEyebrow: "Transparencia",
    transpTitle: ["Documentos ", "públicos."],
    transpSub: "Memorias, cuentas anuales, estatutos y políticas internas a disposición de socios y ciudadanía.",
    transpCta: "Abre el Portal de Transparencia",
    transpDocs: [
      { ext: "PDF", yr: "2025", title: ["Memoria ", "anual"], desc: "Resumen de actividades, espectáculos, programación e investigación del año en curso." },
      { ext: "PDF", yr: "2025", title: ["Cuentas ", "anuales"], desc: "Balance económico auditado del ejercicio, ingresos y gastos detallados." },
      { ext: "PDF", yr: "2024", title: ["Estatutos de ", "la entidad"], desc: "Marco jurídico y organizativo del Esbart, aprobado en asamblea general." },
      { ext: "PDF", yr: "2024", title: ["Código ético y ", "de conducta"], desc: "Principios y normas que rigen la convivencia y el funcionamiento interno." },
      { ext: "PDF", yr: "2024", title: ["Protección ", "de menores"], desc: "Política y protocolos de prevención en actividades con niños y jóvenes." },
      { ext: "PDF", yr: "2024", title: ["Composición de ", "la junta"], desc: "Acta de la última asamblea de renovación de cargos y organigrama vigente." },
    ],
    transpRead: "Descargar",
    closingQuote: "Sin memoria no hay tradición; sin tradición no hay futuro.",
    closingAttr: "Aureli Capmany · Folklorista",
    closingCta1: "Ven a bailar",
    closingCta2: "Centro de Documentación",
  },

  en: {
    pageTitle: "About the Esbart",
    heroEyebrow: "About the organisation · Founded 1908",
    heroTitle: ["A ", "century-old", " organisation devoted to ", "Catalan", " traditional dance."],
    heroLead: "We research, preserve and share the intangible heritage of a people. We are one of Catalonia's oldest active cultural organisations and a leading reference in traditional dance, headquartered at La Casa dels Entremesos in the heart of Ciutat Vella.",
    heroMeta: [
      { num: ["1908"], label: "Founding year" },
      { num: ["120", "+"], label: "Active members" },
      { num: ["80", "+"], label: "Dances in repertoire" },
    ],
    heroScroll: "Discover",
    manifestQuote: ["We research with ", { strong: "rigour" }, ", preserve with ", { strong: "care" }, " and share with ", { strong: "joy" }, "."],
    manifestAttr: "Manifesto · Esbart Català de Dansaires",
    histEyebrow: "History",
    histTitle: ["Over a century ", "of dancing tradition."],
    histSub: "In 1908, on Carrer Més Baix de Sant Pere in Barcelona, a group of friends signed the founding statutes of the Esbart Català de Dansaires. That was over a hundred years ago. Pick a period to read its history.",
    histPdfLabel: "Download full PDF",
    histPrev: "Previous period",
    histNext: "Next period",
    histProgress: "of",
    eras: [
      {
        range: "1908—1914", start: "1908", end: "1914",
        kicker: "The beginnings",
        title: "Modernisme, founding and a first identity",
        lead: "On Carrer Més Baix de Sant Pere in Barcelona, a circle of friends drawn to dance drafts and signs the statutes of a new organisation: the Esbart Català de Dansaires.",
        body: [
          "These were times of cultural ferment. Across Europe, daring architects raised buildings of sinuous forms; painters and sculptors captured everyday realities through a new sensibility. The decorative arts placed small wonders within the reach of the bourgeoisie.",
          "It was the age of Modernisme. Artists searched for everything new and innovative, anything that could break with the memory of past eras. Creation was an end in itself.",
          "The founders share a single will: to gather, study and share Catalan traditional dance — the people's culture as raw material of a collective identity in the making.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201908%20-%201914.pdf",
      },
      {
        range: "1915—1929", start: "1915", end: "1929",
        kicker: "The great push",
        title: "Capmany, Canals and a stable calendar",
        lead: "Aureli Capmany joins as Artistic Director and Cèsar Canals as Music Director, consolidating the organisation's path.",
        body: [
          "1915 brings changes to the Board: Joan B. Soler Bru replaces Antoni Casalí, but resigns by year-end citing a lack of cohesion in the council. Despite the turbulence, activity holds steady.",
          "On 30 January 1915 a soirée is held at the Workers' Athenaeum on Carrer del Bisbe Caçador. The next day, a sardana audition. The Festa del Soci becomes an annual fixture and structures the internal calendar.",
          "The Esbart positions itself as a reference point for Catalan dance in the city, weaving the network of alliances with other cultural organisations that will define it for decades.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201915%20-%201929.pdf",
      },
      {
        range: "1930—1938", start: "1930", end: "1938",
        kicker: "Splendour and creativity",
        title: "25th anniversary, key recoveries and Civil War",
        lead: "A decade of intense activity marked by major events: the Esbart's 25th anniversary, then the outbreak of the Civil War.",
        body: [
          "Under Antoni Casalí's direction, the organisation is known across Catalonia. Its presence at festes majors, cultural and solidarity events is a constant.",
          "Crucial recoveries date from this period: the Quadrilla of Granollers and the Ballet of Sant Vicenç de Montalt (1930); the Ball de Nans and Ball de Cavallets of Olot, and the Ball de Nans of Berga (1932); the Ball Pla of Sant Vicenç (1933); and the Ball de Gitanes of Argentona (1935).",
          "The outbreak of the Civil War forces the work underground in order to keep alive the project begun at the start of the century.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201930%20-%201938.pdf",
      },
      {
        range: "1939—1948", start: "1939", end: "1948",
        kicker: "From post-war to recovery",
        title: "Silent resistance and a new Board",
        lead: "Days before the Battle of the Ebro, the final words are written in the Llibre d'Actes 1923-1938, which will remain unfinished.",
        body: [
          "Once the Republican defeat is a reality, the Board decides to put the Esbart on hold momentarily. Josep Ventura takes the chair after the twenty years that Antoni Casalí had occupied it across three terms.",
          "The new Board — Carles Gàllego (vice-chair), Manuel Vidal (secretary), Pere Villes (deputy secretary), Francesc X. Vilaresau (outreach) and Ramon Sesé (administrator) — faces the dark years with Felip Blasco as dance master and Ricard Llansà as music director.",
          "Activity recovers slowly, always seeking gaps to keep traditional dance alive in a hostile context.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201939%20-%201948.pdf",
      },
      {
        range: "1949—1958", start: "1949", end: "1958",
        kicker: "Return to public life",
        title: "Aplecs, ballades and the public sphere",
        lead: "The Esbart lifts its head. Any reason will do for an event, a collaboration ballada or a social gathering.",
        body: [
          "1949 brings the session devoted to José de Udaeta and Susanne Anderson (February), a fellowship dinner (May) and participation in the Workers' Athenaeum end-of-course event (July).",
          "In February the second Aplec del Esbart Català de Dansaires is announced for July at the Vila Llobet in Valldoreix, owned by member Lluís Llobet, who once again provides the means so everyone feels at home.",
          "Games and activities — pot-breaking, sack races, treasure hunts in plates of ash, grimace contests, skipping rope — reaffirm the social bond that has always been at the core of the organisation.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201949%20-%201958.pdf",
      },
      {
        range: "1959—1975", start: "1959", end: "1975",
        kicker: "After the fiftieth anniversary",
        title: "Handovers, mourning and Ballet de Muntanya at Camp Nou",
        lead: "The year after the fiftieth anniversary opens with Jaume Simon's resignation as dance master for health reasons. Francesc Passapera accepts the role.",
        body: [
          "News arrives of the passing of Joan Amades, member and former chair of the organisation between 1924 and 1926. The Board bids him farewell with full honours.",
          "For the fiftieth anniversary of the Palau de la Música Catalana, two hundred couples dance the Ballet de Muntanya at the FC Barcelona stadium, coordinated by the Català. It is one of the most massive events in the organisation's history.",
          "The years that follow are years of choreographic consolidation and openness to new generations of dancers and teachers.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201959%20-%201975.pdf",
      },
      {
        range: "1976—1992", start: "1976", end: "1992",
        kicker: "Post-Franco era and new town councils",
        title: "Transition, suspicion and youth sections",
        lead: "The new political stage does not immediately change the life of the organisation. The Esbart enters 1976 not knowing exactly what will come.",
        body: [
          "The still-active Sección Femenina proposes a tribute to the Esbart as the oldest active esbart. Sarrat, as chair, brings the proposal to the Board: the members are wary and leave it without reply.",
          "Activity centres heavily on the Children's and Youth sections. A first meeting of esbarts is organised on 13 March; a children's festival on 31 July at the Penya Cultural Barcelonesa. In between, the youngest dancers attend the 20th Aplec d'Esbarts de Montserrat.",
          "The arrival of the new democratic town councils slowly opens an unprecedented stage of institutional collaboration.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201976%20-%201992.pdf",
      },
      {
        range: "1993—2009", start: "1993", end: "2009",
        kicker: "Facing the new century",
        title: "Casa dels Entremesos, Mercè and centenary",
        lead: "The post-Olympic year is one of intense activity. A new relationship with the city council and substantial internal change will mark the period.",
        body: [
          "The Ciutat Vella District and, later, the Institut Municipal Barcelona Espectacles — which will become the Departament de Festes — formalise a partnership born from the Fes-ta teva la Mercè award given to an Esbart project.",
          "Substantial changes take place in the music and choreography leadership of the organisation, opening a new stage in the long history of the Esbart Català de Dansaires.",
          "The headquarters at the Casa dels Entremesos, on Plaça de les Beates, are consolidated within a venue shared with other popular-culture organisations. The period will culminate with the centenary of 2008.",
        ],
        pdf: "https://www.esbartcatala.org/img/315/Hist%C3%B2ria%201993%20-%202009.pdf",
      },
    ],
    missionEyebrow: "What we do",
    missionTitle: ["Three commitments, ", "one mission."],
    missionCols: [
      { num: "01", title: ["We research.", ""], p: "We study, document and transcribe the heritage of Catalan traditional dance with historical and ethnoscientific rigour.", list: ["Field work", "Documentation Centre", "Rafel Tudó Award", "Publications"] },
      { num: "02", title: ["We preserve.", ""], p: "We safeguard a unique archive — the Aureli Capmany fonds, the library, the photographic fonds and the phonoteca — and make it available to research.", list: ["Archive & Library", "Photographic fonds", "Phonoteca", "Costume"] },
      { num: "03", title: ["We share.", ""], p: "We share the tradition through performances, training, open dances and educational activities in classrooms and neighbourhoods.", list: ["Dance Company", "Open dances", "Dance in schools", "Workshops"] },
    ],
    teamEyebrow: "Board of directors",
    teamTitle: ["The people who ", "make the Esbart."],
    teamSub: "A volunteer board, elected in assembly every four years, ensuring the smooth running of the organisation.",
    teamPrev: "Previous member",
    teamNext: "Next member",
    teamMembers: [
      { name: "Daniel Trullols i Ruau",  role: "Chair",           initials: "DT" },
      { name: "Anna Bigas i Puig",       role: "Vice-chair",      initials: "AB" },
      { name: "Anna Jordana i Moreso",   role: "Secretary",       initials: "AJ" },
      { name: "Manel Rubio i Arbós",     role: "Treasurer",       initials: "MR" },
      { name: "Albert Montcada i Ribera",role: "Member",          initials: "AM" },
      { name: "Jordi Lleras i Gòrriz",   role: "Member",          initials: "JL" },
      { name: "Joana Pedreira Font",     role: "Member",          initials: "JP" },
      { name: "Alba Manteca i Esteve",   role: "Member",          initials: "AL" },
      { name: "Enric Poch i Giró",       role: "Member",          initials: "EP" },
    ],
    mastersEyebrow: "Directory · 1908 — present",
    mastersTitle: ["The people who built ", "the Esbart."],
    mastersSub: "Presidents, teachers, music directors, pianists and everyone who has devoted their time to keeping Catalan traditional dance alive since 1908.",
    mastersPrev: "Previous section",
    mastersNext: "Next section",
    mastersSections: MASTERS_SECTIONS_ITEMS.map((s, i) => ({
      ...s,
      title: ["Presidents","Dance Company Teachers","Youth & Children's Teachers","Music Directors","Pianists","Dance Company Assistants","Costume & Wardrobe","Friday Dance"][i]
    })),
    bodiesEyebrow: "Dance Company & sections",
    bodiesTitle: ["The organisation is shaped ", "by three sections."],
    bodies: [
      { num: "01", name: ["Dance ", "Company"], desc: "The adult company, open to all ages. They practise Catalan dances, stick dances and 18th–19th-century Barcelona historical dances, and perform the Cavallets Cotoners de Barcelona. They offer street parades and shows of 30–90 minutes. Rehearsal: Tue & Fri 20:30–22:30.", count: "32", lbl: "Members" },
      { num: "02", name: ["Youth ", "Group"], desc: "Open to anyone who wants to dance and work as a team. Catalan dances are learnt through body control, balance and coordination with props —hobby-horses, sticks, ribbons, scarves. About ten public ballades per year. Rehearsal: Fri 18:30–20:00.", count: "18", lbl: "Members" },
      { num: "03", name: ["Children's ", "Section"], desc: "From age four, three groups by age range. The youngest combine song, rhythm and movement games; older children work on more complex choreographies. All groups learn stick dances and take part in the Mercè, Santa Eulàlia and Carnival festivals. Rehearsal: Fri 18:30–20:00.", count: "44", lbl: "Members" },
    ],
    bodiesCta: "Come dance with us",
    seatEyebrow: "Our headquarters",
    seatTitle: ["La Casa dels ", "Entremesos."],
    seatP1: "We share our home with other popular-culture organisations in the heart of Ciutat Vella, in a landmark building dedicated to the world of giants, dragons and Catalan festivals.",
    seatP2: "Here we have the rehearsal hall, the archive and specialised library — and it's our weekly meeting point.",
    seatLabel1: "Address", seatVal1: "Plaça de les Beates, 2 · 08003 Barcelona",
    seatLabel2: "Metro", seatVal2: "L4 Jaume I · L1/L4 Urquinaona",
    seatLabel3: "Hours", seatVal3: "Tuesday to Friday · 18:00 — 22:30",
    seatLabel4: "Contact", seatVal4: "93 412 51 11 · info@esbartcatala.org",
    seatYear: "2009",
    seatYearCap: "Year of settlement at La Casa dels Entremesos",
    seatSeusBtn: "Former locations",
    seatCta: "How to get here",

    // Honors
    honorsEyebrow: "Honour & memory · 1910 — present",
    honorsTitle: ["Members of merit, of honour ", "and tributes."],
    honorsSub: "More than a century honouring the people who have made the Esbart great. Travel along the timeline and open any name to see their full record.",
    honorsHint: "Scroll to travel through the years",
    honorsClickHint: "Click a name to open it",
    honorsPeopleLbl: "people honoured",
    honorsRecsLbl: "recognitions",
    honorsSpanLbl: "over a century",
    honorsHonoredLbl: "honoured this year",
    honorsNavHint: "Drag or click to travel the years",
    honorsPrev: "Previous year",
    honorsNext: "Next year",
    honorsModalEyebrow: "Record of recognitions",
    honorsModalRecsLbl: "recognitions",
    honorsClose: "Close",
    honorsSkip: "Skip section",
    recogEyebrow: "Recognitions & partners",
    recogTitle: ["A track record ", "of recognition."],
    recogAwards: [
      { yr:"1980", title:"Almorratxa d'Or", inst:"Obra del Ballet Popular", desc:"Awarded for the first time by the Obra del Ballet Popular." },
      { yr:"1983", title:"Dept. of Culture Recognition", inst:"Generalitat de Catalunya", desc:"In recognition of outstanding commitment to Catalan traditional dances, on the occasion of the 75th Anniversary (1908–1983)." },
      { yr:"1992", title:"Fes-te teva la Mercè", inst:"Ajuntament de Barcelona", desc:"For the MercèDansa project: best Catalan popular dance initiative for the Festes de la Mercè." },
      { yr:"1993", title:"Ateneu Award for Artistic Creativity", inst:"Federació d'Ateneus de Catalunya", desc:"For the La Cafetera initiative." },
      { yr:"1998", title:"Institut de Cultura de Barcelona Recognition", inst:"Institut de Cultura de Barcelona", desc:"" },
      { yr:"1999", title:"Entity of Cultural Interest", inst:"Generalitat de Catalunya", desc:"Official declaration of the Esbart Català de Dansaires as an Entity of Cultural Interest." },
      { yr:"2001", title:"Medal of Merit in Catalan Dance", inst:"Obra del Ballet Popular", desc:"Awarded for the first time." },
      { yr:"2008", title:"City Honour Medal", inst:"Ajuntament de Barcelona", desc:"" },
      { yr:"2008", title:"Centenary Trophy", inst:"Agrupament d'Esbarts Dansaires", desc:"" },
      { yr:"2008", title:"Continuity Trophy", inst:"Obra del Ballet Popular", desc:"" },
      { yr:"2008", title:"El Grupet Trophy", inst:"El Grupet", desc:"" },
      { yr:"2009", title:"Rosa de Plata Trophy", inst:"BarnaCentre", desc:"" },
      { yr:"2010", title:"Creu de Sant Jordi", inst:"Generalitat de Catalunya", desc:"" },
      { yr:"2012", title:"Barcelona City Prize 2012", inst:"Ajuntament de Barcelona", desc:"Popular Culture category. Project Apel·les Mestres, complete artist and multifaceted man." },
      { yr:"2013", title:"Guardó Firaire d'Honor", inst:"Associació Fira de Santa Llúcia", desc:"" },
      { yr:"2015", title:"Best Prize · Best Strategic Project", inst:"Agrupació del Bestiari Festiu a Catalunya", desc:"For the project L'Any dels Cavallets Cotoners." },
      { yr:"2015", title:"Cultural Interest Association Diploma", inst:"Generalitat de Catalunya", desc:"" },
      { yr:"2018", title:"Capital de la Sardana Award for Musical Outreach", inst:"Obra del Ballet Popular", desc:"For the publication of records featuring Catalan popular dance music." },
      { yr:"2020", title:"Josep Anselm Clavé Prize 2020", inst:"Federació de Cors de Clavé", desc:"Best non-choral performing-arts production of popular culture. Awarded in 2021." },
    ],
    recogCountLabel: "honours · 1980–2020",
    recogPartnersLbl: "With the support of",
    recogPartners: ["Generalitat de Catalunya", "Diputació de Barcelona", "Ajuntament de Barcelona", "ICUB", "Fundació la Caixa", "ESMUC"],
    transpEyebrow: "Transparency",
    transpTitle: ["Public ", "documents."],
    transpSub: "Annual reports, accounts, bylaws and internal policies, available to members and the public.",
    transpCta: "Open the Transparency Portal",
    transpDocs: [
      { ext: "PDF", yr: "2025", title: ["Annual ", "report"], desc: "Summary of activities, performances, programming and research for the current year." },
      { ext: "PDF", yr: "2025", title: ["Annual ", "accounts"], desc: "Audited financial balance for the year, with detailed income and expenses." },
      { ext: "PDF", yr: "2024", title: ["Bylaws of the ", "organisation"], desc: "Legal and organisational framework of the Esbart, approved in general assembly." },
      { ext: "PDF", yr: "2024", title: ["Code of ", "conduct"], desc: "Principles and rules that govern internal life and operations." },
      { ext: "PDF", yr: "2024", title: ["Child safeguarding ", "policy"], desc: "Policy and protocols for activities with children and young people." },
      { ext: "PDF", yr: "2024", title: ["Board ", "composition"], desc: "Minutes of the latest assembly renewing positions and the current org chart." },
    ],
    transpRead: "Download",
    closingQuote: "Without memory there is no tradition; without tradition there is no future.",
    closingAttr: "Aureli Capmany · Folklorist",
    closingCta1: "Come dance with us",
    closingCta2: "Documentation Centre",
  },
};

/* ─── Helpers ────────────────────────────────────────────────────────────── */
// Render a sentence-array with optional {strong: "..."} fragments.
function renderQuote(parts) {
  return parts.map((p, i) =>
    typeof p === 'string' ? <React.Fragment key={i}>{p}</React.Fragment>
    : <strong key={i}>{p.strong}</strong>
  );
}

/* ─── Hero silhouette (logo oficial — line art animat) ──────────────────── */
function HeroDancersSilhouette() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const host = ref.current;
    if (!host) return;
    let cancelled = false;
    fetch("assets/ecd-silhouette.svg")
      .then((r) => r.text())
      .then((txt) => {
        if (cancelled) return;
        host.innerHTML = txt;
        const svg = host.querySelector("svg");
        if (!svg) return;
        svg.setAttribute("class", "hero-dancers");
        svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
        svg.setAttribute("aria-hidden", "true");
        svg.removeAttribute("width");
        svg.removeAttribute("height");
        const paths = svg.querySelectorAll("path");
        paths.forEach((p, i) => {
          p.setAttribute("stroke", "currentColor");
          p.setAttribute("fill", "none");
          let len = 0;
          try { len = p.getTotalLength(); } catch (e) { len = 1200; }
          p.style.strokeDasharray = len;
          p.style.strokeDashoffset = len;
          p.style.animation = "heroDraw 2.2s cubic-bezier(.65,.05,.36,1) forwards";
          p.style.animationDelay = (i * 0.018).toFixed(3) + "s";
        });
      })
      .catch(() => {});
    return () => { cancelled = true; };
  }, []);
  return <div ref={ref} className="hero-dancers-host" aria-hidden="true"></div>;
}

/* ─── Hero (sober editorial) ─────────────────────────────────────────────── */
function AboutHero({ t }) {
  // heroTitle pattern: [pre, italic1, mid, italic2, end]
  const ti = t.heroTitle;
  return (
    <header className="about-hero" id="hero">
      <HeroDancersSilhouette />
      <div className="wrap">
        <div className="ah-eyebrow reveal">{t.heroEyebrow}</div>
        <h1 className="reveal d1">
          {ti[0]}<em>{ti[1]}</em>{ti[2]}<em>{ti[3]}</em>{ti[4]}
        </h1>
        <p className="ah-lead reveal d2">{t.heroLead}</p>
        <div className="ah-meta reveal d3">
          {t.heroMeta.map((m, i) => (
            <div key={i} className="item">
              <div className="num">
                {m.num.map((n, j) => j === 0 ? n : <em key={j}>{n}</em>)}
              </div>
              <div className="label">{m.label}</div>
            </div>
          ))}
        </div>
      </div>
      <div className="ah-scroll" aria-hidden="true">{t.heroScroll}</div>
    </header>
  );
}

/* ─── Manifest ───────────────────────────────────────────────────────────── */
function AboutManifest({ t }) {
  return (
    <section className="manifest">
      <div className="wrap">
        <div className="rule reveal"></div>
        <div>
          <blockquote className="reveal d1">{renderQuote(t.manifestQuote)}</blockquote>
          <div className="attr reveal d2">{t.manifestAttr}</div>
        </div>
        <div className="rule reveal"></div>
      </div>
    </section>
  );
}

/* ─── History · Period reader ────────────────────────────────────────────── */
function AboutHistory({ t }) {
  const eras = t.eras || [];
  const [active, setActive] = React.useState(0);
  const [phase, setPhase] = React.useState("in"); // 'out' → 'in' for crossfade
  const [pendingIdx, setPendingIdx] = React.useState(null);
  const railRef = React.useRef(null);
  const total = eras.length;

  const goTo = React.useCallback((next) => {
    if (next === active || next < 0 || next >= total) return;
    setPendingIdx(next);
    setPhase("out");
  }, [active, total]);

  // After fade-out, swap content, fade-in
  React.useEffect(() => {
    if (phase !== "out" || pendingIdx == null) return;
    const t1 = setTimeout(() => {
      setActive(pendingIdx);
      setPendingIdx(null);
      setPhase("in");
    }, 280);
    return () => clearTimeout(t1);
  }, [phase, pendingIdx]);

  // Keep active chip visible in horizontal rail
  React.useEffect(() => {
    const rail = railRef.current;
    if (!rail) return;
    const chip = rail.querySelector(`[data-era-idx="${active}"]`);
    if (chip && chip.scrollIntoView) {
      const r = chip.getBoundingClientRect();
      const rr = rail.getBoundingClientRect();
      if (r.left < rr.left + 24 || r.right > rr.right - 24) {
        rail.scrollTo({ left: chip.offsetLeft - rail.clientWidth / 2 + chip.clientWidth / 2, behavior: "smooth" });
      }
    }
  }, [active]);

  // Keyboard nav when section is in viewport
  const sectionRef = React.useRef(null);
  React.useEffect(() => {
    const onKey = (e) => {
      const sec = sectionRef.current;
      if (!sec) return;
      const rect = sec.getBoundingClientRect();
      const inView = rect.top < window.innerHeight * 0.6 && rect.bottom > window.innerHeight * 0.2;
      if (!inView) return;
      if (e.key === "ArrowRight") { e.preventDefault(); goTo(active + 1); }
      if (e.key === "ArrowLeft")  { e.preventDefault(); goTo(active - 1); }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [active, goTo]);

  const era = eras[active] || {};

  return (
    <section className="history" id="historia" ref={sectionRef}>
      <div className="wrap">
        <div className="sec-head">
          <div>
            <div className="eyebrow reveal">{t.histEyebrow}</div>
            <h2 className="reveal d1" style={{marginTop:16}}>{t.histTitle[0]}<em>{t.histTitle[1]}</em></h2>
          </div>
          <div className="sub reveal d2">{t.histSub}</div>
        </div>

        <div className="era-reader reveal d2">
          {/* Period rail (horizontal navigation) */}
          <div className="era-rail-wrap">
            <div className="era-rail" ref={railRef} role="tablist" aria-label="Períodes">
              {eras.map((e, i) => (
                <button
                  key={i}
                  data-era-idx={i}
                  className={"era-chip" + (i === active ? " is-active" : "")}
                  role="tab"
                  aria-selected={i === active}
                  onClick={() => goTo(i)}
                >
                  <span className="era-chip__range">{e.range}</span>
                  <span className="era-chip__kicker">{e.kicker}</span>
                </button>
              ))}
            </div>
            <div className="era-rail__progress" aria-hidden="true">
              <span style={{ width: `${((active + 1) / total) * 100}%` }} />
            </div>
          </div>

          {/* Reading stage */}
          <div className={"era-stage era-stage--" + phase}>
            <div className="era-stage__bg" aria-hidden="true">
              <span className="era-stage__bgyear">{era.start}</span>
            </div>
            <div className="era-stage__inner">
              <aside className="era-stage__meta">
                <div className="era-stage__count">
                  <span>{String(active + 1).padStart(2, "0")}</span>
                  <span className="era-stage__count-sep">/</span>
                  <span>{String(total).padStart(2, "0")}</span>
                </div>
                <div className="era-stage__range">
                  <em>{era.start}</em>
                  <span>—</span>
                  <em>{era.end}</em>
                </div>
                <div className="era-stage__kicker">{era.kicker}</div>
              </aside>
              <div className="era-stage__body">
                <h3 className="era-stage__title">{era.title}</h3>
                <p className="era-stage__lead">{era.lead}</p>
                {(era.body || []).map((p, i) => (
                  <p key={i} className="era-stage__p">{p}</p>
                ))}
                {era.pdf && (
                  <a className="era-stage__pdf" href={era.pdf} target="_blank" rel="noopener">
                    <span className="era-stage__pdf-icon" aria-hidden="true">
                      <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6">
                        <path d="M12 4v12m0 0l-4-4m4 4l4-4M4 20h16" strokeLinecap="round" strokeLinejoin="round"/>
                      </svg>
                    </span>
                    <span>{t.histPdfLabel}</span>
                    <span className="era-stage__pdf-tag">PDF</span>
                  </a>
                )}
              </div>
            </div>
          </div>

          {/* Footer controls */}
          <div className="era-controls">
            <button
              className="era-nav"
              onClick={() => goTo(active - 1)}
              disabled={active === 0}
              aria-label={t.histPrev}
            >
              <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M14 6l-6 6 6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
              <span>{t.histPrev}</span>
            </button>
            <div className="era-progress">
              <span className="era-progress__num">{String(active + 1).padStart(2, "0")}</span>
              <span className="era-progress__of">{t.histProgress}</span>
              <span className="era-progress__total">{String(total).padStart(2, "0")}</span>
            </div>
            <button
              className="era-nav era-nav--next"
              onClick={() => goTo(active + 1)}
              disabled={active === total - 1}
              aria-label={t.histNext}
            >
              <span>{t.histNext}</span>
              <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M10 6l6 6-6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </button>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ─── Mission ────────────────────────────────────────────────────────────── */
function AboutMission({ t }) {
  return (
    <section className="mission">
      <div className="wrap">
        <div className="sec-head">
          <div>
            <div className="eyebrow reveal">{t.missionEyebrow}</div>
            <h2 className="reveal d1" style={{marginTop:16}}>{t.missionTitle[0]}<em>{t.missionTitle[1]}</em></h2>
          </div>
        </div>
        <div className="mission-grid">
          {t.missionCols.map((col, i) => (
            <div key={i} className={`col reveal d${i+1}`}>
              <div className="num">{col.num}</div>
              <h3>{col.title[0]}<em>{col.title[1]}</em></h3>
              <p>{col.p}</p>
              <ul>{col.list.map((l, j) => <li key={j}>{l}</li>)}</ul>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ─── Team / Junta directiva ─────────────────────────────────────────────── */
/* Galeria horitzontal sobre fons fosc: l'eix vertical navega entre seccions
   i l'horitzontal aprofundeix dins la Junta (drag/swipe, roda horitzontal i
   fletxes; mai no se segresta l'scroll vertical). Cada targeta mostra el
   monograma on anirà el retrat quan hi hagi fotos. */
function AboutTeam({ t }) {
  const rootRef  = React.useRef(null);
  const trackRef = React.useRef(null);
  const [pos, setPos] = React.useState({ i: 0, prog: 0 });
  const n = t.teamMembers.length;

  const step = () => {
    const cards = trackRef.current.querySelectorAll('.tm-card');
    return cards.length > 1 ? cards[1].offsetLeft - cards[0].offsetLeft : 1;
  };

  const onScroll = () => {
    const el = trackRef.current;
    const max = el.scrollWidth - el.clientWidth;
    const prog = max > 0 ? el.scrollLeft / max : 0;
    const i = prog >= 0.999 ? n - 1 : Math.min(n - 1, Math.round(el.scrollLeft / step()));
    setPos({ i, prog });
  };

  const go = (dir) => {
    const smooth = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth';
    trackRef.current.scrollBy({ left: dir * step(), behavior: smooth });
  };

  // Entrada GSAP via IntersectionObserver, no ScrollTrigger: les imatges de
  // seccions superiors carreguen després del mount i desplacen el layout,
  // i les posicions memoritzades per ScrollTrigger queden desfasades
  // (window 'load' arriba abans que React munti, cap refresh les corregeix).
  React.useEffect(() => {
    if (typeof gsap === 'undefined') return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    const ctx = gsap.context(() => {
      gsap.set('.tm-card', { autoAlpha: 0, x: 72 });
    }, rootRef);
    const io = new IntersectionObserver((entries) => {
      if (!entries.some((e) => e.isIntersecting)) return;
      io.disconnect();
      ctx.add(() => {
        gsap.to('.tm-card', { autoAlpha: 1, x: 0, duration: 1.0, ease: 'power3.out', stagger: 0.07 });
      });
    }, { rootMargin: '0px 0px -18% 0px' });
    io.observe(trackRef.current);
    return () => { io.disconnect(); ctx.revert(); };
  }, []);

  // Drag-to-scroll amb ratolí (touch fa servir el swipe natiu + scroll-snap).
  React.useEffect(() => {
    const el = trackRef.current;
    if (!el) return;
    let dragging = false, startX = 0, startL = 0;
    const down = (e) => {
      if (e.pointerType !== 'mouse') return;
      dragging = true;
      startX = e.clientX; startL = el.scrollLeft;
      el.setPointerCapture(e.pointerId);
      el.classList.add('is-drag');
    };
    const move = (e) => {
      if (!dragging) return;
      el.scrollLeft = startL - (e.clientX - startX);
    };
    const up = () => {
      if (!dragging) return;
      dragging = false;
      el.classList.remove('is-drag');
      const cards = el.querySelectorAll('.tm-card');
      if (cards.length > 1) {
        const s = cards[1].offsetLeft - cards[0].offsetLeft;
        el.scrollTo({ left: Math.round(el.scrollLeft / s) * s, behavior: 'smooth' });
      }
    };
    el.addEventListener('pointerdown', down);
    el.addEventListener('pointermove', move);
    el.addEventListener('pointerup', up);
    el.addEventListener('pointercancel', up);
    return () => {
      el.removeEventListener('pointerdown', down);
      el.removeEventListener('pointermove', move);
      el.removeEventListener('pointerup', up);
      el.removeEventListener('pointercancel', up);
    };
  }, []);

  const pad = (x) => String(x).padStart(2, '0');

  return (
    <section className="team" id="organitzacio" ref={rootRef}>
      <div className="wrap">
        <div className="sec-head">
          <div>
            <div className="eyebrow reveal">{t.teamEyebrow}</div>
            <h2 className="reveal d1" style={{marginTop:16}}>{t.teamTitle[0]}<em>{t.teamTitle[1]}</em></h2>
          </div>
          <div className="sub reveal d2">{t.teamSub}</div>
        </div>
      </div>

      <div className="tm-track" ref={trackRef} onScroll={onScroll}>
        {t.teamMembers.map((p, i) => (
          <article key={i} className="tm-card">
            <div className="tm-card__portrait">
              <span className="tm-card__mono">{p.initials}</span>
              <span className="tm-card__num">{pad(i + 1)}</span>
            </div>
            <h4 className="tm-card__name">{p.name}</h4>
            <div className="tm-card__role">{p.role}</div>
          </article>
        ))}
      </div>

      <div className="wrap">
        <div className="tm-toolbar reveal">
          <div className="tm-progress" aria-hidden="true">
            <span className="tm-progress__bar" style={{ transform: `scaleX(${pos.prog})` }}></span>
          </div>
          <span className="tm-count" aria-hidden="true">
            {pad(pos.i + 1)}<span className="tm-count__dim"> / {pad(n)}</span>
          </span>
          <div className="tm-nav">
            <button className="tm-arrow" aria-label={t.teamPrev} disabled={pos.prog <= 0.001} onClick={() => go(-1)}>
              <svg width="18" height="12" viewBox="0 0 18 12" fill="none" stroke="currentColor" strokeWidth="1.5">
                <path d="M17 6H1M6 1L1 6l5 5"/>
              </svg>
            </button>
            <button className="tm-arrow" aria-label={t.teamNext} disabled={pos.prog >= 0.999} onClick={() => go(1)}>
              <svg width="18" height="12" viewBox="0 0 18 12" fill="none" stroke="currentColor" strokeWidth="1.5">
                <path d="M1 6h16M12 1l5 5-5 5"/>
              </svg>
            </button>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ─── Masters (explorador tabbed, estil era-reader) ──────────────────────── */
function AboutMasters({ t }) {
  const [active, setActive] = React.useState(0);
  const [phase,  setPhase]  = React.useState('idle');
  const sections = t.mastersSections;
  const total    = sections.length;
  const sec      = sections[active];

  function goTo(idx) {
    if (idx < 0 || idx >= total || idx === active) return;
    setPhase('out');
    setTimeout(() => {
      setActive(idx);
      setPhase('in');
      setTimeout(() => setPhase('idle'), 350);
    }, 180);
  }

  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'ArrowRight') goTo(active + 1);
      if (e.key === 'ArrowLeft')  goTo(active - 1);
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [active]);

  return (
    <section className="masters">
      <div className="wrap">
        <div className="sec-head">
          <div>
            <div className="eyebrow reveal">{t.mastersEyebrow}</div>
            <h2 className="reveal d1" style={{marginTop:16}}>{t.mastersTitle[0]}<em>{t.mastersTitle[1]}</em></h2>
          </div>
          <div className="sub reveal d2">{t.mastersSub}</div>
        </div>

        <div className="masters-explorer reveal">
          {/* Chip rail */}
          <div className="era-rail-wrap">
            <div className="era-rail masters-rail" role="tablist">
              {sections.map((s, i) => (
                <button
                  key={s.id}
                  className={"era-chip" + (i === active ? " is-active" : "")}
                  role="tab"
                  aria-selected={i === active}
                  onClick={() => goTo(i)}
                >
                  <span className="era-chip__range">{s.title}</span>
                </button>
              ))}
            </div>
            <div className="era-rail__progress" aria-hidden="true">
              <span style={{width: `${((active + 1) / total) * 100}%`}} />
            </div>
          </div>

          {/* Escenari */}
          <div className={"masters-stage masters-stage--" + phase}>
            <div className="masters-stage__head">
              <h3 className="masters-stage__title">{sec.title}</h3>
            </div>
            <div className="masters-list">
              {sec.items.map((m, i) => (
                <div key={i} className="masters-row">
                  <div className="masters-row__span">{m.span}</div>
                  <div className="masters-row__name">
                    {m.name}
                    {m.note && <em className="masters-row__note"> · {m.note}</em>}
                  </div>
                </div>
              ))}
            </div>
          </div>

          {/* Controls */}
          <div className="era-controls">
            <button
              className="era-nav"
              onClick={() => goTo(active - 1)}
              disabled={active === 0}
              aria-label={t.mastersPrev}
            >
              <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M14 6l-6 6 6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
              <span>{t.mastersPrev}</span>
            </button>
            <div className="era-progress">
              <span className="era-progress__num">{String(active + 1).padStart(2, "0")}</span>
              <span className="era-progress__of">{t.histProgress}</span>
              <span className="era-progress__total">{String(total).padStart(2, "0")}</span>
            </div>
            <button
              className="era-nav era-nav--next"
              onClick={() => goTo(active + 1)}
              disabled={active === total - 1}
              aria-label={t.mastersNext}
            >
              <span>{t.mastersNext}</span>
              <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M10 6l6 6-6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </button>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ─── Bodies ─────────────────────────────────────────────────────────────── */
function AboutBodies({ t }) {
  return (
    <section className="bodies">
      <div className="wrap">
        <div className="sec-head">
          <div>
            <div className="eyebrow reveal">{t.bodiesEyebrow}</div>
            <h2 className="reveal d1" style={{marginTop:16}}>{t.bodiesTitle[0]}<em>{t.bodiesTitle[1]}</em></h2>
          </div>
          <div className="sub reveal d2">
            <div style={{marginTop:10}}>
              <a href="Vine-a-ballar.html" className="btn ghost">{t.bodiesCta} →</a>
            </div>
          </div>
        </div>
        <div className="bodies-grid reveal">
          {t.bodies.map((b, i) => (
            <div key={i} className="body">
              <h3>{b.name[0]}<em>{b.name[1]}</em></h3>
              <p>{b.desc}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ─── Seus socials · dades i mapa ────────────────────────────────────────── */
const SEUS_DATA = [
  { yr:"1908", title:"Seu fundacional",                         addr:"Carrer de Sant Pere més Baix, 2",          note:"Cantonada Riera de Sant Joan. Primers estatuts de l'entitat.",                                            lat:41.386243, lng:2.176011 },
  { yr:"1908", title:"Foment Autonomista Català",               addr:"Carrer del Consell de Cent, 401",           note:"Principal.",                                                                                             lat:41.395360, lng:2.171096 },
  { yr:"1910", title:"Domicili del President Antoni Casalí",    addr:"Carrer del Dormitori de Sant Francesc, 15–17", note:"3r 2ª. Avui passatge del Dormitori de Sant Francesc, al Gòtic.",                                       lat:41.377773, lng:2.178596 },
  { yr:"1911", title:"Carrer de la Universitat (interior)",     addr:"Carrer de la Universitat, 83",              note:"Actualment carrer d'Enric Granados.",                                                                   lat:41.391819, lng:2.156787 },
  { yr:"1912", title:"Ateneu Obrer del Districte II",           addr:"Carrer del Bisbe Caçador, 4",               note:"Principal. Compartit amb Eura, diari Renaixement i Associació Nacional Catalana.",                     lat:41.383139, lng:2.179077 },
  { yr:"1924", title:"Cor La Violeta d'En Clavé",               addr:"Carrer del Rec Comtal, 17",                 note:"",                                                                                                      lat:41.390134, lng:2.179960 },
  { yr:"1924", title:"Centro de Naturales de Tarragona",        addr:"Carrer Duc de la Victoria, 14",             note:"Principal. Actualment carrer del Duc.",                                                                 lat:41.384642, lng:2.173037 },
  { yr:"1927", title:"Ateneu Enciclopèdic Popular",             addr:"Carrer del Carme, 28–30",                   note:"",                                                                                                      lat:41.382297, lng:2.170239 },
  { yr:"1932", title:"Orfeó Barcelonès",                        addr:"Carrer de la Tapineria, 33",                note:"Principal.",                                                                                            lat:41.384343, lng:2.177634 },
  { yr:"1936", title:"Portal de l'Àngel",                      addr:"Avinguda del Portal de l'Àngel, 6",         note:"Principal.",                                                                                            lat:41.384944, lng:2.173939 },
  { yr:"1939", title:"Domicili del President Josep Ventura",    addr:"Carrer de Duran i Bas",                     note:"Número desconegut.",                                                                                    lat:41.385763, lng:2.174548 },
  { yr:"1942", title:"Ateneu Obrer",                            addr:"Carrer dels Montcada, 12",                  note:"Principal.",                                                                                            lat:41.384795, lng:2.181001 },
  { yr:"1954", title:"Cercle Barcelonès de Sant Josep",         addr:"Carrer de Pedro Lastortras, 12",            note:"Avui carrer de Verdaguer i Callís, 12 (Antic Teatre).",                                                 lat:41.387144, lng:2.175902 },
  { yr:"1963", title:"Penya Cultural Barcelonesa",              addr:"Carrer de Sant Pere més Baix, 55",          note:"Seu també el 1975.",                                                                                    lat:41.388178, lng:2.178526 },
  { yr:"1974", title:"Associació Cultural Germanor Barcelonina",addr:"Carrer dels Carders, 12",                   note:"Principal.",                                                                                            lat:41.385539, lng:2.179666 },
  { yr:"1996", title:"Passatge del Crèdit",                    addr:"Passatge del Crèdit, 8",                    note:"Baixos.",                                                                                               lat:41.381652, lng:2.176639 },
  { yr:"2006", title:"Carrer de Ripoll",                        addr:"Carrer de Ripoll, 25",                      note:"Primer pis.",                                                                                           lat:41.385536, lng:2.174942 },
  { yr:"2009", title:"Casa dels Entremesos",                    addr:"Plaça de les Beates, 2",                    note:"Seu actual. Compartida amb altres entitats de cultura popular de Barcelona.",                          lat:41.386077, lng:2.176778, current:true },
];

function SeusMapModal({ open, onClose }) {
  const mapRef          = React.useRef(null);
  const mapInstanceRef  = React.useRef(null);
  const markersRef      = React.useRef([]);
  const listRef         = React.useRef(null);
  const [activeIdx, setActiveIdx] = React.useState(null);

  /* Init/destroy map when modal opens/closes */
  React.useEffect(() => {
    if (!open) {
      if (mapInstanceRef.current) { mapInstanceRef.current.remove(); mapInstanceRef.current = null; }
      markersRef.current = [];
      return;
    }
    const timer = setTimeout(() => {
      if (!window.L || !mapRef.current || mapInstanceRef.current) return;
      const map = window.L.map(mapRef.current, {
        center: [41.3858, 2.1742],
        zoom: 15,
        zoomControl: true,
      });
      window.L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
        attribution: '© <a href="https://openstreetmap.org">OpenStreetMap</a> · © <a href="https://carto.com">CARTO</a>',
        subdomains: 'abcd', maxZoom: 19,
      }).addTo(map);

      markersRef.current = SEUS_DATA.map((s, i) => {
        const icon = window.L.divIcon({
          html: `<div class="seus-pin${s.current ? ' seus-pin--current' : ''}" data-idx="${i}">${s.yr}</div>`,
          className: '', iconSize: [44, 22], iconAnchor: [22, 11],
        });
        const marker = window.L.marker([s.lat, s.lng], { icon }).addTo(map);
        marker.on('click', () => setActiveIdx(prev => prev === i ? null : i));
        return marker;
      });
      mapInstanceRef.current = map;
      // Enquadra tots els marcadors automàticament
      const bounds = window.L.latLngBounds(SEUS_DATA.map(s => [s.lat, s.lng]));
      map.fitBounds(bounds, { padding: [42, 42], maxZoom: 16 });
    }, 80);
    return () => clearTimeout(timer);
  }, [open]);

  /* Highlight active marker and scroll list item */
  React.useEffect(() => {
    markersRef.current.forEach((marker, i) => {
      const el = marker.getElement();
      if (el) {
        const pin = el.querySelector('.seus-pin');
        if (pin) pin.classList.toggle('seus-pin--active', i === activeIdx);
      }
      if (marker.setZIndexOffset) marker.setZIndexOffset(i === activeIdx ? 1000 : 0);
    });
    if (activeIdx !== null && listRef.current) {
      const item = listRef.current.querySelector(`[data-list-idx="${activeIdx}"]`);
      if (item) {
        const top = item.offsetTop - listRef.current.offsetTop - 16;
        listRef.current.scrollTo({ top, behavior: 'smooth' });
      }
    }
  }, [activeIdx]);

  const handleItemClick = (i) => {
    setActiveIdx(prev => prev === i ? null : i);
    if (mapInstanceRef.current) {
      mapInstanceRef.current.flyTo([SEUS_DATA[i].lat, SEUS_DATA[i].lng], 17, { duration: 0.75 });
    }
  };

  /* Close on Escape */
  React.useEffect(() => {
    if (!open) return;
    const onKey = e => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  if (!open) return null;

  return (
    <div className="seus-overlay" onClick={e => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="seus-modal" role="dialog" aria-modal="true" aria-label="Antigues seus">
        {/* Header */}
        <div className="seus-modal__hd">
          <div>
            <div className="seus-modal__eyebrow">Seus socials · 1908 — 2009</div>
            <h3 className="seus-modal__title"><em>On hem estat.</em></h3>
          </div>
          <button className="seus-modal__close" onClick={onClose} aria-label="Tancar">
            <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.8">
              <path d="M18 6L6 18M6 6l12 12" strokeLinecap="round"/>
            </svg>
          </button>
        </div>
        {/* Body */}
        <div className="seus-modal__bd">
          <div className="seus-map" ref={mapRef}></div>
          <div className="seus-list" ref={listRef}>
            {SEUS_DATA.map((s, i) => (
              <button
                key={i}
                data-list-idx={i}
                className={`seus-item${activeIdx === i ? ' seus-item--active' : ''}${s.current ? ' seus-item--current' : ''}`}
                onClick={() => handleItemClick(i)}
              >
                <span className="seus-item__yr">{s.yr}</span>
                <span className="seus-item__body">
                  <span className="seus-item__title">{s.title}</span>
                  <span className="seus-item__addr">{s.addr}</span>
                  {activeIdx === i && s.note && (
                    <span className="seus-item__note">{s.note}</span>
                  )}
                </span>
                {s.current && <span className="seus-item__badge">Actual</span>}
              </button>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

/* ─── Seat ───────────────────────────────────────────────────────────────── */
function AboutSeat({ t }) {
  const [seusOpen, setSeusOpen] = React.useState(false);
  return (
    <>
      <section className="seat">
        <div className="photo">
          <img src="assets/casa-dels-entremesos.jpg" alt="La Casa dels Entremesos" className="seat-photo" />
          <div className="yr">{t.seatYear}</div>
          <div className="cap">{t.seatYearCap}</div>
        </div>
        <div className="info">
          <div className="eyebrow reveal">{t.seatEyebrow}</div>
          <h2 className="reveal d1">{t.seatTitle[0]}<em>{t.seatTitle[1]}</em></h2>
          <p className="reveal d2">{t.seatP1}</p>
          <p className="reveal d2">{t.seatP2}</p>
          <div className="details reveal d3">
            <dl><dt>{t.seatLabel1}</dt><dd>{t.seatVal1}</dd></dl>
            <dl><dt>{t.seatLabel2}</dt><dd>{t.seatVal2}</dd></dl>
            <dl><dt>{t.seatLabel3}</dt><dd>{t.seatVal3}</dd></dl>
            <dl><dt>{t.seatLabel4}</dt><dd>{t.seatVal4}</dd></dl>
          </div>
          <div className="seat-cta reveal d4">
            <a href="https://maps.app.goo.gl/PLCdmKvvuPFGdWEV8" target="_blank" rel="noopener" className="btn">{t.seatCta} →</a>
            <button className="btn ghost" onClick={() => setSeusOpen(true)}>{t.seatSeusBtn}</button>
          </div>
        </div>
      </section>
      <SeusMapModal open={seusOpen} onClose={() => setSeusOpen(false)} />
    </>
  );
}

/* ─── Recognitions ───────────────────────────────────────────────────────── */
function AboutRecog({ t }) {
  // Group awards by year preserving insertion order
  const grouped = {};
  const orderedYears = [];
  t.recogAwards.forEach(a => {
    if (!grouped[a.yr]) { grouped[a.yr] = []; orderedYears.push(a.yr); }
    grouped[a.yr].push(a);
  });

  return (
    <section className="recog" id="distincions">
      <div className="wrap">
        <div className="recog-head">
          <div>
            <div className="eyebrow reveal">{t.recogEyebrow}</div>
            <h2 className="reveal d1" style={{marginTop:14}}>{t.recogTitle[0]}<em>{t.recogTitle[1]}</em></h2>
          </div>
          <div className="recog-tally reveal d2" aria-hidden="true">
            <span className="tally-num">{t.recogAwards.length}</span>
            <span className="tally-lbl">{t.recogCountLabel}</span>
          </div>
        </div>

        <div className="recog-chronicle reveal">
          {orderedYears.map(yr => {
            const awards = grouped[yr];
            const multi = awards.length > 1;
            return (
              <div key={yr} className={`rc-row${multi ? ' rc-row--multi' : ''}`}>
                <div className="rc-yr-block">
                  <span className="rc-yr">{yr}</span>
                </div>
                <div className="rc-awards">
                  {awards.map((a, i) => (
                    <div key={i} className="rc-award">
                      <div className="rc-title">{a.title}</div>
                      <div className="rc-inst">{a.inst}</div>
                      {a.desc && <div className="rc-desc">{a.desc}</div>}
                    </div>
                  ))}
                </div>
              </div>
            );
          })}
        </div>

        <div className="partners-strip reveal">
          <span className="lbl">{t.recogPartnersLbl}</span>
          {t.recogPartners.map((p, i) => <span key={i} className="partner">{p}</span>)}
        </div>
      </div>
    </section>
  );
}

/* ─── Transparency ───────────────────────────────────────────────────────── */
function AboutTransp({ t }) {
  return (
    <section className="transp" id="transparencia">
      <div className="wrap">
        <div className="sec-head">
          <div>
            <div className="eyebrow reveal">{t.transpEyebrow}</div>
            <h2 className="reveal d1" style={{marginTop:16}}>{t.transpTitle[0]}<em>{t.transpTitle[1]}</em></h2>
          </div>
          <div className="sub reveal d2">{t.transpSub}</div>
        </div>
        <div className="docs reveal">
          {t.transpDocs.map((d, i) => (
            <a key={i} href="Transparencia.html" className="doc">
              <div className="meta">
                <span className="ext">{d.ext}</span>
                <span className="yr">{d.yr}</span>
              </div>
              <h4>{d.title[0]}<em>{d.title[1]}</em></h4>
              <p>{d.desc}</p>
              <div className="arrow"><b>{t.transpRead}</b><span>→</span></div>
            </a>
          ))}
        </div>
        <div className="transp-cta reveal">
          <a href="Transparencia.html" className="btn ghost">{t.transpCta}</a>
        </div>
      </div>
    </section>
  );
}

/* ─── Closing ────────────────────────────────────────────────────────────── */
function AboutClosing({ t }) {
  return (
    <section className="closing">
      <video
        className="closing-video"
        src="assets/aureli-capmany.mp4"
        autoPlay
        loop
        muted
        playsInline
        aria-hidden="true"
      />
      <div className="wrap">
        <div className="closing-content">
          <blockquote className="reveal d1">{t.closingQuote}</blockquote>
          <div className="attr reveal d2">{t.closingAttr}</div>
          <div className="actions reveal d3">
            <a href="Vine-a-ballar.html" className="btn light">{t.closingCta1} →</a>
            <a href="Patrimoni.html" className="btn outline-light">{t.closingCta2}</a>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ─── Honors · Fris d'Honor (línia del temps daurada, scroll-driven GSAP) ─── */
function HonorModal({ name, lang, t, onClose }) {
  const record = React.useMemo(() => honorPersonRecord(name, lang), [name, lang]);
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [onClose]);
  return (
    <div className="honor-overlay" onClick={onClose}>
      <div className="honor-modal" role="dialog" aria-modal="true" aria-label={name} onClick={(e) => e.stopPropagation()}>
        <button className="honor-modal__close" onClick={onClose} aria-label={t.honorsClose}>
          <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M6 6l12 12M18 6L6 18" strokeLinecap="round"/></svg>
        </button>
        <div className="honor-modal__hd">
          <div className="honor-modal__monogram" aria-hidden="true">{honorInitials(name)}</div>
          <div>
            <div className="honor-modal__eyebrow">{t.honorsModalEyebrow}</div>
            <h3 className="honor-modal__name">{name}</h3>
            <div className="honor-modal__count">{record.length} {t.honorsModalRecsLbl} · {record[0] && record[0].year}{record.length > 1 ? "–" + record[record.length - 1].year : ""}</div>
          </div>
        </div>
        <ol className="honor-record">
          {record.map((r, i) => (
            <li key={i} className="honor-record__row" data-cat={r.cat}>
              <span className="honor-record__yr">{r.year}</span>
              <span className="honor-record__title">{r.label}</span>
            </li>
          ))}
        </ol>
      </div>
    </div>
  );
}

function AboutHonors({ t, lang }) {
  const stations = React.useMemo(() => buildHonorStations(lang), [lang]);
  const total = stations.length;
  const sectionRef = React.useRef(null);
  const trackRef = React.useRef(null);
  const vpRef = React.useRef(null);
  const stRefs = React.useRef([]);
  const [active, setActive] = React.useState(0);
  const [person, setPerson] = React.useState(null);
  const [interacted, setInteracted] = React.useState(false);
  const activeRef = React.useRef(0);
  const scrollAnim = React.useRef(0);
  const dragSuppress = React.useRef(false);
  const markInteracted = React.useCallback(() => setInteracted(true), []);

  // Custom smooth horizontal scroll of the strip (reliable, drives onScroll → focus)
  const animateScrollLeft = React.useCallback((target, duration = 560) => {
    const vp = vpRef.current; if (!vp) return;
    const id = ++scrollAnim.current;
    const start = vp.scrollLeft;
    const dist = target - start;
    if (Math.abs(dist) < 2) { vp.scrollLeft = target; return; }
    const t0 = performance.now();
    const ease = (t) => 1 - Math.pow(1 - t, 3);
    const step = (now) => {
      if (scrollAnim.current !== id || !vpRef.current) return;
      const p = Math.min(1, (now - t0) / duration);
      vpRef.current.scrollLeft = Math.round(start + dist * ease(p));
      if (p < 1) requestAnimationFrame(step);
    };
    requestAnimationFrame(step);
  }, []);

  // Spotlight: drive --f (focus 0..1) on each station by distance to the strip centre
  const updateFocus = React.useCallback(() => {
    const els = stRefs.current;
    const vp = vpRef.current;
    if (!els.length || !vp) return;
    const w0 = els[0] && els[0].offsetWidth;
    if (!w0) return; // not laid out yet — never write NaN to --f
    const vpRect = vp.getBoundingClientRect();
    const mid = vpRect.left + vpRect.width / 2;
    const range = w0 * 1.15;
    let best = 0, bestDist = Infinity;
    for (let i = 0; i < els.length; i++) {
      const el = els[i];
      if (!el) continue;
      const r = el.getBoundingClientRect();
      const c = r.left + r.width / 2;
      const d = Math.abs(c - mid);
      let f = Math.max(0, 1 - d / range);
      f = f * f * (3 - 2 * f); // smoothstep
      el.style.setProperty("--f", f.toFixed(3));
      el.classList.toggle("is-focus", f > 0.55);
      if (d < bestDist) { bestDist = d; best = i; }
    }
    if (best !== activeRef.current) { activeRef.current = best; setActive(best); }
  }, []);

  // Centre a year-station within the strip (intuitive click-to-navigate)
  const goTo = React.useCallback((idx) => {
    idx = Math.max(0, Math.min(total - 1, idx));
    const vp = vpRef.current, el = stRefs.current[idx];
    if (vp && el) animateScrollLeft(el.offsetLeft - (vp.clientWidth - el.clientWidth) / 2);
  }, [total, animateScrollLeft]);

  // Relative step that accumulates rapid clicks (two quick "next" advance two years)
  const navTarget = React.useRef(null);
  const stepNav = React.useCallback((delta) => {
    markInteracted();
    const base = navTarget.current != null ? navTarget.current : activeRef.current;
    const next = Math.max(0, Math.min(total - 1, base + delta));
    navTarget.current = next;
    goTo(next);
    setTimeout(() => { if (navTarget.current === next) navTarget.current = null; }, 640);
  }, [goTo, total, markInteracted]);

  // Strip behaviour: focus on scroll + drag-to-pan (mouse). Never hijacks the page —
  // vertical scroll always flows past the section, both downward and upward.
  React.useEffect(() => {
    const vp = vpRef.current;
    if (!vp) return;
    let raf;
    let ready = false;
    const readyT = setTimeout(() => { ready = true; }, 700); // ignore layout-driven scrolls on load
    const kick = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(updateFocus); };
    const onScroll = () => { kick(); if (ready) markInteracted(); };
    vp.addEventListener("scroll", onScroll, { passive: true });
    const onResize = () => kick();
    window.addEventListener("resize", onResize);

    // Drag to pan (mouse only — touch uses native horizontal scroll)
    let down = false, startX = 0, startLeft = 0, moved = false;
    const onDown = (e) => {
      if (e.pointerType === "touch") return;
      if (e.button != null && e.button !== 0) return;
      down = true; moved = false;
      startX = e.clientX; startLeft = vp.scrollLeft;
      vp.classList.add("is-dragging");
    };
    const onMove = (e) => {
      if (!down) return;
      const dx = e.clientX - startX;
      if (Math.abs(dx) > 4) { moved = true; markInteracted(); }
      vp.scrollLeft = startLeft - dx;
    };
    const onUp = () => {
      if (!down) return;
      down = false;
      vp.classList.remove("is-dragging");
      dragSuppress.current = moved; // swallow the click that ends a drag
      setTimeout(() => { dragSuppress.current = false; }, 0);
    };
    vp.addEventListener("pointerdown", onDown);
    window.addEventListener("pointermove", onMove);
    window.addEventListener("pointerup", onUp);

    requestAnimationFrame(updateFocus);
    const t1 = setTimeout(updateFocus, 120);
    const t2 = setTimeout(updateFocus, 500);
    window.addEventListener("load", updateFocus);
    return () => {
      vp.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onResize);
      vp.removeEventListener("pointerdown", onDown);
      window.removeEventListener("pointermove", onMove);
      window.removeEventListener("pointerup", onUp);
      window.removeEventListener("load", updateFocus);
      clearTimeout(t1); clearTimeout(t2); clearTimeout(readyT); cancelAnimationFrame(raf);
    };
  }, [stations, updateFocus, markInteracted]);

  // Keyboard nav while section is on screen
  React.useEffect(() => {
    const onKey = (e) => {
      if (person) return;
      const sec = sectionRef.current;
      if (!sec) return;
      const r = sec.getBoundingClientRect();
      if (r.bottom < 0 || r.top > window.innerHeight) return;
      if (e.key === "ArrowRight") { e.preventDefault(); stepNav(1); }
      if (e.key === "ArrowLeft") { e.preventDefault(); stepNav(-1); }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [stepNav, person]);

  const colsFor = (n) => (n > 10 ? 3 : n > 5 ? 2 : 1);

  return (
    <section className="honors" id="honors" ref={sectionRef} aria-label={t.honorsTitle.join("")}>
      <div className="honors-aura" aria-hidden="true"></div>
      <header className="honors-head wrap">
        <div className="honors-head__lead">
          <div className="eyebrow eyebrow-white">{t.honorsEyebrow}</div>
          <h2 className="honors-head__title">{t.honorsTitle[0]}<em>{t.honorsTitle[1]}</em></h2>
          <p className="honors-head__sub">{t.honorsSub}</p>
        </div>
        <div className="honors-head__stats" aria-hidden="true">
          <div className="honors-stat"><b>{HONOR_STATS.people}</b><span>{t.honorsPeopleLbl}</span></div>
          <div className="honors-stat"><b>{HONOR_STATS.recs}</b><span>{t.honorsRecsLbl}</span></div>
          <div className="honors-stat"><b>{HONOR_STATS.first}<span className="honors-stat__dash">–</span>{HONOR_STATS.last}</b><span>{t.honorsSpanLbl}</span></div>
        </div>
      </header>

      <div className="honors-stage">
      <div className="honors-viewport" ref={vpRef}>
        <div className="honors-track" ref={trackRef}>
          <div className="honors-cap" aria-hidden="true"></div>
          {stations.map((s, i) => (
            <div
              className="honors-station"
              key={s.year}
              data-year={s.year}
              ref={(el) => (stRefs.current[i] = el)}
              onClick={() => { if (dragSuppress.current) return; markInteracted(); goTo(i); }}
            >
              <div className="honors-rail" aria-hidden="true"></div>
              <div className="honors-station__inner">
                <div className={"honors-panel dense-" + colsFor(s.people.length)} style={{ gridTemplateColumns: "repeat(" + colsFor(s.people.length) + ", minmax(0,1fr))" }}>
                  {s.people.map((p, j) => (
                    <button
                      key={j}
                      className="honor-person"
                      onClick={(e) => { e.stopPropagation(); if (dragSuppress.current) return; setPerson(p.name); }}
                      aria-label={p.name + " — " + p.titles.map((x) => x.label).join(", ")}
                    >
                      <span className="honor-person__name">{p.name}</span>
                      <span className="honor-person__titles">
                        {p.titles.map((x, k) => (
                          <span key={k} className="honor-person__title" data-cat={x.cat}>{x.label}</span>
                        ))}
                      </span>
                    </button>
                  ))}
                </div>
                <div className="honors-node" aria-hidden="true"><span></span></div>
                <div className="honors-yearblock">
                  <div className="honors-year">{s.year}</div>
                  <div className="honors-year__count">{s.people.length} · {t.honorsHonoredLbl}</div>
                </div>
              </div>
            </div>
          ))}
          <div className="honors-cap" aria-hidden="true"></div>
        </div>
      </div>
        <div className={"honors-hint" + (interacted ? " is-hidden" : "")} aria-hidden="true">
          <svg viewBox="0 0 40 16" width="34" height="14" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M9 3L3 8l6 5"/><path d="M31 3l6 5-6 5"/><path d="M3 8h34"/></svg>
          <span>{t.honorsNavHint}</span>
        </div>
      </div>

      <footer className="honors-foot wrap">
        <button className="honors-nav" onClick={() => stepNav(-1)} disabled={active === 0} aria-label={t.honorsPrev}>
          <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M14 6l-6 6 6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
          <span>{t.honorsPrev}</span>
        </button>
        <div className="honors-foot__hint">
          <span className="honors-foot__year">{stations[active] && stations[active].year}</span>
          <span className="honors-foot__sep">·</span>
          <span>{t.honorsClickHint}</span>
        </div>
        <button className="honors-nav honors-nav--next" onClick={() => stepNav(1)} disabled={active === total - 1} aria-label={t.honorsNext}>
          <span>{t.honorsNext}</span>
          <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M10 6l6 6-6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
        </button>
      </footer>

      {person && <HonorModal name={person} lang={lang} t={t} onClose={() => setPerson(null)} />}
    </section>
  );
}

/* ─── App ────────────────────────────────────────────────────────────────── */
/* ─── Sub-navegació de pàgina (shared/components/Subnav.jsx) ──────────── */
const EsbartSubnav = window.EsbartSubnav;
const SOBRE_SUBNAV = {
  ca: [
    { id: "historia", label: "Història" },
    { id: "organitzacio", label: "Organització" },
    { id: "honors", label: "Honors" },
    { id: "distincions", label: "Distincions" },
    { id: "transparencia", label: "Transparència" },
  ],
  es: [
    { id: "historia", label: "Historia" },
    { id: "organitzacio", label: "Organización" },
    { id: "honors", label: "Honores" },
    { id: "distincions", label: "Distinciones" },
    { id: "transparencia", label: "Transparencia" },
  ],
  en: [
    { id: "historia", label: "History" },
    { id: "organitzacio", label: "Organisation" },
    { id: "honors", label: "Honours" },
    { id: "distincions", label: "Awards" },
    { id: "transparencia", label: "Transparency" },
  ],
};

function App() {
  const { lang, setLang, t } = window.EsbartI18n.useI18n(SOBRE_STRINGS);
  const tweaks = useEsbartTweaks();
  const [heroMode] = useState(false); // sober hero is on cream → use light nav, not hero-mode

  useEffect(() => {
    if (t.pageTitle) document.title = `${t.pageTitle} · Esbart Català de Dansaires`;
  }, [lang, t]);

  return (
    <>
      <EsbartNav lang={lang} setLang={setLang} t={t} heroMode={heroMode} current="sobre" />
      <main id="main-content" tabIndex={-1}>
        <AboutHero t={t} />
        <EsbartSubnav items={SOBRE_SUBNAV[lang] || SOBRE_SUBNAV.ca} />
        <AboutClosing t={t} />
        <AboutHistory t={t} />
        <AboutManifest t={t} />
        <AboutMission t={t} />
        <AboutTeam t={t} />
        <AboutMasters t={t} />
        <AboutHonors t={t} lang={lang} />
        <AboutBodies t={t} />
        <AboutSeat t={t} />
        <AboutRecog t={t} />
        <AboutTransp t={t} />
      </main>
      <EsbartFooter t={t} />
      <EsbartTweaksPanel {...tweaks} />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<App />);
