Quelle-Badges (OT/WF), Legende verschoben, Footer mit Emojis, A11y-Verbesserungen; Generator: Merge OpenThesaurus+wordfreq; Dockerfile/Gunicorn hinzugefügt

This commit is contained in:
2025-08-19 11:26:02 +02:00
parent d6d23a230e
commit 916f6510d8
5 changed files with 26823 additions and 60 deletions

View File

@@ -11,51 +11,95 @@
.grid input { text-align: center; font-size: 1.25rem; padding: .4rem; }
label { font-weight: 600; display: block; margin-top: 1rem; margin-bottom: .25rem; }
.results { margin-top: 1.5rem; }
.badge { display: inline-block; padding: .25rem .5rem; background: #f3f4f6; border-radius: .375rem; margin-right: .25rem; margin-bottom: .25rem; }
.badge { display: inline-block; padding: .25rem .5rem; background: #e5e7eb; color: #111827; border-radius: .375rem; margin-right: .25rem; margin-bottom: .25rem; }
.source { font-size: .75rem; padding: .1rem .35rem; border-radius: .25rem; margin-left: .25rem; }
.source.ot { background: #dbeafe; color: #1e40af; }
.source.wf { background: #dcfce7; color: #065f46; }
button { margin-top: 1rem; padding: .5rem 1rem; font-size: 1rem; }
summary { cursor: pointer; }
.footer { margin-top: 2rem; font-size: .9rem; color: #6b7280; }
.footer a { color: inherit; text-decoration: underline; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 1px, 1px); white-space: nowrap; border: 0; }
.skip-link { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }
.skip-link:focus { position: static; width: auto; height: auto; padding: .5rem .75rem; background: #111827; color: #ffffff; border-radius: .25rem; }
.hint { margin-top: .25rem; color: #374151; font-size: .9rem; }
.word-list { list-style: none; padding: 0; margin: 0; }
.word-list li { display: inline-block; margin: 0 .25rem .25rem 0; }
fieldset { border: 1px solid #e5e7eb; border-radius: .5rem; padding: .75rem; }
legend { font-weight: 700; padding: 0 .25rem; }
</style>
</head>
<body>
<a href="#results" class="skip-link">Zum Ergebnisbereich springen</a>
<div class="container">
<h1>WordleCheater (Deutsch)</h1>
<p>Wortliste geladen: <strong>{{ words_count }}</strong> Wörter</p>
<form method="post">
<label for="pos1">Buchstaben mit korrekter Position</label>
<div class="grid">
<input id="pos1" name="pos1" maxlength="1" value="{{ pos[0] }}" />
<input id="pos2" name="pos2" maxlength="1" value="{{ pos[1] }}" />
<input id="pos3" name="pos3" maxlength="1" value="{{ pos[2] }}" />
<input id="pos4" name="pos4" maxlength="1" value="{{ pos[3] }}" />
<input id="pos5" name="pos5" maxlength="1" value="{{ pos[4] }}" />
</div>
<label for="includes">Weitere enthaltene Buchstaben (beliebige Reihenfolge)</label>
<input id="includes" name="includes" value="{{ includes }}" />
<main id="main" role="main">
<form method="post" aria-describedby="form-hint">
<p id="form-hint" class="hint">Gib bekannte Buchstaben ein. Leere Felder werden ignoriert.</p>
<label for="excludes">Ausgeschlossene Buchstaben</label>
<input id="excludes" name="excludes" value="{{ excludes }}" />
<fieldset>
<legend>Buchstaben mit korrekter Position</legend>
<div class="grid" aria-describedby="pos-hint">
<input id="pos1" name="pos1" maxlength="1" aria-label="Position 1" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[0] }}" />
<input id="pos2" name="pos2" maxlength="1" aria-label="Position 2" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[1] }}" />
<input id="pos3" name="pos3" maxlength="1" aria-label="Position 3" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[2] }}" />
<input id="pos4" name="pos4" maxlength="1" aria-label="Position 4" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[3] }}" />
<input id="pos5" name="pos5" maxlength="1" aria-label="Position 5" inputmode="text" autocomplete="off" pattern="[A-Za-zÄÖÜäöüß]" value="{{ pos[4] }}" />
</div>
<p id="pos-hint" class="hint">Je Feld genau ein Buchstabe. Umlaute (ä, ö, ü) und ß sind erlaubt.</p>
</fieldset>
<button type="submit">Suchen</button>
</form>
<label for="includes">Weitere enthaltene Buchstaben (beliebige Reihenfolge)</label>
<input id="includes" name="includes" aria-describedby="includes-hint" inputmode="text" autocomplete="off" value="{{ includes }}" />
<p id="includes-hint" class="hint">Mehrere Buchstaben ohne Trennzeichen eingeben (z.B. „aei“).</p>
{% if results is not none %}
<div class="results">
<h2>Vorschläge ({{ results|length }})</h2>
{% if results|length == 0 %}
<p>Keine Treffer. Bitte Bedingungen anpassen.</p>
{% else %}
<details open>
<summary>Liste anzeigen</summary>
<p>
{% for w in results %}
<span class="badge">{{ w }}</span>
{% endfor %}
</p>
</details>
{% endif %}
</div>
{% endif %}
<label for="excludes">Ausgeschlossene Buchstaben</label>
<input id="excludes" name="excludes" aria-describedby="excludes-hint" inputmode="text" autocomplete="off" value="{{ excludes }}" />
<p id="excludes-hint" class="hint">Buchstaben, die nicht vorkommen (z.B. „rst“).</p>
<button type="submit">Suchen</button>
</form>
{% if results is not none %}
<div class="results" id="results" role="region" aria-labelledby="results-title">
<h2 id="results-title">Vorschläge ({{ results|length }})</h2>
{% if results|length == 0 %}
<p>Keine Treffer. Bitte Bedingungen anpassen.</p>
{% else %}
<details open>
<summary>Liste anzeigen</summary>
<ul class="word-list">
{% for w in results %}
<li>
<span class="badge">{{ w }}
{% set srcs = sources_map.get(w, []) %}
{% for s in srcs %}
{% if s == 'ot' %}
<span class="source ot">OT</span>
{% elif s == 'wf' %}
<span class="source wf">WF</span>
{% endif %}
{% endfor %}
</span>
</li>
{% endfor %}
</ul>
</details>
{% endif %}
<p>
<strong>Legende:</strong>
<span class="source wf">WF</span> = Wordfreq,
<span class="source ot">OT</span> = OpenThesaurus
</p>
</div>
{% endif %}
</main>
<footer class="footer">
Made in 2025 with ❤️ and ☕ by <a href="mailto:elpatron@mailbox.org">Markus F.J. Busche</a>
</footer>
</div>
</body>
</html>