Compare commits
52 Commits
573bc74cfa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 63d4ed9470 | |||
| 5138e61854 | |||
| 867d3c96b1 | |||
| b727c110a2 | |||
| a10a876e0c | |||
| 8c639a83a9 | |||
| d6a026287a | |||
| 81d54e3e57 | |||
| 7f49ca1626 | |||
| 2c435472f5 | |||
| 202d4460e9 | |||
| b2e4b63729 | |||
| 4e4c72da7f | |||
| cfb778776e | |||
| 09020b7aef | |||
| dca3a66206 | |||
| 275dda65e0 | |||
| 2a57be6e2f | |||
| 63108cb5a1 | |||
| d982ff1068 | |||
| 6811fc8161 | |||
| edaca815a7 | |||
| 40618d2953 | |||
| 7c910e9199 | |||
| 1d94f805fd | |||
| b3eb21e59b | |||
| 87624ae484 | |||
| 6e73cccdff | |||
| a60cf9c604 | |||
| fafb9dce4b | |||
| 4896fe7159 | |||
| 1a99bd8029 | |||
| e9701ce25b | |||
| 4d838e2fb7 | |||
| 7bad12df68 | |||
| 89a9075391 | |||
| 2b3cadfcb5 | |||
| a721de5b23 | |||
| bf931e70c0 | |||
| 6bb6f9be7a | |||
| 6f0acaad4c | |||
| 1985289a37 | |||
| a38b3fa517 | |||
| 49256e83c6 | |||
| 6eec396b8c | |||
| 1cd4ae3bfb | |||
| 597d321a34 | |||
| c9bdc0c5cf | |||
| a4a47b431a | |||
| 4cb27e7b97 | |||
| a106f28257 | |||
| c848d5a7b5 |
@@ -1,7 +1,9 @@
|
|||||||
# football-data.org API-Token (kostenlos: https://www.football-data.org/client/register)
|
# FIFA-API als Primärquelle (kein Token nötig)
|
||||||
# Ohne Token liefert die API nur eingeschränkte Daten.
|
|
||||||
FOOTBALL_DATA_TOKEN=dein_token_hier
|
|
||||||
|
|
||||||
# Polymarket-Slug des WM-Events (Standard: world-cup-2026).
|
# Polymarket-Slug des WM-Events (Standard: world-cup-2026).
|
||||||
# Den genauen Slug findest du in der Polymarket-URL nach /event/.
|
# Den genauen Slug findest du in der Polymarket-URL nach /event/.
|
||||||
POLYMARKET_WC_SLUG=world-cup-2026
|
POLYMARKET_WC_SLUG=world-cup-2026
|
||||||
|
|
||||||
|
# Umami Analytics (selbst gehostet, cookiefrei)
|
||||||
|
# NEXT_PUBLIC_UMAMI_SRC=https://analytics.example.com/script.js
|
||||||
|
# NEXT_PUBLIC_UMAMI_ID=deine-website-id
|
||||||
|
|||||||
1
.gitignore
vendored
@@ -3,3 +3,4 @@ node_modules
|
|||||||
.env
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
*.log
|
*.log
|
||||||
|
testdata
|
||||||
@@ -10,6 +10,12 @@ WORKDIR /app
|
|||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
COPY . .
|
COPY . .
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
ARG NEXT_PUBLIC_UMAMI_SRC
|
||||||
|
ARG NEXT_PUBLIC_UMAMI_ID
|
||||||
|
ENV NEXT_PUBLIC_UMAMI_SRC=${NEXT_PUBLIC_UMAMI_SRC}
|
||||||
|
ENV NEXT_PUBLIC_UMAMI_ID=${NEXT_PUBLIC_UMAMI_ID}
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# --- Stufe 3: Runtime (standalone) ---
|
# --- Stufe 3: Runtime (standalone) ---
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useCallback } from "react";
|
import { useMemo, useState, useCallback } from "react";
|
||||||
import { GroupTable, Match, Team, ThirdPlaceRow } from "@/lib/types";
|
import { GroupTable, Match, Team, ThirdPlaceRow, teamName } from "@/lib/types";
|
||||||
import { ThirdAssignment, orderedRound } from "@/lib/bracket";
|
import { ThirdAssignment, orderedRound } from "@/lib/bracket";
|
||||||
import { resolveBracket, ResolvedSide, ResolvedTie } from "@/lib/resolve-bracket";
|
import { resolveBracket, ResolvedSide, ResolvedTie } from "@/lib/resolve-bracket";
|
||||||
|
import { Dictionary } from "@/lib/i18n";
|
||||||
|
import { STADIUMS, MATCH_STADIUMS, MATCH_DATES } from "@/lib/stadiums";
|
||||||
import Flag from "./Flag";
|
import Flag from "./Flag";
|
||||||
|
|
||||||
interface TipState { x: number; y: number; text: string }
|
interface TipState { x: number; y: number; text: string }
|
||||||
|
|
||||||
function Side({
|
function Side({
|
||||||
s, prob, teams, onShowTip, onHideTip,
|
s, prob, teams, locale, dict, onShowTip, onHideTip,
|
||||||
}: {
|
}: {
|
||||||
s: ResolvedSide; prob?: number | null; teams: Team[];
|
s: ResolvedSide; prob?: number | null; teams: Team[]; locale: string; dict: Dictionary;
|
||||||
onShowTip: (text: string, x: number, y: number) => void;
|
onShowTip: (text: string, x: number, y: number) => void;
|
||||||
onHideTip: () => void;
|
onHideTip: () => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -32,8 +34,8 @@ function Side({
|
|||||||
{s.teamId ? (
|
{s.teamId ? (
|
||||||
<>
|
<>
|
||||||
<Flag team={team} size={18} />
|
<Flag team={team} size={18} />
|
||||||
<span className="tn">{s.label}</span>
|
<span className="tn">{teamName(team, locale)}</span>
|
||||||
{s.provisional && <span className="prov-mark" title="vorläufig – Gruppe/Zuordnung noch nicht fix">≈</span>}
|
{s.provisional && <span className="prov-mark" title={dict.bracket.provisionalTooltip}>≈</span>}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span className="lbl">{s.label}</span>
|
<span className="lbl">{s.label}</span>
|
||||||
@@ -47,36 +49,71 @@ function Side({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fmtMatchInfo(utcDate?: string, stadiumId?: string, locale: string = "de"): string {
|
||||||
|
if (!utcDate) return "";
|
||||||
|
const intlLocale = locale === "en" ? "en-US" : "de-DE";
|
||||||
|
const d = new Date(utcDate);
|
||||||
|
const dateStr = d.toLocaleDateString(intlLocale, { day: "numeric", month: "numeric" });
|
||||||
|
const timeStr = d.toLocaleTimeString(intlLocale, { hour: "2-digit", minute: "2-digit" });
|
||||||
|
const city = stadiumId ? STADIUMS[stadiumId]?.city : "";
|
||||||
|
const parts = [`${dateStr}`, `${timeStr}`];
|
||||||
|
if (city) parts.push(city);
|
||||||
|
return parts.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
function Tie({
|
function Tie({
|
||||||
tie, teams, isFinal, onShowTip, onHideTip,
|
tie, teams, isFinal, matchInfo, locale, dict, onShowTip, onHideTip,
|
||||||
}: {
|
}: {
|
||||||
tie: ResolvedTie; teams: Team[]; isFinal?: boolean;
|
tie: ResolvedTie; teams: Team[]; isFinal?: boolean;
|
||||||
|
matchInfo?: string;
|
||||||
|
locale: string; dict: Dictionary;
|
||||||
onShowTip: (text: string, x: number, y: number) => void;
|
onShowTip: (text: string, x: number, y: number) => void;
|
||||||
onHideTip: () => void;
|
onHideTip: () => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className={`tie ${isFinal ? "final-tie" : ""}`}>
|
<div className={`tie ${isFinal ? "final-tie" : ""}`}>
|
||||||
<div className="tie-head">Spiel {tie.matchNumber}</div>
|
<div className="match-badge">{tie.matchNumber}</div>
|
||||||
<Side s={tie.home} prob={tie.prob?.home} teams={teams} onShowTip={onShowTip} onHideTip={onHideTip} />
|
<div className="tie-meta">
|
||||||
<Side s={tie.away} prob={tie.prob?.away} teams={teams} onShowTip={onShowTip} onHideTip={onHideTip} />
|
{matchInfo || dict.bracket.match(tie.matchNumber)}
|
||||||
|
</div>
|
||||||
|
<Side s={tie.home} prob={tie.prob?.home} teams={teams} locale={locale} dict={dict} onShowTip={onShowTip} onHideTip={onHideTip} />
|
||||||
|
<Side s={tie.away} prob={tie.prob?.away} teams={teams} locale={locale} dict={dict} onShowTip={onShowTip} onHideTip={onHideTip} />
|
||||||
|
{tie.homePenalty != null && tie.awayPenalty != null && (
|
||||||
|
<div className="tie-meta" style={{ padding: "2px 10px 4px", textAlign: "center" }}>
|
||||||
|
({tie.homePenalty}:{tie.awayPenalty} {dict.bracket.penaltyShootout})
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Bracket({
|
export default function Bracket({
|
||||||
matches, teams, tables, thirds, assignment, annexResolved,
|
matches, teams, tables, thirds, assignment, annexResolved,
|
||||||
preResolved,
|
preResolved, dict, locale,
|
||||||
}: {
|
}: {
|
||||||
matches: Match[]; teams: Team[]; tables: GroupTable[];
|
matches: Match[]; teams: Team[]; tables: GroupTable[];
|
||||||
thirds: ThirdPlaceRow[]; assignment: ThirdAssignment | null; annexResolved: boolean;
|
thirds: ThirdPlaceRow[]; assignment: ThirdAssignment | null; annexResolved: boolean;
|
||||||
preResolved?: { r32: ResolvedTie[]; later: Record<number, ResolvedTie> };
|
preResolved?: { r32: ResolvedTie[]; later: Record<number, ResolvedTie> };
|
||||||
|
dict: Dictionary; locale: string;
|
||||||
}) {
|
}) {
|
||||||
const { r32: r32Array, later } = preResolved ?? resolveBracket(
|
const { r32: r32Array, later } = preResolved ?? resolveBracket(
|
||||||
matches, teams, tables, thirds, assignment, annexResolved,
|
matches, teams, tables, thirds, assignment, annexResolved, undefined, dict,
|
||||||
);
|
);
|
||||||
|
|
||||||
const r32ByNum = new Map(r32Array.map((t) => [t.matchNumber, t]));
|
const r32ByNum = new Map(r32Array.map((t) => [t.matchNumber, t]));
|
||||||
|
|
||||||
|
// Slot-Nummer → formatierte Anzeige (Datum/Uhrzeit aus MATCH_DATES, Stadt aus MATCH_STADIUMS)
|
||||||
|
const matchMeta = useMemo(() => {
|
||||||
|
const meta = new Map<number, string>();
|
||||||
|
for (let n = 73; n <= 104; n++) {
|
||||||
|
const utcDate = MATCH_DATES[n];
|
||||||
|
const stadiumId = MATCH_STADIUMS[n];
|
||||||
|
const info = fmtMatchInfo(utcDate, stadiumId, locale);
|
||||||
|
if (info) meta.set(n, info);
|
||||||
|
}
|
||||||
|
return meta;
|
||||||
|
}, [locale]);
|
||||||
|
|
||||||
const sfOrder = orderedRound([104]);
|
const sfOrder = orderedRound([104]);
|
||||||
const qfOrder = orderedRound(sfOrder);
|
const qfOrder = orderedRound(sfOrder);
|
||||||
const r16Order = orderedRound(qfOrder);
|
const r16Order = orderedRound(qfOrder);
|
||||||
@@ -96,48 +133,48 @@ export default function Bracket({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="bracket-banner">
|
<div className="bracket-banner">
|
||||||
<span className="k">Annex-C-Zuordnung der Drittplatzierten:</span>
|
<span className="k">{dict.bracket.annexHeader}</span>
|
||||||
<span className="v">
|
<span className="v">
|
||||||
{annexResolved
|
{annexResolved
|
||||||
? "aufgelöst — die acht Dritten sind den Gruppensiegern fest zugeteilt"
|
? dict.bracket.annexResolved
|
||||||
: "noch offen — sobald die 8 besten Dritten feststehen, verbindet sich der Baum automatisch"}
|
: dict.bracket.annexPending}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bracket-scroll">
|
<div className="bracket-scroll">
|
||||||
<div className="bracket">
|
<div className="bracket">
|
||||||
<div className="round">
|
<div className="round">
|
||||||
<div className="round-label">Letzte 32</div>
|
<div className="round-label">{dict.round.r32}</div>
|
||||||
<div className="round-matches">
|
<div className="round-matches">
|
||||||
{r32.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
{r32.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} locale={locale} dict={dict} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="round">
|
<div className="round">
|
||||||
<div className="round-label">Achtelfinale</div>
|
<div className="round-label">{dict.round.r16}</div>
|
||||||
<div className="round-matches">
|
<div className="round-matches">
|
||||||
{r16.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
{r16.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} locale={locale} dict={dict} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="round">
|
<div className="round">
|
||||||
<div className="round-label">Viertelfinale</div>
|
<div className="round-label">{dict.round.qf}</div>
|
||||||
<div className="round-matches">
|
<div className="round-matches">
|
||||||
{qf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
{qf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} locale={locale} dict={dict} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="round">
|
<div className="round">
|
||||||
<div className="round-label">Halbfinale</div>
|
<div className="round-label">{dict.round.sf}</div>
|
||||||
<div className="round-matches">
|
<div className="round-matches">
|
||||||
{sf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
{sf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} locale={locale} dict={dict} matchInfo={matchMeta.get(t.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="round">
|
<div className="round">
|
||||||
<div className="round-label">Finale</div>
|
<div className="round-label">{dict.round.final}</div>
|
||||||
<div className="round-matches">
|
<div className="round-matches">
|
||||||
{fin && <Tie tie={fin} teams={teams} isFinal onShowTip={showTip} onHideTip={hideTip} />}
|
{fin && <Tie tie={fin} teams={teams} isFinal locale={locale} dict={dict} matchInfo={matchMeta.get(fin.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />}
|
||||||
{third && (
|
{third && (
|
||||||
<div style={{ marginTop: 20 }}>
|
<div style={{ marginTop: 20 }}>
|
||||||
<div className="round-label" style={{ marginBottom: 8 }}>Spiel um Platz 3</div>
|
<div className="round-label" style={{ marginBottom: 8 }}>{dict.round.thirdPlace}</div>
|
||||||
<Tie tie={third} teams={teams} onShowTip={showTip} onHideTip={hideTip} />
|
<Tie tie={third} teams={teams} locale={locale} dict={dict} matchInfo={matchMeta.get(third.matchNumber)} onShowTip={showTip} onHideTip={hideTip} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -146,12 +183,12 @@ export default function Bracket({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="legend">
|
<div className="legend">
|
||||||
<span><i style={{ background: "var(--turf)" }} />Sieger / weiter</span>
|
<span><i style={{ background: "var(--turf)" }} />{dict.legend.winner}</span>
|
||||||
<span><i style={{ background: "var(--gold)" }} />Finale</span>
|
<span><i style={{ background: "var(--gold)" }} />{dict.legend.final}</span>
|
||||||
<span><i className="leg-fix" />fix qualifiziert</span>
|
<span><i className="leg-fix" />{dict.legend.fixed}</span>
|
||||||
<span><i className="leg-prov" />vorläufig (≈, nach aktueller Tabelle)</span>
|
<span><i className="leg-prov" />{dict.legend.provisional}</span>
|
||||||
<span><i style={{ background: "var(--ink-faint)" }} />Platzhalter offen</span>
|
<span><i style={{ background: "var(--ink-faint)" }} />{dict.legend.placeholder}</span>
|
||||||
<span>%-Werte: Polymarket-Wahrscheinlichkeit (falls verfügbar)</span>
|
<span>{dict.legend.probExplanation}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{tip && (
|
{tip && (
|
||||||
@@ -1,53 +1,54 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { GROUP_IDS, GroupId, Match, Team } from "@/lib/types";
|
import { GROUP_IDS, GroupId, Match, Team, teamName } from "@/lib/types";
|
||||||
import { computeGroupTables } from "@/lib/standings";
|
import { computeGroupTables } from "@/lib/standings";
|
||||||
|
import { Dictionary } from "@/lib/i18n";
|
||||||
import Flag from "./Flag";
|
import Flag from "./Flag";
|
||||||
|
|
||||||
function teamById(teams: Team[], id: string | null) {
|
function teamById(teams: Team[], id: string | null) {
|
||||||
return id ? teams.find((t) => t.id === id) : undefined;
|
return id ? teams.find((t) => t.id === id) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kürzel der lokalen Browser-Zeitzone, z.B. "MEZ"/"GMT+1" – einmal ermittelt.
|
function tzLabel(locale: string): string {
|
||||||
const TZ_LABEL = (() => {
|
|
||||||
try {
|
try {
|
||||||
const parts = new Intl.DateTimeFormat("de-DE", { timeZoneName: "short" })
|
const parts = new Intl.DateTimeFormat(locale === "en" ? "en-US" : "de-DE", { timeZoneName: "short" })
|
||||||
.formatToParts(new Date());
|
.formatToParts(new Date());
|
||||||
return parts.find((p) => p.type === "timeZoneName")?.value ?? "";
|
return parts.find((p) => p.type === "timeZoneName")?.value ?? "";
|
||||||
} catch {
|
} catch {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
})();
|
}
|
||||||
|
|
||||||
function fmtDate(iso: string): string {
|
function fmtDate(iso: string, locale: string): string {
|
||||||
const d = new Date(iso);
|
const d = new Date(iso);
|
||||||
const s = d.toLocaleString("de-DE", {
|
const s = d.toLocaleString(locale === "en" ? "en-US" : "de-DE", {
|
||||||
weekday: "short", day: "2-digit", month: "2-digit",
|
weekday: "short", day: "2-digit", month: "2-digit",
|
||||||
hour: "2-digit", minute: "2-digit",
|
hour: "2-digit", minute: "2-digit",
|
||||||
});
|
});
|
||||||
return TZ_LABEL ? `${s} ${TZ_LABEL}` : s;
|
const tz = tzLabel(locale);
|
||||||
|
return tz ? `${s} ${tz}` : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
function statusText(m: Match): { text: string; live: boolean } {
|
function statusText(m: Match, dict: Dictionary): { text: string; live: boolean } {
|
||||||
switch (m.status) {
|
switch (m.status) {
|
||||||
case "LIVE":
|
case "LIVE":
|
||||||
case "IN_PLAY":
|
case "IN_PLAY":
|
||||||
return { text: m.minute != null ? `${m.minute}'` : "läuft", live: true };
|
return { text: m.minute != null ? `${m.minute}'` : dict.status.running, live: true };
|
||||||
case "PAUSED":
|
case "PAUSED":
|
||||||
return { text: "Halbzeit", live: true };
|
return { text: dict.status.halftime, live: true };
|
||||||
case "FINISHED":
|
case "FINISHED":
|
||||||
return { text: "Beendet", live: false };
|
return { text: dict.status.finished, live: false };
|
||||||
default:
|
default:
|
||||||
return { text: fmtDate(m.utcDate), live: false };
|
return { text: "", live: false };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mitte: Ergebnis (wenn vorhanden) oder ein schlichtes "–" bei ungespielten
|
// Mitte: Ergebnis (wenn vorhanden) oder ein schlichtes "–" bei ungespielten
|
||||||
// Spielen. Datum/Uhrzeit steht bereits links im Status und wird hier NICHT
|
// Spielen. Datum/Uhrzeit steht bereits links im Status und wird hier NICHT
|
||||||
// wiederholt.
|
// wiederholt.
|
||||||
function ScoreCell({ m }: { m: Match }) {
|
function ScoreCell({ m, dict }: { m: Match; dict: Dictionary }) {
|
||||||
const hasScore = m.homeScore != null && m.awayScore != null;
|
const hasScore = m.homeScore != null && m.awayScore != null;
|
||||||
const st = statusText(m);
|
const st = statusText(m, dict);
|
||||||
if (hasScore) {
|
if (hasScore) {
|
||||||
return (
|
return (
|
||||||
<span className={`fx-score ${st.live ? "score-live" : ""}`}>
|
<span className={`fx-score ${st.live ? "score-live" : ""}`}>
|
||||||
@@ -59,8 +60,8 @@ function ScoreCell({ m }: { m: Match }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function GroupStandings({
|
function GroupStandings({
|
||||||
group, teams, matches,
|
group, teams, matches, dict,
|
||||||
}: { group: GroupId; teams: Team[]; matches: Match[] }) {
|
}: { group: GroupId; teams: Team[]; matches: Match[]; dict: Dictionary }) {
|
||||||
// Live-Tabelle: laufende Spiele werden mit Zwischenstand eingerechnet.
|
// Live-Tabelle: laufende Spiele werden mit Zwischenstand eingerechnet.
|
||||||
const table = computeGroupTables(teams, matches, true).find((t) => t.group === group);
|
const table = computeGroupTables(teams, matches, true).find((t) => t.group === group);
|
||||||
if (!table) return null;
|
if (!table) return null;
|
||||||
@@ -80,15 +81,15 @@ function GroupStandings({
|
|||||||
return (
|
return (
|
||||||
<div className="fx-standings">
|
<div className="fx-standings">
|
||||||
<div className="fx-standings-title">
|
<div className="fx-standings-title">
|
||||||
Tabelle – Gruppe {group}
|
{dict.fixtures.standingsTitle(group)}
|
||||||
{hasLive && <span className="fx-standings-live">● LIVE</span>}
|
{hasLive && <span className="fx-standings-live">{dict.label.liveIndicator}</span>}
|
||||||
</div>
|
</div>
|
||||||
<table className="standings">
|
<table className="standings">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="team">Mannschaft</th>
|
<th className="team">{dict.table.team}</th>
|
||||||
<th>Sp</th><th>S</th><th>U</th><th>N</th>
|
<th>{dict.table.matches}</th><th>{dict.table.won}</th><th>{dict.table.drawn}</th><th>{dict.table.lost}</th>
|
||||||
<th>Tore</th><th>±</th><th>Pkt</th>
|
<th>{dict.table.goals}</th><th>{dict.table.goalDiff}</th><th>{dict.table.points}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -101,8 +102,8 @@ function GroupStandings({
|
|||||||
<td className="team">
|
<td className="team">
|
||||||
<span className={`rankdot ${cls}`}>{r.rank}</span>
|
<span className={`rankdot ${cls}`}>{r.rank}</span>
|
||||||
<Flag team={team} size={20} />
|
<Flag team={team} size={20} />
|
||||||
<span className="team-name">{team?.localisedName ?? team?.name ?? r.teamId}</span>
|
<span className="team-name">{teamName(team, "de")}</span>
|
||||||
{isLive && <span className="row-live-dot" title="läuft gerade" />}
|
{isLive && <span className="row-live-dot" title={dict.status.running} />}
|
||||||
</td>
|
</td>
|
||||||
<td>{r.played}</td>
|
<td>{r.played}</td>
|
||||||
<td>{r.won}</td>
|
<td>{r.won}</td>
|
||||||
@@ -121,11 +122,13 @@ function GroupStandings({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Fixtures({
|
export default function Fixtures({
|
||||||
group, teams, matches, onSelectGroup,
|
group, teams, matches, onSelectGroup, dict, locale,
|
||||||
}: {
|
}: {
|
||||||
group: GroupId; teams: Team[]; matches: Match[];
|
group: GroupId; teams: Team[]; matches: Match[];
|
||||||
onSelectGroup: (g: GroupId) => void;
|
onSelectGroup: (g: GroupId) => void;
|
||||||
|
dict: Dictionary; locale: string;
|
||||||
}) {
|
}) {
|
||||||
|
const intlLocale = locale === "en" ? "en-US" : "de-DE";
|
||||||
const list = matches
|
const list = matches
|
||||||
.filter((m) => m.group === group)
|
.filter((m) => m.group === group)
|
||||||
.sort((a, b) => +new Date(a.utcDate) - +new Date(b.utcDate));
|
.sort((a, b) => +new Date(a.utcDate) - +new Date(b.utcDate));
|
||||||
@@ -145,37 +148,41 @@ export default function Fixtures({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{list.length === 0 ? (
|
{list.length === 0 ? (
|
||||||
<div className="notice">Für Gruppe {group} liegen noch keine Spiele im Feed vor.</div>
|
<div className="notice">{dict.fixtures.noMatches(group)}</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="fixtures">
|
<div className="fixtures">
|
||||||
{list.map((m) => {
|
{list.map((m) => {
|
||||||
const home = teamById(teams, m.homeTeamId);
|
const home = teamById(teams, m.homeTeamId);
|
||||||
const away = teamById(teams, m.awayTeamId);
|
const away = teamById(teams, m.awayTeamId);
|
||||||
const st = statusText(m);
|
const st = statusText(m, dict);
|
||||||
|
const displayText = st.text || fmtDate(m.utcDate, locale);
|
||||||
const homeWin = m.homeScore != null && m.awayScore != null && m.homeScore > m.awayScore;
|
const homeWin = m.homeScore != null && m.awayScore != null && m.homeScore > m.awayScore;
|
||||||
const awayWin = m.homeScore != null && m.awayScore != null && m.awayScore > m.homeScore;
|
const awayWin = m.homeScore != null && m.awayScore != null && m.awayScore > m.homeScore;
|
||||||
return (
|
return (
|
||||||
<div className={`fx ${st.live ? "fx-live" : ""}`} key={m.id}>
|
<div className={`fx ${st.live ? "fx-live" : ""}`} key={m.id}>
|
||||||
<div className="fx-status">
|
<div className="fx-status">
|
||||||
{st.live && <span className="dot live" />}
|
{st.live && <span className="dot live" />}
|
||||||
<span>{st.text}</span>
|
<span>{displayText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="fx-teams">
|
<div className="fx-teams">
|
||||||
<div className={`fx-team home ${homeWin ? "win" : ""}`}>
|
<div className={`fx-team home ${homeWin ? "win" : ""}`}>
|
||||||
<Flag team={home} size={22} />
|
<Flag team={home} size={22} />
|
||||||
<span className="fx-name">{home?.localisedName ?? home?.name ?? "—"}</span>
|
<span className="fx-name">{teamName(home, locale)}</span>
|
||||||
</div>
|
</div>
|
||||||
<ScoreCell m={m} />
|
<ScoreCell m={m} dict={dict} />
|
||||||
<div className={`fx-team away ${awayWin ? "win" : ""}`}>
|
<div className={`fx-team away ${awayWin ? "win" : ""}`}>
|
||||||
<Flag team={away} size={22} />
|
<Flag team={away} size={22} />
|
||||||
<span className="fx-name">{away?.localisedName ?? away?.name ?? "—"}</span>
|
<span className="fx-name">{teamName(away, locale)}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="fx-meta">
|
<div className="fx-meta">
|
||||||
{m.venue && <span className="fx-venue">📍 {m.venue}</span>}
|
{(() => {
|
||||||
{m.attendance != null && (
|
const stadium = [m.stadiumName, m.stadiumCity].filter(Boolean).join(", ");
|
||||||
<span className="fx-att">👥 {m.attendance.toLocaleString("de-DE")}</span>
|
const crowd = m.attendance != null ? m.attendance.toLocaleString(intlLocale) : "";
|
||||||
)}
|
const sep = stadium && crowd ? " · " : "";
|
||||||
|
const text = stadium + sep + crowd;
|
||||||
|
return text ? <span className="fx-venue">{text}</span> : null;
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -184,7 +191,7 @@ export default function Fixtures({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{list.length > 0 && (
|
{list.length > 0 && (
|
||||||
<GroupStandings group={group} teams={teams} matches={matches} />
|
<GroupStandings group={group} teams={teams} matches={matches} dict={dict} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
27
app/[locale]/components/Flag.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Team } from "@/lib/types";
|
||||||
|
import { TLA_TO_ISO2 } from "@/lib/flags";
|
||||||
|
|
||||||
|
// Zeigt die Flagge eines Teams aus lokalem circle-flags-Bestand.
|
||||||
|
// Fallback: kein Rendering bei fehlendem Team/Code (kein Broken-Image).
|
||||||
|
export default function Flag({
|
||||||
|
team, size = 22,
|
||||||
|
}: { team?: Team; size?: number }) {
|
||||||
|
const style = { width: size, height: size } as const;
|
||||||
|
|
||||||
|
const iso2 = team?.code ? TLA_TO_ISO2[team.code.toUpperCase()] : undefined;
|
||||||
|
if (iso2) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={`/flags/${iso2}.svg`}
|
||||||
|
alt={team!.code || team!.localisedName || team!.name}
|
||||||
|
className="flag"
|
||||||
|
style={style}
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Kein Team / kein Code: nichts rendern (kein Broken-Image)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { GroupId, GroupTable, Match, Team } from "@/lib/types";
|
import { GroupId, GroupTable, Match, Team, teamName } from "@/lib/types";
|
||||||
|
import { Dictionary } from "@/lib/i18n";
|
||||||
import Flag from "./Flag";
|
import Flag from "./Flag";
|
||||||
|
|
||||||
function teamById(teams: Team[], id: string) {
|
function teamById(teams: Team[], id: string) {
|
||||||
@@ -26,10 +27,11 @@ function liveTeamIdsFor(group: GroupId, matches: Match[]): Set<string> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Groups({
|
export default function Groups({
|
||||||
tables, teams, matches, onOpenGroup,
|
tables, teams, matches, onOpenGroup, dict, locale,
|
||||||
}: {
|
}: {
|
||||||
tables: GroupTable[]; teams: Team[]; matches: Match[];
|
tables: GroupTable[]; teams: Team[]; matches: Match[];
|
||||||
onOpenGroup: (g: GroupId) => void;
|
onOpenGroup: (g: GroupId) => void;
|
||||||
|
dict: Dictionary; locale: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="group-grid">
|
<div className="group-grid">
|
||||||
@@ -43,19 +45,19 @@ export default function Groups({
|
|||||||
<button
|
<button
|
||||||
className="group-head group-head-btn"
|
className="group-head group-head-btn"
|
||||||
onClick={() => onOpenGroup(t.group)}
|
onClick={() => onOpenGroup(t.group)}
|
||||||
title={`Spiele der Gruppe ${t.group} ansehen`}
|
title={dict.groups.viewGroupGames(t.group)}
|
||||||
>
|
>
|
||||||
<span className={`group-name${groupComplete ? " group-complete" : ""}`}>Gruppe {t.group}</span>
|
<span className={`group-name${groupComplete ? " group-complete" : ""}`}>{dict.groups.groupLabel(t.group)}</span>
|
||||||
<span className="group-tag">
|
<span className="group-tag">
|
||||||
{live ? "● LIVE" : "Spiele ansehen →"}
|
{live ? dict.label.liveIndicator : dict.groups.viewGames}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<table className="standings">
|
<table className="standings">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="team">Mannschaft</th>
|
<th className="team">{dict.table.team}</th>
|
||||||
<th>Sp</th><th>S</th><th>U</th><th>N</th>
|
<th>{dict.table.matches}</th><th>{dict.table.won}</th><th>{dict.table.drawn}</th><th>{dict.table.lost}</th>
|
||||||
<th>Tore</th><th>±</th><th>Pkt</th>
|
<th>{dict.table.goals}</th><th>{dict.table.goalDiff}</th><th>{dict.table.points}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -68,8 +70,8 @@ export default function Groups({
|
|||||||
<td className="team">
|
<td className="team">
|
||||||
<span className={`rankdot ${cls}`}>{r.rank}</span>
|
<span className={`rankdot ${cls}`}>{r.rank}</span>
|
||||||
<Flag team={team} size={20} />
|
<Flag team={team} size={20} />
|
||||||
<span className="team-name">{team?.localisedName ?? team?.name ?? r.teamId}</span>
|
<span className="team-name">{teamName(team, locale)}</span>
|
||||||
{isLive && <span className="row-live-dot" title="läuft gerade" />}
|
{isLive && <span className="row-live-dot" title={dict.status.running} />}
|
||||||
</td>
|
</td>
|
||||||
<td>{r.played}</td>
|
<td>{r.played}</td>
|
||||||
<td>{r.won}</td>
|
<td>{r.won}</td>
|
||||||
301
app/[locale]/components/KoFixtures.tsx
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useMemo, useState, useEffect, useRef } from "react";
|
||||||
|
import { Match, Team, teamName } from "@/lib/types";
|
||||||
|
import { STADIUMS, MATCH_STADIUMS } from "@/lib/stadiums";
|
||||||
|
import { Dictionary } from "@/lib/i18n";
|
||||||
|
import Flag from "./Flag";
|
||||||
|
|
||||||
|
function fmtShortDate(iso: string, locale: string): string {
|
||||||
|
const d = new Date(iso);
|
||||||
|
return d.toLocaleDateString(locale === "en" ? "en-US" : "de-DE", { weekday: "short", day: "2-digit", month: "2-digit" });
|
||||||
|
}
|
||||||
|
|
||||||
|
function fmtTime(iso: string, locale: string): string {
|
||||||
|
const d = new Date(iso);
|
||||||
|
return d.toLocaleTimeString(locale === "en" ? "en-US" : "de-DE", { hour: "2-digit", minute: "2-digit" });
|
||||||
|
}
|
||||||
|
|
||||||
|
function scoreMain(m: Match): string {
|
||||||
|
if (m.status === "SCHEDULED" || m.status === "POSTPONED" || (m.homeScore == null && m.awayScore == null)) return "– : –";
|
||||||
|
return `${m.homeScore ?? 0} : ${m.awayScore ?? 0}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scorePenalty(m: Match, dict: Dictionary): string | null {
|
||||||
|
if (m.homePenalty != null && m.awayPenalty != null) {
|
||||||
|
return `${m.homePenalty}:${m.awayPenalty} ${dict.bracket.penaltyShootout}`;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLive(m: Match): boolean {
|
||||||
|
return m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED";
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function KoFixtures({ teams, matches, dict, locale }: { teams: Team[]; matches: Match[]; dict: Dictionary; locale: string }) {
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
useEffect(() => { setMounted(true); }, []);
|
||||||
|
|
||||||
|
function statusLabel(m: Match): string {
|
||||||
|
switch (m.status) {
|
||||||
|
case "LIVE": case "IN_PLAY": return m.minute != null ? `${m.minute}'` : dict.status.live;
|
||||||
|
case "PAUSED": return dict.status.halftime;
|
||||||
|
case "POSTPONED": return dict.status.postponed;
|
||||||
|
case "FINISHED": return dict.status.finished;
|
||||||
|
default: return fmtTime(m.utcDate, locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const koMatches = useMemo(() => {
|
||||||
|
return matches
|
||||||
|
.filter((m) =>
|
||||||
|
m.group == null &&
|
||||||
|
m.homeTeamId != null && m.awayTeamId != null &&
|
||||||
|
// Nur Spiele mit bekannten Teams (keine TBD)
|
||||||
|
teams.some(t => t.id === m.homeTeamId) &&
|
||||||
|
teams.some(t => t.id === m.awayTeamId),
|
||||||
|
)
|
||||||
|
.sort((a, b) => +new Date(a.utcDate) - +new Date(b.utcDate));
|
||||||
|
}, [matches, teams]);
|
||||||
|
|
||||||
|
// Lokale Datums-Extraktion (vermeidet UTC-Tagesverschiebung bei US-Spielen)
|
||||||
|
function localDateKey(iso: string): string {
|
||||||
|
const d = new Date(iso);
|
||||||
|
const y = d.getFullYear();
|
||||||
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(d.getDate()).padStart(2, "0");
|
||||||
|
return `${y}-${m}-${day}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nach Datum gruppieren (lokale Zeitzone nach Hydration, sonst UTC)
|
||||||
|
const groups = useMemo(() => {
|
||||||
|
const map = new Map<string, Match[]>();
|
||||||
|
for (const m of koMatches) {
|
||||||
|
const key = mounted ? localDateKey(m.utcDate) : m.utcDate.slice(0, 10);
|
||||||
|
if (!map.has(key)) map.set(key, []);
|
||||||
|
map.get(key)!.push(m);
|
||||||
|
}
|
||||||
|
return [...map.entries()];
|
||||||
|
}, [koMatches, mounted]);
|
||||||
|
|
||||||
|
const targetMatchId = useMemo(() => {
|
||||||
|
const live = koMatches.find(m => isLive(m));
|
||||||
|
if (live) return live.id;
|
||||||
|
const upcoming = koMatches.find(m => m.status !== "FINISHED");
|
||||||
|
return upcoming?.id ?? null;
|
||||||
|
}, [koMatches]);
|
||||||
|
|
||||||
|
// Scroll-Ziel: aktueller Tag (heute, oder nächster Spieltag bei Ruhetag)
|
||||||
|
const targetDateKey = useMemo(() => {
|
||||||
|
const todayKey = localDateKey(new Date().toISOString());
|
||||||
|
const dayKeys = groups.map(([key]) => key);
|
||||||
|
if (dayKeys.includes(todayKey)) return todayKey;
|
||||||
|
const future = dayKeys.find(k => k >= todayKey);
|
||||||
|
return future ?? dayKeys[dayKeys.length - 1] ?? null;
|
||||||
|
}, [groups]);
|
||||||
|
|
||||||
|
const targetDateRef = useRef<HTMLHeadingElement>(null);
|
||||||
|
const hasScrolledRef = useRef<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!mounted || !targetDateRef.current) return;
|
||||||
|
if (targetDateKey === hasScrolledRef.current) return;
|
||||||
|
const el = targetDateRef.current;
|
||||||
|
const raf = requestAnimationFrame(() => {
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
const absoluteTop = rect.top + window.scrollY;
|
||||||
|
const offset = 180;
|
||||||
|
window.scrollTo({ top: Math.max(0, absoluteTop - offset), behavior: "smooth" });
|
||||||
|
});
|
||||||
|
hasScrolledRef.current = targetDateKey;
|
||||||
|
return () => cancelAnimationFrame(raf);
|
||||||
|
}, [mounted, targetDateKey, koMatches.length]);
|
||||||
|
|
||||||
|
const [showScrollTop, setShowScrollTop] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const onScroll = () => setShowScrollTop(window.scrollY > 100);
|
||||||
|
window.addEventListener("scroll", onScroll, { passive: true });
|
||||||
|
onScroll();
|
||||||
|
return () => window.removeEventListener("scroll", onScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (koMatches.length === 0) {
|
||||||
|
return <div className="notice">{dict.koFixtures.noMatches}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
{groups.map(([date, groupMatches]) => (
|
||||||
|
<div key={date} style={{ marginBottom: 24 }}>
|
||||||
|
<h3 ref={date === targetDateKey ? targetDateRef : undefined} style={{
|
||||||
|
fontFamily: "var(--font-display)", fontSize: 13,
|
||||||
|
textTransform: "uppercase", letterSpacing: "0.06em",
|
||||||
|
color: "var(--ink-dim)", margin: "0 0 10px",
|
||||||
|
}}>
|
||||||
|
{fmtShortDate(groupMatches[0].utcDate, locale)}
|
||||||
|
</h3>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
|
||||||
|
{groupMatches.map((m) => {
|
||||||
|
const home = m.homeTeamId ? teams.find(t => t.id === m.homeTeamId) : undefined;
|
||||||
|
const away = m.awayTeamId ? teams.find(t => t.id === m.awayTeamId) : undefined;
|
||||||
|
const live = isLive(m);
|
||||||
|
const stageMap: Record<string, string> = {
|
||||||
|
R32: "R32", R16: dict.stage.r16, QF: dict.stage.qf,
|
||||||
|
SF: dict.stage.sf, "3RD": dict.stage.thirdPlace, FINAL: dict.stage.final,
|
||||||
|
};
|
||||||
|
|
||||||
|
const city = STADIUMS[MATCH_STADIUMS[m.matchNumber]]?.city;
|
||||||
|
const isTarget = String(m.id) === String(targetMatchId);
|
||||||
|
const finished = m.status === "FINISHED";
|
||||||
|
const penalty = scorePenalty(m, dict);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={m.id}
|
||||||
|
style={{
|
||||||
|
background: "var(--bg-card)",
|
||||||
|
border: `${isTarget ? 2 : 1}px solid ${live ? "var(--turf)" : isTarget ? "var(--turf)" : "var(--line-soft)"}`,
|
||||||
|
borderRadius: "var(--radius-sm)", padding: "12px 14px",
|
||||||
|
opacity: finished && !isTarget ? 0.65 : 1,
|
||||||
|
boxShadow: isTarget ? "0 0 0 1px var(--turf)" : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Kopfzeile */}
|
||||||
|
<div style={{
|
||||||
|
display: "flex", justifyContent: "space-between", alignItems: "center",
|
||||||
|
marginBottom: 8, fontSize: 11,
|
||||||
|
fontFamily: "var(--font-mono)", color: "var(--ink-faint)",
|
||||||
|
}}>
|
||||||
|
<span style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||||
|
{isTarget && (
|
||||||
|
<span style={{
|
||||||
|
background: live ? "var(--turf)" : "var(--turf-deep)",
|
||||||
|
color: "#fff", fontSize: 9, fontWeight: 700,
|
||||||
|
padding: "1px 6px", borderRadius: 999,
|
||||||
|
letterSpacing: "0.04em",
|
||||||
|
}}>
|
||||||
|
{live ? dict.koFixtures.liveBadge : dict.koFixtures.nextMatch}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{m.status === "POSTPONED" && (
|
||||||
|
<span style={{
|
||||||
|
background: "var(--ink-faint)", color: "#fff",
|
||||||
|
fontSize: 9, fontWeight: 700,
|
||||||
|
padding: "1px 6px", borderRadius: 999,
|
||||||
|
letterSpacing: "0.04em",
|
||||||
|
}}>
|
||||||
|
{dict.koFixtures.postponedBadge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{stageMap[m.stage] ?? m.stage} · {m.matchNumber ? dict.koFixtures.match(m.matchNumber) : dict.koFixtures.match(0).replace("0", "—")}
|
||||||
|
{city ? ` · ${city}` : ""}
|
||||||
|
</span>
|
||||||
|
<span style={{ color: live ? "var(--turf)" : undefined, fontWeight: live ? 700 : undefined }}>
|
||||||
|
{statusLabel(m)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Teams + Score */}
|
||||||
|
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
|
||||||
|
<TeamLabel team={home} locale={locale} />
|
||||||
|
<div style={{
|
||||||
|
position: "relative",
|
||||||
|
display: "flex", flexDirection: "column", alignItems: "center",
|
||||||
|
padding: "0 16px",
|
||||||
|
}}>
|
||||||
|
<span style={{
|
||||||
|
fontFamily: "var(--font-mono)", fontSize: 22, fontWeight: 700,
|
||||||
|
color: live ? "var(--turf)" : "var(--ink)",
|
||||||
|
lineHeight: 1,
|
||||||
|
}}>
|
||||||
|
{scoreMain(m)}
|
||||||
|
{penalty && <span className="pso-inline"> ({penalty})</span>}
|
||||||
|
</span>
|
||||||
|
{penalty && <span className="pso-badge">{penalty}</span>}
|
||||||
|
</div>
|
||||||
|
<TeamLabel team={away} reverse locale={locale} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Torabfolge */}
|
||||||
|
{m.goals && m.goals.length > 0 && (
|
||||||
|
<div style={{
|
||||||
|
marginTop: 8, padding: "8px 10px",
|
||||||
|
background: "var(--bg-raised)", borderRadius: "var(--radius-sm)",
|
||||||
|
fontSize: 12, fontFamily: "var(--font-mono)",
|
||||||
|
}}>
|
||||||
|
<div style={{ color: "var(--ink-faint)", fontSize: 10, marginBottom: 4 }}>
|
||||||
|
{dict.label.goals}
|
||||||
|
</div>
|
||||||
|
<div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
|
||||||
|
{m.goals.map((g, i) => (
|
||||||
|
<span key={i} style={{
|
||||||
|
display: "inline-flex", alignItems: "center", gap: 4,
|
||||||
|
}}>
|
||||||
|
<Flag team={g.team === "home" ? home : away} size={14} />
|
||||||
|
<span style={{ color: "var(--turf)", fontWeight: 700 }}>
|
||||||
|
{g.scorer}
|
||||||
|
</span>
|
||||||
|
<span style={{ color: "var(--ink-faint)", fontSize: 10 }}>
|
||||||
|
{g.minute}'
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Prob (falls vorhanden) */}
|
||||||
|
{m.prob && m.prob.home > 0 && (
|
||||||
|
<div style={{
|
||||||
|
marginTop: 6, fontSize: 10, color: "var(--ink-faint)",
|
||||||
|
fontFamily: "var(--font-mono)",
|
||||||
|
}}>
|
||||||
|
Polymarket: {Math.round(m.prob.home * 100)}% / {Math.round(m.prob.draw * 100)}% / {Math.round(m.prob.away * 100)}%
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{showScrollTop && (
|
||||||
|
<button
|
||||||
|
onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
|
||||||
|
style={{
|
||||||
|
position: "fixed", right: 24, bottom: 24, zIndex: 50,
|
||||||
|
width: 48, height: 48, borderRadius: "50%",
|
||||||
|
background: "var(--bg-card)", color: "var(--ink-dim)",
|
||||||
|
border: "1px solid var(--line)", boxShadow: "0 2px 8px rgba(0,0,0,0.4)",
|
||||||
|
cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
|
||||||
|
fontSize: 22, lineHeight: 1,
|
||||||
|
}}
|
||||||
|
title={dict.label.scrollToTop}
|
||||||
|
>
|
||||||
|
↑
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TeamLabel({ team, reverse, locale }: { team?: Team; reverse?: boolean; locale: string }) {
|
||||||
|
return (
|
||||||
|
<div style={{
|
||||||
|
display: "flex", alignItems: "center", gap: 8,
|
||||||
|
flexDirection: reverse ? "row-reverse" : "row",
|
||||||
|
flex: 1, minWidth: 0,
|
||||||
|
}}>
|
||||||
|
<Flag team={team} size={20} />
|
||||||
|
<span style={{
|
||||||
|
fontWeight: 600, fontSize: 14,
|
||||||
|
whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
|
||||||
|
maxWidth: 120,
|
||||||
|
}}>
|
||||||
|
{teamName(team, locale)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
118
app/[locale]/components/Simulation.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { Match, Team } from "@/lib/types";
|
||||||
|
import { Dictionary } from "@/lib/i18n";
|
||||||
|
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
|
||||||
|
import { qualifiedThirdGroups, resolveAnnexC, LATER_ROUNDS } from "@/lib/bracket";
|
||||||
|
import { resolveBracket, ResolvedTie } from "@/lib/resolve-bracket";
|
||||||
|
import { buildSimMatches } from "@/lib/simulation";
|
||||||
|
import Bracket from "./Bracket";
|
||||||
|
|
||||||
|
export default function Simulation({ teams, matches, dict, locale }: { teams: Team[]; matches: Match[]; dict: Dictionary; locale: string }) {
|
||||||
|
// ---- Simulations-Pipeline (Polymarket-Defaults, keine manuellen Overrides) ----
|
||||||
|
const simMatches = useMemo(() => buildSimMatches(matches, {}), [matches]);
|
||||||
|
const simTables = useMemo(() => computeGroupTables(teams, simMatches), [teams, simMatches]);
|
||||||
|
const simThirds = useMemo(() => computeThirdPlaceTable(simTables), [simTables]);
|
||||||
|
const simQGroups = useMemo(() => qualifiedThirdGroups(simThirds), [simThirds]);
|
||||||
|
const simAnnex = useMemo(
|
||||||
|
() => (simQGroups.length === 8 ? resolveAnnexC(simQGroups) : null),
|
||||||
|
[simQGroups],
|
||||||
|
);
|
||||||
|
const simAnnexResolved = simAnnex != null;
|
||||||
|
|
||||||
|
const simBracket = useMemo(
|
||||||
|
() => resolveBracket(simMatches, teams, simTables, simThirds, simAnnex, simAnnexResolved, true, dict),
|
||||||
|
[simMatches, teams, simTables, simThirds, simAnnex, simAnnexResolved, dict],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Echte Tabellen/Bracket für fix/provisional-Flags (nur tatsächlich FINISHED).
|
||||||
|
const realTables = useMemo(() => computeGroupTables(teams, matches), [teams, matches]);
|
||||||
|
const realThirds = useMemo(() => computeThirdPlaceTable(realTables), [realTables]);
|
||||||
|
const realQGroups = useMemo(() => qualifiedThirdGroups(realThirds), [realThirds]);
|
||||||
|
const realAnnex = useMemo(
|
||||||
|
() => (realQGroups.length === 8 ? resolveAnnexC(realQGroups) : null),
|
||||||
|
[realQGroups],
|
||||||
|
);
|
||||||
|
const realBracket = useMemo(
|
||||||
|
() => resolveBracket(matches, teams, realTables, realThirds, realAnnex, realAnnex != null, undefined, dict),
|
||||||
|
[matches, teams, realTables, realThirds, realAnnex, dict],
|
||||||
|
);
|
||||||
|
|
||||||
|
// R32: provisional-Flags aus dem echten Bracket übernehmen.
|
||||||
|
const realProvisional = useMemo(() => {
|
||||||
|
const m = new Map<number, { home: boolean; away: boolean }>();
|
||||||
|
for (const tie of realBracket.r32) {
|
||||||
|
m.set(tie.matchNumber, { home: tie.home.provisional, away: tie.away.provisional });
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}, [realBracket]);
|
||||||
|
|
||||||
|
// Folgerunden: decided-Flags aus echten Matches (status === FINISHED).
|
||||||
|
const realDecided = useMemo(() => {
|
||||||
|
const m = new Map<number, boolean>();
|
||||||
|
for (const mt of matches) {
|
||||||
|
if (mt.group == null && mt.matchNumber >= 73) {
|
||||||
|
m.set(mt.matchNumber, mt.status === "FINISHED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}, [matches]);
|
||||||
|
|
||||||
|
// Sim-Bracket mit echten provisional-Flags mergen (inkl. Tooltip-Korrektur).
|
||||||
|
const preResolved = useMemo(() => {
|
||||||
|
const fixTooltip = (t: string | null, prov: boolean): string | null => {
|
||||||
|
if (!t) return t;
|
||||||
|
if (prov) return t.startsWith("aktuell ") ? t : `aktuell ${t}`;
|
||||||
|
return t.startsWith("aktuell ") ? t.slice(8) : t;
|
||||||
|
};
|
||||||
|
|
||||||
|
const r32Fixed: ResolvedTie[] = simBracket.r32.map((tie) => {
|
||||||
|
const rp = realProvisional.get(tie.matchNumber);
|
||||||
|
if (!rp) return tie;
|
||||||
|
return {
|
||||||
|
...tie,
|
||||||
|
home: { ...tie.home, provisional: rp.home, tooltip: fixTooltip(tie.home.tooltip, rp.home) },
|
||||||
|
away: { ...tie.away, provisional: rp.away, tooltip: fixTooltip(tie.away.tooltip, rp.away) },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const laterFixed: Record<number, ResolvedTie> = {};
|
||||||
|
for (const km of LATER_ROUNDS) {
|
||||||
|
const tie = simBracket.later[km.matchNumber];
|
||||||
|
if (!tie) continue;
|
||||||
|
const homeProv = !(realDecided.get(km.fromHome) ?? false);
|
||||||
|
const awayProv = !(realDecided.get(km.fromAway) ?? false);
|
||||||
|
laterFixed[km.matchNumber] = {
|
||||||
|
...tie,
|
||||||
|
home: { ...tie.home, provisional: homeProv },
|
||||||
|
away: { ...tie.away, provisional: awayProv },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { r32: r32Fixed, later: laterFixed };
|
||||||
|
}, [simBracket, realProvisional, realDecided]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="notice" style={{ marginBottom: 20 }}>
|
||||||
|
{dict.sim.notice}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 style={{ fontFamily: "var(--font-display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-dim)", margin: "0 0 12px" }}>
|
||||||
|
{dict.sim.heading}
|
||||||
|
</h3>
|
||||||
|
<Bracket
|
||||||
|
matches={simMatches}
|
||||||
|
teams={teams}
|
||||||
|
tables={simTables}
|
||||||
|
thirds={simThirds}
|
||||||
|
assignment={simAnnex}
|
||||||
|
annexResolved={simAnnexResolved}
|
||||||
|
preResolved={preResolved}
|
||||||
|
dict={dict}
|
||||||
|
locale={locale}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,28 +1,27 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Team, ThirdPlaceRow } from "@/lib/types";
|
import { Team, ThirdPlaceRow, teamName } from "@/lib/types";
|
||||||
|
import { Dictionary } from "@/lib/i18n";
|
||||||
|
|
||||||
export default function ThirdPlace({
|
export default function ThirdPlace({
|
||||||
rows, teams,
|
rows, teams, secureTeams, dict,
|
||||||
}: { rows: ThirdPlaceRow[]; teams: Team[] }) {
|
}: { rows: ThirdPlaceRow[]; teams: Team[]; secureTeams?: string[]; dict: Dictionary }) {
|
||||||
const name = (id: string) => {
|
const name = (id: string) => {
|
||||||
const t = teams.find((t) => t.id === id);
|
const t = teams.find((t) => t.id === id);
|
||||||
return t?.localisedName ?? t?.name ?? id;
|
return teamName(t, "de");
|
||||||
};
|
};
|
||||||
|
const secureSet = secureTeams ? new Set(secureTeams) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="third-wrap">
|
<div className="third-wrap">
|
||||||
<p className="notice" style={{ marginBottom: 16 }}>
|
<p className="notice" style={{ marginBottom: 16 }}>
|
||||||
Acht der zwölf Gruppendritten erreichen die Runde der letzten 32. Gewertet wird
|
{dict.thirds.explanation}
|
||||||
gruppenübergreifend nach Punkten, Tordifferenz und Toren — der Direktvergleich
|
|
||||||
entfällt, weil diese Teams nie gegeneinander gespielt haben. Die Trennlinie markiert
|
|
||||||
den Schnitt zwischen Platz 8 und 9.
|
|
||||||
</p>
|
</p>
|
||||||
<table className="third-table">
|
<table className="third-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th><th>Gruppe</th><th>Team</th>
|
<th>{dict.table.rank}</th><th>{dict.table.group}</th><th>Team</th>
|
||||||
<th>Sp</th><th>Pkt</th><th>±</th><th>Tore</th><th>Status</th>
|
<th>{dict.table.matches}</th><th>{dict.table.points}</th><th>{dict.table.goalDiff}</th><th>{dict.table.goals}</th><th>{dict.table.status}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -35,14 +34,19 @@ export default function ThirdPlace({
|
|||||||
>
|
>
|
||||||
<td>{r.overallRank}</td>
|
<td>{r.overallRank}</td>
|
||||||
<td>{r.group}</td>
|
<td>{r.group}</td>
|
||||||
<td style={{ fontWeight: 600 }}>{name(r.teamId)}</td>
|
<td className={r.played === 3 ? "team-complete" : ""} style={{ fontWeight: 600 }}>
|
||||||
|
{name(r.teamId)}
|
||||||
|
{secureSet?.has(r.teamId) && (
|
||||||
|
<span style={{ color: "var(--turf)", marginLeft: 6, fontSize: 13 }} title={dict.label.securelyQualified}>✓</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
<td>{r.played}</td>
|
<td>{r.played}</td>
|
||||||
<td className="pts">{r.points}</td>
|
<td className="pts">{r.points}</td>
|
||||||
<td>{r.goalDiff > 0 ? `+${r.goalDiff}` : r.goalDiff}</td>
|
<td>{r.goalDiff > 0 ? `+${r.goalDiff}` : r.goalDiff}</td>
|
||||||
<td>{r.goalsFor}:{r.goalsAgainst}</td>
|
<td>{r.goalsFor}:{r.goalsAgainst}</td>
|
||||||
<td>
|
<td>
|
||||||
<span className={`qual-badge ${r.qualifies ? "yes" : "no"}`}>
|
<span className={`qual-badge ${r.qualifies ? "yes" : "no"}`}>
|
||||||
{r.qualifies ? "weiter" : "raus"}
|
{r.qualifies ? dict.thirds.advances : dict.thirds.eliminated}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
BIN
app/[locale]/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
501
app/[locale]/globals.css
Normal file
@@ -0,0 +1,501 @@
|
|||||||
|
:root {
|
||||||
|
/* Palette: Stadion bei Nacht über drei Zeitzonen.
|
||||||
|
Tiefes Mitternachtsblau, kühles Flutlicht-Weiß, warmer Rasen-Akzent,
|
||||||
|
ein Signal-Magenta für "live". Bewusst nicht die üblichen AI-Defaults. */
|
||||||
|
--bg: #0b1020;
|
||||||
|
--bg-raised: #121a32;
|
||||||
|
--bg-card: #16203c;
|
||||||
|
--line: #243152;
|
||||||
|
--line-soft: #1b2540;
|
||||||
|
--ink: #eef2fb;
|
||||||
|
--ink-dim: #9aa6c4;
|
||||||
|
--ink-faint: #5f6d92;
|
||||||
|
--turf: #4ade80; /* Rasen / qualifiziert */
|
||||||
|
--turf-deep: #1f7a45;
|
||||||
|
--floodlight: #cfe0ff;
|
||||||
|
--live: #ff3d7f; /* Live-Signal */
|
||||||
|
--gold: #ffd24a; /* Sieger / Finale */
|
||||||
|
--radius: 10px;
|
||||||
|
--radius-sm: 6px;
|
||||||
|
--shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
|
||||||
|
|
||||||
|
--font-display: "Archivo Expanded", "Archivo", system-ui, sans-serif;
|
||||||
|
--font-body: "Inter", system-ui, -apple-system, sans-serif;
|
||||||
|
--font-mono: "Geist Mono", "SFMono-Regular", ui-monospace, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
html { scroll-behavior: smooth; }
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
html { scroll-behavior: auto; }
|
||||||
|
* { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background:
|
||||||
|
radial-gradient(1200px 600px at 70% -10%, #16224a 0%, transparent 55%),
|
||||||
|
radial-gradient(900px 500px at 10% 0%, #102046 0%, transparent 50%),
|
||||||
|
var(--bg);
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
a { color: inherit; text-decoration: none; }
|
||||||
|
|
||||||
|
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 20px 0 0; }
|
||||||
|
|
||||||
|
/* ---------- Header / Hero ---------- */
|
||||||
|
.masthead {
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
background: linear-gradient(180deg, rgba(18,26,50,0.7), transparent);
|
||||||
|
position: sticky; top: 0; z-index: 50;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
.masthead-inner {
|
||||||
|
display: flex; align-items: center; justify-content: space-between;
|
||||||
|
padding: 14px 0; gap: 16px; flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.brand { display: flex; align-items: baseline; gap: 12px; }
|
||||||
|
.brand-mark {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-weight: 800; letter-spacing: -0.02em;
|
||||||
|
font-size: clamp(20px, 3vw, 28px);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.brand-mark .accent { color: var(--turf); }
|
||||||
|
.brand-sub {
|
||||||
|
font-family: var(--font-mono); font-size: 11px;
|
||||||
|
color: var(--ink-faint); letter-spacing: 0.08em; text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-pill {
|
||||||
|
display: inline-flex; align-items: center; gap: 8px;
|
||||||
|
font-family: var(--font-mono); font-size: 12px;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
border: 1px solid var(--line); border-radius: 999px;
|
||||||
|
padding: 6px 12px; background: var(--bg-card);
|
||||||
|
}
|
||||||
|
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-faint); }
|
||||||
|
.dot.on { background: var(--turf); box-shadow: 0 0 0 3px rgba(74,222,128,0.18); }
|
||||||
|
.dot.live { background: var(--live); box-shadow: 0 0 0 3px rgba(255,61,127,0.2); animation: pulse 1.6s infinite; }
|
||||||
|
@keyframes pulse { 50% { box-shadow: 0 0 0 6px rgba(255,61,127,0); } }
|
||||||
|
|
||||||
|
/* ---------- Tabs ---------- */
|
||||||
|
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin: 0 0 4px; }
|
||||||
|
.masthead-tabs { width: 100%; border-bottom: none; margin: 0; }
|
||||||
|
.tab {
|
||||||
|
font-family: var(--font-display); font-weight: 700;
|
||||||
|
text-transform: uppercase; letter-spacing: 0.01em;
|
||||||
|
font-size: 14px; color: var(--ink-faint);
|
||||||
|
padding: 16px 18px; cursor: pointer; border: none; background: none;
|
||||||
|
border-bottom: 2px solid transparent; transition: color .15s, border-color .15s;
|
||||||
|
}
|
||||||
|
.tab:hover { color: var(--ink-dim); }
|
||||||
|
.tab.active { color: var(--ink); border-bottom-color: var(--turf); }
|
||||||
|
|
||||||
|
.section { padding: 28px 0 64px; }
|
||||||
|
|
||||||
|
/* ---------- Gruppen ---------- */
|
||||||
|
.group-grid {
|
||||||
|
display: grid; gap: 16px;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
|
||||||
|
}
|
||||||
|
.group-card {
|
||||||
|
background: var(--bg-card); border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius); overflow: hidden;
|
||||||
|
}
|
||||||
|
.group-head {
|
||||||
|
display: flex; align-items: center; justify-content: space-between;
|
||||||
|
padding: 12px 14px; border-bottom: 1px solid var(--line-soft);
|
||||||
|
background: var(--bg-raised);
|
||||||
|
}
|
||||||
|
.group-name {
|
||||||
|
font-family: var(--font-display); font-weight: 800; font-size: 16px;
|
||||||
|
text-transform: uppercase; letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
.group-name.group-complete { color: var(--turf); }
|
||||||
|
.group-tag { font-family: var(--font-mono); font-size: 10px; color: var(--ink-faint); }
|
||||||
|
|
||||||
|
table.standings { width: 100%; border-collapse: collapse; }
|
||||||
|
.standings th {
|
||||||
|
font-family: var(--font-mono); font-size: 10px; font-weight: 500;
|
||||||
|
text-transform: uppercase; letter-spacing: 0.06em;
|
||||||
|
color: var(--ink-faint); text-align: right; padding: 8px 6px;
|
||||||
|
}
|
||||||
|
.standings th.team { text-align: left; padding-left: 14px; }
|
||||||
|
.standings td {
|
||||||
|
padding: 9px 6px; text-align: right; font-variant-numeric: tabular-nums;
|
||||||
|
border-top: 1px solid var(--line-soft); font-size: 13px;
|
||||||
|
}
|
||||||
|
.standings td.team {
|
||||||
|
text-align: left; padding-left: 14px; display: flex; align-items: center; gap: 9px;
|
||||||
|
}
|
||||||
|
.rankdot {
|
||||||
|
width: 18px; height: 18px; border-radius: 5px; flex: none;
|
||||||
|
display: grid; place-items: center;
|
||||||
|
font-family: var(--font-mono); font-size: 10px; font-weight: 600;
|
||||||
|
color: var(--bg); background: var(--ink-faint);
|
||||||
|
}
|
||||||
|
.rankdot.q1, .rankdot.q2 { background: var(--turf); }
|
||||||
|
.rankdot.q3 { background: var(--gold); color: #2a2200; }
|
||||||
|
.rankdot.q3.out { background: var(--ink-faint); color: var(--bg); }
|
||||||
|
.team-name { font-weight: 600; }
|
||||||
|
.team-code { font-family: var(--font-mono); font-size: 11px; color: var(--ink-faint); }
|
||||||
|
.pts { font-weight: 700; color: var(--floodlight); }
|
||||||
|
|
||||||
|
/* Live-Zeile */
|
||||||
|
.score-live { color: var(--live); font-weight: 700; }
|
||||||
|
|
||||||
|
/* Gruppen-Tab: grüne Hervorhebung für Teams mit laufendem Spiel */
|
||||||
|
.group-grid .row-live { background: rgba(74, 222, 128, 0.08); }
|
||||||
|
.group-grid .row-live .team-name { color: var(--turf); }
|
||||||
|
.group-grid .row-live-dot {
|
||||||
|
background: var(--turf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Drittplatzierte ---------- */
|
||||||
|
.third-wrap { margin-top: 8px; }
|
||||||
|
.third-table { width: 100%; border-collapse: collapse; background: var(--bg-card);
|
||||||
|
border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
|
||||||
|
.third-table th {
|
||||||
|
font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
|
||||||
|
letter-spacing: 0.06em; color: var(--ink-faint); padding: 11px 12px; text-align: right;
|
||||||
|
background: var(--bg-raised); border-bottom: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
.third-table th:first-child, .third-table td:first-child { text-align: left; }
|
||||||
|
.third-table td {
|
||||||
|
padding: 10px 12px; text-align: right; font-variant-numeric: tabular-nums;
|
||||||
|
border-top: 1px solid var(--line-soft); font-size: 13px;
|
||||||
|
}
|
||||||
|
.third-row.qual { background: linear-gradient(90deg, rgba(74,222,128,0.07), transparent); }
|
||||||
|
.third-row.cut td { border-top: 2px solid var(--turf-deep); }
|
||||||
|
.qual-badge {
|
||||||
|
font-family: var(--font-mono); font-size: 10px; padding: 2px 7px; border-radius: 999px;
|
||||||
|
}
|
||||||
|
.qual-badge.yes { background: rgba(74,222,128,0.16); color: var(--turf); }
|
||||||
|
.qual-badge.no { background: rgba(95,109,146,0.16); color: var(--ink-faint); }
|
||||||
|
|
||||||
|
/* Drittplatzierte: Teamname grün, wenn alle 3 Gruppenspiele gespielt */
|
||||||
|
.third-table td.team-complete { color: var(--turf); }
|
||||||
|
|
||||||
|
/* ---------- Bracket ---------- */
|
||||||
|
.bracket-banner {
|
||||||
|
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
||||||
|
background: var(--bg-card); border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius); padding: 14px 16px; margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.bracket-banner .k {
|
||||||
|
font-family: var(--font-mono); font-size: 12px; color: var(--ink-dim);
|
||||||
|
}
|
||||||
|
.bracket-banner .v { font-family: var(--font-mono); font-size: 12px; color: var(--turf); }
|
||||||
|
.bracket-scroll {
|
||||||
|
margin-left: -20px;
|
||||||
|
margin-right: -20px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: visible;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
scrollbar-gutter: stable;
|
||||||
|
}
|
||||||
|
.bracket {
|
||||||
|
display: flex; gap: 26px; min-width: max-content; align-items: stretch;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
.round { display: flex; flex-direction: column; min-width: 220px; }
|
||||||
|
.round-label {
|
||||||
|
font-family: var(--font-display); font-weight: 800; text-transform: uppercase;
|
||||||
|
font-size: 12px; letter-spacing: 0.06em; color: var(--ink-faint);
|
||||||
|
margin-bottom: 10px; padding-left: 2px;
|
||||||
|
}
|
||||||
|
.round-matches { display: flex; flex-direction: column; justify-content: space-around; flex: 1; gap: 12px; }
|
||||||
|
|
||||||
|
.tie {
|
||||||
|
background: var(--bg-card); border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius-sm); position: relative;
|
||||||
|
}
|
||||||
|
.tie.final-tie { border-color: var(--gold); box-shadow: 0 0 0 1px rgba(255,210,74,0.2); }
|
||||||
|
.tie-meta {
|
||||||
|
font-family: var(--font-mono); font-size: 9px; color: rgba(255,255,255,0.55);
|
||||||
|
letter-spacing: 0.04em; padding: 5px 10px 0;
|
||||||
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.match-badge {
|
||||||
|
position: absolute; top: -6px; right: -6px;
|
||||||
|
font-family: var(--font-mono); font-size: 9px; font-weight: 700;
|
||||||
|
line-height: 18px; min-width: 18px; text-align: center;
|
||||||
|
border-radius: 999px; padding: 0 4px;
|
||||||
|
background: #1a2744; color: #ffffff; border: 1px solid rgba(255,255,255,0.15);
|
||||||
|
}
|
||||||
|
.side {
|
||||||
|
display: flex; align-items: center; justify-content: space-between;
|
||||||
|
padding: 8px 10px; font-size: 13px;
|
||||||
|
}
|
||||||
|
.side + .side { border-top: 1px solid var(--line-soft); }
|
||||||
|
.side .nm { display: flex; align-items: center; gap: 7px; min-width: 0; }
|
||||||
|
.side .nm .c { font-family: var(--font-mono); font-size: 10px; color: var(--ink-faint); }
|
||||||
|
.side .lbl { color: var(--ink-dim); font-style: italic; }
|
||||||
|
.side .sc { font-family: var(--font-mono); font-weight: 700; color: var(--floodlight); }
|
||||||
|
.side.win .sc { color: var(--turf); }
|
||||||
|
.side .prob {
|
||||||
|
font-family: var(--font-mono); font-size: 10px; color: var(--ink-faint);
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 16px;
|
||||||
|
font-family: var(--font-mono); font-size: 11px; color: var(--ink-faint); }
|
||||||
|
.legend span { display: inline-flex; align-items: center; gap: 6px; }
|
||||||
|
.legend i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
|
||||||
|
|
||||||
|
/* Tooltip im K.o.-Baum (position: fixed, damit overflow-x den Tooltip nicht abschneidet) */
|
||||||
|
.kobaum-tip {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 200;
|
||||||
|
pointer-events: none;
|
||||||
|
background: var(--bg-card);
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 6px 9px;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 6px 20px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Zustände ---------- */
|
||||||
|
.notice {
|
||||||
|
background: var(--bg-card); border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius); padding: 18px 20px; color: var(--ink-dim);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.notice.err { border-color: #5a2230; color: #ffb0c0; }
|
||||||
|
.skel { background: var(--bg-card); border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius); height: 220px; animation: shimmer 1.4s infinite; }
|
||||||
|
@keyframes shimmer { 50% { opacity: .55; } }
|
||||||
|
|
||||||
|
.foot {
|
||||||
|
border-top: 1px solid var(--line); padding: 24px 0 48px;
|
||||||
|
color: var(--ink-faint); font-size: 12px; font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
.foot a { color: var(--ink-dim); text-decoration: underline; text-underline-offset: 2px; }
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
MOBIL — Breakpoint 640px (iPhone ~375, Galaxy ~412, alle ≤640)
|
||||||
|
===================================================================== */
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
body { font-size: 14px; }
|
||||||
|
.wrap { padding: 0 12px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Header ---------- */
|
||||||
|
.masthead { padding: 0 12px; }
|
||||||
|
.masthead-inner { padding: 10px 0; gap: 8px; }
|
||||||
|
.brand { gap: 6px; }
|
||||||
|
.brand-mark { font-size: 18px; }
|
||||||
|
.brand-sub { font-size: 9px; letter-spacing: 0.04em; }
|
||||||
|
.status-pill { font-size: 10px; padding: 4px 10px; gap: 5px; }
|
||||||
|
.dot { width: 6px; height: 6px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Tabs (zwei Zeilen, kein horizontaler Scroll) ---------- */
|
||||||
|
.masthead-tabs {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px 4px;
|
||||||
|
}
|
||||||
|
.tab { padding: 8px 13px; font-size: 12px; }
|
||||||
|
|
||||||
|
.section { padding: 18px 0 48px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Gruppen ---------- */
|
||||||
|
.group-grid { grid-template-columns: 1fr; gap: 12px; }
|
||||||
|
.group-head { padding: 10px 12px; }
|
||||||
|
.group-name { font-size: 14px; }
|
||||||
|
.standings th { font-size: 9px; padding: 6px 3px; }
|
||||||
|
.standings th.team { padding-left: 10px; }
|
||||||
|
.standings td { font-size: 11px; padding: 7px 3px; }
|
||||||
|
.standings td.team { padding-left: 10px; gap: 6px; }
|
||||||
|
.rankdot { width: 16px; height: 16px; font-size: 8px; }
|
||||||
|
.team-name { font-size: 12px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Spiele (Fixtures) ---------- */
|
||||||
|
.fx { grid-template-columns: 1fr; gap: 8px; padding: 10px 12px; }
|
||||||
|
.fx-meta { flex-direction: row; gap: 14px; align-items: center; }
|
||||||
|
.fx-status { order: -1; }
|
||||||
|
.fx-teams { column-gap: 16px; }
|
||||||
|
.fx-score { font-size: 16px; min-width: 44px; }
|
||||||
|
.fx-vs { font-size: 14px; min-width: 44px; }
|
||||||
|
.fx-name { font-size: 13px; max-width: 110px; }
|
||||||
|
.grp-switch { gap: 8px; }
|
||||||
|
.grp-chip { width: 40px; height: 40px; font-size: 14px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Drittplatzierte ---------- */
|
||||||
|
.third-table th { font-size: 9px; padding: 8px 6px; }
|
||||||
|
.third-table td { font-size: 11px; padding: 7px 6px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: K.o.-Baum ---------- */
|
||||||
|
.bracket-scroll {
|
||||||
|
margin-left: -12px;
|
||||||
|
margin-right: -12px;
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
.bracket { gap: 18px; }
|
||||||
|
.round { min-width: 170px; }
|
||||||
|
.round-label { font-size: 10px; }
|
||||||
|
.round-matches { gap: 8px; }
|
||||||
|
.tie-meta { font-size: 8px; padding: 3px 8px 0; }
|
||||||
|
.side { padding: 6px 8px; font-size: 11px; }
|
||||||
|
.side .nm { gap: 5px; }
|
||||||
|
.prov-mark { font-size: 10px; }
|
||||||
|
.side .prob { font-size: 9px; }
|
||||||
|
.bracket-banner { padding: 10px 12px; font-size: 13px; }
|
||||||
|
.legend { font-size: 10px; gap: 12px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Simulation ---------- */
|
||||||
|
.sim-row { flex-wrap: wrap; gap: 6px; padding: 8px 10px; }
|
||||||
|
.sim-row-phase { min-width: 100%; font-size: 9px; }
|
||||||
|
.sim-row-date { min-width: auto; font-size: 9px; }
|
||||||
|
.sim-row input[type="number"] { width: 32px; height: 32px; font-size: 15px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Footer ---------- */
|
||||||
|
.foot { font-size: 11px; padding: 16px 0 32px; }
|
||||||
|
|
||||||
|
/* Kein horizontaler Überlauf außer im Bracket */
|
||||||
|
body { overflow-x: hidden; }
|
||||||
|
.bracket-scroll { overflow-x: auto; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============ Erweiterungen v2 ============ */
|
||||||
|
|
||||||
|
/* Flaggen / Wappen */
|
||||||
|
.flag {
|
||||||
|
border-radius: 50%; object-fit: cover; flex: none;
|
||||||
|
background: var(--bg-raised); border: 1px solid var(--line-soft);
|
||||||
|
}
|
||||||
|
.flag-fallback {
|
||||||
|
display: grid; place-items: center;
|
||||||
|
font-family: var(--font-mono); font-size: 9px; color: var(--ink-faint);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gruppen-Header als Button */
|
||||||
|
.group-head-btn {
|
||||||
|
width: 100%; cursor: pointer; text-align: left;
|
||||||
|
font: inherit; color: inherit;
|
||||||
|
transition: background .15s;
|
||||||
|
}
|
||||||
|
.group-head-btn:hover { background: var(--bg-card); }
|
||||||
|
.group-head-btn:hover .group-tag { color: var(--turf); }
|
||||||
|
.group-head-btn:focus-visible { outline: 2px solid var(--turf); outline-offset: -2px; }
|
||||||
|
|
||||||
|
/* Gruppen-Wechsler im Spiele-Tab */
|
||||||
|
.grp-switch { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 20px; }
|
||||||
|
.grp-chip {
|
||||||
|
width: 38px; height: 38px; border-radius: 8px;
|
||||||
|
border: 1px solid var(--line); background: var(--bg-card);
|
||||||
|
color: var(--ink-dim); font-family: var(--font-display); font-weight: 700;
|
||||||
|
font-size: 14px; cursor: pointer; transition: all .15s;
|
||||||
|
}
|
||||||
|
.grp-chip:hover { border-color: var(--turf); color: var(--ink); }
|
||||||
|
.grp-chip.active { background: var(--turf); color: var(--bg); border-color: var(--turf); }
|
||||||
|
|
||||||
|
/* Spiele-Karten */
|
||||||
|
.fixtures { display: flex; flex-direction: column; gap: 10px; }
|
||||||
|
.fx {
|
||||||
|
background: var(--bg-card); border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius); padding: 12px 16px;
|
||||||
|
display: grid; grid-template-columns: 110px minmax(0, 560px) 1fr; gap: 14px; align-items: center;
|
||||||
|
}
|
||||||
|
.fx-live { border-color: rgba(255,61,127,0.4); }
|
||||||
|
.fx-status {
|
||||||
|
display: flex; align-items: center; gap: 7px;
|
||||||
|
font-family: var(--font-mono); font-size: 12px; color: var(--ink-dim);
|
||||||
|
}
|
||||||
|
.fx-teams {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
||||||
|
align-items: center; column-gap: 34px;
|
||||||
|
}
|
||||||
|
/* Beide Teams: Flagge links, Name daneben. Linkes Team rechtsbündig an den Score,
|
||||||
|
rechtes Team linksbündig – so ist der Abstand zum Ergebnis beidseitig gleich. */
|
||||||
|
.fx-team { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
||||||
|
.fx-team.home { justify-content: flex-end; }
|
||||||
|
.fx-team.away { justify-content: flex-start; }
|
||||||
|
.fx-team .fx-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||||
|
.fx-team.win .fx-name { color: var(--turf); }
|
||||||
|
.fx-score { font-family: var(--font-mono); font-weight: 700; font-size: 18px; color: var(--floodlight); white-space: nowrap; text-align: center; min-width: 54px; }
|
||||||
|
.fx-score.score-live { color: var(--live); }
|
||||||
|
.fx-vs { font-family: var(--font-mono); font-size: 15px; color: var(--ink-faint); text-align: center; min-width: 54px; }
|
||||||
|
.fx-meta {
|
||||||
|
display: flex; flex-direction: column; gap: 3px; align-items: flex-end;
|
||||||
|
font-family: var(--font-mono); font-size: 11px; color: var(--ink-faint); white-space: nowrap;
|
||||||
|
}
|
||||||
|
/* Austragungsort heller hervorheben. */
|
||||||
|
.fx-venue { color: var(--ink-dim); }
|
||||||
|
|
||||||
|
/* Live-Tabelle der Gruppe unterhalb der Spiele. */
|
||||||
|
.fx-standings { margin-top: 22px; }
|
||||||
|
.fx-standings-title {
|
||||||
|
font-family: var(--font-display, var(--font-mono)); font-size: 13px; letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase; color: var(--ink-dim); margin: 0 2px 10px;
|
||||||
|
display: flex; align-items: center; gap: 10px;
|
||||||
|
}
|
||||||
|
.fx-standings-live {
|
||||||
|
font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em;
|
||||||
|
color: var(--live); font-weight: 700;
|
||||||
|
animation: livepulse 1.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
.fx-standings .standings { width: 100%; }
|
||||||
|
/* Zeile eines Teams mit laufendem Spiel hervorheben. */
|
||||||
|
.fx-standings .row-live { background: rgba(255, 61, 127, 0.07); }
|
||||||
|
.fx-standings .row-live .team-name { color: var(--floodlight); }
|
||||||
|
.row-live-dot {
|
||||||
|
display: inline-block; width: 7px; height: 7px; border-radius: 50%;
|
||||||
|
background: var(--live); margin-left: 8px; vertical-align: middle;
|
||||||
|
animation: livepulse 1.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes livepulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.35; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 720px) {
|
||||||
|
.fx { grid-template-columns: 1fr; gap: 8px; }
|
||||||
|
.fx-meta { flex-direction: row; gap: 14px; align-items: center; }
|
||||||
|
.fx-status { order: -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bracket: Label-Header braucht kein Extra-Padding mehr (sitzt im Kasten) */
|
||||||
|
.round-matches { padding-top: 0; }
|
||||||
|
|
||||||
|
/* Bracket: fix vs. vorläufig.
|
||||||
|
.nm trägt die Standardfarbe; Team-Name liegt in .tn. */
|
||||||
|
.side .nm .tn { color: var(--ink); }
|
||||||
|
|
||||||
|
/* vorläufig: gedimmt + kursiv + Marker */
|
||||||
|
.side.prov .nm .tn { color: var(--ink-dim); font-style: italic; }
|
||||||
|
.prov-mark {
|
||||||
|
color: #f0a23a; font-family: var(--font-mono); font-weight: 700;
|
||||||
|
font-size: 12px; margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix: echtes Team steht fest -> fett weiß + grüner Marker links */
|
||||||
|
.side.fix .nm .tn { color: #ffffff; font-weight: 700; }
|
||||||
|
.side.fix { box-shadow: inset 3px 0 0 var(--turf-deep); }
|
||||||
|
|
||||||
|
/* Sieger eines bereits gespielten Tie sticht zusätzlich grün hervor */
|
||||||
|
.side.win .nm .tn { color: var(--turf); font-weight: 700; }
|
||||||
|
.side.win { box-shadow: inset 3px 0 0 var(--turf); }
|
||||||
|
|
||||||
|
/* Legende-Marker */
|
||||||
|
.legend i.leg-fix { background: var(--turf-deep); }
|
||||||
|
.legend i.leg-prov {
|
||||||
|
background: repeating-linear-gradient(45deg, #f0a23a, #f0a23a 3px, transparent 3px, transparent 6px);
|
||||||
|
border: 1px solid #f0a23a;
|
||||||
|
}
|
||||||
67
app/[locale]/layout.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import Script from "next/script";
|
||||||
|
import { Locale, getDictionary } from "@/lib/i18n";
|
||||||
|
|
||||||
|
const BASE_URL = "https://soccer-2026.info";
|
||||||
|
|
||||||
|
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }): Promise<Metadata> {
|
||||||
|
const { locale } = await params;
|
||||||
|
const dict = getDictionary(locale as Locale);
|
||||||
|
return {
|
||||||
|
metadataBase: new URL(BASE_URL),
|
||||||
|
title: dict.meta.title,
|
||||||
|
description: dict.meta.description,
|
||||||
|
alternates: {
|
||||||
|
canonical: `${BASE_URL}/${locale}`,
|
||||||
|
languages: {
|
||||||
|
en: `${BASE_URL}/en`,
|
||||||
|
de: `${BASE_URL}/de`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
openGraph: {
|
||||||
|
title: dict.meta.title,
|
||||||
|
description: dict.meta.description,
|
||||||
|
url: `${BASE_URL}/${locale}`,
|
||||||
|
locale: locale === "en" ? "en_US" : "de_DE",
|
||||||
|
siteName: "WM 2026 Dashboard",
|
||||||
|
type: "website",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateStaticParams() {
|
||||||
|
return [{ locale: "en" }, { locale: "de" }];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function LocaleLayout({
|
||||||
|
children,
|
||||||
|
params,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
params: Promise<{ locale: string }>;
|
||||||
|
}) {
|
||||||
|
const { locale } = await params;
|
||||||
|
return (
|
||||||
|
<html lang={locale}>
|
||||||
|
<head>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Archivo:wght@500;700;800&family=Archivo+Expanded:wght@700;800&family=Inter:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{children}
|
||||||
|
{process.env.NEXT_PUBLIC_UMAMI_SRC && process.env.NEXT_PUBLIC_UMAMI_ID && (
|
||||||
|
<Script
|
||||||
|
defer
|
||||||
|
src={process.env.NEXT_PUBLIC_UMAMI_SRC}
|
||||||
|
data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID}
|
||||||
|
strategy="afterInteractive"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState, useCallback } from "react";
|
import { useEffect, useState, useCallback, useMemo, use } from "react";
|
||||||
import { GroupId, GroupTable, Match, Team, ThirdPlaceRow } from "@/lib/types";
|
import { GroupId, GroupTable, Match, Team, ThirdPlaceRow } from "@/lib/types";
|
||||||
import { ThirdAssignment } from "@/lib/bracket";
|
import { ThirdAssignment } from "@/lib/bracket";
|
||||||
|
import { getDictionary, Locale, Dictionary } from "@/lib/i18n";
|
||||||
import Groups from "./components/Groups";
|
import Groups from "./components/Groups";
|
||||||
import ThirdPlace from "./components/ThirdPlace";
|
import ThirdPlace from "./components/ThirdPlace";
|
||||||
import Bracket from "./components/Bracket";
|
import Bracket from "./components/Bracket";
|
||||||
import Fixtures from "./components/Fixtures";
|
import Fixtures from "./components/Fixtures";
|
||||||
import Simulation from "./components/Simulation";
|
import Simulation from "./components/Simulation";
|
||||||
|
import KoFixtures from "./components/KoFixtures";
|
||||||
|
|
||||||
interface ApiData {
|
interface ApiData {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
@@ -16,22 +18,25 @@ interface ApiData {
|
|||||||
groupTables: GroupTable[];
|
groupTables: GroupTable[];
|
||||||
groupTablesLive: GroupTable[];
|
groupTablesLive: GroupTable[];
|
||||||
thirdTable: ThirdPlaceRow[];
|
thirdTable: ThirdPlaceRow[];
|
||||||
|
secureThirdTeams: string[];
|
||||||
annexAssignment: ThirdAssignment | null;
|
annexAssignment: ThirdAssignment | null;
|
||||||
annexResolved: boolean;
|
annexResolved: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tab = "groups" | "fixtures" | "thirds" | "bracket" | "sim";
|
type Tab = "groups" | "groupfixtures" | "kofixtures" | "thirds" | "bracket" | "sim";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home({ params }: { params: Promise<{ locale: string }> }) {
|
||||||
|
const { locale } = use(params) as { locale: Locale };
|
||||||
|
const dict = useMemo(() => getDictionary(locale), [locale]);
|
||||||
const [data, setData] = useState<ApiData | null>(null);
|
const [data, setData] = useState<ApiData | null>(null);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [tab, setTab] = useState<Tab>("groups");
|
const [tab, setTab] = useState<Tab>("kofixtures");
|
||||||
// Zuletzt gewählte Gruppe für den Spiele-Tab. null = noch keine gewählt.
|
// Zuletzt gewählte Gruppe für den Spiele-Tab. null = noch keine gewählt.
|
||||||
const [fixturesGroup, setFixturesGroup] = useState<GroupId | null>(null);
|
const [fixturesGroup, setFixturesGroup] = useState<GroupId | null>(null);
|
||||||
|
|
||||||
const load = useCallback(async () => {
|
const load = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/matches", { cache: "no-store" });
|
const res = await fetch(`/api/matches?locale=${locale}&t=${Date.now()}`, { cache: "no-store", headers: { "Pragma": "no-cache", "Cache-Control": "no-cache" } });
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const body = await res.json().catch(() => ({}));
|
const body = await res.json().catch(() => ({}));
|
||||||
throw new Error(body.detail || `Fehler ${res.status}`);
|
throw new Error(body.detail || `Fehler ${res.status}`);
|
||||||
@@ -41,7 +46,7 @@ export default function Home() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e instanceof Error ? e.message : "Verbindung fehlgeschlagen");
|
setError(e instanceof Error ? e.message : "Verbindung fehlgeschlagen");
|
||||||
}
|
}
|
||||||
}, []);
|
}, [locale]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
load();
|
load();
|
||||||
@@ -52,9 +57,14 @@ export default function Home() {
|
|||||||
// Klick auf einen Gruppen-Header: Gruppe merken und zum Spiele-Tab wechseln.
|
// Klick auf einen Gruppen-Header: Gruppe merken und zum Spiele-Tab wechseln.
|
||||||
const openGroupFixtures = useCallback((g: GroupId) => {
|
const openGroupFixtures = useCallback((g: GroupId) => {
|
||||||
setFixturesGroup(g);
|
setFixturesGroup(g);
|
||||||
setTab("fixtures");
|
setTab("groupfixtures");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Tab-Wechsel: nach ganz oben scrollen
|
||||||
|
useEffect(() => {
|
||||||
|
window.scrollTo({ top: 0, behavior: "auto" });
|
||||||
|
}, [tab]);
|
||||||
|
|
||||||
const anyLive = data?.matches.some(
|
const anyLive = data?.matches.some(
|
||||||
(m) => m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED",
|
(m) => m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED",
|
||||||
);
|
);
|
||||||
@@ -65,34 +75,37 @@ export default function Home() {
|
|||||||
<div className="wrap masthead-inner">
|
<div className="wrap masthead-inner">
|
||||||
<div className="brand">
|
<div className="brand">
|
||||||
<span className="brand-mark">WM <span className="accent">26</span></span>
|
<span className="brand-mark">WM <span className="accent">26</span></span>
|
||||||
<span className="brand-sub">USA · Kanada · Mexiko</span>
|
<span className="brand-sub">{dict.header.hostCountries}</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="status-pill">
|
<span className="status-pill">
|
||||||
<span className={`dot ${anyLive ? "live" : data ? "on" : ""}`} />
|
<span className={`dot ${anyLive ? "live" : data ? "on" : ""}`} />
|
||||||
{error
|
{error
|
||||||
? "Feed offline"
|
? dict.status.feedOffline
|
||||||
: data
|
: data
|
||||||
? anyLive ? "Live" : `Aktualisiert ${new Date(data.updatedAt).toLocaleTimeString("de-DE")}`
|
? anyLive ? dict.status.live : dict.status.updated(new Date(data.updatedAt).toLocaleTimeString(locale === "en" ? "en-US" : "de-DE"))
|
||||||
: "Lade Daten…"}
|
: dict.status.loading}
|
||||||
</span>
|
</span>
|
||||||
<nav className="tabs masthead-tabs">
|
<nav className="tabs masthead-tabs">
|
||||||
|
<button className={`tab ${tab === "kofixtures" ? "active" : ""}`} onClick={() => setTab("kofixtures")}>
|
||||||
|
{dict.nav.koFixtures}
|
||||||
|
</button>
|
||||||
<button className={`tab ${tab === "groups" ? "active" : ""}`} onClick={() => setTab("groups")}>
|
<button className={`tab ${tab === "groups" ? "active" : ""}`} onClick={() => setTab("groups")}>
|
||||||
Gruppen
|
{dict.nav.groups}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`tab ${tab === "fixtures" ? "active" : ""}`}
|
className={`tab ${tab === "groupfixtures" ? "active" : ""}`}
|
||||||
onClick={() => { if (!fixturesGroup) setFixturesGroup("A"); setTab("fixtures"); }}
|
onClick={() => { if (!fixturesGroup) setFixturesGroup("A"); setTab("groupfixtures"); }}
|
||||||
>
|
>
|
||||||
{fixturesGroup ? `Spiele – Gruppe ${fixturesGroup}` : "Spiele"}
|
{fixturesGroup ? dict.nav.groupFixtures(fixturesGroup) : dict.nav.groupFixturesNoGroup}
|
||||||
</button>
|
</button>
|
||||||
<button className={`tab ${tab === "thirds" ? "active" : ""}`} onClick={() => setTab("thirds")}>
|
<button className={`tab ${tab === "thirds" ? "active" : ""}`} onClick={() => setTab("thirds")}>
|
||||||
Drittplatzierte
|
{dict.nav.thirdPlace}
|
||||||
</button>
|
</button>
|
||||||
<button className={`tab ${tab === "bracket" ? "active" : ""}`} onClick={() => setTab("bracket")}>
|
<button className={`tab ${tab === "bracket" ? "active" : ""}`} onClick={() => setTab("bracket")}>
|
||||||
K.o.-Baum
|
{dict.nav.bracket}
|
||||||
</button>
|
</button>
|
||||||
<button className={`tab ${tab === "sim" ? "active" : ""}`} onClick={() => setTab("sim")}>
|
<button className={`tab ${tab === "sim" ? "active" : ""}`} onClick={() => setTab("sim")}>
|
||||||
Simulation
|
{dict.nav.simulation}
|
||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,9 +116,7 @@ export default function Home() {
|
|||||||
<section className="section">
|
<section className="section">
|
||||||
{error && (
|
{error && (
|
||||||
<div className="notice err">
|
<div className="notice err">
|
||||||
Die Live-Feeds sind gerade nicht erreichbar: {error}.
|
{dict.error.feedUnreachable}
|
||||||
Prüfe den <code>FOOTBALL_DATA_TOKEN</code> und die Netzwerkfreigabe des Servers.
|
|
||||||
Die Seite versucht es automatisch erneut.
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -115,38 +126,76 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{data && tab === "kofixtures" && (
|
||||||
|
<KoFixtures teams={data.teams} matches={data.matches} dict={dict} locale={locale} />
|
||||||
|
)}
|
||||||
{data && tab === "groups" && (
|
{data && tab === "groups" && (
|
||||||
<Groups
|
<Groups
|
||||||
tables={data.groupTablesLive} teams={data.teams} matches={data.matches}
|
tables={data.groupTablesLive} teams={data.teams} matches={data.matches}
|
||||||
onOpenGroup={openGroupFixtures}
|
onOpenGroup={openGroupFixtures} dict={dict} locale={locale}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{data && tab === "fixtures" && fixturesGroup && (
|
{data && tab === "groupfixtures" && fixturesGroup && (
|
||||||
<Fixtures
|
<Fixtures
|
||||||
group={fixturesGroup} teams={data.teams} matches={data.matches}
|
group={fixturesGroup} teams={data.teams} matches={data.matches}
|
||||||
onSelectGroup={setFixturesGroup}
|
onSelectGroup={setFixturesGroup} dict={dict} locale={locale}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{data && tab === "thirds" && (
|
{data && tab === "thirds" && (
|
||||||
<ThirdPlace rows={data.thirdTable} teams={data.teams} />
|
<ThirdPlace rows={data.thirdTable} teams={data.teams} secureTeams={data.secureThirdTeams} dict={dict} />
|
||||||
)}
|
)}
|
||||||
{data && tab === "bracket" && (
|
{data && tab === "bracket" && (
|
||||||
<Bracket
|
<Bracket
|
||||||
matches={data.matches} teams={data.teams} tables={data.groupTablesLive}
|
matches={data.matches} teams={data.teams} tables={data.groupTablesLive}
|
||||||
thirds={data.thirdTable} assignment={data.annexAssignment}
|
thirds={data.thirdTable} assignment={data.annexAssignment}
|
||||||
annexResolved={data.annexResolved}
|
annexResolved={data.annexResolved} dict={dict} locale={locale}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{data && tab === "sim" && (
|
{data && tab === "sim" && (
|
||||||
<Simulation teams={data.teams} matches={data.matches} />
|
<Simulation teams={data.teams} matches={data.matches} dict={dict} locale={locale} />
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer className="foot">
|
<footer style={{
|
||||||
<div className="wrap">
|
borderTop: "1px solid var(--line-soft)",
|
||||||
Daten: football-data.org (Spiele & Tabellen) · Polymarket Gamma API (Wahrscheinlichkeiten) ·
|
padding: "24px 0",
|
||||||
Annex-C-Zuordnung nach den FIFA-Wettbewerbsregeln WM 2026. Kein offizielles FIFA-Produkt.
|
marginTop: 40,
|
||||||
|
}}>
|
||||||
|
<div className="wrap" style={{
|
||||||
|
display: "flex", flexDirection: "column", alignItems: "center", gap: 8,
|
||||||
|
}}>
|
||||||
|
<div style={{
|
||||||
|
display: "flex", alignItems: "center", gap: 12,
|
||||||
|
}}>
|
||||||
|
<span style={{
|
||||||
|
display: "inline-flex", alignItems: "center", justifyContent: "center",
|
||||||
|
width: 28, height: 28,
|
||||||
|
fontFamily: "var(--font-display)", fontSize: 13, fontWeight: 700,
|
||||||
|
color: "var(--ink-dim)", background: "var(--bg-card)",
|
||||||
|
border: "1px solid var(--line-soft)", borderRadius: "var(--radius-sm)",
|
||||||
|
}}>
|
||||||
|
AK
|
||||||
|
</span>
|
||||||
|
<a href="#" style={{
|
||||||
|
fontFamily: "var(--font-mono)", fontSize: 12,
|
||||||
|
color: "var(--ink-faint)", textDecoration: "none",
|
||||||
|
}}>
|
||||||
|
Andreas Knuth
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<span style={{
|
||||||
|
fontFamily: "var(--font-mono)", fontSize: 10,
|
||||||
|
color: "var(--ink-faint)",
|
||||||
|
}}>
|
||||||
|
{dict.footer.dashboard}
|
||||||
|
</span>
|
||||||
|
<span style={{
|
||||||
|
fontFamily: "var(--font-mono)", fontSize: 9,
|
||||||
|
color: "var(--ink-faint)", opacity: 0.5, marginTop: 8,
|
||||||
|
}}>
|
||||||
|
{dict.footer.dataSources}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</>
|
</>
|
||||||
78
app/api/live/route.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import type { NextRequest } from "next/server";
|
||||||
|
import { fetchMatchesAndTeamsFifa, fetchFifaScores, applyFifaScores, attachFifaGoals } from "@/lib/feeds";
|
||||||
|
import type { Match, Team } from "@/lib/types";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
const RECENT_MS = 60 * 60 * 1000;
|
||||||
|
const MATCH_DURATION = 2.5 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
function isRecentlyFinished(m: Match): boolean {
|
||||||
|
if (m.status !== "FINISHED") return false;
|
||||||
|
const kickoff = new Date(m.utcDate).getTime();
|
||||||
|
if (isNaN(kickoff)) return false;
|
||||||
|
return kickoff + MATCH_DURATION > Date.now() - RECENT_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
const locale = request.nextUrl.searchParams.get("locale") || "de";
|
||||||
|
try {
|
||||||
|
const { matches: rawMatches, teams } = await fetchMatchesAndTeamsFifa(locale);
|
||||||
|
|
||||||
|
const relevant = rawMatches.filter(m =>
|
||||||
|
m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED" || isRecentlyFinished(m),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (relevant.length === 0) {
|
||||||
|
return NextResponse.json({
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
liveCount: 0,
|
||||||
|
recentCount: 0,
|
||||||
|
teams: [] as Team[],
|
||||||
|
matches: [] as Match[],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let fifaData: Awaited<ReturnType<typeof fetchFifaScores>>;
|
||||||
|
try {
|
||||||
|
fifaData = await fetchFifaScores();
|
||||||
|
} catch {
|
||||||
|
return NextResponse.json({
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
liveCount: relevant.filter(m => m.status !== "FINISHED").length,
|
||||||
|
recentCount: relevant.filter(m => m.status === "FINISHED").length,
|
||||||
|
teams,
|
||||||
|
matches: relevant,
|
||||||
|
goalsFailed: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let matches = applyFifaScores(relevant, teams, fifaData);
|
||||||
|
let goalsFailed = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
matches = await attachFifaGoals(matches, fifaData, locale);
|
||||||
|
} catch {
|
||||||
|
goalsFailed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const liveCount = matches.filter(m => m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED").length;
|
||||||
|
const recentCount = matches.filter(m => m.status === "FINISHED" && isRecentlyFinished(m)).length;
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
liveCount,
|
||||||
|
recentCount,
|
||||||
|
teams,
|
||||||
|
matches,
|
||||||
|
goalsFailed,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
const message = err instanceof Error ? err.message : "unbekannter Fehler";
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Live-Feed nicht erreichbar", detail: message },
|
||||||
|
{ status: 502 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,51 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { fetchMatchesAndTeams, fetchOdds, attachOdds } from "@/lib/feeds";
|
import type { NextRequest } from "next/server";
|
||||||
|
import { fetchMatchesAndTeamsFifa, fetchOdds, attachOdds, attachKOOdds, attachFifaLiveData } from "@/lib/feeds";
|
||||||
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
|
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
|
||||||
import { qualifiedThirdGroups, resolveAnnexC } from "@/lib/bracket";
|
import { qualifiedThirdGroups, resolveAnnexC } from "@/lib/bracket";
|
||||||
|
import { securelyQualifiedThirdTeams } from "@/lib/third-place-security";
|
||||||
|
|
||||||
// Diese Route wird vom Frontend gepollt. Sie ist der einzige Ort, der die
|
// Diese Route wird vom Frontend gepollt. FIFA-API als Primärquelle.
|
||||||
// Upstream-Feeds berührt — gecacht, damit Rate Limits eingehalten werden.
|
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET(request: NextRequest) {
|
||||||
|
const locale = request.nextUrl.searchParams.get("locale") || "de";
|
||||||
try {
|
try {
|
||||||
const { matches: rawMatches, teams } = await fetchMatchesAndTeams();
|
const { matches: rawMatches, teams } = await fetchMatchesAndTeamsFifa(locale);
|
||||||
|
|
||||||
// Odds sind optional: fällt der Polymarket-Call aus, liefern wir trotzdem.
|
// Odds sind optional: fällt der Polymarket-Call aus, liefern wir trotzdem.
|
||||||
let matches = rawMatches;
|
let matches = rawMatches;
|
||||||
|
let odds: Awaited<ReturnType<typeof fetchOdds>> | null = null;
|
||||||
try {
|
try {
|
||||||
const odds = await fetchOdds();
|
odds = await fetchOdds();
|
||||||
matches = attachOdds(rawMatches, teams, odds);
|
matches = attachOdds(rawMatches, teams, odds);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("[polymarket] fetchOdds fehlgeschlagen:", err);
|
console.error("[polymarket] fetchOdds fehlgeschlagen:", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (odds) {
|
||||||
|
matches = attachKOOdds(matches, teams, odds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIFA-Live-Scores als häufiger gecachtes Overlay (Pipeline: Scores → Goals)
|
||||||
|
try {
|
||||||
|
matches = await attachFifaLiveData(matches, teams, locale);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("[fifa] Live-Overlay fehlgeschlagen:", err instanceof Error ? err.message : err);
|
||||||
|
}
|
||||||
|
|
||||||
const groupTables = computeGroupTables(teams, matches);
|
const groupTables = computeGroupTables(teams, matches);
|
||||||
const groupTablesLive = computeGroupTables(teams, matches, true);
|
const groupTablesLive = computeGroupTables(teams, matches, true);
|
||||||
|
|
||||||
// prob-Feld normalisieren: immer null statt undefined, damit JSON konsistent ist
|
|
||||||
const normalizedMatches = matches.map((m) => ({ ...m, prob: m.prob ?? null }));
|
const normalizedMatches = matches.map((m) => ({ ...m, prob: m.prob ?? null }));
|
||||||
|
|
||||||
const thirdTable = computeThirdPlaceTable(groupTablesLive);
|
const thirdTable = computeThirdPlaceTable(groupTablesLive);
|
||||||
const qGroups = qualifiedThirdGroups(thirdTable);
|
const qGroups = qualifiedThirdGroups(thirdTable);
|
||||||
const annex = qGroups.length === 8 ? resolveAnnexC(qGroups) : null;
|
const annex = qGroups.length === 8 ? resolveAnnexC(qGroups) : null;
|
||||||
|
|
||||||
|
// Sichere Drittplatzierte (Team-IDs, deren Top-8-Platz mathematisch feststeht)
|
||||||
|
const secureThirdTeams = securelyQualifiedThirdTeams(matches, teams);
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
teams,
|
teams,
|
||||||
@@ -37,6 +53,7 @@ export async function GET() {
|
|||||||
groupTables,
|
groupTables,
|
||||||
groupTablesLive,
|
groupTablesLive,
|
||||||
thirdTable,
|
thirdTable,
|
||||||
|
secureThirdTeams: [...secureThirdTeams],
|
||||||
annexAssignment: annex,
|
annexAssignment: annex,
|
||||||
annexResolved: annex != null,
|
annexResolved: annex != null,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { Team } from "@/lib/types";
|
|
||||||
|
|
||||||
// Zeigt die Flagge/das Wappen eines Teams. Fällt auf ein neutrales Rund
|
|
||||||
// zurück, wenn keine crest-URL vorliegt. SVG-Crests (football-data) skalieren
|
|
||||||
// sauber; das Rendern als rundes Bild gibt den Flaggen-Look aus dem Screenshot.
|
|
||||||
export default function Flag({
|
|
||||||
team, size = 22,
|
|
||||||
}: { team?: Team; size?: number }) {
|
|
||||||
const style = { width: size, height: size } as const;
|
|
||||||
if (team?.crest) {
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
src={team.crest}
|
|
||||||
alt={team.code || team.localisedName || team.name}
|
|
||||||
className="flag"
|
|
||||||
style={style}
|
|
||||||
loading="lazy"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Fallback: Kreis mit Ländercode
|
|
||||||
return (
|
|
||||||
<span className="flag flag-fallback" style={style} aria-hidden>
|
|
||||||
{team?.code?.slice(0, 2) || "··"}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { useState, useMemo, useCallback, useEffect } from "react";
|
|
||||||
import { Match, Team } from "@/lib/types";
|
|
||||||
import { computeGroupTables, computeThirdPlaceTable } from "@/lib/standings";
|
|
||||||
import { qualifiedThirdGroups, resolveAnnexC, LATER_ROUNDS } from "@/lib/bracket";
|
|
||||||
import { resolveBracket, ResolvedTie } from "@/lib/resolve-bracket";
|
|
||||||
import {
|
|
||||||
loadOverrides, saveOverrides, buildSimMatches,
|
|
||||||
defaultScore, SimOverrides,
|
|
||||||
} from "@/lib/simulation";
|
|
||||||
import Bracket from "./Bracket";
|
|
||||||
import ThirdPlace from "./ThirdPlace";
|
|
||||||
import Flag from "./Flag";
|
|
||||||
|
|
||||||
function teamById(teams: Team[], id: string | null) {
|
|
||||||
return id ? teams.find((t) => t.id === id) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fmtDate(iso: string): string {
|
|
||||||
const d = new Date(iso);
|
|
||||||
return d.toLocaleString("de-DE", {
|
|
||||||
weekday: "short", day: "2-digit", month: "2-digit",
|
|
||||||
hour: "2-digit", minute: "2-digit",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Label für die Spielphase in der Liste
|
|
||||||
function phaseLabel(match: Match): string {
|
|
||||||
if (match.stage === "GROUP" && match.group) return `Gruppe ${match.group}`;
|
|
||||||
if (match.stage === "R32") return "Sechzehntelfinale";
|
|
||||||
if (match.stage === "R16") return "Achtelfinale";
|
|
||||||
if (match.stage === "QF") return "Viertelfinale";
|
|
||||||
if (match.stage === "SF") return "Halbfinale";
|
|
||||||
if (match.stage === "3RD") return "Spiel um Platz 3";
|
|
||||||
if (match.stage === "FINAL") return "Finale";
|
|
||||||
return match.stage;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Simulation({ teams, matches }: { teams: Team[]; matches: Match[] }) {
|
|
||||||
const [overrides, setOverrides] = useState<SimOverrides>({});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setOverrides(loadOverrides());
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleScore = useCallback((matchId: string, homeScore: number, awayScore: number) => {
|
|
||||||
setOverrides((prev) => {
|
|
||||||
const next = { ...prev, [matchId]: { homeScore, awayScore } };
|
|
||||||
saveOverrides(next);
|
|
||||||
return next;
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleReset = useCallback(() => {
|
|
||||||
setOverrides({});
|
|
||||||
saveOverrides({});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleClear = useCallback((matchId: string) => {
|
|
||||||
setOverrides((prev) => {
|
|
||||||
const next = { ...prev };
|
|
||||||
delete next[matchId];
|
|
||||||
saveOverrides(next);
|
|
||||||
return next;
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// ---- Simulations-Pipeline ----
|
|
||||||
const simMatches = useMemo(() => buildSimMatches(matches, overrides), [matches, overrides]);
|
|
||||||
const simTables = useMemo(() => computeGroupTables(teams, simMatches), [teams, simMatches]);
|
|
||||||
const simThirds = useMemo(() => computeThirdPlaceTable(simTables), [simTables]);
|
|
||||||
const simQGroups = useMemo(() => qualifiedThirdGroups(simThirds), [simThirds]);
|
|
||||||
const simAnnex = useMemo(
|
|
||||||
() => (simQGroups.length === 8 ? resolveAnnexC(simQGroups) : null),
|
|
||||||
[simQGroups],
|
|
||||||
);
|
|
||||||
const simAnnexResolved = simAnnex != null;
|
|
||||||
|
|
||||||
const simBracket = useMemo(
|
|
||||||
() => resolveBracket(simMatches, teams, simTables, simThirds, simAnnex, simAnnexResolved, true),
|
|
||||||
[simMatches, teams, simTables, simThirds, simAnnex, simAnnexResolved],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Echte Tabellen/Bracket für fix/provisional-Flags (nur tatsächlich FINISHED).
|
|
||||||
const realTables = useMemo(() => computeGroupTables(teams, matches), [teams, matches]);
|
|
||||||
const realThirds = useMemo(() => computeThirdPlaceTable(realTables), [realTables]);
|
|
||||||
const realQGroups = useMemo(() => qualifiedThirdGroups(realThirds), [realThirds]);
|
|
||||||
const realAnnex = useMemo(
|
|
||||||
() => (realQGroups.length === 8 ? resolveAnnexC(realQGroups) : null),
|
|
||||||
[realQGroups],
|
|
||||||
);
|
|
||||||
const realBracket = useMemo(
|
|
||||||
() => resolveBracket(matches, teams, realTables, realThirds, realAnnex, realAnnex != null),
|
|
||||||
[matches, teams, realTables, realThirds, realAnnex],
|
|
||||||
);
|
|
||||||
|
|
||||||
// R32: provisional-Flags aus dem echten Bracket übernehmen.
|
|
||||||
const realProvisional = useMemo(() => {
|
|
||||||
const m = new Map<number, { home: boolean; away: boolean }>();
|
|
||||||
for (const tie of realBracket.r32) {
|
|
||||||
m.set(tie.matchNumber, { home: tie.home.provisional, away: tie.away.provisional });
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}, [realBracket]);
|
|
||||||
|
|
||||||
// Folgerunden: decided-Flags aus echten Matches (status === FINISHED).
|
|
||||||
const realDecided = useMemo(() => {
|
|
||||||
const m = new Map<number, boolean>();
|
|
||||||
for (const mt of matches) {
|
|
||||||
if (mt.group == null && mt.matchNumber >= 73) {
|
|
||||||
m.set(mt.matchNumber, mt.status === "FINISHED");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}, [matches]);
|
|
||||||
|
|
||||||
// Sim-Bracket mit echten provisional-Flags mergen (inkl. Tooltip-Korrektur).
|
|
||||||
const preResolved = useMemo(() => {
|
|
||||||
const fixTooltip = (t: string | null, prov: boolean): string | null => {
|
|
||||||
if (!t) return t;
|
|
||||||
if (prov) return t.startsWith("aktuell ") ? t : `aktuell ${t}`;
|
|
||||||
return t.startsWith("aktuell ") ? t.slice(8) : t;
|
|
||||||
};
|
|
||||||
|
|
||||||
const r32Fixed: ResolvedTie[] = simBracket.r32.map((tie) => {
|
|
||||||
const rp = realProvisional.get(tie.matchNumber);
|
|
||||||
if (!rp) return tie;
|
|
||||||
return {
|
|
||||||
...tie,
|
|
||||||
home: { ...tie.home, provisional: rp.home, tooltip: fixTooltip(tie.home.tooltip, rp.home) },
|
|
||||||
away: { ...tie.away, provisional: rp.away, tooltip: fixTooltip(tie.away.tooltip, rp.away) },
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const laterFixed: Record<number, ResolvedTie> = {};
|
|
||||||
for (const km of LATER_ROUNDS) {
|
|
||||||
const tie = simBracket.later[km.matchNumber];
|
|
||||||
if (!tie) continue;
|
|
||||||
const homeProv = !(realDecided.get(km.fromHome) ?? false);
|
|
||||||
const awayProv = !(realDecided.get(km.fromAway) ?? false);
|
|
||||||
laterFixed[km.matchNumber] = {
|
|
||||||
...tie,
|
|
||||||
home: { ...tie.home, provisional: homeProv },
|
|
||||||
away: { ...tie.away, provisional: awayProv },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return { r32: r32Fixed, later: laterFixed };
|
|
||||||
}, [simBracket, realProvisional, realDecided]);
|
|
||||||
|
|
||||||
// ---- Eingabeliste: offene Spiele aus dem echten Feed ----
|
|
||||||
const openMatches = useMemo(
|
|
||||||
() =>
|
|
||||||
matches
|
|
||||||
.filter((m) => m.status !== "FINISHED")
|
|
||||||
.sort((a, b) => +new Date(a.utcDate) - +new Date(b.utcDate)),
|
|
||||||
[matches],
|
|
||||||
);
|
|
||||||
|
|
||||||
const groupPhase = openMatches.filter((m) => m.stage === "GROUP");
|
|
||||||
const koPhase = openMatches.filter((m) => m.stage !== "GROUP");
|
|
||||||
|
|
||||||
// KO-Eingaben erst freigeben, wenn alle Gruppenspiele beendet sind.
|
|
||||||
const groupPhaseComplete = matches
|
|
||||||
.filter((m) => m.group != null)
|
|
||||||
.every((m) => m.status === "FINISHED");
|
|
||||||
|
|
||||||
const hasChanges = Object.keys(overrides).length > 0;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="notice" style={{ marginBottom: 20 }}>
|
|
||||||
Simulation — Ergebnisse frei wählbar, beeinflusst nicht die echten Daten.
|
|
||||||
Alle ungespielten Spiele sind vorbelegt mit dem Polymarket-Favoriten.
|
|
||||||
Eingaben werden im Browser gespeichert.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* ---- Eingabeliste ---- */}
|
|
||||||
<div style={{ marginBottom: 28 }}>
|
|
||||||
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
|
|
||||||
<h3 style={{ fontFamily: "var(--font-display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-dim)", margin: 0 }}>
|
|
||||||
Offene Spiele ({openMatches.length})
|
|
||||||
</h3>
|
|
||||||
{hasChanges && (
|
|
||||||
<button
|
|
||||||
onClick={handleReset}
|
|
||||||
style={{
|
|
||||||
fontFamily: "var(--font-mono)", fontSize: 11,
|
|
||||||
color: "var(--ink-faint)", background: "var(--bg-card)",
|
|
||||||
border: "1px solid var(--line)", borderRadius: "var(--radius-sm)",
|
|
||||||
padding: "5px 12px", cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Auf Polymarket-Defaults zurücksetzen
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{groupPhase.length > 0 && (
|
|
||||||
<div style={{ marginBottom: 16 }}>
|
|
||||||
<div style={{ fontFamily: "var(--font-display)", fontSize: 12, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-faint)", marginBottom: 8 }}>
|
|
||||||
Gruppenphase
|
|
||||||
</div>
|
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
|
|
||||||
{groupPhase.map((m) => (
|
|
||||||
<SimRow key={m.id} match={m} teams={teams} overrides={overrides} onScore={handleScore} onClear={handleClear} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{koPhase.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<div style={{ fontFamily: "var(--font-display)", fontSize: 12, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-faint)", marginBottom: 8 }}>
|
|
||||||
K.o.-Phase
|
|
||||||
</div>
|
|
||||||
{groupPhaseComplete ? (
|
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
|
|
||||||
{koPhase.map((m) => (
|
|
||||||
<SimRow key={m.id} match={m} teams={teams} overrides={overrides} onScore={handleScore} onClear={handleClear} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="notice" style={{ fontSize: 13 }}>
|
|
||||||
K.o.-Spiele werden zur Eingabe freigegeben, sobald die Gruppenphase abgeschlossen ist.
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* ---- Drittplatzierte (simuliert) ---- */}
|
|
||||||
<h3 style={{ fontFamily: "var(--font-display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-dim)", margin: "0 0 12px" }}>
|
|
||||||
Drittplatzierte (simuliert)
|
|
||||||
</h3>
|
|
||||||
<ThirdPlace rows={simThirds} teams={teams} />
|
|
||||||
|
|
||||||
{/* ---- Simulierter K.o.-Baum ---- */}
|
|
||||||
<h3 style={{ fontFamily: "var(--font-display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--ink-dim)", margin: "28px 0 12px" }}>
|
|
||||||
Simulierter K.o.-Baum
|
|
||||||
</h3>
|
|
||||||
<Bracket
|
|
||||||
matches={simMatches}
|
|
||||||
teams={teams}
|
|
||||||
tables={simTables}
|
|
||||||
thirds={simThirds}
|
|
||||||
assignment={simAnnex}
|
|
||||||
annexResolved={simAnnexResolved}
|
|
||||||
preResolved={preResolved}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Einzelne Eingabezeile ----
|
|
||||||
function SimRow({
|
|
||||||
match, teams, overrides, onScore, onClear,
|
|
||||||
}: {
|
|
||||||
match: Match; teams: Team[]; overrides: SimOverrides; onScore: (id: string, h: number, a: number) => void;
|
|
||||||
onClear: (id: string) => void;
|
|
||||||
}) {
|
|
||||||
const home = teamById(teams, match.homeTeamId);
|
|
||||||
const away = teamById(teams, match.awayTeamId);
|
|
||||||
const def = defaultScore(match);
|
|
||||||
const ov = overrides[match.id];
|
|
||||||
const homeVal = ov?.homeScore ?? def?.homeScore;
|
|
||||||
const awayVal = ov?.awayScore ?? def?.awayScore;
|
|
||||||
const homeChanged = ov != null;
|
|
||||||
const isKO = match.stage !== "GROUP";
|
|
||||||
|
|
||||||
const inputStyle = (changed: boolean): React.CSSProperties => ({
|
|
||||||
width: 36,
|
|
||||||
height: 28,
|
|
||||||
textAlign: "center",
|
|
||||||
fontFamily: "var(--font-mono)",
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: 700,
|
|
||||||
color: changed ? "var(--turf)" : "var(--ink)",
|
|
||||||
background: "var(--bg-raised)",
|
|
||||||
border: `1px solid ${changed ? "var(--turf)" : "var(--line)"}`,
|
|
||||||
borderRadius: "var(--radius-sm)",
|
|
||||||
outline: "none",
|
|
||||||
MozAppearance: "textfield",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{
|
|
||||||
display: "flex", alignItems: "center", gap: 10,
|
|
||||||
padding: "6px 12px",
|
|
||||||
background: "var(--bg-card)", border: "1px solid var(--line-soft)",
|
|
||||||
borderRadius: "var(--radius-sm)",
|
|
||||||
fontSize: 13,
|
|
||||||
}}>
|
|
||||||
<span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-faint)", minWidth: 75 }}>
|
|
||||||
{phaseLabel(match)}
|
|
||||||
</span>
|
|
||||||
<span style={{ display: "flex", alignItems: "center", gap: 6, minWidth: 0, flex: 1, justifyContent: "flex-end" }}>
|
|
||||||
<Flag team={home} size={18} />
|
|
||||||
<span style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 140 }}>
|
|
||||||
{home?.localisedName ?? home?.name ?? "—"}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min={0}
|
|
||||||
style={inputStyle(homeChanged)}
|
|
||||||
value={homeVal ?? ""}
|
|
||||||
placeholder="–"
|
|
||||||
onChange={(e) => {
|
|
||||||
const v = parseInt(e.target.value, 10);
|
|
||||||
if (!isNaN(v) && v >= 0) {
|
|
||||||
onScore(match.id, v, awayVal ?? (isKO ? 0 : 1));
|
|
||||||
} else if (e.target.value === "") {
|
|
||||||
// Bei Leerung: Standard wiederherstellen
|
|
||||||
const fallback = def;
|
|
||||||
if (fallback) onScore(match.id, fallback.homeScore, fallback.awayScore);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<span style={{ fontFamily: "var(--font-mono)", fontWeight: 700, color: "var(--ink-faint)" }}>:</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min={0}
|
|
||||||
style={inputStyle(homeChanged)}
|
|
||||||
value={awayVal ?? ""}
|
|
||||||
placeholder="–"
|
|
||||||
onChange={(e) => {
|
|
||||||
const v = parseInt(e.target.value, 10);
|
|
||||||
if (!isNaN(v) && v >= 0) {
|
|
||||||
onScore(match.id, homeVal ?? (isKO ? 0 : 1), v);
|
|
||||||
} else if (e.target.value === "") {
|
|
||||||
const fallback = def;
|
|
||||||
if (fallback) onScore(match.id, fallback.homeScore, fallback.awayScore);
|
|
||||||
else onClear(match.id);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<span style={{ display: "flex", alignItems: "center", gap: 6, minWidth: 0, flex: 1 }}>
|
|
||||||
<span style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 140 }}>
|
|
||||||
{away?.localisedName ?? away?.name ?? "—"}
|
|
||||||
</span>
|
|
||||||
<Flag team={away} size={18} />
|
|
||||||
</span>
|
|
||||||
<span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--ink-faint)", minWidth: 100, textAlign: "right" }}>
|
|
||||||
{fmtDate(match.utcDate)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
123
app/globals.css
@@ -47,7 +47,7 @@ body {
|
|||||||
|
|
||||||
a { color: inherit; text-decoration: none; }
|
a { color: inherit; text-decoration: none; }
|
||||||
|
|
||||||
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 20px; }
|
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 20px 0 0; }
|
||||||
|
|
||||||
/* ---------- Header / Hero ---------- */
|
/* ---------- Header / Hero ---------- */
|
||||||
.masthead {
|
.masthead {
|
||||||
@@ -180,6 +180,9 @@ table.standings { width: 100%; border-collapse: collapse; }
|
|||||||
.qual-badge.yes { background: rgba(74,222,128,0.16); color: var(--turf); }
|
.qual-badge.yes { background: rgba(74,222,128,0.16); color: var(--turf); }
|
||||||
.qual-badge.no { background: rgba(95,109,146,0.16); color: var(--ink-faint); }
|
.qual-badge.no { background: rgba(95,109,146,0.16); color: var(--ink-faint); }
|
||||||
|
|
||||||
|
/* Drittplatzierte: Teamname grün, wenn alle 3 Gruppenspiele gespielt */
|
||||||
|
.third-table td.team-complete { color: var(--turf); }
|
||||||
|
|
||||||
/* ---------- Bracket ---------- */
|
/* ---------- Bracket ---------- */
|
||||||
.bracket-banner {
|
.bracket-banner {
|
||||||
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
||||||
@@ -195,7 +198,7 @@ table.standings { width: 100%; border-collapse: collapse; }
|
|||||||
margin-right: -20px;
|
margin-right: -20px;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
overflow-x: hidden;
|
overflow-x: auto;
|
||||||
overflow-y: visible;
|
overflow-y: visible;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
scrollbar-gutter: stable;
|
scrollbar-gutter: stable;
|
||||||
@@ -217,9 +220,17 @@ table.standings { width: 100%; border-collapse: collapse; }
|
|||||||
border-radius: var(--radius-sm); position: relative;
|
border-radius: var(--radius-sm); position: relative;
|
||||||
}
|
}
|
||||||
.tie.final-tie { border-color: var(--gold); box-shadow: 0 0 0 1px rgba(255,210,74,0.2); }
|
.tie.final-tie { border-color: var(--gold); box-shadow: 0 0 0 1px rgba(255,210,74,0.2); }
|
||||||
.tie-head {
|
.tie-meta {
|
||||||
font-family: var(--font-mono); font-size: 9px; color: var(--ink-faint);
|
font-family: var(--font-mono); font-size: 9px; color: rgba(255,255,255,0.55);
|
||||||
letter-spacing: 0.04em; padding: 5px 10px 0;
|
letter-spacing: 0.04em; padding: 5px 10px 0;
|
||||||
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.match-badge {
|
||||||
|
position: absolute; top: -6px; right: -6px;
|
||||||
|
font-family: var(--font-mono); font-size: 9px; font-weight: 700;
|
||||||
|
line-height: 18px; min-width: 18px; text-align: center;
|
||||||
|
border-radius: 999px; padding: 0 4px;
|
||||||
|
background: #1a2744; color: #ffffff; border: 1px solid rgba(255,255,255,0.15);
|
||||||
}
|
}
|
||||||
.side {
|
.side {
|
||||||
display: flex; align-items: center; justify-content: space-between;
|
display: flex; align-items: center; justify-content: space-between;
|
||||||
@@ -274,9 +285,109 @@ table.standings { width: 100%; border-collapse: collapse; }
|
|||||||
}
|
}
|
||||||
.foot a { color: var(--ink-dim); text-decoration: underline; text-underline-offset: 2px; }
|
.foot a { color: var(--ink-dim); text-decoration: underline; text-underline-offset: 2px; }
|
||||||
|
|
||||||
|
/* PSO-Badge: auf Desktop inline im Score, auf Mobile absolut darunter schwebend */
|
||||||
|
.pso-badge { display: none; }
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
MOBIL — Breakpoint 640px (iPhone ~375, Galaxy ~412, alle ≤640)
|
||||||
|
===================================================================== */
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.tab { padding: 14px 12px; font-size: 12px; }
|
body { font-size: 14px; }
|
||||||
.group-grid { grid-template-columns: 1fr; }
|
.wrap { padding: 0 12px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Header ---------- */
|
||||||
|
.masthead { padding: 0 12px; }
|
||||||
|
.masthead-inner { padding: 10px 0; gap: 8px; }
|
||||||
|
.brand { gap: 6px; }
|
||||||
|
.brand-mark { font-size: 18px; }
|
||||||
|
.brand-sub { font-size: 9px; letter-spacing: 0.04em; }
|
||||||
|
.status-pill { font-size: 10px; padding: 4px 10px; gap: 5px; }
|
||||||
|
.dot { width: 6px; height: 6px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Tabs (zwei Zeilen, kein horizontaler Scroll) ---------- */
|
||||||
|
.masthead-tabs {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px 4px;
|
||||||
|
}
|
||||||
|
.tab { padding: 8px 13px; font-size: 12px; }
|
||||||
|
|
||||||
|
.section { padding: 18px 0 48px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Gruppen ---------- */
|
||||||
|
.group-grid { grid-template-columns: 1fr; gap: 12px; }
|
||||||
|
.group-head { padding: 10px 12px; }
|
||||||
|
.group-name { font-size: 14px; }
|
||||||
|
.standings th { font-size: 9px; padding: 6px 3px; }
|
||||||
|
.standings th.team { padding-left: 10px; }
|
||||||
|
.standings td { font-size: 11px; padding: 7px 3px; }
|
||||||
|
.standings td.team { padding-left: 10px; gap: 6px; }
|
||||||
|
.rankdot { width: 16px; height: 16px; font-size: 8px; }
|
||||||
|
.team-name { font-size: 12px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Spiele (Fixtures) ---------- */
|
||||||
|
.fx { grid-template-columns: 1fr; gap: 8px; padding: 10px 12px; }
|
||||||
|
.fx-meta { flex-direction: row; gap: 14px; align-items: center; }
|
||||||
|
.fx-status { order: -1; }
|
||||||
|
.fx-teams { column-gap: 16px; }
|
||||||
|
.fx-score { font-size: 16px; min-width: 44px; }
|
||||||
|
.fx-vs { font-size: 14px; min-width: 44px; }
|
||||||
|
.fx-name { font-size: 13px; max-width: 110px; }
|
||||||
|
.grp-switch { gap: 8px; }
|
||||||
|
.grp-chip { width: 40px; height: 40px; font-size: 14px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Drittplatzierte ---------- */
|
||||||
|
.third-table th { font-size: 9px; padding: 8px 6px; }
|
||||||
|
.third-table td { font-size: 11px; padding: 7px 6px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: K.o.-Baum ---------- */
|
||||||
|
.bracket-scroll {
|
||||||
|
margin-left: -12px;
|
||||||
|
margin-right: -12px;
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
.bracket { gap: 18px; }
|
||||||
|
.round { min-width: 170px; }
|
||||||
|
.round-label { font-size: 10px; }
|
||||||
|
.round-matches { gap: 8px; }
|
||||||
|
.tie-meta { font-size: 8px; padding: 3px 8px 0; }
|
||||||
|
.side { padding: 6px 8px; font-size: 11px; }
|
||||||
|
.side .nm { gap: 5px; }
|
||||||
|
.prov-mark { font-size: 10px; }
|
||||||
|
.side .prob { font-size: 9px; }
|
||||||
|
.bracket-banner { padding: 10px 12px; font-size: 13px; }
|
||||||
|
.legend { font-size: 10px; gap: 12px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: PSO-Badge (Elfmeterschießen unter dem Score) ---------- */
|
||||||
|
.pso-inline { display: none; }
|
||||||
|
.pso-badge {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
margin-top: 2px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
color: var(--ink);
|
||||||
|
white-space: nowrap;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- mobil: Simulation ---------- */
|
||||||
|
.sim-row { flex-wrap: wrap; gap: 6px; padding: 8px 10px; }
|
||||||
|
.sim-row-phase { min-width: 100%; font-size: 9px; }
|
||||||
|
.sim-row-date { min-width: auto; font-size: 9px; }
|
||||||
|
.sim-row input[type="number"] { width: 32px; height: 32px; font-size: 15px; }
|
||||||
|
|
||||||
|
/* ---------- mobil: Footer ---------- */
|
||||||
|
.foot { font-size: 11px; padding: 16px 0 32px; }
|
||||||
|
|
||||||
|
/* Kein horizontaler Überlauf außer im Bracket */
|
||||||
|
body { overflow-x: hidden; }
|
||||||
|
.bracket-scroll { overflow-x: auto; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============ Erweiterungen v2 ============ */
|
/* ============ Erweiterungen v2 ============ */
|
||||||
|
|||||||
@@ -1,24 +1,5 @@
|
|||||||
import type { Metadata } from "next";
|
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "WM 26 — Gruppen & K.o.-Baum",
|
|
||||||
description:
|
|
||||||
"Live-Gruppentabellen, Drittplatzierten-Wertung und der vollständige K.o.-Baum der FIFA WM 2026 mit Annex-C-Zuordnung und Polymarket-Wahrscheinlichkeiten.",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return children;
|
||||||
<html lang="de">
|
|
||||||
<head>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Archivo:wght@500;700;800&family=Archivo+Expanded:wght@700;800&family=Inter:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
</head>
|
|
||||||
<body>{children}</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
12
app/robots.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import type { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
export default function robots(): MetadataRoute.Robots {
|
||||||
|
return {
|
||||||
|
rules: {
|
||||||
|
userAgent: "*",
|
||||||
|
allow: "/",
|
||||||
|
disallow: ["/api/"],
|
||||||
|
},
|
||||||
|
sitemap: "https://soccer-2026.info/sitemap.xml",
|
||||||
|
};
|
||||||
|
}
|
||||||
33
app/sitemap.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
const BASE = "https://soccer-2026.info";
|
||||||
|
|
||||||
|
export default function sitemap(): MetadataRoute.Sitemap {
|
||||||
|
const now = new Date();
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
url: `${BASE}/en`,
|
||||||
|
lastModified: now,
|
||||||
|
changeFrequency: "hourly",
|
||||||
|
priority: 1.0,
|
||||||
|
alternates: {
|
||||||
|
languages: {
|
||||||
|
en: `${BASE}/en`,
|
||||||
|
de: `${BASE}/de`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${BASE}/de`,
|
||||||
|
lastModified: now,
|
||||||
|
changeFrequency: "hourly",
|
||||||
|
priority: 1.0,
|
||||||
|
alternates: {
|
||||||
|
languages: {
|
||||||
|
en: `${BASE}/en`,
|
||||||
|
de: `${BASE}/de`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
wm2026:
|
wm2026:
|
||||||
build: .
|
build:
|
||||||
|
context: .
|
||||||
|
args:
|
||||||
|
NEXT_PUBLIC_UMAMI_SRC: ${NEXT_PUBLIC_UMAMI_SRC:-}
|
||||||
|
NEXT_PUBLIC_UMAMI_ID: ${NEXT_PUBLIC_UMAMI_ID:-}
|
||||||
image: wm2026-board:latest
|
image: wm2026-board:latest
|
||||||
container_name: wm2026
|
container_name: wm2026
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -12,7 +16,7 @@ services:
|
|||||||
expose:
|
expose:
|
||||||
- "3000"
|
- "3000"
|
||||||
networks:
|
networks:
|
||||||
- caddy_net
|
- soccer-net
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/matches"]
|
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/matches"]
|
||||||
interval: 60s
|
interval: 60s
|
||||||
@@ -21,5 +25,5 @@ services:
|
|||||||
start_period: 20s
|
start_period: 20s
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
caddy_net:
|
soccer-net:
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ANNEX_C } from "./annexc-data";
|
import { ANNEX_C } from "./annexc-data";
|
||||||
import { GroupId, GroupTable, ThirdPlaceRow } from "./types";
|
import { GroupId, GroupTable, ThirdPlaceRow } from "./types";
|
||||||
|
import { Dictionary } from "./i18n";
|
||||||
|
|
||||||
// Die festen Paarungen der Runde der letzten 32 (FIFA-Spielplan, Annex zur Auslosung).
|
// Die festen Paarungen der Runde der letzten 32 (FIFA-Spielplan, Annex zur Auslosung).
|
||||||
// Quelle: FIFA WM 2026 Wettbewerbsregeln, Spiele 73-88.
|
// Quelle: FIFA WM 2026 Wettbewerbsregeln, Spiele 73-88.
|
||||||
@@ -100,14 +101,16 @@ export function slotLabel(
|
|||||||
slot: BracketSlot,
|
slot: BracketSlot,
|
||||||
assignment: ThirdAssignment | null,
|
assignment: ThirdAssignment | null,
|
||||||
winnerGroupForThisMatch?: GroupId,
|
winnerGroupForThisMatch?: GroupId,
|
||||||
|
dict?: Dictionary,
|
||||||
): string {
|
): string {
|
||||||
if (slot.type === "W") return `Sieger ${slot.group}`;
|
const s = dict?.slot;
|
||||||
if (slot.type === "R") return `Zweiter ${slot.group}`;
|
if (slot.type === "W") return s?.winner(slot.group!) ?? `Sieger ${slot.group}`;
|
||||||
|
if (slot.type === "R") return s?.runnerUp(slot.group!) ?? `Zweiter ${slot.group}`;
|
||||||
// 3. Platz
|
// 3. Platz
|
||||||
if (assignment && winnerGroupForThisMatch && assignment[winnerGroupForThisMatch]) {
|
if (assignment && winnerGroupForThisMatch && assignment[winnerGroupForThisMatch]) {
|
||||||
return `3. der Gruppe ${assignment[winnerGroupForThisMatch]}`;
|
return s?.thirdOfGroup(assignment[winnerGroupForThisMatch]!) ?? `3. der Gruppe ${assignment[winnerGroupForThisMatch]}`;
|
||||||
}
|
}
|
||||||
return `3. ${slot.thirdPool?.join("/") ?? "?"}`;
|
return s?.thirdPlacePool(slot.thirdPool?.join("/") ?? "?") ?? `3. ${slot.thirdPool?.join("/") ?? "?"}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup: matchNumber → Quellspiele (fromHome, fromAway, losers).
|
// Lookup: matchNumber → Quellspiele (fromHome, fromAway, losers).
|
||||||
|
|||||||
800
lib/feeds.ts
@@ -1,163 +1,65 @@
|
|||||||
import { GroupId, Match, MatchStatus, Team } from "./types";
|
import { GroupId, GoalEvent, Match, MatchStatus, Team } from "./types";
|
||||||
import { venueFor } from "./venues";
|
import { TEAM_LOCALIZATION } from "./team-mappings";
|
||||||
import { localisedTeamName } from "./team-mappings";
|
import { R32, LATER_ROUNDS, resolveAnnexC, qualifiedThirdGroups } from "./bracket";
|
||||||
|
import { computeGroupTables, computeThirdPlaceTable } from "./standings";
|
||||||
|
import { FIFA_GROUP_MAP, FIFA_STAGE_MAP } from "./fifa-constants";
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Caching: einfacher In-Memory-Cache mit TTL. Verhindert, dass jede Browser-
|
// Caching: In-Memory-Cache mit TTL + stale-while-revalidate.
|
||||||
// Anfrage einen Upstream-Call auslöst (football-data: 10 req/min Limit).
|
// Bei abgelaufenem Cache wird der alte Wert sofort zurückgegeben und die
|
||||||
|
// Erneuerung im Hintergrund angestoßen (keine Wartezeit für den Nutzer).
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
interface CacheEntry<T> { value: T; expires: number; }
|
interface CacheEntry<T> { value: T; expires: number; refreshing?: boolean; }
|
||||||
const cache = new Map<string, CacheEntry<unknown>>();
|
const cache = new Map<string, CacheEntry<unknown>>();
|
||||||
|
|
||||||
|
// Subscription-System: Benachrichtigt Listener (z.B. API-Routen) bei
|
||||||
|
// erfolgreichem Hintergrund-Refresh, sodass das Frontend nach dem
|
||||||
|
// nächsten Poll die aktuellen Daten erhält.
|
||||||
|
type CacheListener = (value: unknown) => void;
|
||||||
|
const cacheSubscriptions = new Map<string, Set<CacheListener>>();
|
||||||
|
|
||||||
|
function notifyCacheListeners(key: string, value: unknown): void {
|
||||||
|
const subs = cacheSubscriptions.get(key);
|
||||||
|
if (!subs) return;
|
||||||
|
for (const cb of subs) {
|
||||||
|
try { cb(value); } catch { /* silent */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onCacheRefresh<T>(key: string, cb: (value: T) => void): () => void {
|
||||||
|
if (!cacheSubscriptions.has(key)) cacheSubscriptions.set(key, new Set());
|
||||||
|
const set = cacheSubscriptions.get(key)!;
|
||||||
|
const wrapped = cb as CacheListener;
|
||||||
|
set.add(wrapped);
|
||||||
|
return () => { set.delete(wrapped); if (set.size === 0) cacheSubscriptions.delete(key); };
|
||||||
|
}
|
||||||
|
|
||||||
export async function cached<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T> {
|
export async function cached<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T> {
|
||||||
const hit = cache.get(key) as CacheEntry<T> | undefined;
|
const hit = cache.get(key) as CacheEntry<T> | undefined;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
|
// Frischer Cache → direkt zurück
|
||||||
if (hit && hit.expires > now) return hit.value;
|
if (hit && hit.expires > now) return hit.value;
|
||||||
try {
|
|
||||||
const value = await fn();
|
// Abgelaufen, aber vorhanden → sofort alten Wert liefern, im Hintergrund erneuern
|
||||||
cache.set(key, { value, expires: now + ttlMs });
|
if (hit) {
|
||||||
return value;
|
if (!hit.refreshing) {
|
||||||
} catch (err) {
|
hit.refreshing = true;
|
||||||
// Bei Upstream-Fehler abgelaufenen Cache weiterverwenden, statt hart zu failen.
|
fn()
|
||||||
if (hit) return hit.value;
|
.then((value) => {
|
||||||
throw err;
|
cache.set(key, { value, expires: Date.now() + ttlMs });
|
||||||
|
notifyCacheListeners(key, value);
|
||||||
|
})
|
||||||
|
.catch((err) => { console.error(`[cache] Hintergrund-Refresh fehlgeschlagen (${key}):`, err); })
|
||||||
|
.finally(() => { const e = cache.get(key) as CacheEntry<T> | undefined; if (e) e.refreshing = false; });
|
||||||
|
}
|
||||||
|
return hit.value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// Kaltstart: kein Cache → synchron laden
|
||||||
// football-data.org: Teams, Spiele, Status
|
const value = await fn();
|
||||||
// ----------------------------------------------------------------------------
|
cache.set(key, { value, expires: now + ttlMs });
|
||||||
const FD_BASE = "https://api.football-data.org/v4";
|
return value;
|
||||||
const FD_COMP = "WC"; // FIFA World Cup
|
|
||||||
|
|
||||||
function fdHeaders(): Record<string, string> {
|
|
||||||
const token = process.env.FOOTBALL_DATA_TOKEN;
|
|
||||||
return token ? { "X-Auth-Token": token } : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapStatus(s: string): MatchStatus {
|
|
||||||
switch (s) {
|
|
||||||
case "LIVE": return "LIVE";
|
|
||||||
case "IN_PLAY": return "IN_PLAY";
|
|
||||||
case "PAUSED": return "PAUSED";
|
|
||||||
case "FINISHED": return "FINISHED";
|
|
||||||
default: return "SCHEDULED";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wandelt einen football-data-Gruppennamen ("GROUP_A") in unsere GroupId.
|
|
||||||
function parseGroup(g: string | null | undefined): GroupId | null {
|
|
||||||
if (!g) return null;
|
|
||||||
const m = /GROUP_([A-L])/.exec(g);
|
|
||||||
return m ? (m[1] as GroupId) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FdMatchesResponse {
|
|
||||||
matches: Array<{
|
|
||||||
id: number;
|
|
||||||
utcDate: string;
|
|
||||||
status: string;
|
|
||||||
minute?: number | null;
|
|
||||||
matchday?: number | null;
|
|
||||||
stage: string;
|
|
||||||
group?: string | null;
|
|
||||||
venue?: string | null;
|
|
||||||
attendance?: number | null;
|
|
||||||
homeTeam: { id: number | null; name: string | null; tla?: string | null; crest?: string | null };
|
|
||||||
awayTeam: { id: number | null; name: string | null; tla?: string | null; crest?: string | null };
|
|
||||||
score: { fullTime: { home: number | null; away: number | null } };
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stageFor(stage: string, group: GroupId | null): Match["stage"] {
|
|
||||||
if (group) return "GROUP";
|
|
||||||
switch (stage) {
|
|
||||||
case "LAST_32": return "R32";
|
|
||||||
case "LAST_16": return "R16";
|
|
||||||
case "QUARTER_FINALS": return "QF";
|
|
||||||
case "SEMI_FINALS": return "SF";
|
|
||||||
case "THIRD_PLACE": return "3RD";
|
|
||||||
case "FINAL": return "FINAL";
|
|
||||||
default: return "GROUP";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phasen-Reihenfolge für die K.o.-Nummerierung.
|
|
||||||
const STAGE_ORDER: Record<Match["stage"], number> = {
|
|
||||||
GROUP: 0, R32: 1, R16: 2, QF: 3, SF: 4, "3RD": 5, FINAL: 6,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setzt Spielnummern und Stadien.
|
|
||||||
// - K.o.-Spiele: chronologisch ab 73 (Anstöße dort eindeutig) -> für Bracket nötig.
|
|
||||||
// - Venue: Gruppenspiele über die Teampaarung, K.o.-Spiele über die Spielnummer.
|
|
||||||
function assignNumbersAndVenues(matches: Match[], teams: Team[]): void {
|
|
||||||
// K.o.-Spiele eindeutig durchnummerieren (73..104).
|
|
||||||
const ko = matches
|
|
||||||
.filter((m) => m.group == null)
|
|
||||||
.sort((a, b) => {
|
|
||||||
const sa = STAGE_ORDER[a.stage], sb = STAGE_ORDER[b.stage];
|
|
||||||
if (sa !== sb) return sa - sb;
|
|
||||||
const t = +new Date(a.utcDate) - +new Date(b.utcDate);
|
|
||||||
return t !== 0 ? t : Number(a.id) - Number(b.id);
|
|
||||||
});
|
|
||||||
ko.forEach((m, i) => { m.matchNumber = 73 + i; });
|
|
||||||
|
|
||||||
// Stadien setzen (Gruppenphase per Paarung, K.o. per Nummer).
|
|
||||||
for (const m of matches) {
|
|
||||||
m.venue = venueFor(m, teams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Holt alle Spiele + leitet die Teamliste daraus ab (spart einen Extra-Call).
|
|
||||||
export async function fetchMatchesAndTeams(): Promise<{ matches: Match[]; teams: Team[] }> {
|
|
||||||
return cached("fd:matches", 60_000, async () => {
|
|
||||||
const res = await fetch(`${FD_BASE}/competitions/${FD_COMP}/matches`, {
|
|
||||||
headers: fdHeaders(),
|
|
||||||
// Next.js: kein eigenes Caching, wir cachen selbst
|
|
||||||
cache: "no-store",
|
|
||||||
});
|
|
||||||
if (!res.ok) throw new Error(`football-data ${res.status}`);
|
|
||||||
const data = (await res.json()) as FdMatchesResponse;
|
|
||||||
|
|
||||||
const teamMap = new Map<string, Team>();
|
|
||||||
const matches: Match[] = data.matches.map((m) => {
|
|
||||||
const group = parseGroup(m.group);
|
|
||||||
// Teams registrieren (nur wenn Gruppenspiel und ID vorhanden)
|
|
||||||
for (const side of [m.homeTeam, m.awayTeam]) {
|
|
||||||
if (side.id != null && side.name && group) {
|
|
||||||
const id = String(side.id);
|
|
||||||
if (!teamMap.has(id)) {
|
|
||||||
teamMap.set(id, {
|
|
||||||
id, name: side.name, code: side.tla ?? "", group,
|
|
||||||
crest: side.crest ?? null,
|
|
||||||
localisedName: localisedTeamName(side.tla ?? "", side.name ?? ""),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: String(m.id),
|
|
||||||
group,
|
|
||||||
stage: stageFor(m.stage, group),
|
|
||||||
// Vorläufig 0 — die echte FIFA-Spielnummer wird unten gesetzt.
|
|
||||||
matchNumber: 0,
|
|
||||||
utcDate: m.utcDate,
|
|
||||||
status: mapStatus(m.status),
|
|
||||||
minute: m.minute ?? null,
|
|
||||||
homeTeamId: m.homeTeam.id != null ? String(m.homeTeam.id) : null,
|
|
||||||
awayTeamId: m.awayTeam.id != null ? String(m.awayTeam.id) : null,
|
|
||||||
homeScore: m.score.fullTime.home,
|
|
||||||
awayScore: m.score.fullTime.away,
|
|
||||||
venue: null, // wird unten aus der Map gesetzt
|
|
||||||
attendance: m.attendance ?? null,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const teams = [...teamMap.values()];
|
|
||||||
assignNumbersAndVenues(matches, teams);
|
|
||||||
|
|
||||||
return { matches, teams };
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -183,6 +85,7 @@ interface PmMarket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ParsedOdds {
|
export interface ParsedOdds {
|
||||||
|
slug: string;
|
||||||
homeCode: string;
|
homeCode: string;
|
||||||
awayCode: string;
|
awayCode: string;
|
||||||
homeName: string;
|
homeName: string;
|
||||||
@@ -190,6 +93,7 @@ export interface ParsedOdds {
|
|||||||
pHome: number;
|
pHome: number;
|
||||||
pDraw: number;
|
pDraw: number;
|
||||||
pAway: number;
|
pAway: number;
|
||||||
|
startTime: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalisiert Teamcodes zwischen Polymarket-Slug und Feed (3-Buchstaben).
|
// Normalisiert Teamcodes zwischen Polymarket-Slug und Feed (3-Buchstaben).
|
||||||
@@ -214,7 +118,7 @@ function safeParse<T>(s: string, fallback: T): T {
|
|||||||
// Holt alle WM-Spiele über den Series-Endpoint mit Pagination.
|
// Holt alle WM-Spiele über den Series-Endpoint mit Pagination.
|
||||||
// Parst pro Event die drei Moneyline-Märkte (Heim/Draw/Auswärts).
|
// Parst pro Event die drei Moneyline-Märkte (Heim/Draw/Auswärts).
|
||||||
export async function fetchOdds(): Promise<ParsedOdds[]> {
|
export async function fetchOdds(): Promise<ParsedOdds[]> {
|
||||||
return cached("pm:odds", 120_000, async () => {
|
return cached("pm:odds", 300_000, async () => {
|
||||||
const allEvents: PmEvent[] = [];
|
const allEvents: PmEvent[] = [];
|
||||||
for (let offset = 0; ; offset += 100) {
|
for (let offset = 0; ; offset += 100) {
|
||||||
const url = `${PM_BASE}/events?series_id=${PM_SERIES}&active=true&closed=false&limit=100&offset=${offset}`;
|
const url = `${PM_BASE}/events?series_id=${PM_SERIES}&active=true&closed=false&limit=100&offset=${offset}`;
|
||||||
@@ -227,9 +131,9 @@ export async function fetchOdds(): Promise<ParsedOdds[]> {
|
|||||||
allEvents.push(...page);
|
allEvents.push(...page);
|
||||||
if (page.length < 100) break;
|
if (page.length < 100) break;
|
||||||
}
|
}
|
||||||
//console.log("[polymarket] events fetched:", allEvents.length);
|
|
||||||
|
|
||||||
const parsed: ParsedOdds[] = [];
|
const parsed: ParsedOdds[] = [];
|
||||||
|
|
||||||
for (const ev of allEvents) {
|
for (const ev of allEvents) {
|
||||||
// Slug: fifwc-{home}-{away}-{yyyy}-{mm}-{dd}
|
// Slug: fifwc-{home}-{away}-{yyyy}-{mm}-{dd}
|
||||||
const slugParts = ev.slug.replace("fifwc-", "").split("-");
|
const slugParts = ev.slug.replace("fifwc-", "").split("-");
|
||||||
@@ -239,10 +143,12 @@ export async function fetchOdds(): Promise<ParsedOdds[]> {
|
|||||||
|
|
||||||
let pHome = 0, pDraw = 0, pAway = 0;
|
let pHome = 0, pDraw = 0, pAway = 0;
|
||||||
let homeName = "", awayName = "";
|
let homeName = "", awayName = "";
|
||||||
|
let marketGameStartTime: string | null = null;
|
||||||
|
|
||||||
for (const mk of ev.markets ?? []) {
|
for (const mk of ev.markets ?? []) {
|
||||||
if (mk.sportsMarketType && mk.sportsMarketType !== "moneyline") continue;
|
if (mk.sportsMarketType && mk.sportsMarketType !== "moneyline") continue;
|
||||||
if (mk.closed) continue;
|
if (mk.closed) continue;
|
||||||
|
if (!marketGameStartTime) marketGameStartTime = (mk as any).gameStartTime ?? null;
|
||||||
const prices = safeParse<string[]>(mk.outcomePrices, []).map(Number);
|
const prices = safeParse<string[]>(mk.outcomePrices, []).map(Number);
|
||||||
if (prices.length < 2) continue;
|
if (prices.length < 2) continue;
|
||||||
const yes = prices[0]; // erster Preis = "Yes"-Wahrscheinlichkeit
|
const yes = prices[0]; // erster Preis = "Yes"-Wahrscheinlichkeit
|
||||||
@@ -266,7 +172,8 @@ export async function fetchOdds(): Promise<ParsedOdds[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pHome > 0 || pDraw > 0 || pAway > 0) {
|
if (pHome > 0 || pDraw > 0 || pAway > 0) {
|
||||||
parsed.push({ homeCode, awayCode, homeName, awayName, pHome, pDraw, pAway });
|
const startTime = marketGameStartTime ?? (ev as any).gameStartTime ?? (ev as any).endDate ?? (ev as any).startDate;
|
||||||
|
parsed.push({ slug: ev.slug, homeCode, awayCode, homeName, awayName, pHome, pDraw, pAway, startTime });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +219,9 @@ export function attachOdds(matches: Match[], teams: Team[], odds: ParsedOdds[]):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return matches.map((m) => {
|
const attachedOdds = new Set<ParsedOdds>();
|
||||||
|
|
||||||
|
const result = matches.map((m) => {
|
||||||
if (!m.homeTeamId || !m.awayTeamId) return m;
|
if (!m.homeTeamId || !m.awayTeamId) return m;
|
||||||
// Suche in oddsMatch nach einer Kombination die beide Team-IDs matcht
|
// Suche in oddsMatch nach einer Kombination die beide Team-IDs matcht
|
||||||
for (const [o, ids] of oddsMatch) {
|
for (const [o, ids] of oddsMatch) {
|
||||||
@@ -321,6 +230,7 @@ export function attachOdds(matches: Match[], teams: Team[], odds: ParsedOdds[]):
|
|||||||
if ((ids.homeId === m.homeTeamId && ids.awayId === m.awayTeamId) ||
|
if ((ids.homeId === m.homeTeamId && ids.awayId === m.awayTeamId) ||
|
||||||
(ids.homeId === m.awayTeamId && ids.awayId === m.homeTeamId)) {
|
(ids.homeId === m.awayTeamId && ids.awayId === m.homeTeamId)) {
|
||||||
const swapped = ids.homeId === m.awayTeamId;
|
const swapped = ids.homeId === m.awayTeamId;
|
||||||
|
attachedOdds.add(o);
|
||||||
return {
|
return {
|
||||||
...m,
|
...m,
|
||||||
prob: {
|
prob: {
|
||||||
@@ -333,4 +243,588 @@ export function attachOdds(matches: Match[], teams: Team[], odds: ParsedOdds[]):
|
|||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// KO-Odds-Fallback: löst R32-Paarungen auf und verknüpft Polymarket-Events
|
||||||
|
// mit K.o.-Feed-Matches, die noch keine Team-IDs im Feed haben.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Löst für jeden R32-Slot (73-88) die aktuellen Team-Paarungen auf Basis der
|
||||||
|
// Gruppentabellen und Annex-C-Zuordnung. Gibt eine Map matchNumber → Paarung
|
||||||
|
// zurück, NUR wenn beide Team-IDs eindeutig bekannt sind (kein Raten).
|
||||||
|
function resolveR32Pairings(matches: Match[], teams: Team[]): Map<number, { homeTeamId: string; awayTeamId: string }> {
|
||||||
|
const tables = computeGroupTables(teams, matches);
|
||||||
|
const thirds = computeThirdPlaceTable(tables);
|
||||||
|
const qGroups = qualifiedThirdGroups(thirds);
|
||||||
|
const annex = qGroups.length === 8 ? resolveAnnexC(qGroups) : null;
|
||||||
|
|
||||||
|
const pairings = new Map<number, { homeTeamId: string; awayTeamId: string }>();
|
||||||
|
|
||||||
|
for (const slot of R32) {
|
||||||
|
const homeGroup = slot.home.type === "W" ? slot.home.group : undefined;
|
||||||
|
const awayGroup = slot.away.type === "W" ? slot.away.group : undefined;
|
||||||
|
const wg = (homeGroup ?? awayGroup) as GroupId | undefined;
|
||||||
|
|
||||||
|
let hid: string | null = null;
|
||||||
|
if (slot.home.type === "W" && slot.home.group) {
|
||||||
|
hid = tables.find(t => t.group === slot.home.group)?.rows.find(r => r.rank === 1)?.teamId ?? null;
|
||||||
|
} else if (slot.home.type === "R" && slot.home.group) {
|
||||||
|
hid = tables.find(t => t.group === slot.home.group)?.rows.find(r => r.rank === 2)?.teamId ?? null;
|
||||||
|
} else if (slot.home.type === "3" && annex && wg) {
|
||||||
|
const tg = annex[wg];
|
||||||
|
if (tg) hid = thirds.find(r => r.group === tg && r.qualifies)?.teamId ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let aid: string | null = null;
|
||||||
|
if (slot.away.type === "W" && slot.away.group) {
|
||||||
|
aid = tables.find(t => t.group === slot.away.group)?.rows.find(r => r.rank === 1)?.teamId ?? null;
|
||||||
|
} else if (slot.away.type === "R" && slot.away.group) {
|
||||||
|
aid = tables.find(t => t.group === slot.away.group)?.rows.find(r => r.rank === 2)?.teamId ?? null;
|
||||||
|
} else if (slot.away.type === "3" && annex && wg) {
|
||||||
|
const tg = annex[wg];
|
||||||
|
if (tg) aid = thirds.find(r => r.group === tg && r.qualifies)?.teamId ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hid && aid) {
|
||||||
|
pairings.set(slot.matchNumber, { homeTeamId: hid, awayTeamId: aid });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pairings;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extrahiert das Datum (YYYY-MM-DD) aus einem Polymarket-Slug.
|
||||||
|
// Slug-Format: fifwc-{home}-{away}-{yyyy}-{mm}-{dd}
|
||||||
|
function slugToDate(slug: string): string | null {
|
||||||
|
const parts = slug.split("-");
|
||||||
|
if (parts.length < 3) return null;
|
||||||
|
const y = parts[parts.length - 3];
|
||||||
|
const m = parts[parts.length - 2];
|
||||||
|
const d = parts[parts.length - 1];
|
||||||
|
if (/^\d{4}$/.test(y) && /^\d{2}$/.test(m) && /^\d{2}$/.test(d)) {
|
||||||
|
return `${y}-${m}-${d}`;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zweiter Durchlauf für attachOdds: ordnet Polymarket-Events K.o.-Feed-Matches
|
||||||
|
// zu, die (noch) keine Team-IDs im Feed haben. Arbeitet direkt auf den
|
||||||
|
// aufgelösten R32-Paarungen (resolveR32Pairings). Identifiziert das Ziel-
|
||||||
|
// Feed-Match über die Slot-matchNumber (Stufe 1) oder Datums-Lookup aus dem
|
||||||
|
// Slug (Stufe 2) — KEINE chronologische Nummernvergabe.
|
||||||
|
// Mutiert matches in-place, setzt nur bei Matches OHNE bestehende prob.
|
||||||
|
export function attachKOOdds(matches: Match[], teams: Team[], odds: ParsedOdds[]): Match[] {
|
||||||
|
const pairings = resolveR32Pairings(matches, teams);
|
||||||
|
if (pairings.size === 0) return matches;
|
||||||
|
|
||||||
|
const idByName = new Map<string, string>();
|
||||||
|
for (const t of teams) {
|
||||||
|
const nn = normName(t.name);
|
||||||
|
if (!idByName.has(nn)) idByName.set(nn, t.id);
|
||||||
|
}
|
||||||
|
const idByCode = new Map(teams.map((t) => [t.code.toLowerCase(), t.id]));
|
||||||
|
|
||||||
|
for (const [matchNum, pairing] of pairings) {
|
||||||
|
if (!pairing.homeTeamId || !pairing.awayTeamId) continue;
|
||||||
|
|
||||||
|
// Finde Polymarket-Event für dieses Team-Paar
|
||||||
|
let matchedEvent: ParsedOdds | null = null;
|
||||||
|
for (const o of odds) {
|
||||||
|
const hn = normName(o.homeName);
|
||||||
|
const an = normName(o.awayName);
|
||||||
|
const homeId = idByName.get(hn) ?? idByCode.get(o.homeCode);
|
||||||
|
const awayId = idByName.get(an) ?? idByCode.get(o.awayCode);
|
||||||
|
if (!homeId || !awayId) continue;
|
||||||
|
if ((homeId === pairing.homeTeamId && awayId === pairing.awayTeamId) ||
|
||||||
|
(homeId === pairing.awayTeamId && awayId === pairing.homeTeamId)) {
|
||||||
|
matchedEvent = o;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matchedEvent) continue;
|
||||||
|
|
||||||
|
// Ziel-Feed-Match identifizieren
|
||||||
|
let targetMatch: Match | undefined;
|
||||||
|
|
||||||
|
// Stufe 1: bereits nummeriertes R32-Match (via assignKONumbersBySlots Pass 1)
|
||||||
|
targetMatch = matches.find(m =>
|
||||||
|
m.stage === "R32" && m.group == null && m.matchNumber === matchNum,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Stufe 2: Datums-Lookup aus Polymarket-Slug für unnummerierte Matches
|
||||||
|
if (!targetMatch) {
|
||||||
|
const slugDate = slugToDate(matchedEvent.slug);
|
||||||
|
if (slugDate) {
|
||||||
|
const candidates = matches.filter(m =>
|
||||||
|
m.stage === "R32" && m.group == null && m.matchNumber === 0 &&
|
||||||
|
m.utcDate.slice(0, 10) === slugDate,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (candidates.length === 1) {
|
||||||
|
targetMatch = candidates[0];
|
||||||
|
targetMatch.matchNumber = matchNum;
|
||||||
|
} else if (candidates.length > 1) {
|
||||||
|
// Tie-breaker: falls Polymarket-Event eine Startzeit hat, nächstgelegenes Feed-Match
|
||||||
|
if (matchedEvent.startTime) {
|
||||||
|
const eventTime = new Date(matchedEvent.startTime).getTime();
|
||||||
|
let best: Match | undefined;
|
||||||
|
let bestDiff = Infinity;
|
||||||
|
for (const c of candidates) {
|
||||||
|
const diff = Math.abs(new Date(c.utcDate).getTime() - eventTime);
|
||||||
|
if (diff < bestDiff) { bestDiff = diff; best = c; }
|
||||||
|
}
|
||||||
|
// Nur zuordnen, wenn Zeitdifferenz plausibel (<4h)
|
||||||
|
if (best && bestDiff < 4 * 60 * 60 * 1000) {
|
||||||
|
targetMatch = best;
|
||||||
|
targetMatch.matchNumber = matchNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetMatch) continue;
|
||||||
|
|
||||||
|
// prob nicht überschreiben, falls schon gesetzt
|
||||||
|
if (targetMatch.prob) continue;
|
||||||
|
|
||||||
|
const homeIdFromEvent = idByName.get(normName(matchedEvent.homeName)) ??
|
||||||
|
idByCode.get(matchedEvent.homeCode);
|
||||||
|
const swapped = homeIdFromEvent === pairing.awayTeamId;
|
||||||
|
|
||||||
|
targetMatch.prob = {
|
||||||
|
home: swapped ? matchedEvent.pAway : matchedEvent.pHome,
|
||||||
|
draw: matchedEvent.pDraw,
|
||||||
|
away: swapped ? matchedEvent.pHome : matchedEvent.pAway,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// FIFA-API: Live-Scores, Elfmeterschießen, Spielminute
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
const FIFA_BASE = "https://api.fifa.com/api/v3";
|
||||||
|
const FIFA_SEASON = "285023";
|
||||||
|
|
||||||
|
// FIFA-Code → App-Code (nur Abweichungen; sonst identisch)
|
||||||
|
const FIFA_CODE_OVERRIDE: Record<string, string> = {
|
||||||
|
CRO: "HRV", // Kroatien
|
||||||
|
POR: "PRT", // Portugal
|
||||||
|
SUI: "CHE", // Schweiz
|
||||||
|
};
|
||||||
|
function fifaCodeToAppCode(fifaCode: string): string {
|
||||||
|
return FIFA_CODE_OVERRIDE[fifaCode] ?? fifaCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FifaTeamBlock {
|
||||||
|
IdTeam: string; // FIFA-Team-ID
|
||||||
|
Abbreviation: string; // FIFA-Code (z.B. PAR, CRO)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FifaMatch {
|
||||||
|
MatchNumber: number;
|
||||||
|
IdMatch?: string | null;
|
||||||
|
IdStage?: string | null;
|
||||||
|
Home: FifaTeamBlock | null;
|
||||||
|
Away: FifaTeamBlock | null;
|
||||||
|
HomeTeamScore: number | null;
|
||||||
|
AwayTeamScore: number | null;
|
||||||
|
HomeTeamPenaltyScore: number | null;
|
||||||
|
AwayTeamPenaltyScore: number | null;
|
||||||
|
MatchStatus: number; // 0=finished, 1=scheduled, else=live
|
||||||
|
MatchTime: string | null; // z.B. "132'"
|
||||||
|
ResultType: number | null; // 1=regular, 2=penalties
|
||||||
|
Winner?: string | null; // Team-ID des Siegers
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FifaScores {
|
||||||
|
homeScore: number | null;
|
||||||
|
awayScore: number | null;
|
||||||
|
homePenalty: number | null;
|
||||||
|
awayPenalty: number | null;
|
||||||
|
resultType: number | null;
|
||||||
|
status: MatchStatus;
|
||||||
|
matchTime: string | null;
|
||||||
|
winnerTeamId: string | null;
|
||||||
|
idMatch: string | null;
|
||||||
|
idStage: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// FIFA-API Calendar-Endpoint: Primärquelle für Spiele + Teams
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
interface FifaCalendarTeamBlock {
|
||||||
|
IdTeam: string;
|
||||||
|
Abbreviation: string;
|
||||||
|
TeamName: Array<{ Locale: string; Description: string }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FifaCalendarMatch {
|
||||||
|
IdMatch: string;
|
||||||
|
IdStage: string;
|
||||||
|
IdGroup: string | null;
|
||||||
|
MatchNumber: number;
|
||||||
|
Date: string;
|
||||||
|
Home: FifaCalendarTeamBlock | null;
|
||||||
|
Away: FifaCalendarTeamBlock | null;
|
||||||
|
HomeTeamScore: number | null;
|
||||||
|
AwayTeamScore: number | null;
|
||||||
|
HomeTeamPenaltyScore: number | null;
|
||||||
|
AwayTeamPenaltyScore: number | null;
|
||||||
|
MatchStatus: number;
|
||||||
|
MatchTime: string | null;
|
||||||
|
ResultType: number | null;
|
||||||
|
Winner?: string | null;
|
||||||
|
Attendance: string | null;
|
||||||
|
Stadium?: {
|
||||||
|
Name: Array<{ Locale: string; Description: string }>;
|
||||||
|
CityName: Array<{ Locale: string; Description: string }>;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Holt alle Spiele + Teams von der FIFA-API (parallele Quelle, noch nicht aktiv).
|
||||||
|
export async function fetchMatchesAndTeamsFifa(locale: string = "de"): Promise<{ matches: Match[]; teams: Team[] }> {
|
||||||
|
return cached(`fifa:matches:${locale}`, 60_000, async () => {
|
||||||
|
const lang = locale === "en" ? "en" : "de";
|
||||||
|
const url = `${FIFA_BASE}/calendar/matches?language=${lang}&count=500&idSeason=${FIFA_SEASON}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
cache: "no-store",
|
||||||
|
headers: { "User-Agent": "wm2026-board/1.0" },
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`fifa-calendar ${res.status}`);
|
||||||
|
const data = (await res.json()) as { Results: FifaCalendarMatch[] };
|
||||||
|
console.log("[fifa-fetch] Kalender geladen, Result-Array Länge:", (data.Results ?? []).length);
|
||||||
|
|
||||||
|
const teamMap = new Map<string, Team>();
|
||||||
|
|
||||||
|
function teamFromBlock(tb: FifaCalendarTeamBlock, idGroup: string | null): Team | null {
|
||||||
|
const id = tb.IdTeam;
|
||||||
|
if (teamMap.has(id)) return teamMap.get(id)!;
|
||||||
|
const code = fifaCodeToAppCode(tb.Abbreviation);
|
||||||
|
const group = idGroup ? FIFA_GROUP_MAP[idGroup] : null;
|
||||||
|
if (!group) return null;
|
||||||
|
const loc = TEAM_LOCALIZATION[code.toUpperCase()];
|
||||||
|
const name = tb.TeamName?.[0]?.Description ?? "";
|
||||||
|
const t: Team = {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
code,
|
||||||
|
group,
|
||||||
|
localisedName: loc ? loc[lang === "en" ? "en" : "de"] : name,
|
||||||
|
localisedNames: loc ? { de: loc.de, en: loc.en } : { de: name, en: name },
|
||||||
|
};
|
||||||
|
teamMap.set(id, t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapFifaStatus(ms: number): MatchStatus {
|
||||||
|
switch (ms) {
|
||||||
|
case 0: return "FINISHED";
|
||||||
|
case 1: return "SCHEDULED";
|
||||||
|
case 10: return "POSTPONED";
|
||||||
|
default: return "LIVE";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const matches: Match[] = (data.Results ?? []).map((fm) => {
|
||||||
|
const group = fm.IdGroup ? FIFA_GROUP_MAP[fm.IdGroup] ?? null : null;
|
||||||
|
let homeTeam: Team | null = null;
|
||||||
|
let awayTeam: Team | null = null;
|
||||||
|
if (fm.Home) homeTeam = teamFromBlock(fm.Home, fm.IdGroup);
|
||||||
|
if (fm.Away) awayTeam = teamFromBlock(fm.Away, fm.IdGroup);
|
||||||
|
const attendance = fm.Attendance ? parseInt(fm.Attendance, 10) || null : null;
|
||||||
|
const minute = fm.MatchTime ? parseInt(fm.MatchTime, 10) || null : null;
|
||||||
|
const pref = lang === "en" ? "en-GB" : "de-DE";
|
||||||
|
const stadiumName = fm.Stadium?.Name?.find(n => n.Locale === pref)?.Description
|
||||||
|
?? fm.Stadium?.Name?.[0]?.Description ?? null;
|
||||||
|
const stadiumCity = fm.Stadium?.CityName?.find(n => n.Locale === pref)?.Description
|
||||||
|
?? fm.Stadium?.CityName?.[0]?.Description ?? null;
|
||||||
|
return {
|
||||||
|
id: fm.IdMatch,
|
||||||
|
group,
|
||||||
|
stage: FIFA_STAGE_MAP[fm.IdStage] ?? "GROUP",
|
||||||
|
matchNumber: fm.MatchNumber,
|
||||||
|
utcDate: fm.Date,
|
||||||
|
status: mapFifaStatus(fm.MatchStatus),
|
||||||
|
minute,
|
||||||
|
homeTeamId: fm.Home?.IdTeam ?? null,
|
||||||
|
awayTeamId: fm.Away?.IdTeam ?? null,
|
||||||
|
homeScore: fm.HomeTeamScore,
|
||||||
|
awayScore: fm.AwayTeamScore,
|
||||||
|
homePenalty: fm.HomeTeamPenaltyScore,
|
||||||
|
awayPenalty: fm.AwayTeamPenaltyScore,
|
||||||
|
winnerTeamId: fm.Winner ?? null,
|
||||||
|
venue: null,
|
||||||
|
stadiumName,
|
||||||
|
stadiumCity,
|
||||||
|
attendance,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const teams = [...teamMap.values()];
|
||||||
|
console.log("[fifa-fetch] Teams:", teams.length, "Matches:", matches.length);
|
||||||
|
return { matches, teams };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Holt Live-Scores von der FIFA-API. Gibt Map MatchNumber → Scores + FIFA-ID→App-Code-Map zurück.
|
||||||
|
// Scores/Status/Penalties/Winner sind sprachunabhängig → locale-freier Cache-Key.
|
||||||
|
export async function fetchFifaScores(): Promise<{
|
||||||
|
scores: Map<number, FifaScores>;
|
||||||
|
fifaIdToAppCode: Map<string, string>;
|
||||||
|
}> {
|
||||||
|
return cached("fifa:scores", 45_000, async () => {
|
||||||
|
const url = `${FIFA_BASE}/calendar/matches?language=en&count=500&idSeason=${FIFA_SEASON}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
cache: "no-store",
|
||||||
|
headers: { "User-Agent": "wm2026-board/1.0" },
|
||||||
|
signal: AbortSignal.timeout(5000),
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`fifa ${res.status}`);
|
||||||
|
const data = (await res.json()) as { Results: FifaMatch[] };
|
||||||
|
console.log("[fifa-fetch] Scores geladen, Result-Array Länge:", (data.Results ?? []).length);
|
||||||
|
const scores = new Map<number, FifaScores>();
|
||||||
|
const fifaIdToAppCode = new Map<string, string>();
|
||||||
|
|
||||||
|
for (const fm of data.Results ?? []) {
|
||||||
|
// Team-Mapping sammeln
|
||||||
|
for (const tb of [fm.Home, fm.Away]) {
|
||||||
|
if (tb && !fifaIdToAppCode.has(tb.IdTeam)) {
|
||||||
|
fifaIdToAppCode.set(tb.IdTeam, fifaCodeToAppCode(tb.Abbreviation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let status: MatchStatus;
|
||||||
|
switch (fm.MatchStatus) {
|
||||||
|
case 0: status = "FINISHED"; break;
|
||||||
|
case 1: status = "SCHEDULED"; break;
|
||||||
|
case 10: status = "POSTPONED"; break;
|
||||||
|
default: status = "LIVE"; break;
|
||||||
|
}
|
||||||
|
scores.set(fm.MatchNumber, {
|
||||||
|
homeScore: fm.HomeTeamScore,
|
||||||
|
awayScore: fm.AwayTeamScore,
|
||||||
|
homePenalty: fm.HomeTeamPenaltyScore,
|
||||||
|
awayPenalty: fm.AwayTeamPenaltyScore,
|
||||||
|
resultType: fm.ResultType,
|
||||||
|
status,
|
||||||
|
matchTime: fm.MatchTime,
|
||||||
|
winnerTeamId: fm.Winner ?? null,
|
||||||
|
idMatch: fm.IdMatch ?? null,
|
||||||
|
idStage: fm.IdStage ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("[fifa-fetch] Score-Einträge:", scores.size, "Team-Mappings:", fifaIdToAppCode.size);
|
||||||
|
return { scores, fifaIdToAppCode };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wendet FIFA-Live-Scores auf Matches an (MatchNumber als exakter Schlüssel).
|
||||||
|
// Team-IDs sind jetzt FIFA-IDs → winnerTeamId kann direkt gesetzt werden.
|
||||||
|
export function applyFifaScores(
|
||||||
|
matches: Match[], teams: Team[],
|
||||||
|
fifaData: { scores: Map<number, FifaScores>; fifaIdToAppCode: Map<string, string> },
|
||||||
|
): Match[] {
|
||||||
|
const { scores: fifaMap } = fifaData;
|
||||||
|
if (fifaMap.size === 0) return matches;
|
||||||
|
let applied = 0;
|
||||||
|
const result = matches.map((m) => {
|
||||||
|
const fs = fifaMap.get(m.matchNumber);
|
||||||
|
if (!fs) return m;
|
||||||
|
const r = { ...m };
|
||||||
|
if (fs.homeScore != null) r.homeScore = fs.homeScore;
|
||||||
|
if (fs.awayScore != null) r.awayScore = fs.awayScore;
|
||||||
|
if (fs.homePenalty != null) r.homePenalty = fs.homePenalty;
|
||||||
|
if (fs.awayPenalty != null) r.awayPenalty = fs.awayPenalty;
|
||||||
|
if (fs.winnerTeamId) r.winnerTeamId = fs.winnerTeamId;
|
||||||
|
if (fs.matchTime) {
|
||||||
|
const min = parseInt(fs.matchTime, 10);
|
||||||
|
if (!isNaN(min)) r.minute = min;
|
||||||
|
}
|
||||||
|
r.status = fs.status;
|
||||||
|
applied++;
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
if (applied > 0) console.log("[fifa] scores angewandt:", applied);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Holt Tor-Details pro Spiel vom FIFA-Detail-Endpoint.
|
||||||
|
interface FifaGoalRaw { scorer: string; minute: string; team: "home" | "away"; type: number | null; }
|
||||||
|
|
||||||
|
function locName(arr: Array<{ Locale: string; Description: string }> | undefined): string {
|
||||||
|
if (!arr || arr.length === 0) return "";
|
||||||
|
return (arr.find(x => x.Locale === "de-DE")
|
||||||
|
?? arr.find(x => x.Locale === "en-GB")
|
||||||
|
?? arr[0])?.Description ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function normMinuteStr(min: string | null | undefined): string {
|
||||||
|
return (min ?? "").replace(/'/g, "").replace(/\s+/g, "").trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchFifaGoals(
|
||||||
|
idStage: string, idMatch: string, locale: string = "de",
|
||||||
|
ttlMs: number = 60_000,
|
||||||
|
): Promise<FifaGoalRaw[]> {
|
||||||
|
return cached(`fifa:detail:${locale}:${idMatch}`, ttlMs, async () => {
|
||||||
|
const lang = locale === "en" ? "en" : "de";
|
||||||
|
const url = `${FIFA_BASE}/live/football/17/${FIFA_SEASON}/${idStage}/${idMatch}?language=${lang}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
cache: "no-store",
|
||||||
|
headers: { "User-Agent": "wm2026-board/1.0" },
|
||||||
|
signal: AbortSignal.timeout(5000),
|
||||||
|
});
|
||||||
|
if (!res.ok) { console.warn("[fifa-detail] status", res.status, idMatch); return []; }
|
||||||
|
const dj: any = await res.json();
|
||||||
|
|
||||||
|
const buildPlayerMap = (teamBlock: any): Map<string, string> => {
|
||||||
|
const map = new Map<string, string>();
|
||||||
|
for (const p of teamBlock?.Players ?? []) {
|
||||||
|
map.set(String(p.IdPlayer), locName(p.PlayerName) || locName(p.ShortName));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
const homeBlock = dj.HomeTeam, awayBlock = dj.AwayTeam;
|
||||||
|
const homePlayers = buildPlayerMap(homeBlock);
|
||||||
|
const awayPlayers = buildPlayerMap(awayBlock);
|
||||||
|
|
||||||
|
const goals: FifaGoalRaw[] = [];
|
||||||
|
for (const [block, players, side] of [
|
||||||
|
[homeBlock, homePlayers, "home"] as const,
|
||||||
|
[awayBlock, awayPlayers, "away"] as const,
|
||||||
|
]) {
|
||||||
|
for (const g of block?.Goals ?? []) {
|
||||||
|
const min = normMinuteStr(g.Minute);
|
||||||
|
if (min === "" || isNaN(parseInt(min, 10))) continue;
|
||||||
|
goals.push({
|
||||||
|
scorer: players.get(String(g.IdPlayer)) || "?",
|
||||||
|
minute: normMinuteStr(g.Minute),
|
||||||
|
team: side,
|
||||||
|
type: g.Type ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goals.sort((a, b) => parseInt(a.minute, 10) - parseInt(b.minute, 10));
|
||||||
|
return goals;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lädt Tor-Details für laufende und alle beendeten Spiele mit Toren.
|
||||||
|
// Beendete Spiele werden über langlebiges Caching (24h) gespart, nicht über Ausschluss.
|
||||||
|
// Tore eines beendeten Spiels ändern sich nie mehr → einmal fetchen genügt.
|
||||||
|
export async function attachFifaGoals(
|
||||||
|
matches: Match[],
|
||||||
|
fifaData: { scores: Map<number, FifaScores>; fifaIdToAppCode: Map<string, string> },
|
||||||
|
locale: string = "de",
|
||||||
|
): Promise<Match[]> {
|
||||||
|
const targets = matches.filter(m =>
|
||||||
|
(m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED" || m.status === "FINISHED") &&
|
||||||
|
((m.homeScore ?? 0) + (m.awayScore ?? 0)) > 0,
|
||||||
|
);
|
||||||
|
if (targets.length === 0) return matches;
|
||||||
|
|
||||||
|
const goalsByMatchId = new Map<string, GoalEvent[]>();
|
||||||
|
const results = await Promise.allSettled(targets.map(async (m) => {
|
||||||
|
const fs = fifaData.scores.get(m.matchNumber);
|
||||||
|
if (!fs?.idMatch || !fs?.idStage) return;
|
||||||
|
const isFinished = m.status === "FINISHED";
|
||||||
|
const ttl = isFinished ? 24 * 60 * 60 * 1000 : 60_000;
|
||||||
|
const goals = await fetchFifaGoals(fs.idStage, fs.idMatch, locale, ttl);
|
||||||
|
if (goals.length) goalsByMatchId.set(m.id, goals);
|
||||||
|
}));
|
||||||
|
|
||||||
|
const fetched = results.filter(r => r.status === "fulfilled").length;
|
||||||
|
const failed = results.filter(r => r.status === "rejected").length;
|
||||||
|
if (goalsByMatchId.size > 0 || failed > 0) {
|
||||||
|
console.log("[fifa-fetch] Goals: geladen für", goalsByMatchId.size, "Matches,", fetched, "OK,", failed, "Fehler");
|
||||||
|
}
|
||||||
|
if (goalsByMatchId.size === 0) return matches;
|
||||||
|
|
||||||
|
return matches.map(m => {
|
||||||
|
const g = goalsByMatchId.get(m.id);
|
||||||
|
return g ? { ...m, goals: g.map(({ scorer, minute, team }) => ({ scorer, minute, team })) } : m;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// FIFA Live-Daten Pipeline: kombiniert Scores + Goals in gestufter Abfolge.
|
||||||
|
// Step 1: Scores von der FIFA-API holen (enthält idMatch/idStage-Mappings).
|
||||||
|
// Step 2: Scores auf die Matches anwenden (MatchNumber als Schlüssel).
|
||||||
|
// Step 3: Goal-Details NUR für live/beendete Matches mit Toren nachladen.
|
||||||
|
//
|
||||||
|
// Die Schritte werden sequentiell ausgeführt (kein Promise.all wie zuvor),
|
||||||
|
// damit fehlende ID-Mappings nicht zu sinnlosen Requests führen.
|
||||||
|
// Jeder Schritt loggt die Array-/Map-Länge, sodass auf der Vercel-Konsole
|
||||||
|
// sofort ersichtlich ist, ob der Upstream leer ist oder der Fehler im Mapping liegt.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
export async function attachFifaLiveData(
|
||||||
|
matches: Match[],
|
||||||
|
teams: Team[],
|
||||||
|
locale: string = "de",
|
||||||
|
): Promise<Match[]> {
|
||||||
|
// --- Step 1: Scores von FIFA holen ---
|
||||||
|
let fifaData: Awaited<ReturnType<typeof fetchFifaScores>>;
|
||||||
|
try {
|
||||||
|
fifaData = await fetchFifaScores();
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("[fifa-fetch] Scores fehlgeschlagen:", err instanceof Error ? err.message : err);
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Step 2: Scores auf Matches anwenden ---
|
||||||
|
const updated = applyFifaScores(matches, teams, fifaData);
|
||||||
|
|
||||||
|
// --- Step 3: Goal-Details für alle Spiele mit Toren (live + beendet) ---
|
||||||
|
// Requests werden durch differenzierte Cache-TTL gespart:
|
||||||
|
// beendete Spiele → 24h (Tore ändern sich nie)
|
||||||
|
// laufende Spiele → 60s (neue Tore erscheinen)
|
||||||
|
const targets = updated.filter(m => {
|
||||||
|
const fs = fifaData.scores.get(m.matchNumber);
|
||||||
|
return (
|
||||||
|
(m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED" || m.status === "FINISHED") &&
|
||||||
|
((m.homeScore ?? 0) + (m.awayScore ?? 0)) > 0 &&
|
||||||
|
fs?.idMatch != null &&
|
||||||
|
fs?.idStage != null
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (targets.length === 0) {
|
||||||
|
console.log("[fifa-fetch] Pipeline: Scores aktualisiert, keine Goal-Requests nötig");
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
const goalsByMatchId = new Map<string, GoalEvent[]>();
|
||||||
|
let fetched = 0;
|
||||||
|
let failed = 0;
|
||||||
|
|
||||||
|
for (const m of targets) {
|
||||||
|
const fs = fifaData.scores.get(m.matchNumber)!;
|
||||||
|
if (!fs.idMatch || !fs.idStage) continue;
|
||||||
|
const isFinished = m.status === "FINISHED";
|
||||||
|
const ttl = isFinished ? 24 * 60 * 60 * 1000 : 60_000; // beendet: 24h, live: 60s
|
||||||
|
try {
|
||||||
|
const goals = await fetchFifaGoals(fs.idStage, fs.idMatch, locale, ttl);
|
||||||
|
fetched++;
|
||||||
|
if (goals.length) goalsByMatchId.set(m.id, goals);
|
||||||
|
} catch {
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[fifa-fetch] Pipeline: Goals für", goalsByMatchId.size, "Matches geladen (", fetched, "OK,", failed, "Fehler )");
|
||||||
|
|
||||||
|
if (goalsByMatchId.size === 0) return updated;
|
||||||
|
|
||||||
|
return updated.map(m => {
|
||||||
|
const g = goalsByMatchId.get(m.id);
|
||||||
|
return g ? { ...m, goals: g.map(({ scorer, minute, team }) => ({ scorer, minute, team })) } : m;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
14
lib/fifa-constants.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { GroupId, Match } from "./types";
|
||||||
|
|
||||||
|
// FIFA IdGroup → App-GroupId (verifiziert, fortlaufend 289275-289286)
|
||||||
|
export const FIFA_GROUP_MAP: Record<string, GroupId> = {
|
||||||
|
"289275": "A", "289276": "B", "289277": "C", "289278": "D",
|
||||||
|
"289279": "E", "289280": "F", "289281": "G", "289282": "H",
|
||||||
|
"289283": "I", "289284": "J", "289285": "K", "289286": "L",
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIFA IdStage → App-Stage (verifiziert)
|
||||||
|
export const FIFA_STAGE_MAP: Record<string, Match["stage"]> = {
|
||||||
|
"289273": "GROUP", "289287": "R32", "289288": "R16",
|
||||||
|
"289289": "QF", "289290": "SF", "289291": "3RD", "289292": "FINAL",
|
||||||
|
};
|
||||||
52
lib/flags.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// TLA (3-Buchstaben, wie in TEAM_LOCALIZATION) → circle-flags ISO-2-Dateiname.
|
||||||
|
// Vollständig für alle Teams aus TEAM_LOCALIZATION.
|
||||||
|
export const TLA_TO_ISO2: Record<string, string> = {
|
||||||
|
ALG: "dz",
|
||||||
|
ARG: "ar",
|
||||||
|
AUS: "au",
|
||||||
|
AUT: "at",
|
||||||
|
BEL: "be",
|
||||||
|
BIH: "ba",
|
||||||
|
BRA: "br",
|
||||||
|
CAN: "ca",
|
||||||
|
CHE: "ch",
|
||||||
|
CIV: "ci",
|
||||||
|
COD: "cd",
|
||||||
|
COL: "co",
|
||||||
|
CPV: "cv",
|
||||||
|
CUW: "cw",
|
||||||
|
CZE: "cz",
|
||||||
|
ECU: "ec",
|
||||||
|
EGY: "eg",
|
||||||
|
ENG: "gb-eng",
|
||||||
|
ESP: "es",
|
||||||
|
FRA: "fr",
|
||||||
|
GER: "de",
|
||||||
|
GHA: "gh",
|
||||||
|
HAI: "ht",
|
||||||
|
HRV: "hr",
|
||||||
|
IRN: "ir",
|
||||||
|
IRQ: "iq",
|
||||||
|
JOR: "jo",
|
||||||
|
JPN: "jp",
|
||||||
|
KOR: "kr",
|
||||||
|
KSA: "sa",
|
||||||
|
MAR: "ma",
|
||||||
|
MEX: "mx",
|
||||||
|
NED: "nl",
|
||||||
|
NOR: "no",
|
||||||
|
NZL: "nz",
|
||||||
|
PAN: "pa",
|
||||||
|
PAR: "py",
|
||||||
|
PRT: "pt",
|
||||||
|
QAT: "qa",
|
||||||
|
RSA: "za",
|
||||||
|
SCO: "gb-sct",
|
||||||
|
SEN: "sn",
|
||||||
|
SWE: "se",
|
||||||
|
TUN: "tn",
|
||||||
|
TUR: "tr",
|
||||||
|
URU: "uy",
|
||||||
|
USA: "us",
|
||||||
|
UZB: "uz",
|
||||||
|
};
|
||||||
140
lib/i18n/de.ts
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import { Dictionary } from "./types";
|
||||||
|
|
||||||
|
const de: Dictionary = {
|
||||||
|
meta: {
|
||||||
|
title: "WM 2026 Live-Ticker, Ergebnisse & K.o.-Baum",
|
||||||
|
description:
|
||||||
|
"Live-Ergebnisse, Gruppentabellen, K.o.-Baum und Prognosen zur Fußball-WM 2026 in den USA, Kanada & Mexiko. Alle Spiele in Echtzeit.",
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
hostCountries: "USA · Kanada · Mexiko",
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
feedOffline: "Feed offline",
|
||||||
|
updated: (time: string) => `Aktualisiert ${time}`,
|
||||||
|
live: "Live",
|
||||||
|
loading: "Lade Daten…",
|
||||||
|
running: "läuft",
|
||||||
|
halftime: "Halbzeit",
|
||||||
|
finished: "Beendet",
|
||||||
|
postponed: "Verzögert",
|
||||||
|
},
|
||||||
|
nav: {
|
||||||
|
koFixtures: "K.O.-Spiele",
|
||||||
|
groups: "Gruppen",
|
||||||
|
groupFixtures: (group: string) => `Gruppenspiele – ${group}`,
|
||||||
|
groupFixturesNoGroup: "Gruppenspiele",
|
||||||
|
thirdPlace: "Drittplatzierte",
|
||||||
|
bracket: "K.o.-Baum",
|
||||||
|
simulation: "Simulation",
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
feedUnreachable:
|
||||||
|
"Die Live-Feeds sind gerade nicht erreichbar. Die Seite versucht es automatisch erneut.",
|
||||||
|
unknown: "unbekannter Fehler",
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
dashboard: "WM 2026 Dashboard",
|
||||||
|
dataSources: "Daten: FIFA · Polymarket · Annex C",
|
||||||
|
},
|
||||||
|
sim: {
|
||||||
|
notice:
|
||||||
|
"Simulation — alle ungespielten Spiele sind mit dem Polymarket-Favoriten vorbelegt. Die angezeigten Wahrscheinlichkeiten stammen von Polymarket.",
|
||||||
|
heading: "Simulierter K.o.-Baum",
|
||||||
|
},
|
||||||
|
koFixtures: {
|
||||||
|
noMatches: "Keine K.o.-Spiele mit bekannten Teams verfügbar.",
|
||||||
|
liveBadge: "LIVE",
|
||||||
|
nextMatch: "NÄCHSTES SPIEL",
|
||||||
|
postponedBadge: "VERZÖGERT",
|
||||||
|
match: (n: number) => `Spiel ${n}`,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
goals: "Tore",
|
||||||
|
liveIndicator: "● LIVE",
|
||||||
|
scrollToTop: "Nach oben scrollen",
|
||||||
|
securelyQualified: "sicher qualifiziert",
|
||||||
|
},
|
||||||
|
stage: {
|
||||||
|
r16: "Achtelfinale",
|
||||||
|
qf: "Viertelfinale",
|
||||||
|
sf: "Halbfinale",
|
||||||
|
thirdPlace: "Platz 3",
|
||||||
|
final: "Finale",
|
||||||
|
},
|
||||||
|
round: {
|
||||||
|
r32: "Letzte 32",
|
||||||
|
r16: "Achtelfinale",
|
||||||
|
qf: "Viertelfinale",
|
||||||
|
sf: "Halbfinale",
|
||||||
|
final: "Finale",
|
||||||
|
thirdPlace: "Spiel um Platz 3",
|
||||||
|
},
|
||||||
|
bracket: {
|
||||||
|
provisionalTooltip: "vorläufig – Gruppe/Zuordnung noch nicht fix",
|
||||||
|
match: (n: number) => `Spiel ${n}`,
|
||||||
|
penaltyShootout: "i.E.",
|
||||||
|
annexHeader: "Annex-C-Zuordnung der Drittplatzierten:",
|
||||||
|
annexResolved:
|
||||||
|
"aufgelöst — die acht Dritten sind den Gruppensiegern fest zugeteilt",
|
||||||
|
annexPending:
|
||||||
|
"noch offen — sobald die 8 besten Dritten feststehen, verbindet sich der Baum automatisch",
|
||||||
|
winner: "Sieger",
|
||||||
|
loser: "Verlierer",
|
||||||
|
winnerFromMatch: (n: number) => `Sieger aus Spiel ${n}`,
|
||||||
|
loserFromMatch: (n: number) => `Verlierer aus Spiel ${n}`,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
winner: "Sieger / weiter",
|
||||||
|
final: "Finale",
|
||||||
|
fixed: "fix qualifiziert",
|
||||||
|
provisional: "vorläufig (≈, nach aktueller Tabelle)",
|
||||||
|
placeholder: "Platzhalter offen",
|
||||||
|
probExplanation:
|
||||||
|
"%-Werte: Polymarket-Wahrscheinlichkeit (falls verfügbar)",
|
||||||
|
},
|
||||||
|
tooltips: {
|
||||||
|
provisionalPrefix: "aktuell",
|
||||||
|
firstOfGroup: (group: string) => `1. Gruppe ${group}`,
|
||||||
|
secondOfGroup: (group: string) => `2. Gruppe ${group}`,
|
||||||
|
thirdOfGroup: (group: string) => `3. der Gruppe ${group}`,
|
||||||
|
provisionalThird: (pool: string) => `aktuell 3. Gruppe ${pool}`,
|
||||||
|
},
|
||||||
|
slot: {
|
||||||
|
winner: (group: string) => `Sieger ${group}`,
|
||||||
|
runnerUp: (group: string) => `Zweiter ${group}`,
|
||||||
|
thirdOfGroup: (group: string) => `3. der Gruppe ${group}`,
|
||||||
|
thirdPlacePool: (pool: string) => `3. ${pool}`,
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
rank: "#",
|
||||||
|
team: "Mannschaft",
|
||||||
|
group: "Gruppe",
|
||||||
|
matches: "Sp",
|
||||||
|
won: "S",
|
||||||
|
drawn: "U",
|
||||||
|
lost: "N",
|
||||||
|
goals: "Tore",
|
||||||
|
goalDiff: "±",
|
||||||
|
points: "Pkt",
|
||||||
|
status: "Status",
|
||||||
|
},
|
||||||
|
thirds: {
|
||||||
|
explanation:
|
||||||
|
"Acht der zwölf Gruppendritten erreichen die Runde der letzten 32. Gewertet wird gruppenübergreifend nach Punkten, Tordifferenz und Toren — der Direktvergleich entfällt, weil diese Teams nie gegeneinander gespielt haben. Die Trennlinie markiert den Schnitt zwischen Platz 8 und 9.",
|
||||||
|
advances: "weiter",
|
||||||
|
eliminated: "raus",
|
||||||
|
},
|
||||||
|
fixtures: {
|
||||||
|
standingsTitle: (group: string) => `Tabelle – Gruppe ${group}`,
|
||||||
|
noMatches: (group: string) =>
|
||||||
|
`Für Gruppe ${group} liegen noch keine Spiele im Feed vor.`,
|
||||||
|
},
|
||||||
|
groups: {
|
||||||
|
viewGroupGames: (group: string) => `Spiele der Gruppe ${group} ansehen`,
|
||||||
|
groupLabel: (group: string) => `Gruppe ${group}`,
|
||||||
|
viewGames: "Spiele ansehen →",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default de;
|
||||||
145
lib/i18n/en.ts
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import { Dictionary } from "./types";
|
||||||
|
|
||||||
|
function ordinal(n: number): string {
|
||||||
|
const s = ["th", "st", "nd", "rd"];
|
||||||
|
const v = n % 100;
|
||||||
|
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const en: Dictionary = {
|
||||||
|
meta: {
|
||||||
|
title: "World Cup 2026 Live Scores, Bracket & Standings",
|
||||||
|
description:
|
||||||
|
"Live scores, group standings, knockout bracket and match predictions for the 2026 FIFA World Cup in the USA, Canada & Mexico. Real-time results.",
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
hostCountries: "USA · Canada · Mexico",
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
feedOffline: "Feed offline",
|
||||||
|
updated: (time: string) => `Updated ${time}`,
|
||||||
|
live: "Live",
|
||||||
|
loading: "Loading…",
|
||||||
|
running: "running",
|
||||||
|
halftime: "Half time",
|
||||||
|
finished: "Finished",
|
||||||
|
postponed: "Postponed",
|
||||||
|
},
|
||||||
|
nav: {
|
||||||
|
koFixtures: "KO Matches",
|
||||||
|
groups: "Groups",
|
||||||
|
groupFixtures: (group: string) => `Group Stage – ${group}`,
|
||||||
|
groupFixturesNoGroup: "Group Stage",
|
||||||
|
thirdPlace: "Third Place",
|
||||||
|
bracket: "KO Bracket",
|
||||||
|
simulation: "Simulation",
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
feedUnreachable:
|
||||||
|
"Live feeds are currently unavailable. The page will retry automatically.",
|
||||||
|
unknown: "unknown error",
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
dashboard: "WC 2026 Dashboard",
|
||||||
|
dataSources: "Data: FIFA · Polymarket · Annex C",
|
||||||
|
},
|
||||||
|
sim: {
|
||||||
|
notice:
|
||||||
|
"Simulation — all unplayed matches are pre-filled with the Polymarket favourite. Probabilities shown are from Polymarket.",
|
||||||
|
heading: "Simulated KO Bracket",
|
||||||
|
},
|
||||||
|
koFixtures: {
|
||||||
|
noMatches: "No KO matches with known teams available.",
|
||||||
|
liveBadge: "LIVE",
|
||||||
|
nextMatch: "NEXT MATCH",
|
||||||
|
postponedBadge: "POSTPONED",
|
||||||
|
match: (n: number) => `Match ${n}`,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
goals: "Goals",
|
||||||
|
liveIndicator: "● LIVE",
|
||||||
|
scrollToTop: "Scroll to top",
|
||||||
|
securelyQualified: "securely qualified",
|
||||||
|
},
|
||||||
|
stage: {
|
||||||
|
r16: "Round of 16",
|
||||||
|
qf: "Quarter-finals",
|
||||||
|
sf: "Semi-finals",
|
||||||
|
thirdPlace: "3rd Place",
|
||||||
|
final: "Final",
|
||||||
|
},
|
||||||
|
round: {
|
||||||
|
r32: "Round of 32",
|
||||||
|
r16: "Round of 16",
|
||||||
|
qf: "Quarter-finals",
|
||||||
|
sf: "Semi-finals",
|
||||||
|
final: "Final",
|
||||||
|
thirdPlace: "Third Place Match",
|
||||||
|
},
|
||||||
|
bracket: {
|
||||||
|
provisionalTooltip: "provisional – group/assignment not yet fixed",
|
||||||
|
match: (n: number) => `Match ${n}`,
|
||||||
|
penaltyShootout: "PSO",
|
||||||
|
annexHeader: "Annex C third-place assignment:",
|
||||||
|
annexResolved:
|
||||||
|
"resolved — the eight third-placed teams are permanently assigned to group winners",
|
||||||
|
annexPending:
|
||||||
|
"pending — once the 8 best third-placed teams are determined, the bracket auto-connects",
|
||||||
|
winner: "Winner",
|
||||||
|
loser: "Loser",
|
||||||
|
winnerFromMatch: (n: number) => `Winner of match ${n}`,
|
||||||
|
loserFromMatch: (n: number) => `Loser of match ${n}`,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
winner: "Winner / advances",
|
||||||
|
final: "Final",
|
||||||
|
fixed: "securely qualified",
|
||||||
|
provisional: "provisional (≈, current standings)",
|
||||||
|
placeholder: "placeholder open",
|
||||||
|
probExplanation: "% values: Polymarket probability (if available)",
|
||||||
|
},
|
||||||
|
tooltips: {
|
||||||
|
provisionalPrefix: "currently",
|
||||||
|
firstOfGroup: (group: string) => `${ordinal(1)} in Group ${group}`,
|
||||||
|
secondOfGroup: (group: string) => `${ordinal(2)} in Group ${group}`,
|
||||||
|
thirdOfGroup: (group: string) => `${ordinal(3)} in Group ${group}`,
|
||||||
|
provisionalThird: (pool: string) => `currently 3rd of Group ${pool}`,
|
||||||
|
},
|
||||||
|
slot: {
|
||||||
|
winner: (group: string) => `Winner ${group}`,
|
||||||
|
runnerUp: (group: string) => `Runner-up ${group}`,
|
||||||
|
thirdOfGroup: (group: string) => `3rd of Group ${group}`,
|
||||||
|
thirdPlacePool: (pool: string) => `3rd ${pool}`,
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
rank: "#",
|
||||||
|
team: "Team",
|
||||||
|
group: "Group",
|
||||||
|
matches: "GP",
|
||||||
|
won: "W",
|
||||||
|
drawn: "D",
|
||||||
|
lost: "L",
|
||||||
|
goals: "Goals",
|
||||||
|
goalDiff: "±",
|
||||||
|
points: "Pts",
|
||||||
|
status: "Status",
|
||||||
|
},
|
||||||
|
thirds: {
|
||||||
|
explanation:
|
||||||
|
"Eight of the twelve group third-placed teams advance to the Round of 32. Ranking is across all groups by points, goal difference and goals scored — head-to-head does not apply because these teams have never met. The separator marks the cut between 8th and 9th place.",
|
||||||
|
advances: "advances",
|
||||||
|
eliminated: "out",
|
||||||
|
},
|
||||||
|
fixtures: {
|
||||||
|
standingsTitle: (group: string) => `Standings – Group ${group}`,
|
||||||
|
noMatches: (group: string) =>
|
||||||
|
`No matches available yet for Group ${group}.`,
|
||||||
|
},
|
||||||
|
groups: {
|
||||||
|
viewGroupGames: (group: string) => `View Group ${group} matches`,
|
||||||
|
groupLabel: (group: string) => `Group ${group}`,
|
||||||
|
viewGames: "View matches →",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default en;
|
||||||
11
lib/i18n/index.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Locale, Dictionary } from "./types";
|
||||||
|
import de from "./de";
|
||||||
|
import en from "./en";
|
||||||
|
|
||||||
|
export const dictionaries: Record<Locale, Dictionary> = { de, en };
|
||||||
|
|
||||||
|
export function getDictionary(locale: Locale): Dictionary {
|
||||||
|
return dictionaries[locale] ?? en;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type Locale, type Dictionary } from "./types";
|
||||||
130
lib/i18n/types.ts
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
export type Locale = "de" | "en";
|
||||||
|
|
||||||
|
export interface Dictionary {
|
||||||
|
meta: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
header: {
|
||||||
|
hostCountries: string;
|
||||||
|
};
|
||||||
|
status: {
|
||||||
|
feedOffline: string;
|
||||||
|
updated: (time: string) => string;
|
||||||
|
live: string;
|
||||||
|
loading: string;
|
||||||
|
running: string;
|
||||||
|
halftime: string;
|
||||||
|
finished: string;
|
||||||
|
postponed: string;
|
||||||
|
};
|
||||||
|
nav: {
|
||||||
|
koFixtures: string;
|
||||||
|
groups: string;
|
||||||
|
groupFixtures: (group: string) => string;
|
||||||
|
groupFixturesNoGroup: string;
|
||||||
|
thirdPlace: string;
|
||||||
|
bracket: string;
|
||||||
|
simulation: string;
|
||||||
|
};
|
||||||
|
error: {
|
||||||
|
feedUnreachable: string;
|
||||||
|
unknown: string;
|
||||||
|
};
|
||||||
|
footer: {
|
||||||
|
dashboard: string;
|
||||||
|
dataSources: string;
|
||||||
|
};
|
||||||
|
sim: {
|
||||||
|
notice: string;
|
||||||
|
heading: string;
|
||||||
|
};
|
||||||
|
koFixtures: {
|
||||||
|
noMatches: string;
|
||||||
|
liveBadge: string;
|
||||||
|
nextMatch: string;
|
||||||
|
postponedBadge: string;
|
||||||
|
match: (n: number) => string;
|
||||||
|
};
|
||||||
|
label: {
|
||||||
|
goals: string;
|
||||||
|
liveIndicator: string;
|
||||||
|
scrollToTop: string;
|
||||||
|
securelyQualified: string;
|
||||||
|
};
|
||||||
|
stage: {
|
||||||
|
r16: string;
|
||||||
|
qf: string;
|
||||||
|
sf: string;
|
||||||
|
thirdPlace: string;
|
||||||
|
final: string;
|
||||||
|
};
|
||||||
|
round: {
|
||||||
|
r32: string;
|
||||||
|
r16: string;
|
||||||
|
qf: string;
|
||||||
|
sf: string;
|
||||||
|
final: string;
|
||||||
|
thirdPlace: string;
|
||||||
|
};
|
||||||
|
bracket: {
|
||||||
|
provisionalTooltip: string;
|
||||||
|
match: (n: number) => string;
|
||||||
|
penaltyShootout: string;
|
||||||
|
annexHeader: string;
|
||||||
|
annexResolved: string;
|
||||||
|
annexPending: string;
|
||||||
|
winner: string;
|
||||||
|
loser: string;
|
||||||
|
winnerFromMatch: (n: number) => string;
|
||||||
|
loserFromMatch: (n: number) => string;
|
||||||
|
};
|
||||||
|
legend: {
|
||||||
|
winner: string;
|
||||||
|
final: string;
|
||||||
|
fixed: string;
|
||||||
|
provisional: string;
|
||||||
|
placeholder: string;
|
||||||
|
probExplanation: string;
|
||||||
|
};
|
||||||
|
tooltips: {
|
||||||
|
provisionalPrefix: string;
|
||||||
|
firstOfGroup: (group: string) => string;
|
||||||
|
secondOfGroup: (group: string) => string;
|
||||||
|
thirdOfGroup: (group: string) => string;
|
||||||
|
provisionalThird: (pool: string) => string;
|
||||||
|
};
|
||||||
|
slot: {
|
||||||
|
winner: (group: string) => string;
|
||||||
|
runnerUp: (group: string) => string;
|
||||||
|
thirdOfGroup: (group: string) => string;
|
||||||
|
thirdPlacePool: (pool: string) => string;
|
||||||
|
};
|
||||||
|
table: {
|
||||||
|
rank: string;
|
||||||
|
team: string;
|
||||||
|
group: string;
|
||||||
|
matches: string;
|
||||||
|
won: string;
|
||||||
|
drawn: string;
|
||||||
|
lost: string;
|
||||||
|
goals: string;
|
||||||
|
goalDiff: string;
|
||||||
|
points: string;
|
||||||
|
status: string;
|
||||||
|
};
|
||||||
|
thirds: {
|
||||||
|
explanation: string;
|
||||||
|
advances: string;
|
||||||
|
eliminated: string;
|
||||||
|
};
|
||||||
|
fixtures: {
|
||||||
|
standingsTitle: (group: string) => string;
|
||||||
|
noMatches: (group: string) => string;
|
||||||
|
};
|
||||||
|
groups: {
|
||||||
|
viewGroupGames: (group: string) => string;
|
||||||
|
groupLabel: (group: string) => string;
|
||||||
|
viewGames: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import {
|
|||||||
ThirdAssignment, slotLabel,
|
ThirdAssignment, slotLabel,
|
||||||
} from "@/lib/bracket";
|
} from "@/lib/bracket";
|
||||||
import { placeIsSecure } from "@/lib/secure-places";
|
import { placeIsSecure } from "@/lib/secure-places";
|
||||||
|
import { thirdSlotIsSecure, securelyQualifiedThirdTeams } from "@/lib/third-place-security";
|
||||||
|
import { Dictionary } from "@/lib/i18n";
|
||||||
|
|
||||||
// Ein aufgelöster Teilnehmer einer K.o.-Begegnung.
|
// Ein aufgelöster Teilnehmer einer K.o.-Begegnung.
|
||||||
export interface ResolvedSide {
|
export interface ResolvedSide {
|
||||||
@@ -23,6 +25,8 @@ export interface ResolvedTie {
|
|||||||
away: ResolvedSide;
|
away: ResolvedSide;
|
||||||
status: string;
|
status: string;
|
||||||
prob?: { home: number; draw: number | null; away: number } | null;
|
prob?: { home: number; draw: number | null; away: number } | null;
|
||||||
|
homePenalty?: number | null;
|
||||||
|
awayPenalty?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Findet das tatsächliche Spiel (aus dem Feed) zu einer FIFA-Match-Nummer.
|
// Findet das tatsächliche Spiel (aus dem Feed) zu einer FIFA-Match-Nummer.
|
||||||
@@ -33,28 +37,42 @@ function feedMatch(matches: Match[], num: number): Match | undefined {
|
|||||||
// Bestimmt den Sieger eines abgeschlossenen Spiels (Feed) als Team-ID.
|
// Bestimmt den Sieger eines abgeschlossenen Spiels (Feed) als Team-ID.
|
||||||
function winnerOf(m: Match | undefined): string | null {
|
function winnerOf(m: Match | undefined): string | null {
|
||||||
if (!m || m.status !== "FINISHED") return null;
|
if (!m || m.status !== "FINISHED") return null;
|
||||||
|
if (m.winnerTeamId) return m.winnerTeamId;
|
||||||
if (m.homeScore == null || m.awayScore == null) return null;
|
if (m.homeScore == null || m.awayScore == null) return null;
|
||||||
if (m.homeScore > m.awayScore) return m.homeTeamId;
|
if (m.homeScore > m.awayScore) return m.homeTeamId;
|
||||||
if (m.awayScore > m.homeScore) return m.awayTeamId;
|
if (m.awayScore > m.homeScore) return m.awayTeamId;
|
||||||
return null; // Unentschieden -> Elfmeter; Feed liefert i.d.R. Sieger separat
|
return null;
|
||||||
}
|
}
|
||||||
|
// Bestimmt im Sim-Modus die Sieger-Slot-ID.
|
||||||
|
// Real gespielte Spiele: echtes winnerTeamId (inkl. Elfmeter) auf die
|
||||||
|
// aufgelöste Slot-Seite mappen. Simulierte Spiele: Score-Vergleich.
|
||||||
|
function simWinnerSlotId(feed: Match, homeSlotId: string, awaySlotId: string): string {
|
||||||
|
if (feed.status === "FINISHED" && feed.winnerTeamId) {
|
||||||
|
if (feed.winnerTeamId === homeSlotId) return homeSlotId;
|
||||||
|
if (feed.winnerTeamId === awaySlotId) return awaySlotId;
|
||||||
|
if (feed.homePenalty != null && feed.awayPenalty != null
|
||||||
|
&& feed.homePenalty !== feed.awayPenalty) {
|
||||||
|
return feed.homePenalty > feed.awayPenalty ? homeSlotId : awaySlotId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (feed.homeScore != null && feed.awayScore != null) {
|
||||||
|
if (feed.homeScore > feed.awayScore) return homeSlotId;
|
||||||
|
if (feed.awayScore > feed.homeScore) return awaySlotId;
|
||||||
|
}
|
||||||
|
return homeSlotId;
|
||||||
|
}
|
||||||
|
|
||||||
function loserOf(m: Match | undefined): string | null {
|
function loserOf(m: Match | undefined): string | null {
|
||||||
if (!m || m.status !== "FINISHED") return null;
|
if (!m || m.status !== "FINISHED") return null;
|
||||||
|
if (m.winnerTeamId) {
|
||||||
|
return m.homeTeamId === m.winnerTeamId ? m.awayTeamId : m.homeTeamId;
|
||||||
|
}
|
||||||
if (m.homeScore == null || m.awayScore == null) return null;
|
if (m.homeScore == null || m.awayScore == null) return null;
|
||||||
if (m.homeScore > m.awayScore) return m.awayTeamId;
|
if (m.homeScore > m.awayScore) return m.awayTeamId;
|
||||||
if (m.awayScore > m.homeScore) return m.homeTeamId;
|
if (m.awayScore > m.homeScore) return m.homeTeamId;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prüft, ob die gesamte Gruppenphase abgeschlossen ist.
|
|
||||||
// Erst dann stehen die Drittplatzierten-Rangliste und die
|
|
||||||
// Annex-C-Zuordnung final fest.
|
|
||||||
function groupStageComplete(matches: Match[]): boolean {
|
|
||||||
const groupMatches = matches.filter((m) => m.group != null);
|
|
||||||
if (groupMatches.length === 0) return false;
|
|
||||||
return groupMatches.every((m) => m.status === "FINISHED");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Löst einen R32-Slot (W/R/3) zu einer Team-ID auf, sofern bereits bekannt.
|
// Löst einen R32-Slot (W/R/3) zu einer Team-ID auf, sofern bereits bekannt.
|
||||||
// provisional = true, solange die zugrunde liegende Gruppe/Zuordnung nicht fix ist.
|
// provisional = true, solange die zugrunde liegende Gruppe/Zuordnung nicht fix ist.
|
||||||
function resolveR32Slot(
|
function resolveR32Slot(
|
||||||
@@ -66,46 +84,52 @@ function resolveR32Slot(
|
|||||||
matches: Match[],
|
matches: Match[],
|
||||||
teams: Team[],
|
teams: Team[],
|
||||||
annexResolved: boolean,
|
annexResolved: boolean,
|
||||||
|
secureTeamIds: Set<string>,
|
||||||
|
dict?: Dictionary,
|
||||||
): { teamId: string | null; provisional: boolean; tooltip: string | null } {
|
): { teamId: string | null; provisional: boolean; tooltip: string | null } {
|
||||||
|
const t = dict?.tooltips;
|
||||||
const table = (g: GroupId) => tables.find((t) => t.group === g);
|
const table = (g: GroupId) => tables.find((t) => t.group === g);
|
||||||
if (slot.type === "W") {
|
if (slot.type === "W") {
|
||||||
const t = table(slot.group!);
|
const tab = table(slot.group!);
|
||||||
const teamId = t?.rows.find((r) => r.rank === 1)?.teamId ?? null;
|
const teamId = tab?.rows.find((r) => r.rank === 1)?.teamId ?? null;
|
||||||
// Sieger fix, sobald Platz 1 rechnerisch gesichert ist (auch vor Gruppenende).
|
// Sieger fix, sobald Platz 1 rechnerisch gesichert ist (auch vor Gruppenende).
|
||||||
const provisional = !placeIsSecure(slot.group!, 1, teams, matches);
|
const provisional = !placeIsSecure(slot.group!, 1, teams, matches);
|
||||||
const prefix = provisional ? "aktuell " : "";
|
const prefix = provisional ? (t?.provisionalPrefix ?? "aktuell") + " " : "";
|
||||||
return { teamId, provisional, tooltip: `${prefix}1. Gruppe ${slot.group}` };
|
return { teamId, provisional, tooltip: `${prefix}${t?.firstOfGroup(slot.group!) ?? `1. Gruppe ${slot.group}`}` };
|
||||||
}
|
}
|
||||||
if (slot.type === "R") {
|
if (slot.type === "R") {
|
||||||
const t = table(slot.group!);
|
const tab = table(slot.group!);
|
||||||
const teamId = t?.rows.find((r) => r.rank === 2)?.teamId ?? null;
|
const teamId = tab?.rows.find((r) => r.rank === 2)?.teamId ?? null;
|
||||||
// Zweiter fix, sobald Platz 2 rechnerisch gesichert ist.
|
// Zweiter fix, sobald Platz 2 rechnerisch gesichert ist.
|
||||||
const provisional = !placeIsSecure(slot.group!, 2, teams, matches);
|
const provisional = !placeIsSecure(slot.group!, 2, teams, matches);
|
||||||
const prefix = provisional ? "aktuell " : "";
|
const prefix = provisional ? (t?.provisionalPrefix ?? "aktuell") + " " : "";
|
||||||
return { teamId, provisional, tooltip: `${prefix}2. Gruppe ${slot.group}` };
|
return { teamId, provisional, tooltip: `${prefix}${t?.secondOfGroup(slot.group!) ?? `2. Gruppe ${slot.group}`}` };
|
||||||
}
|
}
|
||||||
// 3. Platz: braucht Annex-C-Zuordnung + den Gruppensieger dieses Spiels
|
// 3. Platz: braucht Annex-C-Zuordnung + den Gruppensieger dieses Spiels
|
||||||
if (slot.type === "3" && assignment && winnerGroup) {
|
if (slot.type === "3" && assignment && winnerGroup) {
|
||||||
const thirdGroup = assignment[winnerGroup];
|
const thirdGroup = assignment[winnerGroup];
|
||||||
if (thirdGroup) {
|
if (thirdGroup) {
|
||||||
const row = thirds.find((r) => r.group === thirdGroup && r.qualifies);
|
const row = thirds.find((r) => r.group === thirdGroup && r.qualifies);
|
||||||
// Fix nur, wenn ALLE drei Bedingungen erfüllt sind:
|
// Fix nur, wenn ALLE Bedingungen erfüllt sind:
|
||||||
// 1. Annex C aufgelöst (8 Dritte zuweisbar)
|
// 1. Annex C aufgelöst (8 Dritte zuweisbar)
|
||||||
// 2. Komplette Gruppenphase beendet (Dritten-Rangliste final)
|
// 2. Der Slot ist in allen noch möglichen Konstellationen stabil
|
||||||
// 3. Das Team gehört gesichert zu den besten 8
|
// 3. Das konkrete Team ist sicher qualifiziert (kann nicht aus Top 8 fallen)
|
||||||
const fix = annexResolved && groupStageComplete(matches) && row?.qualifies === true;
|
// 4. Die Gruppe hat alle Spiele gespielt (Team bekannt)
|
||||||
|
const slotStable = thirdSlotIsSecure(winnerGroup, matches, teams);
|
||||||
|
const teamSecure = row?.teamId ? secureTeamIds.has(row.teamId) : false;
|
||||||
|
const fix = annexResolved && slotStable && teamSecure && row?.qualifies === true;
|
||||||
const provisional = !fix;
|
const provisional = !fix;
|
||||||
const prefix = provisional ? "aktuell " : "";
|
const prefix = provisional ? (t?.provisionalPrefix ?? "aktuell") + " " : "";
|
||||||
return {
|
return {
|
||||||
teamId: row?.teamId ?? null,
|
teamId: row?.teamId ?? null,
|
||||||
provisional,
|
provisional,
|
||||||
tooltip: `${prefix}3. der Gruppe ${thirdGroup}`,
|
tooltip: `${prefix}${t?.thirdOfGroup(thirdGroup) ?? `3. der Gruppe ${thirdGroup}`}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (slot.type === "3") {
|
if (slot.type === "3") {
|
||||||
const pool = slot.thirdPool?.join("") ?? "?";
|
const pool = slot.thirdPool?.join("") ?? "?";
|
||||||
return { teamId: null, provisional: true, tooltip: `aktuell 3. Gruppe ${pool}` };
|
return { teamId: null, provisional: true, tooltip: t?.provisionalThird(pool) ?? `aktuell 3. Gruppe ${pool}` };
|
||||||
}
|
}
|
||||||
return { teamId: null, provisional: true, tooltip: null };
|
return { teamId: null, provisional: true, tooltip: null };
|
||||||
}
|
}
|
||||||
@@ -142,12 +166,16 @@ export function resolveBracket(
|
|||||||
thirds: ThirdPlaceRow[], assignment: ThirdAssignment | null,
|
thirds: ThirdPlaceRow[], assignment: ThirdAssignment | null,
|
||||||
annexResolved: boolean,
|
annexResolved: boolean,
|
||||||
resolveWinners = false,
|
resolveWinners = false,
|
||||||
|
dict?: Dictionary,
|
||||||
): { r32: ResolvedTie[]; later: Record<number, ResolvedTie> } {
|
): { r32: ResolvedTie[]; later: Record<number, ResolvedTie> } {
|
||||||
// Map: Match-Nummer -> Sieger-Team-ID (für Propagation in Folgerunden)
|
// Map: Match-Nummer -> Sieger-Team-ID (für Propagation in Folgerunden)
|
||||||
const winners = new Map<number, string | null>();
|
const winners = new Map<number, string | null>();
|
||||||
const losers = new Map<number, string | null>();
|
const losers = new Map<number, string | null>();
|
||||||
// Map: Match-Nummer -> ist das Spiel beendet (Sieger fix)?
|
// Map: Match-Nummer -> ist das Spiel beendet (Sieger fix)?
|
||||||
const decided = new Map<number, boolean>();
|
const decided = new Map<number, boolean>();
|
||||||
|
const secureTeamIds = securelyQualifiedThirdTeams(matches, teams);
|
||||||
|
|
||||||
|
const b = dict?.bracket;
|
||||||
|
|
||||||
const r32: ResolvedTie[] = R32.map((rm: R32Match) => {
|
const r32: ResolvedTie[] = R32.map((rm: R32Match) => {
|
||||||
const feed = feedMatch(matches, rm.matchNumber);
|
const feed = feedMatch(matches, rm.matchNumber);
|
||||||
@@ -156,26 +184,18 @@ export function resolveBracket(
|
|||||||
// Für 3.-Platz-Slots: Gruppensieger ist die andere Seite (immer W)
|
// Für 3.-Platz-Slots: Gruppensieger ist die andere Seite (immer W)
|
||||||
const winnerGroup = (homeGroup ?? awayGroup) as GroupId | undefined;
|
const winnerGroup = (homeGroup ?? awayGroup) as GroupId | undefined;
|
||||||
|
|
||||||
const h = resolveR32Slot(rm.home, winnerGroup, tables, assignment, thirds, matches, teams, annexResolved);
|
const h = resolveR32Slot(rm.home, winnerGroup, tables, assignment, thirds, matches, teams, annexResolved, secureTeamIds, dict);
|
||||||
const a = resolveR32Slot(rm.away, winnerGroup, tables, assignment, thirds, matches, teams, annexResolved);
|
const a = resolveR32Slot(rm.away, winnerGroup, tables, assignment, thirds, matches, teams, annexResolved, secureTeamIds, dict);
|
||||||
const home = sideFrom(h.teamId, slotLabel(rm.home, assignment, winnerGroup), teams, feed, "home", h.provisional, h.tooltip);
|
const home = sideFrom(h.teamId, slotLabel(rm.home, assignment, winnerGroup, dict), teams, feed, "home", h.provisional, h.tooltip);
|
||||||
const away = sideFrom(a.teamId, slotLabel(rm.away, assignment, winnerGroup), teams, feed, "away", a.provisional, a.tooltip);
|
const away = sideFrom(a.teamId, slotLabel(rm.away, assignment, winnerGroup, dict), teams, feed, "away", a.provisional, a.tooltip);
|
||||||
|
|
||||||
const feedWinner = winnerOf(feed);
|
const feedWinner = winnerOf(feed);
|
||||||
if (resolveWinners && !feedWinner && feed && h.teamId && a.teamId
|
if (resolveWinners && feed && h.teamId && a.teamId
|
||||||
&& feed.homeScore != null && feed.awayScore != null) {
|
&& feed.homeScore != null && feed.awayScore != null) {
|
||||||
// Simulation: Gewinner aus Scores und aufgelösten Team-IDs ableiten
|
const winnerId = simWinnerSlotId(feed, h.teamId, a.teamId);
|
||||||
if (feed.homeScore > feed.awayScore) {
|
const loserId = winnerId === h.teamId ? a.teamId : h.teamId;
|
||||||
winners.set(rm.matchNumber, h.teamId);
|
winners.set(rm.matchNumber, winnerId);
|
||||||
losers.set(rm.matchNumber, loserOf(feed) ?? a.teamId);
|
losers.set(rm.matchNumber, loserId);
|
||||||
} else if (feed.awayScore > feed.homeScore) {
|
|
||||||
winners.set(rm.matchNumber, a.teamId);
|
|
||||||
losers.set(rm.matchNumber, loserOf(feed) ?? h.teamId);
|
|
||||||
} else {
|
|
||||||
// Unentschieden → Heim gewinnt
|
|
||||||
winners.set(rm.matchNumber, h.teamId);
|
|
||||||
losers.set(rm.matchNumber, loserOf(feed) ?? a.teamId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
winners.set(rm.matchNumber, feedWinner);
|
winners.set(rm.matchNumber, feedWinner);
|
||||||
losers.set(rm.matchNumber, loserOf(feed));
|
losers.set(rm.matchNumber, loserOf(feed));
|
||||||
@@ -184,6 +204,7 @@ export function resolveBracket(
|
|||||||
return {
|
return {
|
||||||
matchNumber: rm.matchNumber, stage: "R32",
|
matchNumber: rm.matchNumber, stage: "R32",
|
||||||
home, away, status: feed?.status ?? "SCHEDULED", prob: feed?.prob,
|
home, away, status: feed?.status ?? "SCHEDULED", prob: feed?.prob,
|
||||||
|
homePenalty: feed?.homePenalty, awayPenalty: feed?.awayPenalty,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -193,29 +214,44 @@ export function resolveBracket(
|
|||||||
const src = km.losers ? losers : winners;
|
const src = km.losers ? losers : winners;
|
||||||
const homeId = src.get(km.fromHome) ?? null;
|
const homeId = src.get(km.fromHome) ?? null;
|
||||||
const awayId = src.get(km.fromAway) ?? null;
|
const awayId = src.get(km.fromAway) ?? null;
|
||||||
|
if (km.matchNumber === 89 || km.matchNumber === 90) {
|
||||||
|
console.log("[PROPAGATE-R16]", {
|
||||||
|
zielSlot: km.matchNumber,
|
||||||
|
fromHome: km.fromHome,
|
||||||
|
fromAway: km.fromAway,
|
||||||
|
homeIdAusWinners: homeId,
|
||||||
|
awayIdAusWinners: awayId,
|
||||||
|
homeIdAusLosers: losers.get(km.fromHome) ?? null,
|
||||||
|
awayIdAusLosers: losers.get(km.fromAway) ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Ein Folgeteam ist fix, wenn das speisende Spiel beendet ist.
|
// Ein Folgeteam ist fix, wenn das speisende Spiel beendet ist.
|
||||||
const homeProv = !(decided.get(km.fromHome) ?? false);
|
const homeProv = !(decided.get(km.fromHome) ?? false);
|
||||||
const awayProv = !(decided.get(km.fromAway) ?? false);
|
const awayProv = !(decided.get(km.fromAway) ?? false);
|
||||||
const homeLabel = `${km.losers ? "Verlierer" : "Sieger"} ${km.fromHome}`;
|
const loserLabel = km.losers ? true : false;
|
||||||
const awayLabel = `${km.losers ? "Verlierer" : "Sieger"} ${km.fromAway}`;
|
const homeLabel = loserLabel
|
||||||
const homeTtip = `${km.losers ? "Verlierer" : "Sieger"} aus Spiel ${km.fromHome}`;
|
? (b?.loser ?? "Verlierer") + " " + km.fromHome
|
||||||
const awayTtip = `${km.losers ? "Verlierer" : "Sieger"} aus Spiel ${km.fromAway}`;
|
: (b?.winner ?? "Sieger") + " " + km.fromHome;
|
||||||
|
const awayLabel = loserLabel
|
||||||
|
? (b?.loser ?? "Verlierer") + " " + km.fromAway
|
||||||
|
: (b?.winner ?? "Sieger") + " " + km.fromAway;
|
||||||
|
const homeTtip = loserLabel
|
||||||
|
? (b?.loserFromMatch(km.fromHome) ?? `Verlierer aus Spiel ${km.fromHome}`)
|
||||||
|
: (b?.winnerFromMatch(km.fromHome) ?? `Sieger aus Spiel ${km.fromHome}`);
|
||||||
|
const awayTtip = loserLabel
|
||||||
|
? (b?.loserFromMatch(km.fromAway) ?? `Verlierer aus Spiel ${km.fromAway}`)
|
||||||
|
: (b?.winnerFromMatch(km.fromAway) ?? `Sieger aus Spiel ${km.fromAway}`);
|
||||||
const home = sideFrom(homeId, homeLabel, teams, feed, "home", homeProv, homeTtip);
|
const home = sideFrom(homeId, homeLabel, teams, feed, "home", homeProv, homeTtip);
|
||||||
const away = sideFrom(awayId, awayLabel, teams, feed, "away", awayProv, awayTtip);
|
const away = sideFrom(awayId, awayLabel, teams, feed, "away", awayProv, awayTtip);
|
||||||
|
|
||||||
const feedWinner = winnerOf(feed);
|
const feedWinner = winnerOf(feed);
|
||||||
if (resolveWinners && !feedWinner && feed && homeId && awayId
|
if (resolveWinners && feed && homeId && awayId
|
||||||
&& feed.homeScore != null && feed.awayScore != null) {
|
&& feed.homeScore != null && feed.awayScore != null) {
|
||||||
if (feed.homeScore > feed.awayScore) {
|
const winnerId = simWinnerSlotId(feed, homeId, awayId);
|
||||||
winners.set(km.matchNumber, homeId);
|
const loserId = winnerId === homeId ? awayId : homeId;
|
||||||
losers.set(km.matchNumber, loserOf(feed) ?? awayId);
|
winners.set(km.matchNumber, winnerId);
|
||||||
} else if (feed.awayScore > feed.homeScore) {
|
losers.set(km.matchNumber, loserId);
|
||||||
winners.set(km.matchNumber, awayId);
|
|
||||||
losers.set(km.matchNumber, loserOf(feed) ?? homeId);
|
|
||||||
} else {
|
|
||||||
winners.set(km.matchNumber, homeId);
|
|
||||||
losers.set(km.matchNumber, loserOf(feed) ?? awayId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
winners.set(km.matchNumber, feedWinner);
|
winners.set(km.matchNumber, feedWinner);
|
||||||
losers.set(km.matchNumber, loserOf(feed));
|
losers.set(km.matchNumber, loserOf(feed));
|
||||||
@@ -224,6 +260,7 @@ export function resolveBracket(
|
|||||||
later[km.matchNumber] = {
|
later[km.matchNumber] = {
|
||||||
matchNumber: km.matchNumber, stage: km.stage,
|
matchNumber: km.matchNumber, stage: km.stage,
|
||||||
home, away, status: feed?.status ?? "SCHEDULED", prob: feed?.prob,
|
home, away, status: feed?.status ?? "SCHEDULED", prob: feed?.prob,
|
||||||
|
homePenalty: feed?.homePenalty, awayPenalty: feed?.awayPenalty,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function saveOverrides(overrides: SimOverrides): void {
|
|||||||
// Plausibles Standardergebnis aus Polymarket-3-Wege-Wahrscheinlichkeiten.
|
// Plausibles Standardergebnis aus Polymarket-3-Wege-Wahrscheinlichkeiten.
|
||||||
//
|
//
|
||||||
// Schwellen (zentral):
|
// Schwellen (zentral):
|
||||||
// Draw am höchsten ODER max(home,away) < 0.40 → 0:0 (Gruppe) / 1:0 Heim (K.o.)
|
// Draw am höchsten ODER max(home,away) < 0.40 → 0:0 (Gruppe) / Favorit 1:0 (K.o.)
|
||||||
// Favorit 0.40–0.60 → 1:0
|
// Favorit 0.40–0.60 → 1:0
|
||||||
// Favorit 0.60–0.78 → 2:0
|
// Favorit 0.60–0.78 → 2:0
|
||||||
// Favorit > 0.78 → 3:0
|
// Favorit > 0.78 → 3:0
|
||||||
@@ -48,7 +48,11 @@ export function defaultScore(match: Match): { homeScore: number; awayScore: numb
|
|||||||
|
|
||||||
if (isDraw || maxFA < 0.40) {
|
if (isDraw || maxFA < 0.40) {
|
||||||
if (isGroup) return { homeScore: 0, awayScore: 0 };
|
if (isGroup) return { homeScore: 0, awayScore: 0 };
|
||||||
return { homeScore: 1, awayScore: 0 }; // K.o.: knapp Heim (kein Remis)
|
// K.o.: kein Remis möglich → der wahrscheinlichere von Heim/Auswärts gewinnt knapp,
|
||||||
|
// Draw wird ignoriert (kein gültiges K.o.-Ergebnis).
|
||||||
|
return prob.home >= prob.away
|
||||||
|
? { homeScore: 1, awayScore: 0 }
|
||||||
|
: { homeScore: 0, awayScore: 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Favorit bestimmen
|
// Favorit bestimmen
|
||||||
|
|||||||
74
lib/stadiums.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Statische Stadion-Daten für WM 2026.
|
||||||
|
export const STADIUMS: Record<string, { name: string; city: string }> = {
|
||||||
|
"1": { name: "Estadio Azteca", city: "Mexico City" },
|
||||||
|
"2": { name: "Estadio Akron", city: "Guadalajara" },
|
||||||
|
"3": { name: "Estadio BBVA", city: "Monterrey" },
|
||||||
|
"4": { name: "AT&T Stadium", city: "Dallas" },
|
||||||
|
"5": { name: "NRG Stadium", city: "Houston" },
|
||||||
|
"6": { name: "GEHA Field at Arrowhead Stadium", city: "Kansas City" },
|
||||||
|
"7": { name: "Mercedes-Benz Stadium", city: "Atlanta" },
|
||||||
|
"8": { name: "Hard Rock Stadium", city: "Miami" },
|
||||||
|
"9": { name: "Gillette Stadium", city: "Boston" },
|
||||||
|
"10": { name: "Lincoln Financial Field", city: "Philadelphia" },
|
||||||
|
"11": { name: "MetLife Stadium", city: "New York/New Jersey" },
|
||||||
|
"12": { name: "BMO Field", city: "Toronto" },
|
||||||
|
"13": { name: "BC Place", city: "Vancouver" },
|
||||||
|
"14": { name: "Lumen Field", city: "Seattle" },
|
||||||
|
"15": { name: "Levi's Stadium", city: "San Francisco Bay Area" },
|
||||||
|
"16": { name: "SoFi Stadium", city: "Los Angeles" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// K.o.-Spielnummer → ISO-8601 UTC-Anstoßzeit (FIFA-Spielplan, statisch).
|
||||||
|
export const MATCH_DATES: Record<number, string> = {
|
||||||
|
// Letzte 32 (28.06. - 03.07.)
|
||||||
|
73: "2026-06-28T19:00:00Z", // 28.06. 14:00
|
||||||
|
74: "2026-06-29T20:30:00Z", // 29.06. 15:30
|
||||||
|
75: "2026-06-30T01:00:00Z", // 29.06. 20:00 (UTC nächster Tag)
|
||||||
|
76: "2026-06-29T17:00:00Z", // 29.06. 12:00
|
||||||
|
77: "2026-06-30T21:00:00Z", // 30.06. 16:00
|
||||||
|
78: "2026-06-30T17:00:00Z", // 30.06. 12:00
|
||||||
|
79: "2026-07-01T01:00:00Z", // 30.06. 20:00 (UTC nächster Tag)
|
||||||
|
80: "2026-07-01T16:00:00Z", // 01.07. 11:00
|
||||||
|
81: "2026-07-02T00:00:00Z", // 01.07. 19:00 (UTC nächster Tag)
|
||||||
|
82: "2026-07-01T20:00:00Z", // 01.07. 15:00
|
||||||
|
83: "2026-07-02T23:00:00Z", // 02.07. 18:00
|
||||||
|
84: "2026-07-02T19:00:00Z", // 02.07. 14:00
|
||||||
|
85: "2026-07-03T03:00:00Z", // 02.07. 22:00 (UTC nächster Tag)
|
||||||
|
86: "2026-07-03T22:00:00Z", // 03.07. 17:00
|
||||||
|
87: "2026-07-04T01:30:00Z", // 03.07. 20:30 (UTC nächster Tag)
|
||||||
|
88: "2026-07-03T18:00:00Z", // 03.07. 13:00
|
||||||
|
|
||||||
|
// Achtelfinale (04.07. - 07.07.)
|
||||||
|
89: "2026-07-04T21:00:00Z", // 04.07. 16:00
|
||||||
|
90: "2026-07-04T17:00:00Z", // 04.07. 12:00
|
||||||
|
91: "2026-07-05T20:00:00Z", // 05.07. 15:00
|
||||||
|
92: "2026-07-06T00:00:00Z", // 05.07. 19:00 (UTC nächster Tag)
|
||||||
|
93: "2026-07-06T19:00:00Z", // 06.07. 14:00
|
||||||
|
94: "2026-07-07T00:00:00Z", // 06.07. 19:00 (UTC nächster Tag)
|
||||||
|
95: "2026-07-07T16:00:00Z", // 07.07. 11:00
|
||||||
|
96: "2026-07-07T20:00:00Z", // 07.07. 15:00
|
||||||
|
|
||||||
|
// Viertelfinale (09.07. - 11.07.)
|
||||||
|
97: "2026-07-09T20:00:00Z", // 09.07. 15:00
|
||||||
|
98: "2026-07-10T19:00:00Z", // 10.07. 14:00
|
||||||
|
99: "2026-07-11T21:00:00Z", // 11.07. 16:00
|
||||||
|
100: "2026-07-12T01:00:00Z",// 11.07. 20:00 (UTC nächster Tag)
|
||||||
|
|
||||||
|
// Halbfinale (14.07. - 15.07.)
|
||||||
|
101: "2026-07-14T19:00:00Z",// 14.07. 14:00
|
||||||
|
102: "2026-07-15T19:00:00Z",// 15.07. 14:00
|
||||||
|
|
||||||
|
// Spiel um Platz 3 (18.07.)
|
||||||
|
103: "2026-07-18T21:00:00Z",// 18.07. 16:00
|
||||||
|
|
||||||
|
// Finale (19.07.)
|
||||||
|
104: "2026-07-19T19:00:00Z",// 19.07. 14:00
|
||||||
|
};
|
||||||
|
|
||||||
|
// K.o.-Spielnummer → stadium_id (FIFA-Quelle, statisch).
|
||||||
|
export const MATCH_STADIUMS: Record<number, string> = {
|
||||||
|
73: "16", 74: "9", 75: "3", 76: "5", 77: "11", 78: "4", 79: "1", 80: "7",
|
||||||
|
81: "15", 82: "14", 83: "12", 84: "16", 85: "13", 86: "8", 87: "6", 88: "4",
|
||||||
|
89: "10", 90: "5", 91: "11", 92: "1", 93: "4", 94: "14", 95: "7", 96: "13",
|
||||||
|
97: "9", 98: "16", 99: "8", 100: "6", 101: "4", 102: "7", 103: "8", 104: "11",
|
||||||
|
};
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// Zentrale Lokalisierungstabelle für Teamnamen (TLA → Deutsch / Englisch).
|
// Zentrale Lokalisierungstabelle für Teamnamen (TLA → Deutsch / Englisch).
|
||||||
// Schlüssel = FIFA-3-Buchstaben-Code (uppercase), wie er von football-data.org
|
// Schlüssel = App-3-Buchstaben-Code (uppercase), gemappt von FIFA-Abbreviation.
|
||||||
// im Feld `tla` geliefert wird.
|
|
||||||
//
|
//
|
||||||
// Erweiterung auf weitere Sprachen: einfach pro Sprache ein Feld ergänzen.
|
// Erweiterung auf weitere Sprachen: einfach pro Sprache ein Feld ergänzen.
|
||||||
|
|
||||||
@@ -18,6 +17,7 @@ export const TEAM_LOCALIZATION: Record<string, { de: string; en: string }> = {
|
|||||||
COD: { de: "DR Kongo", en: "Congo DR" },
|
COD: { de: "DR Kongo", en: "Congo DR" },
|
||||||
COL: { de: "Kolumbien", en: "Colombia" },
|
COL: { de: "Kolumbien", en: "Colombia" },
|
||||||
CPV: { de: "Kap Verde", en: "Cape Verde" },
|
CPV: { de: "Kap Verde", en: "Cape Verde" },
|
||||||
|
CUW: { de: "Curaçao", en: "Curaçao" },
|
||||||
CZE: { de: "Tschechien", en: "Czech Republic" },
|
CZE: { de: "Tschechien", en: "Czech Republic" },
|
||||||
ECU: { de: "Ecuador", en: "Ecuador" },
|
ECU: { de: "Ecuador", en: "Ecuador" },
|
||||||
EGY: { de: "Ägypten", en: "Egypt" },
|
EGY: { de: "Ägypten", en: "Egypt" },
|
||||||
|
|||||||
252
lib/third-place-security.ts
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
import { GroupId, GROUP_IDS, Match, Team } from "./types";
|
||||||
|
import { computeGroupTables, computeThirdPlaceTable } from "./standings";
|
||||||
|
import { resolveAnnexC, qualifiedThirdGroups } from "./bracket";
|
||||||
|
|
||||||
|
// Repräsentative Ergebnis-Varianten je Restspiel (decken alle Punktkombinationen ab).
|
||||||
|
const OUTCOMES: Array<[number, number]> = [
|
||||||
|
[1, 0], // Heimsieg
|
||||||
|
[0, 1], // Auswärtssieg
|
||||||
|
[0, 0], // Unentschieden
|
||||||
|
];
|
||||||
|
|
||||||
|
interface ThirdInfo {
|
||||||
|
teamId: string;
|
||||||
|
points: number;
|
||||||
|
goalsFor: number;
|
||||||
|
goalsAgainst: number;
|
||||||
|
goalDiff: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupThirdState {
|
||||||
|
finished: boolean;
|
||||||
|
third: ThirdInfo | null;
|
||||||
|
minPoints: number;
|
||||||
|
maxPoints: number;
|
||||||
|
possibleTeamIds: Set<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openMatches(group: GroupId, matches: Match[]): Match[] {
|
||||||
|
return matches.filter(
|
||||||
|
(m) => m.group === group && m.status !== "FINISHED"
|
||||||
|
&& m.homeTeamId != null && m.awayTeamId != null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enumerateThirdPossibilities(
|
||||||
|
group: GroupId, teams: Team[], matches: Match[],
|
||||||
|
): { minPoints: number; maxPoints: number; teamIds: Set<string> } {
|
||||||
|
const open = openMatches(group, matches);
|
||||||
|
const played = matches.filter(
|
||||||
|
(m) => m.group === group && (m.status === "FINISHED" || m.homeTeamId == null || m.awayTeamId == null),
|
||||||
|
);
|
||||||
|
|
||||||
|
let minP = Infinity, maxP = -Infinity;
|
||||||
|
const teamIds = new Set<string>();
|
||||||
|
|
||||||
|
if (open.length === 0) {
|
||||||
|
const table = computeGroupTables(teams, matches).find((t) => t.group === group);
|
||||||
|
const third = table?.rows.find((r) => r.rank === 3);
|
||||||
|
if (third) { minP = maxP = third.points; teamIds.add(third.teamId); }
|
||||||
|
return { minPoints: minP, maxPoints: maxP, teamIds };
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalCombos = Math.pow(OUTCOMES.length, open.length);
|
||||||
|
if (totalCombos > 500) return { minPoints: 0, maxPoints: 9, teamIds };
|
||||||
|
|
||||||
|
for (let combo = 0; combo < totalCombos; combo++) {
|
||||||
|
let c = combo;
|
||||||
|
const simulated: Match[] = open.map((m) => {
|
||||||
|
const variantIdx = c % OUTCOMES.length;
|
||||||
|
c = Math.floor(c / OUTCOMES.length);
|
||||||
|
const [hg, ag] = OUTCOMES[variantIdx];
|
||||||
|
return { ...m, status: "FINISHED" as const, homeScore: hg, awayScore: ag };
|
||||||
|
});
|
||||||
|
const all = [...played, ...simulated];
|
||||||
|
const table = computeGroupTables(teams, all).find((t) => t.group === group);
|
||||||
|
const third = table?.rows.find((r) => r.rank === 3);
|
||||||
|
if (third) { minP = Math.min(minP, third.points); maxP = Math.max(maxP, third.points); teamIds.add(third.teamId); }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { minPoints: minP === Infinity ? 0 : minP, maxPoints: maxP === -Infinity ? 9 : maxP, teamIds };
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildThirdStates(matches: Match[], teams: Team[]): Map<GroupId, GroupThirdState> {
|
||||||
|
const states = new Map<GroupId, GroupThirdState>();
|
||||||
|
for (const g of GROUP_IDS) {
|
||||||
|
const gm = matches.filter((m) => m.group === g);
|
||||||
|
const allDone = gm.length > 0 && gm.every((m) => m.status === "FINISHED");
|
||||||
|
const table = computeGroupTables(teams, matches).find((t) => t.group === g);
|
||||||
|
const thirdRow = table?.rows.find((r) => r.rank === 3);
|
||||||
|
let third: ThirdInfo | null = null;
|
||||||
|
if (thirdRow) third = { teamId: thirdRow.teamId, points: thirdRow.points, goalsFor: thirdRow.goalsFor, goalsAgainst: thirdRow.goalsAgainst, goalDiff: thirdRow.goalDiff };
|
||||||
|
if (allDone && third) {
|
||||||
|
states.set(g, { finished: true, third, minPoints: third.points, maxPoints: third.points, possibleTeamIds: new Set([third.teamId]) });
|
||||||
|
} else {
|
||||||
|
const { minPoints, maxPoints, teamIds } = enumerateThirdPossibilities(g, teams, matches);
|
||||||
|
states.set(g, { finished: false, third, minPoints, maxPoints, possibleTeamIds: teamIds });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
|
||||||
|
function classifyGroups(states: Map<GroupId, GroupThirdState>): {
|
||||||
|
lockedIn: Set<GroupId>; lockedOut: Set<GroupId>; contested: Set<GroupId>;
|
||||||
|
} {
|
||||||
|
const lockedIn = new Set<GroupId>();
|
||||||
|
const lockedOut = new Set<GroupId>();
|
||||||
|
const contested = new Set<GroupId>();
|
||||||
|
|
||||||
|
for (const g of GROUP_IDS) {
|
||||||
|
const st = states.get(g)!;
|
||||||
|
if (st.finished && !st.third) { lockedOut.add(g); continue; }
|
||||||
|
|
||||||
|
let countCouldBeBetter = 0;
|
||||||
|
for (const other of GROUP_IDS) {
|
||||||
|
if (other === g) continue;
|
||||||
|
const os = states.get(other)!;
|
||||||
|
if (os.maxPoints > st.minPoints) countCouldBeBetter++;
|
||||||
|
else if (os.maxPoints === st.minPoints && !st.finished && os.finished) countCouldBeBetter++;
|
||||||
|
}
|
||||||
|
const alwaysTop8 = countCouldBeBetter <= 7;
|
||||||
|
|
||||||
|
let countDefinitelyBetter = 0;
|
||||||
|
for (const other of GROUP_IDS) {
|
||||||
|
if (other === g) continue;
|
||||||
|
const os = states.get(other)!;
|
||||||
|
if (os.minPoints > st.maxPoints) countDefinitelyBetter++;
|
||||||
|
else if (os.minPoints === st.maxPoints && os.finished && !st.finished) countDefinitelyBetter++;
|
||||||
|
}
|
||||||
|
const neverTop8 = countDefinitelyBetter >= 8;
|
||||||
|
|
||||||
|
if (alwaysTop8) lockedIn.add(g);
|
||||||
|
else if (neverTop8) lockedOut.add(g);
|
||||||
|
else contested.add(g);
|
||||||
|
}
|
||||||
|
return { lockedIn, lockedOut, contested };
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Public API ---
|
||||||
|
|
||||||
|
// Liefert die Team-IDs der Dritten, die mathematisch sicher unter den Top 8
|
||||||
|
// der gruppenübergreifenden Dritten-Tabelle sind. Prüft für jedes Team aus
|
||||||
|
// einer FERTIGEN Gruppe (played === 3), ob es in ALLEN noch möglichen
|
||||||
|
// Restspiel-Konstellationen von maximal 7 anderen Dritten überholt werden kann.
|
||||||
|
export function securelyQualifiedThirdTeams(matches: Match[], teams: Team[]): Set<string> {
|
||||||
|
const states = buildThirdStates(matches, teams);
|
||||||
|
const secureTeams = new Set<string>();
|
||||||
|
|
||||||
|
for (const g of GROUP_IDS) {
|
||||||
|
const st = states.get(g)!;
|
||||||
|
if (!st.finished || !st.third || st.possibleTeamIds.size !== 1) continue;
|
||||||
|
|
||||||
|
const my = st.third;
|
||||||
|
let couldBeBetter = 0;
|
||||||
|
for (const og of GROUP_IDS) {
|
||||||
|
if (og === g) continue;
|
||||||
|
const os = states.get(og)!;
|
||||||
|
if (os.finished && os.third) {
|
||||||
|
if (os.third.points > my.points) couldBeBetter++;
|
||||||
|
else if (os.third.points === my.points && os.third.goalDiff > my.goalDiff) couldBeBetter++;
|
||||||
|
else if (os.third.points === my.points && os.third.goalDiff === my.goalDiff && os.third.goalsFor > my.goalsFor) couldBeBetter++;
|
||||||
|
} else {
|
||||||
|
if (os.maxPoints > my.points) couldBeBetter++;
|
||||||
|
else if (os.maxPoints === my.points && !os.finished) couldBeBetter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (couldBeBetter <= 7) secureTeams.add(my.teamId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return secureTeams;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liefert die Gruppen, deren Dritter mathematisch sicher unter den Top 8 ist.
|
||||||
|
// (Gruppen-Ebene — für Fix-Markierung im Baum, nicht für Team-Häkchen.)
|
||||||
|
export function securelyQualifiedThirdGroups(matches: Match[], teams: Team[]): GroupId[] {
|
||||||
|
const states = buildThirdStates(matches, teams);
|
||||||
|
const { lockedIn } = classifyGroups(states);
|
||||||
|
return [...lockedIn];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüft, ob ein bestimmter Dritten-Slot (Gegner des Siegers von `winnerGroup`)
|
||||||
|
// in ALLEN noch möglichen Konstellationen identisch bleibt.
|
||||||
|
export function thirdSlotIsSecure(winnerGroup: GroupId, matches: Match[], teams: Team[]): boolean {
|
||||||
|
const states = buildThirdStates(matches, teams);
|
||||||
|
const { lockedIn, contested } = classifyGroups(states);
|
||||||
|
|
||||||
|
if (lockedIn.size > 8) {
|
||||||
|
// Alle Gruppen fertig oder zu viele lockedIn → die 8 tatsächlich qualifizierten
|
||||||
|
// Dritten bestimmen (nicht die 12 lockedIn-Gruppen).
|
||||||
|
const tables = computeGroupTables(teams, matches);
|
||||||
|
const thirds = computeThirdPlaceTable(tables);
|
||||||
|
const qGroups = qualifiedThirdGroups(thirds);
|
||||||
|
if (qGroups.length !== 8) return false;
|
||||||
|
const assignment = resolveAnnexC(qGroups);
|
||||||
|
if (!assignment) return false;
|
||||||
|
const ag = assignment[winnerGroup];
|
||||||
|
if (!ag) return false;
|
||||||
|
const ss = states.get(ag);
|
||||||
|
if (!ss) return false;
|
||||||
|
return ss.finished && ss.third != null && ss.possibleTeamIds.size === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockedIn.size === 8) {
|
||||||
|
const assignment = resolveAnnexC([...lockedIn]);
|
||||||
|
if (!assignment) return false;
|
||||||
|
const ag = assignment[winnerGroup];
|
||||||
|
if (!ag) return false;
|
||||||
|
const ss = states.get(ag);
|
||||||
|
if (!ss) return false;
|
||||||
|
const result = ss.finished && ss.third != null && ss.possibleTeamIds.size === 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockedIn.size + contested.size < 8) return false;
|
||||||
|
|
||||||
|
const contestedArr = [...contested];
|
||||||
|
const need = 8 - lockedIn.size;
|
||||||
|
const combos = combinations(contestedArr.length, need);
|
||||||
|
if (combos > 200) return false;
|
||||||
|
|
||||||
|
let stableGroup: GroupId | null = null;
|
||||||
|
for (const indices of enumerateCombinations(contestedArr.length, need)) {
|
||||||
|
const qGroups: GroupId[] = [...lockedIn, ...indices.map((i) => contestedArr[i])];
|
||||||
|
if (qGroups.length !== 8) continue;
|
||||||
|
const assignment = resolveAnnexC(qGroups);
|
||||||
|
if (!assignment) continue;
|
||||||
|
const ag = assignment[winnerGroup];
|
||||||
|
if (!ag) return false;
|
||||||
|
if (stableGroup === null) stableGroup = ag;
|
||||||
|
else if (stableGroup !== ag) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stableGroup === null) return false;
|
||||||
|
const ss = states.get(stableGroup);
|
||||||
|
if (!ss) return false;
|
||||||
|
const result = ss.finished && ss.third != null && ss.possibleTeamIds.size === 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Combinatorics helpers ---
|
||||||
|
|
||||||
|
function combinations(n: number, k: number): number {
|
||||||
|
if (k < 0 || k > n) return 0;
|
||||||
|
if (k === 0 || k === n) return 1;
|
||||||
|
let r = 1;
|
||||||
|
for (let i = 1; i <= k; i++) r = r * (n - i + 1) / i;
|
||||||
|
return Math.round(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
function* enumerateCombinations(n: number, k: number): Generator<number[]> {
|
||||||
|
if (k === 0) { yield []; return; }
|
||||||
|
if (k > n) return;
|
||||||
|
const idx = Array.from({ length: k }, (_, i) => i);
|
||||||
|
while (true) {
|
||||||
|
yield [...idx];
|
||||||
|
let i = k - 1;
|
||||||
|
while (i >= 0 && idx[i] === n - k + i) i--;
|
||||||
|
if (i < 0) break;
|
||||||
|
idx[i]++;
|
||||||
|
for (let j = i + 1; j < k; j++) idx[j] = idx[j - 1] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/types.ts
@@ -1,5 +1,5 @@
|
|||||||
// Datenmodell für die WM-Seite. Bewusst entkoppelt von den Feed-Formaten:
|
// Datenmodell für die WM-Seite. Bewusst entkoppelt von den Feed-Formaten:
|
||||||
// Adapter (siehe lib/feeds.ts) übersetzen football-data.org & Polymarket in diese Typen.
|
// Adapter (siehe lib/feeds.ts) übersetzen FIFA & Polymarket in diese Typen.
|
||||||
|
|
||||||
export type GroupId =
|
export type GroupId =
|
||||||
| "A" | "B" | "C" | "D" | "E" | "F"
|
| "A" | "B" | "C" | "D" | "E" | "F"
|
||||||
@@ -14,12 +14,25 @@ export interface Team {
|
|||||||
name: string; // Originalname aus dem Feed (englisch)
|
name: string; // Originalname aus dem Feed (englisch)
|
||||||
code: string; // 3-Buchstaben-Code, z.B. GER
|
code: string; // 3-Buchstaben-Code, z.B. GER
|
||||||
group: GroupId;
|
group: GroupId;
|
||||||
crest?: string | null; // URL zur Flagge / zum Wappen (football-data: crest)
|
crest?: string | null; // URL zur Flagge / zum Wappen (veraltet)
|
||||||
localisedName: string; // Lokalisierter Anzeigename (z.B. "Deutschland")
|
localisedName: string; // Lokalisierter Anzeigename (z.B. "Deutschland")
|
||||||
|
localisedNames?: { de: string; en: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function teamName(team: Team | undefined, locale: string): string {
|
||||||
|
if (!team) return "—";
|
||||||
|
if (locale === "en") return team.localisedNames?.en ?? team.name ?? "—";
|
||||||
|
return team.localisedNames?.de ?? team.name ?? "—";
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MatchStatus =
|
export type MatchStatus =
|
||||||
| "SCHEDULED" | "LIVE" | "IN_PLAY" | "PAUSED" | "FINISHED";
|
| "SCHEDULED" | "LIVE" | "IN_PLAY" | "PAUSED" | "FINISHED" | "POSTPONED";
|
||||||
|
|
||||||
|
export interface GoalEvent {
|
||||||
|
scorer: string; // Torschützen-Name
|
||||||
|
minute: string; // Spielminute (z.B. "72", "90+1")
|
||||||
|
team: "home" | "away";
|
||||||
|
}
|
||||||
|
|
||||||
export interface Match {
|
export interface Match {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -33,10 +46,16 @@ export interface Match {
|
|||||||
awayTeamId: string | null;
|
awayTeamId: string | null;
|
||||||
homeScore: number | null;
|
homeScore: number | null;
|
||||||
awayScore: number | null;
|
awayScore: number | null;
|
||||||
|
homePenalty?: number | null; // Elfmeterschießen (FIFA-API)
|
||||||
|
awayPenalty?: number | null;
|
||||||
|
winnerTeamId?: string | null; // FIFA-Winner (auch bei Elfmeterschießen)
|
||||||
// Wahrscheinlichkeiten 0..1 (Polymarket), falls vorhanden
|
// Wahrscheinlichkeiten 0..1 (Polymarket), falls vorhanden
|
||||||
prob?: { home: number; draw: number; away: number } | null;
|
prob?: { home: number; draw: number; away: number } | null;
|
||||||
venue?: string | null; // Austragungsort
|
venue?: string | null; // Austragungsort (veraltet)
|
||||||
attendance?: number | null; // Zuschauerzahl, falls verfügbar
|
stadiumName?: string | null; // FIFA-Stadionname
|
||||||
|
stadiumCity?: string | null; // FIFA-Stadt
|
||||||
|
attendance?: number | null; // Zuschauerzahl
|
||||||
|
goals?: GoalEvent[] | null; // Torereignisse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eine berechnete Tabellenzeile innerhalb einer Gruppe.
|
// Eine berechnete Tabellenzeile innerhalb einer Gruppe.
|
||||||
|
|||||||
42
middleware.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import type { NextRequest } from "next/server";
|
||||||
|
|
||||||
|
const SUPPORTED_LOCALES = ["en", "de"] as const;
|
||||||
|
|
||||||
|
function getLocale(request: NextRequest): string {
|
||||||
|
const acceptLang = request.headers.get("accept-language") ?? "";
|
||||||
|
const preferred = acceptLang.split(",")[0]?.trim().slice(0, 2);
|
||||||
|
if (preferred && SUPPORTED_LOCALES.includes(preferred as any)) return preferred;
|
||||||
|
return "en";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function middleware(request: NextRequest) {
|
||||||
|
const { pathname } = request.nextUrl;
|
||||||
|
|
||||||
|
// API routes and static files pass through
|
||||||
|
if (
|
||||||
|
pathname.startsWith("/api/") ||
|
||||||
|
pathname.includes(".") ||
|
||||||
|
pathname.startsWith("/_next")
|
||||||
|
) {
|
||||||
|
return NextResponse.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if pathname already has a supported locale
|
||||||
|
const hasLocale = SUPPORTED_LOCALES.some(
|
||||||
|
(l) => pathname === `/${l}` || pathname.startsWith(`/${l}/`),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hasLocale) {
|
||||||
|
const locale = getLocale(request);
|
||||||
|
const url = request.nextUrl.clone();
|
||||||
|
url.pathname = `/${locale}${pathname === "/" ? "" : pathname}`;
|
||||||
|
return NextResponse.redirect(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
matcher: ["/((?!_next|api|favicon.ico).*)"],
|
||||||
|
};
|
||||||
519
package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
"@types/node": "22.10.7",
|
"@types/node": "22.10.7",
|
||||||
"@types/react": "19.0.7",
|
"@types/react": "19.0.7",
|
||||||
"@types/react-dom": "19.0.3",
|
"@types/react-dom": "19.0.3",
|
||||||
|
"tsx": "^4.22.4",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -29,6 +30,448 @@
|
|||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
|
||||||
|
"cpu": [
|
||||||
|
"ppc64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"aix"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/android-arm": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/android-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/android-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/darwin-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/darwin-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/freebsd-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/freebsd-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-arm": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-ia32": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-loong64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
|
||||||
|
"cpu": [
|
||||||
|
"loong64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-mips64el": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
|
||||||
|
"cpu": [
|
||||||
|
"mips64el"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-ppc64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
|
||||||
|
"cpu": [
|
||||||
|
"ppc64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-riscv64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-s390x": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
|
||||||
|
"cpu": [
|
||||||
|
"s390x"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/netbsd-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"netbsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/netbsd-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"netbsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/openbsd-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openbsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/openbsd-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openbsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/openharmony-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openharmony"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/sunos-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"sunos"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/win32-arm64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/win32-ia32": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/win32-x64": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@img/sharp-darwin-arm64": {
|
"node_modules/@img/sharp-darwin-arm64": {
|
||||||
"version": "0.33.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
|
||||||
@@ -668,6 +1111,63 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/esbuild": {
|
||||||
|
"version": "0.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
||||||
|
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"esbuild": "bin/esbuild"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@esbuild/aix-ppc64": "0.28.1",
|
||||||
|
"@esbuild/android-arm": "0.28.1",
|
||||||
|
"@esbuild/android-arm64": "0.28.1",
|
||||||
|
"@esbuild/android-x64": "0.28.1",
|
||||||
|
"@esbuild/darwin-arm64": "0.28.1",
|
||||||
|
"@esbuild/darwin-x64": "0.28.1",
|
||||||
|
"@esbuild/freebsd-arm64": "0.28.1",
|
||||||
|
"@esbuild/freebsd-x64": "0.28.1",
|
||||||
|
"@esbuild/linux-arm": "0.28.1",
|
||||||
|
"@esbuild/linux-arm64": "0.28.1",
|
||||||
|
"@esbuild/linux-ia32": "0.28.1",
|
||||||
|
"@esbuild/linux-loong64": "0.28.1",
|
||||||
|
"@esbuild/linux-mips64el": "0.28.1",
|
||||||
|
"@esbuild/linux-ppc64": "0.28.1",
|
||||||
|
"@esbuild/linux-riscv64": "0.28.1",
|
||||||
|
"@esbuild/linux-s390x": "0.28.1",
|
||||||
|
"@esbuild/linux-x64": "0.28.1",
|
||||||
|
"@esbuild/netbsd-arm64": "0.28.1",
|
||||||
|
"@esbuild/netbsd-x64": "0.28.1",
|
||||||
|
"@esbuild/openbsd-arm64": "0.28.1",
|
||||||
|
"@esbuild/openbsd-x64": "0.28.1",
|
||||||
|
"@esbuild/openharmony-arm64": "0.28.1",
|
||||||
|
"@esbuild/sunos-x64": "0.28.1",
|
||||||
|
"@esbuild/win32-arm64": "0.28.1",
|
||||||
|
"@esbuild/win32-ia32": "0.28.1",
|
||||||
|
"@esbuild/win32-x64": "0.28.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-arrayish": {
|
"node_modules/is-arrayish": {
|
||||||
"version": "0.3.4",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
|
||||||
@@ -918,6 +1418,25 @@
|
|||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
|
"node_modules/tsx": {
|
||||||
|
"version": "4.22.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz",
|
||||||
|
"integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"esbuild": "~0.28.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"tsx": "dist/cli.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.7.3",
|
"version": "5.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
"react-dom": "19.0.0"
|
"react-dom": "19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "5.7.3",
|
|
||||||
"@types/node": "22.10.7",
|
"@types/node": "22.10.7",
|
||||||
"@types/react": "19.0.7",
|
"@types/react": "19.0.7",
|
||||||
"@types/react-dom": "19.0.3"
|
"@types/react-dom": "19.0.3",
|
||||||
|
"tsx": "^4.22.4",
|
||||||
|
"typescript": "5.7.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
public/crests/1060.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 8"><defs><clipPath id="a"><path d="M0 0h16v8H0z"/></clipPath></defs><g clip-path="url(#a)"><path fill="#002395" d="M0 0h16v8H0z"/><path d="M4.24 0h8v8z" fill="#fecb00"/><g id="c"><path d="M2.353.525L2.8-.85 3.247.525l-1.17-.85h1.446z" fill="#fff" id="b"/><use xlink:href="#b" x="1" y="1"/><use xlink:href="#b" x="2" y="2"/></g><use xlink:href="#c" x="3" y="3"/><use xlink:href="#c" x="6" y="6"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 504 B |
1
public/crests/1836.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600"><path d="M0 0h900v600H0z" fill="#fff"/><path d="M0 300h450v300H0z" fill="#002855"/><path d="M450 0h450v300H450z" fill="#A6192E"/><path d="M675 375l16.84 51.822 54.49.002-44.082 32.03 16.836 51.823L675 478.65l-44.084 32.027 16.836-51.823-44.081-32.03 54.489-.002z" fill="#A6192E" fill-rule="evenodd"/><path d="M225 75l16.84 51.822 54.49.002-44.082 32.03 16.836 51.823L225 178.65l-44.084 32.027 16.836-51.823-44.081-32.03 54.489-.002z" fill="#002855" fill-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 538 B |
24
public/crests/1930.svg
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 510 300">
|
||||||
|
<rect width="510" height="300" fill="#003893"/>
|
||||||
|
<rect width="510" height="75" y="150" fill="#fff"/>
|
||||||
|
<rect width="510" height="25" y="175" fill="#cf2027"/>
|
||||||
|
<g fill="#f7d116" transform="translate(191.25,187.5)">
|
||||||
|
<g id="s2">
|
||||||
|
<g id="s" transform="translate(0,-75)">
|
||||||
|
<g id="c">
|
||||||
|
<path id="t" d="M0,-15V0H7.5" transform="rotate(18,0,-15)"/>
|
||||||
|
<use xlink:href="#t" transform="scale(-1,1)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#c" transform="rotate(72)"/>
|
||||||
|
<use xlink:href="#c" transform="rotate(144)"/>
|
||||||
|
<use xlink:href="#c" transform="rotate(216)"/>
|
||||||
|
<use xlink:href="#c" transform="rotate(288)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#s" y="150"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#s2" transform="rotate(72)"/>
|
||||||
|
<use xlink:href="#s2" transform="rotate(144)"/>
|
||||||
|
<use xlink:href="#s2" transform="rotate(216)"/>
|
||||||
|
<use xlink:href="#s2" transform="rotate(288)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 923 B |
1
public/crests/1934.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600"><path fill="#007fff" d="M0 0h800v600H0z"/><path d="M36 120h84l26-84 26 84h84l-68 52 26 84-68-52-68 52 26-84-68-52zM750 0L0 450v150h50l750-450V0h-50" fill="#f7d618"/><path d="M800 0L0 480v120l800-480V0" fill="#ce1021"/></svg>
|
||||||
|
After Width: | Height: | Size: 286 B |
1
public/crests/1935.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3 2"><path fill="#009e60" d="M0 0h3v2H0z"/><path fill="#fff" d="M0 0h2v2H0z"/><path fill="#f77f00" d="M0 0h1v2H0z"/></svg>
|
||||||
|
After Width: | Height: | Size: 175 B |
1
public/crests/758.svg
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
6
public/crests/759.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5 3">
|
||||||
|
<desc>Flag of Germany</desc>
|
||||||
|
<rect id="black_stripe" width="5" height="3" y="0" x="0" fill="#000"/>
|
||||||
|
<rect id="red_stripe" width="5" height="2" y="1" x="0" fill="#D00"/>
|
||||||
|
<rect id="gold_stripe" width="5" height="1" y="2" x="0" fill="#FFCE00"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 308 B |
581
public/crests/760.svg
Normal file
@@ -0,0 +1,581 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 500">
|
||||||
|
<path fill="#c60b1e" d="M0 0h750v500H0z"/>
|
||||||
|
<path fill="#ffc400" d="M0 125h750v250H0z"/>
|
||||||
|
<path d="M167.99 222.24s-.51 0-.8-.16c-.27-.16-1.12-.96-1.12-.96l-.68-.49-.62-.85s-.73-1.18-.4-2.09c.34-.9.9-1.23 1.42-1.5.5-.26 1.58-.59 1.58-.59s.85-.37 1.13-.42c.28-.06 1.3-.33 1.3-.33s.28-.15.56-.26c.29-.1.68-.1.9-.16.23-.06.8-.24 1.14-.26.52-.02 1.35.1 1.64.1.28 0 1.24.05 1.64.05.39 0 1.8-.1 2.2-.1.4 0 .68-.06 1.13 0 .45.05 1.24.31 1.47.42.23.1 1.58.6 2.1.75.5.16 1.74.37 2.31.64.56.27.9.72 1.19 1.1.28.37.34.78.45 1.05.1.26.11.84 0 1.1-.11.27-.51.82-.51.82l-.62 1.02-.8.64s-.56.54-1 .48c-.46-.05-5.04-.86-7.98-.86-2.94 0-7.63.86-7.63.86" fill="#ad1519"/>
|
||||||
|
<path d="M167.99 222.24s-.51 0-.8-.16c-.27-.16-1.12-.96-1.12-.96l-.68-.49-.62-.85s-.73-1.18-.4-2.09c.34-.9.9-1.23 1.42-1.5.5-.26 1.58-.59 1.58-.59s.85-.37 1.13-.42c.28-.06 1.3-.33 1.3-.33s.28-.15.56-.26c.29-.1.68-.1.9-.16.23-.06.8-.24 1.14-.26.52-.02 1.35.1 1.64.1.28 0 1.24.05 1.64.05.39 0 1.8-.1 2.2-.1.4 0 .68-.06 1.13 0 .45.05 1.24.31 1.47.42.23.1 1.58.6 2.1.75.5.16 1.74.37 2.31.64.56.27.9.72 1.19 1.1.28.37.34.78.45 1.05.1.26.11.84 0 1.1-.11.27-.51.82-.51.82l-.62 1.02-.8.64s-.56.54-1 .48c-.46-.05-5.04-.86-7.98-.86-2.94 0-7.63.86-7.63.86z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".26"/>
|
||||||
|
<path d="M174.28 215.68c0-1.38.62-2.5 1.38-2.5.76 0 1.38 1.12 1.38 2.5s-.62 2.5-1.38 2.5c-.76 0-1.38-1.12-1.38-2.5" fill="#c8b100"/>
|
||||||
|
<path d="M174.28 215.68c0-1.38.62-2.5 1.38-2.5.76 0 1.38 1.12 1.38 2.5s-.62 2.5-1.38 2.5c-.76 0-1.38-1.12-1.38-2.5z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.05 215.68c0-1.27.28-2.3.63-2.3s.64 1.03.64 2.3c0 1.26-.28 2.3-.64 2.3-.35 0-.63-1.04-.63-2.3" fill="#c8b100"/>
|
||||||
|
<path d="M175.05 215.68c0-1.27.28-2.3.63-2.3s.64 1.03.64 2.3c0 1.26-.28 2.3-.64 2.3-.35 0-.63-1.04-.63-2.3z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M174.75 213.04a.9.9 0 0 1 .93-.87c.5 0 .92.4.92.87 0 .49-.41.87-.92.87-.52 0-.93-.38-.93-.87" fill="#c8b100"/>
|
||||||
|
<path d="M176.33 212.74v.58h-1.43v-.58h.47v-1.31h-.62v-.58h.62v-.57h.6v.57h.62v.58h-.62v1.3h.36" fill="#c8b100"/>
|
||||||
|
<path d="M176.33 212.74v.58h-1.43v-.58h.47v-1.31h-.62v-.58h.62v-.57h.6v.57h.62v.58h-.62v1.3h.36" fill="none" stroke="#000" stroke-width=".3"/>
|
||||||
|
<path d="M176.97 212.74v.58h-2.54v-.58h.94v-1.31h-.62v-.58h.62v-.57h.6v.57h.62v.58h-.62v1.3h1" fill="#c8b100"/>
|
||||||
|
<path d="M176.97 212.74v.58h-2.54v-.58h.94v-1.31h-.62v-.58h.62v-.57h.6v.57h.62v.58h-.62v1.3h1" fill="none" stroke="#000" stroke-width=".3"/>
|
||||||
|
<path d="M175.94 212.2c.38.1.66.45.66.84 0 .49-.41.87-.92.87-.52 0-.93-.38-.93-.87 0-.4.3-.75.69-.84" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.68 222.08h-4.8l-.12-1.18-.23-1.23-.24-1.53c-1.32-1.75-2.54-2.9-2.95-2.65.1-.32.22-.56.47-.71 1.18-.7 3.6.98 5.44 3.74.16.25.32.5.46.75h3.97c.14-.25.3-.5.46-.75 1.83-2.76 4.26-4.44 5.43-3.74.26.15.37.39.47.71-.4-.24-1.62.9-2.95 2.65l-.24 1.53-.23 1.23-.1 1.18h-4.84" fill="#c8b100"/>
|
||||||
|
<path d="M175.68 222.08h-4.8l-.12-1.18-.23-1.23-.24-1.53c-1.32-1.75-2.54-2.9-2.95-2.65.1-.32.22-.56.47-.71 1.18-.7 3.6.98 5.44 3.74.16.25.32.5.46.75h3.97c.14-.25.3-.5.46-.75 1.83-2.76 4.26-4.44 5.43-3.74.26.15.37.39.47.71-.4-.24-1.62.9-2.95 2.65l-.24 1.53-.23 1.23-.1 1.18h-4.84z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M167.55 215.44c.9-.53 3.02 1.15 4.73 3.74m11.55-3.74c-.9-.53-3.01 1.15-4.73 3.74" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M168.58 224.25c-.2-.57-.58-1.08-.58-1.08a28.7 28.7 0 0 1 7.67-.94c3.01 0 5.75.37 7.69.94l-.52.91c-.17.3-.39.81-.38.81a23.8 23.8 0 0 0-6.8-.82c-2.79 0-5.46.35-6.86.86.02 0-.1-.32-.23-.68" fill="#c8b100"/>
|
||||||
|
<path d="M168.58 224.25c-.2-.57-.58-1.08-.58-1.08a28.7 28.7 0 0 1 7.67-.94c3.01 0 5.75.37 7.69.94l-.52.91c-.17.3-.39.81-.38.81a23.8 23.8 0 0 0-6.8-.82c-2.79 0-5.46.35-6.86.86.02 0-.1-.32-.23-.68" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.67 226.73c2.43 0 5.11-.38 6.1-.63.66-.2 1.05-.5.98-.84-.04-.16-.18-.3-.37-.38-1.46-.47-4.07-.8-6.7-.8-2.65 0-5.28.33-6.73.8-.19.08-.33.22-.36.38-.08.35.31.65.97.84.99.25 3.68.62 6.11.63" fill="#c8b100"/>
|
||||||
|
<path d="M175.67 226.73c2.43 0 5.11-.38 6.1-.63.66-.2 1.05-.5.98-.84-.04-.16-.18-.3-.37-.38-1.46-.47-4.07-.8-6.7-.8-2.65 0-5.28.33-6.73.8-.19.08-.33.22-.36.38-.08.35.31.65.97.84.99.25 3.68.62 6.11.63z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M183.48 222.08l-.6-.53s-.56.34-1.27.24c-.7-.11-.93-.97-.93-.97s-.8.67-1.44.62a1.7 1.7 0 0 1-1.07-.62s-.7.5-1.33.46c-.62-.06-1.21-.83-1.21-.83s-.63.8-1.25.86c-.62.05-1.13-.54-1.13-.54s-.28.59-1.07.72c-.8.13-1.47-.62-1.47-.62s-.45.73-.99.92c-.53.18-1.24-.27-1.24-.27l-.2.43c-.09.16-.31.19-.31.19l.18.47c1.93-.56 4.56-.9 7.53-.9 2.97 0 5.67.34 7.61.9l.2-.53" fill="#c8b100"/>
|
||||||
|
<path d="M183.48 222.08l-.6-.53s-.56.34-1.27.24c-.7-.11-.93-.97-.93-.97s-.8.67-1.44.62a1.7 1.7 0 0 1-1.07-.62s-.7.5-1.33.46c-.62-.06-1.21-.83-1.21-.83s-.63.8-1.25.86c-.62.05-1.13-.54-1.13-.54s-.28.59-1.07.72c-.8.13-1.47-.62-1.47-.62s-.45.73-.99.92c-.53.18-1.24-.27-1.24-.27l-.2.43c-.09.16-.31.19-.31.19l.18.47c1.93-.56 4.56-.9 7.53-.9 2.97 0 5.67.34 7.61.9l.2-.53z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.69 219.5l.28.04a1.09 1.09 0 0 0 1.06 1.43c.5 0 .91-.3 1.06-.73.01.01.1-.38.15-.38.03 0 .03.41.05.4.07.53.55.9 1.1.9.62 0 1.1-.47 1.1-1.06v-.12l.35-.35.2.44a.9.9 0 0 0-.11.46c0 .56.47 1 1.06 1 .37 0 .7-.17.88-.44l.23-.29v.35c0 .35.15.66.49.72 0 0 .38.03.9-.38.52-.41.81-.75.81-.75l.03.42s-.5.84-.97 1.1c-.25.15-.64.3-.95.25-.32-.04-.55-.3-.67-.6-.23.13-.5.21-.8.21-.63 0-1.2-.35-1.42-.86a1.62 1.62 0 0 1-2.42-.08 1.63 1.63 0 0 1-2.43-.26 1.62 1.62 0 0 1-2.42.26 1.63 1.63 0 0 1-2.42.08c-.22.5-.79.86-1.42.86-.29 0-.56-.08-.8-.22-.11.3-.34.56-.67.61-.3.06-.69-.1-.94-.25-.47-.26-1.02-1.1-1.02-1.1l.07-.42s.3.34.8.75c.53.41.92.38.92.38.34-.06.49-.37.49-.72v-.35l.22.29c.19.27.51.45.88.45.59 0 1.06-.45 1.06-1.01a.94.94 0 0 0-.1-.46l.2-.44.34.35-.01.12c0 .59.5 1.06 1.11 1.06.55 0 1.03-.37 1.1-.9.02.01.02-.4.05-.4.05 0 .14.4.16.38.14.42.56.73 1.06.73a1.09 1.09 0 0 0 1.06-1.43l.29-.05" fill="#c8b100"/>
|
||||||
|
<path d="M175.69 219.5l.28.04a1.09 1.09 0 0 0 1.06 1.43c.5 0 .91-.3 1.06-.73.01.01.1-.38.15-.38.03 0 .03.41.05.4.07.53.55.9 1.1.9.62 0 1.1-.47 1.1-1.06v-.12l.35-.35.2.44a.9.9 0 0 0-.11.46c0 .56.47 1 1.06 1 .37 0 .7-.17.88-.44l.23-.29v.35c0 .35.15.66.49.72 0 0 .38.03.9-.38.52-.41.81-.75.81-.75l.03.42s-.5.84-.97 1.1c-.25.15-.64.3-.95.25-.32-.04-.55-.3-.67-.6-.23.13-.5.21-.8.21-.63 0-1.2-.35-1.42-.86a1.62 1.62 0 0 1-2.42-.08 1.63 1.63 0 0 1-2.43-.26 1.62 1.62 0 0 1-2.42.26 1.63 1.63 0 0 1-2.42.08c-.22.5-.79.86-1.42.86-.29 0-.56-.08-.8-.22-.11.3-.34.56-.67.61-.3.06-.69-.1-.94-.25-.47-.26-1.02-1.1-1.02-1.1l.07-.42s.3.34.8.75c.53.41.92.38.92.38.34-.06.49-.37.49-.72v-.35l.22.29c.19.27.51.45.88.45.59 0 1.06-.45 1.06-1.01a.94.94 0 0 0-.1-.46l.2-.44.34.35-.01.12c0 .59.5 1.06 1.11 1.06.55 0 1.03-.37 1.1-.9.02.01.02-.4.05-.4.05 0 .14.4.16.38.14.42.56.73 1.06.73a1.09 1.09 0 0 0 1.06-1.43l.29-.05z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.67 222.23c-3.01 0-5.72.37-7.67.94-.13.04-.29-.06-.33-.17-.04-.13.05-.28.18-.32 1.95-.6 4.73-.97 7.82-.98 3.09 0 5.88.38 7.83.98.13.04.22.2.18.32-.04.11-.2.21-.33.17a28.45 28.45 0 0 0-7.68-.94" fill="#c8b100"/>
|
||||||
|
<path d="M175.67 222.23c-3.01 0-5.72.37-7.67.94-.13.04-.29-.06-.33-.17-.04-.13.05-.28.18-.32 1.95-.6 4.73-.97 7.82-.98 3.09 0 5.88.38 7.83.98.13.04.22.2.18.32-.04.11-.2.21-.33.17a28.45 28.45 0 0 0-7.68-.94z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".26"/>
|
||||||
|
<path d="M172.75 223.3c0-.22.2-.4.44-.4s.44.18.44.4c0 .23-.2.41-.44.41s-.44-.18-.44-.4" fill="#fff"/>
|
||||||
|
<path d="M172.75 223.3c0-.22.2-.4.44-.4s.44.18.44.4c0 .23-.2.41-.44.41s-.44-.18-.44-.4z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.7 223.48h-.96c-.18 0-.33-.14-.33-.31 0-.17.14-.3.32-.3h1.96c.19 0 .33.13.33.3 0 .17-.15.31-.33.31h-.98" fill="#ad1519"/>
|
||||||
|
<path d="M175.7 223.48h-.96c-.18 0-.33-.14-.33-.31 0-.17.14-.3.32-.3h1.96c.19 0 .33.13.33.3 0 .17-.15.31-.33.31h-.98" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M170.85 223.81l-.7.1c-.17.03-.34-.08-.37-.25a.3.3 0 0 1 .27-.35l.7-.1.71-.11c.18-.02.34.09.37.25.02.17-.1.33-.27.35l-.71.11" fill="#058e6e"/>
|
||||||
|
<path d="M170.85 223.81l-.7.1c-.17.03-.34-.08-.37-.25a.3.3 0 0 1 .27-.35l.7-.1.71-.11c.18-.02.34.09.37.25.02.17-.1.33-.27.35l-.71.11" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M168.05 224.3l.3-.5.66.13-.38.56-.58-.19" fill="#ad1519"/>
|
||||||
|
<path d="M168.05 224.3l.3-.5.66.13-.38.56-.58-.19" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M177.72 223.3c0-.22.2-.4.44-.4s.43.18.43.4c0 .23-.2.41-.43.41-.25 0-.44-.18-.44-.4" fill="#fff"/>
|
||||||
|
<path d="M177.72 223.3c0-.22.2-.4.44-.4s.43.18.43.4c0 .23-.2.41-.43.41-.25 0-.44-.18-.44-.4z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M180.5 223.81l.7.1c.17.03.34-.08.37-.25a.3.3 0 0 0-.27-.35l-.7-.1-.71-.11c-.18-.02-.34.09-.37.25-.03.17.1.33.27.35l.7.11" fill="#058e6e"/>
|
||||||
|
<path d="M180.5 223.81l.7.1c.17.03.34-.08.37-.25a.3.3 0 0 0-.27-.35l-.7-.1-.71-.11c-.18-.02-.34.09-.37.25-.03.17.1.33.27.35l.7.11" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M183.24 224.33l-.25-.53-.67.06.32.59.6-.12" fill="#ad1519"/>
|
||||||
|
<path d="M183.24 224.33l-.25-.53-.67.06.32.59.6-.12" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.66 226.16c-2.43 0-4.63-.22-6.3-.65 1.67-.43 3.87-.7 6.3-.7 2.44 0 4.65.27 6.33.7-1.68.44-3.9.65-6.33.65" fill="#ad1519"/>
|
||||||
|
<path d="M175.66 226.16c-2.43 0-4.63-.22-6.3-.65 1.67-.43 3.87-.7 6.3-.7 2.44 0 4.65.27 6.33.7-1.68.44-3.9.65-6.33.65z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".26"/>
|
||||||
|
<path d="M183.34 220.88c.06-.18 0-.37-.13-.41-.14-.04-.3.08-.37.26-.06.19 0 .38.13.42.14.04.3-.08.37-.27" fill="#c8b100"/>
|
||||||
|
<path d="M183.34 220.88c.06-.18 0-.37-.13-.41-.14-.04-.3.08-.37.26-.06.19 0 .38.13.42.14.04.3-.08.37-.27z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M178.5 219.95c.02-.2-.08-.37-.22-.39-.14-.02-.28.13-.3.33-.02.2.07.37.21.38.14.02.28-.13.3-.32" fill="#c8b100"/>
|
||||||
|
<path d="M178.5 219.95c.02-.2-.08-.37-.22-.39-.14-.02-.28.13-.3.33-.02.2.07.37.21.38.14.02.28-.13.3-.32z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M172.87 219.95c-.03-.2.07-.37.21-.39.14-.02.28.13.3.33.03.2-.07.37-.21.38-.14.02-.28-.13-.3-.32" fill="#c8b100"/>
|
||||||
|
<path d="M172.87 219.95c-.03-.2.07-.37.21-.39.14-.02.28.13.3.33.03.2-.07.37-.21.38-.14.02-.28-.13-.3-.32z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M168.02 220.88c-.06-.18 0-.37.13-.41.14-.04.3.08.37.26.06.19 0 .38-.14.42-.13.04-.3-.08-.36-.27" fill="#c8b100"/>
|
||||||
|
<path d="M168.02 220.88c-.06-.18 0-.37.13-.41.14-.04.3.08.37.26.06.19 0 .38-.14.42-.13.04-.3-.08-.36-.27z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.66 217.15l-.85.52.63 1.38.22.14.22-.14.64-1.38-.86-.52" fill="#c8b100"/>
|
||||||
|
<path d="M175.66 217.15l-.85.52.63 1.38.22.14.22-.14.64-1.38-.86-.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M173.78 219.24l.4.57 1.34-.42.14-.18-.15-.2-1.33-.39-.4.62" fill="#c8b100"/>
|
||||||
|
<path d="M173.78 219.24l.4.57 1.34-.42.14-.18-.15-.2-1.33-.39-.4.62" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M177.55 219.24l-.39.57-1.34-.42-.14-.18.14-.2 1.34-.39.4.62" fill="#c8b100"/>
|
||||||
|
<path d="M177.55 219.24l-.39.57-1.34-.42-.14-.18.14-.2 1.34-.39.4.62" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M170.08 217.76l-.67.64.86 1.14.23.09.17-.18.3-1.37-.89-.32" fill="#c8b100"/>
|
||||||
|
<path d="M170.08 217.76l-.67.64.86 1.14.23.09.17-.18.3-1.37-.89-.32" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M168.67 220.04l.5.48 1.23-.66.1-.21-.18-.16-1.4-.13-.25.68" fill="#c8b100"/>
|
||||||
|
<path d="M168.67 220.04l.5.48 1.23-.66.1-.21-.18-.16-1.4-.13-.25.68" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M172.36 219.3l-.26.63-1.4-.13-.18-.16.1-.21 1.22-.65.52.52" fill="#c8b100"/>
|
||||||
|
<path d="M172.36 219.3l-.26.63-1.4-.13-.18-.16.1-.21 1.22-.65.52.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M167.32 220.22l-.11.66-1.4.15-.21-.12.05-.23 1.05-.87.62.41" fill="#c8b100"/>
|
||||||
|
<path d="M167.32 220.22l-.11.66-1.4.15-.21-.12.05-.23 1.05-.87.62.41" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M170.02 219.65c0-.26.22-.47.5-.47.26 0 .48.21.48.47 0 .25-.22.46-.49.46a.48.48 0 0 1-.49-.46" fill="#c8b100"/>
|
||||||
|
<path d="M170.02 219.65c0-.26.22-.47.5-.47.26 0 .48.21.48.47 0 .25-.22.46-.49.46a.48.48 0 0 1-.49-.46z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M181.27 217.76l.67.64-.86 1.14-.23.09-.16-.18-.3-1.37.88-.32" fill="#c8b100"/>
|
||||||
|
<path d="M181.27 217.76l.67.64-.86 1.14-.23.09-.16-.18-.3-1.37.88-.32" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M182.68 220.04l-.5.48-1.23-.66-.1-.21.19-.16 1.4-.13.24.68" fill="#c8b100"/>
|
||||||
|
<path d="M182.68 220.04l-.5.48-1.23-.66-.1-.21.19-.16 1.4-.13.24.68" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M179 219.3l.25.63 1.4-.13.18-.16-.1-.21-1.22-.65-.52.52" fill="#c8b100"/>
|
||||||
|
<path d="M179 219.3l.25.63 1.4-.13.18-.16-.1-.21-1.22-.65-.52.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M183.84 220.22l.11.66 1.4.15.21-.12-.05-.23-1.05-.87-.62.41" fill="#c8b100"/>
|
||||||
|
<path d="M183.84 220.22l.11.66 1.4.15.21-.12-.05-.23-1.05-.87-.62.41" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M175.18 219.2c0-.25.22-.46.5-.46.26 0 .48.2.48.47 0 .25-.22.46-.49.46s-.49-.2-.49-.46" fill="#c8b100"/>
|
||||||
|
<path d="M175.18 219.2c0-.25.22-.46.5-.46.26 0 .48.2.48.47 0 .25-.22.46-.49.46s-.49-.2-.49-.46z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M180.36 219.65c0-.26.22-.47.49-.47s.49.21.49.47c0 .25-.22.46-.5.46a.48.48 0 0 1-.48-.46" fill="#c8b100"/>
|
||||||
|
<path d="M180.36 219.65c0-.26.22-.47.49-.47s.49.21.49.47c0 .25-.22.46-.5.46a.48.48 0 0 1-.48-.46z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M165.43 221c-.01 0-.38-.49-.66-.73-.2-.18-.67-.33-.67-.33 0-.09.28-.28.58-.28.18 0 .35.07.45.2l.04-.2s.24.05.36.32c.1.29.04.72.04.72s-.05.2-.14.3" fill="#c8b100"/>
|
||||||
|
<path d="M165.43 221c-.01 0-.38-.49-.66-.73-.2-.18-.67-.33-.67-.33 0-.09.28-.28.58-.28.18 0 .35.07.45.2l.04-.2s.24.05.36.32c.1.29.04.72.04.72s-.05.2-.14.3z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M165.45 220.75c.12-.12.36-.1.53.06.18.15.24.38.12.5-.12.13-.36.1-.53-.06-.18-.15-.24-.38-.12-.5" fill="#c8b100"/>
|
||||||
|
<path d="M165.45 220.75c.12-.12.36-.1.53.06.18.15.24.38.12.5-.12.13-.36.1-.53-.06-.18-.15-.24-.38-.12-.5z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M185.73 221c.01 0 .38-.49.66-.73.19-.18.67-.33.67-.33 0-.09-.28-.28-.58-.28a.58.58 0 0 0-.45.2l-.04-.2s-.24.05-.36.32c-.1.29-.03.72-.03.72s.04.2.13.3" fill="#c8b100"/>
|
||||||
|
<path d="M185.73 221c.01 0 .38-.49.66-.73.19-.18.67-.33.67-.33 0-.09-.28-.28-.58-.28a.58.58 0 0 0-.45.2l-.04-.2s-.24.05-.36.32c-.1.29-.03.72-.03.72s.04.2.13.3z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M185.74 220.75c-.11-.12-.35-.1-.53.06-.18.15-.24.38-.12.5.12.13.36.1.54-.06.18-.15.22-.38.11-.5" fill="#c8b100"/>
|
||||||
|
<path d="M185.74 220.75c-.11-.12-.35-.1-.53.06-.18.15-.24.38-.12.5.12.13.36.1.54-.06.18-.15.22-.38.11-.5z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M164.58 232.37h22.29v-5.84h-22.29v5.84z" fill="#c8b100"/>
|
||||||
|
<path d="M164.58 232.37h22.29v-5.84h-22.29v5.84z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M166.92 236.26a.97.97 0 0 1 .41-.07h16.7c.16 0 .31.03.44.08a1.4 1.4 0 0 1-.98-1.32c0-.6.45-1.14 1.03-1.33-.14.04-.33.08-.49.08h-16.7c-.17 0-.33-.01-.47-.06l.1.02c.59.18.93.71.93 1.3 0 .55-.38 1.12-.97 1.3" fill="#c8b100"/>
|
||||||
|
<path d="M166.92 236.26a.97.97 0 0 1 .41-.07h16.7c.16 0 .31.03.44.08a1.4 1.4 0 0 1-.98-1.32c0-.6.45-1.14 1.03-1.33-.14.04-.33.08-.49.08h-16.7c-.17 0-.33-.01-.47-.06l.1.02c.59.18.93.71.93 1.3 0 .55-.38 1.12-.97 1.3z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M167.33 236.2h16.7c.56 0 1.01.34 1.01.77 0 .44-.45.79-1.02.79h-16.69c-.56 0-1.02-.35-1.02-.79 0-.43.46-.78 1.02-.78" fill="#c8b100"/>
|
||||||
|
<path d="M167.33 236.2h16.7c.56 0 1.01.34 1.01.77 0 .44-.45.79-1.02.79h-16.69c-.56 0-1.02-.35-1.02-.79 0-.43.46-.78 1.02-.78z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M167.33 232.37h16.7c.56 0 1.03.3 1.03.66 0 .37-.47.67-1.03.67h-16.7c-.56 0-1.02-.3-1.02-.67 0-.36.46-.66 1.02-.66" fill="#c8b100"/>
|
||||||
|
<path d="M167.33 232.37h16.7c.56 0 1.03.3 1.03.66 0 .37-.47.67-1.03.67h-16.7c-.56 0-1.02-.3-1.02-.67 0-.36.46-.66 1.02-.66z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M191.28 330.68a8.48 8.48 0 0 1-3.93-.87 8.7 8.7 0 0 0-3.86-.82c-1.5 0-2.9.32-3.9.83-1.02.53-2.41.86-3.93.86a8.48 8.48 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8a8.5 8.5 0 0 0-3.85.82 8.64 8.64 0 0 1-3.95.88v2.41c1.53 0 2.94-.35 3.95-.88 1-.52 2.34-.82 3.86-.82 1.45 0 2.79.3 3.79.8 1 .54 2.39.9 3.93.9 1.52 0 2.91-.33 3.92-.86 1-.52 2.4-.84 3.9-.84s2.87.32 3.87.84a8.4 8.4 0 0 0 3.91.86l.02-2.41" fill="#005bbf"/>
|
||||||
|
<path d="M191.28 330.68a8.48 8.48 0 0 1-3.93-.87 8.7 8.7 0 0 0-3.86-.82c-1.5 0-2.9.32-3.9.83-1.02.53-2.41.86-3.93.86a8.48 8.48 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8a8.5 8.5 0 0 0-3.85.82 8.64 8.64 0 0 1-3.95.88v2.41c1.53 0 2.94-.35 3.95-.88 1-.52 2.34-.82 3.86-.82 1.45 0 2.79.3 3.79.8 1 .54 2.39.9 3.93.9 1.52 0 2.91-.33 3.92-.86 1-.52 2.4-.84 3.9-.84s2.87.32 3.87.84a8.4 8.4 0 0 0 3.91.86l.02-2.41z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M191.28 333.09a8.5 8.5 0 0 1-3.93-.86c-1-.52-2.36-.84-3.86-.84s-2.9.32-3.9.84c-1.02.53-2.41.86-3.93.86a8.52 8.52 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8-1.5 0-2.85.3-3.85.82a8.69 8.69 0 0 1-3.95.88v2.4a8.7 8.7 0 0 0 3.95-.87c1-.52 2.34-.82 3.86-.82 1.45 0 2.79.3 3.79.8 1 .54 2.39.9 3.93.9a8.7 8.7 0 0 0 3.92-.86c1-.52 2.4-.84 3.9-.84s2.87.32 3.87.83c1.02.54 2.37.87 3.91.87l.02-2.41" fill="#ccc"/>
|
||||||
|
<path d="M191.28 333.09a8.5 8.5 0 0 1-3.93-.86c-1-.52-2.36-.84-3.86-.84s-2.9.32-3.9.84c-1.02.53-2.41.86-3.93.86a8.52 8.52 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8-1.5 0-2.85.3-3.85.82a8.69 8.69 0 0 1-3.95.88v2.4a8.7 8.7 0 0 0 3.95-.87c1-.52 2.34-.82 3.86-.82 1.45 0 2.79.3 3.79.8 1 .54 2.39.9 3.93.9a8.7 8.7 0 0 0 3.92-.86c1-.52 2.4-.84 3.9-.84s2.87.32 3.87.83c1.02.54 2.37.87 3.91.87l.02-2.41" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M191.28 335.5a8.52 8.52 0 0 1-3.93-.87c-1-.5-2.36-.83-3.86-.83s-2.9.32-3.9.84c-1.02.53-2.41.86-3.93.86a8.52 8.52 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8-1.5 0-2.85.3-3.85.82a8.7 8.7 0 0 1-3.95.88v2.4c1.53 0 2.94-.34 3.95-.88 1-.51 2.34-.8 3.86-.8 1.45 0 2.79.3 3.79.79 1 .54 2.39.9 3.93.9 1.52 0 2.91-.33 3.92-.86 1-.52 2.4-.83 3.9-.83s2.87.3 3.87.82c1.02.55 2.37.86 3.91.86l.02-2.4" fill="#005bbf"/>
|
||||||
|
<path d="M191.28 335.5a8.52 8.52 0 0 1-3.93-.87c-1-.5-2.36-.83-3.86-.83s-2.9.32-3.9.84c-1.02.53-2.41.86-3.93.86a8.52 8.52 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8-1.5 0-2.85.3-3.85.82a8.7 8.7 0 0 1-3.95.88v2.4c1.53 0 2.94-.34 3.95-.88 1-.51 2.34-.8 3.86-.8 1.45 0 2.79.3 3.79.79 1 .54 2.39.9 3.93.9 1.52 0 2.91-.33 3.92-.86 1-.52 2.4-.83 3.9-.83s2.87.3 3.87.82c1.02.55 2.37.86 3.91.86l.02-2.4" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M191.26 340.32c-1.54 0-2.9-.33-3.9-.87a8.7 8.7 0 0 0-3.87-.82c-1.5 0-2.9.31-3.9.83-1.02.52-2.41.86-3.93.86a8.48 8.48 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8-1.5 0-2.85.3-3.85.82a8.64 8.64 0 0 1-3.95.88v-2.4c1.53 0 2.94-.36 3.95-.9 1-.51 2.34-.8 3.86-.8 1.45 0 2.79.3 3.79.79 1 .54 2.39.9 3.93.9 1.52 0 2.91-.33 3.92-.86 1-.52 2.4-.83 3.9-.83s2.87.3 3.87.82c1.02.55 2.39.86 3.93.86l-.02 2.42" fill="#ccc"/>
|
||||||
|
<path d="M191.26 340.32c-1.54 0-2.9-.33-3.9-.87a8.7 8.7 0 0 0-3.87-.82c-1.5 0-2.9.31-3.9.83-1.02.52-2.41.86-3.93.86a8.48 8.48 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8-1.5 0-2.85.3-3.85.82a8.64 8.64 0 0 1-3.95.88v-2.4c1.53 0 2.94-.36 3.95-.9 1-.51 2.34-.8 3.86-.8 1.45 0 2.79.3 3.79.79 1 .54 2.39.9 3.93.9 1.52 0 2.91-.33 3.92-.86 1-.52 2.4-.83 3.9-.83s2.87.3 3.87.82c1.02.55 2.39.86 3.93.86l-.02 2.42" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M191.26 342.73c-1.54 0-2.9-.33-3.9-.86a8.6 8.6 0 0 0-3.87-.84c-1.5 0-2.9.32-3.9.84-1.02.52-2.41.86-3.93.86a8.52 8.52 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8a8.5 8.5 0 0 0-3.85.82 8.69 8.69 0 0 1-3.95.88v-2.4c1.53 0 2.94-.36 3.95-.9 1-.51 2.34-.8 3.86-.8 1.45 0 2.79.3 3.79.79 1 .53 2.39.9 3.93.9a8.7 8.7 0 0 0 3.92-.86c1-.52 2.4-.83 3.9-.83s2.87.31 3.87.82a8.5 8.5 0 0 0 3.93.87l-.02 2.4" fill="#005bbf"/>
|
||||||
|
<path d="M191.26 342.73c-1.54 0-2.9-.33-3.9-.86a8.6 8.6 0 0 0-3.87-.84c-1.5 0-2.9.32-3.9.84-1.02.52-2.41.86-3.93.86a8.52 8.52 0 0 1-3.93-.9c-1-.5-2.33-.8-3.8-.8a8.5 8.5 0 0 0-3.85.82 8.69 8.69 0 0 1-3.95.88v-2.4c1.53 0 2.94-.36 3.95-.9 1-.51 2.34-.8 3.86-.8 1.45 0 2.79.3 3.79.79 1 .53 2.39.9 3.93.9a8.7 8.7 0 0 0 3.92-.86c1-.52 2.4-.83 3.9-.83s2.87.31 3.87.82a8.5 8.5 0 0 0 3.93.87l-.02 2.4z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M166.92 320.78c.05.2.13.4.13.62 0 1.46-1.27 2.63-2.81 2.63h22.94c-1.55 0-2.81-1.17-2.81-2.63 0-.21.04-.41.1-.62-.14.05-.3.06-.45.06h-16.69c-.13 0-.29-.02-.41-.06" fill="#c8b100"/>
|
||||||
|
<path d="M166.92 320.78c.05.2.13.4.13.62 0 1.46-1.27 2.63-2.81 2.63h22.94c-1.55 0-2.81-1.17-2.81-2.63 0-.21.04-.41.1-.62-.14.05-.3.06-.45.06h-16.69c-.13 0-.29-.02-.41-.06z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M167.33 319.27h16.7c.56 0 1.01.35 1.01.78 0 .44-.45.79-1.02.79h-16.69c-.56 0-1.02-.35-1.02-.79 0-.43.46-.78 1.02-.78" fill="#c8b100"/>
|
||||||
|
<path d="M167.33 319.27h16.7c.56 0 1.01.35 1.01.78 0 .44-.45.79-1.02.79h-16.69c-.56 0-1.02-.35-1.02-.79 0-.43.46-.78 1.02-.78z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M164.27 329.86h22.88v-5.83h-22.88v5.83z" fill="#c8b100"/>
|
||||||
|
<path d="M164.27 329.86h22.88v-5.83h-22.88v5.83z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M162.48 298.62c-2.26 1.3-3.8 2.64-3.55 3.31.12.62.84 1.07 1.87 1.75 1.62 1.13 2.6 3.14 1.83 4.07a5.76 5.76 0 0 0-.15-9.13" fill="#ad1519"/>
|
||||||
|
<path d="M162.48 298.62c-2.26 1.3-3.8 2.64-3.55 3.31.12.62.84 1.07 1.87 1.75 1.62 1.13 2.6 3.14 1.83 4.07a5.76 5.76 0 0 0-.15-9.13z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M167.55 318.32h16.25V238.7h-16.25v79.63z" fill="#ccc"/>
|
||||||
|
<path d="M179.13 238.8v79.46m1.83-79.46v79.46M167.55 318.32h16.25V238.7h-16.25v79.63z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M200.4 268.47c-3.54-1.46-9.57-2.55-16.5-2.78a50.2 50.2 0 0 0-7.78.7c-9.72 1.63-17.13 5.5-16.54 8.67l.05.26s-3.64-8.2-3.7-8.52c-.65-3.51 7.56-7.82 18.35-9.62 3.39-.57 6.7-.79 9.56-.76 6.9 0 12.9.89 16.52 2.23l.04 9.82" fill="#ad1519"/>
|
||||||
|
<path d="M200.4 268.47c-3.54-1.46-9.57-2.55-16.5-2.78a50.2 50.2 0 0 0-7.78.7c-9.72 1.63-17.13 5.5-16.54 8.67l.05.26s-3.64-8.2-3.7-8.52c-.65-3.51 7.56-7.82 18.35-9.62 3.39-.57 6.7-.79 9.56-.76 6.9 0 12.9.89 16.52 2.23l.04 9.82" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M167.52 278.47c-4.5-.32-7.59-1.53-7.94-3.41-.28-1.5 1.25-3.17 3.97-4.68 1.21.14 2.58.3 4 .3l-.03 7.79" fill="#ad1519"/>
|
||||||
|
<path d="M167.52 278.47c-4.5-.32-7.59-1.53-7.94-3.41-.28-1.5 1.25-3.17 3.97-4.68 1.21.14 2.58.3 4 .3l-.03 7.79" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M183.83 272.38c2.82.43 4.93 1.13 5.98 1.99l.1.17c.5 1.03-1.97 3.22-6.1 5.67l.02-7.83" fill="#ad1519"/>
|
||||||
|
<path d="M183.83 272.38c2.82.43 4.93 1.13 5.98 1.99l.1.17c.5 1.03-1.97 3.22-6.1 5.67l.02-7.83" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M157.42 293.83c-.43-1.28 3.97-3.86 10.18-6.14 2.84-1.01 5.18-2.07 8.09-3.35 8.63-3.82 15-8.2 14.22-9.8l-.09-.16c.46.38 1.18 8.24 1.18 8.24.78 1.46-5.05 5.78-13 9.58-2.54 1.22-7.9 3.2-10.44 4.1-4.54 1.56-9.04 4.53-8.63 5.63l-1.5-8.1" fill="#ad1519"/>
|
||||||
|
<path d="M157.42 293.83c-.43-1.28 3.97-3.86 10.18-6.14 2.84-1.01 5.18-2.07 8.09-3.35 8.63-3.82 15-8.2 14.22-9.8l-.09-.16c.46.38 1.18 8.24 1.18 8.24.78 1.46-5.05 5.78-13 9.58-2.54 1.22-7.9 3.2-10.44 4.1-4.54 1.56-9.04 4.53-8.63 5.63l-1.5-8.1z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M166.43 264.65c1.98-.72 3.28-1.58 2.65-3.14-.4-1-1.43-1.19-2.97-.63l-2.72.99 2.45 6.03c.27-.12.54-.24.81-.34.28-.1.57-.18.85-.26l-1.07-2.64zm-1.19-2.9l.69-.26c.57-.2 1.22.1 1.5.8.21.53.16 1.13-.5 1.55-.21.13-.46.23-.7.33l-.99-2.43M172.78 259.22c-.29.07-.57.16-.86.22l-.88.13 1.41 6.27 4.38-.88c-.05-.13-.12-.26-.14-.38-.03-.14-.03-.28-.04-.41-.77.22-1.6.46-2.61.66l-1.26-5.61M181.56 264.63c.82-2.28 1.82-4.46 2.81-6.67a5.51 5.51 0 0 1-1.08.07c-.53 1.6-1.18 3.2-1.87 4.8-.82-1.51-1.73-2.99-2.43-4.51-.34.04-.69.1-1.03.12-.34.02-.7.01-1.04.02 1.26 2.06 2.48 4.1 3.64 6.23l.5-.08c.16 0 .33 0 .5.02M190.72 259.8c.15-.3.3-.6.48-.89a3.6 3.6 0 0 0-1.81-.63c-1.79-.18-2.81.61-2.93 1.7-.26 2.25 3.3 2.06 3.14 3.56-.07.64-.75.9-1.48.83-.81-.08-1.4-.53-1.51-1.19l-.22-.02c-.12.4-.3.77-.48 1.15.53.34 1.2.53 1.85.6 1.83.18 3.22-.55 3.35-1.75.23-2.15-3.37-2.27-3.23-3.54.06-.53.47-.88 1.4-.79.67.07 1.08.43 1.26.95l.18.02" fill="#c8b100"/>
|
||||||
|
<path d="M324.85 220.42s-.74.78-1.28.89c-.53.1-1.21-.49-1.21-.49s-.48.5-1.08.64c-.59.14-1.41-.67-1.41-.67s-.57.8-1.07 1c-.51.18-1.13-.24-1.13-.24s-.23.4-.65.61c-.18.09-.48-.05-.48-.05l-.6-.38-.68-.72-.62-.24s-.28-.91-.3-1.07l-.1-.57c-.12-.64.88-1.4 2.31-1.72.82-.2 1.54-.18 2.06-.02.57-.48 1.78-.82 3.2-.82 1.29 0 2.42.27 3.04.7.61-.43 1.74-.7 3.03-.7 1.42 0 2.62.34 3.2.82a4.1 4.1 0 0 1 2.06.02c1.42.32 2.43 1.08 2.3 1.72l-.08.57c-.03.16-.31 1.07-.31 1.07l-.63.24-.68.72-.59.38s-.3.14-.47.05a1.76 1.76 0 0 1-.66-.61s-.62.42-1.13.24c-.5-.2-1.07-1-1.07-1s-.82.8-1.42.67c-.59-.13-1.07-.64-1.07-.64s-.68.6-1.21.49c-.54-.11-1.27-.89-1.27-.89" fill="#ad1519"/>
|
||||||
|
<path d="M324.85 220.42s-.74.78-1.28.89c-.53.1-1.21-.49-1.21-.49s-.48.5-1.08.64c-.59.14-1.41-.67-1.41-.67s-.57.8-1.07 1c-.51.18-1.13-.24-1.13-.24s-.23.4-.65.61c-.18.09-.48-.05-.48-.05l-.6-.38-.68-.72-.62-.24s-.28-.91-.3-1.07l-.1-.57c-.12-.64.88-1.4 2.31-1.72.82-.2 1.54-.18 2.06-.02.57-.48 1.78-.82 3.2-.82 1.29 0 2.42.27 3.04.7.61-.43 1.74-.7 3.03-.7 1.42 0 2.62.34 3.2.82a4.1 4.1 0 0 1 2.06.02c1.42.32 2.43 1.08 2.3 1.72l-.08.57c-.03.16-.31 1.07-.31 1.07l-.63.24-.68.72-.59.38s-.3.14-.47.05a1.76 1.76 0 0 1-.66-.61s-.62.42-1.13.24c-.5-.2-1.07-1-1.07-1s-.82.8-1.42.67c-.59-.13-1.07-.64-1.07-.64s-.68.6-1.21.49c-.54-.11-1.27-.89-1.27-.89z" fill="none" stroke="#000" stroke-width=".27"/>
|
||||||
|
<path d="M323.45 216.2c0-1.09.61-1.96 1.37-1.96.76 0 1.38.87 1.38 1.96 0 1.08-.62 1.96-1.38 1.96-.76 0-1.37-.88-1.37-1.96" fill="#c8b100"/>
|
||||||
|
<path d="M323.45 216.2c0-1.09.61-1.96 1.37-1.96.76 0 1.38.87 1.38 1.96 0 1.08-.62 1.96-1.38 1.96-.76 0-1.37-.88-1.37-1.96z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M324.22 216.2c0-1 .28-1.8.63-1.8s.63.8.63 1.8-.28 1.8-.63 1.8-.63-.8-.63-1.8" fill="#c8b100"/>
|
||||||
|
<path d="M324.22 216.2c0-1 .28-1.8.63-1.8s.63.8.63 1.8-.28 1.8-.63 1.8-.63-.8-.63-1.8z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M317.75 224.25a4.72 4.72 0 0 0-.58-1.08c1.94-.57 4.65-.93 7.67-.94 3.01 0 5.74.37 7.69.94l-.52.91c-.17.3-.4.81-.38.81a23.8 23.8 0 0 0-6.8-.82c-2.79 0-5.47.35-6.86.86.02 0-.1-.32-.24-.68h.02" fill="#c8b100"/>
|
||||||
|
<path d="M317.75 224.25a4.72 4.72 0 0 0-.58-1.08c1.94-.57 4.65-.93 7.67-.94 3.01 0 5.74.37 7.69.94l-.52.91c-.17.3-.4.81-.38.81a23.8 23.8 0 0 0-6.8-.82c-2.79 0-5.47.35-6.86.86.02 0-.1-.32-.24-.68h.02" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M324.84 226.73c2.43 0 5.1-.38 6.1-.63.66-.2 1.05-.5.97-.84-.03-.16-.17-.3-.37-.38-1.45-.47-4.06-.8-6.7-.8-2.64 0-5.27.33-6.72.8-.19.08-.33.22-.37.38-.07.35.32.65.98.84.99.25 3.68.62 6.1.63" fill="#c8b100"/>
|
||||||
|
<path d="M324.84 226.73c2.43 0 5.1-.38 6.1-.63.66-.2 1.05-.5.97-.84-.03-.16-.17-.3-.37-.38-1.45-.47-4.06-.8-6.7-.8-2.64 0-5.27.33-6.72.8-.19.08-.33.22-.37.38-.07.35.32.65.98.84.99.25 3.68.62 6.1.63z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M330.74 217.07c0-.23.2-.42.44-.42.26 0 .46.19.46.42 0 .24-.2.43-.45.43a.44.44 0 0 1-.45-.43" fill="#fff"/>
|
||||||
|
<path d="M330.74 217.07c0-.23.2-.42.44-.42.26 0 .46.19.46.42 0 .24-.2.43-.45.43a.44.44 0 0 1-.45-.43zM330.48 215.58c0-.24.2-.43.45-.43s.45.19.45.43c0 .23-.2.42-.45.42a.44.44 0 0 1-.45-.42zm-1.13-.94c0-.24.2-.43.45-.43s.45.2.45.43c0 .24-.2.43-.45.43a.44.44 0 0 1-.45-.43zm-1.42-.45c0-.24.2-.44.46-.44.25 0 .45.2.45.44 0 .23-.2.42-.45.42s-.46-.2-.46-.42zm-1.44.05c0-.24.2-.43.45-.43.26 0 .46.19.46.43 0 .23-.2.42-.45.42a.44.44 0 0 1-.45-.42z" fill="none" stroke="#000" stroke-width=".21"/>
|
||||||
|
<path d="M335.2 219.99a2.85 2.85 0 0 0-2.6-3.96c-.5 0-.97.13-1.38.37" fill="none" stroke="#000" stroke-linecap="round" stroke-width=".26"/>
|
||||||
|
<path d="M330.17 217.96c.15-.26.25-.57.25-.87 0-1.15-1.18-2.08-2.64-2.08-.62 0-1.2.17-1.64.45" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M335.6 218.68c0-.24.2-.43.45-.43s.45.2.45.43c0 .24-.2.43-.45.43s-.45-.2-.45-.43zm-.18-1.58c0-.24.21-.42.46-.42s.45.18.45.42-.2.43-.45.43-.45-.2-.45-.43zm-1-1.2c0-.24.2-.43.44-.43.25 0 .45.2.45.43 0 .23-.2.42-.45.42a.44.44 0 0 1-.45-.42zm-1.37-.65c0-.23.2-.42.46-.42.25 0 .45.19.45.42 0 .24-.2.44-.45.44a.44.44 0 0 1-.46-.44zm-1.44.06c0-.24.2-.43.45-.43s.46.2.46.43c0 .23-.2.43-.46.43-.25 0-.45-.2-.45-.43z" fill="none" stroke="#000" stroke-width=".21"/>
|
||||||
|
<path d="M332.65 222.08l-.6-.53s-.56.34-1.27.24c-.7-.11-.93-.97-.93-.97s-.8.67-1.44.62a1.7 1.7 0 0 1-1.07-.62s-.71.5-1.33.46c-.62-.06-1.22-.83-1.22-.83s-.62.8-1.24.86c-.62.05-1.13-.54-1.13-.54s-.29.59-1.08.72-1.47-.62-1.47-.62-.44.73-.98.92c-.54.18-1.24-.27-1.24-.27l-.2.43c-.09.16-.31.19-.31.19l.17.47c1.94-.56 4.57-.9 7.54-.9 2.97 0 5.67.34 7.6.9l.2-.53" fill="#c8b100"/>
|
||||||
|
<path d="M332.65 222.08l-.6-.53s-.56.34-1.27.24c-.7-.11-.93-.97-.93-.97s-.8.67-1.44.62a1.7 1.7 0 0 1-1.07-.62s-.71.5-1.33.46c-.62-.06-1.22-.83-1.22-.83s-.62.8-1.24.86c-.62.05-1.13-.54-1.13-.54s-.29.59-1.08.72-1.47-.62-1.47-.62-.44.73-.98.92c-.54.18-1.24-.27-1.24-.27l-.2.43c-.09.16-.31.19-.31.19l.17.47c1.94-.56 4.57-.9 7.54-.9 2.97 0 5.67.34 7.6.9l.2-.53z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M317.98 217.07c0-.23.2-.42.45-.42s.45.19.45.42c0 .24-.2.43-.45.43s-.45-.19-.45-.43" fill="#fff"/>
|
||||||
|
<path d="M317.98 217.07c0-.23.2-.42.45-.42s.45.19.45.42c0 .24-.2.43-.45.43s-.45-.19-.45-.43zM318.23 215.58c0-.24.2-.43.45-.43s.45.19.45.43c0 .23-.2.42-.44.42-.26 0-.46-.19-.46-.42zm1.13-.94c0-.24.2-.43.45-.43s.46.2.46.43c0 .24-.2.43-.46.43a.44.44 0 0 1-.45-.43zm1.41-.45c0-.24.2-.44.46-.44.25 0 .45.2.45.44 0 .23-.2.42-.45.42s-.46-.2-.46-.42zm1.45.05c0-.24.2-.43.45-.43s.45.19.45.43c0 .23-.2.42-.45.42a.44.44 0 0 1-.45-.42z" fill="none" stroke="#000" stroke-width=".21"/>
|
||||||
|
<path d="M314.4 219.99a2.85 2.85 0 0 1 2.6-3.96c.51 0 .98.13 1.4.37" fill="none" stroke="#000" stroke-linecap="round" stroke-width=".26"/>
|
||||||
|
<path d="M319.48 217.93a1.75 1.75 0 0 1-.29-.84c0-1.15 1.19-2.08 2.64-2.08.62 0 1.2.17 1.65.45" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M313.11 218.68c0-.24.2-.43.46-.43.24 0 .45.2.45.43 0 .24-.2.43-.45.43s-.46-.2-.46-.43zm.17-1.58c0-.24.2-.42.46-.42.25 0 .45.18.45.42s-.2.43-.45.43-.46-.2-.46-.43zm1.02-1.2c0-.24.2-.43.46-.43.24 0 .45.2.45.43 0 .23-.2.42-.45.42a.44.44 0 0 1-.46-.42zm1.36-.65c0-.23.2-.42.45-.42s.45.19.45.42c0 .24-.2.44-.45.44a.44.44 0 0 1-.45-.44zm1.44.06c0-.24.2-.43.45-.43s.45.2.45.43c0 .23-.2.43-.45.43s-.45-.2-.45-.43z" fill="none" stroke="#000" stroke-width=".21"/>
|
||||||
|
<path d="M324.85 219.5l.28.04c-.04.12-.05.24-.05.38 0 .58.5 1.05 1.12 1.05.5 0 .91-.3 1.05-.73.02.01.11-.38.16-.38.04 0 .03.41.04.4.07.53.56.9 1.1.9.62 0 1.12-.47 1.12-1.06l-.01-.12.35-.35.19.44c-.08.14-.1.3-.1.46 0 .56.47 1 1.06 1 .37 0 .7-.17.88-.44l.23-.29v.35c0 .35.14.66.48.72 0 0 .4.03.91-.38.53-.41.81-.75.81-.75l.03.42s-.51.84-.97 1.1c-.25.15-.64.3-.95.25-.33-.04-.55-.3-.68-.6-.23.13-.5.21-.8.21-.62 0-1.19-.35-1.41-.86a1.63 1.63 0 0 1-2.42-.08 1.63 1.63 0 0 1-2.43-.26 1.62 1.62 0 0 1-2.42.26c-.3.35-.75.58-1.26.58-.47 0-.87-.19-1.16-.5-.22.5-.79.86-1.42.86-.29 0-.56-.08-.8-.22-.11.3-.34.56-.67.61-.3.06-.69-.1-.94-.25-.47-.26-1.02-1.1-1.02-1.1l.07-.42s.28.34.8.75.92.38.92.38c.34-.06.48-.37.48-.72v-.35l.23.29c.19.27.51.45.88.45.6 0 1.07-.45 1.07-1.01a.93.93 0 0 0-.1-.46l.18-.44.35.35-.01.12c0 .59.5 1.06 1.1 1.06.56 0 1.04-.37 1.11-.9.02.01.01-.4.05-.4.05 0 .14.4.15.38.15.42.57.73 1.06.73a1.09 1.09 0 0 0 1.07-1.43l.29-.05" fill="#c8b100"/>
|
||||||
|
<path d="M324.85 219.5l.28.04c-.04.12-.05.24-.05.38 0 .58.5 1.05 1.12 1.05.5 0 .91-.3 1.05-.73.02.01.11-.38.16-.38.04 0 .03.41.04.4.07.53.56.9 1.1.9.62 0 1.12-.47 1.12-1.06l-.01-.12.35-.35.19.44c-.08.14-.1.3-.1.46 0 .56.47 1 1.06 1 .37 0 .7-.17.88-.44l.23-.29v.35c0 .35.14.66.48.72 0 0 .4.03.91-.38.53-.41.81-.75.81-.75l.03.42s-.51.84-.97 1.1c-.25.15-.64.3-.95.25-.33-.04-.55-.3-.68-.6-.23.13-.5.21-.8.21-.62 0-1.19-.35-1.41-.86a1.63 1.63 0 0 1-2.42-.08 1.63 1.63 0 0 1-2.43-.26 1.62 1.62 0 0 1-2.42.26c-.3.35-.75.58-1.26.58-.47 0-.87-.19-1.16-.5-.22.5-.79.86-1.42.86-.29 0-.56-.08-.8-.22-.11.3-.34.56-.67.61-.3.06-.69-.1-.94-.25-.47-.26-1.02-1.1-1.02-1.1l.07-.42s.28.34.8.75.92.38.92.38c.34-.06.48-.37.48-.72v-.35l.23.29c.19.27.51.45.88.45.6 0 1.07-.45 1.07-1.01a.93.93 0 0 0-.1-.46l.18-.44.35.35-.01.12c0 .59.5 1.06 1.1 1.06.56 0 1.04-.37 1.11-.9.02.01.01-.4.05-.4.05 0 .14.4.15.38.15.42.57.73 1.06.73a1.09 1.09 0 0 0 1.07-1.43l.29-.05z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M324.84 222.23c-3.02 0-5.72.37-7.67.94-.13.04-.29-.06-.33-.17-.04-.13.05-.28.18-.32 1.95-.6 4.73-.97 7.82-.98 3.08 0 5.87.38 7.83.98.13.04.22.2.18.32-.04.11-.2.21-.33.17a28.45 28.45 0 0 0-7.68-.94" fill="#c8b100"/>
|
||||||
|
<path d="M324.84 222.23c-3.02 0-5.72.37-7.67.94-.13.04-.29-.06-.33-.17-.04-.13.05-.28.18-.32 1.95-.6 4.73-.97 7.82-.98 3.08 0 5.87.38 7.83.98.13.04.22.2.18.32-.04.11-.2.21-.33.17a28.45 28.45 0 0 0-7.68-.94z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M321.92 223.3c0-.22.2-.4.44-.4s.44.18.44.4c0 .23-.2.41-.44.41s-.44-.18-.44-.4" fill="#fff"/>
|
||||||
|
<path d="M321.92 223.3c0-.22.2-.4.44-.4s.44.18.44.4c0 .23-.2.41-.44.41s-.44-.18-.44-.4z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M324.88 223.48h-.98c-.18 0-.33-.14-.33-.31 0-.17.15-.3.33-.3h1.96c.18 0 .32.13.32.3 0 .17-.14.31-.32.31h-.99" fill="#ad1519"/>
|
||||||
|
<path d="M324.88 223.48h-.98c-.18 0-.33-.14-.33-.31 0-.17.15-.3.33-.3h1.96c.18 0 .32.13.32.3 0 .17-.14.31-.32.31h-.99" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M320.02 223.81l-.7.1a.33.33 0 0 1-.37-.25.3.3 0 0 1 .27-.35l.7-.1.7-.11c.18-.02.35.09.38.25.02.17-.1.33-.27.35l-.71.11" fill="#058e6e"/>
|
||||||
|
<path d="M320.02 223.81l-.7.1a.33.33 0 0 1-.37-.25.3.3 0 0 1 .27-.35l.7-.1.7-.11c.18-.02.35.09.38.25.02.17-.1.33-.27.35l-.71.11" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M317.21 224.3l.31-.5.66.13-.38.56-.59-.19" fill="#ad1519"/>
|
||||||
|
<path d="M317.21 224.3l.31-.5.66.13-.38.56-.59-.19" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M326.89 223.3c0-.22.2-.4.43-.4.25 0 .44.18.44.4 0 .23-.2.41-.44.41s-.43-.18-.43-.4" fill="#fff"/>
|
||||||
|
<path d="M326.89 223.3c0-.22.2-.4.43-.4.25 0 .44.18.44.4 0 .23-.2.41-.44.41s-.43-.18-.43-.4z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M329.66 223.81l.7.1c.18.03.34-.08.37-.25a.3.3 0 0 0-.26-.35l-.7-.1-.71-.11c-.18-.02-.35.09-.38.25-.03.17.1.33.28.35l.7.11" fill="#058e6e"/>
|
||||||
|
<path d="M329.66 223.81l.7.1c.18.03.34-.08.37-.25a.3.3 0 0 0-.26-.35l-.7-.1-.71-.11c-.18-.02-.35.09-.38.25-.03.17.1.33.28.35l.7.11" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M332.4 224.33l-.24-.53-.68.06.33.59.6-.12" fill="#ad1519"/>
|
||||||
|
<path d="M332.4 224.33l-.24-.53-.68.06.33.59.6-.12" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M324.83 226.16c-2.43 0-4.63-.22-6.3-.65 1.67-.43 3.87-.7 6.3-.7 2.44 0 4.65.27 6.32.7-1.67.44-3.88.65-6.32.65" fill="#ad1519"/>
|
||||||
|
<path d="M324.83 226.16c-2.43 0-4.63-.22-6.3-.65 1.67-.43 3.87-.7 6.3-.7 2.44 0 4.65.27 6.32.7-1.67.44-3.88.65-6.32.65z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".26"/>
|
||||||
|
<path d="M332.5 220.88c.07-.18.01-.37-.13-.41-.13-.04-.3.08-.36.26-.06.19 0 .38.13.42.14.04.3-.08.37-.27" fill="#c8b100"/>
|
||||||
|
<path d="M332.5 220.88c.07-.18.01-.37-.13-.41-.13-.04-.3.08-.36.26-.06.19 0 .38.13.42.14.04.3-.08.37-.27z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M327.66 219.95c.03-.2-.07-.37-.21-.39-.14-.02-.28.13-.3.33-.03.2.06.37.2.38.15.02.28-.13.31-.32" fill="#c8b100"/>
|
||||||
|
<path d="M327.66 219.95c.03-.2-.07-.37-.21-.39-.14-.02-.28.13-.3.33-.03.2.06.37.2.38.15.02.28-.13.31-.32z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M322.04 219.95c-.03-.2.06-.37.2-.39.15-.02.28.13.31.33.02.2-.07.37-.2.38-.15.02-.29-.13-.31-.32" fill="#c8b100"/>
|
||||||
|
<path d="M322.04 219.95c-.03-.2.06-.37.2-.39.15-.02.28.13.31.33.02.2-.07.37-.2.38-.15.02-.29-.13-.31-.32z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M317.2 220.88c-.07-.18-.01-.37.12-.41.13-.04.3.08.36.26.07.19.01.38-.12.42-.14.04-.3-.08-.37-.27" fill="#c8b100"/>
|
||||||
|
<path d="M317.2 220.88c-.07-.18-.01-.37.12-.41.13-.04.3.08.36.26.07.19.01.38-.12.42-.14.04-.3-.08-.37-.27z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M324.83 217.15l-.85.52.63 1.38.22.14.22-.14.64-1.38-.86-.52" fill="#c8b100"/>
|
||||||
|
<path d="M324.83 217.15l-.85.52.63 1.38.22.14.22-.14.64-1.38-.86-.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M322.95 219.24l.4.57 1.33-.42.14-.18-.14-.2-1.34-.39-.39.62" fill="#c8b100"/>
|
||||||
|
<path d="M322.95 219.24l.4.57 1.33-.42.14-.18-.14-.2-1.34-.39-.39.62" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M326.72 219.24l-.39.57-1.34-.42-.14-.18.14-.2 1.34-.39.4.62" fill="#c8b100"/>
|
||||||
|
<path d="M326.72 219.24l-.39.57-1.34-.42-.14-.18.14-.2 1.34-.39.4.62" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M319.25 217.76l-.67.64.86 1.14.23.09.17-.18.3-1.37-.89-.32" fill="#c8b100"/>
|
||||||
|
<path d="M319.25 217.76l-.67.64.86 1.14.23.09.17-.18.3-1.37-.89-.32" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M317.84 220.04l.5.48 1.23-.66.09-.21-.18-.16-1.4-.13-.24.68" fill="#c8b100"/>
|
||||||
|
<path d="M317.84 220.04l.5.48 1.23-.66.09-.21-.18-.16-1.4-.13-.24.68" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M321.53 219.3l-.26.63-1.4-.13-.18-.16.1-.21 1.22-.65.52.52" fill="#c8b100"/>
|
||||||
|
<path d="M321.53 219.3l-.26.63-1.4-.13-.18-.16.1-.21 1.22-.65.52.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M316.5 220.22l-.12.66-1.4.15-.22-.12.06-.23 1.05-.87.62.41" fill="#c8b100"/>
|
||||||
|
<path d="M316.5 220.22l-.12.66-1.4.15-.22-.12.06-.23 1.05-.87.62.41" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M319.19 219.65c0-.26.22-.47.49-.47s.49.21.49.47c0 .25-.22.46-.5.46a.48.48 0 0 1-.48-.46" fill="#c8b100"/>
|
||||||
|
<path d="M319.19 219.65c0-.26.22-.47.49-.47s.49.21.49.47c0 .25-.22.46-.5.46a.48.48 0 0 1-.48-.46z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M330.44 217.76l.67.64-.86 1.14-.23.09-.17-.18-.3-1.37.89-.32" fill="#c8b100"/>
|
||||||
|
<path d="M330.44 217.76l.67.64-.86 1.14-.23.09-.17-.18-.3-1.37.89-.32" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M331.85 220.04l-.5.48-1.23-.66-.1-.21.18-.16 1.4-.13.25.68" fill="#c8b100"/>
|
||||||
|
<path d="M331.85 220.04l-.5.48-1.23-.66-.1-.21.18-.16 1.4-.13.25.68" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M328.16 219.3l.26.63 1.4-.13.18-.16-.1-.21-1.22-.65-.52.52" fill="#c8b100"/>
|
||||||
|
<path d="M328.16 219.3l.26.63 1.4-.13.18-.16-.1-.21-1.22-.65-.52.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M333 220.22l.12.66 1.4.15.2-.12-.04-.23-1.05-.87-.62.41" fill="#c8b100"/>
|
||||||
|
<path d="M333 220.22l.12.66 1.4.15.2-.12-.04-.23-1.05-.87-.62.41" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M324.35 219.2c0-.25.22-.46.5-.46.26 0 .48.2.48.47 0 .25-.22.46-.49.46a.48.48 0 0 1-.49-.46" fill="#c8b100"/>
|
||||||
|
<path d="M324.35 219.2c0-.25.22-.46.5-.46.26 0 .48.2.48.47 0 .25-.22.46-.49.46a.48.48 0 0 1-.49-.46z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M329.52 219.65c0-.26.23-.47.5-.47s.5.21.5.47c0 .25-.23.46-.5.46a.48.48 0 0 1-.5-.46" fill="#c8b100"/>
|
||||||
|
<path d="M329.52 219.65c0-.26.23-.47.5-.47s.5.21.5.47c0 .25-.23.46-.5.46a.48.48 0 0 1-.5-.46z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M323.92 213.95a.9.9 0 0 1 .92-.87c.51 0 .93.39.93.87 0 .49-.42.88-.93.88a.9.9 0 0 1-.92-.88" fill="#c8b100"/>
|
||||||
|
<path d="M325.5 213.64v.58h-1.43v-.58h.47v-1.3h-.62v-.59h.62v-.57h.6v.57h.61v.59h-.6v1.3h.34" fill="#c8b100"/>
|
||||||
|
<path d="M325.5 213.64v.58h-1.43v-.58h.47v-1.3h-.62v-.59h.62v-.57h.6v.57h.61v.59h-.6v1.3h.34z" fill="none" stroke="#000" stroke-width=".3"/>
|
||||||
|
<path d="M326.13 213.64v.58h-2.53v-.58h.94v-1.3h-.62v-.59h.62v-.57h.6v.57h.62v.59h-.61v1.3h.98" fill="#c8b100"/>
|
||||||
|
<path d="M325.1 213.12c.39.1.67.44.67.83a.9.9 0 0 1-.93.88.9.9 0 0 1-.92-.88c0-.4.29-.74.68-.84" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M314.6 221c-.01 0-.38-.49-.66-.73-.2-.18-.67-.33-.67-.33 0-.09.28-.28.58-.28.18 0 .35.07.45.2l.03-.2s.25.05.36.32c.11.29.04.72.04.72s-.05.2-.13.3" fill="#c8b100"/>
|
||||||
|
<path d="M314.6 221c-.01 0-.38-.49-.66-.73-.2-.18-.67-.33-.67-.33 0-.09.28-.28.58-.28.18 0 .35.07.45.2l.03-.2s.25.05.36.32c.11.29.04.72.04.72s-.05.2-.13.3z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M314.62 220.75c.11-.12.35-.1.53.06.18.15.23.38.11.5-.11.13-.35.1-.53-.06-.18-.15-.23-.38-.11-.5" fill="#c8b100"/>
|
||||||
|
<path d="M314.62 220.75c.11-.12.35-.1.53.06.18.15.23.38.11.5-.11.13-.35.1-.53-.06-.18-.15-.23-.38-.11-.5z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M334.9 221c.01 0 .38-.49.65-.73.2-.18.68-.33.68-.33 0-.09-.28-.28-.59-.28a.58.58 0 0 0-.44.2l-.04-.2s-.25.05-.36.32c-.1.29-.04.72-.04.72s.05.2.14.3" fill="#c8b100"/>
|
||||||
|
<path d="M334.9 221c.01 0 .38-.49.65-.73.2-.18.68-.33.68-.33 0-.09-.28-.28-.59-.28a.58.58 0 0 0-.44.2l-.04-.2s-.25.05-.36.32c-.1.29-.04.72-.04.72s.05.2.14.3z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M334.91 220.75c-.12-.12-.36-.1-.54.06-.18.15-.23.38-.11.5.11.13.35.1.53-.06.18-.15.24-.38.12-.5" fill="#c8b100"/>
|
||||||
|
<path d="M334.91 220.75c-.12-.12-.36-.1-.54.06-.18.15-.23.38-.11.5.11.13.35.1.53-.06.18-.15.24-.38.12-.5z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M313.71 232.37H336v-5.84H313.7v5.84z" fill="#c8b100"/>
|
||||||
|
<path d="M313.71 232.37H336v-5.84H313.7v5.84z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M333.66 236.26a.98.98 0 0 0-.41-.07h-16.7c-.16 0-.31.03-.45.08.57-.19.98-.7.98-1.32 0-.6-.44-1.14-1.02-1.33.14.04.32.08.49.08h16.7c.17 0 .32-.01.47-.06l-.1.02c-.6.18-.93.71-.93 1.3 0 .55.37 1.12.97 1.3" fill="#c8b100"/>
|
||||||
|
<path d="M333.66 236.26a.98.98 0 0 0-.41-.07h-16.7c-.16 0-.31.03-.45.08.57-.19.98-.7.98-1.32 0-.6-.44-1.14-1.02-1.33.14.04.32.08.49.08h16.7c.17 0 .32-.01.47-.06l-.1.02c-.6.18-.93.71-.93 1.3 0 .55.37 1.12.97 1.3z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M316.56 236.2h16.69c.56 0 1.02.34 1.02.77 0 .44-.46.79-1.02.79h-16.7c-.56 0-1.01-.35-1.01-.79 0-.43.45-.78 1.02-.78" fill="#c8b100"/>
|
||||||
|
<path d="M316.56 236.2h16.69c.56 0 1.02.34 1.02.77 0 .44-.46.79-1.02.79h-16.7c-.56 0-1.01-.35-1.01-.79 0-.43.45-.78 1.02-.78z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M316.55 232.37h16.7c.56 0 1.02.3 1.02.66 0 .37-.46.67-1.02.67h-16.7c-.57 0-1.03-.3-1.03-.67 0-.36.46-.66 1.03-.66" fill="#c8b100"/>
|
||||||
|
<path d="M316.55 232.37h16.7c.56 0 1.02.3 1.02.66 0 .37-.46.67-1.02.67h-16.7c-.57 0-1.03-.3-1.03-.67 0-.36.46-.66 1.03-.66z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M309.3 330.68c1.54 0 2.91-.33 3.93-.87 1-.5 2.36-.82 3.86-.82s2.9.32 3.9.83c1.01.53 2.4.86 3.93.86a8.5 8.5 0 0 0 3.93-.9c1-.5 2.33-.8 3.8-.8a8.5 8.5 0 0 1 3.85.82c1.01.54 2.42.88 3.95.88v2.41a8.67 8.67 0 0 1-3.95-.88c-1-.52-2.34-.82-3.86-.82-1.46 0-2.8.3-3.79.8-1 .54-2.4.9-3.93.9a8.7 8.7 0 0 1-3.92-.86c-1-.52-2.4-.84-3.9-.84s-2.87.32-3.88.84a8.4 8.4 0 0 1-3.9.86l-.02-2.41" fill="#005bbf"/>
|
||||||
|
<path d="M309.3 330.68c1.54 0 2.91-.33 3.93-.87 1-.5 2.36-.82 3.86-.82s2.9.32 3.9.83c1.01.53 2.4.86 3.93.86a8.5 8.5 0 0 0 3.93-.9c1-.5 2.33-.8 3.8-.8a8.5 8.5 0 0 1 3.85.82c1.01.54 2.42.88 3.95.88v2.41a8.67 8.67 0 0 1-3.95-.88c-1-.52-2.34-.82-3.86-.82-1.46 0-2.8.3-3.79.8-1 .54-2.4.9-3.93.9a8.7 8.7 0 0 1-3.92-.86c-1-.52-2.4-.84-3.9-.84s-2.87.32-3.88.84a8.4 8.4 0 0 1-3.9.86l-.02-2.41z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M309.3 333.09a8.5 8.5 0 0 0 3.93-.86c1-.52 2.36-.84 3.86-.84s2.9.32 3.9.84c1.01.53 2.4.86 3.93.86 1.54 0 2.92-.36 3.93-.9 1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v2.4a8.67 8.67 0 0 1-3.95-.87c-1-.52-2.34-.82-3.86-.82-1.46 0-2.8.3-3.79.8-1 .54-2.4.9-3.93.9a8.7 8.7 0 0 1-3.92-.86c-1-.52-2.4-.84-3.9-.84s-2.87.32-3.88.83a8.43 8.43 0 0 1-3.9.87l-.02-2.41" fill="#ccc"/>
|
||||||
|
<path d="M309.3 333.09a8.5 8.5 0 0 0 3.93-.86c1-.52 2.36-.84 3.86-.84s2.9.32 3.9.84c1.01.53 2.4.86 3.93.86 1.54 0 2.92-.36 3.93-.9 1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v2.4a8.67 8.67 0 0 1-3.95-.87c-1-.52-2.34-.82-3.86-.82-1.46 0-2.8.3-3.79.8-1 .54-2.4.9-3.93.9a8.7 8.7 0 0 1-3.92-.86c-1-.52-2.4-.84-3.9-.84s-2.87.32-3.88.83a8.43 8.43 0 0 1-3.9.87l-.02-2.41" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M309.3 335.5c1.54 0 2.91-.33 3.93-.87 1-.5 2.36-.83 3.86-.83s2.9.32 3.9.84c1.01.53 2.4.86 3.93.86 1.54 0 2.92-.36 3.93-.9 1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v2.4a8.63 8.63 0 0 1-3.95-.88c-1-.51-2.34-.8-3.86-.8-1.46 0-2.8.3-3.79.79-1 .54-2.4.9-3.93.9a8.71 8.71 0 0 1-3.92-.86c-1-.52-2.4-.83-3.9-.83s-2.87.3-3.88.82a8.37 8.37 0 0 1-3.9.86l-.02-2.4" fill="#005bbf"/>
|
||||||
|
<path d="M309.3 335.5c1.54 0 2.91-.33 3.93-.87 1-.5 2.36-.83 3.86-.83s2.9.32 3.9.84c1.01.53 2.4.86 3.93.86 1.54 0 2.92-.36 3.93-.9 1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v2.4a8.63 8.63 0 0 1-3.95-.88c-1-.51-2.34-.8-3.86-.8-1.46 0-2.8.3-3.79.79-1 .54-2.4.9-3.93.9a8.71 8.71 0 0 1-3.92-.86c-1-.52-2.4-.83-3.9-.83s-2.87.3-3.88.82a8.37 8.37 0 0 1-3.9.86l-.02-2.4" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M309.32 340.32a8.4 8.4 0 0 0 3.9-.87c1.01-.51 2.37-.82 3.87-.82s2.9.31 3.9.83c1.01.52 2.4.86 3.93.86a8.5 8.5 0 0 0 3.93-.9c1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v-2.4a8.63 8.63 0 0 1-3.95-.9c-1-.51-2.34-.8-3.86-.8-1.46 0-2.8.3-3.79.79-1 .54-2.4.9-3.93.9a8.71 8.71 0 0 1-3.92-.86c-1-.52-2.4-.83-3.9-.83s-2.87.3-3.88.82a8.46 8.46 0 0 1-3.92.86l.02 2.42" fill="#ccc"/>
|
||||||
|
<path d="M309.32 340.32a8.4 8.4 0 0 0 3.9-.87c1.01-.51 2.37-.82 3.87-.82s2.9.31 3.9.83c1.01.52 2.4.86 3.93.86a8.5 8.5 0 0 0 3.93-.9c1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v-2.4a8.63 8.63 0 0 1-3.95-.9c-1-.51-2.34-.8-3.86-.8-1.46 0-2.8.3-3.79.79-1 .54-2.4.9-3.93.9a8.71 8.71 0 0 1-3.92-.86c-1-.52-2.4-.83-3.9-.83s-2.87.3-3.88.82a8.46 8.46 0 0 1-3.92.86l.02 2.42" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M309.32 342.73c1.54 0 2.9-.33 3.9-.86a8.6 8.6 0 0 1 3.87-.84c1.5 0 2.9.32 3.9.84 1.01.52 2.4.86 3.93.86 1.54 0 2.92-.37 3.93-.9 1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v-2.4a8.61 8.61 0 0 1-3.95-.9c-1-.51-2.34-.8-3.86-.8-1.46 0-2.8.3-3.79.79-1 .53-2.4.9-3.93.9a8.7 8.7 0 0 1-3.92-.86c-1-.52-2.4-.83-3.9-.83s-2.87.31-3.88.82a8.5 8.5 0 0 1-3.92.87l.02 2.4" fill="#005bbf"/>
|
||||||
|
<path d="M309.32 342.73c1.54 0 2.9-.33 3.9-.86a8.6 8.6 0 0 1 3.87-.84c1.5 0 2.9.32 3.9.84 1.01.52 2.4.86 3.93.86 1.54 0 2.92-.37 3.93-.9 1-.5 2.33-.8 3.8-.8 1.5 0 2.84.3 3.85.82 1.01.53 2.42.88 3.95.88v-2.4a8.61 8.61 0 0 1-3.95-.9c-1-.51-2.34-.8-3.86-.8-1.46 0-2.8.3-3.79.79-1 .53-2.4.9-3.93.9a8.7 8.7 0 0 1-3.92-.86c-1-.52-2.4-.83-3.9-.83s-2.87.31-3.88.82a8.5 8.5 0 0 1-3.92.87l.02 2.4z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M333.66 320.78c-.06.2-.13.4-.13.62 0 1.46 1.27 2.63 2.8 2.63H313.4c1.55 0 2.8-1.17 2.8-2.63 0-.21-.03-.41-.08-.62.12.05.28.06.44.06h16.69c.13 0 .29-.02.4-.06" fill="#c8b100"/>
|
||||||
|
<path d="M333.66 320.78c-.06.2-.13.4-.13.62 0 1.46 1.27 2.63 2.8 2.63H313.4c1.55 0 2.8-1.17 2.8-2.63 0-.21-.03-.41-.08-.62.12.05.28.06.44.06h16.69c.13 0 .29-.02.4-.06z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M316.56 319.27h16.69c.56 0 1.02.35 1.02.78 0 .44-.46.79-1.02.79h-16.7c-.56 0-1.01-.35-1.01-.79 0-.43.45-.78 1.02-.78" fill="#c8b100"/>
|
||||||
|
<path d="M316.56 319.27h16.69c.56 0 1.02.35 1.02.78 0 .44-.46.79-1.02.79h-16.7c-.56 0-1.01-.35-1.01-.79 0-.43.45-.78 1.02-.78z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M313.43 329.86h22.88v-5.83h-22.88v5.83z" fill="#c8b100"/>
|
||||||
|
<path d="M313.43 329.86h22.88v-5.83h-22.88v5.83z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M338.1 298.62c2.26 1.3 3.8 2.64 3.55 3.31-.12.62-.84 1.07-1.87 1.75-1.62 1.13-2.6 3.14-1.83 4.07a5.76 5.76 0 0 1 .15-9.13" fill="#ad1519"/>
|
||||||
|
<path d="M338.1 298.62c2.26 1.3 3.8 2.64 3.55 3.31-.12.62-.84 1.07-1.87 1.75-1.62 1.13-2.6 3.14-1.83 4.07a5.76 5.76 0 0 1 .15-9.13z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M316.78 318.32h16.25V238.7h-16.25v79.63z" fill="#ccc"/>
|
||||||
|
<path d="M328.57 238.66v79.46m1.82-79.46v79.46M316.78 318.32h16.25V238.7h-16.25v79.63z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M300.17 268.47c3.55-1.46 9.58-2.55 16.5-2.78 2.38.02 5.04.25 7.79.7 9.72 1.63 17.12 5.5 16.54 8.67l-.05.26s3.64-8.2 3.7-8.52c.65-3.51-7.56-7.82-18.35-9.62a55.7 55.7 0 0 0-9.56-.76c-6.9 0-12.9.89-16.52 2.23l-.05 9.82" fill="#ad1519"/>
|
||||||
|
<path d="M300.17 268.47c3.55-1.46 9.58-2.55 16.5-2.78 2.38.02 5.04.25 7.79.7 9.72 1.63 17.12 5.5 16.54 8.67l-.05.26s3.64-8.2 3.7-8.52c.65-3.51-7.56-7.82-18.35-9.62a55.7 55.7 0 0 0-9.56-.76c-6.9 0-12.9.89-16.52 2.23l-.05 9.82" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M333.06 278.47c4.5-.32 7.59-1.53 7.94-3.41.28-1.5-1.25-3.17-3.97-4.68-1.22.14-2.59.3-4 .3l.03 7.79" fill="#ad1519"/>
|
||||||
|
<path d="M333.06 278.47c4.5-.32 7.59-1.53 7.94-3.41.28-1.5-1.25-3.17-3.97-4.68-1.22.14-2.59.3-4 .3l.03 7.79" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M316.75 272.38c-2.82.43-4.93 1.13-5.99 1.99l-.1.17c-.5 1.03 1.98 3.22 6.11 5.67l-.02-7.83" fill="#ad1519"/>
|
||||||
|
<path d="M316.75 272.38c-2.82.43-4.93 1.13-5.99 1.99l-.1.17c-.5 1.03 1.98 3.22 6.11 5.67l-.02-7.83" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M343.15 293.83c.43-1.28-3.96-3.86-10.17-6.14-2.84-1.01-5.19-2.07-8.1-3.35-8.62-3.82-15-8.2-14.2-9.8l.08-.16c-.46.38-1.17 8.24-1.17 8.24-.79 1.46 5.05 5.78 12.98 9.58 2.55 1.22 7.92 3.2 10.45 4.1 4.54 1.56 9.04 4.53 8.63 5.63l1.5-8.1" fill="#ad1519"/>
|
||||||
|
<path d="M343.15 293.83c.43-1.28-3.96-3.86-10.17-6.14-2.84-1.01-5.19-2.07-8.1-3.35-8.62-3.82-15-8.2-14.2-9.8l.08-.16c-.46.38-1.17 8.24-1.17 8.24-.79 1.46 5.05 5.78 12.98 9.58 2.55 1.22 7.92 3.2 10.45 4.1 4.54 1.56 9.04 4.53 8.63 5.63l1.5-8.1z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M310.3 264.98c.62-2.33 1.41-4.58 2.2-6.87a5.52 5.52 0 0 1-1.08.16 54.67 54.67 0 0 1-1.42 4.94c-.95-1.44-2-2.84-2.83-4.3-.34.07-.68.15-1.02.2-.34.05-.7.07-1.04.1 1.45 1.95 2.85 3.9 4.2 5.92.16-.04.32-.1.5-.12.16-.02.33-.02.5-.03M316.49 258.16l-.9.03c-.29 0-.59-.04-.88-.06l-.12 6.41 4.49.08c-.03-.13-.06-.27-.06-.41 0-.13.04-.27.07-.4-.8.05-1.68.1-2.71.08l.1-5.73M323.52 259.21c.72.06 1.41.19 2.1.31-.01-.13-.03-.27-.02-.4 0-.14.06-.27.1-.4l-6.07-.5c.01.13.03.27.02.4-.01.14-.06.27-.1.4a20.1 20.1 0 0 1 2.2.05l-.52 5.77c.3 0 .59 0 .88.03.3.02.6.07.88.11l.53-5.77M326 265.53c.3.05.6.09.89.15.28.06.57.15.85.23l.72-2.94.08.01.5 1.19.9 2.22c.35.06.7.1 1.04.18.36.08.7.18 1.04.28l-.31-.67c-.48-1-1-2-1.41-3.02 1.12.04 1.98-.36 2.2-1.26.15-.62-.1-1.11-.69-1.53-.43-.31-1.27-.48-1.82-.6l-2.44-.53-1.54 6.3m3.14-5.43c.7.16 1.59.27 1.59 1.07 0 .2-.03.35-.06.48-.23.94-.94 1.26-2.13.9l.6-2.45M337.57 267.45c-.05.7-.18 1.38-.31 2.1.3.15.6.28.9.45.3.16.57.34.86.52l.6-7.23a4.03 4.03 0 0 1-.78-.43l-6.38 4.05c.17.08.35.16.51.25l.47.28c.54-.45 1.1-.82 1.74-1.3l2.39 1.31zm-1.8-1.65l2.12-1.37-.25 2.4-1.88-1.03" fill="#c8b100"/>
|
||||||
|
<path d="M225.2 200.45c0-1.14.97-2.06 2.17-2.06 1.19 0 2.16.92 2.16 2.06 0 1.13-.97 2.05-2.16 2.05-1.2 0-2.17-.92-2.17-2.05z" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M249.65 182.72c6.64 0 12.56.99 16.4 2.51 2.21 1 5.17 1.73 8.41 2.17 2.47.33 4.81.4 6.85.24 2.73-.06 6.67.74 10.62 2.48 3.26 1.45 5.99 3.2 7.8 4.91l-1.57 1.4-.45 3.96-4.3 4.92-2.15 1.83-5.09 4.07-2.6.21-.79 2.25-32.91-3.86-33.02 3.86-.8-2.25-2.6-.21-5.08-4.07-2.15-1.83-4.3-4.92-.44-3.96-1.58-1.4a28.79 28.79 0 0 1 7.8-4.91c3.95-1.74 7.9-2.54 10.62-2.48 2.04.15 4.38.09 6.85-.24a31.2 31.2 0 0 0 8.4-2.17c3.86-1.52 9.44-2.5 16.08-2.5z" fill="#ad1519" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M250.15 226.18c-12.26-.02-23.25-1.47-31.09-3.83a1.2 1.2 0 0 1-.84-1.25c0-.52.29-1 .84-1.17 7.84-2.36 18.83-3.81 31.1-3.83 12.26.02 23.23 1.47 31.08 3.83.55.17.84.65.83 1.17a1.2 1.2 0 0 1-.83 1.25c-7.85 2.36-18.82 3.81-31.09 3.83" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.12 224.57c-11.06-.01-21.07-1.3-28.68-3.26 7.61-1.97 17.62-3.17 28.68-3.2 11.07.03 21.13 1.23 28.74 3.2-7.61 1.97-17.67 3.25-28.74 3.26" fill="#ad1519"/>
|
||||||
|
<path d="M250.95 224.64v-6.57" fill="none" stroke="#000" stroke-width=".09"/>
|
||||||
|
<path d="M249.16 224.64v-6.57" fill="none" stroke="#000" stroke-width=".14"/>
|
||||||
|
<path d="M247.48 224.64v-6.57" fill="none" stroke="#000" stroke-width=".18"/>
|
||||||
|
<path d="M245.8 224.64v-6.57" fill="none" stroke="#000" stroke-width=".23"/>
|
||||||
|
<path d="M244.32 224.64v-6.57" fill="none" stroke="#000" stroke-width=".28"/>
|
||||||
|
<path d="M241.48 224.28l-.03-5.97m1.38 6.05v-6.25" fill="none" stroke="#000" stroke-width=".33"/>
|
||||||
|
<path d="M238.87 224.01v-5.5m1.32 5.66l-.04-5.86" fill="none" stroke="#000" stroke-width=".37"/>
|
||||||
|
<path d="M235.35 223.7v-4.84m1.15 4.92v-5.08m1.2 5.24v-5.28" fill="none" stroke="#000" stroke-width=".42"/>
|
||||||
|
<path d="M234.12 223.66v-4.68" fill="none" stroke="#000" stroke-width=".46"/>
|
||||||
|
<path d="M232.97 223.42v-4.36" fill="none" stroke="#000" stroke-width=".51"/>
|
||||||
|
<path d="M231.74 223.3v-4.05" fill="none" stroke="#000" stroke-width=".56"/>
|
||||||
|
<path d="M229.22 222.95l-.04-3.22m1.33 3.38v-3.62" fill="none" stroke="#000" stroke-width=".6"/>
|
||||||
|
<path d="M227.93 222.68v-2.84" fill="none" stroke="#000" stroke-width=".63"/>
|
||||||
|
<path d="M226.74 222.45v-2.36" fill="none" stroke="#000" stroke-width=".68"/>
|
||||||
|
<path d="M225.45 222.13v-1.84" fill="none" stroke="#000" stroke-width=".73"/>
|
||||||
|
<path d="M224.12 221.98v-1.38" fill="none" stroke="#000" stroke-width=".77"/>
|
||||||
|
<path d="M222.72 221.66V221" fill="none" stroke="#000" stroke-width=".91"/>
|
||||||
|
<path d="M258.04 224.28v-6.01m-3.02 6.21l.04-6.37m-2.24 6.45v-6.49" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M250.07 216.1c-12.41.02-23.55 1.57-31.4 3.99.66-.31.6-1.12-.21-3.2-.98-2.53-2.5-2.42-2.5-2.42 8.66-2.56 20.73-4.16 34.16-4.18 13.44.02 25.6 1.62 34.27 4.18 0 0-1.53-.1-2.5 2.42-.82 2.08-.88 2.89-.22 3.2-7.84-2.42-19.2-3.97-31.6-4" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.12 210.3c-13.43.02-25.5 1.61-34.16 4.18-.58.17-1.2-.05-1.38-.6-.19-.55.12-1.18.7-1.35 8.7-2.68 21.09-4.35 34.84-4.38 13.77.03 26.2 1.7 34.9 4.38.58.17.89.8.7 1.35-.19.55-.8.77-1.38.6-8.67-2.56-20.78-4.16-34.22-4.19" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.12 224.57c-11.06-.01-21.07-1.3-28.68-3.26 7.61-1.97 17.62-3.17 28.68-3.2 11.07.03 21.13 1.23 28.74 3.2-7.61 1.97-17.67 3.25-28.74 3.26z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".39"/>
|
||||||
|
<path d="M240.54 213.35c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.15 214.16h-3.29c-.6 0-1.1-.46-1.1-1.03 0-.58.49-1.04 1.09-1.04h6.64c.6 0 1.1.46 1.1 1.04 0 .57-.5 1.03-1.11 1.03h-3.33" fill="#ad1519" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M233.64 215.07l-2.36.27c-.6.07-1.17-.33-1.24-.9-.08-.57.35-1.09.96-1.15l2.37-.28 2.42-.28c.6-.07 1.15.33 1.22.9.07.57-.36 1.09-.96 1.16l-2.41.28" fill="#058e6e" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M224.03 215.28c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.03" fill="#fff" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M216.72 217.16l1.22-1.6 3.37.44-2.7 1.96-1.89-.8" fill="#ad1519" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M266.66 215.07l2.36.27c.6.07 1.17-.33 1.24-.9a1.05 1.05 0 0 0-.96-1.15l-2.37-.28-2.42-.28c-.6-.07-1.15.33-1.22.9-.08.57.36 1.09.96 1.16l2.41.28" fill="#058e6e" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M257.56 213.35c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04M274.07 215.28c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.03" fill="#fff" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M283.57 217.16l-1.21-1.6-3.37.44 2.7 1.96 1.88-.8" fill="#ad1519" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M220.12 221.66c7.75-2.17 18.3-3.52 30-3.54 11.71.02 22.31 1.37 30.06 3.54" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M225.34 191.42l1.38 1.11 2.09-3.4a7.7 7.7 0 0 1-3.75-7.42c.21-4.34 5.5-7.92 12.2-7.92 3.48 0 6.63.95 8.84 2.48.06-.67.12-1.25.21-1.86a18.11 18.11 0 0 0-9.05-2.28c-7.7 0-13.74 4.38-14.03 9.57a9.25 9.25 0 0 0 3.22 7.9l-1.11 1.82" fill="#c8b100"/>
|
||||||
|
<path d="M225.34 191.42l1.38 1.11 2.09-3.4a7.7 7.7 0 0 1-3.75-7.42c.21-4.34 5.5-7.92 12.2-7.92 3.48 0 6.63.95 8.84 2.48.06-.67.12-1.25.21-1.86a18.11 18.11 0 0 0-9.05-2.28c-7.7 0-13.74 4.38-14.03 9.57a9.25 9.25 0 0 0 3.22 7.9l-1.11 1.82" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M225.43 191.46c-2.64-1.97-4.27-4.64-4.27-7.58 0-3.38 2.22-6.4 5.58-8.4a8.84 8.84 0 0 0-3.56 7.14 9.25 9.25 0 0 0 3.26 6.99l-1.01 1.85" fill="#c8b100"/>
|
||||||
|
<path d="M225.43 191.46c-2.64-1.97-4.27-4.64-4.27-7.58 0-3.38 2.22-6.4 5.58-8.4a8.84 8.84 0 0 0-3.56 7.14 9.25 9.25 0 0 0 3.26 6.99l-1.01 1.85" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M202.2 194.89a9.16 9.16 0 0 1-2.37-6.12c0-1.4.32-2.75.91-3.95 2.13-4.38 8.81-7.57 16.76-7.57 2.16 0 4.23.23 6.14.67-.42.46-.75.97-1.08 1.48-1.59-.31-3.29-.48-5.06-.48-7.27 0-13.35 2.83-15.12 6.65a7.36 7.36 0 0 0-.73 3.2c0 2.32 1.09 4.4 2.8 5.82l-2.64 4.3-1.41-1.12 1.8-2.88" fill="#c8b100"/>
|
||||||
|
<path d="M202.2 194.89a9.16 9.16 0 0 1-2.37-6.12c0-1.4.32-2.75.91-3.95 2.13-4.38 8.81-7.57 16.76-7.57 2.16 0 4.23.23 6.14.67-.42.46-.75.97-1.08 1.48-1.59-.31-3.29-.48-5.06-.48-7.27 0-13.35 2.83-15.12 6.65a7.36 7.36 0 0 0-.73 3.2c0 2.32 1.09 4.4 2.8 5.82l-2.64 4.3-1.41-1.12 1.8-2.88z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M204.9 180.48a10.98 10.98 0 0 0-4.16 4.34 8.95 8.95 0 0 0-.91 3.95c0 2.33.9 4.47 2.38 6.12l-1.6 2.6a10.87 10.87 0 0 1-2.42-6.7c0-4.2 2.67-7.88 6.71-10.3" fill="#c8b100"/>
|
||||||
|
<path d="M204.9 180.48a10.98 10.98 0 0 0-4.16 4.34 8.95 8.95 0 0 0-.91 3.95c0 2.33.9 4.47 2.38 6.12l-1.6 2.6a10.87 10.87 0 0 1-2.42-6.7c0-4.2 2.67-7.88 6.71-10.3z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.04 171.27a3.69 3.69 0 0 1 3.64 2.72c.23 1.39.38 2.96.41 4.63l-.01.52c0 .2.04.41.05.61.06 3.52.56 6.62 1.27 8.52l-5.36 5.14-5.43-5.14c.72-1.9 1.22-5 1.28-8.52 0-.2.05-.41.05-.61l-.01-.51c.03-1.68.18-3.25.41-4.63.36-1.57 1.94-2.73 3.7-2.73" fill="#c8b100"/>
|
||||||
|
<path d="M250.04 171.27a3.69 3.69 0 0 1 3.64 2.72c.23 1.39.38 2.96.41 4.63l-.01.52c0 .2.04.41.05.61.06 3.52.56 6.62 1.27 8.52l-5.36 5.14-5.43-5.14c.72-1.9 1.22-5 1.28-8.52 0-.2.05-.41.05-.61l-.01-.51c.03-1.68.18-3.25.41-4.63.36-1.57 1.94-2.73 3.7-2.73z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.04 172.94c.91 0 1.69.58 1.87 1.4a30 30 0 0 1 .4 4.37l-.01.48c0 .2.03.4.04.6.05 3.31.53 6.24 1.21 8.04l-3.54 3.35-3.54-3.35c.68-1.8 1.15-4.73 1.21-8.05 0-.2.04-.4.04-.59v-.48c.02-1.58.16-3.07.39-4.38.18-.8 1.02-1.39 1.93-1.39" fill="#c8b100"/>
|
||||||
|
<path d="M250.04 172.94c.91 0 1.69.58 1.87 1.4a30 30 0 0 1 .4 4.37l-.01.48c0 .2.03.4.04.6.05 3.31.53 6.24 1.21 8.04l-3.54 3.35-3.54-3.35c.68-1.8 1.15-4.73 1.21-8.05 0-.2.04-.4.04-.59v-.48c.02-1.58.16-3.07.39-4.38.18-.8 1.02-1.39 1.93-1.39z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M274.7 191.42l-1.39 1.11-2.08-3.4a7.71 7.71 0 0 0 3.75-7.42c-.21-4.34-5.5-7.92-12.2-7.92-3.5 0-6.63.95-8.84 2.48-.06-.67-.12-1.25-.22-1.86a18.12 18.12 0 0 1 9.06-2.28c7.7 0 13.74 4.38 14.03 9.57a9.24 9.24 0 0 1-3.22 7.9l1.11 1.82" fill="#c8b100"/>
|
||||||
|
<path d="M274.7 191.42l-1.39 1.11-2.08-3.4a7.71 7.71 0 0 0 3.75-7.42c-.21-4.34-5.5-7.92-12.2-7.92-3.5 0-6.63.95-8.84 2.48-.06-.67-.12-1.25-.22-1.86a18.12 18.12 0 0 1 9.06-2.28c7.7 0 13.74 4.38 14.03 9.57a9.24 9.24 0 0 1-3.22 7.9l1.11 1.82" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M274.61 191.46c2.63-1.97 4.27-4.64 4.27-7.58 0-3.38-2.22-6.4-5.58-8.4a8.87 8.87 0 0 1 3.56 7.14 9.24 9.24 0 0 1-3.27 6.99l1.02 1.85" fill="#c8b100"/>
|
||||||
|
<path d="M274.61 191.46c2.63-1.97 4.27-4.64 4.27-7.58 0-3.38-2.22-6.4-5.58-8.4a8.87 8.87 0 0 1 3.56 7.14 9.24 9.24 0 0 1-3.27 6.99l1.02 1.85" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M297.83 194.89a9.02 9.02 0 0 0 1.46-10.07c-2.13-4.38-8.8-7.57-16.75-7.57-2.17 0-4.23.23-6.15.67.43.46.76.97 1.09 1.48 1.58-.31 3.29-.48 5.06-.48 7.27 0 13.35 2.83 15.11 6.65.47.97.73 2.06.73 3.2 0 2.32-1.09 4.4-2.79 5.82l2.63 4.3 1.42-1.12-1.8-2.88" fill="#c8b100"/>
|
||||||
|
<path d="M297.83 194.89a9.02 9.02 0 0 0 1.46-10.07c-2.13-4.38-8.8-7.57-16.75-7.57-2.17 0-4.23.23-6.15.67.43.46.76.97 1.09 1.48 1.58-.31 3.29-.48 5.06-.48 7.27 0 13.35 2.83 15.11 6.65.47.97.73 2.06.73 3.2 0 2.32-1.09 4.4-2.79 5.82l2.63 4.3 1.42-1.12-1.8-2.88z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M295.13 180.48a11.02 11.02 0 0 1 4.17 4.34 9.06 9.06 0 0 1-1.47 10.07l1.6 2.6a10.86 10.86 0 0 0 2.41-6.7c0-4.2-2.67-7.88-6.7-10.3" fill="#c8b100"/>
|
||||||
|
<path d="M295.13 180.48a11.02 11.02 0 0 1 4.17 4.34 9.06 9.06 0 0 1-1.47 10.07l1.6 2.6a10.86 10.86 0 0 0 2.41-6.7c0-4.2-2.67-7.88-6.7-10.3z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M248.13 188.93c0-1 .86-1.8 1.9-1.8 1.06 0 1.91.8 1.91 1.8s-.85 1.8-1.9 1.8c-1.05 0-1.9-.8-1.9-1.8" fill="#fff"/>
|
||||||
|
<path d="M248.13 188.93c0-1 .86-1.8 1.9-1.8 1.06 0 1.91.8 1.91 1.8s-.85 1.8-1.9 1.8c-1.05 0-1.9-.8-1.9-1.8z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M248.13 185.4c0-1 .86-1.8 1.9-1.8 1.06 0 1.91.8 1.91 1.8s-.85 1.8-1.9 1.8c-1.05 0-1.9-.8-1.9-1.8M248.51 181.6c0-.8.69-1.44 1.53-1.44.83 0 1.51.64 1.51 1.44 0 .8-.68 1.44-1.51 1.44-.84 0-1.53-.64-1.53-1.44M248.94 178.17c0-.57.5-1.03 1.1-1.03.6 0 1.09.46 1.09 1.03 0 .58-.49 1.05-1.1 1.05-.6 0-1.09-.47-1.09-1.05M249.16 175.18c0-.47.39-.83.88-.83.48 0 .87.37.87.83 0 .45-.4.83-.87.83a.86.86 0 0 1-.88-.83" fill="#fff" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.2 199.78l1.23.22a4.8 4.8 0 0 0 4.68 6.28 4.9 4.9 0 0 0 4.68-3.21c.07.05.46-1.68.67-1.66.17.02.15 1.8.22 1.77.31 2.34 2.46 3.93 4.87 3.93a4.78 4.78 0 0 0 4.87-5.22l1.54-1.52.83 1.94c-.33.61-.46 1.3-.46 2.03 0 2.46 2.1 4.44 4.7 4.44 1.62 0 3.05-.78 3.9-1.97l.98-1.25v1.53c0 1.55.65 2.93 2.15 3.18 0 0 1.73.1 4.03-1.7 2.3-1.8 3.56-3.29 3.56-3.29l.2 1.8s-1.91 2.95-3.98 4.15c-1.14.66-2.86 1.35-4.23 1.13-1.44-.24-2.47-1.4-3-2.74a7 7 0 0 1-3.56.97c-2.8 0-5.33-1.54-6.32-3.86a7.28 7.28 0 0 1-10.77-.3 7.22 7.22 0 0 1-4.88 1.86 7.2 7.2 0 0 1-5.94-3.05 7.19 7.19 0 0 1-5.94 3.05c-1.89 0-3.61-.71-4.87-1.86a7.27 7.27 0 0 1-10.77.3c-1 2.32-3.52 3.86-6.32 3.86-1.3 0-2.52-.36-3.55-.97-.54 1.34-1.57 2.5-3.01 2.74-1.37.22-3.1-.47-4.23-1.13-2.07-1.2-3.98-4.14-3.98-4.14l.2-1.8s1.27 1.48 3.56 3.28c2.3 1.8 4.02 1.7 4.02 1.7 1.5-.25 2.16-1.63 2.16-3.18v-1.53l.98 1.25a4.76 4.76 0 0 0 3.9 1.97c2.6 0 4.7-1.98 4.7-4.44 0-.73-.14-1.42-.47-2.03l.83-1.94 1.54 1.52-.03.57c0 2.57 2.19 4.65 4.9 4.65 2.42 0 4.56-1.59 4.88-3.93.06.03.05-1.75.22-1.77.2-.02.6 1.7.67 1.66a4.9 4.9 0 0 0 4.68 3.21 4.79 4.79 0 0 0 4.67-6.28l1.29-.22" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M283.96 205.91c.28-.83.03-1.66-.57-1.84-.6-.18-1.32.34-1.6 1.17-.3.83-.04 1.65.56 1.84.6.18 1.32-.34 1.6-1.17M262.58 201.77c.11-.87-.3-1.63-.93-1.7-.63-.07-1.22.57-1.34 1.44-.11.86.3 1.63.93 1.7.63.07 1.23-.57 1.34-1.44M237.76 201.77c-.1-.87.31-1.63.93-1.7.63-.07 1.23.57 1.34 1.44.11.86-.3 1.63-.93 1.7-.63.07-1.22-.57-1.34-1.44M216.4 205.91c-.3-.83-.04-1.66.56-1.84.6-.18 1.32.34 1.6 1.17.28.83.03 1.65-.57 1.84-.6.18-1.31-.34-1.6-1.17" fill="#fff" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M225.68 191.65a5.34 5.34 0 0 1 2.3 3.03s.13-.25.71-.6c.6-.32 1.09-.31 1.09-.31s-.17.97-.25 1.32c-.09.34-.1 1.38-.32 2.32a7.72 7.72 0 0 1-.63 1.68 1.98 1.98 0 0 0-1.58-.41 1.9 1.9 0 0 0-1.32.9s-.66-.58-1.2-1.38c-.56-.8-.94-1.78-1.14-2.08-.21-.3-.72-1.15-.72-1.15s.47-.18 1.14-.05c.67.12.88.32.88.32a5.1 5.1 0 0 1 1.04-3.59" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M226.13 201.86c-.34-.27-.6-.64-.68-1.08a1.7 1.7 0 0 1 .23-1.23s-.88-.44-1.83-.7c-.72-.18-1.99-.19-2.37-.2l-1.15-.02s.07.17.28.55c.26.46.5.75.5.75a5.25 5.25 0 0 0-3.03 2.09c.99.68 2.3 1.1 3.6.97 0 0-.12.34-.2.86-.06.43-.06.61-.06.61l1.07-.4c.35-.12 1.54-.54 2.15-.95.8-.54 1.49-1.25 1.49-1.25M228.97 201.38a1.72 1.72 0 0 0-.42-2.3s.67-.71 1.47-1.26c.6-.4 1.8-.82 2.15-.95l1.07-.4s0 .18-.06.61c-.08.52-.2.87-.2.87 1.3-.14 2.62.3 3.6.98a5.27 5.27 0 0 1-3.03 2.08 6.82 6.82 0 0 0 .78 1.3l-1.15-.03c-.38 0-1.65 0-2.37-.2-.95-.25-1.84-.7-1.84-.7" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M225.2 200.45c0-1.14.97-2.06 2.17-2.06 1.19 0 2.16.92 2.16 2.06 0 1.13-.97 2.05-2.16 2.05-1.2 0-2.17-.92-2.17-2.05" fill="#ad1519" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M250.11 188.37a5.91 5.91 0 0 1 1.95 3.8s.19-.26.91-.52 1.28-.16 1.28-.16-.39 1.05-.56 1.42c-.16.37-.38 1.53-.83 2.53a8.58 8.58 0 0 1-1.05 1.76c-.4-.45-1-.75-1.67-.75-.67 0-1.27.3-1.67.75 0 0-.61-.76-1.06-1.76-.44-1-.66-2.16-.83-2.53-.17-.37-.56-1.42-.56-1.42s.56-.1 1.28.16.92.53.92.53c.1-1.46.86-2.87 1.9-3.81" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M248.5 199.83a1.96 1.96 0 0 1-.01-2.65s-.9-.67-1.9-1.12c-.77-.35-2.18-.59-2.6-.67l-1.28-.24s.04.2.2.67c.2.56.4.93.4.93a6.1 6.1 0 0 0-3.81 1.76 6.17 6.17 0 0 0 3.8 1.75s-.19.36-.39.93c-.16.46-.2.66-.2.66l1.28-.23c.42-.09 1.83-.32 2.6-.67 1-.46 1.9-1.11 1.9-1.11M251.76 199.83a1.95 1.95 0 0 0 .01-2.65s.9-.67 1.9-1.12c.77-.35 2.18-.59 2.6-.67l1.28-.24s-.03.2-.2.67c-.2.56-.4.93-.4.93 1.47.08 2.86.81 3.81 1.76a6.15 6.15 0 0 1-3.8 1.75 7.05 7.05 0 0 0 .59 1.6l-1.27-.24c-.43-.09-1.84-.32-2.6-.67-1-.46-1.92-1.11-1.92-1.11M274.67 191.65a5.36 5.36 0 0 0-2.3 3.03s-.13-.25-.72-.6c-.58-.32-1.09-.31-1.09-.31s.17.97.26 1.32c.09.34.09 1.38.31 2.32.23.93.64 1.68.64 1.68.42-.34.99-.5 1.57-.41.59.1 1.06.44 1.33.9 0 0 .66-.58 1.2-1.38.55-.8.93-1.78 1.13-2.08.21-.3.72-1.15.72-1.15s-.47-.18-1.14-.05c-.67.12-.88.32-.88.32a5.06 5.06 0 0 0-1.03-3.59" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M274.22 201.86c.34-.27.6-.64.67-1.08.09-.44 0-.87-.22-1.23 0 0 .88-.44 1.82-.7.73-.18 2-.19 2.37-.2l1.15-.02s-.06.17-.28.55c-.26.46-.5.75-.5.75a5.26 5.26 0 0 1 3.04 2.09 5.5 5.5 0 0 1-3.6.97s.11.34.2.86c.06.43.05.61.05.61l-1.06-.4c-.36-.12-1.55-.54-2.16-.95-.8-.54-1.48-1.25-1.48-1.25M271.38 201.38a1.74 1.74 0 0 1-.25-1.23c.09-.44.33-.8.67-1.08 0 0-.67-.7-1.47-1.25-.61-.4-1.8-.82-2.16-.95l-1.06-.4s0 .18.06.61c.08.52.2.87.2.87-1.3-.14-2.62.3-3.6.98a5.27 5.27 0 0 0 3.02 2.08s-.23.28-.49.74c-.22.39-.28.56-.28.56l1.14-.03c.38 0 1.66 0 2.37-.2.95-.25 1.84-.7 1.84-.7" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M270.81 200.45c0-1.14.97-2.06 2.17-2.06s2.17.92 2.17 2.06c0 1.13-.97 2.05-2.17 2.05s-2.17-.92-2.17-2.05M295.05 205c-.5-.53-1.57-.42-2.36.26-.79.67-1.02 1.66-.5 2.2.5.53 1.56.41 2.35-.26.8-.67 1.02-1.66.51-2.2" fill="#ad1519" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M291.97 206.31c.11-.36.36-.74.72-1.05.8-.68 1.85-.8 2.36-.25.06.07.14.17.18.25 0 0 1.1-2.08 2.4-2.78 1.3-.7 3.5-.52 3.5-.52 0-1.6-1.3-2.89-3-2.89-.99 0-1.92.41-2.48 1.1l-.22-1.06s-1.36.27-1.98 1.82c-.62 1.55.05 3.8.05 3.8s-.33-.96-.84-1.6a8.33 8.33 0 0 0-2.49-1.66 11.2 11.2 0 0 1-1.37-.8s-.03.18-.06.6c-.02.52.02.84.02.84a8.21 8.21 0 0 0-3.83.48c.48.95 1.4 1.84 2.61 2.3 0 0-.43.36-.83.75-.33.34-.44.5-.44.5l1.28.18c.43.05 1.84.28 2.68.22.63-.04 1.32-.14 1.74-.22M208.37 206.31c-.1-.36-.35-.74-.72-1.05-.79-.68-1.84-.8-2.36-.25a1.1 1.1 0 0 0-.17.25s-1.1-2.08-2.4-2.78c-1.3-.7-3.5-.52-3.5-.52 0-1.6 1.3-2.89 2.99-2.89 1 0 1.92.41 2.48 1.1l.23-1.06s1.36.27 1.98 1.82c.62 1.55-.06 3.8-.06 3.8s.34-.96.85-1.6a8.36 8.36 0 0 1 2.49-1.66c.67-.32 1.37-.8 1.37-.8a8.21 8.21 0 0 0 .04 1.44c1.24-.17 2.7.04 3.83.48a4.92 4.92 0 0 1-2.62 2.3s.44.36.83.75c.34.34.44.5.44.5l-1.27.18c-.43.05-1.84.28-2.69.22-.62-.04-1.32-.14-1.74-.22" fill="#c8b100" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M205.3 205c.5-.53 1.56-.42 2.35.26.8.67 1.02 1.66.51 2.2-.5.53-1.57.41-2.36-.26-.79-.67-1.02-1.66-.5-2.2M247.97 198.5c0-1.13.97-2.05 2.17-2.05s2.17.92 2.17 2.05c0 1.14-.97 2.06-2.17 2.06s-2.17-.92-2.17-2.06" fill="#ad1519" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M245.63 167.3c0-2.32 1.98-4.2 4.42-4.2a4.32 4.32 0 0 1 4.43 4.2 4.31 4.31 0 0 1-4.43 4.2 4.32 4.32 0 0 1-4.43-4.2" fill="#005bbf" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M248.9 155.54v2.26h-2.43v2.3h2.42V166.7h-3.05c-.03.21-.22.37-.22.6 0 .57.12 1.13.35 1.63 0 .02.02.02.03.03h8.12l.03-.03a4 4 0 0 0 .34-1.63c0-.23-.18-.39-.22-.6h-2.95v-6.61h2.42v-2.3h-2.42v-2.26h-2.43z" fill="#c8b100" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M250.5 344.33a85.31 85.31 0 0 1-36.96-8.54 23.65 23.65 0 0 1-13.36-21.19v-33.3h100.43v33.3c0 9.19-5.33 17.21-13.37 21.2a84.42 84.42 0 0 1-36.75 8.53" fill="#ccc"/>
|
||||||
|
<path d="M250.5 344.33a85.31 85.31 0 0 1-36.96-8.54 23.65 23.65 0 0 1-13.36-21.19v-33.3h100.43v33.3c0 9.19-5.33 17.21-13.37 21.2a84.42 84.42 0 0 1-36.75 8.53z" fill="none" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M250.28 281.25h50.32v-55.72h-50.32v55.72z" fill="#ccc"/>
|
||||||
|
<path d="M250.28 281.25h50.32v-55.72h-50.32v55.72z" fill="none" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M250.32 314.57c0 13.16-11.16 23.82-25.05 23.82-13.9 0-25.16-10.66-25.16-23.82V281.2h50.2v33.36" fill="#ad1519"/>
|
||||||
|
<path d="M211.08 334.23c1.57.83 3.72 2.22 6.03 2.77l-.15-56.96h-5.88v54.19z" fill="#c8b100" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M200.03 314.12a25.4 25.4 0 0 0 5.73 15.67v-49.47h-5.66l-.07 33.8z" fill="#c8b100" stroke="#000" stroke-linejoin="round" stroke-width=".5"/>
|
||||||
|
<path d="M222.28 338.25c2.3.23 4.01.19 5.87 0v-58.21h-5.88v58.21z" fill="#c7b500" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M233.32 337c2.3-.46 4.9-1.9 6.03-2.63v-54.33h-5.88l-.15 56.96z" fill="#c8b100" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M200.12 281.25h50.18v-55.72h-50.18v55.72z" fill="#ad1519"/>
|
||||||
|
<path d="M200.12 281.25h50.18v-55.72h-50.18v55.72z" fill="none" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M244.81 329.24c2.45-2.18 4.75-7.13 5.59-12.76l.14-36.44h-5.87l.14 49.2z" fill="#c8b100" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M250.32 314.57c0 13.16-11.16 23.82-25.05 23.82-13.9 0-25.16-10.66-25.16-23.82V281.2h50.2v33.36" fill="none" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M300.65 281.21v33.36c0 13.16-11.28 23.82-25.17 23.82-13.9 0-25.16-10.66-25.16-23.82V281.2h50.33" fill="#ad1519"/>
|
||||||
|
<path d="M300.65 281.21v33.36c0 13.16-11.28 23.82-25.17 23.82-13.9 0-25.16-10.66-25.16-23.82V281.2h50.33" fill="none" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M259.47 306.39c.08.17.13.34.13.52 0 .61-.52 1.1-1.17 1.1-.65 0-1.17-.49-1.17-1.1 0-.18.04-.35.12-.5l-1.63-.02a2.6 2.6 0 0 0 1.85 2.99v4.01l1.71.01v-4.04c.8-.26 1.43-.86 1.7-1.62h4.6v-1.35h-6.14m22.58 0v1.35l-4.14.01c-.06.19-.16.35-.26.51l4.8 5.46-1.29 1.05-4.78-5.47-.23.09v9.04h-1.7v-9.08c-.08-.02-.14-.05-.2-.09l-4.98 5.5-1.3-1.04 4.98-5.52c-.08-.14-.15-.3-.2-.46h-4.28v-1.35h13.59zm2.76 0v1.35h4.6c.28.76.9 1.36 1.7 1.62v4.04h1.71v-4.02a2.6 2.6 0 0 0 1.91-2.47c0-.18-.02-.36-.06-.52h-1.63c.08.17.12.34.12.52 0 .61-.52 1.1-1.16 1.1-.65 0-1.17-.49-1.17-1.1 0-.18.04-.35.12-.5l-6.14-.02m-6.96 23.04c1.34-.21 2.58-.58 3.8-1.1l.85 1.43c-1.41.6-2.93 1.04-4.5 1.28a2.7 2.7 0 0 1-2.67 2.04 2.7 2.7 0 0 1-2.67-2.02 18.23 18.23 0 0 1-4.73-1.3l.84-1.43c1.29.55 2.66.9 4.08 1.1a2.6 2.6 0 0 1 1.58-1.38l.01-7.01h1.7l.01 6.98c.75.22 1.38.74 1.7 1.4zm-11.5-2.35l-.83 1.44a17.35 17.35 0 0 1-3.8-3.22c-.86.26-1.85.1-2.59-.5a2.49 2.49 0 0 1-.3-3.64l.14-.16a15.9 15.9 0 0 1-1.32-5h1.71c.13 1.51.51 2.94 1.1 4.28.48-.06.99 0 1.45.16l4.28-4.73 1.29 1.04-4.25 4.73c.57.87.55 2-.1 2.85a15.8 15.8 0 0 0 3.23 2.75zm-6.33-4.96a1.21 1.21 0 0 1 1.65-.13c.49.4.55 1.1.13 1.56-.42.47-1.16.52-1.65.13-.5-.4-.55-1.1-.13-1.56zm-2.16-4.69l-1.76-.39-.25-4.45 1.75-.58v2.56c0 .99.09 1.92.26 2.86zm1.46-5.52l1.75.41s.09 2.87.05 2.22c-.04-.75.2 2.24.2 2.24l-1.77.58c-.18-.9-.24-1.84-.24-2.8v-2.65zm5.77 14.25a16.32 16.32 0 0 0 5.04 2.68l.4-1.7a14.27 14.27 0 0 1-4.18-2.1l-1.26 1.12m-.84 1.46c1.5 1.13 3.2 2.03 5.04 2.65l-1.31 1.23a19.49 19.49 0 0 1-4.12-2.11l.38-1.77m2.29-9.81l1.67.7 3.06-3.39-1-1.44-3.73 4.13m-1.3-1.05l-1-1.45 3.06-3.4 1.67.72-3.73 4.13m18.84 10.32l.83 1.44a17.4 17.4 0 0 0 3.8-3.22c.87.26 1.85.1 2.6-.5a2.5 2.5 0 0 0 .3-3.64l-.15-.16c.7-1.56 1.17-3.24 1.32-5h-1.7c-.14 1.51-.52 2.94-1.1 4.28-.48-.06-1 0-1.46.16l-4.27-4.73-1.3 1.04 4.26 4.73c-.57.87-.55 2 .1 2.85a15.71 15.71 0 0 1-3.23 2.75zm6.34-4.96a1.2 1.2 0 0 0-1.65-.13c-.5.4-.55 1.1-.13 1.56.42.47 1.16.52 1.65.13.5-.4.55-1.1.13-1.56zm2.15-4.69l1.76-.39.25-4.45-1.74-.58v2.56c0 .99-.1 1.92-.27 2.86zm-1.45-5.52l-1.75.41s-.1 2.87-.06 2.22c.05-.75-.2 2.24-.2 2.24l1.77.58c.18-.9.24-1.84.24-2.8v-2.65m-5.78 14.25a16.38 16.38 0 0 1-5.04 2.68l-.39-1.7a14.24 14.24 0 0 0 4.17-2.1l1.26 1.12m.85 1.46a18.18 18.18 0 0 1-5.04 2.65l1.31 1.23a19.5 19.5 0 0 0 4.12-2.11l-.39-1.77m-2.28-9.81l-1.67.7-3.06-3.39 1-1.44 3.73 4.13m1.3-1.05l1-1.45-3.06-3.4-1.67.72 3.72 4.13m-20.94-9.01l.51 1.67h4.72l.5-1.67h-5.73m22.02 0l-.52 1.67h-4.71l-.5-1.67h5.73m-12.11 22.75c0-.62.52-1.12 1.17-1.12.64 0 1.17.5 1.17 1.12 0 .6-.53 1.1-1.17 1.1-.65 0-1.17-.5-1.17-1.1zm1.98-8.08l1.76-.5v-4.45l-1.76-.48v5.43m-1.7 0l-1.76-.5v-4.45l1.76-.48v5.43" fill="#c8b100"/>
|
||||||
|
<path d="M255.75 306.43c.2-.93.93-1.69 1.86-1.97l-.01-5.5h1.7v5.53c.84.26 1.48.88 1.74 1.68h4.57v.26h-6.14a1.2 1.2 0 0 0-2.09.02l-1.63-.02m12.71 0v-.25h4.25c.05-.14.11-.28.19-.4l-5.25-5.85 1.3-1.04 5.17 5.75.27-.12.01-7.66h1.7v7.61l.26.07 5.06-5.76 1.3 1.03-5.08 5.74c.13.19.22.4.3.63h4.1v.25h-13.58zm22.5 0a1.2 1.2 0 0 1 1.04-.6c.45 0 .85.26 1.04.62l1.63-.02a2.68 2.68 0 0 0-1.86-1.97l.01-5.5h-1.7v5.54c-.83.26-1.48.87-1.73 1.67h-4.58v.26h6.14m-31.38-15.54l6.3 7.07 1.3-1.05-6.34-7.04c.12-.19.21-.4.29-.62h4.61v-1.6h-4.61a2.72 2.72 0 0 0-2.61-1.8 2.67 2.67 0 0 0-2.73 2.6c0 1.13.76 2.1 1.84 2.45l-.01 5.45h1.69v-5.42l.27-.04zm33.27.03l-.01 5.43h-1.7v-5.45c-.13-.04-.26-.1-.38-.15l-6.27 7.07-1.3-1.03 6.4-7.21c-.06-.1-.12-.21-.15-.33h-4.64v-1.6h4.62a2.71 2.71 0 0 1 2.6-1.8c1.5 0 2.73 1.17 2.73 2.6a2.6 2.6 0 0 1-1.9 2.47zm-16.73-.02l-.01 3.35h-1.7v-3.32a2.68 2.68 0 0 1-1.78-1.68h-4.13v-1.6h4.13a2.7 2.7 0 0 1 2.6-1.8c1.2 0 2.23.75 2.6 1.8h4.21v1.6h-4.23a2.63 2.63 0 0 1-1.69 1.65zm-18.49 4.06l-1.76.5v4.46l1.76.49v-5.45m1.7 0l1.76.5v4.46l-1.75.49v-5.45m31.78 0l-1.75.5v4.46l1.75.49v-5.45m1.71 0l1.76.5v4.46l-1.76.49v-5.45m-26.61.88l1.67-.7 3.06 3.4-1 1.44-3.73-4.14m-1.3 1.06l-1 1.45 3.06 3.4 1.67-.72-3.73-4.13m19.22-1.19l-1.68-.7-3.03 3.43 1.02 1.44 3.69-4.17m1.3 1.04l1.02 1.45-3.03 3.42-1.68-.7 3.7-4.17m-21.19 9.43l.51-1.67h4.72l.5 1.67h-5.73m-6.91-17.73c0-.61.52-1.11 1.17-1.11.64 0 1.17.5 1.17 1.11 0 .61-.53 1.1-1.17 1.1-.65 0-1.17-.49-1.17-1.1zm12.6.8l-.51 1.68h-4.71l-.51-1.67h5.74m0-1.62l-.52-1.67h-4.71l-.51 1.67h5.74m16.32 18.54l-.52-1.67h-4.71l-.5 1.67h5.73m4.57-17.73c0-.61.52-1.11 1.17-1.11.64 0 1.16.5 1.16 1.11 0 .61-.52 1.1-1.16 1.1-.65 0-1.17-.49-1.17-1.1zm-16.8 0c0-.61.53-1.11 1.17-1.11.65 0 1.17.5 1.17 1.11 0 .61-.52 1.1-1.17 1.1-.64 0-1.17-.49-1.17-1.1zm6.53.8l.52 1.68h4.7l.52-1.67h-5.74m0-1.62l.52-1.67h4.7l.52 1.67h-5.74m-6.15 5.22l-1.76.5v4.46l1.76.49v-5.45m1.69 0l1.75.5v4.46l-1.75.49v-5.45" fill="#c8b100"/>
|
||||||
|
<path d="M277.85 329.43c1.34-.21 2.58-.58 3.8-1.1l.85 1.43c-1.41.6-2.93 1.04-4.5 1.28a2.7 2.7 0 0 1-2.67 2.04 2.7 2.7 0 0 1-2.67-2.02 18.23 18.23 0 0 1-4.73-1.3l.84-1.43c1.29.55 2.66.9 4.08 1.1a2.6 2.6 0 0 1 1.58-1.38l.01-7.01h1.7l.01 6.98c.75.22 1.38.74 1.7 1.4zm-4.9-21.23c-.09-.14-.15-.3-.2-.46h-4.29v-1.6h4.25c.05-.14.12-.27.19-.4l-5.25-5.83 1.3-1.05 5.17 5.74.28-.12v-7.64h1.7v7.6c.07.02.19.04.26.07l5.06-5.75 1.3 1.03-5.08 5.72c.13.19.22.4.3.63h4.1v1.6l-4.13.01c-.06.19-.17.35-.26.51l4.8 5.47-1.29 1.04-4.78-5.47c-.09.03-.13.07-.23.1l-.01 9.03h-1.7v-9.08c-.07-.02-.13-.05-.2-.09l-4.98 5.51-1.29-1.04 4.98-5.53m-13.38-17.32l6.3 7.05 1.3-1.04-6.34-7.03c.12-.19.21-.4.29-.61h4.61v-1.6h-4.61a2.72 2.72 0 0 0-2.61-1.8 2.66 2.66 0 0 0-2.73 2.6c0 1.12.76 2.09 1.84 2.44l-.01 5.44h1.69v-5.4c.07-.03.2-.03.27-.05zm6.79 36.2l-.84 1.44a17.35 17.35 0 0 1-3.8-3.22c-.86.26-1.85.1-2.59-.5a2.49 2.49 0 0 1-.3-3.64l.14-.16a15.9 15.9 0 0 1-1.32-5h1.71c.13 1.51.51 2.94 1.1 4.28.48-.06.99 0 1.45.16l4.28-4.73 1.29 1.04-4.25 4.73c.57.87.55 2-.1 2.85a15.8 15.8 0 0 0 3.23 2.75zm-8.76-13.69v-4.01a2.6 2.6 0 0 1-1.9-2.47c0-1.16.8-2.15 1.91-2.48l-.01-5.5h1.7v5.53c.84.26 1.48.88 1.74 1.67h4.57v1.61h-4.6c-.27.76-.9 1.36-1.7 1.62v4.04h-1.71m2.42 8.72a1.21 1.21 0 0 1 1.65-.13c.49.4.55 1.1.13 1.56-.42.47-1.16.52-1.65.13-.5-.4-.55-1.1-.13-1.56zm-2.16-4.69l-1.76-.39-.25-4.45 1.75-.58v2.56c0 .99.09 1.92.26 2.86zm1.46-5.52l1.75.41s.09 2.87.05 2.22c-.04-.75.2 2.24.2 2.24l-1.77.58c-.18-.9-.24-1.84-.24-2.8v-2.65zm5.77 14.25a16.32 16.32 0 0 0 5.04 2.68l.4-1.7a14.27 14.27 0 0 1-4.18-2.1l-1.26 1.12m-.84 1.46c1.5 1.13 3.2 2.03 5.04 2.65l-1.31 1.23a19.49 19.49 0 0 1-4.12-2.11l.38-1.77" fill="none" stroke="#c8b100" stroke-width=".26"/>
|
||||||
|
<path d="M266.53 317.8l1.67.72 3.06-3.4-1-1.44-3.73 4.13m-1.3-1.05l-1-1.45 3.06-3.4 1.67.72-3.73 4.13m-7.97-9.85c0-.62.52-1.11 1.17-1.11.64 0 1.16.5 1.16 1.11 0 .61-.52 1.1-1.16 1.1-.65 0-1.17-.49-1.17-1.1zm26.8 20.17l.84 1.44a17.4 17.4 0 0 0 3.8-3.22c.87.26 1.85.1 2.6-.5a2.5 2.5 0 0 0 .3-3.64l-.15-.16c.7-1.56 1.17-3.24 1.32-5h-1.7c-.14 1.51-.52 2.94-1.1 4.28-.48-.06-1 0-1.46.16l-4.27-4.73-1.3 1.04 4.26 4.73c-.57.87-.55 2 .1 2.85a15.71 15.71 0 0 1-3.23 2.75zm8.77-13.69v-4.01a2.6 2.6 0 0 0 1.9-2.47c0-1.16-.81-2.15-1.92-2.48l.01-5.5h-1.7v5.53c-.83.26-1.48.88-1.73 1.67h-4.58v1.61h4.6c.28.76.9 1.36 1.7 1.62v4.04h1.71zm-2.42 8.73a1.2 1.2 0 0 0-1.65-.13c-.5.4-.55 1.1-.13 1.56.42.47 1.16.52 1.65.13.5-.4.55-1.1.13-1.56zm2.15-4.69l1.76-.39.25-4.45-1.74-.58v2.56c0 .99-.1 1.92-.27 2.86zm-1.45-5.52l-1.75.41s-.1 2.87-.06 2.22c.05-.75-.2 2.24-.2 2.24l1.77.58c.18-.9.24-1.84.24-2.8v-2.65m1.73-21l-.01 5.42h-1.7v-5.44c-.13-.04-.26-.1-.38-.15l-6.27 7.06-1.3-1.03 6.4-7.2c-.06-.1-.12-.2-.15-.32h-4.64v-1.6h4.62a2.71 2.71 0 0 1 2.6-1.8c1.5 0 2.73 1.16 2.73 2.6a2.6 2.6 0 0 1-1.9 2.46zm-16.73-.02l-.01 3.34h-1.7v-3.31a2.68 2.68 0 0 1-1.78-1.67h-4.13v-1.6h4.13a2.7 2.7 0 0 1 2.6-1.8c1.2 0 2.23.75 2.6 1.8h4.21v1.6h-4.23a2.63 2.63 0 0 1-1.69 1.64zm9.22 35.27a16.38 16.38 0 0 1-5.04 2.68l-.39-1.7a14.24 14.24 0 0 0 4.17-2.1l1.26 1.12m.85 1.46a18.18 18.18 0 0 1-5.04 2.65l1.31 1.23a19.5 19.5 0 0 0 4.12-2.11l-.39-1.77m-28.56-32.68l-1.76.5v4.46l1.76.48v-5.44m1.7 0l1.76.5v4.46l-1.75.48v-5.44m31.78 0l-1.75.5v4.46l1.75.48v-5.44" fill="none" stroke="#c8b100" stroke-width=".26"/>
|
||||||
|
<path d="M292.82 294.94l1.76.5v4.46l-1.76.48v-5.44m-8.92 22.87l-1.67.7-3.06-3.39 1-1.44 3.73 4.13m1.3-1.05l1-1.45-3.06-3.4-1.67.72 3.72 4.13m-18.98-20.94l1.67-.7 3.06 3.39-1 1.45-3.73-4.14m-1.3 1.05l-1 1.46 3.06 3.39 1.67-.72-3.73-4.13m19.22-1.18l-1.68-.7-3.03 3.43 1.02 1.43 3.69-4.16m1.3 1.04l1.02 1.44-3.03 3.42-1.68-.7 3.7-4.16m-21.19 9.4l.51-1.66h4.72l.5 1.67h-5.73m0 1.6l.51 1.68h4.72l.5-1.67h-5.73m-6.91-19.3c0-.62.52-1.11 1.17-1.11.64 0 1.17.5 1.17 1.1 0 .62-.53 1.1-1.17 1.1-.65 0-1.17-.48-1.17-1.1zm12.6.8l-.51 1.67h-4.71l-.51-1.67h5.74m0-1.62l-.52-1.66h-4.71l-.51 1.66h5.74m20.88 19.28c0-.62.52-1.11 1.17-1.11.64 0 1.16.5 1.16 1.11 0 .61-.52 1.1-1.16 1.1-.65 0-1.17-.49-1.17-1.1zm-4.56-.77l-.52-1.67h-4.71l-.5 1.67h5.73m0 1.6l-.52 1.68h-4.71l-.5-1.67h5.73m-12.11 22.75c0-.62.52-1.12 1.17-1.12.64 0 1.17.5 1.17 1.12 0 .6-.53 1.1-1.17 1.1-.65 0-1.17-.5-1.17-1.1zm1.98-8.08l1.76-.5v-4.45l-1.76-.48v5.43m-1.7 0l-1.76-.5v-4.45l1.76-.48v5.43m16.4-33.98c0-.6.52-1.1 1.17-1.1.64 0 1.16.5 1.16 1.1 0 .62-.52 1.1-1.16 1.1-.65 0-1.17-.48-1.17-1.1zm-16.8 0c0-.6.53-1.1 1.17-1.1.65 0 1.17.5 1.17 1.1 0 .62-.52 1.1-1.17 1.1-.64 0-1.17-.48-1.17-1.1zm6.53.81l.52 1.67h4.7l.52-1.67h-5.74m0-1.62l.52-1.66h4.7l.52 1.66h-5.74M274.42 292.85l-1.76.49v4.46l1.76.48v-5.43m1.69 0l1.75.49v4.46l-1.75.48v-5.43" fill="none" stroke="#c8b100" stroke-width=".26"/>
|
||||||
|
<path d="M272.6 306.94c0-1.44 1.22-2.6 2.73-2.6 1.5 0 2.73 1.16 2.73 2.6a2.66 2.66 0 0 1-2.73 2.58c-1.51 0-2.74-1.15-2.74-2.58" fill="#058e6e"/>
|
||||||
|
<path d="M275.93 239.26l.06-.62.08-.34s-1.61.13-2.46-.1a6.15 6.15 0 0 1-2.4-1.26c-.8-.68-1.1-1.1-1.67-1.18-1.36-.22-2.4.4-2.4.4s1.02.37 1.78 1.3a4.85 4.85 0 0 0 1.95 1.54c.6.18 2.66.05 3.22.07.57.03 1.84.2 1.84.2" fill="#db4446"/>
|
||||||
|
<path d="M275.93 239.26l.06-.62.08-.34s-1.61.13-2.46-.1a6.15 6.15 0 0 1-2.4-1.26c-.8-.68-1.1-1.1-1.67-1.18-1.36-.22-2.4.4-2.4.4s1.02.37 1.78 1.3a4.85 4.85 0 0 0 1.95 1.54c.6.18 2.66.05 3.22.07.57.03 1.84.2 1.84.2z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M283.46 237s0 .72.08 1.4c.06.67-.22 1.24-.1 1.61.1.37.15.66.3.93.13.26.2.94.2.94l-.74-.54c-.35-.27-.6-.44-.6-.44l.1 1.03c.04.31.22.9.51 1.24.29.33.87.89 1.05 1.33.18.45.14 1.44.14 1.44s-.46-.75-.87-.89c-.4-.14-1.26-.62-1.26-.62s.8.8.8 1.55-.33 1.6-.33 1.6-.36-.68-.83-1.13c-.47-.44-1.13-.89-1.13-.89s.52 1.17.52 1.95c0 .8-.15 2.47-.15 2.47s-.4-.64-.8-.96c-.4-.3-.86-.58-1-.78-.15-.2.46.64.53 1.16.07.51.32 2.35 1.92 4.7.94 1.36 2.39 3.76 5.5 2.97 3.11-.78 1.95-4.97 1.3-6.92a17.52 17.52 0 0 1-.94-4.87c.04-.75.58-2.97.5-3.39-.06-.4-.23-2 .15-3.28.4-1.33.73-1.85.94-2.4.22-.55.4-.86.47-1.34.07-.48.07-1.37.07-1.37s.58 1.06.72 1.44c.15.38.15 1.5.15 1.5s.1-1.12.98-1.67c.87-.55 1.88-1.13 2.13-1.44.25-.31.33-.51.33-.51s-.08 1.92-.62 2.67c-.36.5-1.77 2.1-1.77 2.1s.73-.29 1.23-.31c.5-.04.87 0 .87 0s-.62.48-1.41 1.64c-.8 1.16-.47 1.26-1.05 2.22-.58.96-1.05 1-1.78 1.58-1.08.87-.5 4.34-.36 4.86.15.51 2.03 4.76 2.07 5.8.03 1.02.21 3.32-1.6 4.79-1.16.95-3.07.96-3.5 1.23-.44.28-1.3 1.13-1.3 2.91 0 1.79.64 2.06 1.15 2.5.5.45 1.16.21 1.3.56.15.34.22.54.44.75.22.2.36.44.29.82-.07.38-.9 1.23-1.2 1.85-.29.61-.87 2.23-.87 2.47 0 .24-.06 1 .18 1.37 0 0 .9 1.06.3 1.26-.4.14-.8-.25-.98-.2-.54.14-.82.47-.98.44-.36-.06-.36-.24-.4-.75-.03-.51-.01-.72-.18-.72-.21 0-.32.18-.36.45-.04.27-.04.89-.29.89-.25 0-.61-.45-.83-.55-.22-.1-.83-.2-.87-.48-.03-.27.36-.85.76-.96.4-.1.76-.3.5-.5-.25-.21-.5-.21-.75 0-.25.2-.8.03-.76-.28.04-.31.1-.69.07-.86-.03-.17-.47-.51.1-.82.59-.3.84.27 1.42.17s.87-.31 1.08-.65c.22-.34.18-1.06-.21-1.5-.4-.45-.8-.52-.95-.8-.14-.27-.36-.92-.36-.92s.1 1.2.04 1.37c-.07.17-.04.89-.04.89l-.72-.79a5.1 5.1 0 0 1-.65-1.37l-.03 1.34c0 .37.43.72.29.86-.15.13-.83-.72-1.02-.86a3.81 3.81 0 0 1-1.01-1.06c-.25-.48-.44-1.16-.5-1.4-.08-.25-.2-1.32-.08-1.59.18-.4.47-1.13.47-1.13h-1.41c-.76 0-1.3-.23-1.6.28-.28.51-.14 1.54.22 2.88.37 1.33.58 1.98.48 2.22-.11.24-.58.8-.76.9-.19.1-.7.06-.91-.04a2.6 2.6 0 0 0-1.26-.27c-.69 0-1.12.03-1.38-.03-.25-.07-.87-.38-1.16-.31-.29.07-.79.32-.65.72.22.61-.21.75-.5.72-.3-.04-.54-.14-.91-.24-.36-.1-.9 0-.83-.42.07-.4.22-.44.4-.75.18-.3.25-.5.04-.53-.25-.02-.5-.05-.7.11-.2.16-.5.5-.76.38-.26-.14-.46-.43-.46-1.08 0-.64-.68-1.2-.05-1.17.62.03 1.41.48 1.55.13.14-.35.06-.5-.28-.78-.34-.26-.76-.43-.3-.77.44-.35.55-.35.73-.54.17-.18.4-.79.72-.64.63.3.03.73.66 1.42.62.7 1.01.94 2.06.83 1.04-.1 1.33-.24 1.33-.54 0-.3-.09-.82-.12-1.04-.02-.21.15-1 .15-1s-.48.3-.63.6c-.13.3-.42.8-.42.8s-.11-.6-.08-1.1c.02-.28.12-.78.11-.88-.03-.27-.22-.94-.22-.94s-.18.73-.29.94c-.1.21-.17 1.07-.17 1.07s-.66-.58-.47-1.55c.13-.75-.12-1.74.1-2.06.23-.33.77-1.64 2.07-1.7 1.3-.04 2.31.06 2.77.04.45-.03 2.06-.32 2.06-.32s-2.97-1.53-3.65-1.99a9.89 9.89 0 0 1-2.06-2.16c-.34-.54-.65-1.58-.65-1.58s-.53.03-1.02.3a5.13 5.13 0 0 0-1.97 2.03s.08-.94.08-1.24c0-.28-.06-.85-.06-.85s-.33 1.28-1.01 1.76c-.68.49-1.47 1.15-1.47 1.15s.08-.71.08-.88c0-.16.17-.99.17-.99s-.48.72-1.21.86c-.74.13-1.81.1-1.9.56-.08.45.2 1.07.03 1.4-.17.31-.54.53-.54.53s-.42-.35-.79-.38c-.36-.03-.7.16-.7.16s-.32-.4-.2-.67c.11-.26.68-.66.54-.83-.15-.16-.6.06-.88.2-.28.13-.88.26-.82-.2.06-.45.2-.72.06-1.04-.15-.32-.06-.53.17-.62.22-.07 1.13.03 1.21-.18.08-.21-.22-.48-.82-.61-.6-.14-.88-.49-.56-.78.3-.3.4-.38.53-.64.14-.27.2-.75.74-.51.53.24.42.82.99 1.01.56.2 1.89-.07 2.17-.23.29-.17 1.19-.84 1.5-1 .31-.16 1.6-1.12 1.6-1.12s-.75-.53-1.04-.8c-.28-.27-.78-.91-1.04-1.05a8.72 8.72 0 0 0-1.92-.64 12 12 0 0 1-1.73-.48s.6-.19.8-.35c.2-.16.64-.56.87-.53l.28.03s-1.21-.06-1.47-.14c-.25-.08-.99-.54-1.27-.54s-.84.11-.84.11.76-.48 1.38-.59c.62-.1 1.1-.08 1.1-.08s-.96-.26-1.19-.58c-.22-.33-.45-.8-.62-1.02-.17-.21-.28-.56-.6-.59-.3-.03-.84.38-1.15.35-.3-.02-.54-.22-.57-.67-.02-.46 0-.3-.1-.53-.12-.25-.57-.81-.15-.94.43-.14 1.33.08 1.42-.08.08-.16-.48-.65-.85-.83-.37-.19-.96-.51-.65-.78.31-.27.62-.37.8-.61.16-.24.36-.91.73-.7.36.21.87 1.26 1.16 1.18.28-.08.3-.83.25-1.15-.06-.32 0-.88.28-.83.28.05.5.43.96.46.45.02 1.13-.11 1.07.2-.05.33-.3.72-.62 1.08a1.6 1.6 0 0 0-.25 1.5c.2.45.7 1.18 1.16 1.47.45.3 1.3.5 1.84.85.53.36 1.78 1.34 2.2 1.45.42.1.85.32.85.32s.48-.21 1.13-.21c.65 0 2.15.1 2.71-.14.57-.24 1.3-.64 1.08-1.15-.23-.5-1.47-.96-1.36-1.36.11-.4.57-.43 1.33-.46.76-.02 1.8.14 2-.94.2-1.06.25-1.68-.81-1.92-1.08-.24-1.87-.27-2.07-1.04-.2-.78-.4-.97-.17-1.18.23-.21.62-.32 1.41-.37.8-.06 1.7-.06 1.95-.25.26-.18.31-.7.62-.91.31-.21 1.53-.4 1.53-.4s1.45.7 2.8 1.7c1.21.91 2.3 2.24 2.3 2.24" fill="#ed72aa" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M273.05 236.24s-.17-.48-.2-.62c-.03-.13-.12-.29-.12-.29s.88 0 .85.27c-.02.27-.28.27-.33.37-.06.1-.2.27-.2.27"/>
|
||||||
|
<path d="M273.05 236.24s-.17-.48-.2-.62c-.03-.13-.12-.29-.12-.29s.88 0 .85.27c-.02.27-.28.27-.33.37-.06.1-.2.27-.2.27z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M277.06 234.85l-.06-.43s.77 0 1.13.26c.57.4.93 1.02.9 1.05-.09.1-.53-.27-.84-.38 0 0-.23.06-.45.06-.23 0-.34-.1-.37-.22-.03-.1.03-.29.03-.29l-.34-.05"/>
|
||||||
|
<path d="M277.06 234.85l-.06-.43s.77 0 1.13.26c.57.4.93 1.02.9 1.05-.09.1-.53-.27-.84-.38 0 0-.23.06-.45.06-.23 0-.34-.1-.37-.22-.03-.1.03-.29.03-.29l-.34-.05z" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M282.57 240.9s-.34-.49-.42-.65c-.09-.15-.23-.48-.23-.48" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M261.88 236.08s.48.34.85.4c.37.05.76.05.82.05.06 0 .17-.54.11-.9a1.84 1.84 0 0 0-1.3-1.48s.33.73.17 1.07c-.23.48-.65.86-.65.86" fill="#db4446"/>
|
||||||
|
<path d="M261.88 236.08s.48.34.85.4c.37.05.76.05.82.05.06 0 .17-.54.11-.9a1.84 1.84 0 0 0-1.3-1.48s.33.73.17 1.07c-.23.48-.65.86-.65.86z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M259.59 237.12s-.42-.77-1.33-.67c-.9.1-1.5.8-1.5.8s1-.02 1.25.14c.37.24.48.86.48.86s.54-.32.7-.54c.17-.21.4-.59.4-.59" fill="#db4446"/>
|
||||||
|
<path d="M259.59 237.12s-.42-.77-1.33-.67c-.9.1-1.5.8-1.5.8s1-.02 1.25.14c.37.24.48.86.48.86s.54-.32.7-.54c.17-.21.4-.59.4-.59z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M258.49 240.25s-.76.11-1.19.6c-.43.48-.37 1.39-.37 1.39s.51-.54.96-.54c.46 0 1.16.16 1.16.16s-.22-.56-.22-.8-.34-.8-.34-.8" fill="#db4446"/>
|
||||||
|
<path d="M258.49 240.25s-.76.11-1.19.6c-.43.48-.37 1.39-.37 1.39s.51-.54.96-.54c.46 0 1.16.16 1.16.16s-.22-.56-.22-.8-.34-.8-.34-.8z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M273.08 240.15l.33-.54.34.49-.67.05"/>
|
||||||
|
<path d="M273.08 240.15l.33-.54.34.49-.67.05" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M273.9 240.12l.39-.53.42.48-.82.05"/>
|
||||||
|
<path d="M273.9 240.12l.39-.53.42.48-.82.05" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M273.53 236.83l.82.3-.74.37-.08-.67"/>
|
||||||
|
<path d="M273.53 236.83l.82.3-.74.37-.08-.67" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M274.51 237.1l.74.18-.6.46-.13-.64"/>
|
||||||
|
<path d="M274.51 237.1l.74.18-.6.46-.13-.64" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M269 243.39s-.8.23-1.1.67c-.37.53-.34 1.07-.34 1.07s.68-.56 1.56-.33c.87.24.96.33 1.33.3.37-.03 1.27-.35 1.27-.35s-.74.86-.65 1.45c.08.59.2.85.17 1.15-.06.72-.6 1.6-.6 1.6s.31-.18 1.05-.34a4.77 4.77 0 0 0 1.75-.8c.4-.3.9-1.03.9-1.03s-.16 1 0 1.43c.17.42.23 1.66.23 1.66s.47-.42.85-.62c.2-.11.7-.38.9-.7.14-.22.31-1.06.31-1.06s.12.9.4 1.34c.28.42.7 1.74.7 1.74s.29-.86.6-1.21c.3-.35.68-.8.7-1.07.03-.27-.08-.85-.08-.85l.4.85m-11.42.61s.48-.83.93-1.1c.46-.27 1.08-.75 1.25-.8.16-.05.9-.46.9-.46m.99 5.17s1.09-.55 1.41-.75a4.11 4.11 0 0 0 1.16-1.12" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M261.06 250.37s-.43-.45-1.16-.32c-.73.14-1.21.97-1.21.97s.62-.17.99-.08c.36.08.62.45.62.45s.33-.3.45-.45c.11-.16.3-.57.3-.57" fill="#db4446"/>
|
||||||
|
<path d="M261.06 250.37s-.43-.45-1.16-.32c-.73.14-1.21.97-1.21.97s.62-.17.99-.08c.36.08.62.45.62.45s.33-.3.45-.45c.11-.16.3-.57.3-.57z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M260.21 253.34s-.62-.1-1.16.33c-.53.43-.56 1.25-.56 1.25s.5-.43.9-.37c.4.05.88.27.88.27l.11-.64c.09-.38-.17-.84-.17-.84" fill="#db4446"/>
|
||||||
|
<path d="M260.21 253.34s-.62-.1-1.16.33c-.53.43-.56 1.25-.56 1.25s.5-.43.9-.37c.4.05.88.27.88.27l.11-.64c.09-.38-.17-.84-.17-.84z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M261.65 256.08s-.04.8.34 1.28c.4.51 1.13.59 1.13.59s-.24-.53-.28-.8c-.06-.4.34-.75.34-.75s-.37-.38-.73-.38c-.37 0-.8.06-.8.06" fill="#db4446"/>
|
||||||
|
<path d="M261.65 256.08s-.04.8.34 1.28c.4.51 1.13.59 1.13.59s-.24-.53-.28-.8c-.06-.4.34-.75.34-.75s-.37-.38-.73-.38c-.37 0-.8.06-.8.06zM278.33 257.41s2.04 1.26 1.98 2.3c-.06 1.05-1.13 2.42-1.13 2.42" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M269 263.12s-.5-.64-1.21-.62c-.71.03-1.45.7-1.45.7s.88-.08 1.1.21c.24.3.46.67.46.67s.4-.21.57-.35c.17-.13.53-.61.53-.61" fill="#db4446"/>
|
||||||
|
<path d="M269 263.12s-.5-.64-1.21-.62c-.71.03-1.45.7-1.45.7s.88-.08 1.1.21c.24.3.46.67.46.67s.4-.21.57-.35c.17-.13.53-.61.53-.61z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M266.83 265.93s-.93-.14-1.39.35c-.45.48-.42 1.36-.42 1.36s.56-.61 1.07-.56c.51.05 1.08.32 1.08.32s-.09-.53-.15-.78c-.05-.24-.2-.7-.2-.7" fill="#db4446"/>
|
||||||
|
<path d="M266.83 265.93s-.93-.14-1.39.35c-.45.48-.42 1.36-.42 1.36s.56-.61 1.07-.56c.51.05 1.08.32 1.08.32s-.09-.53-.15-.78c-.05-.24-.2-.7-.2-.7z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M268.83 268.9s-.45.64-.1 1.15a2.3 2.3 0 0 0 1.04.75s-.26-.37-.14-.8c.09-.34.68-.8.68-.8l-1.48-.3" fill="#db4446"/>
|
||||||
|
<path d="M268.83 268.9s-.45.64-.1 1.15a2.3 2.3 0 0 0 1.04.75s-.26-.37-.14-.8c.09-.34.68-.8.68-.8l-1.48-.3z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M281.24 270.1s-.81-.18-1.27.09c-.45.26-.82 1.39-.82 1.39s.74-.62 1.28-.54c.53.08.93.3.93.3s.08-.46.02-.78c-.03-.19-.14-.45-.14-.45" fill="#db4446"/>
|
||||||
|
<path d="M281.24 270.1s-.81-.18-1.27.09c-.45.26-.82 1.39-.82 1.39s.74-.62 1.28-.54c.53.08.93.3.93.3s.08-.46.02-.78c-.03-.19-.14-.45-.14-.45z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M281.64 273.1s-.62.64-.4 1.18c.23.54.63 1.1.63 1.1s-.03-.8.22-1.02c.37-.32 1.05-.37 1.05-.37s-.54-.48-.71-.54c-.17-.05-.79-.35-.79-.35" fill="#db4446"/>
|
||||||
|
<path d="M281.64 273.1s-.62.64-.4 1.18c.23.54.63 1.1.63 1.1s-.03-.8.22-1.02c.37-.32 1.05-.37 1.05-.37s-.54-.48-.71-.54c-.17-.05-.79-.35-.79-.35z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M284.75 274.04s-.31.78.28 1.28c.6.51 1.1.57 1.1.57s-.45-.8-.3-1.23c.14-.45.53-.73.53-.73s-.74-.24-.85-.21c-.1.02-.76.32-.76.32" fill="#db4446"/>
|
||||||
|
<path d="M284.75 274.04s-.31.78.28 1.28c.6.51 1.1.57 1.1.57s-.45-.8-.3-1.23c.14-.45.53-.73.53-.73s-.74-.24-.85-.21c-.1.02-.76.32-.76.32z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M252.9 329.55c2.1.63 3.16 2.19 3.16 4.01 0 2.38-2.3 4.18-5.3 4.18-2.99 0-5.41-1.8-5.41-4.18 0-1.8 1-3.8 3.07-3.94 0 0-.06-.2-.24-.5l-.64-.66s.8-.15 1.25.02c.46.18.77.47.77.47s.21-.43.52-.76c.3-.33.7-.53.7-.53s.46.38.61.64c.15.27.25.59.25.59s.42-.35.8-.5c.36-.14.83-.25.83-.25s-.13.46-.22.69c-.1.23-.14.72-.14.72" fill="#ffd691" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M250.32 340.32s-3.98-2.68-5.7-3.04c-2.2-.47-4.69-.1-5.76-.15.03.03 1.29.93 1.84 1.48.55.55 2.39 1.65 3.43 1.91 3.22.81 6.2-.2 6.2-.2M251.46 340.56s2.54-2.66 5.21-3.02c3.15-.44 5.22.26 6.44.58.03 0-1.01.5-1.56.87-.55.38-1.97 1.56-4.14 1.59-2.18.03-4.58-.23-4.98-.17l-.97.14" fill="#058e6e" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M250.7 337.28a5.05 5.05 0 0 1 0-7.43 5.05 5.05 0 0 1 0 7.43" fill="#ad1519" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M249.68 342.71s.61-1.52.67-2.83c.06-1.09-.15-2.17-.15-2.17h.8s.4 1.16.4 2.17c0 1.02-.2 2.37-.2 2.37s-.54.08-.72.17c-.19.09-.8.29-.8.29" fill="#058e6e" stroke="#000" stroke-width=".52"/>
|
||||||
|
<path d="M300 198.67c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M300 198.67c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M301.5 196.02c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M301.5 196.02c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M302.5 192.94c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M302.5 192.94c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M302.63 189.64c0-.57.49-1.03 1.1-1.03.6 0 1.09.46 1.09 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.09-.46-1.09-1.04" fill="#fff"/>
|
||||||
|
<path d="M302.63 189.64c0-.57.49-1.03 1.1-1.03.6 0 1.09.46 1.09 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.09-.46-1.09-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M301.82 186.4c0-.58.49-1.04 1.09-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.05-1.1 1.05-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M301.82 186.4c0-.58.49-1.04 1.09-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.05-1.1 1.05-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M300.13 183.45c0-.58.49-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.61 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M300.13 183.45c0-.58.49-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.61 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M297.88 181.03c0-.58.49-1.04 1.1-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.61 0-1.1-.46-1.1-1.03" fill="#fff"/>
|
||||||
|
<path d="M297.88 181.03c0-.58.49-1.04 1.1-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.61 0-1.1-.46-1.1-1.03z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M295.26 179.01c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M295.26 179.01c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M292.14 177.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M292.14 177.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M288.9 176.19c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M288.9 176.19c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M285.28 175.54c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M285.28 175.54c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M281.84 175.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M281.84 175.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M278.47 175.48c0-.57.49-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.61 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M278.47 175.48c0-.57.49-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.61 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M275.1 175.48c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M275.1 175.48c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M276.79 178.37c0-.57.49-1.04 1.09-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04M277.47 181.57c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.03-1.1 1.03-.6 0-1.1-.46-1.1-1.03M277.6 184.75c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04M276.6 187.65c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04M274.73 190.31c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.03" fill="#fff" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M272.54 173.47c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M272.54 173.47c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M269.55 171.81c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M269.55 171.81c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M266.25 170.82c0-.58.49-1.04 1.1-1.04.6 0 1.09.46 1.09 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M266.25 170.82c0-.58.49-1.04 1.1-1.04.6 0 1.09.46 1.09 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M262.81 170.23c0-.57.5-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .57-.49 1.03-1.1 1.03-.6 0-1.09-.46-1.09-1.03" fill="#fff"/>
|
||||||
|
<path d="M262.81 170.23c0-.57.5-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .57-.49 1.03-1.1 1.03-.6 0-1.09-.46-1.09-1.03z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M259.45 170.28c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M259.45 170.28c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M255.95 170.87c0-.57.49-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.61 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M255.95 170.87c0-.57.49-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.61 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M252.7 172c0-.58.5-1.05 1.1-1.05.61 0 1.1.47 1.1 1.04 0 .57-.49 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M252.7 172c0-.58.5-1.05 1.1-1.05.61 0 1.1.47 1.1 1.04 0 .57-.49 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M197.84 198.67c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M197.84 198.67c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M196.34 196.02c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M196.34 196.02c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M195.34 192.94c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M195.34 192.94c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M195.22 189.64c0-.57.49-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.61 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M195.22 189.64c0-.57.49-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.61 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M196.03 186.4c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.05-1.1 1.05-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M196.03 186.4c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.03 0 .58-.5 1.05-1.1 1.05-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M197.71 183.45c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M197.71 183.45c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M199.97 181.03c0-.58.49-1.04 1.1-1.04.6 0 1.09.46 1.09 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.03" fill="#fff"/>
|
||||||
|
<path d="M199.97 181.03c0-.58.49-1.04 1.1-1.04.6 0 1.09.46 1.09 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.03z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M202.58 179.01c0-.57.49-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.61 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M202.58 179.01c0-.57.49-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.61 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M205.7 177.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M205.7 177.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M208.94 176.19c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M208.94 176.19c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M212.57 175.54c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M212.57 175.54c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M216 175.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M216 175.36c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M219.38 175.48c0-.57.49-1.04 1.09-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M219.38 175.48c0-.57.49-1.04 1.09-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M222.75 175.48c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M222.75 175.48c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M221.06 178.37c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04M220.38 181.57c0-.58.48-1.04 1.1-1.04.6 0 1.09.46 1.09 1.04 0 .57-.5 1.03-1.1 1.03-.6 0-1.1-.46-1.1-1.03M220.25 184.75c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04M221.25 187.65c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04M223.11 190.31c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.03" fill="#fff" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M225.3 173.47c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M225.3 173.47c0-.57.5-1.03 1.1-1.03.6 0 1.1.46 1.1 1.03 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M228.3 171.81c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M228.3 171.81c0-.57.5-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M231.6 170.82c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M231.6 170.82c0-.58.5-1.04 1.1-1.04.6 0 1.1.46 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M235.04 170.23c0-.57.49-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.03-1.1 1.03-.61 0-1.1-.46-1.1-1.03" fill="#fff"/>
|
||||||
|
<path d="M235.04 170.23c0-.57.49-1.04 1.1-1.04.6 0 1.1.47 1.1 1.04 0 .57-.5 1.03-1.1 1.03-.61 0-1.1-.46-1.1-1.03z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M238.4 170.28c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.09-.46-1.09-1.04" fill="#fff"/>
|
||||||
|
<path d="M238.4 170.28c0-.57.49-1.04 1.1-1.04.6 0 1.09.47 1.09 1.04 0 .58-.5 1.04-1.1 1.04-.6 0-1.09-.46-1.09-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M241.9 170.87c0-.57.49-1.03 1.1-1.03.6 0 1.09.46 1.09 1.03 0 .58-.49 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M241.9 170.87c0-.57.49-1.03 1.1-1.03.6 0 1.09.46 1.09 1.03 0 .58-.49 1.04-1.1 1.04-.6 0-1.1-.46-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M245.13 172c0-.58.5-1.05 1.1-1.05.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04" fill="#fff"/>
|
||||||
|
<path d="M245.13 172c0-.58.5-1.05 1.1-1.05.6 0 1.1.47 1.1 1.04 0 .57-.5 1.04-1.1 1.04-.6 0-1.1-.47-1.1-1.04z" fill="none" stroke="#000" stroke-width=".39"/>
|
||||||
|
<path d="M217.34 238.41h-.92v-.92h-1.62v3.7h1.62v2.54h-3.47v7.4h1.85v14.78h-3.7v7.63h28.42v-7.63h-3.7v-14.79h1.86v-7.4h-3.47v-2.53h1.62v-3.7h-1.62v.92h-.93v-.92h-1.61v.92h-1.16v-.92h-1.62v3.7h1.62v2.54h-3.46v-8.1h1.84v-3.69h-1.84v.93h-.93v-.93h-1.62v.93h-.92v-.93h-1.85v3.7h1.85v8.09h-3.47v-2.54h1.62v-3.7h-1.62v.92h-.92v-.92h-1.85v.92zm-6.24 35.13h28.42m-28.42-1.85h28.42m-28.42-1.85h28.42m-28.42-1.85h28.42m-28.42-2.08h28.42m-24.72-1.62h21.03m-21.03-1.85h21.03m-21.03-2.08h21.03m-21.03-1.85h21.03m-21.03-1.84h21.03m-21.03-1.85h21.03m-21.03-1.85h21.03m-22.88-1.85h24.73m-24.73-1.85h24.73m-24.73-1.85h24.73m-24.73-1.84h24.73m-21.26-1.85h17.79m-10.63-1.85h3.47m-3.47-1.85h3.47m-3.47-1.85h3.47m-3.47-1.85h3.47m-5.32-2.3h7.16m-12.47 7.85h3.7m-5.32-2.31h6.93m-6.93 33.97v-1.85m0-1.85v-1.85m-1.85 1.85v1.85m3.47 0v-1.85m1.84 3.7v-1.85m0-1.85v-1.85m0-2.08v-1.62m0-1.85v-2.08m-1.84 7.63v-2.08m-3.47 2.08v-2.08m7.16 0v2.08m1.62-2.08v-1.62m-5.31-1.85v1.85m3.7-1.85v1.85m3.46-1.85v1.85m-1.85-1.85v-2.08m1.85-1.85v1.85m0-5.54v1.85m-1.85-3.7v1.85m1.85-3.7v1.85m-3.47-1.85v1.85m-3.7-1.85v1.85m-1.61-3.7v1.85m3.46-1.85v1.85m3.47-1.85v1.85m1.85-3.7v1.85m-3.47-1.85v1.85m-3.7-1.85v1.85m-1.61-3.7v1.85m6.93-1.84v1.84m-3.47-5.54v1.85m15.95-1.85h-3.7m5.32-2.31h-6.94m6.94 33.97v-1.85m0-1.85v-1.85m1.84 1.85v1.85m-3.46 0v-1.85m-1.85 3.7v-1.85m0-1.85v-1.85m0-2.08v-1.62m0-1.85v-2.08m1.85 7.63v-2.08m3.47 2.08v-2.08m-7.17 0v2.08m-1.62-2.08v-1.62m5.32-1.85v1.85m-3.7-1.85v1.85m-3.46-1.85v1.85m1.84-1.85v-2.08m-1.84-1.85v1.85m0-5.54v1.85m1.84-3.7v1.85m-1.84-3.7v1.85m3.46-1.85v1.85m3.7-1.85v1.85m1.62-3.7v1.85m-3.47-1.85v1.85m-3.47-1.85v1.85m-1.84-3.7v1.85m3.46-1.85v1.85m3.7-1.85v1.85m1.62-3.7v1.85m-6.94-1.84v1.84m3.47-5.54v1.85m-7.16 18.71v-2.08m0-5.54v-1.85m0 5.54v-1.84m0-5.55v-1.85m0-1.85v-1.84m0-3.7v-1.85m0-1.85v-1.85m-8.78 4.85h3.7m3.46-5.54h3.47m3.46 5.55h3.7" fill="#c8b100" stroke="#000" stroke-width=".46"/>
|
||||||
|
<path d="M230.05 273.54v-4.86c0-.92-.46-3.7-4.85-3.7-4.16 0-4.62 2.78-4.62 3.7v4.86h9.47z" fill="#c8b100" stroke="#000" stroke-width=".46"/>
|
||||||
|
<path d="M222.2 268.91l-2.32-.23c0-.92.23-2.3.93-2.77l2.08 1.62c-.23.23-.7.92-.7 1.38zM228.43 268.91l2.31-.23c0-.92-.23-2.3-.92-2.77l-2.08 1.62c.23.23.7.92.7 1.38zM226.12 266.6l1.16-2.08a5.52 5.52 0 0 0-2.08-.46c-.46 0-1.39.23-1.85.46l1.15 2.08h1.62zM221.73 260.83v-5.09c0-1.38-.92-2.54-2.54-2.54s-2.54 1.16-2.54 2.54v5.09h5.08zM228.9 260.83v-5.09c0-1.38.92-2.54 2.54-2.54 1.61 0 2.54 1.16 2.54 2.54v5.09h-5.09zM227.05 248.35l.46-4.62h-4.4l.24 4.62h3.7zM230.51 248.35l-.46-4.62h4.62l-.46 4.62h-3.7zM220.11 248.35l.23-4.62h-4.39l.47 4.62h3.7z" fill="#c8b100" stroke="#000" stroke-width=".46"/>
|
||||||
|
<path d="M228.43 273.54v-4.17c0-.69-.46-2.77-3.23-2.77a2.8 2.8 0 0 0-3 2.77v4.17h6.23zM221.27 260.36v-4.39c0-1.15-.7-2.3-2.08-2.3-1.39 0-2.08 1.15-2.08 2.3v4.4h4.16zM229.36 260.36v-4.39c0-1.15.69-2.3 2.08-2.3 1.38 0 2.08 1.15 2.08 2.3v4.4h-4.16z" fill="#0039f0"/>
|
||||||
|
<path d="M234.18 281c0-10.1 7.27-18.29 16.25-18.29s16.26 8.2 16.26 18.3c0 10.1-7.28 18.29-16.26 18.29s-16.25-8.2-16.25-18.3" fill="#ad1519"/>
|
||||||
|
<path d="M234.18 281c0-10.1 7.27-18.29 16.25-18.29s16.26 8.2 16.26 18.3c0 10.1-7.28 18.29-16.26 18.29s-16.25-8.2-16.25-18.3z" fill="none" stroke="#000" stroke-width=".61"/>
|
||||||
|
<path d="M239 280.97c0-7.4 5.12-13.41 11.44-13.41 6.31 0 11.43 6 11.43 13.41s-5.12 13.42-11.43 13.42c-6.32 0-11.44-6-11.44-13.42" fill="#005bbf"/>
|
||||||
|
<path d="M239 280.97c0-7.4 5.12-13.41 11.44-13.41 6.31 0 11.43 6 11.43 13.41s-5.12 13.42-11.43 13.42c-6.32 0-11.44-6-11.44-13.42z" fill="none" stroke="#000" stroke-width=".61"/>
|
||||||
|
<path d="M245.03 271.74s-1.35 1.49-1.35 2.86c0 1.39.57 2.54.57 2.54a1.5 1.5 0 0 0-1.41-.94c-.83 0-1.5.63-1.5 1.42 0 .22.14.58.24.77l.5.99c.15-.37.53-.57.97-.57.6 0 1.08.45 1.08 1.01 0 .09-.01.17-.04.25h-1.22v1.04h1.1l-.82 1.6 1.07-.41.81.91.84-.91 1.07.42-.8-1.6h1.08v-1.05H246a1.04 1.04 0 0 1 1.04-1.26c.44 0 .82.2.99.57l.48-.99c.1-.2.24-.55.24-.77 0-.79-.66-1.42-1.5-1.42-.65 0-1.2.4-1.4.94 0 0 .57-1.15.57-2.54 0-1.38-1.39-2.86-1.39-2.86" fill="#c8b100"/>
|
||||||
|
<path d="M245.03 271.74s-1.35 1.49-1.35 2.86c0 1.39.57 2.54.57 2.54a1.5 1.5 0 0 0-1.41-.94c-.83 0-1.5.63-1.5 1.42 0 .22.14.58.24.77l.5.99c.15-.37.53-.57.97-.57.6 0 1.08.45 1.08 1.01 0 .09-.01.17-.04.25h-1.22v1.04h1.1l-.82 1.6 1.07-.41.81.91.84-.91 1.07.42-.8-1.6h1.08v-1.05H246a1.04 1.04 0 0 1 1.04-1.26c.44 0 .82.2.99.57l.48-.99c.1-.2.24-.55.24-.77 0-.79-.66-1.42-1.5-1.42-.65 0-1.2.4-1.4.94 0 0 .57-1.15.57-2.54 0-1.38-1.39-2.86-1.39-2.86z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".34"/>
|
||||||
|
<path d="M242.87 281.11h4.36v-1.04h-4.36v1.04z" fill="#c8b100"/>
|
||||||
|
<path d="M242.87 281.11h4.36v-1.04h-4.36v1.04z" fill="none" stroke="#000" stroke-width=".34"/>
|
||||||
|
<path d="M255.66 271.74s-1.35 1.49-1.35 2.86c0 1.39.57 2.54.57 2.54a1.5 1.5 0 0 0-1.41-.94c-.83 0-1.5.63-1.5 1.42 0 .22.14.58.24.77l.49.99c.16-.37.54-.57.98-.57.6 0 1.07.45 1.07 1.01 0 .09 0 .17-.03.25h-1.22v1.04h1.1l-.82 1.6 1.07-.41.81.91.84-.91 1.07.42-.8-1.6h1.08v-1.05h-1.22a.88.88 0 0 1-.03-.25c0-.56.48-1 1.07-1 .44 0 .82.2.98.56l.49-.99c.1-.2.24-.55.24-.77 0-.79-.67-1.42-1.5-1.42-.64 0-1.2.4-1.4.94 0 0 .57-1.15.57-2.54 0-1.38-1.39-2.86-1.39-2.86" fill="#c8b100"/>
|
||||||
|
<path d="M255.66 271.74s-1.35 1.49-1.35 2.86c0 1.39.57 2.54.57 2.54a1.5 1.5 0 0 0-1.41-.94c-.83 0-1.5.63-1.5 1.42 0 .22.14.58.24.77l.49.99c.16-.37.54-.57.98-.57.6 0 1.07.45 1.07 1.01 0 .09 0 .17-.03.25h-1.22v1.04h1.1l-.82 1.6 1.07-.41.81.91.84-.91 1.07.42-.8-1.6h1.08v-1.05h-1.22a.88.88 0 0 1-.03-.25c0-.56.48-1 1.07-1 .44 0 .82.2.98.56l.49-.99c.1-.2.24-.55.24-.77 0-.79-.67-1.42-1.5-1.42-.64 0-1.2.4-1.4.94 0 0 .57-1.15.57-2.54 0-1.38-1.39-2.86-1.39-2.86z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".34"/>
|
||||||
|
<path d="M253.5 281.11h4.35v-1.04h-4.35v1.04z" fill="#c8b100"/>
|
||||||
|
<path d="M253.5 281.11h4.35v-1.04h-4.35v1.04z" fill="none" stroke="#000" stroke-width=".34"/>
|
||||||
|
<path d="M250.35 280.88s-1.36 1.49-1.36 2.87c0 1.38.57 2.53.57 2.53a1.5 1.5 0 0 0-1.41-.94c-.83 0-1.5.63-1.5 1.42 0 .23.14.58.25.78l.48.98c.17-.36.54-.57.99-.57.59 0 1.07.45 1.07 1.02a.9.9 0 0 1-.03.25h-1.22v1.04h1.09l-.81 1.6 1.07-.42.8.91.85-.9 1.07.41-.81-1.6h1.09v-1.04h-1.22a.94.94 0 0 1-.03-.25c0-.57.47-1.02 1.07-1.02.44 0 .81.2.98.57l.49-.98c.1-.2.24-.55.24-.78 0-.79-.67-1.42-1.5-1.42-.65 0-1.2.4-1.41.94 0 0 .57-1.15.57-2.53s-1.39-2.87-1.39-2.87" fill="#c8b100"/>
|
||||||
|
<path d="M250.35 280.88s-1.36 1.49-1.36 2.87c0 1.38.57 2.53.57 2.53a1.5 1.5 0 0 0-1.41-.94c-.83 0-1.5.63-1.5 1.42 0 .23.14.58.25.78l.48.98c.17-.36.54-.57.99-.57.59 0 1.07.45 1.07 1.02a.9.9 0 0 1-.03.25h-1.22v1.04h1.09l-.81 1.6 1.07-.42.8.91.85-.9 1.07.41-.81-1.6h1.09v-1.04h-1.22a.94.94 0 0 1-.03-.25c0-.57.47-1.02 1.07-1.02.44 0 .81.2.98.57l.49-.98c.1-.2.24-.55.24-.78 0-.79-.67-1.42-1.5-1.42-.65 0-1.2.4-1.41.94 0 0 .57-1.15.57-2.53s-1.39-2.87-1.39-2.87z" fill="none" stroke="#000" stroke-linejoin="round" stroke-width=".34"/>
|
||||||
|
<path d="M248.19 290.26h4.35v-1.04h-4.35v1.04z" fill="#c8b100"/>
|
||||||
|
<path d="M248.19 290.26h4.35v-1.04h-4.35v1.04z" fill="none" stroke="#000" stroke-width=".34"/>
|
||||||
|
<path d="M282.88 232.7l-.29.03c-.01.03-.14.24-.26.35-.26.25-.64.27-.86.07a.5.5 0 0 1-.14-.4.52.52 0 0 1-.51-.02c-.26-.14-.32-.5-.14-.8.03-.05.06-.13.1-.17l-.01-.32-.35.08-.1.2c-.22.24-.54.3-.7.16a.58.58 0 0 1-.13-.27c0 .01-.09.09-.18.1-.53.14-.74-1.04-.76-1.34l-.17.25s.16.7.08 1.3c-.08.6-.3 1.2-.3 1.2.75.18 1.87.79 2.98 1.64a9.39 9.39 0 0 1 2.35 2.42s.57-.32 1.17-.5c.6-.2 1.36-.2 1.36-.2l.22-.22c-.32.05-1.59.1-1.56-.43 0-.08.07-.18.08-.18 0 .01-.21 0-.3-.06-.18-.13-.18-.43.02-.69l.18-.13.01-.34-.34.05c-.03.04-.1.09-.15.13-.27.23-.65.25-.86.03a.44.44 0 0 1-.11-.46.57.57 0 0 1-.45-.05c-.26-.15-.31-.52-.11-.8.1-.14.28-.3.3-.32l-.06-.3" fill="#c8b100"/>
|
||||||
|
<path d="M282.88 232.7l-.29.03c-.01.03-.14.24-.26.35-.26.25-.64.27-.86.07a.5.5 0 0 1-.14-.4.52.52 0 0 1-.51-.02c-.26-.14-.32-.5-.14-.8.03-.05.06-.13.1-.17l-.01-.32-.35.08-.1.2c-.22.24-.54.3-.7.16a.58.58 0 0 1-.13-.27c0 .01-.09.09-.18.1-.53.14-.74-1.04-.76-1.34l-.17.25s.16.7.08 1.3c-.08.6-.3 1.2-.3 1.2.75.18 1.87.79 2.98 1.64a9.39 9.39 0 0 1 2.35 2.42s.57-.32 1.17-.5c.6-.2 1.36-.2 1.36-.2l.22-.22c-.32.05-1.59.1-1.56-.43 0-.08.07-.18.08-.18 0 .01-.21 0-.3-.06-.18-.13-.18-.43.02-.69l.18-.13.01-.34-.34.05c-.03.04-.1.09-.15.13-.27.23-.65.25-.86.03a.44.44 0 0 1-.11-.46.57.57 0 0 1-.45-.05c-.26-.15-.31-.52-.11-.8.1-.14.28-.3.3-.32l-.06-.3z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M280.63 233.4c.05-.07.16-.06.23 0 .08.06.1.16.06.21-.05.06-.15.06-.24 0-.07-.06-.1-.16-.05-.22"/>
|
||||||
|
<path d="M280.63 233.4c.05-.07.16-.06.23 0 .08.06.1.16.06.21-.05.06-.15.06-.24 0-.07-.06-.1-.16-.05-.22z" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M281.58 234.2l-.33-.26c-.06-.04-.07-.12-.04-.16.04-.04.12-.04.18 0l.32.26.34.25c.06.04.08.12.04.16-.04.04-.12.04-.18 0l-.33-.26"/>
|
||||||
|
<path d="M281.58 234.2l-.33-.26c-.06-.04-.07-.12-.04-.16.04-.04.12-.04.18 0l.32.26.34.25c.06.04.08.12.04.16-.04.04-.12.04-.18 0l-.33-.26" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M279.84 233l-.26-.15c-.07-.04-.1-.12-.07-.16.03-.06.1-.07.17-.03l.26.16.26.15c.06.03.1.1.07.16-.03.05-.1.06-.17.02l-.26-.15"/>
|
||||||
|
<path d="M279.84 233l-.26-.15c-.07-.04-.1-.12-.07-.16.03-.06.1-.07.17-.03l.26.16.26.15c.06.03.1.1.07.16-.03.05-.1.06-.17.02l-.26-.15" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M278.8 232.29c.05-.06.16-.06.24 0 .08.06.1.16.05.22-.05.05-.15.05-.23 0-.08-.07-.1-.16-.06-.22"/>
|
||||||
|
<path d="M278.8 232.29c.05-.06.16-.06.24 0 .08.06.1.16.05.22-.05.05-.15.05-.23 0-.08-.07-.1-.16-.06-.22z" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M282.63 234.93c.05-.06.02-.15-.05-.22-.08-.06-.19-.06-.23 0-.05.05-.03.15.05.21s.18.06.23 0"/>
|
||||||
|
<path d="M282.63 234.93c.05-.06.02-.15-.05-.22-.08-.06-.19-.06-.23 0-.05.05-.03.15.05.21s.18.06.23 0z" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M283.2 235.58l.22.2c.05.06.13.08.18.04.04-.04.04-.11-.01-.16l-.21-.2-.22-.22c-.05-.05-.14-.07-.18-.03-.05.03-.04.11.01.16l.21.21"/>
|
||||||
|
<path d="M283.2 235.58l.22.2c.05.06.13.08.18.04.04-.04.04-.11-.01-.16l-.21-.2-.22-.22c-.05-.05-.14-.07-.18-.03-.05.03-.04.11.01.16l.21.21" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M284.15 236.4c.05-.07.03-.16-.05-.22-.08-.07-.18-.07-.23 0-.05.05-.03.14.05.2s.18.07.23.01"/>
|
||||||
|
<path d="M284.15 236.4c.05-.07.03-.16-.05-.22-.08-.07-.18-.07-.23 0-.05.05-.03.14.05.2s.18.07.23.01z" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M281.4 230.35l-.59.02-.11.87.06.14h.15l.76-.52-.27-.5" fill="#c8b100"/>
|
||||||
|
<path d="M281.4 230.35l-.59.02-.11.87.06.14h.15l.76-.52-.27-.5" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M279.8 230.84l-.02.54.92.12.15-.07-.02-.15-.53-.7-.5.26" fill="#c8b100"/>
|
||||||
|
<path d="M279.8 230.84l-.02.54.92.12.15-.07-.02-.15-.53-.7-.5.26" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M281.7 231.92l-.5.27-.53-.71v-.15l.13-.06.93.11-.03.54" fill="#c8b100"/>
|
||||||
|
<path d="M281.7 231.92l-.5.27-.53-.71v-.15l.13-.06.93.11-.03.54" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M280.51 231.25a.3.3 0 0 1 .4-.1c.13.08.17.25.1.38a.3.3 0 0 1-.4.1.27.27 0 0 1-.1-.38" fill="#c8b100"/>
|
||||||
|
<path d="M280.51 231.25a.3.3 0 0 1 .4-.1c.13.08.17.25.1.38a.3.3 0 0 1-.4.1.27.27 0 0 1-.1-.38z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M278.36 230.35c-.01 0-.13-.46-.26-.71-.08-.19-.39-.43-.39-.43.03-.06.42-.2.87.1.38.3-.03.86-.03.86s-.1.14-.19.18" fill="#c8b100"/>
|
||||||
|
<path d="M278.36 230.35c-.01 0-.13-.46-.26-.71-.08-.19-.39-.43-.39-.43.03-.06.42-.2.87.1.38.3-.03.86-.03.86s-.1.14-.19.18z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M279.4 230.66l-.43.37-.68-.6.06-.08.02-.15.93-.07.1.53" fill="#c8b100"/>
|
||||||
|
<path d="M279.4 230.66l-.43.37-.68-.6.06-.08.02-.15.93-.07.1.53" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M278.24 230.3c.05-.16.18-.24.28-.21.1.04.15.18.1.33-.05.15-.18.23-.29.2-.1-.03-.15-.18-.1-.33" fill="#c8b100"/>
|
||||||
|
<path d="M278.24 230.3c.05-.16.18-.24.28-.21.1.04.15.18.1.33-.05.15-.18.23-.29.2-.1-.03-.15-.18-.1-.33z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M283.67 231.77l-.6-.06-.24.85.05.14h.15l.83-.4-.2-.53" fill="#c8b100"/>
|
||||||
|
<path d="M283.67 231.77l-.6-.06-.24.85.05.14h.15l.83-.4-.2-.53" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M282 232.03l-.09.54.9.24.15-.05v-.14l-.42-.79-.53.2" fill="#c8b100"/>
|
||||||
|
<path d="M282 232.03l-.09.54.9.24.15-.05v-.14l-.42-.79-.53.2" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M283.73 233.35l-.53.22-.42-.79.01-.15.15-.03.9.23-.1.52" fill="#c8b100"/>
|
||||||
|
<path d="M283.73 233.35l-.53.22-.42-.79.01-.15.15-.03.9.23-.1.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M282.65 232.54c.1-.12.28-.13.4-.04.13.1.15.26.05.38a.3.3 0 0 1-.4.04.26.26 0 0 1-.05-.38" fill="#c8b100"/>
|
||||||
|
<path d="M282.65 232.54c.1-.12.28-.13.4-.04.13.1.15.26.05.38a.3.3 0 0 1-.4.04.26.26 0 0 1-.05-.38z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M285.64 233.6l.11.56-.87.3-.15-.03-.02-.15.36-.8.57.13" fill="#c8b100"/>
|
||||||
|
<path d="M285.64 233.6l.11.56-.87.3-.15-.03-.02-.15.36-.8.57.13" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M285.49 235.2l-.56.13-.31-.84.03-.14.16-.02.85.35-.17.52" fill="#c8b100"/>
|
||||||
|
<path d="M285.49 235.2l-.56.13-.31-.84.03-.14.16-.02.85.35-.17.52" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M283.97 233.66l-.18.52.85.34.16-.02.03-.14-.3-.83-.56.13" fill="#c8b100"/>
|
||||||
|
<path d="M283.97 233.66l-.18.52.85.34.16-.02.03-.14-.3-.83-.56.13" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M284.91 234.63c.12-.11.12-.28.02-.4a.31.31 0 0 0-.41 0 .27.27 0 0 0-.01.38c.1.11.29.12.4.02" fill="#c8b100"/>
|
||||||
|
<path d="M284.91 234.63c.12-.11.12-.28.02-.4a.31.31 0 0 0-.41 0 .27.27 0 0 0-.01.38c.1.11.29.12.4.02z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M286.29 236.43c0 .01.5.03.79.09.2.04.52.27.52.27.06-.04.11-.42-.28-.78-.4-.29-.88.2-.88.2s-.12.13-.15.22" fill="#c8b100"/>
|
||||||
|
<path d="M286.29 236.43c0 .01.5.03.79.09.2.04.52.27.52.27.06-.04.11-.42-.28-.78-.4-.29-.88.2-.88.2s-.12.13-.15.22z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M285.75 235.53l-.29.47.76.51.1-.08.12-.04-.12-.88-.57.03" fill="#c8b100"/>
|
||||||
|
<path d="M285.75 235.53l-.29.47.76.51.1-.08.12-.04-.12-.88-.57.03" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M286.37 236.53c.14-.07.2-.22.15-.3-.06-.1-.22-.1-.36-.03-.14.08-.2.22-.14.31.05.1.21.1.35.02" fill="#c8b100"/>
|
||||||
|
<path d="M286.37 236.53c.14-.07.2-.22.15-.3-.06-.1-.22-.1-.36-.03-.14.08-.2.22-.14.31.05.1.21.1.35.02z" fill="none" stroke="#000" stroke-width=".26"/>
|
||||||
|
<path d="M326.13 213.64v.58h-2.53v-.58h.94v-1.3h-.62v-.59h.62v-.57h.6v.57h.62v.59h-.61v1.3h.98" fill="none" stroke="#000" stroke-width=".3"/>
|
||||||
|
<path d="M175.44 226.15v-1.27" fill="none" stroke="#000" stroke-width=".02"/>
|
||||||
|
<path d="M175.1 226.15v-1.27" fill="none" stroke="#000" stroke-width=".03"/>
|
||||||
|
<path d="M174.77 226.15v-1.27M174.44 226.15v-1.27" fill="none" stroke="#000" stroke-width=".04"/>
|
||||||
|
<path d="M174.16 226.15v-1.27" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M173.6 226.08v-1.15m.27 1.17v-1.21" fill="none" stroke="#000" stroke-width=".06"/>
|
||||||
|
<path d="M173.1 226.03v-1.06m.26 1.09v-1.13" fill="none" stroke="#000" stroke-width=".07"/>
|
||||||
|
<path d="M172.43 225.97v-.94m.22.95v-.97m.23 1V225" fill="none" stroke="#000" stroke-width=".08"/>
|
||||||
|
<path d="M172.19 225.96v-.9" fill="none" stroke="#000" stroke-width=".09"/>
|
||||||
|
<path d="M171.97 225.92v-.85" fill="none" stroke="#000" stroke-width=".1"/>
|
||||||
|
<path d="M171.73 225.9v-.79" fill="none" stroke="#000" stroke-width=".11"/>
|
||||||
|
<path d="M171.24 225.82v-.62m.25.66v-.7M171 225.77v-.55" fill="none" stroke="#000" stroke-width=".12"/>
|
||||||
|
<path d="M170.76 225.73v-.46" fill="none" stroke="#000" stroke-width=".13"/>
|
||||||
|
<path d="M170.51 225.67v-.36" fill="none" stroke="#000" stroke-width=".14"/>
|
||||||
|
<path d="M170.26 225.64v-.27" fill="none" stroke="#000" stroke-width=".15"/>
|
||||||
|
<path d="M169.99 225.58v-.13" fill="none" stroke="#000" stroke-width=".18"/>
|
||||||
|
<path d="M176.8 226.08v-1.16m-.58 1.2v-1.23m-.42 1.25v-1.26" fill="none" stroke="#000" stroke-width=".01"/>
|
||||||
|
<path d="M324.77 226.17v-1.27" fill="none" stroke="#000" stroke-width=".02"/>
|
||||||
|
<path d="M324.42 226.17v-1.27" fill="none" stroke="#000" stroke-width=".03"/>
|
||||||
|
<path d="M324.1 226.17v-1.27M323.78 226.17v-1.27" fill="none" stroke="#000" stroke-width=".04"/>
|
||||||
|
<path d="M323.49 226.17v-1.27" fill="none" stroke="#000" stroke-width=".05"/>
|
||||||
|
<path d="M322.94 226.1v-1.15m.26 1.17v-1.2" fill="none" stroke="#000" stroke-width=".06"/>
|
||||||
|
<path d="M322.44 226.05V225m.25 1.1v-1.14" fill="none" stroke="#000" stroke-width=".07"/>
|
||||||
|
<path d="M321.76 226v-.94m.22.95v-.98m.23 1v-1.01" fill="none" stroke="#000" stroke-width=".08"/>
|
||||||
|
<path d="M321.52 225.98v-.9" fill="none" stroke="#000" stroke-width=".09"/>
|
||||||
|
<path d="M321.3 225.94v-.84" fill="none" stroke="#000" stroke-width=".1"/>
|
||||||
|
<path d="M321.06 225.91v-.78" fill="none" stroke="#000" stroke-width=".11"/>
|
||||||
|
<path d="M320.57 225.85v-.63m.25.66v-.7M320.32 225.8v-.55" fill="none" stroke="#000" stroke-width=".12"/>
|
||||||
|
<path d="M320.1 225.75v-.46" fill="none" stroke="#000" stroke-width=".13"/>
|
||||||
|
<path d="M319.85 225.69v-.36" fill="none" stroke="#000" stroke-width=".14"/>
|
||||||
|
<path d="M319.6 225.66v-.27" fill="none" stroke="#000" stroke-width=".15"/>
|
||||||
|
<path d="M319.32 225.6v-.13" fill="none" stroke="#000" stroke-width=".18"/>
|
||||||
|
<path d="M326.14 226.1v-1.16m-.58 1.2v-1.23m-.43 1.25v-1.26" fill="none" stroke="#000" stroke-width=".01"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 119 KiB |
1
public/crests/761.svg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/crests/762.svg
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
6
public/crests/763.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 450 300">
|
||||||
|
<rect width="450" height="300" fill="#006b3f"/>
|
||||||
|
<rect width="450" height="200" fill="#fcd116"/>
|
||||||
|
<rect width="450" height="100" fill="#ce1126"/>
|
||||||
|
<path d="M225,100 257.492,200 172.427,138.197H277.573L192.508,200z" fill="#000"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 296 B |
1
public/crests/764.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-2100 -1470 4200 2940"><defs><path id="i" fill-rule="evenodd" d="M-31.5 0h33a30 30 0 0030-30v-10a30 30 0 00-30-30h-33zm13-13h19a19 19 0 0019-19v-6a19 19 0 00-19-19h-19z"/><path id="n" d="M-15.75-22C-15.75-15-9-11.5 1-11.5s14.74-3.25 14.75-7.75c0-14.25-46.75-5.25-46.5-30.25C-30.5-71-6-70 3-70s26 4 25.75 21.25H13.5c0-7.5-7-10.25-15-10.25-7.75 0-13.25 1.25-13.25 8.5-.25 11.75 46.25 4 46.25 28.75C31.5-3.5 13.5 0 0 0c-11.5 0-31.55-4.5-31.5-22z"/><path id="l" d="M-26.25 0h52.5v-12h-40.5v-16h33v-12h-33v-11H25v-12h-51.25z"/><path id="k" d="M-31.5 0h12v-48l14 48h11l14-48V0h12v-70H14L0-22l-14-48h-17.5z"/><path id="d" fill-rule="evenodd" d="M0 0a31.5 35 0 000-70A31.5 35 0 000 0m0-13a18.5 22 0 000-44 18.5 22 0 000 44"/><path id="f" fill-rule="evenodd" d="M-31.5 0h13v-26h28a22 22 0 000-44h-40zm13-39h27a9 9 0 000-18h-27z"/><path id="j" transform="translate(-31.5)" d="M0 0h63v-13H12v-18h40v-12H12v-14h48v-13H0z"/><use id="q" xlink:href="#a" transform="scale(15)"/><use id="s" xlink:href="#a" transform="scale(10.5)"/><use id="r" xlink:href="#a" transform="scale(21)"/><use id="o" xlink:href="#a" transform="scale(31.5)"/><use id="p" xlink:href="#a" transform="scale(26.25)"/><g id="a" fill="#fff"><g id="c"><path id="b" transform="rotate(18 0 -1)" d="M0-1v1h.5"/><use xlink:href="#b" transform="scale(-1 1)"/></g><use xlink:href="#c" transform="rotate(72)"/><use xlink:href="#c" transform="rotate(-72)"/><use xlink:href="#c" transform="rotate(144)"/><use xlink:href="#c" transform="rotate(216)"/></g><g id="m"><clipPath id="e"><path d="M-31.5 0v-70h63V0zM0-47v12h31.5v-12z"/></clipPath><use xlink:href="#d" clip-path="url(#e)"/><path d="M5-35h26.5v10H5z"/><path d="M21.5-35h10V0h-10z"/></g><g id="h"><use xlink:href="#f"/><path d="M28 0c0-10 0-32-15-32H-6c22 0 22 22 22 32"/></g></defs><rect y="-50%" x="-50%" height="100%" fill="#009b3a" width="100%"/><path d="M-1743 0L0 1113 1743 0 0-1113z" fill="#fedf00"/><circle r="735" fill="#002776"/><clipPath id="g"><circle r="735"/></clipPath><path fill="#fff" d="M-2205 1470a1785 1785 0 013570 0h-105a1680 1680 0 10-3360 0z" clip-path="url(#g)"/><g transform="translate(-420 1470)" fill="#009b3a"><use y="-1697.5" xlink:href="#d" transform="rotate(-7)"/><use y="-1697.5" xlink:href="#h" transform="rotate(-4)"/><use y="-1697.5" xlink:href="#i" transform="rotate(-1)"/><use y="-1697.5" xlink:href="#j" transform="rotate(2)"/><use y="-1697.5" xlink:href="#k" transform="rotate(5)"/><use y="-1697.5" xlink:href="#l" transform="rotate(9.75)"/><use y="-1697.5" xlink:href="#f" transform="rotate(14.5)"/><use y="-1697.5" xlink:href="#h" transform="rotate(17.5)"/><use y="-1697.5" xlink:href="#d" transform="rotate(20.5)"/><use y="-1697.5" xlink:href="#m" transform="rotate(23.5)"/><use y="-1697.5" xlink:href="#h" transform="rotate(26.5)"/><use y="-1697.5" xlink:href="#j" transform="rotate(29.5)"/><use y="-1697.5" xlink:href="#n" transform="rotate(32.5)"/><use y="-1697.5" xlink:href="#n" transform="rotate(35.5)"/><use y="-1697.5" xlink:href="#d" transform="rotate(38.5)"/></g><use y="-132" x="-600" xlink:href="#o"/><use y="177" x="-535" xlink:href="#o"/><use y="243" x="-625" xlink:href="#p"/><use y="132" x="-463" xlink:href="#q"/><use y="250" x="-382" xlink:href="#p"/><use y="323" x="-404" xlink:href="#r"/><use y="-228" x="228" xlink:href="#o"/><use y="258" x="515" xlink:href="#o"/><use y="265" x="617" xlink:href="#r"/><use y="323" x="545" xlink:href="#p"/><use y="477" x="368" xlink:href="#p"/><use y="551" x="367" xlink:href="#r"/><use y="419" x="441" xlink:href="#r"/><use y="382" x="500" xlink:href="#p"/><use y="405" x="365" xlink:href="#r"/><use y="30" x="-280" xlink:href="#p"/><use y="-37" x="200" xlink:href="#r"/><use y="330" xlink:href="#o"/><use y="184" x="85" xlink:href="#p"/><use y="118" xlink:href="#p"/><use y="184" x="-74" xlink:href="#r"/><use y="235" x="-37" xlink:href="#q"/><use y="495" x="220" xlink:href="#p"/><use y="430" x="283" xlink:href="#r"/><use y="412" x="162" xlink:href="#r"/><use y="390" x="-295" xlink:href="#o"/><use y="575" xlink:href="#s"/></svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
66
public/crests/765.svg
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 600 400">
|
||||||
|
<rect width="600" height="400" fill="#f00"/>
|
||||||
|
<rect width="240" height="400" fill="#060"/>
|
||||||
|
<g fill="#ff0" fill-rule="evenodd" stroke="#000" stroke-width="0.573" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="m318.24,262.04c-30.21-0.91-168.74-87.38-169.69-101.15l7.6496-12.757c13.741,19.966,155.36,104.06,169.27,101.08l-7.2299,12.823"/>
|
||||||
|
<path d="m154.59,146.4c-2.7101,7.2937,36.149,31.318,82.903,59.754,46.752,28.434,87.065,46.006,90.053,43.486,0.18256-0.32544,1.4701-2.5409,1.352-2.5232-0.56001,0.84402-1.9234,1.1104-4.0506,0.49741-12.631-3.6433-45.575-18.765-86.374-43.506-40.798-24.743-76.294-47.544-81.811-57.232-0.38363-0.67116-0.65702-1.8962-0.60146-2.8487l-0.13405-0.002-1.1747,2.0532-0.16139,0.32191h-0.00088zm164.36,116.04c-0.51238,0.92957-1.4675,0.96044-3.2816,0.76112-11.3-1.2506-45.589-17.925-86.162-42.213-47.21-28.26-86.2-54.01-81.97-60.74l1.1509-2.0346,0.22665,0.0706c-3.8037,11.405,76.948,57.578,81.702,60.522,46.724,28.947,86.115,45.851,89.601,41.458l-1.2682,2.181v-0.002z"/>
|
||||||
|
<path d="m240.17,169.23c30.237-0.23901,67.55-4.1319,89.023-12.69l-4.6265-7.5168c-12.692,7.0247-50.21,11.644-84.652,12.335-40.736-0.37483-69.49-4.1681-83.897-13.835l-4.3672,8.0045c26.484,11.207,53.623,13.587,88.52,13.703"/>
|
||||||
|
<path d="m330.44,156.71c-0.73904,1.1818-14.743,6.0113-35.373,9.5753-13.988,2.1325-32.234,3.9555-55.004,3.9776-21.633,0.0203-39.305-1.5196-52.684-3.3329-21.656-3.3955-32.833-8.1201-36.965-9.7896,0.39509-0.78581,0.64908-1.337,1.0301-2.0708,11.895,4.736,23.124,7.5918,36.279,9.6158,13.291,1.8,30.75,3.362,52.276,3.3417,22.664-0.0229,40.709-1.9844,54.616-4.0534,21.155-3.4122,32.711-7.8034,34.334-9.8425l1.494,2.5788h-0.002zm-4.0603-7.6226c-2.293,1.8415-13.718,5.8932-33.819,9.1034-13.415,1.9226-30.472,3.6433-52.265,3.6645-20.704,0.0203-37.619-1.375-50.485-3.2491-20.414-2.6661-31.279-7.4754-35.196-8.8776,0.3898-0.67381,0.78666-1.3423,1.1941-2.0135,3.0479,1.5346,13.533,5.7909,34.226,8.7224,12.72,1.8036,29.661,3.1477,50.262,3.1265,21.69-0.0221,38.553-1.7762,51.883-3.6883,20.205-2.7799,31.077-7.9472,32.728-9.241l1.4728,2.4509v0.002z"/>
|
||||||
|
<path d="m140.88,205.66c18.598,10.003,59.905,15.044,98.994,15.391,35.591,0.0564,81.958-5.5016,99.297-14.69l-0.47712-10.012c-5.4246,8.4773-55.113,16.609-99.206,16.276-44.093-0.3325-85.038-7.1429-98.687-15.959l0.0794,8.9914"/>
|
||||||
|
<path d="m340.12,204.22,0.00088,2.3874c-2.606,3.1159-18.946,7.8255-39.437,11.142-15.595,2.391-35.927,4.1945-61.262,4.1945-24.069,0-43.263-1.7163-58.148-4.0014-23.529-3.4264-38.579-9.4262-41.6-11.217l0.0132-2.7852c9.0748,6.0334,33.661,10.447,41.917,11.798,14.788,2.2701,33.868,3.9732,57.817,3.9732,25.216,0,45.434-1.7912,60.931-4.1663,14.701-2.1237,35.644-7.6465,39.767-11.324h0.00088zm0.01-8.4922,0.00088,2.3874c-2.606,3.1142-18.946,7.8237-39.437,11.14-15.595,2.391-35.927,4.1945-61.262,4.1945-24.069,0-43.263-1.7145-58.148-4.0014-23.529-3.4246-38.579-9.4245-41.6-11.216l0.0132-2.7852c9.0748,6.0325,33.661,10.447,41.917,11.796,14.788,2.2719,33.868,3.9758,57.817,3.9758,25.216,0,45.434-1.7921,60.931-4.169,14.701-2.1237,35.644-7.6465,39.767-11.324l0.00088,0.002z"/>
|
||||||
|
<path d="m239.79,260.32c-42.772-0.25489-79.421-11.659-87.16-13.544l5.6433,8.8344c13.67,5.7503,49.424,14.32,81.927,13.371,32.504-0.94809,60.91-3.466,80.928-13.211l5.7862-9.1555c-13.642,6.425-60.068,13.639-87.125,13.705"/>
|
||||||
|
<path stroke-width="0.55" d="m323.3,253.72c-0.85016,1.2991-1.7171,2.5823-2.5963,3.8294-9.4417,3.3293-24.319,6.8245-30.597,7.844-12.824,2.6423-32.665,4.594-50.274,4.6029-37.89-0.55474-68.905-7.9719-83.496-14.299l-1.1773-2.0241,0.19225-0.30427,1.9966,0.77435c25.948,9.2834,55.091,12.987,82.698,13.652,17.538,0.0617,35.095-2.01,49.292-4.5491,21.771-4.3621,30.574-7.65,33.275-9.1405l0.68701-0.38541h-0.00088zm5.0172-8.2753c0.022,0.0256,0.0441,0.0503,0.0653,0.0776-0.63585,1.0733-1.2911,2.1652-1.9622,3.2623-5.0357,1.8-18.702,5.7988-38.659,8.5893-13.149,1.7912-21.322,3.526-47.479,4.034-49.015-1.2471-80.75-10.831-88.289-13.195l-1.1174-2.1431c28.406,7.4154,57.422,12.592,89.408,13.121,23.931-0.50976,34.112-2.2719,47.152-4.0499,23.271-3.6186,34.996-7.4498,38.515-8.5558-0.0441-0.0635-0.0961-0.13053-0.15433-0.19932l2.5231-0.9428-0.002,0.002z"/>
|
||||||
|
<path d="m328.83,197.76c0.13873,28.137-14.26,53.386-25.858,64.525-16.408,15.759-38.163,25.896-63.569,26.363-28.37,0.52117-55.12-17.974-62.295-26.099-14.028-15.885-25.449-36.057-25.815-63.243,1.7376-30.709,13.793-52.1,31.268-66.769s40.743-21.813,60.121-21.302c22.358,0.59003,48.475,11.558,66.521,33.332,11.823,14.266,16.943,29.748,19.627,53.193zm-89.186-96.342c54.485,0,99.296,44.338,99.296,98.703,0,54.364-44.811,98.704-99.296,98.704s-98.924-44.339-98.924-98.704,44.439-98.703,98.924-98.703"/>
|
||||||
|
<path d="m239.91,101.08c54.534,0,99.011,44.483,99.011,99.022,0,54.538-44.478,99.02-99.011,99.02-54.534,0-99.011-44.481-99.011-99.02s44.478-99.022,99.011-99.022zm-96.832,99.0224c0,53.26,43.736,96.842,96.832,96.842,53.097,0,96.833-43.582,96.833-96.842,0-53.262-43.737-96.844-96.833-96.844s-96.832,43.584-96.832,96.844z"/>
|
||||||
|
<path d="m239.99,109.31c49.731,0,90.693,40.821,90.693,90.704,0,49.884-40.963,90.703-90.693,90.703s-90.693-40.819-90.693-90.703c0-49.883,40.964-90.704,90.693-90.704zm-88.515,90.7034c0,48.685,39.979,88.524,88.515,88.524s88.515-39.839,88.515-88.524c0-48.686-39.978-88.525-88.515-88.525-48.536,0-88.515,39.839-88.515,88.525z"/>
|
||||||
|
<path d="m243.98,100.68-8.48545,0,0.01,198.96,8.51455,0z"/>
|
||||||
|
<path d="m243.13,99.546h2.1598l0.0185,201.25h-2.1616l-0.0159-201.25zm-8.4213,0.0018h2.1766l0.003,201.25h-2.1783v-201.25z"/>
|
||||||
|
<path d="m338.99,203.935,0-7.3554-5.99-5.58-34-9-49-5-59,3-42,10-8.48,6.28,0,7.3572l21.48-9.637,51-8h49l36,4,25,6z"/>
|
||||||
|
<path d="m239.95,184.77c23.383-0.0432,46.07,2.2154,64.065,5.7194,18.569,3.7121,31.637,8.3556,36.105,13.571l-0.005,2.5823c-5.3884-6.4902-22.973-11.248-36.518-13.968-17.858-3.474-40.393-5.7168-63.647-5.6736-24.538,0.0459-47.387,2.3698-64.984,5.8032-14.12,2.8019-32.951,8.3679-35.302,13.858v-2.689c1.2911-3.8003,15.313-9.4792,34.984-13.417,17.729-3.4572,40.62-5.7415,65.302-5.7864zm0.01-8.4922c23.383-0.0423,46.07,2.2172,64.065,5.7194,18.569,3.7139,31.637,8.3556,36.105,13.571l-0.005,2.5823c-5.3884-6.4885-22.973-11.247-36.518-13.966-17.858-3.4757-40.393-5.7185-63.647-5.6736-24.538,0.0441-47.276,2.3698-64.875,5.8014-13.626,2.5832-33.226,8.3696-35.412,13.86v-2.6908c1.2911-3.7588,15.597-9.6414,34.985-13.417,17.729-3.4572,40.62-5.7397,65.302-5.7864z"/>
|
||||||
|
<path d="m239.48,132.96c36.849-0.18433,68.99,5.1523,83.695,12.685l5.3638,9.279c-12.781-6.888-47.456-14.05-89.005-12.979-33.854,0.20814-70.027,3.7271-88.176,13.41l6.4035-10.709c14.895-7.7241,50.022-11.643,81.72-11.684"/>
|
||||||
|
<path d="m239.97,140.62c21.017-0.0556,41.325,1.1298,57.476,4.0437,15.041,2.7993,29.385,7.0009,31.436,9.2604l1.5901,2.8099c-4.9881-3.257-17.401-6.8836-33.339-9.906-16.006-3.0083-36.3-4.0049-57.2-3.9502-23.722-0.0811-42.152,1.1712-57.969,3.9291-16.728,3.13-28.334,7.6015-31.197,9.7261l1.5583-2.9704c5.5631-2.8381,14.39-6.2592,29.223-8.9297,16.357-2.988,34.983-3.8841,58.423-4.0128h-0.00088zm-0.009-8.4843c20.113-0.0529,39.972,1.068,55.452,3.8506,12.209,2.3768,24.283,6.0872,28.704,9.3892l2.3256,3.6954c-3.9536-4.3947-18.836-8.5593-31.974-10.892-15.361-2.6494-34.395-3.698-54.508-3.8656-21.108,0.0591-40.615,1.352-55.752,4.1081-14.441,2.7481-23.76,6.0016-27.703,8.5425l2.0451-3.0868c5.4414-2.8646,14.232-5.4954,25.303-7.6465,15.249-2.7764,34.876-4.0358,56.108-4.0949z"/>
|
||||||
|
<path d="m289.15,241.26c-18.218-3.4008-36.469-3.8947-49.217-3.7447-61.407,0.71967-81.244,12.609-83.665,16.209l-4.5894-7.4815c15.634-11.332,49.073-17.687,88.587-17.037,20.518,0.33602,38.224,1.6986,53.119,4.5835l-4.2358,7.4727"/>
|
||||||
|
<path stroke-width="0.55" d="m239.58,236.46c17.082,0.25488,33.849,0.96044,50.033,3.9784l-1.172,2.069c-15.031-2.7746-31.055-3.8365-48.803-3.75-22.663-0.17727-45.585,1.9394-65.541,7.6668-6.2968,1.7524-16.721,5.8006-17.784,9.1458l-1.1659-1.9226c0.33601-1.9773,6.6363-6.081,18.414-9.3901,22.858-6.5458,44.239-7.6491,66.019-7.799v0.002zm0.77519-8.5963c17.698,0.33073,35.975,1.1492,53.74,4.6681l-1.2206,2.1537c-16.042-3.1847-31.369-4.2466-52.415-4.5702-22.735,0.0414-46.851,1.6625-68.778,8.0372-7.0791,2.062-19.297,6.5202-19.704,10.05l-1.1659-2.0655c0.26545-3.2059,10.842-7.388,20.358-10.156,22.096-6.4241,46.275-8.076,69.186-8.1174z"/>
|
||||||
|
<path d="M327.58,247.38,320.201,258.829,299,240,244,203,182,169,149.81,157.99,156.67,145.27,159,144l20,5,66,34,38,24,32,23,13,15z"/>
|
||||||
|
<path d="m148.65,158.29c5.646-3.8294,47.139,14.655,90.555,40.834,43.301,26.254,84.677,55.921,80.942,61.473l-1.2285,1.9323-0.56354,0.4445c0.12083-0.0864,0.74345-0.84755-0.0609-2.906-1.8449-6.0704-31.195-29.491-79.894-58.895-47.475-28.309-87.041-45.371-90.997-40.494l1.247-2.3892h-0.00089zm180.44,88.927c3.57-7.052-34.916-36.044-82.632-64.272-48.813-27.666-83.994-43.951-90.42-39.095l-1.4278,2.5991c-0.0124,0.14287,0.052-0.17727,0.35364-0.4101,1.1685-1.0195,3.1052-0.95074,3.9792-0.96662,11.065,0.16581,42.667,14.709,87.006,40.128,19.428,11.315,82.071,51.491,81.832,62.789,0.0168,0.97102,0.0803,1.1712-0.28485,1.6519l1.5936-2.4236v-0.002z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path fill="#fff" stroke="#000" stroke-width="0.67037" d="m180.6,211.01c0,16.271,6.6628,30.987,17.457,41.742,10.815,10.778,25.512,17.579,41.809,17.579,16.381,0,31.247-6.6525,42.016-17.389,10.769-10.735,17.443-25.552,17.446-41.88h-0.002v-79.189l-118.74-0.14111,0.0123,79.278h0.002z"/>
|
||||||
|
<path fill="#f00" stroke="#000" stroke-width="0.50734" d="m182.82,211.12v0.045c0,15.557,6.4414,29.724,16.775,40.009,10.354,10.305,24.614,16.712,40.214,16.712,15.681,0,29.912-6.3606,40.222-16.626,10.308-10.265,16.697-24.433,16.699-40.044h-0.002v-76.826l-113.84-0.0185-0.0697,76.748m91.022-53.747,0.004,48.891-0.0414,5.1717h0.00088c0,1.3608-0.082,2.9122-0.24076,4.2333-0.92512,7.7294-4.4801,14.467-9.7451,19.708-6.1636,6.1357-14.671,9.9413-24.047,9.9413-9.327,0-17.639-3.9379-23.829-10.1-6.3497-6.32-10.03-14.986-10.03-23.947l-0.0132-54.023,67.94,0.12259,0.002,0.002z"/>
|
||||||
|
<g id="castle3">
|
||||||
|
<g id="castle" fill="#ff0" stroke="#000" stroke-width="0.5">
|
||||||
|
<path stroke="none" d="m190.19,154.43c0.13493-5.521,4.0524-6.828,4.0806-6.8474,0.0282-0.0185,4.2314,1.4076,4.2173,6.8986l-8.2978-0.0512"/>
|
||||||
|
<path d="m186.81,147.69-0.68172,6.3447,4.1406,0.009c0.0397-5.2493,3.9739-6.1225,4.0691-6.1031,0.0891-0.005,3.9889,1.1606,4.0929,6.1031h4.1511l-0.74962-6.3932-15.022,0.0379v0.002z"/>
|
||||||
|
<path d="m185.85,154.06h16.946c0.35717,0,0.64908,0.35277,0.64908,0.78404,0,0.43039-0.29191,0.78141-0.64908,0.78141h-16.946c-0.35717,0-0.64908-0.35102-0.64908-0.78141,0-0.43127,0.29191-0.78404,0.64908-0.78404z"/>
|
||||||
|
<path d="m192.01,154.03c0.0185-3.3126,2.2621-4.2501,2.2736-4.2483,0.00088,0,2.3423,0.96661,2.3609,4.2483h-4.6344"/>
|
||||||
|
<path d="m186.21,145.05h16.245c0.34218,0,0.62263,0.31839,0.62263,0.70468,0,0.38717-0.28045,0.70467-0.62263,0.70467h-16.245c-0.34218,0-0.62263-0.31573-0.62263-0.70467,0-0.38629,0.28045-0.70468,0.62263-0.70468z"/>
|
||||||
|
<path d="m186.55,146.47h15.538c0.32719,0,0.59529,0.31662,0.59529,0.70379,0,0.38805-0.2681,0.70467-0.59529,0.70467h-15.538c-0.32719,0-0.59529-0.31662-0.59529-0.70467,0-0.38717,0.2681-0.70379,0.59529-0.70379z"/>
|
||||||
|
<path d="m191.57,135.88,1.2267,0.002v0.87136h0.89513v-0.89076l1.2567,0.004v0.88723h0.89778v-0.89076h1.2576l-0.002,2.0117c0,0.31574-0.25398,0.52035-0.54854,0.52035h-4.4113c-0.29633,0-0.56972-0.23724-0.5706-0.52652l-0.003-1.9879h0.00088z"/>
|
||||||
|
<path d="m196.19,138.57,0.27691,6.4514-4.3028-0.0159,0.28486-6.4523,3.741,0.0168"/>
|
||||||
|
<path id="cp1" d="m190.94,141.56,0.13141,3.4775-4.1256,0.002,0.11641-3.4793h3.8786-0.00089z"/>
|
||||||
|
<use xlink:href="#cp1" x="10.609"/>
|
||||||
|
<path id="cp2" d="m186.3,139.04,1.1994,0.003v0.87224h0.8775v-0.89253l1.2294,0.004v0.889h0.87926v-0.89253l1.2302,0.002-0.002,2.0117c0,0.31398-0.2487,0.51859-0.5362,0.51859h-4.3169c-0.28926,0-0.55824-0.23548-0.55913-0.52564l-0.003-1.9888h0.00088z"/>
|
||||||
|
<use xlink:href="#cp2" x="10.609"/>
|
||||||
|
<path fill="#000" stroke="none" d="m193.9,140.61c-0.0265-0.62706,0.87661-0.63411,0.86603,0v1.5364h-0.866v-1.536"/>
|
||||||
|
<path id="cp3" fill="#000" stroke="none" d="m188.57,142.84c-0.003-0.6059,0.83693-0.61824,0.82635,0v1.1871h-0.826v-1.187"/>
|
||||||
|
<use xlink:href="#cp3" x="10.641"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#castle" y="46.3198"/>
|
||||||
|
<use xlink:href="#castle" transform="matrix(0.70460892,-0.70959585,0.70959585,0.70460892,-35.341459,275.10898)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#castle" x="45.7138"/>
|
||||||
|
<use xlink:href="#castle3" transform="matrix(-1,0,0,1,479.79195,0)"/>
|
||||||
|
<g id="quina" fill="#fff">
|
||||||
|
<path fill="#039" d="m232.636,202.406v0.005c0,2.2119,0.84927,4.2272,2.2118,5.6894,1.3652,1.4667,3.2454,2.3777,5.302,2.3777,2.0672,0,3.9439-0.90487,5.3029-2.3654,1.3581-1.4587,2.2021-3.47219,2.2021-5.693v-10.768l-14.992-0.0123-0.0273,10.766"/>
|
||||||
|
<circle cx="236.074" cy="195.735" r="1.486"/>
|
||||||
|
<circle cx="244.392" cy="195.742" r="1.486"/>
|
||||||
|
<circle cx="240.225" cy="199.735" r="1.486"/>
|
||||||
|
<circle cx="236.074" cy="203.916" r="1.486"/>
|
||||||
|
<circle cx="244.383" cy="203.905" r="1.486"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#quina" y="-26.016"/>
|
||||||
|
<use xlink:href="#quina" x="-20.799"/>
|
||||||
|
<use xlink:href="#quina" x="20.745"/>
|
||||||
|
<use xlink:href="#quina" y="25.784"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 13 KiB |
4
public/crests/766.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600">
|
||||||
|
<rect fill="#fff" height="600" width="900"/>
|
||||||
|
<circle fill="#bc002d" cx="450" cy="300" r="180"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 166 B |
1
public/crests/769.svg
Normal file
|
After Width: | Height: | Size: 156 KiB |
7
public/crests/770.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 15">
|
||||||
|
<rect width="25" height="15" fill="#FFF"/>
|
||||||
|
<g fill="#CE1124">
|
||||||
|
<rect width="3" height="15" x="11"/>
|
||||||
|
<rect width="25" height="3" y="6"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 208 B |
1
public/crests/771.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 7410 3900"><path fill="#b22234" d="M0 0h7410v3900H0z"/><path d="M0 450h7410m0 600H0m0 600h7410m0 600H0m0 600h7410m0 600H0" stroke="#fff" stroke-width="300"/><path fill="#3c3b6e" d="M0 0h2964v2100H0z"/><g fill="#fff"><g id="d"><g id="c"><g id="e"><g id="b"><path id="a" d="M247 90l70.534 217.082-184.66-134.164h228.253L176.466 307.082z"/><use xlink:href="#a" y="420"/><use xlink:href="#a" y="840"/><use xlink:href="#a" y="1260"/></g><use xlink:href="#a" y="1680"/></g><use xlink:href="#b" x="247" y="210"/></g><use xlink:href="#c" x="494"/></g><use xlink:href="#d" x="988"/><use xlink:href="#c" x="1976"/><use xlink:href="#e" x="2470"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 741 B |
BIN
public/crests/772.svg
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
5
public/crests/773.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3 2">
|
||||||
|
<rect width="3" height="2" fill="#ED2939"/>
|
||||||
|
<rect width="2" height="2" fill="#fff"/>
|
||||||
|
<rect width="1" height="2" fill="#002395"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 195 B |
1
public/crests/774.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 9 6"><clipPath id="c"><path d="M0 0l4.5 3L0 6" id="b"/></clipPath><clipPath id="a"><path d="M0 0h9v6H0z"/></clipPath><g clip-path="url(#a)"><path d="M0 0v6h9V0z" fill="#001489"/><path d="M0 0v3h9V0z" fill="#e03c31"/><g stroke-width="2" stroke="#fff"><path d="M0 0l4.5 3L0 6m4.5-3H9" id="d"/><use xlink:href="#b" stroke="#ffb81c" clip-path="url(#c)"/></g><use xlink:href="#d" fill="none" stroke="#007749" stroke-width="1.2"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 530 B |
5
public/crests/778.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600">
|
||||||
|
<rect fill="#fff" width="900" height="600"/>
|
||||||
|
<rect fill="#006233" width="450" height="600"/>
|
||||||
|
<path fill="#d21034" d="M580,225a150,150 0 1,0 0,150 120,120 0 1,1 0-150m5,75-135-44 84,115v-142l-84,115z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 272 B |
1
public/crests/779.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 10080 5040"><defs><clipPath id="b"><path d="M0 0h6v3H0z"/></clipPath><clipPath id="c"><path d="M0 0v1.5h6V3zm6 0H3v3H0z"/></clipPath><path id="a" d="M0-360l69.421 215.845 212.038-80.301L155.99-35.603l194.985 115.71-225.881 19.651 31.105 224.59L0 160l-156.198 164.349 31.105-224.59-225.881-19.651 194.986-115.711-125.471-188.853 212.038 80.301z"/><path id="e" d="M0-210L54.86-75.508l144.862 10.614L88.765 28.842l34.67 141.052L0 93.334l-123.435 76.56 34.67-141.052-110.957-93.736L-54.86-75.508z"/><use id="d" xlink:href="#a" transform="scale(2.1)"/></defs><path fill="#012169" d="M0 0h10080v5040H0z"/><path d="M0 0l6 3m0-3L0 3" stroke="#fff" stroke-width=".6" clip-path="url(#b)" transform="scale(840)"/><path d="M0 0l6 3m0-3L0 3" stroke="#e4002b" stroke-width=".4" clip-path="url(#c)" transform="scale(840)"/><path d="M2520 0v2520M0 1260h5040" stroke="#fff" stroke-width="840"/><path d="M2520 0v2520M0 1260h5040" stroke="#e4002b" stroke-width="504"/><g fill="#fff"><use xlink:href="#d" x="2520" y="3780"/><use xlink:href="#a" x="7560" y="4200"/><use xlink:href="#a" x="6300" y="2205"/><use xlink:href="#a" x="7560" y="840"/><use xlink:href="#a" x="8680" y="1869"/><use xlink:href="#e" x="8064" y="2730"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
1
public/crests/783.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1200 600"><defs><clipPath id="b"><path d="M0 0h600v300H0z"/></clipPath><clipPath id="c"><path d="M0 0l300 150H0zm300 0h300L300 150zm0 150h300v150zm0 0v150H0z"/></clipPath><g id="d"><g id="a"><path d="M0 0v.5L1 0z" transform="translate(0 -.325)"/><path d="M0 0v-.5L1 0z" transform="rotate(-36 .5 -.162)"/></g><use xlink:href="#a" transform="scale(-1 1)"/><use xlink:href="#a" transform="rotate(72 0 0)"/><use xlink:href="#a" transform="rotate(-72 0 0)"/><use xlink:href="#a" transform="scale(-1 1) rotate(72)"/></g></defs><path fill="#012169" d="M0 0h1200v600H0z"/><path stroke="#FFF" d="M0 0l600 300M0 300L600 0" stroke-width="60" clip-path="url(#b)"/><path stroke="#C8102E" d="M0 0l600 300M0 300L600 0" stroke-width="40" clip-path="url(#c)"/><path stroke="#FFF" d="M300 0v300M0 150h600" stroke-width="100" clip-path="url(#b)"/><path stroke="#C8102E" d="M300 0v300M0 150h600" stroke-width="60" clip-path="url(#b)"/><use xlink:href="#d" fill="#FFF" transform="matrix(45.4 0 0 45.4 900 120)"/><use xlink:href="#d" fill="#C8102E" transform="matrix(30 0 0 30 900 120)"/><g transform="rotate(82 900 240)"><use xlink:href="#d" fill="#FFF" transform="rotate(-82 519.022 -457.666) scale(40.4)"/><use xlink:href="#d" fill="#C8102E" transform="rotate(-82 519.022 -457.666) scale(25)"/></g><g transform="rotate(82 900 240)"><use xlink:href="#d" fill="#FFF" transform="rotate(-82 668.57 -327.666) scale(45.4)"/><use xlink:href="#d" fill="#C8102E" transform="rotate(-82 668.57 -327.666) scale(30)"/></g><use xlink:href="#d" fill="#FFF" transform="matrix(50.4 0 0 50.4 900 480)"/><use xlink:href="#d" fill="#C8102E" transform="matrix(35 0 0 35 900 480)"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
5
public/crests/788.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 320">
|
||||||
|
<rect fill="#D52B1E" height="320" width="320"/>
|
||||||
|
<rect fill="#fff" height="60" width="200" x="60" y="130"/>
|
||||||
|
<rect fill="#fff" height="200" width="60" x="130" y="60"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 236 B |
519
public/crests/791.svg
Normal file
|
After Width: | Height: | Size: 173 KiB |
5
public/crests/792.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 10">
|
||||||
|
<rect width="16" height="10" fill="#006aa7"/>
|
||||||
|
<rect width="2" height="10" x="5" fill="#fecc00"/>
|
||||||
|
<rect width="16" height="2" y="4" fill="#fecc00"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 216 B |
5
public/crests/798.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600">
|
||||||
|
<rect width="900" height="600" fill="#d7141a"/>
|
||||||
|
<rect width="900" height="300" fill="#fff"/>
|
||||||
|
<path d="M 450,300 0,0 V 600 z" fill="#11457e"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 212 B |
240
public/crests/799.svg
Normal file
|
After Width: | Height: | Size: 67 KiB |
1
public/crests/801.svg
Normal file
|
After Width: | Height: | Size: 20 KiB |
9
public/crests/802.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-60 -40 120 80">
|
||||||
|
<g fill="#E70013">
|
||||||
|
<rect x="-60" y="-40" width="120" height="80"/>
|
||||||
|
<circle fill="#FFF" r="20"/>
|
||||||
|
<circle r="15"/>
|
||||||
|
<circle fill="#FFF" cx="4" r="12"/>
|
||||||
|
<path transform="translate(4)scale(9)rotate(-90)" d="M0,-1 L0.58779,0.80902 L-0.95106,-0.30902 L0.95106,-0.30902 L-0.58779,0.80902z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 362 B |
6
public/crests/803.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||||
|
<rect width="1200" height="800" fill="#E30A17"/>
|
||||||
|
<circle cx="425" cy="400" r="200" style="fill:#ffffff"/>
|
||||||
|
<circle cx="475" cy="400" r="160" style="fill:#E30A17"/>
|
||||||
|
<polygon style="fill:#ffffff" points="583.334,400 764.235,458.779 652.431,304.894 652.431,495.106 764.235,341.221"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 351 B |
1
public/crests/8030.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 550"><path fill="#8d1b3d" d="M0 0h1400v550H0z"/><path d="M400 550H0V0h400l100 30.556L400 61.11l100 30.556-100 30.555 100 30.556-100 30.555 100 30.556-100 30.555L500 275l-100 30.556 100 30.555-100 30.556 100 30.555-100 30.556 100 30.555-100 30.556 100 30.555z" fill="#fff"/></svg>
|
||||||
|
After Width: | Height: | Size: 337 B |
1
public/crests/804.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 900 600"><path fill="#00853f" d="M0 0h300v600H0z"/><path fill="#fdef42" d="M300 0h300v600H300z"/><path fill="#e31b23" d="M600 0h300v600H600z"/><g transform="translate(450 300)" fill="#00853f"><g id="b"><path id="a" d="M0-100V0h50z" transform="rotate(18 0 -100)"/><use xlink:href="#a" transform="scale(-1 1)"/></g><use xlink:href="#b" transform="rotate(72)"/><use xlink:href="#b" transform="rotate(144)"/><use xlink:href="#b" transform="rotate(216)"/><use xlink:href="#b" transform="rotate(288)"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 602 B |
BIN
public/crests/8049.svg
Normal file
|
After Width: | Height: | Size: 914 B |
5
public/crests/805.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 450 390">
|
||||||
|
<rect fill="#ED2939" width="450" height="390"/>
|
||||||
|
<rect fill="#FAE042" width="300" height="390"/>
|
||||||
|
<rect width="150" height="390"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 199 B |
1
public/crests/8062.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600"><path d="M0 0h900v600H0z" fill="#ce1126"/><path d="M0 200h900v400H0z" fill="#fff"/><path d="M0 400h900v200H0z"/><g transform="translate(-1.009 -.584) scale(2.18978)" fill="#007a3d"><path d="M246.026 120.178c-.558-.295-1.186-.768-1.395-1.054-.314-.438-.132-.456 1.163-.104 2.318.629 3.814.383 5.298-.873l1.308-1.103 1.54.784c.848.428 1.748.725 2.008.656.667-.176 2.05-1.95 2.005-2.564-.054-.759.587-.568.896.264.615 1.631-.281 3.502-1.865 3.918-.773.201-1.488.127-2.659-.281-1.438-.502-1.684-.494-2.405.058-1.618 1.239-3.869 1.355-5.894.299zm5.734-5.242c-.563-.717-1.239-3.424-1.021-4.088.192-.576.391-.691.914-.527.918.287 1.13.92.993 3.064-.107 1.747-.366 2.206-.886 1.551zm-67.516-1.946c-.185 1.311 2.325 4.568 3.458 5.158-.77.345-1.728.188-2.434.576-3.948 3.948-18.367 18.006-21 21.366 7.799.154 16.448-.106 23.761-.44-.007-5.299 5.018-5.572 8.381-7.502 1.73 2.725 6.075 2.516 6.618 6.617 0 4.91.009 12.307.009 17.646h-66.625c-1.172 5.176-5.844 9.125-12.354 7.5 2.014-2.104 5.405-2.827 6.619-5.734 1.024-6.365-2.046-10.296-4.031-13.906 3.284-1.195 3.782-1.494 7.121-3.737-2.344 7.12 6.091 6.338 12.353 6.175.211-2.417.089-5.271-1.766-5.624 2.396-.87 2.794-1.168 6.619-4.412v9.593c14.886 0 30.942-.111 46.139-.111 0-3.002.795-7.824-1.581-7.824-2.269 0-.107 6.173-1.87 6.173h-35.63c0-1.328-.034-4.104-.034-6.104 1.51-1.51 1.331-1.379 11.648-11.697 1.028-1.031 8.266-7.568 14.599-13.713zm89.06-.254c2.487 1.339 4.457 3.191 7.502 3.972-.354 1.261-1.476 1.759-1.77 3.087v26.91c3.402.75 4.118-1.178 5.737-2.205.442 4.307 3.186 8.529 3.088 11.91h-14.559c.002-14.555.002-29.114.002-43.674zm-19.412 14.412s5.296-4.471 5.296-4.643v23.484l3.814-.006c0-8.947-.118-18.022-.118-26.338 1.548-1.549 4.58-3.791 5.338-5.358v42.06c-10.746 0-30.793.012-33.443.012-.493-8.729-.577-17.771 9.6-15.826v-3.563c-.311-.609-.868.147-.998-.645 1.615-1.617 2.163-2.029 6.538-5.852 0 4.612.08 15.5.08 15.5 1.07 0 3.153.004 3.857.004.001.002.036-18.227.036-18.829zm-12.553 18.603c.716 1.075 3.154 1.056 3.04-.755-.411-1.493-3.616-.924-3.04.755z"/><circle cx="144.527" cy="161.369" r="2.042"/><path d="M207.549 112.779c2.488 1.339 4.457 3.191 7.502 3.971-.353 1.26-1.476 1.76-1.768 3.087v26.911c3.401.749 4.117-1.18 5.736-2.206.441 4.308 3.185 8.528 3.088 11.91h-14.56c.002-14.556.002-29.114.002-43.673z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/crests/8070.svg
Normal file
|
After Width: | Height: | Size: 745 B |
1
public/crests/815.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 6"><path fill="#B7312C" d="M0 0h9v6H0z"/><path fill="none" stroke="#006341" stroke-width=".143" d="M4.5 1.73l.746 2.297-1.953-1.42h2.414l-1.953 1.42z"/></svg>
|
||||||
|
After Width: | Height: | Size: 213 B |
4
public/crests/816.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600">
|
||||||
|
<rect fill="#ed2939" width="900" height="600"/>
|
||||||
|
<rect fill="#fff" y="200" width="900" height="200"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 171 B |
5
public/crests/818.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 4">
|
||||||
|
<rect fill="#CE1126" width="6" height="4"/>
|
||||||
|
<rect fill="#003893" width="6" height="3"/>
|
||||||
|
<rect fill="#FCD116" width="6" height="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 198 B |
78
public/crests/825.svg
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 900 600">
|
||||||
|
<rect width="900" height="600" fill="#000"/>
|
||||||
|
<rect width="900" height="400" fill="#fff"/>
|
||||||
|
<rect width="900" height="200" fill="#ce1126"/>
|
||||||
|
<g fill="#fff" stroke="#c09300">
|
||||||
|
<path stroke-width="1.2703" stroke-linejoin="round" d="m450.81,302.4,68.488,63.579-4.8759-115.47c-0.71638-17.5-15.924-13.485-26.971-7.1723-11.191,7.1723-23.958,7.1723-37.446,2.437-13.485,4.7353-26.253,4.7353-37.444-2.437-11.046-6.3123-26.252-10.328-26.97,7.1723l-4.8789,115.47,70.098-63.579z"/>
|
||||||
|
<g id="w" fill="#c09300" stroke="none">
|
||||||
|
<path d="m393.47,246.49-4.7342,112.32-8.0347,7.168,4.8784-115.47c2.2949-1.5782,6.3132-4.0171,7.8905-4.0171z"/>
|
||||||
|
<path d="m403.09,254.53-4.0171,93.955-8.0323,8.2204,4.8772-108.49c1.5791,1.577,6.3138,5.4498,7.1721,6.3104z"/>
|
||||||
|
<path d="m411.84,261.7-3.1545,78.362-6.4556,6.3092,4.0177-89.405c1.5748,1.5782,4.7311,3.8734,5.5924,4.7334z"/>
|
||||||
|
<path d="m421.31,265.72-3.1563,66.787-6.3132,5.1193,3.1563-74.344c1.5791,0.71638,4.7348,2.4376,6.3132,2.4376z"/>
|
||||||
|
<path d="m430.06,265.72-2.2974,55.657-6.4544,6.3129,2.4392-61.252c1.576-0.00061,5.5937-0.00061,6.3126-0.7182z"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#w" transform="matrix(-1,0,0,1,900,0)"/>
|
||||||
|
<path fill="#c09300" stroke-width="1.0739" d="m453.16,315.06,9.6126,43.755-3.1575,3.1552-3.2993-2.4388-5.4518-39.018,2.2955,39.018-3.1569,4.0158-3.1563-4.0158,2.2962-39.018-5.4506,39.018-3.3024,2.4388-3.1545-3.1552,9.6113-43.755h6.3138z"/>
|
||||||
|
<g id="b" fill="none" stroke-width="1.2705" stroke-linejoin="round">
|
||||||
|
<path fill="#fff" stroke-width="1.1888" d="m428.48,295.84-19.08,67.705,26.255,4.0177,11.188-50.924-18.363-20.799z"/>
|
||||||
|
<path d="m422.17,318.94,2.2955,5.5928,12.405-11.848"/>
|
||||||
|
<path d="m430.76,304.92,2.5957,24.346,7.8905-10.328"/>
|
||||||
|
<path d="m438.09,322.95,4.31,14.875"/>
|
||||||
|
<path d="m444.09,332.36-8.7177,13.241m2.7189,13.216-2.7902-13.198-2.4356-13.423-5.8406,7.9091-2.5613-9.1191-8.1747,8.3847,4.1575,15.251,5.7375-9.4349,3.1557,9.6123,5.8903-9.1621"/>
|
||||||
|
<path d="m414.99,361.97,5.2997-7.4437,3.4528,11.457,4.7342-8.0323,3.1575,9.6136"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#b" transform="matrix(-1,0,0,1,900,0)"/>
|
||||||
|
<g stroke-width="1.2705" stroke-linejoin="round" stroke-linecap="round">
|
||||||
|
<path stroke-width="2.3777" stroke-linejoin="round" d="m450,393.81c19.943,0,39.024-1.5776,50.213-4.734,4.7354-0.8588,4.7354-3.2976,4.7354-6.4553,4.7354-1.5776,2.2949-7.1704,5.5943-7.1704-3.2994,0.86244-4.0158-5.5941-8.0329-4.7316,0-5.5965-5.5955-6.3129-10.33-4.7377-9.4695,3.1576-26.255,3.8752-42.18,3.8752-15.924-0.71758-32.567-0.71758-42.179-3.8752-4.7342-1.5752-10.327-0.85881-10.327,4.7377-4.0183-0.86245-4.7354,5.5941-8.0341,4.7316,3.2988,0,0.85954,5.5928,5.5943,7.1704,0,3.1576,0,5.5965,4.8778,6.4553,11.045,3.1564,30.128,4.734,50.068,4.734z"/>
|
||||||
|
<path d="m422.89,363.54c6.4544,0.86123,13.628,1.5776,19.225,0.86123,3.1533,0,5.4494,5.4504-0.86257,6.3129-5.5931,0.71515-14.345,0-19.08-0.86245-4.0171-0.71759-12.768-2.2946-18.364-3.8752-5.5949-2.4364-1.576-7.168,1.5772-6.4522,4.879,1.577,11.192,3.1564,17.505,4.0158z"/>
|
||||||
|
<path d="m477.12,363.54c-6.4569,0.86123-13.628,1.5776-19.081,0.86123-3.3006,0-5.5961,5.4504,0.71711,6.3129,5.5955,0.71515,14.347,0,19.078-0.86245,4.0189-0.71759,12.769-2.2946,18.364-3.8752,5.5967-2.4364,1.5803-7.168-1.5772-6.4522-4.8778,1.577-11.19,3.1564-17.501,4.0158z"/>
|
||||||
|
<path d="m403.09,360.39c-4.8771-0.86123-7.1723,4.7316-5.5928,7.8868,0.71637-1.5776,4.0164-1.5776,4.7346-3.1552,0.8582-2.437-0.7182-2.437,0.8582-4.7316z"/>
|
||||||
|
<path d="m422.17,375.06c0-3.1528,3.1545-2.7651,3.1545-5.9215,0-1.577-0.85893-4.0171-2.4368-4.0171-1.5785,0-3.1575,1.5776-3.1575,3.1552-0.7177,3.157,2.4398,3.6312,2.4398,6.7834z"/>
|
||||||
|
<path d="m444.88,365.98c4.7305,0,4.2618,6.3141,1.9656,9.4699,0-2.2952-4.0164-3.1558-4.0164-4.7316,0-2.4419,3.6262-2.4419,2.0508-4.7383z"/>
|
||||||
|
<path d="m496.91,360.39c4.8777-0.86123,7.1741,4.7316,5.5953,7.8868-0.71819-1.5776-4.017-1.5776-4.734-3.1552-0.86124-2.437,0.71759-2.437-0.86124-4.7316z"/>
|
||||||
|
<path d="m477.83,375.06c0-3.1528-3.1532-2.7651-3.1532-5.9215,0-1.577,0.85953-4.0171,2.438-4.0171,1.5772,0,3.1563,1.5776,3.1563,3.1552,0.71771,3.157-2.441,3.6312-2.441,6.7834z"/>
|
||||||
|
<path d="m455.12,365.98c-4.7323,0-4.263,6.3141-1.9674,9.4699,0-2.2952,4.0158-3.1558,4.0158-4.7316,0.00061-2.4419-3.6262-2.4419-2.0484-4.7383z"/>
|
||||||
|
<g stroke-width="0.8915">
|
||||||
|
<path d="m404.67,361.97c1.58,0,4.0177,0.71758,4.7353,1.577l-4.74-1.58z"/>
|
||||||
|
<path d="m412.55,364.41c0.86184,0,4.0183,0.71639,5.5959,1.5752l-5.6-1.58z"/>
|
||||||
|
<path d="m441.25,367.56c-1.5776,0-4.734,0-5.5928,0.71516l5.59-0.72z"/>
|
||||||
|
<path d="m432.5,367.56c-0.8588-0.86245-4.0165-0.86245-5.5935,0h5.59z"/>
|
||||||
|
<path d="m495.34,361.97c-1.5776,0-3.8746,0.71758-4.7353,1.577l4.7353-1.577z"/>
|
||||||
|
<path d="m487.45,364.41c-0.86002,0-4.0171,0.71639-5.5953,1.5752l5.6-1.58z"/>
|
||||||
|
<path d="m458.75,367.56c1.5794,0,4.7352,0,5.5953,0.71516l-5.6-0.72z"/>
|
||||||
|
<path d="m467.5,367.56c0.86002-0.86245,4.0183-0.86245,5.5953,0h-5.6z"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#c09300" stroke="none">
|
||||||
|
<path d="m403.34,374.58c-0.53406-0.10208-0.81452-0.52459-0.68011-1.0246,0.16371-0.609,0.65161-0.95739,1.1126-0.79442,0.29312,0.10362,0.82973,0.64469,0.83184,0.83874,0.003,0.22275-0.28059,0.75257-0.40266,0.75379-0.0527,0.00053-0.1342,0.0465-0.18122,0.10201-0.10001,0.11816-0.41341,0.17549-0.68041,0.12446z"/>
|
||||||
|
<path d="m458.27,378.5c-0.19869-0.0736-0.51521-0.5185-0.51485-0.72377,0.002-0.38717,0.57418-1.0178,0.92881-1.0214,0.17516-0.001,0.65475,0.2481,0.83411,0.43462,0.32504,0.33789,0.25419,0.89278-0.15423,1.2079-0.20096,0.15505-0.80025,0.21125-1.0938,0.1026z"/>
|
||||||
|
<path d="m458.63,380.98c-0.42018-0.14209-0.57388-0.34776-0.60803-0.8136-0.0355-0.4854,0.0116-0.56097,0.52453-0.84064l0.36556-0.19931,0.34646,0.1545c0.47988,0.21397,0.69338,0.44463,0.71031,0.76742,0.0182,0.34768-0.2397,0.70345-0.64012,0.8829-0.35162,0.15758-0.37253,0.15904-0.69871,0.0488z"/>
|
||||||
|
<path d="m407.75,370.09c-0.34619-0.0109-0.82136,0.30729-1.0938,0.46875-0.64912,0.15215-1.4047,0.5511-2.0312,0.125-0.61719-0.19079-1.438-0.0404-1.5312,0.71875,0.15839,0.65179,1.0715,1.0243,1.625,0.59375,0.4106-0.53758,1.5312-0.8528,1.6562,0.0625-0.45705,0.69215-0.40489,1.6089-0.78125,2.3438-0.0612,0.45773-0.25176,0.8924-0.5,1.2812-0.4621,0.0464-0.95375-0.008-1.3438,0.28125-0.62601,0.0342-1.2647,0.34537-1.625,0.875-0.40338,0.57818-0.78869,1.1654-0.90625,1.875,0.10725,0.72494,0.93754,0.93275,1.5625,0.96875,0.66694,0.18359,1.3344,0.42433,2,0.625,1.0853,0.24303,2.102,0.63539,3.1875,0.875,1.5844,0.47758,3.2479,0.69739,4.8438,1.125,0.16722,0.0555,0.32405,0.1038,0.5,0.125,0.66233,0.13773,1.0079-0.58289,1.0625-1.125,0.32864-1.1596,0.57948-2.3391,0.90625-3.5,0.22487-0.46559,0.49645-1.5172-0.40625-1.2812-0.51485,0.30872-0.95182,0.7734-1.5938,0.8125-0.87392,0.0509-0.37513,0.94518-0.0312,1.3125,0.0759,0.5872-0.10989,1.2888-0.5,1.75-0.51994,0.32957-1.1716-0.0561-1.7188-0.1875-0.57469,0.01-1.7234-0.28325-1.1875-1.0625,0.19033-0.57691,0.20718-1.2083,0.4375-1.7812,0.29353-0.61455,0.33553-1.2851,0.46875-1.9375-0.36122-0.77733-0.97856,0.25585-1.4688,0.34375-0.33769,0.23455-1.6054,0.33418-0.9375,0.9375,0.57518,0.43696,0.1343,1.1967,0.0312,1.75-0.0369,0.77025-0.83781,0.95394-1.4688,0.78125-0.62768-0.0303-1.5013-0.49748-0.96875-1.1875,0.12115-0.57512,0.322-1.1402,0.4375-1.7188,0.2374-0.69777,0.43732-1.3628,0.6875-2.0625,0.10851-0.61996,0.33113-1.2079,0.625-1.75,0.0173-0.68543,0.47775-1.2752,0.46875-1.9688-0.0469-0.33876-0.19853-0.4622-0.40625-0.46875zm-3.5938,7.25c0.0817-0.0141,0.1399-0.002,0.21875,0.0312,0.24971,0.10625,0.25708,0.30938,0,0.53125-0.11238,0.097-0.23995,0.1905-0.28125,0.1875-0.46771-0.0402-0.6056-0.10974-0.625-0.28125-0.0172-0.15117,0.0307-0.19455,0.34375-0.34375,0.15556-0.0742,0.26207-0.11086,0.34375-0.125z"/>
|
||||||
|
<path d="m403.12,382.36c-0.49596-0.46627-0.41621-0.80642,0.31729-1.3532,0.31384-0.23393,0.50421-0.20747,0.8631,0.11997,0.55237,0.50393,0.57448,0.82295,0.0869,1.2548-0.24101,0.21344-0.34645,0.25721-0.62697,0.26001-0.29347,0.003-0.3766-0.0334-0.64036-0.28155z"/>
|
||||||
|
<path d="m406.17,383.28c-0.48488-0.11955-0.76441-0.60787-0.62254-1.0876,0.12852-0.43459,0.20285-0.47736,0.84026-0.48378,0.71478-0.007,0.85352,0.11244,0.86039,0.74185,0.004,0.35432-0.0235,0.43652-0.19971,0.60041-0.2071,0.19261-0.6052,0.29644-0.8784,0.22908z"/>
|
||||||
|
<path d="m495.28,383.36c-0.22701-0.18894-0.27272-0.27435-0.27532-0.51479-0.003-0.41064,0.23349-0.71172,0.74605-0.94382,0.68183-0.30882,0.95981-0.26636,1.2166,0.18575,0.34158,0.60129,0.32512,0.84675-0.0839,1.252-0.22578,0.22366-0.26805,0.2367-0.78493,0.2419-0.50756,0.003-0.56562-0.0105-0.8185-0.22102z"/>
|
||||||
|
<path d="m410.22,384.51c-0.36389-0.0971-0.5525-0.37016-0.55726-0.80675-0.004-0.33383,0.0201-0.38706,0.25362-0.56985,0.15122-0.11834,0.39018-0.21971,0.57856-0.24541,0.2669-0.0365,0.36442-0.0132,0.57916,0.13775,0.55052,0.38698,0.66746,0.76972,0.3487,1.1412-0.33953,0.39572-0.66141,0.48753-1.2028,0.34303z"/>
|
||||||
|
<path d="m432.14,385.49c-0.0807-0.10062-0.25916-0.16012-0.2775-0.287,0.032-0.55487,0.0585-1.1167,0.23525-1.6482,0.0962-0.52301,0.012-1.0692,0.19432-1.5787,0.18698-0.92682,0.18682-1.8826,0.40217-2.8036,0.01-0.47427,0.0549-0.949,0.19241-1.4054,0.15774-0.72168,0.0136-1.4762,0.22606-2.1894-0.0228-0.26786,0.28574-0.98321,0.55658-0.55944,0.39321,0.57645,0.91139,1.0451,1.4208,1.5153,0.43771,0.25252,0.0359,0.62445-0.26658,0.74975-0.41521,0.16364-0.51613,0.62086-0.48666,1.0222-0.0582,0.41455-0.22464,0.80685-0.24153,1.23-0.0878,0.62242-0.0706,1.2546-0.15153,1.8765-0.18211,0.60901-0.11244,1.2597-0.17323,1.8875,0.008,0.39859-0.18142,0.7606-0.15525,1.1604-0.0484,0.40592-0.0665,0.89432-0.40713,1.1724-0.32888,0.16605-0.80429,0.13737-1.0682-0.14228z"/>
|
||||||
|
<path d="m461.84,375.69c-0.48222,0.36463-0.91353,0.79527-1.3438,1.2188-0.59251,0.4489,0.48677,0.70998,0.625,1.0938,0.15716,0.58638,0.1478,1.2106,0.1875,1.8125,0.17923,0.55142,0.25835,1.1384,0.21875,1.7188-0.0519,0.6223-0.86338,0.49115-1.2188,0.84375-0.49176,0.20722-0.68789,0.69047-1.0625,1.0312-0.24625,0.48275-0.31215,1.0763-0.34375,1.625,0.0353,0.44788-0.30248,0.94931,0,1.3438,0.039,0.0557,0.0852,0.132,0.125,0.1875,0.10115,0.1452,0.3425,0.0292,0.5,0.0625,0.50368-0.0282,1.0285,0.0473,1.5-0.15625,1.21-0.20943,2.4311-0.22605,3.6562-0.28125,0.74925,0.0239,1.4701-0.23695,2.2188-0.21875,0.58681,0.12974,0.85075-0.50626,0.84375-0.96875-0.33224-0.65359-0.045-1.4285-0.3125-2.0938-0.23494-0.67246-0.14236-1.428-0.25-2.125-0.0148-0.54835-0.71068-0.75172-1.0625-0.34375-0.34144,0.34514-0.89289,0.41403-1.1562,0.84375-0.29659,0.60239,0.62745,0.60317,0.78125,1.0625,0.17589,0.4642,0.11825,0.98059,0.15625,1.4688,0.11422,0.59237-0.52919,0.6262-0.9375,0.6875-0.53675,0.20112-1.29,0.33589-1.5938-0.3125-0.1909-0.47948-0.16475-0.99286-0.21875-1.5-0.0131-0.89182-0.22755-1.7684-0.28125-2.6562-0.0514-1.0968-0.2407-2.1866-0.3125-3.2812-0.01-0.45549-0.0706-1.198-0.71875-1.0625zm-0.625,8.25,0.3125,0.0312,0.0312,0.375,0.0312,0.375-0.40625,0.125c-0.21512,0.0636-0.40325,0.0943-0.40625,0.0937-0.003-0.00085-0.088-0.0531-0.1875-0.125-0.21959-0.1586-0.16345-0.38503,0.125-0.6875,0.1626-0.17028,0.23879-0.2033,0.5-0.1875z"/>
|
||||||
|
<path d="m431.25,374.66c-0.38018,0.13504-0.86245,0.69313-1.25,0.6875-0.88,0.0623-0.75718,0.91919-0.125,1.2188,0.0833,0.25988,0.005,0.58789,0.0312,0.875,0.12288,0.7896-0.37535,1.4249-0.28125,2.2188-0.0442,0.87031-0.30695,1.7177-0.34375,2.5938-0.24704,0.90327-0.24984,1.8321-0.40625,2.75-0.10431,0.82323-0.69963,0.53271-1.2188,0.3125-0.004-0.35689-0.0272-0.70562-0.0312-1.0625,0.21637-0.81711-0.44101-1.0556-1.0938-1.1562-0.68611,0.0649-1.0228-0.52316-0.875-1.125,0.29488-0.35103,1.036-0.2534,1.5-0.3125,0.9813,0.20342,0.9416-1.1118,0.4375-1.5625-0.34472-0.63567-1.1982-0.90926-1.4375-1.5625,0.0956-0.86642-0.47971-1.7322-1.1875-2.1562-1.0885-0.0764-1.9104,0.86306-2.3125,1.7812-0.4525,0.13085-0.90391,0.26657-1.3438,0.4375-0.70889,0.17748-1.7197,1.407-0.75,1.875,0.54424,0.14988,2.2002,0.52782,1.4688,1.2812-0.41224,0.7071-1.201,0.71914-1.9062,0.53125-0.72365,0.00063-1.5294-0.35207-1.5-1.1875-0.14765-0.74985-0.12337-1.5579-0.46875-2.25-0.14847-0.83929-1.1008-0.64297-1.1562,0.125-0.73341,0.53403-0.6357,1.3978-0.125,2.0312,0.31876,0.72891,0.003,1.5776-0.3125,2.25-0.19091,0.87497-1.1559,0.90473-1.8438,1.1875-0.33751,0.13104-1.6285-0.0779-1.1562,0.65625,0.75312,0.26578,1.6525,0.50493,2.4375,0.3125,0.82295-0.10214,1.5375-0.66484,1.9375-1.375,0.55266-0.56003,1.502-0.26685,2.2188-0.28125,0.7728-0.002,1.5626,0.54243,2.3125,0.1875,0.21739-0.56438,1.2219-1.4958,1.5312-0.53125-0.0526,0.86265,0.70932,1.3257,1.5,1.2188,0.86375-0.0494,0.54445,0.61096,0.53125,1.125,0.0571,0.93448,0.65972,1.4247,1.4375,1.8125,0.26491,0.0715,0.545,0.0474,0.8125,0,0.74793-0.23513,1.5536-0.5689,1.7812-1.4062,0.30361-0.68071,0.31071-1.4507,0.53125-2.1562,0.17722-1.1299,0.406-2.26,0.4375-3.4062,0.27617-1.0383,0.19684-2.136,0.40625-3.1875,0.13231-0.7818,0.2308-1.5634,0.3125-2.3438-0.0917-0.41735-0.27189-0.48727-0.5-0.40625zm-6.7812,4.1562c0.15144,0.0185,0.2356,0.20409,0.25,0.53125,0.016,0.36409,0.20628,0.66075,0.4375,0.71875,0.18245,0.0457,0.16681,0.23882-0.0312,0.375-0.11507,0.0791-0.3209,0.127-0.6875,0.125-0.57804-0.003-0.93643-0.15276-1.25-0.46875l-0.1875-0.1875,0.28125-0.1875c0.14178-0.10831,0.39834-0.33259,0.5625-0.5,0.28494-0.29065,0.47356-0.42473,0.625-0.40625z"/>
|
||||||
|
<path d="m490.5,370.94c-0.56713,0.026-1.1373,0.11796-1.6562,0.25-1.0402-0.0647-1.5624,1.0271-0.5625,1.5625,0.60166,1.5343,1.5404-0.31684,2.5-0.1875,1.4375,0.27956,1.559,1.8323,1.7812,3,0.0809,1.1567,0.41439,2.2816,0.75,3.375,0.96222,1.0695-0.72072,1.7402-1.4375,0.90625-0.61128-0.66434-1.9204-1.4795-2.6562-0.5625-0.9036,0.38266-0.94069,1.5903-1.6875,1.9375-1.2091,0.36803-1.3613-1.1188-2-1.75-0.58724-0.82427-1.7103-0.89646-2.625-1.1875-0.42913-0.86865-0.20548-2.3456-1.0938-2.9375-0.7458,0.30425-2.1131,1.7022-0.96875,2.3438,1.1177,0.96067-0.48782,1.4011-1,2.0625-0.73158,0.81456-0.84849,1.936-0.96875,2.9688-1.2593,0.69566-1.5044-0.78769-1.6562-1.7188-0.0981-1.1115-1.0358-0.78521-1.6875-0.375-0.95249,0.38586-1.4281,1.2903-2.0938,2-0.0799,0.64767,0.0372,1.3567,0.0312,2.0312,0.21646,0.81142,1.2024,0.4303,1.8125,0.375,0.9788-0.40937,1.3795,0.62745,0.59375,1.2188-0.53181,0.67603-2.2198,0.32293-2.0625,1.4062,0.54395,0.0636,1.1105,0.0432,1.6562,0,1.0905-0.29799,2.2614-1.0673,2.375-2.2812,0.1436-1.0582,1.6676-0.86544,2.5-1.0938,1.0408-0.30002,2.2948-0.37704,2.5312,0.9375,0.70943,0.74499,2.2486,1.584,3.0312,0.5625,0.79451-0.48523,1.1764-1.3376,1.125-2.25-0.16203-0.78461,1.2688-0.81314,1.625-0.375,0.52141,0.85796,2.151,0.60478,2.9375,0.125,0.8361-0.61721,1.0176-1.705,2.2188-1.7188,1.7823-0.53352,3.6342-0.84122,5.375-1.5,1.4104-0.3073-0.2099-1.1977-0.5625-1.7188-1.0737-0.53098-2.0081,1.6419-3.2188,0.5625-0.93564-0.71605-0.87212-2.0766-1.2188-3.125-0.23714-1.3573-0.17721-2.9227-1.1562-4-0.67242-0.71491-1.586-0.887-2.5312-0.84375zm-6.8125,9.4688c0.12573-0.003,0.26757,0.0593,0.5,0.1875,0.43841,0.24193,0.75063,0.64294,0.75,0.96875-0.00043,0.21261-0.0545,0.22697-0.375,0.375-0.19719,0.091-0.4214,0.1885-0.5,0.1875-0.18098-0.002-0.62438-0.35688-0.625-0.5-0.00065-0.0594-0.0581-0.28649-0.125-0.46875-0.11761-0.32068-0.0994-0.31643,0.0625-0.53125,0.10347-0.13744,0.18677-0.21532,0.3125-0.21875zm6.5312,0.34375c0.37229-0.0244,0.59356,0.0918,0.75,0.375,0.18178,0.32896,0.0582,0.58095-0.40625,0.78125-0.20349,0.0878-0.407,0.15925-0.4375,0.15625-0.0306-0.003-0.19844-0.10253-0.375-0.21875-0.27012-0.17777-0.3095-0.26387-0.3125-0.46875-0.003-0.31541,0.34928-0.5967,0.78125-0.625zm-8.9375,0.0937c0.10904-0.017,0.20831,0.04,0.34375,0.15625,0.17999,0.15456,0.23685,0.27887,0.28125,0.59375,0.0314,0.21884,0.0265,0.50184,0,0.625-0.0486,0.2261-0.0532,0.21575-0.5625,0.21875-0.64029,0.006-0.6997-0.0639-0.6875-0.65625,0.008-0.37682,0.0118-0.4782,0.21875-0.6875,0.16044-0.16228,0.29721-0.23305,0.40625-0.25zm-5.5,1.4375c0.19951,0.0469,0.3879,0.19761,0.4375,0.4375,0.0656,0.3175,0.008,0.46223-0.25,0.59375-0.2221,0.1131-0.73401,0.1508-0.875,0.0625-0.0457-0.0286-0.1399-0.103-0.1875-0.1875-0.068-0.12114-0.0555-0.1794,0.0312-0.25,0.0605-0.0492,0.12539-0.11985,0.125-0.15625-0.0004-0.0364,0.0673-0.16316,0.15625-0.28125,0.14608-0.1939,0.36299-0.26563,0.5625-0.21875zm9.25,1.1875c0.17794-0.001,0.32863,0.0609,0.4375,0.15625,0.18526,0.16231,0.179,0.40039-0.0312,0.5625-0.13509,0.1044-0.87165,0.0948-1.125,0-0.11272-0.0421-0.15563-0.0987-0.15625-0.21875-0.002-0.14091,0.0375-0.22767,0.28125-0.34375,0.20425-0.0976,0.41581-0.15507,0.59375-0.15625z"/>
|
||||||
|
<path d="m467.86,388.29c-0.0958-0.0625-0.23767-0.11699-0.0948-0.22157,0.17277-0.30247,0.51785-0.40716,0.82434-0.51974,0.54779-0.23732,1.0207-0.64036,1.3737-1.1184,0.05-0.33298,0.42384-0.51355,0.42219-0.86174,0.003-0.47487,0.0311-0.9616-0.0846-1.426-0.12837-0.4257-0.45147-0.75199-0.82649-0.97395-0.25667-0.20149-0.674-0.25712-0.76877-0.61402-0.0525-0.34279,0.25343-0.60401,0.36053-0.90935,0.22325-0.42151,0.41109-0.86364,0.6509-1.275,0.25912-0.2878,0.65892-0.0156,0.79298,0.26239,0.18915,0.27771,0.35679,0.57593,0.45076,0.89748,0.30225,0.33175,0.57024,0.72087,0.679,1.1618,0.14839,0.31056,0.38316,0.60234,0.36929,0.96609,0.0003,0.4164,0.23509,0.78738,0.22034,1.2063,0.0133,0.56042,0.0131,1.1449-0.19184,1.6741-0.14001,0.29344-0.42058,0.46964-0.60639,0.73256-0.31897,0.29554-0.67037,0.57899-1.0797,0.73615-0.28928,0.092-0.45706,0.42565-0.81934,0.34466-0.51458,0.009-1.0366,0.079-1.5472-0.004,0.0323,0.0542-0.15633-0.0915-0.12493-0.0573z"/>
|
||||||
|
<path d="m461.01,388.74c-0.24268-0.24958-0.2952-0.35543-0.29788-0.60032-0.003-0.24747,0.0446-0.34567,0.2822-0.58569,0.43829-0.44275,0.65248-0.45344,1.4091-0.0705,0.72304,0.36598,0.9675,0.39912,1.0322,0.14002,0.0625-0.25022,0.47885-0.47916,0.87435-0.4808,0.25006-0.002,0.39157,0.0477,0.59183,0.20368,0.25136,0.19583,0.26349,0.22634,0.26989,0.67935,0.004,0.46299-0.002,0.48055-0.29042,0.73591-0.27723,0.24409-0.32183,0.25915-0.66541,0.22476-0.43718-0.0439-0.69954-0.24407-0.77073-0.58844-0.0516-0.25001-0.13942-0.3097-0.20523-0.1397-0.0209,0.0546-0.12864,0.12185-0.23894,0.1496-0.20352,0.0514-0.5488,0.26862-0.79415,0.50006-0.0927,0.0874-0.25526,0.12855-0.51863,0.13122-0.35563,0.003-0.40513-0.0183-0.67826-0.29915z"/>
|
||||||
|
<path d="m441.19,379.84c-0.66466,0.007-1.3805,0.5662-1.4688,1.2188,0.15206,0.75226,0.77698,1.4895,0.375,2.2812,0.27756,1.0131-0.76147,1.3974-1.4688,0.8125-0.4271-0.97134-0.64349-2.0358-1.2812-2.9062-0.80411-0.22762-1.1545,1.0569-1.7188,1.5,0.27975,0.75505,1.0958,1.4324,1.1875,2.375,0.1952,0.91482-0.36128,1.9306-1.1562,2.4062-0.68584,0.65472-1.6254,0.42074-2.4688,0.5625-1.0242,0.59857,0.75182,0.81755,1.2188,0.84375,1.0477,0.10646,2.1354-0.0317,2.9062-0.8125,0.76911-0.36708,0.70971-1.6972,1.625-1.8438,1.5884-0.0709,3.1626,0.24355,4.75,0.28125,0.84936,0.20336,2.1635-0.10098,2.75,0.53125,0.002,1.1075,0.94078,1.7905,1.8438,2.2188,0.4987,0.13872,1.0241-0.47928,1.5312-0.59375,0.96531-0.30764,0.67182-1.502,1.25-1.9688,1.6504-0.0893,3.3163-0.0704,4.9688-0.0937,0.31463,0.008,0.40734-0.43988,0.625-0.625-0.0363-0.63881-0.0593-1.2726-0.15625-1.9062-0.31819-0.80653,0.0513-1.8446-0.53125-2.5312-0.83011-0.22606-1.5362,0.53355-2.375,0.59375-0.92616,0.41246-1.7065,1.2677-1.75,2.3125-0.54833,0.89658-1.4277-0.15958-1.125-0.90625-0.0346-0.32541,0.0704-0.70429-0.0312-1-0.50698-0.60814-1.3947-0.4094-2.0938-0.5-1.0184,0.0406-2.0127-0.17955-3.0312-0.15625-0.89293-0.0674-1.822,0.0777-2.6875-0.15625-1.0317-0.0293-0.88959-1.0382-1.0625-1.75-0.18299-0.13571-0.40345-0.18973-0.625-0.1875zm2,3.6875c0.34308,0.007,0.66656,0.052,1,0.0937,0.43082,0.0709,0.8899-0.14816,1.3125,0,0.97651,0.16608,1.9536,0.12685,2.9375,0.21875,0.25985-0.004,0.44579,0.18471,0.625,0.34375,0.002,0.68357,0.00066,1.3789,0,2.0625-0.0299,0.25767,0.0763,0.5982-0.15625,0.78125-0.0747,0.0513-0.1583,0.1072-0.25,0.125-0.27065-0.07-0.55731-0.2479-0.6875-0.5-0.0414-0.35742,0.0179-0.70404,0.0312-1.0625-0.007-0.0927,0.0404-0.237,0-0.3125-0.21278-0.15067-0.45387-0.249-0.71875-0.25-0.84945-0.0291-1.682-0.0916-2.5312-0.125-0.7069-0.0446-1.4333,0.0604-2.125-0.125-0.26845-0.0976-0.61789-0.0641-0.78125-0.34375-0.23417-0.27227,0.10362-0.59695,0.34375-0.71875,0.31827-0.1447,0.65692-0.19411,1-0.1875zm11.281,0.25c0.15866-0.002,0.20935,0.05,0.28125,0.34375,0.0459,0.18765,0.0996,0.4172,0.125,0.5,0.0363,0.11811-0.0218,0.15625-0.1875,0.21875-0.494,0.18646-0.98566,0.16797-1.1562-0.0625-0.0774-0.10454,0.0129-0.43451,0.15625-0.5625,0.28946-0.25851,0.60992-0.43691,0.78125-0.4375z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path stroke-width="1.1502" d="m449.98,327.23c32.642-25.106,29.843-61.883,29.843-61.883-0.8613,0.17223-1.6795,0.25835-2.5408,0.25835-6.8471,0-23.178-3.9171-26.988-8.8926-4.0812,4.5034-20.77,8.8926-27.574,8.8926-0.86129,0-1.7225-0.0861-2.5407-0.25835,0,0-2.8422,36.776,29.8,61.883z"/>
|
||||||
|
<path stroke-width="0.9157" d="m477.22,268.04c-0.28097,0.0176-0.5633,0.0264-0.8477,0.0264-6.2055,0-20.619-3.1838-26.175-7.9572-5.8195,4.4095-20.471,7.9572-26.576,7.9572-0.28635,0-0.56925-0.035-0.84965-0.0865-0.0142,1.3908,0.0581,2.8324,0.14448,4.1436,0.323,4.9008,1.1826,9.819,2.4876,14.552,4.1081,14.895,12.516,27.553,24.572,37.155,12.066-9.61,20.484-22.28,24.601-37.186,1.3071-4.7319,2.1694-9.6497,2.4955-14.55,0.0853-1.2845,0.15716-2.6918,0.14745-4.0545z"/>
|
||||||
|
<path fill="#c09300" stroke="none" d="m439.38,265.03c-5.8724,1.8448-12.229,3.0312-15.75,3.0312-0.28633,0-0.56336-0.0423-0.84375-0.0937-0.0142,1.3907,0.0699,2.8451,0.15625,4.1562,0.32298,4.9006,1.1638,9.7995,2.4688,14.531,2.765,10.025,7.5063,19.032,13.969,26.781v-48.406z"/>
|
||||||
|
<path fill="#c09300" stroke="none" d="m460,264.94,0,49.25c6.794-7.9213,11.733-17.206,14.594-27.562,1.307-4.7317,2.1427-9.6313,2.4688-14.531,0.0853-1.2844,0.16596-2.6999,0.15625-4.0625-0.28095,0.0176-0.55937,0.0312-0.84375,0.0312-3.7302,0-10.42-1.1704-16.375-3.125z"/>
|
||||||
|
<g stroke-width="1.2704">
|
||||||
|
<path stroke-width="1.2179" d="m462.31,253.09c0.66655,0.0392-0.90178-3.568-0.90178-3.568,1.7643,1.8036,8.4297,2.2349,8.4297,2.2349-3.999-1.7656-7.9979-15.096-7.528-25.721,0.4319-10.664-1.5284-14.859-3.0971-16.428-1.9995-1.9995-8.4298-3.7639-12.664-3.9991-2.3922-0.11761-1.9995,1.8036-1.9995,1.8036-4.4308-1.137-8.8606-1.5684-10.861-0.2353-1.882,1.2547-2.274,7.5278-0.90178,6.43,3.3326-2.6661,6.2341-0.23524,8.2335,2.6661,1.7644,2.5485,1.6467,9.7627-0.90178,18.192-2.6661,8.8609-9.9588,17.722-9.9588,17.722,3.96,0,9.5276-3.5287,9.5276-3.5287l-1.3331,5.5283c4.1951-1.9996,7.5278-5.0969,7.5278-5.0969l3.9992,4.1951c1.333-1.7643,3.9991-4.1951,3.9991-4.1951s3.3328,3.5286,8.4297,3.9992z"/>
|
||||||
|
<path fill="none" d="m446.12,227.57s-2.2349,16.428-6.43,21.094"/>
|
||||||
|
<path fill="none" d="m449.65,227.14s-0.86252,16.623-3.7639,21.956"/>
|
||||||
|
<path fill="none" d="m452.78,227.81s0,18.192,1.0978,21.289"/>
|
||||||
|
<path fill="none" d="m456.74,228.71s0.90178,15.291,4.6657,20.819"/>
|
||||||
|
<path fill="#c09300" stroke-width="0.3542" d="m442.08,219.61c-0.19598-1.4508-0.54888-2.5878-1.0586-3.3328-1.9996-2.9013-4.9009-5.3321-8.2335-2.6661,0,0,1.137-3.5287,3.5678-3.6463,1.882-0.11767,6.1556,1.4115,9.9196,7.8415,0,0-2.7837-0.62739-3.4502-0.0393-1.2546,1.0979-0.74495,1.8428-0.74495,1.8428z"/>
|
||||||
|
<path fill="#c09300" stroke-width="0.3542" d="m432.44,209.26c0.27439-0.90178,0.7057-1.7251,1.2546-2.078,1.9996-1.333,6.43-0.90177,10.86,0.23524,0,0-0.39205-1.9212,1.9996-1.8036,4.2344,0.23523,10.665,1.9996,12.664,3.9992,0.47046,0.50973,1.0194,1.2547,1.4899,2.3916h-0.0784c-0.98015-1.3721-3.764-1.2937-4.4308-1.2154-1.0586,0.11756-1.7251,0.0784-3.1365,0.4312-0.66655,0.15693-1.686,0.3529-2.2349,0.78422-0.43131,0.3529-0.7841,1.6467-1.4506,1.6467-1.0586,0-0.98019-0.27449-1.2547-0.58814-0.35279-0.43131-0.54888-1.0586-0.90178-1.0194-1.0978,0.19608-2.8621-0.66644-5.0969-2.4308-2.2344-1.7644-3.0971-2.1956-5.9984-1.9996-2.8622,0.23524-3.7639,1.8427-3.7639,1.8427l0.0784-0.19598z"/>
|
||||||
|
<circle cx="448.824" cy="210.672" r="1.176" stroke="none"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 23 KiB |
1
public/crests/828.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9600 4800"><path fill="#d52b1e" d="M0 0h2400l99 99h4602l99-99h2400v4800H7200l-99-99H2499l-99 99H0z"/><path fill="#fff" d="M2400 0h4800v4800H2400zm2490 4430l-45-863a95 95 0 01111-98l859 151-116-320a65 65 0 0120-73l941-762-212-99a65 65 0 01-34-79l186-572-542 115a65 65 0 01-73-38l-105-247-423 454a65 65 0 01-111-57l204-1052-327 189a65 65 0 01-91-27l-332-652-332 652a65 65 0 01-91 27l-327-189 204 1052a65 65 0 01-111 57l-423-454-105 247a65 65 0 01-73 38l-542-115 186 572a65 65 0 01-34 79l-212 99 941 762a65 65 0 0120 73l-116 320 859-151a95 95 0 01111 98l-45 863z"/></svg>
|
||||||
|
After Width: | Height: | Size: 621 B |
1
public/crests/836.svg
Normal file
|
After Width: | Height: | Size: 92 KiB |
31
public/crests/840.svg
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 630 360">
|
||||||
|
<rect width="630" height="360" fill="#da0000"/>
|
||||||
|
<rect width="630" height="240" fill="#fff"/>
|
||||||
|
<rect width="630" height="120" fill="#239f40"/>
|
||||||
|
<g transform="translate(8.4,100.4)">
|
||||||
|
<g id="tb4">
|
||||||
|
<g id="tb1" fill="none" stroke="#fff" stroke-width="2">
|
||||||
|
<path id="tbp1" d="M0,1H26M1,10V5H9V9H17V5H12M4,9H6M26,9H21V5H29M29,0V9H37V0M33,0V9" transform="scale(1.4)"/>
|
||||||
|
<path id="tbp2" d="M0,7H9M10,7H19" transform="scale(2.8)"/>
|
||||||
|
<use xlink:href="#tbp2" y="120"/>
|
||||||
|
<use xlink:href="#tbp1" y="145.2"/>
|
||||||
|
</g>
|
||||||
|
<g id="tb3">
|
||||||
|
<use xlink:href="#tb1" x="56"/>
|
||||||
|
<use xlink:href="#tb1" x="112"/>
|
||||||
|
<use xlink:href="#tb1" x="168"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#tb3" x="168"/>
|
||||||
|
<use xlink:href="#tb4" x="392"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#da0000" transform="matrix(45,0,0,45,315,180)">
|
||||||
|
<g id="emblem_half">
|
||||||
|
<path d="M-0.54815,0.83638A0.912046,0.912046 0 0,0 0.328544,-0.722384A1,1 0 0,1 -0.54815,0.83638"/>
|
||||||
|
<path d="M0.618339,0.661409A0.763932,0.763932 0 0,0 0.421644,-0.741049A1,1 0 0,1 0.618339,0.661409"/>
|
||||||
|
<path d="M0,1 -0.05,0 0,-0.787278A0.309995,0.309995 0 0,0 0.118034,-0.688191V-0.100406L0.077809,0.892905z"/>
|
||||||
|
<path d="M-0.02,-0.85 0,-0.831217A0.14431,0.14431 0 0,0 0.252075,-0.967708A0.136408,0.136408 0 0,1 0,-0.924634"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#emblem_half" transform="scale(-1,1)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
5
public/crests/8601.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 6">
|
||||||
|
<rect fill="#21468B" width="9" height="6"/>
|
||||||
|
<rect fill="#FFF" width="9" height="4"/>
|
||||||
|
<rect fill="#AE1C28" width="9" height="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 195 B |
7
public/crests/8872.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 800">
|
||||||
|
<rect width="1100" height="800" fill="#ef2b2d"/>
|
||||||
|
<rect width="200" height="800" x="300" fill="#fff"/>
|
||||||
|
<rect width="1100" height="200" y="300" fill="#fff"/>
|
||||||
|
<rect width="100" height="800" x="350" fill="#002868"/>
|
||||||
|
<rect width="1100" height="100" y="350" fill="#002868"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 340 B |
1
public/crests/8873.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 600"><rect width="100%" height="100%" fill="#0065BD"/><path d="M0 0l1000 600M0 600L1000 0" stroke="#fff" stroke-width="120"/></svg>
|
||||||
|
After Width: | Height: | Size: 189 B |
16
public/crests/9460.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 54 36">
|
||||||
|
<rect width="54" height="36" fill="#002b7f"/>
|
||||||
|
<path d="M0,22.5H54V27H0z" fill="#f9e814"/>
|
||||||
|
<g fill="#fff" id="s">
|
||||||
|
<g id="f">
|
||||||
|
<g id="t">
|
||||||
|
<path d="m12,8v4h2z" transform="rotate(18,12,8)" id="o"/>
|
||||||
|
<use xlink:href="#o" x="-24" transform="scale(-1,1)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#t" transform="rotate(72,12,12)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#t" transform="rotate(-72,12,12)"/>
|
||||||
|
<use xlink:href="#f" transform="rotate(144,12,12)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#s" x="-4" y="-4" transform="scale(0.75)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 593 B |
16
public/flags/9460.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 54 36">
|
||||||
|
<rect width="54" height="36" fill="#002b7f"/>
|
||||||
|
<path d="M0,22.5H54V27H0z" fill="#f9e814"/>
|
||||||
|
<g fill="#fff" id="s">
|
||||||
|
<g id="f">
|
||||||
|
<g id="t">
|
||||||
|
<path d="m12,8v4h2z" transform="rotate(18,12,8)" id="o"/>
|
||||||
|
<use xlink:href="#o" x="-24" transform="scale(-1,1)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#t" transform="rotate(72,12,12)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#t" transform="rotate(-72,12,12)"/>
|
||||||
|
<use xlink:href="#f" transform="rotate(144,12,12)"/>
|
||||||
|
</g>
|
||||||
|
<use xlink:href="#s" x="-4" y="-4" transform="scale(0.75)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 593 B |
1
public/flags/ar.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#338af3" d="M0 0h512v144.7L488 256l24 111.3V512H0V367.3L26 256 0 144.7z"/><path fill="#eee" d="M0 144.7h512v222.6H0z"/><path fill="#ffda44" d="m332.4 256-31.2 14.7 16.7 30.3-34-6.5-4.2 34.3-23.7-25.2-23.6 25.2-4.3-34.3-34 6.5 16.6-30.3-31.2-14.7 31.3-14.7L194 211l34 6.5 4.3-34.3 23.6 25.2 23.6-25.2 4.4 34.3 34-6.5-16.7 30.3z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 523 B |
1
public/flags/at.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M0 0h512v167l-23.2 89.7L512 345v167H0V345l29.4-89L0 167z"/><path fill="#eee" d="M0 167h512v178H0z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 306 B |
1
public/flags/au.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#0052b4" d="M0 0h512v512H0z"/><path fill="#eee" d="m154 300 14 30 32-8-14 30 25 20-32 7 1 33-26-21-26 21 1-33-33-7 26-20-14-30 32 8zm222-27h47l-38 27 15-44 14 44zm7-162 7 15 16-4-7 15 12 10-15 3v17l-13-11-13 11v-17l-15-3 12-10-7-15 16 4zm57 67 7 15 16-4-7 15 12 10-15 3v16l-13-10-13 11v-17l-15-3 12-10-7-15 16 4zm-122 22 7 15 16-4-7 15 12 10-15 3v16l-13-10-13 11v-17l-15-3 12-10-7-15 16 4zm65 156 7 15 16-4-7 15 12 10-15 3v17l-13-11-13 11v-17l-15-3 12-10-7-15 16 4zM0 0v32l32 32L0 96v160h32l32-32 32 32h32v-83l83 83h45l-8-16 8-15v-14l-83-83h83V96l-32-32 32-32V0H96L64 32 32 0Z"/><path fill="#d80027" d="M32 0v32H0v64h32v160h64V96h160V32H96V0Zm96 128 128 128v-31l-97-97z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 866 B |
1
public/flags/ba.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#ffda44" d="M0 0h445.3l33.9 255-33.9 257-323.7-134.3L0 66.8z"/><path fill="#0052b4" d="M0 66.8V512h445.4z"/><path fill="#0052b4" d="M445.3 0H512v512h-66.7z"/><path fill="#eee" d="m354.6 456-8.3 25.6h-26.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5 21.7-15.8h-26.8zm-55-55.4-8.3 25.5h-26.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5 21.7-15.8h-26.8zM244.4 345l-8.3 25.5h-26.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5 21.7-15.8h-26.8zm-55.1-55.7-8.3 25.5h-26.8l21.7 15.8-8.3 25.5 21.7-15.8L211 356l-8.3-25.5 21.7-15.8h-26.8zm-55.4-55.7-8.3 25.5H98.8l21.7 15.8-8.3 25.5 21.7-15.8 21.7 15.8-8.3-25.5L169 259h-26.8zM78.7 178l-8.3 25.5H43.6l21.7 15.8-8.3 25.5L78.7 229l21.7 15.8-8.3-25.5 21.7-15.8H87zm-55.2-55.7-8.3 25.5h-26.8l21.7 15.8L1.8 189l21.7-15.8L45.2 189l-8.3-25.5 21.7-15.8H31.8z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 998 B |
1
public/flags/be.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#333" d="M0 0h167l38.2 252.6L167 512H0z"/><path fill="#d80027" d="M345 0h167v512H345l-36.7-256z"/><path fill="#ffda44" d="M167 0h178v512H167z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 338 B |
1
public/flags/br.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#6da544" d="M0 0h512v512H0z"/><path fill="#ffda44" d="M256 100.2 467.5 256 256 411.8 44.5 256z"/><path fill="#eee" d="M174.2 221a87 87 0 0 0-7.2 36.3l162 49.8a88.5 88.5 0 0 0 14.4-34c-40.6-65.3-119.7-80.3-169.1-52z"/><path fill="#0052b4" d="M255.7 167a89 89 0 0 0-41.9 10.6 89 89 0 0 0-39.6 43.4 181.7 181.7 0 0 1 169.1 52.2 89 89 0 0 0-9-59.4 89 89 0 0 0-78.6-46.8zM212 250.5a149 149 0 0 0-45 6.8 89 89 0 0 0 10.5 40.9 89 89 0 0 0 120.6 36.2 89 89 0 0 0 30.7-27.3A151 151 0 0 0 212 250.5z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 686 B |
1
public/flags/ca.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M0 0v512h144l112-64 112 64h144V0H368L256 64 144 0Z"/><path fill="#eee" d="M144 0h224v512H144Z"/><path fill="#d80027" d="m301 289 44-22-22-11v-22l-45 22 23-44h-23l-22-34-22 33h-23l23 45-45-22v22l-22 11 45 22-12 23h45v33h22v-33h45z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 438 B |
1
public/flags/cd.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#338af3" d="M0 0h401.9L512 110.3V512H110.3L0 401.9z"/><path fill="#ffda44" d="M401.9 0 0 401.9V449l63 63h47.3L512 110.3V63L449 0z"/><path fill="#d80027" d="M449 0 0 449v63h63L512 63V0h-63z"/><path fill="#ffda44" d="m136.4 78 13.8 42.4H195l-36 26.3 13.7 42.5-36.2-26.3-36 26.3 13.7-42.5L78 120.4h44.7z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 497 B |
1
public/flags/ch.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="M0 0h512v512H0z"/><path fill="#eee" d="M389.6 211.5h-89v-89h-89.1v89h-89v89h89v89h89v-89h89z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 301 B |
1
public/flags/ci.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#eee" d="M167 0h178l31 253.2L345 512H167l-33.4-257.4z"/><path fill="#ff9811" d="M0 0h167v512H0z"/><path fill="#6da544" d="M345 0h167v512H345z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 338 B |
1
public/flags/co.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><mask id="a"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#a)"><path fill="#d80027" d="m0 384 255.8-29.7L512 384v128H0z"/><path fill="#0052b4" d="m0 256 259.5-31L512 256v128H0z"/><path fill="#ffda44" d="M0 0h512v256H0z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 340 B |