This commit is contained in:
relikd
2023-10-02 23:39:20 +02:00
commit 8629b01da3
47 changed files with 1412 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,18 @@
<svg viewBox="0 0 657.3 53.6" xmlns="http://www.w3.org/2000/svg">
<path d="m3.8 53.1c-1 0-1.8-.2-2.6-.6-.8-.5-1.2-1.1-1.2-2v-47.5c0-.8.4-1.4 1.1-1.9.7-.4 1.5-.6 2.3-.6h25.3c.9 0 1.5.4 1.9 1.1s.6 1.5.6 2.2c0 .9-.2 1.7-.6 2.4s-1 1-1.8 1h-21v16.5h11.2c.8 0 1.4.3 1.8.9s.6 1.3.6 2.2c0 .7-.2 1.3-.6 2-.4.6-1 1-1.9 1h-11.3v20.8c0 .9-.4 1.5-1.2 1.9-.7.4-1.6.6-2.6.6z"/>
<path d="m30.2 53.1c-.7 0-1.4-.1-2.2-.4s-1.4-.7-1.9-1.1c-.5-.5-.7-1-.7-1.6 0-.1 0-.4.1-.6l14.4-46.8c.3-.9.9-1.5 1.8-1.9s1.9-.6 3-.6 2.1.2 3.1.6c.9.4 1.5 1.1 1.8 1.9l14.3 46.7c.1.3.1.5.1.6 0 .6-.3 1.1-.8 1.6s-1.1.9-1.9 1.2c-.7.3-1.5.4-2.2.4-.6 0-1.2-.1-1.6-.4-.5-.2-.8-.6-1-1.2l-3-10.2h-17.7l-2.9 10.2c-.1.6-.5 1-1 1.2s-1 .4-1.7.4zm7.3-18h14.4l-7.2-24.7z"/>
<path d="m73.1 53.1c-1 0-1.8-.2-2.4-.7s-.9-1.1-.9-1.7v-47.7c0-.8.4-1.4 1.1-1.9.7-.4 1.5-.6 2.3-.6h13.1c2.6 0 5 .3 7.2 1s4 1.9 5.3 3.7 2 4.4 2 7.7c0 3-.5 5.5-1.6 7.5s-2.6 3.4-4.5 4.2c1.5.6 2.8 1.3 3.9 2.3 1.1.9 2 2.2 2.6 3.7.6 1.6.9 3.6.9 6v1.4c0 3.7-.6 6.6-1.9 8.9-1.2 2.2-3 3.8-5.1 4.8-2.2 1-4.6 1.5-7.3 1.5h-14.7zm4.2-31.6h8.6c2.4 0 4.3-.6 5.4-1.9 1.2-1.2 1.8-3.1 1.8-5.5 0-1.6-.3-3-.9-4s-1.5-1.8-2.6-2.2c-1.1-.5-2.4-.7-3.9-.7h-8.5v14.3zm0 24.8h9c2.6 0 4.6-.7 6-2.1s2.1-3.7 2.1-6.8v-1.2c0-3.2-.7-5.4-2.1-6.7s-3.4-1.9-6-1.9h-9z"/>
<path d="m127.3 53.1c-.8 0-1.6-.2-2.3-.6s-1.1-1.1-1.1-1.9v-47.7c0-.9.4-1.5 1.2-1.9s1.7-.6 2.6-.6c1 0 1.8.2 2.6.6s1.2 1 1.2 1.9v43.4h18.7c.8 0 1.3.3 1.7 1s.6 1.5.6 2.3-.2 1.6-.6 2.3-1 1.1-1.7 1.1h-22.9z"/>
<path d="m159 53.1c-.7 0-1.4-.1-2.2-.4s-1.4-.7-1.9-1.1c-.5-.5-.7-1-.7-1.6 0-.1 0-.4.1-.6l14.3-46.7c.3-.9.9-1.5 1.8-1.9s1.9-.6 3-.6 2.1.2 3.1.6c.9.4 1.5 1.1 1.8 1.9l14.3 46.7c.1.3.1.5.1.6 0 .6-.3 1.1-.8 1.6s-1.1.9-1.9 1.2c-.7.3-1.5.4-2.2.4-.6 0-1.2-.1-1.6-.4-.5-.2-.8-.6-1-1.2l-3-10.2h-17.9l-2.9 10.2c-.1.6-.5 1-1 1.2-.2.1-.7.3-1.4.3zm7.3-18h14.4l-7.2-24.7z"/>
<path d="m201.9 53.1c-1 0-1.8-.2-2.4-.7s-.9-1.1-.9-1.7v-47.7c0-.8.4-1.4 1.1-1.9.7-.4 1.5-.6 2.3-.6h13c2.6 0 5 .3 7.2 1s4 1.9 5.3 3.7 2 4.4 2 7.7c0 3-.5 5.5-1.6 7.5s-2.6 3.4-4.5 4.2c1.5.6 2.8 1.3 3.9 2.3 1.1.9 2 2.2 2.6 3.7.6 1.6.9 3.6.9 6v1.4c0 3.7-.6 6.6-1.9 8.9-1.2 2.2-3 3.8-5.1 4.8-2.2 1-4.6 1.5-7.3 1.5h-14.6zm4.2-31.6h8.6c2.4 0 4.3-.6 5.4-1.9 1.2-1.2 1.8-3.1 1.8-5.5 0-1.6-.3-3-.9-4s-1.5-1.8-2.6-2.2c-1.1-.5-2.4-.7-3.9-.7h-8.5v14.3zm0 24.8h9c2.6 0 4.6-.7 6-2.1s2.1-3.7 2.1-6.8v-1.2c0-3.2-.7-5.4-2.1-6.7s-3.4-1.9-6-1.9h-9z"/>
<path d="m256.5 53.1c-1 0-1.8-.2-2.6-.6s-1.2-1.1-1.2-1.9v-46.4c0-1.4.4-2.4 1.2-3s1.7-.8 2.6-.8 1.7.1 2.4.4 1.3.7 1.9 1.3 1.2 1.5 1.8 2.6l10.1 19.1 10.2-19.1c.6-1.1 1.2-2 1.8-2.6s1.2-1.1 1.8-1.3c.7-.3 1.5-.4 2.4-.4 1 0 1.9.3 2.7.8.8.6 1.2 1.5 1.2 3v46.3c0 .8-.4 1.4-1.2 1.9s-1.7.6-2.6.6c-1 0-1.8-.2-2.6-.6s-1.2-1.1-1.2-1.9v-34.5l-9.6 17.9c-.4.6-.8 1.1-1.3 1.3-.5.3-1 .4-1.5.4-.4 0-.9-.1-1.4-.4-.5-.2-.9-.7-1.2-1.4l-9.6-18.3v35c0 .8-.4 1.4-1.2 1.9s-1.9.7-2.9.7z"/>
<path d="m303.1 53.1c-.7 0-1.4-.1-2.2-.4s-1.4-.7-1.9-1.1c-.5-.5-.7-1-.7-1.6 0-.1 0-.4.1-.6l14.3-46.7c.3-.9.9-1.5 1.8-1.9s1.9-.6 3-.6 2.1.2 3.1.6c.9.4 1.5 1.1 1.8 1.9l14.3 46.7c.1.3.1.5.1.6 0 .6-.3 1.1-.8 1.6s-1.1.9-1.9 1.2c-.7.3-1.5.4-2.2.4-.6 0-1.2-.1-1.6-.4-.5-.2-.8-.6-1-1.2l-3-10.2h-17.9l-2.9 10.2c-.1.6-.5 1-1 1.2-.2.1-.8.3-1.4.3zm7.3-18h14.4l-7.2-24.7z"/>
<path d="m346.4 53.1c-1 0-1.8-.2-2.6-.6s-1.2-1.1-1.2-1.9v-47.7c0-.9.4-1.5 1.2-1.9s1.7-.6 2.6-.6c1 0 1.8.2 2.6.6s1.2 1 1.2 1.9v21.9l17.6-23.3c.5-.7 1.2-1.1 2.2-1.1.6 0 1.3.2 2 .6s1.3.9 1.7 1.5c.5.6.7 1.2.7 1.9 0 .2 0 .4-.1.7s-.2.6-.4.8l-13.8 17.3 16.4 25c.3.4.4.9.4 1.4 0 .6-.2 1.2-.6 1.8s-1 1-1.7 1.4-1.4.5-2.1.5c-.5 0-1-.1-1.5-.3s-.9-.6-1.2-1.1l-14.7-22.2-4.7 5.9v15c0 .8-.4 1.4-1.2 1.9s-1.9.6-2.8.6z"/>
<path d="m385 53.1c-.8 0-1.6-.2-2.3-.6s-1.1-1.1-1.1-1.9v-47.6c0-.8.4-1.4 1.1-1.9s1.5-.6 2.3-.6h25.6c.9 0 1.6.4 1.9 1.1.4.7.6 1.5.6 2.2 0 .9-.2 1.7-.6 2.4s-1.1 1-1.9 1h-21.4v16.5h11.1c.8 0 1.4.3 1.9.9.4.6.6 1.3.6 2.2 0 .7-.2 1.3-.6 2-.4.6-1 1-1.9 1h-11.1v16.6h21.4c.8 0 1.4.3 1.9 1 .4.7.6 1.5.6 2.4 0 .8-.2 1.5-.6 2.2s-1 1.1-1.9 1.1z"/>
<path d="m447.5 53.3c-.6 0-1.2-.2-1.7-.6s-.9-1-1.3-1.6l-10.5-20.6h-7.2v20.1c0 .8-.4 1.4-1.2 1.9s-1.7.6-2.6.6c-1 0-1.8-.2-2.6-.6s-1.2-1.1-1.2-1.9v-47.7c0-.7.2-1.2.7-1.7s1.1-.7 1.9-.7h13.7c3 0 5.8.4 8.3 1.3s4.5 2.4 6 4.5 2.2 5.1 2.2 8.8c0 2.9-.4 5.3-1.3 7.2s-2.1 3.4-3.6 4.6c-1.5 1.1-3.2 2-5.1 2.5l10.1 18.9c.1.1.2.3.2.5s.1.4.1.5c0 .6-.2 1.2-.7 1.8s-1.1 1.1-1.8 1.5c-.9.5-1.6.7-2.4.7zm-20.7-29h8.6c2.7 0 4.8-.6 6.4-1.9s2.4-3.5 2.4-6.6-.8-5.3-2.4-6.6-3.8-1.9-6.4-1.9h-8.6z"/>
<path d="m486.6 53.6c-3.1 0-5.9-.5-8.3-1.4s-4.3-2-5.6-3.3-2-2.6-2-3.8c0-.6.2-1.2.5-1.8s.7-1.2 1.2-1.6c.5-.5 1-.7 1.6-.7.7 0 1.3.3 1.9.8.6.6 1.3 1.2 2.2 2s1.9 1.4 3.2 2 3 .9 5 .9c1.7 0 3.3-.3 4.6-.8 1.4-.6 2.4-1.4 3.2-2.5s1.2-2.6 1.2-4.3c0-1.8-.4-3.3-1.3-4.5-.8-1.2-2-2.2-3.4-3s-2.9-1.6-4.6-2.2c-1.6-.7-3.3-1.4-5-2.2s-3.2-1.7-4.6-2.8-2.5-2.4-3.3-4.1-1.3-3.7-1.3-6.2c0-2.6.5-4.8 1.5-6.6s2.3-3.2 3.9-4.2c1.6-1.1 3.4-1.8 5.4-2.3s3.9-.7 5.8-.7c1.2 0 2.5.1 4 .3s2.9.5 4.3.9 2.5.9 3.5 1.6c.9.7 1.4 1.5 1.4 2.4 0 .5-.1 1-.4 1.7s-.6 1.2-1 1.7c-.5.5-1 .7-1.8.7-.6 0-1.3-.2-2.1-.7s-1.8-.9-3-1.4-2.8-.7-4.9-.7c-1.7 0-3.3.2-4.6.7-1.4.5-2.4 1.2-3.2 2.1s-1.2 2.2-1.2 3.7.4 2.8 1.3 3.8c.8 1 2 1.8 3.3 2.5 1.4.7 2.9 1.4 4.6 2s3.3 1.4 5 2.2 3.2 1.9 4.6 3.1 2.5 2.7 3.4 4.6c.8 1.8 1.3 4.1 1.3 6.9 0 3.5-.7 6.3-2.1 8.6s-3.4 4-5.8 5.1c-2.4 1-5.2 1.5-8.4 1.5z"/>
<path d="m514 53.1c-1 0-1.8-.2-2.6-.6s-1.2-1-1.2-1.9v-47.7c0-.7.3-1.2.8-1.7.6-.5 1.3-.7 2.1-.7h14c2.9 0 5.6.5 8 1.5s4.3 2.7 5.7 5 2.1 5.4 2.1 9.3v.6c0 3.8-.7 6.9-2.2 9.3-1.4 2.3-3.4 4-5.8 5.1s-5.2 1.6-8.2 1.6h-8.9v17.8c0 .9-.4 1.5-1.2 1.9-.8.3-1.6.5-2.6.5zm3.8-26.4h8.9c2.7 0 4.8-.8 6.3-2.3s2.3-3.9 2.3-7.1v-.9c0-3.2-.8-5.5-2.3-7s-3.6-2.3-6.3-2.3h-8.9z"/>
<path d="m547.3 53.1c-.7 0-1.4-.1-2.2-.4s-1.4-.7-1.9-1.1c-.5-.5-.7-1-.7-1.6 0-.1 0-.4.1-.6l14.4-46.8c.3-.9.9-1.5 1.8-1.9s1.9-.6 3-.6 2.1.2 3.1.6c.9.4 1.5 1.1 1.8 1.9l14.3 46.6c.1.3.1.5.1.6 0 .6-.3 1.1-.8 1.6s-1.1.9-1.9 1.2c-.7.3-1.5.4-2.2.4-.6 0-1.2-.1-1.6-.4-.5-.2-.8-.6-1-1.2l-3-10.2h-17.9l-2.7 10.3c-.1.6-.5 1-1 1.2s-1 .4-1.7.4zm7.3-18h14.4l-7.2-24.7z"/>
<path d="m602.2 53.5c-2.9 0-5.5-.5-8-1.6-2.4-1.1-4.4-2.8-5.8-5.1-1.4-2.4-2.2-5.5-2.2-9.4v-21c0-3.9.7-7 2.2-9.4 1.4-2.4 3.4-4.1 5.8-5.1 2.4-1.1 5.1-1.6 8-1.6 3.3 0 6.2.6 8.6 1.7s4.3 2.7 5.7 4.6 2.1 4.2 2.1 6.7c0 1.6-.3 2.7-.9 3.2s-1.6.8-2.9.8c-1.2 0-2.1-.2-2.7-.6-.7-.4-1-1-1.1-1.9 0-.6-.2-1.4-.4-2.2-.2-.9-.6-1.7-1.1-2.6-.5-.7-1.4-1.4-2.5-2s-2.6-.8-4.5-.8c-2.8 0-4.9.8-6.4 2.3s-2.2 3.9-2.2 7v21c0 3.2.8 5.5 2.3 7s3.7 2.3 6.6 2.3c1.8 0 3.3-.3 4.4-.8 1.1-.6 1.9-1.2 2.4-2.1.5-.8.9-1.7 1.1-2.7.2-.9.3-1.8.4-2.6 0-.9.4-1.6 1.1-1.9.7-.4 1.6-.6 2.6-.6 1.3 0 2.3.3 3 .8.6.5.9 1.6.9 3.2 0 2.6-.7 4.9-2.1 6.9s-3.3 3.6-5.7 4.8c-2.5 1.1-5.4 1.7-8.7 1.7z"/>
<path d="m629.1 53.1c-.8 0-1.6-.2-2.3-.6s-1.1-1.1-1.1-1.9v-47.6c0-.8.4-1.4 1.1-1.9s1.5-.6 2.3-.6h25.6c.9 0 1.6.4 1.9 1.1.4.7.6 1.5.6 2.2 0 .9-.2 1.7-.6 2.4s-1.1 1-1.9 1h-21.4v16.5h11.1c.8 0 1.4.3 1.9.9.4.6.6 1.3.6 2.2 0 .7-.2 1.3-.6 2-.4.6-1 1-1.9 1h-11.1v16.6h21.4c.8 0 1.4.3 1.9 1 .4.7.6 1.5.6 2.4 0 .8-.2 1.5-.6 2.2s-1 1.1-1.9 1.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -0,0 +1,5 @@
<svg viewBox="0 0 547 546.8" xmlns="http://www.w3.org/2000/svg">
<path fill="#0e9a48" d="m208.1 485.8v-65.2c2.3-.9 4.6-2 6.8-3.3 31.1-18.3 34.4-70.4 7.3-116.3s-74.2-68.2-105.3-49.9-34.4 70.4-7.3 116.3c4.4 7.4 9.3 14.2 14.5 20.3v48.4l-67-38.3v-240.1l-23.5-15.5c-21.4 39-33.6 83.7-33.6 131.3 0 147.9 117.4 268.3 264.1 273.2v-28.2z"/>
<path fill="#cb2026" d="m130.3 104.2 41 24.3c-.8 6.7-.8 14.1-.8 16.7.4 36.1 49.2 63.5 102.5 63s91.2-32.8 90.9-64.6c-.3-36.1-35-64.3-88.3-65.9-18-.5-35.4 3.1-43.3 4.6l-29.9-19.1 71-40.5 209.4 121.7 24-13.2c-23.1-38-55.8-70.9-97.1-94.6-128-73.9-290.9-32.3-368.3 92.5l23.8 15z"/>
<path fill="#35469d" d="m490 236.5-44.5 23.3c-1.6-.3-11.5-9.5-13.7-10.8-31.5-17.6-77.9 5.7-103.9 52.2-25.9 46.5-23.7 99.8 7.8 117.3 31.5 17.6 78.5-3.5 104.4-50 4.2-7.5 9.8-24.9 12.4-32.6l37.9-21.9-.2 83.3-208.9 122 .1 27.5c44.4-1.2 89.2-13.4 130.3-37.4 127.6-74.8 172.3-236.9 102.3-366l-24 13.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 914 B

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 70 90" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h70v90h-70z" fill="#ddd"/><g fill="#888"><path d="m66.2 73.1c0 3.6-1 6.6-3 9.1-2.1 2.5-4.5 3.8-7.3 3.8h-41.8c-2.9 0-5.4-1.2-7.3-3.8s-3-5.5-3-9.1c0-2.8.2-5.4.4-7.9s.8-4.9 1.5-7.4 1.7-4.6 2.9-6.4 2.7-3.2 4.6-4.4 4.1-1.7 6.6-1.7c4.3 4.2 9.4 6.2 15.3 6.2s11-2.1 15.3-6.2c2.5 0 4.6.5 6.6 1.7s3.4 2.6 4.6 4.4 2.1 3.9 2.9 6.4c.7 2.5 1.2 5 1.5 7.4s.2 5.1.2 7.9z"/><circle cx="35.1" cy="29.9" r="18.7"/></g></svg>

After

Width:  |  Height:  |  Size: 477 B

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0" />
<title>Member card</title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<link rel="manifest" href="./manifest.json">
</head>
<body>
<div id="card">
<div id="msg" data-load="Loading ...">Loading ...</div>
<div id="pass" class="hidden">
<div class="spin"></div>
<header>
<img src="img/header.svg" height="16" style="margin: 4px">
<img src="img/logo.svg" height="60" style="float: right">
</header>
<main>
<img id="img" src="img/no-img.svg">
<div>
<div><span id="name">Name</span></div>
<div>ID: <span id="member_id">42</span></div>
<div>Valid: <span id="valid">on 1/1/1970</span></div>
</div>
</main>
<footer>
Member card valid <span id="valid">on 1/1/1970</span>
</footer>
</div>
</div>
<script>onResize()</script>
</body>
</html>

View File

@@ -0,0 +1,4 @@
{
"name": "Ausweis",
"display": "fullscreen"
}

View File

@@ -0,0 +1,124 @@
async function decrypt(ciphertext, password) {
const pwUtf8 = new TextEncoder().encode(password);
const pwHash = await crypto.subtle.digest('SHA-256', pwUtf8);
const ctUtf8 = new Uint8Array(ciphertext);
const iv = ctUtf8.slice(0, 12);
const alg = { name: 'AES-GCM', iv: iv, additionalData: iv };
const key = await crypto.subtle.importKey('raw', pwHash, alg, false, ['decrypt']);
try {
const buf = await crypto.subtle.decrypt(alg, key, ctUtf8.slice(12));
return new TextDecoder().decode(buf);
} catch (e) {
throw new Error('Decrypt failed')
}
}
function setError(text) {
document.getElementById('msg').innerText = text;
}
function setFields(elem, fields) {
for (const [k, v] of Object.entries(fields)) {
for (const el of elem.querySelectorAll('#' + k)) {
el.innerText = v;
}
}
}
async function apply(data, password) {
const json = JSON.parse(await decrypt(data, password));
const now = new Date().getTime();
const vA = new Date(json['valid_since'] + 'T00:00:00');
if (vA.getTime() > now) {
return setError('Member card not valid yet');
}
const vZ = new Date(json['valid_until'] + 'T23:59:59');
if (vZ.getTime() < now) {
return setError('Member card expired');
}
const pass = document.getElementById('pass');
const imgElem = pass.querySelector('#img');
if (imgElem) {
if (json['img']) {
imgElem.src = 'data:image;base64,' + json['img'];
} else {
imgElem.src = 'img/no-img.svg';
}
}
setFields(pass, {
name: json['name'],
member_id: json['id'],
org_name: json['org'],
valid: 'on ' + new Date().toLocaleDateString('en'),
});
setFields(pass, json['data']); // may overwrite previous fields
const title = 'Member card for ' + json['name'] + ' ' + json['org'];
document.head.querySelector('title').innerText = title;
document.getElementById('msg').classList.add('hidden');
pass.classList.remove('hidden');
}
async function onLoad() {
// reset previous download
document.getElementById('pass').classList.add('hidden');
const msg = document.getElementById('msg');
msg.innerText = msg.dataset.load;
msg.classList.remove('hidden');
// download new data
const [org, uuid, secret] = location.hash.slice(1).split('/');
if (!org || !uuid || !secret) {
return setError('Invalid URL');
}
const res = await fetch('./data/' + org + '/' + uuid);
if (!res.ok) {
return setError('Error loading\n\n' + res.status + ' ' + res.statusText);
}
try {
const data = await res.arrayBuffer();
await apply(data, secret);
} catch (e) {
setError(e);
}
}
// load and parse data
window.onload = onLoad;
// force reload if hash params change
window.addEventListener('hashchange', onLoad, true);
// -------------
// scale-up card
// -------------
function onResize() {
const card = document.getElementById('card');
const sw = window.innerWidth / card.offsetWidth;
const sh = window.innerHeight / card.offsetHeight;
card.style.scale = Math.min(Math.min(sw, sh) * 0.97, 2);
}
window.addEventListener('resize', onResize, true);
window.addEventListener('orientationchange', onResize, true);
screen?.orientation?.addEventListener('change', onResize, true);
// -----------------
// check for updates
// -----------------
lastUpdate = new Date().getTime();
function needsUpdate() {
// reload page if older than 15min
const now = new Date().getTime();
if (now - lastUpdate > 900_000) {
lastUpdate = now;
onLoad();
}
}
// setInterval(needsUpdate, 1000);
window.addEventListener('focus', needsUpdate, true);
window.addEventListener('pageshow', needsUpdate, true);
window.addEventListener('visibilitychange', function () {
!document.hidden && document.visibilityState !== 'hidden' && needsUpdate();
}, true);

View File

@@ -0,0 +1,125 @@
:root {
--w: 85.6mm;
--h: 54mm;
--r: 3.18mm;
--iw: 2.5cm;
--ih: 3.2cm;
--ratio: 2.5 / 3.2;
}
body {
background: #666;
font-family: sans-serif;
}
#msg {
position: absolute;
top: 50%;
transform: translateY(-50%);
text-align: center;
width: 100%;
}
#card {
position: absolute;
background: #fff;
width: var(--w);
height: var(--h);
top: calc(50% - var(--h)/2);
left: calc(50% - var(--w)/2);
border-radius: var(--r);
box-shadow: 0 0 4px;
}
#pass {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
border-radius: var(--r);
font-size: 3mm;
}
header {
padding: 1mm;
border-radius: var(--r) var(--r) 0 0;
max-height: 6mm;
}
footer {
padding: 1mm 3mm;
border-radius: 0 0 var(--r) var(--r);
}
main {
display: flex;
font-size: 1.2em;
}
main>div {
display: flex;
flex-direction: column;
justify-content: center;
gap: 2mm;
text-shadow: 1px 0 #fff, 0 1px #fff, -1px 0 #fff, 0 -1px #fff,
1px 1px #fff, -1px -1px #fff, 1px -1px #fff, -1px 1px #fff;
}
main>div>div {
display: flex;
gap: 1mm;
}
#img {
max-width: var(--iw);
max-height: var(--ih);
object-fit: cover;
border-radius: 1mm;
margin: 0 2mm;
aspect-ratio: var(--ratio);
}
.hidden {
display: none !important;
}
.spin {
position: absolute;
bottom: 1.2mm;
right: 1.5mm;
width: 2mm;
height: 2mm;
border: .5mm solid transparent;
border-top-color: #fff;
border-bottom-color: #fff;
border-radius: 50%;
animation: spin 2s steps(5) infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@media print {
body {
background: unset;
}
#card {
top: unset;
left: unset;
scale: 1 !important;
}
}
/* Customize appearance */
#pass {
background: url('img/bg.png') 25mm 6mm/60mm no-repeat;
}
footer {
color: #fff;
background: #0E9A48;
}