diff --git a/style.css b/style.css index 71990bb..6653296 100644 --- a/style.css +++ b/style.css @@ -193,16 +193,14 @@ body.full #sound { position: fixed; z-index: 13; top: max(8px, env(safe-area-ins #credits-reel .track { display: flex; gap: 10px; height: 100%; width: max-content; animation: reel 240s linear infinite; } #credits-reel img { flex: none; height: 100%; aspect-ratio: 16 / 9; object-fit: cover; image-rendering: pixelated; border-radius: 6px; border: 2px solid #3a2d42; } #credits-reel img.face { aspect-ratio: 1; border-color: var(--accent); } -#credits-reel img.palio { aspect-ratio: 2 / 3; border-color: var(--accent); } +#credits-reel img.palio { aspect-ratio: auto; border: 0; } /* La fine: il quadro del palio accanto alle parole (sotto, sugli schermi stretti). */ #ending .ending-row { display: flex; align-items: center; justify-content: center; gap: 1.2em; max-width: 92%; min-height: 0; } #ending figure.palio { margin: 0; display: flex; flex-direction: column; align-items: center; gap: .3em; flex: none; } -#ending figure.palio img, #face img.palio { height: min(52vh, 300px); max-height: 46vmin; aspect-ratio: 2 / 3; image-rendering: pixelated; - /* La cornice: legno dorato a gradini, con il passe-partout chiaro fra la cornice e la tela. */ - box-sizing: content-box; padding: 5px; background: #efe3c0; border: 12px solid transparent; - border-image: linear-gradient(135deg, #fbe39a, #c08a3a 22%, #f3cf75 40%, #8a5420 58%, #e0ad55 78%, #6b3f18) 12; - outline: 3px solid #3a230e; box-shadow: inset 0 0 0 1px #c9b48a, 0 0 0 5px #2a1f30, 0 10px 24px rgba(0,0,0,.6); } -#face img.palio { height: min(56vmin, 380px); border-radius: 0; } +/* Il quadro ha già la sua cornice dorata (tools/incornicia.py): solo l'ombra sotto. */ +#ending figure.palio img, #face img.palio { height: min(56vh, 330px); max-height: 50vmin; width: auto; image-rendering: pixelated; + filter: drop-shadow(0 8px 14px rgba(0,0,0,.6)); } +#face img.palio { height: min(62vmin, 420px); border: 0; border-radius: 0; } #ending figure.palio figcaption { font-size: clamp(6.5px, .85vw, 9px); color: var(--dim); max-width: 22em; } #ending .ending-row > div { max-width: 26em; text-align: center; } @media (max-aspect-ratio: 1/1) { #ending .ending-row { flex-direction: column; } #ending figure.palio img { height: 30vh; } } diff --git a/tools/griglia.py b/tools/griglia.py new file mode 100644 index 0000000..7879452 --- /dev/null +++ b/tools/griglia.py @@ -0,0 +1,17 @@ +"""Uno sfondo del gioco ingrandito due volte con sopra la griglia delle coordinate di scena (640x360): serve per +piazzare hotspot, candele ed effetti nel punto giusto. + python3 tools/griglia.py assets/scenes/scuola.png /tmp/griglia-scuola.png""" +import sys +from PIL import Image, ImageDraw + +src, out = sys.argv[1], sys.argv[2] +im = Image.open(src).convert('RGB').resize((1280, 720), Image.NEAREST) +d = ImageDraw.Draw(im, 'RGBA') +for x in range(0, 640, 20): + d.line([(x * 2, 0), (x * 2, 720)], fill=(255, 0, 255, 140 if x % 100 == 0 else 50)) +for y in range(0, 360, 20): + d.line([(0, y * 2), (1280, y * 2)], fill=(255, 0, 255, 140 if y % 100 == 0 else 50)) +for x in range(0, 640, 100): + for y in range(0, 360, 100): + d.text((x * 2 + 3, y * 2 + 2), f'{x},{y}', fill=(255, 255, 0, 255)) +im.save(out) diff --git a/tools/incornicia.py b/tools/incornicia.py new file mode 100644 index 0000000..0a3a75d --- /dev/null +++ b/tools/incornicia.py @@ -0,0 +1,37 @@ +"""Mette un quadro dentro una cornice disegnata col centro e il fuori in magenta pieno (#ff00ff): il magenta diventa +trasparente e il quadro riempie l'apertura senza deformarsi (si taglia quel che avanza). Così la tela resta +identica, e la cornice si può rifare a parte (prompt in prompts/personaggi/cornice-palio.txt). + python3 tools/incornicia.py assets/generated/cornice-palio.png assets/generated/palio-quadro.png assets/generated/palio-incorniciato.png""" +import sys +from PIL import Image + +cornice, quadro, out = sys.argv[1:4] +f = Image.open(cornice).convert('RGBA') +W, H = f.size +px = f.load() + + +def magenta(p): + return p[0] > 200 and p[1] < 80 and p[2] > 200 + + +# L'apertura: dal centro si va nei quattro versi finché c'è magenta. +cx, cy = W // 2, H // 2 +l, r, t, b = cx, cx, cy, cy +while l > 0 and magenta(px[l - 1, cy]): l -= 1 +while r < W - 1 and magenta(px[r + 1, cy]): r += 1 +while t > 0 and magenta(px[cx, t - 1]): t -= 1 +while b < H - 1 and magenta(px[cx, b + 1]): b += 1 +for y in range(H): + for x in range(W): + if magenta(px[x, y]): px[x, y] = (0, 0, 0, 0) +p = Image.open(quadro).convert('RGBA') +ow, oh = r - l + 3, b - t + 3 +k = max(ow / p.width, oh / p.height) +p = p.resize((round(p.width * k), round(p.height * k)), Image.LANCZOS) +x0, y0 = (p.width - ow) // 2, (p.height - oh) // 2 +p = p.crop((x0, y0, x0 + ow, y0 + oh)) +res = Image.new('RGBA', (W, H), (0, 0, 0, 0)) +res.paste(p, (l - 1, t - 1)) +res.alpha_composite(f) +res.crop(res.getbbox()).save(out)