/* BoatsFun — Page Catalogue (bateaux.html)
   Grille complète des bateaux + filtres (recherche texte, type, capacité, fourchette de prix).
   Consomme window.BFBoats (BOATS, TYPES) et réutilise Header/Footer partagés. */

(function () {
  const { I, Photo } = window.BF;
  const { BOATS, TYPES, TIME_SLOTS, getRegions, areCombinable, blockTotal, depositFor, startingPriceLabel } = window.BFBoats;

  // Tranches de capacité
  const CAPS = [
    { id: "all",  label: "Toutes",   min: 0,  max: 999 },
    { id: "1-4",  label: "1-4 pers", min: 1,  max: 4   },
    { id: "5-8",  label: "5-8 pers", min: 5,  max: 8   },
    { id: "9-12", label: "9-12 pers",min: 9,  max: 12  },
    { id: "13+",  label: "13+ pers", min: 13, max: 999 }
  ];

  const SORTS = [
    { id: "popular",   label: "Recommandés" },
    { id: "price-asc", label: "Prix : moins cher au plus cher" },
    { id: "price-desc",label: "Prix : plus cher au moins cher" },
    { id: "cap-desc",  label: "Capacité" }
  ];

  // localStorage key pour persister la sélection combinée entre catalogue ↔ checkout
  const COMBINE_KEY = "bf.combine.selection";

  function loadSelection() {
    try { return JSON.parse(localStorage.getItem(COMBINE_KEY)) || { slugs: [], ctx: {} }; }
    catch (e) { return { slugs: [], ctx: {} }; }
  }
  function saveSelection(data) {
    try { localStorage.setItem(COMBINE_KEY, JSON.stringify(data)); } catch (e) {}
  }

  const styles = `
.bf .cat-hero { background:linear-gradient(180deg, #002244 0%, #003a66 100%); color:#fff; padding:64px 0 56px; }
.bf .cat-hero .eyebrow { color:var(--teal); }
.bf .cat-hero h1 { font-family:'Poppins', sans-serif; font-size:48px; line-height:1.1; font-weight:800; color:#fff; margin:14px 0 14px; letter-spacing:-1.2px; }
.bf .cat-hero p.lead { font-size:17px; line-height:1.55; color:rgba(255,255,255,.82); max-width:640px; }
.bf .cat-hero .ch-meta { display:flex; gap:18px; margin-top:22px; flex-wrap:wrap; color:rgba(255,255,255,.7); font-size:13.5px; }
.bf .cat-hero .ch-meta span { display:inline-flex; align-items:center; gap:8px; }
.bf .cat-hero .ch-meta svg { color:var(--teal); width:16px; height:16px; }

/* Bloc filtres */
.bf .cat-filters { background:#fff; border:1px solid var(--hair); border-radius:18px; box-shadow:0 8px 24px -16px rgba(0,34,68,.18); padding:18px 20px; margin-top:-36px; position:relative; z-index:2; }
.bf .cf-row { display:grid; grid-template-columns: 1.6fr 1fr 1fr 1fr 1fr; gap:14px; align-items:end; }
.bf .cf-row-2 { display:grid; grid-template-columns: 1fr auto; gap:14px; align-items:center; margin-top:14px; }
.bf .cf-field { display:flex; flex-direction:column; gap:6px; min-width:0; }
.bf .cf-field label { font-family:'Inter', sans-serif; font-size:11.5px; font-weight:700; letter-spacing:1.4px; text-transform:uppercase; color:var(--muted); }
.bf .cf-search { display:flex; align-items:center; gap:10px; background:var(--sea-mist); border:1px solid var(--hair); border-radius:12px; padding:10px 14px; }
.bf .cf-search svg { color:var(--navy); width:18px; height:18px; flex-shrink:0; }
.bf .cf-search input { flex:1; background:transparent; border:none; outline:none; font-family:'Inter', sans-serif; font-size:14.5px; color:var(--navy); min-width:0; }
.bf .cf-search input::placeholder { color:var(--muted); }
.bf .cf-select { background:var(--sea-mist); border:1px solid var(--hair); border-radius:12px; padding:11px 14px; font-family:'Inter', sans-serif; font-size:14px; color:var(--navy); font-weight:500; outline:none; cursor:pointer; appearance:none; background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%23002244' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>"); background-repeat:no-repeat; background-position:right 14px center; padding-right:38px; }
.bf .cf-reset { background:transparent; border:none; color:var(--muted); font-family:'Inter', sans-serif; font-weight:600; font-size:13px; cursor:pointer; padding:12px 4px; white-space:nowrap; transition:color .15s; }
.bf .cf-reset:hover { color:var(--orange); }
.bf .cf-input { background:var(--sea-mist); border:1px solid var(--hair); border-radius:12px; padding:11px 14px; font-family:'Inter', sans-serif; font-size:14px; color:var(--navy); font-weight:500; outline:none; width:100%; min-width:0; }
.bf .cf-input::placeholder { color:var(--muted); }

/* Combiner toggle */
.bf .cf-combine { display:flex; align-items:flex-start; gap:14px; background:linear-gradient(135deg, #002244 0%, #003a66 100%); color:#fff; border-radius:14px; padding:14px 18px; }
.bf .cf-combine .ccb-text { flex:1; min-width:0; }
.bf .cf-combine .ccb-text strong { display:block; font-family:'Inter', sans-serif; font-weight:700; font-size:14px; letter-spacing:.01em; color:#fff; }
.bf .cf-combine .ccb-text span { display:block; font-size:12.5px; color:rgba(255,255,255,.72); margin-top:3px; line-height:1.4; }
.bf .cf-combine .ccb-switch { position:relative; width:46px; height:26px; flex-shrink:0; cursor:pointer; }
.bf .cf-combine .ccb-switch input { position:absolute; opacity:0; width:0; height:0; }
.bf .cf-combine .ccb-track { position:absolute; inset:0; background:rgba(255,255,255,.22); border-radius:999px; transition:background .2s; }
.bf .cf-combine .ccb-thumb { position:absolute; top:3px; left:3px; width:20px; height:20px; background:#fff; border-radius:50%; transition:transform .2s; }
.bf .cf-combine.is-on .ccb-track { background:var(--orange); }
.bf .cf-combine.is-on .ccb-thumb { transform:translateX(20px); }

/* Combine bar (sticky bottom) */
.bf .combine-bar { position:fixed; bottom:18px; left:50%; transform:translate(-50%, 120%); z-index:55; background:#002244; color:#fff; border-radius:16px; box-shadow:0 24px 60px -16px rgba(0,34,68,.5); padding:14px 18px; display:flex; align-items:center; gap:20px; min-width:min(680px, calc(100vw - 28px)); max-width:calc(100vw - 28px); transition:transform .3s ease; }
.bf .combine-bar.is-visible { transform:translate(-50%, 0); }
.bf .combine-bar .cb-info { flex:1; min-width:0; }
.bf .combine-bar .cb-count { font-family:'Inter', sans-serif; font-weight:700; font-size:15px; }
.bf .combine-bar .cb-count b { color:var(--teal); }
.bf .combine-bar .cb-meta { font-family:'Inter', sans-serif; font-size:12.5px; color:rgba(255,255,255,.7); margin-top:2px; }
.bf .combine-bar .cb-clear { background:transparent; border:1px solid rgba(255,255,255,.22); color:#fff; font-family:'Inter', sans-serif; font-size:12.5px; font-weight:600; padding:8px 14px; border-radius:999px; cursor:pointer; transition:all .15s; }
.bf .combine-bar .cb-clear:hover { background:rgba(255,255,255,.1); }
.bf .combine-bar .cb-cta { background:var(--orange); border:none; color:#fff; font-family:'Inter', sans-serif; font-weight:600; font-size:14px; padding:12px 22px; border-radius:999px; cursor:pointer; display:inline-flex; align-items:center; gap:8px; transition:all .2s; box-shadow:var(--cta-shadow-orange); white-space:nowrap; }
.bf .combine-bar .cb-cta:hover:not(:disabled) { background:#FF9420; transform:translateY(-2px); }
.bf .combine-bar .cb-cta:disabled { opacity:.45; cursor:not-allowed; }

/* Carte : bouton combiner + state sélectionné / désactivé */
.bf .cat-card .cc-combine-btn { width:100%; margin-top:10px; background:#fff; border:1.5px solid var(--navy); color:var(--navy); font-family:'Inter', sans-serif; font-weight:600; font-size:13px; padding:9px 12px; border-radius:999px; cursor:pointer; transition:all .18s; display:inline-flex; align-items:center; justify-content:center; gap:6px; }
.bf .cat-card .cc-combine-btn:hover { background:var(--navy); color:#fff; }
.bf .cat-card.is-selected { border-color:var(--orange); box-shadow:0 0 0 2px var(--orange) inset, 0 18px 40px -20px rgba(255,130,0,.35); }
.bf .cat-card.is-selected .cc-combine-btn { background:var(--orange); border-color:var(--orange); color:#fff; }
.bf .cat-card.is-incompatible { opacity:.55; }
.bf .cat-card.is-incompatible .cc-combine-btn { background:transparent; border-color:var(--hair); color:var(--muted); cursor:not-allowed; }
.bf .cat-card.is-incompatible .cc-combine-btn:hover { background:transparent; color:var(--muted); }
.bf .cat-card .cc-incompatible-note { font-size:11.5px; color:var(--muted); margin-top:6px; font-style:italic; }

/* Pills filtres (type) */
.bf .cat-pills { display:flex; gap:10px; flex-wrap:wrap; margin-top:14px; padding-top:14px; border-top:1px dashed var(--hair); }
.bf .cat-pill { background:#fff; border:1px solid var(--hair); border-radius:999px; padding:9px 18px; font-family:'Inter', sans-serif; font-size:13.5px; font-weight:600; color:var(--navy); cursor:pointer; transition:all .18s ease; }
.bf .cat-pill:hover { border-color:var(--navy); }
.bf .cat-pill.active { background:var(--navy); color:#fff; border-color:var(--navy); }

/* Toolbar : résultats + tri */
.bf .cat-toolbar { display:flex; justify-content:space-between; align-items:center; margin-top:32px; margin-bottom:18px; gap:14px; flex-wrap:wrap; }
.bf .cat-toolbar .ct-count { font-family:'Inter', sans-serif; font-size:14.5px; color:var(--body); }
.bf .cat-toolbar .ct-count b { color:var(--navy); font-weight:700; }
.bf .cat-toolbar .ct-sort { display:flex; align-items:center; gap:10px; font-family:'Inter', sans-serif; font-size:13.5px; color:var(--muted); }

/* Grille bateaux */
.bf .cat-section { padding:0 0 var(--section-pad); }
.bf .cat-grid { display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:22px; }
.bf .cat-card { display:flex; flex-direction:column; background:#fff; border:1px solid var(--hair); border-radius:18px; overflow:hidden; text-decoration:none; color:inherit; transition:transform .25s ease, box-shadow .25s ease, border-color .25s ease; }
.bf .cat-card:hover { transform:translateY(-4px); box-shadow:0 18px 40px -20px rgba(0,34,68,.22); border-color:transparent; }
.bf .cat-card .cc-imgwrap { position:relative; aspect-ratio:16/11; overflow:hidden; background:var(--sea-mist); }
.bf .cat-card .cc-imgwrap img { width:100%; height:100%; object-fit:cover; display:block; transition:transform .5s ease; }
.bf .cat-card:hover .cc-imgwrap img { transform:scale(1.05); }
.bf .cat-card .cc-badges { position:absolute; top:12px; left:12px; display:flex; gap:6px; flex-wrap:wrap; }
.bf .cat-card .cc-badge { background:#fff; color:var(--navy); font-family:'Inter', sans-serif; font-size:11px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; padding:5px 10px; border-radius:999px; box-shadow:0 2px 6px rgba(0,34,68,.15); }
.bf .cat-card .cc-badge.is-orange { background:var(--orange); color:#fff; }
.bf .cat-card .cc-type { position:absolute; bottom:12px; right:12px; background:rgba(0,34,68,.85); color:#fff; backdrop-filter:blur(8px); font-family:'Inter', sans-serif; font-size:11.5px; font-weight:600; padding:5px 11px; border-radius:999px; }
.bf .cat-card .cc-body { padding:18px 20px 20px; display:flex; flex-direction:column; gap:8px; flex:1; }
.bf .cat-card h3 { font-family:'Poppins', sans-serif; font-size:18px; font-weight:700; color:var(--navy); line-height:1.25; letter-spacing:-.3px; }
.bf .cat-card .cc-loc { display:inline-flex; align-items:center; gap:6px; font-size:13.5px; color:var(--body); }
.bf .cat-card .cc-loc svg { width:14px; height:14px; color:var(--teal); }
.bf .cat-card .cc-meta { display:flex; gap:14px; margin-top:4px; font-size:13px; color:var(--muted); }
.bf .cat-card .cc-meta span { display:inline-flex; align-items:center; gap:5px; }
.bf .cat-card .cc-meta svg { width:13px; height:13px; }
.bf .cat-card .cc-foot { display:flex; justify-content:space-between; align-items:center; margin-top:auto; padding-top:14px; border-top:1px dashed var(--hair); }
.bf .cat-card .cc-price { font-family:'Poppins', sans-serif; font-size:20px; font-weight:700; color:var(--navy); }
.bf .cat-card .cc-price .pu { font-family:'Inter', sans-serif; font-size:12.5px; font-weight:500; color:var(--muted); margin-left:3px; }
.bf .cat-card .cc-cta { font-family:'Inter', sans-serif; font-size:13px; font-weight:600; color:var(--orange); display:inline-flex; align-items:center; gap:6px; transition:gap .2s ease; }
.bf .cat-card:hover .cc-cta { gap:10px; }
.bf .cat-card .cc-cta svg { width:14px; height:14px; }

/* Empty state */
.bf .cat-empty { text-align:center; padding:80px 24px; background:#fff; border:1px dashed var(--hair); border-radius:18px; }
.bf .cat-empty h3 { font-family:'Poppins', sans-serif; font-size:22px; color:var(--navy); margin-bottom:8px; }
.bf .cat-empty p { color:var(--body); margin-bottom:18px; }

/* ============ Responsive ============ */
@media (max-width: 1180px) {
  .bf .cat-grid { grid-template-columns:repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1180px) {
  .bf .cf-row { grid-template-columns: 1fr 1fr 1fr; }
  .bf .cf-row .cf-search-field { grid-column: 1 / -1; }
}
@media (max-width: 1024px) {
  .bf .cat-hero h1 { font-size:40px; }
  .bf .cf-row { grid-template-columns: 1fr 1fr; }
  .bf .cf-row-2 { grid-template-columns: 1fr; }
}
@media (max-width: 860px) {
  .bf .cat-hero { padding:48px 0 56px; }
  .bf .cat-hero h1 { font-size:32px; }
  .bf .cat-hero p.lead { font-size:15.5px; }
  .bf .cat-filters { margin-top:-28px; padding:16px; }
  .bf .cf-row { grid-template-columns: 1fr; gap:12px; }
  .bf .cat-pill { padding:8px 14px; font-size:13px; }
  .bf .cat-grid { grid-template-columns:1fr; gap:18px; }
  .bf .cat-toolbar { margin-top:24px; }
  .bf .combine-bar { left:14px; right:14px; transform:translate(0, 120%); min-width:0; flex-direction:column; align-items:stretch; gap:12px; padding:14px; }
  .bf .combine-bar.is-visible { transform:translate(0, 0); }
  .bf .combine-bar .cb-cta { width:100%; justify-content:center; }
  .bf .combine-bar .cb-clear { align-self:flex-end; }
}
@media (max-width: 500px) {
  .bf .cat-hero h1 { font-size:27px; }
  .bf .cat-hero p.lead { font-size:14.5px; }
  .bf .cat-card .cc-body { padding:16px; }
  .bf .cat-card h3 { font-size:16.5px; }
}
`;

  function BoatCard({ b, combineMode, isSelected, isCompatible, incompatibleReason, onToggleSelect }) {
    const href = `/bateau?id=${encodeURIComponent(b.slug)}`;
    const cardClass = [
      "cat-card",
      combineMode && isSelected ? "is-selected" : "",
      combineMode && !isCompatible ? "is-incompatible" : ""
    ].filter(Boolean).join(" ");

    const handleCombineClick = (e) => {
      e.preventDefault();
      e.stopPropagation();
      if (!isCompatible) return;
      onToggleSelect(b.slug);
    };

    return (
      <a className={cardClass} href={href}>
        <div className="cc-imgwrap">
          <img src={b.img} alt={b.name} loading="lazy" />
          <span className="cc-type">{b.type}</span>
        </div>
        <div className="cc-body">
          <h3>{b.name}</h3>
          <span className="cc-loc"><I.pin />{b.loc}</span>
          <div className="cc-meta">
            <span><I.users />{b.pers} pers.</span>
            <span><I.ruler />{b.length_ft} pi</span>
            {b.captain && <span><I.compass />Capitaine sur demande</span>}
          </div>
          <div className="cc-foot">
            <span className="cc-price">{startingPriceLabel(b.lowestPricePerHour)}</span>
            <span className="cc-cta">Voir <I.arrowR /></span>
          </div>
          {combineMode && (
            <React.Fragment>
              <button type="button" className="cc-combine-btn" onClick={handleCombineClick} disabled={!isCompatible}>
                {isSelected ? (<>✓ Sélectionné</>) : (isCompatible ? (<>+ Ajouter à la combinaison</>) : (<>Non compatible</>))}
              </button>
              {!isCompatible && incompatibleReason && (
                <span className="cc-incompatible-note">{incompatibleReason}</span>
              )}
            </React.Fragment>
          )}
        </div>
      </a>
    );
  }

  // Lecture des paramètres URL (homepage redirige avec ?region=...&date=...&slot=...&combine=1)
  function readQueryParams() {
    if (typeof window === "undefined") return {};
    const p = new URLSearchParams(window.location.search);
    return {
      region:   p.get("region")  || "",
      cap:      p.get("cap")     || "all",
      date:     p.get("date")    || "",
      timeSlot: p.get("slot")    || "",
      combine:  p.get("combine") === "1"
    };
  }

  function BFPageCatalogue() {
    const initial = React.useMemo(readQueryParams, []);
    const regions = React.useMemo(() => getRegions(), []);

    const [type, setType]         = React.useState("Tous");
    const [region, setRegion]     = React.useState(initial.region || "");
    const [cap, setCap]           = React.useState(initial.cap || "all");
    const [date, setDate]         = React.useState(initial.date || "");
    const [timeSlot, setTimeSlot] = React.useState(initial.timeSlot || "");
    const [combine, setCombine]   = React.useState(!!initial.combine);
    const [sort, setSort]         = React.useState("popular");
    const [selectedSlugs, setSelectedSlugs] = React.useState(() => {
      const s = loadSelection();
      return Array.isArray(s.slugs) ? s.slugs : [];
    });

    // Persiste la sélection + contexte (date / plage / région) pour la page checkout combinée
    React.useEffect(() => {
      saveSelection({ slugs: selectedSlugs, ctx: { region, date, timeSlot } });
    }, [selectedSlugs, region, date, timeSlot]);

    // Reset sélection quand on quitte le mode combine
    React.useEffect(() => {
      if (!combine && selectedSlugs.length > 0) {
        setSelectedSlugs([]);
      }
    }, [combine]);

    const filtered = React.useMemo(() => {
      let list = BOATS.slice();
      if (type !== "Tous") list = list.filter((b) => b.type === type);
      if (region) list = list.filter((b) => b.region === region);
      const capRule = CAPS.find((c) => c.id === cap);
      if (capRule && cap !== "all") list = list.filter((b) => b.pers >= capRule.min && b.pers <= capRule.max);
      if (timeSlot) list = list.filter((b) => (b.timeSlots || []).includes(timeSlot));
      // En mode combine : ne montrer que les bateaux éligibles à la combinaison
      if (combine) list = list.filter((b) => b.canCombineWithOtherBoats);
      if (sort === "price-asc")   list.sort((a, b) => a.lowestPricePerHour - b.lowestPricePerHour);
      if (sort === "price-desc")  list.sort((a, b) => b.lowestPricePerHour - a.lowestPricePerHour);
      if (sort === "cap-desc")    list.sort((a, b) => b.pers - a.pers);
      return list;
    }, [type, region, cap, timeSlot, sort, combine]);

    const selectedBoats = React.useMemo(
      () => selectedSlugs.map((s) => BOATS.find((b) => b.slug === s)).filter(Boolean),
      [selectedSlugs]
    );

    // Calcule la compatibilité de chaque bateau avec la sélection courante
    const compatibilityFor = React.useCallback((b) => {
      if (!combine) return { ok: true };
      if (!b.canCombineWithOtherBoats) return { ok: false, reason: "Ce bateau n'accepte pas les sorties combinées." };
      if (selectedSlugs.includes(b.slug)) return { ok: true };
      // Si rien n'est sélectionné encore, tout candidat est compatible (si region/timeSlot du contexte cadrent)
      if (selectedBoats.length === 0) {
        if (region && b.region !== region) return { ok: false, reason: "Région différente de votre filtre." };
        if (timeSlot && !(b.timeSlots || []).includes(timeSlot)) return { ok: false, reason: "Plage horaire indisponible." };
        return { ok: true };
      }
      // Sinon : doit être compatible avec TOUS les bateaux déjà sélectionnés
      const ctx = timeSlot ? { timeSlot } : null;
      const allCompat = selectedBoats.every((s) => areCombinable(s, b, ctx));
      if (!allCompat) return { ok: false, reason: "Pas dans la même zone ou plage horaire que la sélection." };
      return { ok: true };
    }, [combine, selectedSlugs, selectedBoats, region, timeSlot]);

    const toggleSelect = (slug) => {
      setSelectedSlugs((prev) => prev.includes(slug) ? prev.filter((s) => s !== slug) : prev.concat(slug));
    };
    const clearSelection = () => setSelectedSlugs([]);

    const totalPrice   = selectedBoats.reduce((sum, b) => sum + blockTotal(b), 0);
    const totalDeposit = selectedBoats.reduce((sum, b) => sum + depositFor(b), 0);

    const reset = () => {
      setType("Tous"); setRegion(""); setCap("all");
      setDate(""); setTimeSlot(""); setCombine(false); setSort("popular");
      setSelectedSlugs([]);
    };

    const goCheckoutCombine = (e) => {
      e.preventDefault();
      if (selectedSlugs.length < 2) return;
      const params = new URLSearchParams();
      params.set("slugs", selectedSlugs.join(","));
      if (region)   params.set("region", region);
      if (date)     params.set("date", date);
      if (timeSlot) params.set("slot", timeSlot);
      window.BF.nav(`/checkout-combine?${params.toString()}`);
    };

    return (
      <div className="bf" data-screen-label="Catalogue bateaux">
        <style>{styles}</style>

        <window.BFHeader />

        {/* HERO */}
        <section className="cat-hero">
          <div className="container">
            <span className="eyebrow">Catalogue complet</span>
            <h1>Trouvez le bateau parfait à Montréal.</h1>
            <p className="lead">Pontons, yachts, voiliers, speedboats. Réservez en quelques clics ou faites une offre — dépôt 100 % remboursable si le propriétaire refuse.</p>
            <div className="ch-meta">
              <span><I.shield />Paiement sécurisé Stripe</span>
              <span><I.refund />Dépôt 100 % remboursable</span>
              <span><I.pin />Montréal et région</span>
            </div>
          </div>
        </section>

        {/* FILTRES */}
        <div className="container">
          <div className="cat-filters">
            <div className="cf-row">

              <div className="cf-field">
                <label htmlFor="bf-region">Région</label>
                <select id="bf-region" className="cf-select" value={region} onChange={(e) => setRegion(e.target.value)}>
                  <option value="">Toutes</option>
                  {regions.map((r) => <option key={r} value={r}>{r}</option>)}
                </select>
              </div>
              <div className="cf-field">
                <label htmlFor="bf-cap">Capacité</label>
                <select id="bf-cap" className="cf-select" value={cap} onChange={(e) => setCap(e.target.value)}>
                  {CAPS.map((c) => <option key={c.id} value={c.id}>{c.label}</option>)}
                </select>
              </div>
              <div className="cf-field">
                <label htmlFor="bf-date">Date</label>
                <input id="bf-date" type="date" className="cf-input" value={date} onChange={(e) => setDate(e.target.value)} />
              </div>
              <div className="cf-field">
                <label htmlFor="bf-slot">Plage horaire</label>
                <select id="bf-slot" className="cf-select" value={timeSlot} onChange={(e) => setTimeSlot(e.target.value)}>
                  <option value="">Toutes</option>
                  {TIME_SLOTS.map((s) => <option key={s} value={s}>{s}</option>)}
                </select>
              </div>
            </div>

            <div className="cf-row-2">
              <label className={`cf-combine ${combine ? "is-on" : ""}`}>
                <div className="ccb-text">
                  <strong>Combiner plusieurs bateaux</strong>
                  <span>Pour les groupes qui veulent réserver 2 bateaux ou plus pouvant se rejoindre sur l'eau.</span>
                </div>
                <span className="ccb-switch">
                  <input type="checkbox" checked={combine} onChange={(e) => setCombine(e.target.checked)} />
                  <span className="ccb-track"></span>
                  <span className="ccb-thumb"></span>
                </span>
              </label>
              <button type="button" className="cf-reset" onClick={reset}>Réinitialiser</button>
            </div>

            <div className="cat-pills" role="tablist" aria-label="Filtres par type">
              {TYPES.map((t) => (
                <button key={t} type="button" role="tab" className={`cat-pill ${type === t ? "active" : ""}`} onClick={() => setType(t)}>{t}</button>
              ))}
            </div>
          </div>
        </div>

        {/* TOOLBAR + GRILLE */}
        <section className="container cat-section">
          <div className="cat-toolbar">
            <span className="ct-count">
              <b>{filtered.length}</b> bateau{filtered.length > 1 ? "x" : ""} disponible{filtered.length > 1 ? "s" : ""}
              {combine && <> · mode combinaison actif</>}
            </span>
            <span className="ct-sort">
              Trier par
              <select aria-label="Trier par" className="cf-select" value={sort} onChange={(e) => setSort(e.target.value)}>
                {SORTS.map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}
              </select>
            </span>
          </div>

          {filtered.length === 0 ? (
            <div className="cat-empty">
              <h3>Aucun bateau ne correspond à vos critères</h3>
              <p>Essayez d'élargir votre recherche ou de réinitialiser les filtres.</p>
              <button type="button" className="btn-outline" onClick={reset}>Réinitialiser les filtres</button>
            </div>
          ) : (
            <div className="cat-grid">
              {filtered.map((b) => {
                const compat = compatibilityFor(b);
                return (
                  <BoatCard
                    key={b.slug}
                    b={b}
                    combineMode={combine}
                    isSelected={selectedSlugs.includes(b.slug)}
                    isCompatible={compat.ok}
                    incompatibleReason={compat.reason}
                    onToggleSelect={toggleSelect}
                  />
                );
              })}
            </div>
          )}
        </section>

        {/* COMBINE BAR (sticky bottom) */}
        <div className={`combine-bar ${combine && selectedSlugs.length > 0 ? "is-visible" : ""}`} role="region" aria-label="Réservation combinée">
          <div className="cb-info">
            <div className="cb-count"><b>{selectedSlugs.length}</b> bateau{selectedSlugs.length > 1 ? "x" : ""} sélectionné{selectedSlugs.length > 1 ? "s" : ""}</div>
            <div className="cb-meta">
              Total estimé : <b className="cb-price">{totalPrice} $</b> · Dépôt total : {totalDeposit} $
              {selectedSlugs.length < 2 && <> · sélectionnez au moins 2 bateaux</>}
            </div>
          </div>
          <button type="button" className="cb-clear" onClick={clearSelection}>Vider</button>
          <button type="button" className="cb-cta" disabled={selectedSlugs.length < 2} onClick={goCheckoutCombine}>
            Continuer avec ces bateaux <I.arrowR />
          </button>
        </div>

        <window.BFFooter />
      </div>
    );
  }

  window.BFPageCatalogue = BFPageCatalogue;
})();
