{"id":10183,"date":"2026-07-02T10:34:19","date_gmt":"2026-07-02T10:34:19","guid":{"rendered":"https:\/\/www.animcloud.fr\/?page_id=10183"},"modified":"2026-07-02T10:34:21","modified_gmt":"2026-07-02T10:34:21","slug":"foot","status":"publish","type":"page","link":"https:\/\/www.animcloud.fr\/en\/foot\/","title":{"rendered":"foot"},"content":{"rendered":"\n<script data-wp-block-html=\"js\">\n          {match.away}{winner === match.away && \" \u2713\"}\n        <\/div>\n      <\/div>\n \n      {match.needsTiebreak && (\n        <div style={{ marginTop: 6, background: \"#1a1200\", border: `1px solid ${COLORS.gold}`, borderRadius: 8, padding: \"10px 14px\", display: \"flex\", alignItems: \"center\", gap: 10, flexWrap: \"wrap\" }}>\n          <span style={{ fontSize: 12, color: COLORS.gold, fontWeight: 700 }}>\u26a0 \u00c9galit\u00e9 \u2014 qui passe (tirs au but) ?<\/span>\n          <button onClick={() => onTiebreak(\"home\")} style={{ background: COLORS.greenMuted, border: `1px solid ${COLORS.green}`, color: COLORS.green, padding: \"5px 12px\", borderRadius: 6, cursor: \"pointer\", fontSize: 12, fontWeight: 700 }}>\n            {match.home}\n          <\/button>\n          <button onClick={() => onTiebreak(\"away\")} style={{ background: COLORS.greenMuted, border: `1px solid ${COLORS.green}`, color: COLORS.green, padding: \"5px 12px\", borderRadius: 6, cursor: \"pointer\", fontSize: 12, fontWeight: 700 }}>\n            {match.away}\n          <\/button>\n        <\/div>\n      )}\n    <\/div>\n  );\n}\n \n\/\/ \u2500\u2500\u2500 PETITS COMPOSANTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction SectionTitle({ icon, title, subtitle, noMargin }) {\n  return (\n    <div style={{ marginBottom: noMargin ? 0 : 24 }}>\n      <div style={{ fontFamily: \"'Barlow Condensed', sans-serif\", fontSize: 28, fontWeight: 900, color: COLORS.white, letterSpacing: 0.5 }}>\n        {icon} {title}\n      <\/div>\n      {subtitle && <div style={{ fontSize: 13, color: COLORS.gray, marginTop: 4 }}>{subtitle}<\/div>}\n    <\/div>\n  );\n}\n \nfunction Card({ title, children, error }) {\n  return (\n    <div style={{ background: COLORS.card, border: `1px solid ${error ? COLORS.red : COLORS.cardBorder}`, borderRadius: 12, padding: \"20px 20px 16px\", marginBottom: 0 }}>\n      {title && <div style={{ fontFamily: \"'Barlow Condensed', sans-serif\", fontSize: 16, fontWeight: 700, color: COLORS.gray, letterSpacing: 1, textTransform: \"uppercase\", marginBottom: 14, borderBottom: `1px solid ${COLORS.cardBorder}`, paddingBottom: 10 }}>{title}<\/div>}\n      {children}\n    <\/div>\n  );\n}\n \nfunction Field({ label, children, error }) {\n  return (\n    <div>\n      <label style={{ display: \"block\", fontSize: 12, color: COLORS.gray, marginBottom: 6, letterSpacing: 0.5, textTransform: \"uppercase\" }}>{label}<\/label>\n      {children}\n      {error && <div style={{ color: COLORS.red, fontSize: 12, marginTop: 4 }}>{error}<\/div>}\n    <\/div>\n  );\n}\n \nfunction Tag({ icon, text }) {\n  return (\n    <span style={{ background: COLORS.greenMuted, border: `1px solid ${COLORS.greenDim}`, color: COLORS.green, padding: \"3px 10px\", borderRadius: 20, fontSize: 12, fontWeight: 600 }}>\n      {icon} {text}\n    <\/span>\n  );\n}\n \nfunction EmptyState({ icon, text }) {\n  return (\n    <div style={{ textAlign: \"center\", padding: \"60px 20px\", color: COLORS.gray }}>\n      <div style={{ fontSize: 48, marginBottom: 14 }}>{icon}<\/div>\n      <div style={{ fontSize: 16 }}>{text}<\/div>\n    <\/div>\n  );\n}\n \nconst inputStyle = (error) => ({\n  width: \"100%\", background: \"#0a200a\", border: `1px solid ${error ? COLORS.red : COLORS.greenDim}`,\n  color: COLORS.white, padding: \"10px 14px\", borderRadius: 8, fontSize: 15, outline: \"none\",\n  transition: \"border-color 0.15s\",\n});\n<\/script>\n\n\n\n<script data-wp-block-html=\"js\">\nimport { useState, useEffect, useCallback } from \"react\";\n \n\/\/ \u2500\u2500\u2500 STORAGE KEY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst STORAGE_KEY = \"tournoi_foot_v1\";\n \n\/\/ \u2500\u2500\u2500 HELPERS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction shuffle(arr) {\n  const a = [...arr];\n  for (let i = a.length - 1; i > 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [a[i], a[j]] = [a[j], a[i]];\n  }\n  return a;\n}\n \nfunction getNextMonday8h15() {\n  const now = new Date();\n  const day = now.getDay(); \/\/ 0=dim, 1=lun\n  const daysUntilMonday = day === 1 ? 7 : (8 - day) % 7 || 7;\n  const next = new Date(now);\n  next.setDate(now.getDate() + daysUntilMonday);\n  next.setHours(20, 15, 0, 0);\n  return next;\n}\n \nfunction isRegistrationOpen() {\n  const now = new Date();\n  const day = now.getDay();\n  if (day !== 1) return true; \/\/ pas lundi \u2192 ouvert\n  const h = now.getHours(), m = now.getMinutes();\n  return h < 20 || (h === 20 &#038;&#038; m < 15);\n}\n \nfunction formatCountdown(ms) {\n  if (ms <= 0) return \"00:00:00\";\n  const s = Math.floor(ms \/ 1000) % 60;\n  const m = Math.floor(ms \/ 60000) % 60;\n  const h = Math.floor(ms \/ 3600000) % 24;\n  const d = Math.floor(ms \/ 86400000);\n  if (d > 0) return `${d}j ${h.toString().padStart(2, \"0\")}h ${m.toString().padStart(2, \"0\")}m`;\n  return `${h.toString().padStart(2, \"0\")}:${m.toString().padStart(2, \"0\")}:${s.toString().padStart(2, \"0\")}`;\n}\n \nfunction generateSchedule(teams) {\n  const n = teams.length;\n  if (n < 2) return { format: null, days: [] };\n \n  \/\/ \u2500\u2500\u2500 FORMATS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  \/\/ 2\u20134 \u00e9quipes : championnat (round-robin)\n  \/\/ 5\u20138 \u00e9quipes : poules + \u00e9lim directe\n  \/\/ 9+ \u00e9quipes : \u00e9lim directe pure (tour pr\u00e9liminaire minimal si besoin)\n \n  if (n <= 4) return buildChampionnat(teams);\n  if (n <= 8) return buildPoulesPlusElim(teams);\n  return buildElimDirecte(teams);\n}\n \n\/\/ R\u00e9partit une liste de matchs sur des jours en garantissant toujours au\n\/\/ moins 2 matchs par jour utilis\u00e9 (jamais de journ\u00e9e \"orpheline\" avec 1 seul\n\/\/ match) \u2014 n'utilise que le nombre de jours n\u00e9cessaire, jamais plus.\nfunction packMatchesIntoDays(matches, dayNames) {\n  const total = matches.length;\n  if (total === 0) return [];\n  if (total === 1) return [{ day: dayNames[0], matches }];\n \n  const maxDays = dayNames.length;\n  const perDay = Math.max(2, Math.ceil(total \/ maxDays));\n  const chunks = [];\n  let idx = 0;\n  while (idx < total) {\n    const end = Math.min(idx + perDay, total);\n    chunks.push(matches.slice(idx, end));\n    idx = end;\n  }\n  \/\/ Si le dernier paquet a moins de 2 matchs, on le fusionne avec le pr\u00e9c\u00e9dent\n  if (chunks.length > 1 && chunks[chunks.length - 1].length < 2) {\n    const last = chunks.pop();\n    chunks[chunks.length - 1] = chunks[chunks.length - 1].concat(last);\n  }\n  \/\/ Si jamais on d\u00e9passe le nombre de jours dispo, on tasse le surplus sur le dernier jour\n<\/script>\n\n<iframe src=\"https:\/\/animcloud.fr\/footournois\/\" style=\"width:100%; height:100vh; border:none;\"><\/iframe>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-10183","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/10183","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/comments?post=10183"}],"version-history":[{"count":8,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/10183\/revisions"}],"predecessor-version":[{"id":10199,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/10183\/revisions\/10199"}],"wp:attachment":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/media?parent=10183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}