"""Sfondo 1080x1920 per la Storia "Indovina il gioco".

Lo sticker sondaggio si aggiunge a mano nell'app, quindi qui si produce solo
lo sfondo e si lascia libera la fascia dove andra' appoggiato.

Per la foto si pescano **le 00, 00b, 00c, 00d**, che sono le migliori
dell'archivio. Vanno pero' sempre guardate: se si legge il titolo del gioco sul
tabellone o sui dorsi delle carte, la domanda non ha piu' senso. Le zone alte e
basse dello schermo sono coperte dall'interfaccia di Instagram (nome profilo,
campo risposta): niente di importante nei primi e negli ultimi 260 px.

Una foto gia' usata nel carosello va benissimo, anzi: si sceglie la migliore che
il gioco ha, e se il giorno dopo l'utente se la ritrova nel post e' un
riconoscimento, non una ripetizione da evitare.

Le due risposte sbagliate devono essere **compatibili con quello che si vede**.
Per Scythe avevo messo Terraforming Mars, che e' cubetti e tessere esagonali,
sotto una foto piena di miniature: chi conosce i giochi la scarta senza pensarci
e il sondaggio si riduce a due opzioni. Sostituita con Blood Rage. Il distrattore
deve poter essere quella foto.

Il formato e' **1080x1920**. Sugli schermi piu' allungati Instagram centra
l'immagine e riempie lui la fascia in basso con un grigio scurissimo, e il
confine col nostro nero pieno si vede. Alzare l'immagine non risolve: la
fascia grigia resta comunque. Quindi gli ultimi pixel della nostra immagine
sfumano verso quel grigio (`GRIGIO_IG`), cosi' il passaggio non si nota.

Il valore va campionato da uno screenshot vero del telefono, non indovinato:
`python3 storia.py grigio <screenshot.png>` lo legge e lo stampa.

Lo sticker sondaggio a tre opzioni misura **653x475** in questo spazio: la
grafica finisce prima di y=1400 e da li' in giu' e' roba sua.
"""
import os, subprocess, sys

QUI = os.path.dirname(os.path.abspath(__file__))
BASE = os.path.dirname(QUI)
FONT = os.path.join(BASE, "font")
FOTO = os.path.join(BASE, "foto")
OUT = os.path.join(BASE, "out", "storie")
HTML = os.path.join(BASE, "out", "html")
CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

# grigio della fascia che Instagram disegna sotto la Storia. Da campionare
# su uno screenshot vero: "python3 storia.py grigio <file.png>".
GRIGIO_IG = "#0c1014"   # misurato sullo screenshot dell'iPhone di Paolo
ALTEZZA_SFUMATURA = 260

CSS = """
*{box-sizing:border-box;margin:0;padding:0}
html,body{width:1080px;height:1920px;background:#000;overflow:hidden}
body{font-family:Inter,system-ui,sans-serif;-webkit-font-smoothing:antialiased}
.st{width:1080px;height:1920px;position:relative;overflow:hidden;background:#000}
.st .foto{position:absolute;left:0;right:0;top:0;height:920px;overflow:hidden}
.st .foto img{width:100%;height:100%;object-fit:cover;display:block}
.st .velo{position:absolute;left:0;right:0;top:620px;height:300px;
  background:linear-gradient(to top,#000 0%,rgba(0,0,0,.75) 40%,rgba(0,0,0,0) 100%)}
.st .testi{position:absolute;left:80px;right:80px;top:980px}
/* zona lasciata libera per lo sticker sondaggio, si vede solo nell'anteprima */
.st .zona{position:absolute;left:213px;right:214px;top:1445px;height:475px;
  border:3px dashed #E0A340;border-radius:24px;display:flex;align-items:center;justify-content:center;
  font-size:30px;color:#E0A340;letter-spacing:.06em;text-transform:uppercase;font-weight:700;text-align:center}
.st .occh{font-size:34px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:#E0A340}
.st .dom{font-family:'Bebas Neue',sans-serif;font-size:150px;line-height:.9;color:#fff;margin-top:26px}
.st .sotto{font-size:36px;color:#8d8d8d;margin-top:30px;line-height:1.35}
.st .filetto{width:120px;height:5px;background:#E0A340;margin-bottom:34px}
.st .coda{position:absolute;left:0;right:0;bottom:0;height:__SFUMA__px;
  background:linear-gradient(to bottom,rgba(0,0,0,0),__GRIGIO__)}
"""


def storia(foto, occhiello, domanda, sotto, stile_foto="", segna_zona=False):
    z = '<div class="zona">lo sticker sondaggio<br>sta qui, 653×475</div>' if segna_zona else ''
    return (f'<div class="st"><div class="foto"><img src="{foto}" style="{stile_foto}">'
            f'<div class="velo"></div></div>'
            f'<div class="testi"><div class="filetto"></div><div class="occh">{occhiello}</div>'
            f'<div class="dom">{domanda}</div><div class="sotto">{sotto}</div></div>{z}'
            f'<div class="coda"></div></div>')


def rasterizza(corpo, nome):
    os.makedirs(OUT, exist_ok=True)
    os.makedirs(HTML, exist_ok=True)
    h, p = os.path.join(HTML, nome + ".html"), os.path.join(OUT, nome + ".png")
    with open(h, "w", encoding="utf-8") as f:
        f.write('<!doctype html><html lang="it"><head><meta charset="utf-8">'
                f'<link rel="stylesheet" href="{FONT}/locale.css">'
                f'<style>{CSS.replace("__GRIGIO__", GRIGIO_IG).replace("__SFUMA__", str(ALTEZZA_SFUMATURA))}</style>'
                f'</head><body>{corpo}</body></html>')
    subprocess.run([CHROME, "--headless", "--disable-gpu", "--hide-scrollbars",
                    "--force-device-scale-factor=1", "--window-size=1080,1920",
                    "--virtual-time-budget=4000", f"--screenshot={p}", f"file://{h}"],
                   check=True, capture_output=True)
    return p


def campiona_grigio(screenshot):
    """Legge il grigio della fascia di Instagram dal fondo di uno screenshot.

    Prende la riga a un decimo dal fondo, salta i bordi laterali e restituisce
    il colore piu' frequente: cosi' un'icona o il campo di testo non spostano
    il risultato.
    """
    from collections import Counter
    from PIL import Image
    im = Image.open(screenshot).convert("RGB")
    w, h = im.size
    y = h - max(6, h // 10)
    riga = [im.getpixel((x, y)) for x in range(w // 5, w * 4 // 5)]
    colore, quanti = Counter(riga).most_common(1)[0]
    return "#%02x%02x%02x" % colore, quanti, len(riga), y


DRIVE = ("/Users/paolo/Library/CloudStorage/GoogleDrive-paoloalby@gmail.com/"
         "Il mio Drive/Instagram")

# Dal 2026-09-14 la card dice "La risposta nel post di domani." (chiesto da Paolo: "la
# risposta domani" da sola si capiva meno). Dal 13 non dice piu' il giorno della
# settimana. Chiesto da Paolo dopo lo slittamento per Wingspan Pocket: le card gia'
# su Drive dicevano il giorno vecchio, e quella del 13 ("la risposta venerdi'") non
# si poteva pubblicare. "Domani" e' vero sempre, anche quando la coda slitta.
# Lo stesso giorno Between Two Cities e Ora et Labora si sono scambiati: la storia
# di BTC era gia' uscita, quindi BTC esce lunedi' 14 e Ora et Labora mercoledi' 16.
# Le storie: chiave = nome del file su Drive (mese-giorno + gioco, dove la data
# e' il giorno in cui Paolo la carica, cioe' la sera prima del post).
STORIE = {
    "09-01 Draftosaurus": dict(
        foto=f"{FOTO}/Drafto_2.jpg", giorno="mercoledì",
        opzioni="Draftosaurus · Dinosaur Island · New York Zoo",
        tag="@ghenosgames @theo_sacha @toinito",
        corretta="Draftosaurus"),
    "09-03 Dixit": dict(
        foto=f"{FOTO}/Dixit_cop.jpg", giorno="venerdì",
        opzioni="Mysterium · Dixit · Similo",
        tag="@asmodee_it @jeanlouis.roubira",
        corretta="Dixit"),
    "09-06 Ratti di Wistar": dict(
        foto=f"{FOTO}/Wistar_storia.jpg", giorno="lunedì",
        opzioni="This War of Mine · Root · Ratti di Wistar",
        tag="@craniocreations_official @mago.baol @volodifarfalle",
        corretta="Ratti di Wistar"),
    "09-10 Cryptid": dict(
        foto=f"{FOTO}/Cryptid_storia.jpg", giorno="venerdì",
        opzioni="Cryptid · Dewan · El Dorado",
        tag="@studiosupernova_games",
        corretta="Cryptid"),
    "09-15 Ora et Labora": dict(
        foto=f"{FOTO}/Ora_storia.jpg", giorno="mercoledì",
        opzioni="Woodcraft · Ora et Labora · Le Havre",
        tag="@uplay.it",
        corretta="Ora et Labora"),
    "09-13 Between Two Cities": dict(
        foto=f"{FOTO}/Btc_storia.jpg", giorno="lunedì",
        opzioni="Quadropolis · Suburbia · Between Two Cities",
        tag="@ghenosgames @blackoakgames",
        corretta="Between Two Cities"),
    "09-17 Lords of Xidit": dict(
        foto=f"{FOTO}/Xidit_storia.jpg", giorno="venerdì",
        opzioni="Lords of Xidit · Cry Havoc · Small World",
        tag="@asmodee_it @regis_bonnessee",
        corretta="Lords of Xidit"),
    "09-20 Pozioni Esplosive": dict(
        foto=f"{FOTO}/Poz_storia.jpg", giorno="lunedì",
        opzioni="Azul · Pozioni Esplosive · Sagrada",
        tag="@ghenosgames @lorenzo_silva_hg",
        corretta="Pozioni Esplosive"),
    "09-22 Terramara": dict(
        foto=f"{FOTO}/Terr_storia.jpg", giorno="mercoledì",
        opzioni="Lorenzo il Magnifico · Barrage · Terramara",
        tag="@tesla.games",
        corretta="Terramara"),
    "10-15 Azul Le vetrate di Sintra": dict(
        foto=f"{FOTO}/Sin_storia.jpg", giorno="venerdì",
        opzioni="Le Vetrate di Sintra · Summer Pavilion · Il Giardino della Regina",
        tag="@ghenosgames",
        corretta="Le Vetrate di Sintra"),
    "10-18 Brass Birmingham": dict(   # post lunedì 19/10 (spostato dal 30/9 per Masterland, 24/9)
        foto=f"{FOTO}/Brass_storia.jpg", giorno="lunedì",
        opzioni="Nucleum · Brass Birmingham · Great Western Trail",
        tag="@ghenosgames @obsessionwoodworking",
        corretta="Brass Birmingham"),
    "10-01 Century La via delle spezie": dict(
        foto=f"{FOTO}/Cent_cop.jpg", giorno="mercoledì",
        opzioni="Splendor · Jaipur · La via delle spezie",
        tag="@asmodee_it @ngplusat50",
        corretta="La via delle spezie"),
    "10-04 Quadropolis": dict(
        foto=f"{FOTO}/Quad_gira.jpg", giorno="venerdì",
        opzioni="Quadropolis · Tiny Towns · Kingdomino",
        tag="@asmodee_it",
        corretta="Quadropolis"),
    "10-06 Noctiluca": dict(
        foto=f"{FOTO}/Noct_fine.jpg", giorno="mercoledì",
        opzioni="Sagrada · Noctiluca · Dice Forge",
        tag="@asmodee_it @garphillgames",
        corretta="Noctiluca"),
    "10-08 Scythe": dict(
        foto=f"{FOTO}/Scy_cop.jpg", giorno="venerdì",
        opzioni="Blood Rage · Dune Imperium · Scythe",
        tag="@ghenosgames @jameystegmaier",
        corretta="Scythe"),
    "10-11 Happy Pigs": dict(
        foto=f"{FOTO}/Pigs_cop.jpg", giorno="lunedì",
        opzioni="Happy Pigs · Agricola · La Granja",
        tag="@uplay.it",
        corretta="Happy Pigs"),
    "10-11 Harmonies": dict(
        foto=f"{FOTO}/Harm_cop.jpg", giorno="lunedì",
        opzioni="Cascadia · Harmonies · Dorfromantik",
        tag="@asmodee_it @johanbenvenuto",
        corretta="Harmonies"),
    "10-13 Terraforming Mars": dict(
        foto=f"{FOTO}/Tm_cop.jpg", giorno="mercoledì",
        opzioni="Gaia Project · On Mars · Terraforming Mars",
        tag="@ghenosgames @fryxgames",
        corretta="Terraforming Mars"),
    "10-15 Faraway": dict(
        foto=f"{FOTO}/Far_cop.jpg", giorno="venerdì",
        opzioni="Faraway · Sea Salt & Paper · Similo",
        tag="@gateongames @akashinai @johannes.goupy @dungeondice.it @mariocortese_dd",
        corretta="Faraway"),
    "10-18 Esdra e Neemia": dict(
        foto=f"{FOTO}/Esd_cop.jpg", giorno="lunedì",
        opzioni="L'Eredità di Yu · Esdra e Neemia · Predoni di Scizia",
        tag="@garphillgames",
        corretta="Esdra e Neemia"),
    "10-20 Wingspan": dict(
        foto=f"{FOTO}/Wing_fine.jpg", giorno="mercoledì",
        opzioni="Finspan · Wyrmspan · Wingspan",
        tag="@ghenosgames @elizharg",
        corretta="Wingspan", stile_foto="object-position:top"),
    "10-22 Sagrada": dict(
        foto=f"{FOTO}/Sag_cose.jpg", giorno="venerdì",
        opzioni="Dice Hospital · Studiosi a Sud del Tigri · Sagrada",
        tag="@craniocreations_official @adrian.adamescu.games @darylandrews",
        corretta="Sagrada"),
    "10-25 Grand Austria Hotel": dict(
        foto=f"{FOTO}/Gah_fine.jpg", giorno="lunedì",
        opzioni="Compagnie delle Indie · Grand Austria Hotel · 21 Giochi Minuti",
        tag="@asmodee_it @mago.baol",
        corretta="Grand Austria Hotel"),
    "10-27 Skara Brae": dict(
        foto=f"{FOTO}/Skb_cop.jpg", giorno="mercoledì",
        opzioni="Skara Brae · Agricola · Alle Porte di Loyang",
        tag="@garphillgames",
        corretta="Skara Brae"),
    "10-29 Kingdomino": dict(
        foto=f"{FOTO}/Kd_cose.jpg", giorno="venerdì",
        opzioni="Carcassonne · Queendomino · Kingdomino",
        tag="@blueorangegames @brunodesmontagnes",
        corretta="Kingdomino"),
    "11-01 Barrage": dict(
        foto=f"{FOTO}/Bar_cose.jpg", giorno="lunedì",
        opzioni="Nucleum · Barrage · Brass: Birmingham",
        tag="@craniocreations_official @mago.baol",
        corretta="Barrage"),
    "11-03 Isle of Skye": dict(
        foto=f"{FOTO}/Isle_cop.jpg", giorno="mercoledì",
        opzioni="Isle of Skye · Carcassonne · Glen More II",
        tag="@uplay.it @alexxpfister",
        corretta="Isle of Skye"),
    "11-05 Revive": dict(
        # La foto e' quella della chiusura del carosello, non la plancia personale:
        # i distrattori si reggono sulle casette di legno sugli esagoni, e sulla
        # plancia quelle non si vedono. Deciso con Paolo il 2026-09-04.
        foto=f"{FOTO}/Rev_fine.jpg", giorno="venerdì",
        opzioni="Terra Mystica · Clans of Caledonia · Revive",
        tag="@ghenosgames",
        corretta="Revive"),
    # Wingspan Pocket, post mercoledi 9 settembre. Le tre opzioni sono i tre giochi
    # della famiglia: chi conosce solo il grande sbaglia, perche' la foto e' del piccolo.
    # Paladini del Regno Occidentale. I distrattori sono gli altri due della
    # trilogia: stesso autore, stesso illustratore (Mihajlo Dimitrievski) e stessa
    # grafica, quindi il colpo d'occhio non basta a escludere niente. E' il caso
    # della regola dei distrattori di famiglia, come su Esdra e Neemia.
    # La data e' provvisoria: il gioco non e' ancora in coda.
    "11-08 Paladini del Regno Occidentale": dict(
        foto=f"{FOTO}/Pal_cop.jpg", giorno="lunedì",
        opzioni="Architetti · Paladini · Visconti",
        tag="@ghenosgames @garphillgames",
        corretta="Paladini"),
    # 5x5 City. Qui la famiglia grafica non c'e', il gioco e' un pezzo unico
    # giapponese: i distrattori si costruiscono su cosa si vede, cioe' tessere
    # quadrate con edifici disegnati su una griglia di citta'. Quadropolis usa
    # tessere praticamente uguali, Happy City ha lo stesso segno da cartone
    # animato. Data provvisoria, il gioco non e' ancora in coda.
    "11-10 5x5 City": dict(
        foto=f"{FOTO}/C5_cop.jpg", giorno="mercoledì",
        opzioni="5x5 City · Quadropolis · Happy City",
        # tag=None vuol dire "cercato, non c'e' nessuno", ed e' diverso dal campo
        # dimenticato. Controllato il 2026-09-08 partendo da BGG: l'editore e'
        # il giapponese OKAZU Brand, che come unico link ufficiale dichiara un
        # blog, e il gioco in italiano non e' mai uscito. L'autore e' Hisashi
        # Hayashi. Se salta fuori un handle vero, va qui.
        tag=None,
        corretta="5x5 City"),
    # Autobahn. Nella foto si vedono camion di legno su una mappa illustrata della
    # Germania, con i cartelli delle citta': i distrattori sono gli altri due giochi
    # di collegamenti su mappa europea che abbiamo in casa. Data provvisoria.
    "11-12 Autobahn": dict(
        foto=f"{FOTO}/Aut_cop.jpg", giorno="venerdì",
        opzioni="Alta Tensione · Autobahn · Ticket to Ride Europa",
        tag="@craniocreations_official",
        corretta="Autobahn"),
    # Blokus. La foto e' il primo piano dei pezzi trasparenti: quello che si vede e'
    # "pezzi colorati e lucidi incastrati su una griglia", quindi i distrattori sono
    # gli altri due giochi di casa che a quella distanza si somigliano, i dadi di
    # Sagrada e le tessere di Azul. Data provvisoria.
    "11-15 Blokus": dict(
        foto=f"{FOTO}/Blo_cop.jpg", giorno="lunedì",
        opzioni="Blokus · Azul · Sagrada",
        tag="@mattel",
        corretta="Blokus"),
    # Boonlake. Nella foto ci sono esagoni, casette di legno in 3D e mucche di legno
    # appoggiate sopra: i distrattori devono avere gli stessi pezzi, non solo lo
    # stesso tema. Clans of Caledonia e Revive hanno tutte e due quelle casette.
    # Scartati, tutti e tre da Paolo il 2026-09-07: Progetto Gaia, ambientato nello
    # spazio e riconoscibile a colpo d'occhio; I Castelli della Borgogna, che ha
    # solo tessere e niente pezzi sopra; Cascadia, dove gli animali sono a loro
    # volta tessere e non pezzi di legno.
    # I distrattori si cercano fra tutti i giochi che esistono, non solo fra i nostri.
    # Data provvisoria, e questo gioco non e' nemmeno in scaletta.
    "11-17 Boonlake": dict(
        foto=f"{FOTO}/Boo_cop.jpg", giorno="mercoledì",
        opzioni="Clans of Caledonia · Boonlake · Revive",
        tag="@craniocreations_official @alexxpfister",
        corretta="Boonlake"),
    # Florenza. La foto e' il tabellone centrale con i pezzi di legno sulla pergamena
    # e i nomi dei luoghi fiorentini: quello che si vede e' "Rinascimento italiano,
    # pezzi di legno grossi su un tabellone color pergamena", e i distrattori sono i
    # due giochi al mondo che danno la stessa immagine. Niente foto col titolo: la
    # 00d, la piu' bella, ha FLORENZA stampato sul tabellone. Data provvisoria.
    "11-19 Florenza": dict(
        foto=f"{FOTO}/Flo_cop.jpg", giorno="venerdì",
        opzioni="Lorenzo il Magnifico · Calimala · Florenza",
        # Gate on Games e DungeonDice sono la stessa societa' (Zerosem), e Mario Cortese
        # ne e' il titolare: sui loro giochi si taggano tutti e tre.
        tag="@gateongames @dungeondice.it @mariocortese_dd",
        corretta="Florenza"),
    # The White Castle. Nella foto si vedono dadi grossi appoggiati su un ponte di legno,
    # quindi i distrattori devono avere dadi presi da una riserva comune su una plancia
    # illustrata: Red Cathedral e' degli stessi autori e ha la stessa cifra grafica, Rajas
    # ha i dadi grossi sulla mappa. Data provvisoria, il gioco non e' ancora in coda.
    "11-22 The White Castle": dict(
        foto=f"{FOTO}/Wc_cop.jpg", giorno="lunedì",
        opzioni="Rajas of the Ganges · The White Castle · The Red Cathedral",
        tag="@deviritalia @llama_dice",
        corretta="The White Castle"),
    # Gizmos. Nella foto si vede il generatore verticale con le biglie di vetro colorate
    # che scivolano fuori: i distrattori devono avere biglie o sfere di vetro come
    # componente, non essere gestionali qualsiasi. Data provvisoria.
    "11-24 Gizmos": dict(
        foto=f"{FOTO}/Giz_cop.jpg", giorno="mercoledì",
        opzioni="Potion Explosion · Gizmos · Abalone",
        tag="@asmodee_it @philwalkerharding",
        corretta="Gizmos"),
    # Viticulture. Nella foto si vede una collina con vigne a filari, casa colonica col tetto
    # rosso e meeple colorati sopra: i distrattori sono gli altri due giochi che danno la
    # stessa immagine di campagna coltivata a colline. Data provvisoria.
    "11-26 Viticulture": dict(
        foto=f"{FOTO}/Vit_cop.jpg", giorno="venerdì",
        opzioni="Fields of Arle · Viticulture · La Granja",
        tag="@ghenosgames @jameystegmaier",
        corretta="Viticulture"),
    # I tre tag sono gli stessi della copertina del post: si decidono insieme, se no
    # storia e post escono con menzioni diverse (successo qui, corretto l'8 settembre).
    # NON si tagga @stonemaiergames: e' un account parcheggiato, 25 post, e la sua bio
    # dice "all posts are made on @jameystegmaier". Stonemaier e' nominato per esteso
    # in didascalia, quindi il credito c'e'.
    # The Red Cathedral. Nella foto si vede una rondella rotonda illustrata con dadi
    # colorati appoggiati sopra: i distrattori devono avere una ruota o un tracciato
    # circolare come componente centrale. Data provvisoria.
    "11-29 The Red Cathedral": dict(
        foto=f"{FOTO}/Rc_cop.jpg", giorno="lunedì",
        opzioni="Trismegistus · The Red Cathedral · Glen More II",
        tag="@deviritalia @llama_dice",
        corretta="The Red Cathedral"),
    # L'Eredita' di Yu. Distrattori scelti da Paolo il 2026-09-09: Skara Brae e
    # Paladini, tutti e tre di Shem Phillips illustrati in casa sua, quindi stessa
    # palette e stesso segno. Davanti a un tabellone verde con le casette di legno
    # il colpo d'occhio non basta a escluderne nessuno. Data provvisoria.
    # Nota: Yu fa da distrattore nella storia di Esdra e Neemia, che esce prima.
    "12-01 L'Eredità di Yu": dict(
        foto=f"{FOTO}/Yu_cop.jpg", giorno="mercoledì",
        opzioni="Skara Brae · L'Eredità di Yu · Paladini",
        tag="@tesla.games @garphillgames",
        corretta="L'Eredità di Yu"),
    # Altiplano. Nella foto il lama di cartone e' l'unica cosa a fuoco, quindi i
    # distrattori devono essere giochi in cui un lama sul tavolo ci starebbe:
    # Llamaland (i lama sono il componente) e Tawantinsuyu, ambientato sulle Ande.
    # Titoli verificati su DungeonDice il 2026-09-09: Tawantinsuyu resta in inglese
    # ("Tawantinsuyu - The Inca Empire"), Llamaland non e' a catalogo e quindi non
    # ha un titolo italiano da usare. Data provvisoria.
    "12-03 Altiplano": dict(
        foto=f"{FOTO}/Alt_cop.jpg", giorno="venerdì",
        opzioni="Llamaland · Altiplano · Tawantinsuyu",
        tag="@giochix",
        corretta="Altiplano"),
    # Clans of Caledonia. Nella foto c'e' una mucca rossa di legno su esagoni verdi
    # attraversati da un fiume: i due distrattori coprono meta' inquadratura a testa,
    # cosi' non se ne esclude nessuno a colpo d'occhio. Glen More II spiega la
    # Scozia e le mucche, Terra Mystica spiega gli esagoni con le costruzioni di
    # legno — ed e' lo stesso ragionamento gia' usato per la storia di Revive.
    # Scelti da Paolo il 2026-09-09. Data provvisoria.
    "12-06 Clans of Caledonia": dict(
        foto=f"{FOTO}/Cal_cop.jpg", giorno="lunedì",
        opzioni="Glen More II · Clans of Caledonia · Terra Mystica",
        tag="@redgloveedizioni",
        corretta="Clans of Caledonia"),
    # Le Rovine Perdute di Arnak. Nella foto due archeologi di legno, un idolo d'oro
    # e una gemma rossa su un tabellone di giungla: i distrattori sono i due giochi
    # con cui Arnak viene confrontato sempre, deck building piu' tabellone, stesso
    # pubblico. Titoli verificati su DungeonDice l'11 settembre 2026: "Dune Imperium"
    # (senza due punti, e' cosi' sulla scheda italiana) e "Clank!". Data provvisoria.
    "12-08 Le Rovine Perdute di Arnak": dict(
        foto=f"{FOTO}/Arn_cop.jpg", giorno="mercoledì",
        opzioni="Dune Imperium · Le Rovine Perdute di Arnak · Clank!",
        tag="@craniocreations_official @czech_games_edition",
        corretta="Le Rovine Perdute di Arnak"),
    # Predoni di Scizia. Famiglia di Shem Phillips illustrata da Sam Phillips, la
    # stessa gia' usata per Esdra e Neemia (dove Predoni fa da distrattore): stesso
    # segno, stessa palette, il colpo d'occhio non esclude nessuno. Scelti con Paolo
    # l'11 settembre 2026. Data provvisoria.
    "12-10 Predoni di Scizia": dict(
        foto=f"{FOTO}/Pre_cop.jpg", giorno="venerdì",
        opzioni="Skara Brae · Predoni di Scizia · Esdra e Neemia",
        tag="@garphillgames",
        corretta="Predoni di Scizia"),
    # Shinkansen Zero-Kei. Nella foto una costa giapponese disegnata, binari di
    # cartone e cubi di legno: i distrattori sono i due giochi di treni e di Giappone
    # che chiunque conosce. "Ticket to Ride" e non "Ticket to Ride: Giappone", perche'
    # su DungeonDice il Giappone esiste solo dentro il pacco mappe "Italia & Giappone"
    # e nessuno lo chiama cosi'. Tokaido verificato. Scelti l'11 settembre 2026.
    "12-13 Shinkansen Zero-Kei": dict(
        foto=f"{FOTO}/Shk_cop.jpg", giorno="lunedì",
        opzioni="Ticket to Ride · Shinkansen Zero-Kei · Tokaido",
        tag="@tesla.games @llama_dice",
        corretta="Shinkansen Zero-Kei"),
    # Ierusalem Anno Domini. Nella foto i seguaci di legno seduti attorno a una
    # tavola: i distrattori sono due gestionali con i meeple da piazzare, scelti
    # perche' il tema non faccia da indizio. Paladini e' gia' un nostro post,
    # Orleans ha lo stesso titolo in italiano. Scelti con Paolo l'11 settembre 2026.
    "12-15 Ierusalem Anno Domini": dict(
        foto=f"{FOTO}/Ier_cop.jpg", giorno="mercoledì",
        opzioni="Paladini del Regno Occidentale · Ierusalem Anno Domini · Orléans",
        tag="@deviritalia @deviriberia",
        corretta="Ierusalem Anno Domini"),
    "09-08 Wingspan Pocket": dict(
        foto=f"{FOTO}/WsP_cop.jpg", giorno="mercoledì",
        opzioni="Wingspan · Wyrmspan · Wingspan Pocket",
        tag="@ghenosgames @elizharg @jameystegmaier",
        corretta="Wingspan Pocket"),
    # --- Dal post48 in poi le date sono PROVVISORIE: i post non sono ancora in coda su
    # Buffer, la data vera si mette quando si fissa, e solo allora la card sale su Drive.
    # Era: la 00b, senza la scritta ERA sul bordo (la 00 e la 00c ce l'hanno). Si vedono
    # mura grigie a incastro, palazzi 3D di plastica, campi e dadi su una plancia gialla a
    # fori: i distrattori hanno edifici 3D su una griglia. Scelti con Paolo il 15/9.
    "12-17 Era": dict(
        foto=f"{FOTO}/Era_storia.jpg", giorno="venerdì",
        opzioni="Cities · Era · Tiny Towns",
        tag="@craniocreations_official @matt.leacock",
        corretta="Era"),
    # Cuzco: la 00b, tempio a gradoni in primo piano, esagoni a terrazze e meeple col
    # copricapo. I distrattori sono gli altri due della trilogia delle maschere di Kramer e
    # Kiesling, gli unici dove questi pezzi ci starebbero. Scelti con Paolo il 15/9.
    "12-20 Cuzco": dict(
        foto=f"{FOTO}/Cuz_storia.jpg", giorno="lunedì",
        opzioni="Tikal · Cuzco · Mexica",
        tag="@dvgames_italia",
        corretta="Cuzco"),
    # Marco Polo II: la 00d, dadi impilati sulla plancia pergamena, senza nomi di città (la
    # 00c ha Kabul e Chengdu leggibili, la 00 Kunming). I distrattori sono il primo Marco Polo,
    # che in questa foto è indistinguibile, e Grand Austria Hotel, stessi dadi da riserva
    # comune. Scelti con Paolo il 15/9.
    "12-22 Marco Polo II": dict(
        foto=f"{FOTO}/Mp2_storia.jpg", giorno="mercoledì",
        opzioni="Grand Austria Hotel · Sulle tracce di Marco Polo · Marco Polo II",
        tag="@giochiuniti @mago.baol",
        corretta="Marco Polo II"),
    # Russian Railroads: la 00c, meeple sulle caselle azione coi binari, senza città (la 00
    # ha Kiev leggibile, la 00b è mossa). Ultimate Railroads è la riedizione, stessa plancia;
    # Great Western Trail ha meeple, treni e tracciato. Scelti con Paolo il 15/9.
    "12-24 Russian Railroads": dict(
        foto=f"{FOTO}/Rus_storia.jpg", giorno="venerdì",
        opzioni="Ultimate Railroads · Russian Railroads · Great Western Trail",
        tag="@asmodee_it",
        corretta="Russian Railroads"),
    # Calico: la 00d, i bottoni obiettivo senza la trapunta. Fuori contesto sembrano
    # ingredienti (funghi viola, teschi blu, gocce, foglie): i distrattori sono giochi di
    # pozioni con gettoni tondi di ingredienti, per far credere che siano quelli. Idea di
    # Paolo, 15/9: la trapunta la riconoscono tutti dalla scatola, i bottoni no.
    "10-13 Calico": dict(   # post mercoledì 14/10, storia il martedì sera
        foto=f"{FOTO}/Cal_storia.jpg", giorno="mercoledì",
        opzioni="I Ciarlatani di Quedlinburg · Calico · Alchimisti",
        tag="@littlerocketgames @gorgerivergamestudio",
        corretta="Calico"),
    # Flamme Rouge: la 00d, il gruppo in curva. Ciclisti di plastica: è per forza un gioco di
    # bici, e i distrattori sono Peloton (l'espansione, stessi pezzi) e la Coppa Cobram di
    # Fantozzi, che come gioco non esiste: è un'esca, e chi la riconosce ride. Idea di
    # Paolo, 15/9. Prima opzione falsa nella storia del canale.
    "12-29 Flamme Rouge": dict(
        foto=f"{FOTO}/Fla_storia.jpg", giorno="mercoledì",
        opzioni="Flamme Rouge · Peloton · Coppa Cobram",
        tag="@ghenosgames",
        corretta="Flamme Rouge"),
    # Food Chain Magnate: la 00e, pile di case marroni sulla griglia di strade, senza i
    # meeple gialli (indizio per chi lo conosce) e senza la scritta del vassoio (00) né i
    # nomi sulle carte (00c). Distrattori di Paolo: Welcome to Las Vegas e Tramways, due
    # giochi di quartieri e strade. 15/9.
    "10-01 Food Chain Magnate": dict(   # in coda per venerdì 2/10 (28/9: al posto di Century, per MS Edizioni)
        foto=f"{FOTO}/Fcm_storia.jpg", giorno="venerdì",
        opzioni="Welcome to Las Vegas · Tramways · Food Chain Magnate",
        tag="@msedizioni @nacheramosart",
        corretta="Food Chain Magnate"),
    # SETI: la 00e, i dischetti trasparenti sulla plancia personale coi palazzi, nessun nome
    # di pianeta (le altre quattro hanno Venere, Giove, Mercurio o la Stella di Barnard
    # leggibili). Fantascienza con segnalini trasparenti: Shackleton Base (la base lunare,
    # stessa Cranio) e Beyond the Sun. Scelti con Paolo il 15/9.
    "10-11 SETI": dict(   # in coda per lunedì 12/10, storia la domenica sera
        foto=f"{FOTO}/Set_storia.jpg", giorno="lunedì",
        opzioni="Shackleton Base · SETI · Beyond the Sun",
        tag="@craniocreations_official",
        corretta="SETI"),
    # Architetti: la 00d, monete e risorse sulla mappa del villaggio, senza le carte dei
    # personaggi (lo stile di The Mico è uguale in tutta la linea). I distrattori sono gli
    # altri due della trilogia: si deve riconoscere il gioco dentro la famiglia. 15/9.
    "01-06 Architetti del Regno Occidentale": dict(
        foto=f"{FOTO}/Arc_storia.jpg", giorno="mercoledì",
        opzioni="Architetti del Regno Occidentale · Paladini del Regno Occidentale · Visconti del Regno Occidentale",
        tag="@ghenosgames @garphillgames",
        corretta="Architetti del Regno Occidentale"),
    # Caylus 1303: la 00c, il mucchio di pezzi di legno senza tabellone (il Prevosto a
    # cavallo nelle altre lo tradisce). I distrattori sono i giochi "pieni di risorse" già
    # usati con lo stesso ruolo: Skara Brae e Alle Porte di Loyang. Il quiz più difficile
    # del giro. Scelti con Paolo il 15/9.
    "01-08 Caylus 1303": dict(
        foto=f"{FOTO}/Cay_storia.jpg", giorno="venerdì",
        opzioni="Skara Brae · Caylus 1303 · Alle Porte di Loyang",
        tag="@space_cowboys_officiel",
        corretta="Caylus 1303"),
    # Nidavellir: la 00, le monete con le rune nel vassoio (EXIF a 180°, raddrizzata).
    # Monete di legno con simboli nordici: i distrattori sono due vichinghi con gettoni,
    # Raiders of the North Sea e A Feast for Odin. Scelti con Paolo il 15/9.
    "01-11 Nidavellir": dict(
        foto=f"{FOTO}/Nid_storia.jpg", giorno="lunedì",
        opzioni="Raiders of the North Sea · Nidavellir · A Feast for Odin",
        tag="@studiosupernova_games",
        corretta="Nidavellir"),
    # Valparaíso: la 00d, meeple e casette colorate sulla costa. Gioco poco noto, quindi i
    # distrattori sono due porti coloniali più famosi di lui: Puerto Rico e Maracaibo.
    # Scelti con Paolo il 15/9.
    "01-13 Valparaíso": dict(
        foto=f"{FOTO}/Val_storia.jpg", giorno="mercoledì",
        opzioni="Puerto Rico · Valparaíso · Maracaibo",
        tag="@craniocreations_official",
        corretta="Valparaíso"),
    # Through the Ages: la 00b, le carte (James Cook, Codice di Leggi) e i cubi sulla plancia.
    # Distrattori di Paolo: Beyond the Horizon (2024, civiltà con leader lungo le ere,
    # verificato su BGG il 15/9) e Nations, il clone dichiarato.
    "01-15 Through the Ages": dict(
        foto=f"{FOTO}/Tta_storia.jpg", giorno="venerdì",
        opzioni="Beyond the Horizon · Through the Ages · Nations",
        tag="@craniocreations_official",
        corretta="Through the Ages"),
    # Caverna: la 00b, animali di legno sui campi. Sembra Agricola uguale, e i distrattori
    # sono i Rosenberg agricoli: Agricola (la CTA del post) e Fields of Arle. 15/9.
    "01-18 Caverna": dict(
        foto=f"{FOTO}/Cav_storia.jpg", giorno="lunedì",
        opzioni="Agricola · Caverna · Fields of Arle",
        tag="@asmodee_it",
        corretta="Caverna"),
    # Stone Age: la 02, cinque dadi di legno e meeple senza il villaggio. Dadi per i
    # lavoratori: Kingsburg e Santa Maria. Scelti con Paolo il 15/9.
    "01-20 Stone Age": dict(
        foto=f"{FOTO}/Sto_storia.jpg", giorno="mercoledì",
        opzioni="Kingsburg · Stone Age · Santa Maria",
        tag="@giochiuniti",
        corretta="Stone Age"),
    # Calimala: la 00b, il tabellone delle rotte con Bruges e Hamburg. Distrattori
    # scelti da Paolo il 18/9: Yokohama e Istanbul, entrambi con lo stesso colpo
    # d'occhio di mappa/plancia commerciale colorata. Posizione 1 per bilanciare
    # (2 era a 35 contro 13 e 13). Autore verificato il 18/9: @f_lopiano.
    "09-20 Calimala": dict(
        foto=f"{FOTO}/Clm_storia.jpg", giorno="lunedì",
        opzioni="Calimala · Yokohama · Istanbul: Big Box",
        tag="@alleycatgames @f_lopiano",
        corretta="Calimala"),
    # Forest Shuffle: la 00d, il mazzo sparso (aquila, allocco, volpe, lepre, alberi):
    # non si vede la fila impilata che lo identifica. Distrattori PROPOSTI, da
    # scelti con Paolo il 21/9: Earth (bgg 350184, tableau di carte su flora e fauna, niente Wingspan) e Ark Nova
    # (carte di animali realistici, per gli esperti). Data provvisoria, non in coda.
    # Kosch senza handle, si tagga solo l'editore.
    "01-22 Forest Shuffle": dict(
        foto=f"{FOTO}/FSH_storia.jpg", giorno="venerdì",
        opzioni="Earth · Forest Shuffle · Ark Nova",
        tag="@asmodee_it",
        corretta="Forest Shuffle"),
    # Coffee Rush: la 00d, il mucchio di ingredienti (caramello, chicchi, foglie,
    # ghiaccio) senza tazzine né baristi: potrebbe essere qualsiasi gioco di cucina.
    # Distrattori scelti con Paolo il 21/9: Kitchen Rush (stesso mondo e
    # stesso "Rush") e Chai (spezie e foglie di tè come ingredienti). Data
    # provvisoria, non in coda. Euijin Han senza handle, solo l'editore.
    "01-25 Coffee Rush": dict(
        foto=f"{FOTO}/CRU_storia.jpg", giorno="lunedì",
        opzioni="Kitchen Rush · Chai · Coffee Rush",
        tag="@asmodee_it",
        corretta="Coffee Rush"),
    # Creature Comforts: la 00c (meeple animali di legno davanti alla tana), la stessa
    # della copertina. Distrattori scelti con Paolo il 21/9: Everdell (bosco,
    # lavoratori animali di legno, stesso genere) e Root (meeple animali serigrafati,
    # lo conoscono tutti). Data provvisoria, non in coda. Autrice senza Instagram:
    # editori entrambi, LRG (la nostra scatola) e Cranio (la ristampa), deciso da Paolo.
    # Glen More II: la 00f, il castello rosso sulla collina a strati, le monete e il grano sulla
    # plancia personale, senza titolo in vista. I distrattori sono gli altri due giochi scozzesi
    # del magazzino, Isle of Skye e Clans of Caledonia: si riconosce dai pezzi, non dalla Scozia.
    "09-27 Glen More II": dict(   # post lunedì 28/9, storia la domenica sera
        foto=f"{FOTO}/GM2_storia.jpg", giorno="lunedì",
        opzioni="Isle of Skye · Glen More II · Clans of Caledonia",
        tag="@gateongames @dungeondice.it @mariocortese_dd",
        corretta="Glen More II"),
    # Masterland: la 00e, la partita apparecchiata con le carte delle due land (si legge PRATERIA e
    # TUNDRA, non il titolo). Distrattori da giochi di carte fantasy con segnalini, da far validare
    # a Paolo. Giusta al primo posto: prima c'è Glen More II al secondo, dopo Century al terzo.
    "09-29 Masterland": dict(   # post mercoledì 30/9, storia il martedì sera
        foto=f"{FOTO}/ML_storia.jpg", giorno="mercoledì",
        opzioni="Masterland · Res Arcana · Magic: The Gathering",
        tag="@masterland_boardgame @philneverland",
        corretta="Masterland"),
    # Moon Colony Bloodbath: la 00, la plancia con la ruota delle azioni e gli edifici (si leggono i nomi
    # delle carte, non il titolo). Distrattori approvati da Paolo il 28/9. Giusta al primo posto: prima c'è
    # Food Chain Magnate al terzo, dopo Noctiluca al secondo. Prende il posto di Quadropolis (1/10).
    "10-04 Moon Colony Bloodbath": dict(   # post lunedì 5/10, storia la domenica sera
        foto=f"{FOTO}/MCB_cop.jpg", giorno="lunedì",
        opzioni="Moon Colony Bloodbath · Terraforming Mars · Space Base",
        tag="@riograndegames",
        corretta="Moon Colony Bloodbath"),
    "10-06 Monster Freeze": dict(   # post mercoledì 7/10; foto 00c e risposte decise con Paolo il 2/10
        foto=f"{FOTO}/MF_gira.jpg", giorno="mercoledì",
        opzioni="Dobble · Monster Freeze · Virus!",
        tag="@mana_project_design @dontpanicgames",
        corretta="Monster Freeze"),
    "10-11 Doomlings": dict(   # post lunedì 12/10; foto 00c e risposte decise con Paolo il 2/10
        foto=f"{FOTO}/DOOM_gira.jpg", giorno="lunedì",
        opzioni="Doomlings · Pokémon GCC · Evolution",
        tag="@doomlings",
        corretta="Doomlings"),
    "10-15 Race for the Galaxy": dict(   # post venerdì 16/10; foto 00c (i quattro cubetti) scelta da Paolo il 2/10
        foto=f"{FOTO}/RFTG_gira.jpg", giorno="venerdì",
        opzioni="It's a Wonderful World · Roll for the Galaxy · Race for the Galaxy",
        tag="@riograndegames",
        corretta="Race for the Galaxy"),
    "10-20 Pacific": dict(   # post mercoledì 21/10; foto 00d e risposte decise con Paolo il 2/10
        foto=f"{FOTO}/PAC_fine.jpg", giorno="mercoledì",
        opzioni="Pacific · Earth · Vanuatu",
        tag="@riograndegames @sightwise",
        corretta="Pacific"),
    "01-27 Creature Comforts": dict(
        foto=f"{FOTO}/CRC_storia.jpg", giorno="mercoledì",
        opzioni="Everdell · Creature Comforts · Root",
        tag="@littlerocketgames @craniocreations_official",
        corretta="Creature Comforts"),
}


def genera(nome, foto, giorno, opzioni, corretta=None, stile_foto="", guida=False, **_):
    # **_ ingoia le chiavi di STORIE che servono solo altrove, come `tag`, che
    # legge su_drive(). Senza, `python3 storia.py` non parte piu'.
    corpo = storia(foto, "Indovina il gioco", "Che gioco è?",
                   "La risposta nel post di domani.", stile_foto, segna_zona=guida)
    return rasterizza(corpo, nome + ("_guida" if guida else ""))


def posizioni():
    """In che posizione sta la risposta giusta, storia per storia.

    Se sta sempre al primo posto chi risponde impara la scorciatoia e il
    sondaggio smette di misurare qualcosa. Le tre posizioni vanno tenute
    all'incirca in pari. Segnalato da Paolo il 2026-09-01, quando tutti e
    quattordici i file avevano la risposta giusta per prima.
    """
    conteggio = {1: 0, 2: 0, 3: 0}
    righe = []
    for nome, d in STORIE.items():
        opz = [o.strip() for o in d["opzioni"].split("·")]
        if d["corretta"] not in opz:
            raise ValueError(f"{nome}: \"{d['corretta']}\" non e' fra le opzioni")
        i = opz.index(d["corretta"]) + 1
        conteggio[i] += 1
        righe.append((nome, i))
    return righe, conteggio


def su_drive(nome):
    """Copia su Drive l'immagine e un .txt con le tre opzioni del sondaggio,
    una per riga, cosi' dal telefono Paolo ha sia la foto sia le risposte.

    **Si chiama solo quando il post e' entrato in coda su Buffer**, non quando si
    monta il gioco. Regola di Paolo del 2026-09-07: nella cartella Drive ci devono
    stare solo le card dei post pianificati, se no lui la sera si trova trenta
    file con date che slittano e deve cercare quello giusto. La card intanto vive
    in `out/storie/` e non va da nessuna parte.
    """
    import shutil
    d = STORIE[nome]
    png = os.path.join(OUT, nome + ".png")
    shutil.copy(png, os.path.join(DRIVE, nome + ".png"))
    with open(os.path.join(DRIVE, nome + ".txt"), "w", encoding="utf-8") as f:
        f.write("\n".join(o.strip() for o in d["opzioni"].split("·")) + "\n")
        # Chiesto da Paolo il 2026-09-04: dal telefono deve avere sotto mano anche
        # chi taggare, senza aprire il foglio degli editori. Solo le chiocciole,
        # niente hashtag: editore prima, poi gli autori di cui conosciamo l'handle.
        if d.get("tag"):
            f.write("\nTAG: " + d["tag"] + "\n")
    return os.path.join(DRIVE, nome + ".png")



def verifica():
    """Controlla il dizionario STORIE prima di generare qualsiasi cosa.

    Nato il 2026-09-08, dopo che Ratti di Wistar e' uscito senza Danilo Sabia fra i
    tag e che nove storie avevano ancora le date di prima dello slittamento. Sono
    tutti errori che si vedono solo a cose fatte, quindi il controllo va qui e non
    negli occhi di chi rilegge. Stampa e basta, non blocca: sta a chi legge decidere.
    """
    import csv, datetime, unicodedata
    GIORNI = ("lunedi", "martedi", "mercoledi", "giovedi",
              "venerdi", "sabato", "domenica")

    def piatto(t):
        t = unicodedata.normalize("NFKD", t.lower())
        t = "".join(c for c in t if not unicodedata.combining(c))
        return " ".join("".join(c for c in t if c.isalnum() or c == " ").split())

    # Il CSV elenca l'autore una riga per volta, con i nostri giochi nell'ultima
    # colonna. Qui serve il contrario: dal gioco agli handle che gli spettano.
    per_gioco = {}
    csv_autori = os.path.join(os.path.dirname(__file__), "..", "dati",
                              "handle_autori.csv")
    if os.path.exists(csv_autori):
        with open(csv_autori, encoding="utf-8") as f:
            for r in csv.DictReader(f):
                handle = (r.get("Instagram") or "").strip()
                note = (r.get("Note") or "").upper()
                # Un handle che esiste ma non serve a niente non e' un buco: gli
                # account vuoti o non confermati il CSV li segna nelle note, e
                # taggarli non porta ricondivisioni.
                if not handle or "VUOTO" in note or "NON CONFERMATO" in note \
                        or "NON LO GESTISCE" in note or "MORTO" in note:
                    continue
                for g in (r.get("Nostri giochi") or "").split(","):
                    if g.strip():
                        per_gioco.setdefault(piatto(g), set()).add(handle)

    problemi = []
    for nome, d in STORIE.items():
        data, titolo = nome.split(" ", 1)
        mese, gg = (int(x) for x in data.split("-"))

        if not os.path.exists(os.path.join(OUT, nome + ".png")):
            problemi.append("%s: manca il png in out/storie" % nome)

        # La storia esce la sera prima, e il giorno che ci scriviamo sopra e'
        # quello del post.
        post = datetime.date(2026, mese, gg) + datetime.timedelta(days=1)
        atteso = GIORNI[post.weekday()]
        if piatto(d.get("giorno", "")) != atteso:
            problemi.append('%s: giorno "%s", ma il post cade di %s'
                            % (nome, d.get("giorno"), atteso))

        # Il campo che manca e' una dimenticanza, tag=None e' una verifica gia'
        # fatta che non ha trovato nessuno: solo il primo e' un problema.
        if "tag" not in d:
            problemi.append("%s: nessun tag, Paolo dal telefono non sa chi taggare."
                            " Se non c'e' davvero nessuno scrivi tag=None"
                            % nome)
        # Nessun tetto al numero di tag: quelli del .txt finiscono sulla foto e nelle
        # storie, dove non si leggono nel testo e non costano caratteri. Il criterio
        # stretto vale solo per le menzioni dentro la didascalia. Deciso il 2026-09-09.
        tag = d.get("tag") or ""

        # Con piu' autori ne basta uno: la regola dice due se sono tutti e due
        # famosi, e comunque il tetto delle tre menzioni non li farebbe stare.
        possibili = per_gioco.get(piatto(titolo), set())
        if possibili and not any(h in tag for h in possibili):
            problemi.append("%s: nessun autore taggato, il CSV ne ha %s"
                            % (nome, " o ".join(sorted(possibili))))

    for x in problemi:
        print("  ATTENZIONE  " + x, file=sys.stderr)
    return problemi


if __name__ == "__main__":
    import shutil
    problemi = verifica()
    # La versione con la zona dello sticker tratteggiata serviva a verificare la
    # geometria, ora verificata. Non si genera piu' di default: Paolo lo sticker
    # lo sa mettere, e vedersi il tratteggio nelle anteprime confonde e basta.
    # --controlla serve a rileggere il dizionario senza rigenerare niente:
    # senza, un controllo al volo riscrive tutti e trentacinque i png.
    if "--controlla" in sys.argv:
        sys.exit(1 if problemi else 0)
    quali = [a for a in sys.argv[1:] if not a.startswith("--")] or list(STORIE)
    guida = "--guida" in sys.argv
    for nome in quali:
        d = STORIE[nome]
        print(genera(nome, **d))
        if guida:
            print(genera(nome, **d, guida=True))
