/*
 * Glaze — de CSS-bibliotheek van glig. Losse klassen voor relief, glas, metaal, papier, ruimte en oogsnoep.
 *
 * Geen custom elements, geen javascript, geen afhankelijkheden: je laadt dit blad en schrijft class="glaze-glassy"
 * op wat je maar wilt. Hij hoort bij glig en is daarvoor gemaakt, maar hij heeft glig niet NODIG - een klas op een
 * kaal element werkt overal.
 *
 * Twee regels die het bij elkaar houden:
 *
 * 1. ELK EFFECT KENT ZIJN ONDERGROND. Relief bestaat alleen doordat licht van boven komt en de ondergrond een kleur
 *    heeft; zet je een ingedrukte letter op zwart, dan zie je niets. Daarom leest alles hier uit --glig-sheet in
 *    plaats van harde grijzen aan te nemen. Zet die goed en de rest volgt.
 * 2. GEEN VAN DEZE KLASSEN BEPAALT DE VORM. Ze zeggen niets over breedte, marge of plek - alleen hoe iets eruit
 *    ziet. Zo kun je ze stapelen: class="glaze-pill glaze-glassy glaze-sparkles" doet wat je hoopt.
 *
 * De zes tokens hieronder zijn het contract met de rest van glig, en daarom als enige --glig-*. Alle andere
 * variabelen in dit blad zijn knoppen per element (--pct, --size, --from) en blijven kort.
 *
 *
 * WAAR DIT BLAD ZIT IN HET PLATFORM
 *
 * De componentenbibliotheek doet de FUNCTIONELE varianten: wat iets is en hoe het zich gedraagt. De thema's
 * (design-plain, design-modern, design-glassy) verschuiven dat een beetje binnen de perken van een huisstijl.
 * En Glaze is de enige laag ZONDER plafond - hier mag goud, gescheurd papier, hologram en glitter.
 *
 * Let op het verschil: Glaze is niet uitsluitend over the top, hij is de laag waar over the top MAG. Er zit net
 * zo goed glaze-measure in (een max-width van 68ch) en glaze-scroll-shadow en glaze-kbd. Een glazuurlaag kan dun
 * en doorzichtig zijn of dik en gekleurd, en dat is precies het bereik dat dit blad bestrijkt.
 *
 * Die drie bijten elkaar niet omdat ze over verschillende dingen gaan. Het component levert het gedrag, de klas
 * levert het uiterlijk, en samen is dat een regel:
 *
 *     <glig-switch class="glaze-gold">
 *
 *
 * VIER KLASSEN DIE GEEN KLAS HADDEN MOETEN ZIJN
 *
 * glaze-tabs, glaze-carousel, glaze-drawer en glaze-leaf (het boek) onthouden iets, en CSS kan niets onthouden.
 * Ze doen het daarom met verborgen radio's en checkboxes. Dat werkt, het is mooi, en het is de verkeerde weg:
 * er is geen toetsenbordbediening, geen aria-selected, en je kunt niet naar een plek SPRINGEN - alleen stap voor
 * stap. Vier checkboxes om een boek open te slaan is leuk als kunststukje en vermoeiend als bouwwijze.
 *
 * De regel die daaruit volgt, en die voor alles hierna geldt:
 *
 *     Moet er een verborgen input aan te pas komen om iets te onthouden, dan is het geen klas maar een component.
 *
 * Die vier blijven staan omdat ze iets anders waard zijn dan waarvoor ze bedoeld leken: het zijn SPECIFICATIES.
 * Ze laten precies zien hoe een bladerpaneel eruit moet zien en bewijzen tegelijk wat het kost om het zonder
 * component te doen. De truc onder het boek - de z-index die halverwege de slag omklapt - verhuist gewoon mee naar
 * binnen zodra glig-book bestaat. Zelfde CSS, ander binnenwerk, en dan werken de pijltjestoetsen ook.
 *
 * De andere 185 klassen zijn verf. Die hebben niets nodig, onthouden niets, en plak je op wat er al staat.
 */

:root
{
    /* De ondergrond. Alles hieronder rekent hiermee, dus dit is de enige knop die je meestal hoeft te draaien. */
    --glig-sheet: #eef0f3;
    --glig-ink: #2a2f3a;

    /* Licht valt van linksboven. Draai je dit om, dan wordt elk reliëf op deze pagina zijn eigen tegendeel. */
    --glig-highlight: rgba(255, 255, 255, .9);
    --glig-shadow: rgba(0, 0, 0, .28);

    --glig-radius: 14px;
    --glig-dur: .18s;
}

/* ============================================================ RELIEF
   Ingedrukt of uitgeduwd is dezelfde truc met de schaduwen omgewisseld: licht boven en donker onder leest als
   omhoog, andersom als omlaag. Meer is het niet, en juist daarom werkt het alleen als de ondergrond kleur heeft. */

.glaze-emboss
{
    color: var(--glig-sheet);
    text-shadow: 0 -1px 1px var(--glig-shadow), 0 1px 1px var(--glig-highlight);
}

.glaze-deboss
{
    color: color-mix(in srgb, var(--glig-sheet) 72%, var(--glig-ink));
    text-shadow: 0 1px 1px var(--glig-highlight), 0 -1px 1px var(--glig-shadow);
}

/* Gegraveerd: dezelfde omkering, maar met een echte inktkleur - leesbaarder dan emboss en nog steeds ingedrukt. */
.glaze-engraved
{
    color: color-mix(in srgb, var(--glig-ink) 78%, var(--glig-sheet));
    text-shadow: 0 1.5px 0 var(--glig-highlight);
}

/* ============================================================ ZACHTE KNOPPEN
   Serhats ronde knop, met de getallen uit zijn origineel. De binnenschaduwen doen het werk: boven een lichte rand
   en onder een donkere, zodat het bolt. Bij indrukken verhuist de knop een paar pixels omlaag EN krimpt de
   slagschaduw - dat tweede is wat het echt indrukt in plaats van verschuift. */

.glaze-round-button, .glaze-pill
{
    display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
    padding: 0; border: 0; text-decoration: none; cursor: pointer;
    background: linear-gradient(color-mix(in srgb, var(--glig-sheet) 88%, #000), color-mix(in srgb, var(--glig-sheet) 55%, #fff));
    color: var(--glig-sheet);
    text-shadow: 0 -1px 1px color-mix(in srgb, var(--glig-shadow) 45%, transparent), 1px 1px 1px var(--glig-highlight);
    box-shadow: 0 7px 8px var(--glig-shadow),
                inset 0 4px 3px var(--glig-highlight),
                inset 0 -2px 3px color-mix(in srgb, var(--glig-ink) 25%, transparent);
    transition: all var(--glig-dur) linear;
}

.glaze-round-button { border-radius: 50%; height: 60px; width: 60px; font-size: 34px; }
.glaze-pill { border-radius: 999px; height: 46px; padding: 0 24px; font-size: 16px; font-weight: 600; }

.glaze-round-button:hover, .glaze-pill:hover { color: color-mix(in srgb, var(--glig-ink) 60%, var(--glig-sheet)); }

.glaze-round-button:active, .glaze-pill:active
{
    transform: translate(1px, 4px);
    box-shadow: 0 3px 6px var(--glig-shadow),
                inset 0 4px 3px var(--glig-highlight),
                inset 0 -2px 3px color-mix(in srgb, var(--glig-ink) 25%, transparent);
}

/* Zacht ingedrukt vlak - hetzelfde recept, alleen alle schaduwen naar binnen. Voor invoervelden en groeven. */
.glaze-groove
{
    border-radius: var(--glig-radius); background: var(--glig-sheet);
    box-shadow: inset 3px 3px 6px color-mix(in srgb, var(--glig-ink) 22%, transparent),
                inset -3px -3px 6px var(--glig-highlight);
}

/* En de bolle tegenhanger, zonder knopgedrag. */
.glaze-bump
{
    border-radius: var(--glig-radius); background: var(--glig-sheet);
    box-shadow: 4px 4px 9px color-mix(in srgb, var(--glig-ink) 20%, transparent),
                -4px -4px 9px var(--glig-highlight);
}

/* ============================================================ GLAS
   Glas is niet doorzichtigheid maar VERVAGING: je ziet dat er iets achter zit zonder te kunnen lezen wat. Vandaar
   backdrop-filter en niet enkel een lage alfa. Het lichte randje bovenaan is de dikte van de ruit. */

.glaze-glassy
{
    border-radius: var(--glig-radius);
    background: color-mix(in srgb, var(--glig-sheet) 30%, transparent);
    backdrop-filter: blur(12px) saturate(160%);
    -webkit-backdrop-filter: blur(12px) saturate(160%);
    border: 1px solid color-mix(in srgb, var(--glig-highlight) 70%, transparent);
    box-shadow: 0 8px 26px color-mix(in srgb, var(--glig-ink) 22%, transparent),
                inset 0 1px 0 var(--glig-highlight);
}

/* Een streep licht die bij aanwijzen één keer over het vlak loopt, als over glanzend fotopapier. Alleen een ::after
   erbovenop (pointer-events: none), dus het element houdt zijn eigen inhoud en zijn eigen vorm; het krijgt position:
   relative als het dat nog niet had (:where, dus zonder gewicht). De streep is een achtergrond van twee vlakken breed die
   van links naar rechts schuift: niets steekt buiten het vlak, er is geen overflow nodig. */
:where(.glaze-sheen) { position: relative; }
.glaze-sheen::after
{
    content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
    background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, .5) 50%, transparent 62%) no-repeat;
    background-size: 200% 100%; background-position-x: -100%;
}
.glaze-sheen:hover::after { animation: glaze-sheen .9s ease-out; }
@keyframes glaze-sheen { from { background-position-x: 200%; } to { background-position-x: -100%; } }
@media (prefers-reduced-motion: reduce) { .glaze-sheen:hover::after { animation: none; } }

/* Een knop van gekleurd glas, zoals de stockplaatjes ze tekenen: een afgeronde rechthoek, de kleur diep in het glas (uit
   --glig-sheet), een hard vel licht over de bovenste helft, een dunne donkere rand en een gloed langs de onderkant. Geen
   pil: de hoeken zijn hoeken. Witte letters met een schaduwtje, want de kleur mag van alles zijn. */
.glaze-glass-button
{
    display: inline-flex; align-items: center; justify-content: center; gap: .45em; box-sizing: border-box;
    padding: .45em 1.1em .5em;
    border: 1px solid color-mix(in srgb, var(--glig-sheet) 45%, #000);
    border-radius: 10px;
    /* --glig-gloss is how hard the sheet of light is: .78 is a wet shine, .35 a quiet satin */
    background:
        linear-gradient(rgba(255, 255, 255, var(--glig-gloss, .78)), rgba(255, 255, 255, calc(var(--glig-gloss, .78) * .28)) 46%, rgba(255, 255, 255, 0) 52%),
        radial-gradient(ellipse 100% 70% at 50% 120%, color-mix(in srgb, #fff calc(var(--glig-gloss, .78) * 70%), var(--glig-sheet)), transparent 60%),
        linear-gradient(color-mix(in srgb, var(--glig-sheet) 80%, #fff), var(--glig-sheet) 55%, color-mix(in srgb, var(--glig-sheet) 70%, #000));
    color: var(--_ink, #fff); text-shadow: 0 1px 1px var(--_cast, rgba(0, 0, 0, .45));
    text-decoration: none; cursor: pointer;
    /* the light along the lower rim is a soft glow inside the glass, not a line: a line under a button reads as a seam */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), inset 0 -4px 6px -3px color-mix(in srgb, var(--glig-sheet) 45%, #fff),
                0 6px 14px -5px color-mix(in srgb, var(--glig-sheet) 65%, #000);
    transition: translate var(--glig-dur), box-shadow var(--glig-dur), filter var(--glig-dur);
}
.glaze-glass-button:hover { color: var(--_ink, #fff); translate: 0 -1px; filter: brightness(1.08); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), inset 0 -4px 6px -3px color-mix(in srgb, var(--glig-sheet) 45%, #fff), 0 10px 18px -6px color-mix(in srgb, var(--glig-sheet) 75%, #000); }
.glaze-glass-button:active { translate: 0 1px; filter: brightness(.96); }
/* De letters volgen het glas: wit op donker glas, op licht glas een heel donkere versie van de glaskleur zelf, en het
   schaduwtje eronder andersom. De grens ligt bij lichtheid 62; de stap is een calc die ver voorbij 0 en 100 schiet en
   daar afgekapt wordt. De rand en de slagschaduw volgen ook: een vast deel donkerder dan het glas, zodat licht glas een
   zachte rand krijgt en geen zwarte lijn. Zonder relatieve kleuren (oudere browsers) blijft het wit met een donker
   schaduwtje en een donkere rand. */
@supports (color: lch(from red l c h))
{
    .glaze-glass-button
    {
        --_ink: lch(from var(--glig-sheet) clamp(22, (l - 62) * -99 + 50, 100) c h);
        --_cast: lch(from var(--glig-sheet) clamp(0, (l - 62) * 99 + 50, 100) 0 0 / .45);
        border-color: lch(from var(--glig-sheet) calc(l * .8) c h);
    }
    .glaze-glass-button, .glaze-glass-button:hover
    {
        box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), inset 0 -4px 6px -3px color-mix(in srgb, var(--glig-sheet) 45%, #fff),
                    0 6px 14px -5px lch(from var(--glig-sheet) calc(l * .4) c h / .5);
    }
}
/* an icon in front stands closer to the edge than letters would: a picture has its own rim, letters need the room */
.glaze-glass-button > glig-icon:first-child { margin-left: -.35em; }

/* Vloeibaar glas: een doos die het beeld erachter wazig doorlaat, met een dikke lichtrand bovenaan en een donkere eronder,
   alsof het glas dikte heeft en het licht erin breekt. Voor een vlak waar dingen in liggen, niet voor een knop. */
.glaze-liquid
{
    border-radius: calc(var(--glig-radius) * 1.6);
    background:
        linear-gradient(color-mix(in srgb, var(--glig-highlight) 38%, transparent), transparent 34%),
        color-mix(in srgb, var(--glig-sheet) 26%, transparent);
    backdrop-filter: blur(16px) saturate(150%);
    -webkit-backdrop-filter: blur(16px) saturate(150%);
    /* The edge is light only where the light falls: bright along the top, faint along the sides and the bottom. A rand
       die rondom even wit is leest als een lijn eromheen, niet als de dikte van het glas. */
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--glig-highlight) 22%, transparent),
                inset 0 2px 0 var(--glig-highlight), inset 0 10px 14px -12px var(--glig-highlight),
                inset 0 -18px 30px -24px color-mix(in srgb, var(--glig-ink) 30%, transparent),
                0 18px 40px -22px color-mix(in srgb, var(--glig-ink) 45%, transparent);
}

/* Bevroren glas: dikker, matter, en met een korrel erin zodat het niet als een gladde vlek leest. */
.glaze-frosted
{
    border-radius: var(--glig-radius);
    background:
        radial-gradient(circle at 20% 15%, color-mix(in srgb, var(--glig-highlight) 55%, transparent), transparent 55%),
        color-mix(in srgb, var(--glig-sheet) 55%, transparent);
    backdrop-filter: blur(20px) saturate(120%) brightness(1.06);
    -webkit-backdrop-filter: blur(20px) saturate(120%) brightness(1.06);
    border: 1px solid color-mix(in srgb, var(--glig-highlight) 50%, transparent);
}

/* ============================================================ METAAL EN GLANS
   Wat metaal metaal maakt is niet de kleur maar dat de glans een SCHERPE band is: een geleidelijk verloop leest als
   plastic, een verloop met een harde knik erin leest als geslepen. */

/*
 * Meer stops en KLEINERE stappen ertussen.
 *
 * Mijn eerste versie sprong van bijna wit naar donkergrijs en terug, en dat leest als plastic met een streep erop.
 * Echt metaal weerkaatst een hele kamer, dus de helderheid gaat op en neer in veel kleine golven in plaats van in
 * twee grote. Zeven stops die dicht bij elkaar liggen doen dat; de band is er nog, hij schreeuwt alleen niet meer.
 */
.glaze-metal
{
    background: linear-gradient(147deg, #fbfcfd, #e6eaef 14%, #ccd3db 27%, #eef2f6 40%, #d4dae2 52%,
                                        #b9c1cb 64%, #e2e7ec 78%, #f7f9fb);
    color: #3a4150;
    text-shadow: 0 1px 0 rgba(255, 255, 255, .8);
    border-radius: var(--glig-radius);
    box-shadow: 0 6px 14px var(--glig-shadow), inset 0 1px 0 #fff;
}

.glaze-gold
{
    background: linear-gradient(147deg, #fff9e8, #f3e0a6 14%, #dcb44e 28%, #fff4d2 41%, #e6c063 53%,
                                        #c39a2c 65%, #efd68f 79%, #fff8e4);
    color: #5a3d00;
    text-shadow: 0 1px 0 rgba(255, 255, 255, .55);
    border-radius: var(--glig-radius);
    box-shadow: 0 6px 14px var(--glig-shadow), inset 0 1px 0 rgba(255, 255, 255, .7);
}

/* Zelfde recept, andere grondtoon. Wat ze tot familie maakt is het RITME van de stops, niet de kleur. */
.glaze-silver
{
    background: linear-gradient(147deg, #ffffff, #eef1f4 14%, #cdd3d9 28%, #fafbfc 41%, #dde2e7 53%,
                                        #b6bdc4 65%, #e8ebee 79%, #fdfdfe);
    color: #46505c; text-shadow: 0 1px 0 rgba(255, 255, 255, .85);
    border-radius: var(--glig-radius); box-shadow: 0 6px 14px var(--glig-shadow), inset 0 1px 0 #fff;
}

.glaze-copper
{
    background: linear-gradient(147deg, #ffe9db, #f0bd96 14%, #cf8552 28%, #ffd9be 41%, #dd9b69 53%,
                                        #a9612f 65%, #e3a877 79%, #ffeadd);
    color: #4d2a12; text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
    border-radius: var(--glig-radius); box-shadow: 0 6px 14px var(--glig-shadow), inset 0 1px 0 rgba(255, 255, 255, .6);
}

.glaze-steel
{
    background: linear-gradient(147deg, #dfe6ee, #aab6c4 16%, #8b99a9 30%, #cdd7e2 44%, #94a2b2 57%,
                                        #6f7d8d 70%, #b3c0cd 84%, #e2e9f0);
    color: #eef2f6; text-shadow: 0 1px 1px rgba(0, 0, 0, .45);
    border-radius: var(--glig-radius); box-shadow: 0 6px 14px var(--glig-shadow), inset 0 1px 0 rgba(255, 255, 255, .55);
}

/* Een veeg licht die er bij aanwijzen overheen trekt. Hij staat buiten beeld te wachten, dus hij kost niets tot je
   erover gaat - en hij loopt SCHUIN, want recht over leest als een scanner. */
.glaze-sparkles { position: relative; overflow: hidden; }
.glaze-sparkles::after
{
    content: ""; position: absolute; inset: -60% -120%;
    background: linear-gradient(72deg, transparent 42%, rgba(255, 255, 255, .75) 50%, transparent 58%);
    transform: translateX(-100%); transition: transform .65s ease;
}
.glaze-sparkles:hover::after { transform: translateX(100%); }

/* ============================================================ LICHT
   Neon is een reeks schaduwen van klein-en-fel naar groot-en-flauw. Eén grote gloed leest als onscherp; de stapel
   leest als een buis die brandt. */

.glaze-neon
{
    color: #fff;
    text-shadow: 0 0 4px #fff, 0 0 11px var(--neon, #21d4fd), 0 0 22px var(--neon, #21d4fd),
                 0 0 44px var(--neon, #21d4fd);
}

.glaze-glow-border
{
    border-radius: var(--glig-radius);
    border: 1px solid color-mix(in srgb, var(--neon, #21d4fd) 70%, transparent);
    box-shadow: 0 0 10px color-mix(in srgb, var(--neon, #21d4fd) 55%, transparent),
                inset 0 0 14px color-mix(in srgb, var(--neon, #21d4fd) 26%, transparent);
}

/* ============================================================ KLEUR
   Verlopen in de tekst zelf, in plaats van erachter. */

.glaze-gradient-letters
{
    background: linear-gradient(92deg, var(--from, #ff6fd8), var(--to, #3813c2));
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
}

/* Parelmoer: de kleur verschuift over het OPPERVLAK, niet met de tijd. Dat is wat een schelp doet en een sticker
   niet - je ziet de hele boog tegelijk liggen. */
.glaze-holo
{
    background: linear-gradient(114deg, #ffd1f2, #c2f0ff 22%, #d6ffd8 40%, #fff5c2 58%, #ffd1f2 78%, #c9c2ff);
    color: #3b2f4a;
    border-radius: var(--glig-radius);
    box-shadow: 0 8px 20px var(--glig-shadow), inset 0 1px 0 rgba(255, 255, 255, .85);
}

/* Sticker: een dikke witte rand rondom plus een schaduw eronder. De rand is wat het van het vlak lostrekt. */
.glaze-sticker
{
    border-radius: var(--glig-radius);
    box-shadow: 0 0 0 5px #fff, 0 8px 16px var(--glig-shadow);
}

/* ============================================================ BEWEGING
   Eén klasse die iets levends doet zonder javascript. */

.glaze-breathes { animation: breathe 2.6s ease-in-out infinite; }
.glaze-glints { position: relative; overflow: hidden; }
.glaze-glints::before
{
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(100deg, transparent 38%, rgba(255, 255, 255, .55) 50%, transparent 62%);
    background-size: 260% 100%;
    animation: sweep-shine 2.2s linear infinite;
}
/* Beweging is een keuze van de kijker, niet van ons. Wie in zijn systeem heeft gezegd dat hij er niet tegen kan,
   krijgt hier niets - dat is één regel en het scheelt iemand een hoop. */
@media (prefers-reduced-motion: reduce)
{
    .glaze-breathes, .glaze-glints::before, .glaze-sparkles::after { animation: none; transition: none; }
}

/* ============================================================ UIT HET SPEL
   Deze komen uit het stijlblad van het de/het-spel op taaltaal.nl/game, van Serhat uit 2023. Daar stonden ze tien
   keer herhaald onder pagina-eigen
   selectors - hier staan ze een keer, met een naam. Dat is precies wat er te winnen valt aan zo'n blad: het waren
   nooit stijlen VAN die knoppen, het waren recepten die toevallig daar stonden. */

/*
 * Het knopvlak, en dit is de handtekening van dat hele bestand.
 *
 * Het geheim zit in de HARDE KNIK: twee kleurstops op precies dezelfde plek (10px), waardoor het verloop daar niet
 * overgaat maar breekt. Daarboven zit een glimmend randje, daaronder een rustig verloop naar grijs - samen leest dat
 * als een geborsteld plaatje met licht erop. Een vloeiend verloop van wit naar grijs geeft dat nooit; dan is het
 * gewoon een grijze knop.
 */
.glaze-button-face
{
    background: linear-gradient(#fff, #f3f6f9 10px, #f0f3f6 10px, #d0d3d6);
    border: 1px solid #999;
    border-radius: 8px;
    color: #003388;
    font-weight: 700;
    box-shadow: 0 0 3px rgba(0, 0, 0, .3);
    user-select: none; cursor: pointer;
}

.glaze-button-face:hover { background: linear-gradient(#336699, #223366); border-color: navy; color: #fff; }

/* De opvallende stand uit datzelfde blad: roze met een derde stop op 150%, dus je ziet alleen het begin van de
   donkere helft. Dat is waarom hij vol lijkt en niet uitgewassen. */
.glaze-standout
{
    background: linear-gradient(#ff66aa, #e03377, #991144 150%);
    border: 2px solid navy; color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}

/* Een veld dat INGEDRUKT staat: wit vlak met de schaduw naar binnen. Het tegenovergestelde van knopvlak, en samen
   vertellen ze de kijker wat hij mag aanraken en wat niet. */
.glaze-pressed
{
    background: #fff; border: 1px solid #999; border-radius: 15px;
    box-shadow: inset 1px 1px 3px rgba(0, 0, 0, .4);
    color: navy;
}

/*
 * De reuzentitel: zes schaduwen die samen een blok vormen.
 *
 * De eerste drie liggen bijna op elkaar en maken de DIKTE van de letter; de laatste drie worden groter en vager en
 * maken de schaduw die het blok op de achtergrond werpt. Die tweedeling is het hele effect - alleen dikte leest als
 * omlijning, alleen schaduw leest als zweven.
 */
.glaze-giant-title
{
    color: #fff; font-size: 40px; font-weight: 800;
    text-shadow: 1px 1px 1px #999, 1px 1px 1px #999, 1px 2px 1px #999,
                 1px 3px 1px rgba(16, 16, 16, .3), 1px 4px 2px rgba(16, 16, 16, .3),
                 1px 5px 10px rgba(16, 16, 16, .4);
}

/* Het gouden woordplaatje: twee binnenschaduwen in de kleur zelf, licht van linksboven en donker van rechtsonder.
   Omdat ze GEEL zijn en niet wit of zwart, blijft het goud in plaats van grijs te worden. */
.glaze-gold-plate
{
    background: gold; border: 1px solid #776633; border-radius: 10px;
    box-shadow: inset 2px 2px 3px #f0f000, inset -2px -2px 3px #b0b000, 0 0 8px rgba(0, 0, 0, .5);
    color: #3a3000;
}

/* Een balk met een glans erover. De glans is een apart laagje dat alleen de bovenste helft pakt - dat is wat het
   bol maakt. En de rechterhoek is ronder dan de linker, zodat hij een KOP heeft en een staart. */
.glaze-bar { position: relative; border-radius: 3px 25px 25px 3px; height: 25px; overflow: hidden;
        background: linear-gradient(to top, #00b300, #006600, #004d00 200%);
        box-shadow: 0 1px 3px rgba(0, 0, 0, .3); }
.glaze-bar::before { content: ""; position: absolute; inset: 0; border-radius: inherit;
                background: linear-gradient(rgba(255, 255, 255, .6), rgba(255, 255, 255, 0) 50%); }

/* Een rij knoppen die als EEN ding leest: alleen de buitenste hoeken zijn rond en de naden delen hun rand. */
.glaze-group { display: inline-flex; }
.glaze-group > * { border-radius: 0; margin: 0; }
.glaze-group > * + * { border-left: 0; }
.glaze-group > :first-child { border-radius: 8px 0 0 8px; }
.glaze-group > :last-child { border-radius: 0 8px 8px 0; }

/*
 * Het gordijn: twee helften die scheef wegklappen.
 *
 * Het aardige is het draaipunt. De linkerhelft draait om haar RECHTERbovenhoek en de rechterhelft om haar
 * linkerbovenhoek, dus ze zwaaien uit elkaar als een theatergordijn in plaats van weg te schuiven. Zonder die
 * transform-origin is het een schuifdeur.
 */
.glaze-curtain { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.glaze-curtain > * { position: absolute; top: 0; bottom: 0; width: 50%;
               background: repeating-linear-gradient(to right, #c62828, #7f0000 20px);
               transition: transform .3s; }
.glaze-curtain > :first-child { left: 0; transform-origin: top right; transform: translateX(-100%) rotate(15deg); }
.glaze-curtain > :last-child { right: 0; transform-origin: top left; transform: translateX(100%) rotate(-15deg); }
.glaze-curtain.glaze-closed > * { transform: none; }

/* ============================================================ MATERIALEN
   Metaal hierboven is glans; deze hebben STRUCTUUR. Het verschil is dat je bij glans het licht ziet en bij structuur
   het oppervlak - en dat laatste maak je met herhaling, niet met een verloop. */

/* Hout: banen van verschillende breedte, want gelijke banen lezen als streepjespapier. De tweede laag ligt er schuin
   overheen en breekt de regelmaat, zoals nerf dat doet. */
.glaze-wood
{
    background:
        repeating-linear-gradient(91deg, rgba(90, 50, 20, .16) 0 2px, transparent 2px 9px,
                                         rgba(90, 50, 20, .09) 9px 11px, transparent 11px 23px),
        linear-gradient(97deg, #b5722f, #a4642a 30%, #c07e38 55%, #9a5c26 78%, #b06f2d);
    color: #fff3e2; text-shadow: 0 1px 2px rgba(0, 0, 0, .5);
    border-radius: var(--glig-radius); box-shadow: 0 6px 14px var(--glig-shadow), inset 0 1px 0 rgba(255, 255, 255, .22);
}

/* Marmer: twee vage vlekverlopen en dan de aders er dun overheen. De aders moeten SCHUIN en ongelijk liggen -
   evenwijdige aders lezen als behang. */
.glaze-marble
{
    background:
        linear-gradient(72deg, transparent 46%, rgba(120, 130, 150, .5) 47%, transparent 48%),
        linear-gradient(63deg, transparent 61%, rgba(120, 130, 150, .32) 62%, transparent 63.4%),
        linear-gradient(104deg, transparent 27%, rgba(140, 150, 170, .28) 28%, transparent 29%),
        radial-gradient(circle at 25% 20%, #ffffff, transparent 60%),
        radial-gradient(circle at 75% 80%, #e7eaf0, transparent 65%),
        #f2f4f7;
    color: #39404d; border-radius: var(--glig-radius);
    box-shadow: 0 6px 14px var(--glig-shadow), inset 0 1px 0 #fff;
}

/* Leer: een fijne korrel uit twee kruisende herhalingen, met een naad langs de rand. De binnenschaduw maakt het
   zacht - zonder die schaduw is het gewoon bruin papier. */
.glaze-leather
{
    background:
        repeating-linear-gradient(58deg, rgba(0, 0, 0, .05) 0 1px, transparent 1px 4px),
        repeating-linear-gradient(-52deg, rgba(255, 255, 255, .05) 0 1px, transparent 1px 5px),
        linear-gradient(150deg, #6b4230, #4e2f21 55%, #5d3927);
    color: #f2e3d8; text-shadow: 0 1px 2px rgba(0, 0, 0, .55);
    border-radius: var(--glig-radius);
    box-shadow: inset 0 0 22px rgba(0, 0, 0, .45), inset 0 0 0 1px rgba(255, 255, 255, .1),
                0 6px 14px var(--glig-shadow);
}

/* Linnen: twee kruisende strepenlagen op halve dekking. Dat is letterlijk hoe geweven stof werkt, dus het klopt
   ook van dichtbij. */
.glaze-linen
{
    background:
        repeating-linear-gradient(90deg, rgba(0, 0, 0, .045) 0 1px, transparent 1px 3px),
        repeating-linear-gradient(0deg, rgba(0, 0, 0, .045) 0 1px, transparent 1px 3px),
        #e9e3d6;
    color: #4a4234; border-radius: var(--glig-radius);
    box-shadow: 0 5px 12px var(--glig-shadow), inset 0 0 0 1px rgba(0, 0, 0, .06);
}

/* Beton: onregelmatige vlekken uit een paar radiale verlopen op verschillende plekken. Regelmaat is hier de vijand,
   dus de middelpunten liggen met opzet niet netjes. */
.glaze-concrete
{
    background:
        radial-gradient(circle at 17% 31%, rgba(0, 0, 0, .07), transparent 42%),
        radial-gradient(circle at 68% 19%, rgba(0, 0, 0, .05), transparent 38%),
        radial-gradient(circle at 41% 78%, rgba(0, 0, 0, .06), transparent 45%),
        radial-gradient(circle at 88% 63%, rgba(255, 255, 255, .5), transparent 40%),
        #b8bcc0;
    color: #2f3336; border-radius: 6px;
    box-shadow: 0 5px 12px var(--glig-shadow), inset 0 1px 0 rgba(255, 255, 255, .35);
}

/* Email: een dikke laag glazuur op een kleur. Eén scherpe lichtvlek bovenaan en een zachte gloed onderaan - dat
   tweede is licht dat door de laag heen weer omhoog komt, en dat is wat het DIK maakt. */
.glaze-enamel
{
    background:
        radial-gradient(ellipse at 50% 118%, rgba(255, 255, 255, .35), transparent 60%),
        radial-gradient(ellipse at 32% -12%, rgba(255, 255, 255, .9), transparent 52%),
        linear-gradient(var(--enamel, #e0396b), color-mix(in srgb, var(--enamel, #e0396b) 62%, #000));
    color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
    border-radius: 999px; box-shadow: 0 7px 16px var(--glig-shadow), inset 0 -2px 6px rgba(0, 0, 0, .3);
}

/* Rubber: mat, en dat betekent GEEN scherpe lichtvlek. Alleen een hele brede, hele flauwe. */
.glaze-rubber
{
    background: radial-gradient(ellipse at 40% 12%, rgba(255, 255, 255, .12), transparent 70%), #2b2f36;
    color: #cdd3da; border-radius: var(--glig-radius);
    box-shadow: 0 5px 12px rgba(0, 0, 0, .5), inset 0 0 0 1px rgba(255, 255, 255, .06);
}

/* ============================================================ BOL GLAS
   Een lens, geen ruit. Drie dingen samen maken de bolling: een lichtvlek linksboven, een donkere ring langs de rand
   waar het glas dikker is, en een tweede lichtvlek onderaan - dat is licht dat er aan de andere kant weer uit komt.
   Laat je die laatste weg, dan is het een knoop; laat je de ring weg, dan is het een sticker. */

.glaze-lens
{
    position: relative; border-radius: 50%;
    background:
        radial-gradient(circle at 50% 128%, rgba(255, 255, 255, .55), transparent 42%),
        radial-gradient(circle at 32% 26%, rgba(255, 255, 255, .95), rgba(255, 255, 255, .12) 34%, transparent 56%),
        radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--glass-color, #6cc7ff) 22%, transparent) 52%,
                                           color-mix(in srgb, var(--glass-color, #6cc7ff) 62%, transparent) 100%);
    backdrop-filter: blur(2px) saturate(150%);
    -webkit-backdrop-filter: blur(2px) saturate(150%);
    box-shadow:
        inset 0 0 14px 6px color-mix(in srgb, var(--glass-color, #6cc7ff) 45%, transparent),
        inset 0 -6px 12px rgba(255, 255, 255, .45),
        0 10px 22px var(--glig-shadow);
}

/* De scherpe glimmer die er bovenop ligt. Apart, omdat hij NIET mee mag vervormen met de rest. */
.glaze-lens::after
{
    content: ""; position: absolute; left: 16%; top: 9%; width: 42%; height: 26%;
    border-radius: 50%; background: linear-gradient(rgba(255, 255, 255, .95), rgba(255, 255, 255, .1));
    filter: blur(1px);
}

/* Een druppel: hetzelfde idee maar met één ronde hoek eruit, zodat hij hangt in plaats van te zweven. */
.glaze-droplet
{
    border-radius: 50% 50% 50% 8%;
    background:
        radial-gradient(circle at 34% 28%, rgba(255, 255, 255, .95), transparent 46%),
        radial-gradient(circle at 62% 76%, rgba(255, 255, 255, .5), transparent 42%),
        color-mix(in srgb, var(--glass-color, #6cc7ff) 30%, transparent);
    backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
    box-shadow: inset 0 0 12px color-mix(in srgb, var(--glass-color, #6cc7ff) 50%, transparent),
                0 8px 18px var(--glig-shadow);
}

/* ============================================================ ONDERDELEN
   Geen elementen, geen javascript - maar wel dingen die zich als een onderdeel gedragen. */

.glaze-card
{
    border-radius: 16px; background: var(--glig-sheet); padding: 16px;
    box-shadow: 0 1px 2px color-mix(in srgb, var(--glig-ink) 12%, transparent),
                0 8px 24px color-mix(in srgb, var(--glig-ink) 14%, transparent);
    transition: transform .22s cubic-bezier(.2, .8, .3, 1), box-shadow .22s;
}
.glaze-card:hover { transform: translateY(-3px);
               box-shadow: 0 2px 4px color-mix(in srgb, var(--glig-ink) 12%, transparent),
                           0 16px 34px color-mix(in srgb, var(--glig-ink) 20%, transparent); }

/* Een schakelaar uit een checkbox. De knop schuift met een veerachtige curve - lineair leest als een schuifje,
   met overshoot leest als een klik. */
.glaze-switch { display: inline-flex; align-items: center; cursor: pointer; }
.glaze-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.glaze-switch i
{
    width: 52px; height: 30px; border-radius: 999px; position: relative; display: block;
    background: color-mix(in srgb, var(--glig-ink) 22%, var(--glig-sheet));
    box-shadow: inset 0 2px 4px color-mix(in srgb, var(--glig-ink) 25%, transparent);
    transition: background .22s;
}
.glaze-switch i::after
{
    content: ""; position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%;
    background: linear-gradient(#fff, #e7eaee);
    box-shadow: 0 2px 5px rgba(0, 0, 0, .3);
    transition: transform .26s cubic-bezier(.34, 1.56, .64, 1);
}
.glaze-switch input:checked + i { background: #22c55e; }
.glaze-switch input:checked + i::after { transform: translateX(22px); }

/* Voortgang met een gestreepte vulling die loopt. De streep is 45 graden en herhaalt zich, dus hij kan eindeloos
   schuiven zonder dat je ziet waar hij begint. */
.glaze-progress { height: 14px; border-radius: 999px; overflow: hidden;
             background: color-mix(in srgb, var(--glig-ink) 16%, var(--glig-sheet));
             box-shadow: inset 0 2px 4px color-mix(in srgb, var(--glig-ink) 25%, transparent); }
.glaze-progress > * { height: 100%; border-radius: inherit;
                 background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, .28) 0 8px,
                                                                    transparent 8px 16px),
                                   linear-gradient(var(--bar-color, #3b82f6), color-mix(in srgb, var(--bar-color, #3b82f6) 70%, #000));
                 background-size: 22.6px 22.6px, auto;
                 animation: slide 1s linear infinite; }
/* Een draaier van twee bogen: de ene volledig en flauw, de andere een kwart en fel. Een enkele ring die draait is
   niet te zien draaien, twee wel. */
.glaze-spinner { width: 34px; height: 34px; border-radius: 50%;
           border: 3px solid color-mix(in srgb, var(--glig-ink) 18%, transparent);
           border-top-color: var(--bar-color, #3b82f6);
           animation: spin .8s linear infinite; }
/* Skelet: een grijs blok met een lichtveeg die er overheen loopt. Wat het als LADEN laat lezen is dat de veeg
   doorloopt terwijl er niets gebeurt - stilstand met beweging erin. */
.glaze-skeleton { border-radius: 8px; background: color-mix(in srgb, var(--glig-ink) 12%, var(--glig-sheet));
          position: relative; overflow: hidden; }
.glaze-skeleton::after { content: ""; position: absolute; inset: 0;
                 background: linear-gradient(100deg, transparent 30%,
                             color-mix(in srgb, var(--glig-highlight) 80%, transparent) 50%, transparent 70%);
                 background-size: 220% 100%; animation: sweep-shine 1.4s linear infinite; }

/* Een stip die pulseert met een ring eromheen die uitdijt en vervaagt. De ring is een tweede laag, want hij moet
   groter worden dan de stip zelf. */
.glaze-pulse { position: relative; width: 12px; height: 12px; border-radius: 50%; background: #22c55e; }
.glaze-pulse::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: inherit;
               animation: expand 1.6s ease-out infinite; }
.glaze-badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px;
         font: 600 12px system-ui; background: color-mix(in srgb, var(--glig-ink) 12%, var(--glig-sheet));
         color: color-mix(in srgb, var(--glig-ink) 85%, var(--glig-sheet)); }

/* Een lint over de hoek. Het draait om 45 graden en steekt aan beide kanten uit, want een lint dat precies past
   leest als een driehoekje. */
.glaze-ribbon { position: relative; overflow: hidden; }
.glaze-ribbon > [data-lint]
{
    position: absolute; top: 14px; right: -46px; width: 160px; text-align: center;
    transform: rotate(45deg); font: 700 11px system-ui; letter-spacing: .06em; text-transform: uppercase;
    background: linear-gradient(#ff6fd8, #b8189a); color: #fff; padding: 5px 0;
    box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
}
.glaze-ribbon > [data-lint]::before { content: attr(data-lint); }

/* Een kaartje met perforatie: de gaatjes zijn radiale verlopen die de achtergrond wegknippen. */
.glaze-scalloped
{
    background:
        radial-gradient(circle at 0 50%, transparent 9px, var(--glig-sheet) 9px),
        radial-gradient(circle at 100% 50%, transparent 9px, var(--glig-sheet) 9px);
    background-size: 51% 100%; background-position: left, right; background-repeat: no-repeat;
    filter: drop-shadow(0 6px 12px color-mix(in srgb, var(--glig-ink) 22%, transparent));
}

/* Een omgevouwen hoek: een driehoekje in de kleur van de achtergrond, met een schuine slagschaduw eronder. */
.glaze-corner-curl { position: relative; }
.glaze-corner-curl::after
{
    content: ""; position: absolute; right: 0; bottom: 0; width: 26px; height: 26px;
    background: linear-gradient(135deg, transparent 50%, color-mix(in srgb, var(--glig-ink) 20%, var(--glig-sheet)) 50%);
    box-shadow: -2px -2px 5px rgba(0, 0, 0, .18);
}

/* Uitklapper uit details/summary: geen javascript, en het pijltje draait mee. */
.glaze-disclosure { border-radius: 12px; background: var(--glig-sheet); padding: 2px 14px;
              box-shadow: 0 1px 3px color-mix(in srgb, var(--glig-ink) 16%, transparent); }
.glaze-disclosure > summary { cursor: pointer; padding: 11px 0; font-weight: 600; list-style: none;
                        display: flex; align-items: center; gap: 9px; }
.glaze-disclosure > summary::-webkit-details-marker { display: none; }
.glaze-disclosure > summary::before { content: "\203A"; font-size: 20px; line-height: 0;
                                transition: transform .2s; display: inline-block; }
.glaze-disclosure[open] > summary::before { transform: rotate(90deg); }

/* ============================================================ BEWEGING */

.glaze-floats { animation: float 3.4s ease-in-out infinite; }
/* Een hartslag is twee tikken en dan rust - een gelijkmatige puls leest als een machine. */
.glaze-beats { animation: beat 1.5s ease-in-out infinite; }
.glaze-wobbles { animation: wobble 2.4s ease-in-out infinite; }
.glaze-spins { animation: spin 6s linear infinite; }

/* Een regenboog die rondloopt. Het verloop is twee keer zo breed als het vlak en schuift een hele slag op, dus je
   ziet nooit waar hij begint. */
.glaze-rainbow-run
{
    background: linear-gradient(92deg, #ff6fd8, #ffd166, #6ee7b7, #60a5fa, #a78bfa, #ff6fd8);
    background-size: 300% 100%; animation: arc-slide 5s linear infinite;
    color: #26203a; border-radius: var(--glig-radius);
}
/* Binnenkomen: van iets te klein en iets te laag naar precies goed, met een curve die er net voorbij schiet. */
.glaze-drops-in { animation: fall-in .5s cubic-bezier(.2, 1.3, .4, 1) both; }
@media (prefers-reduced-motion: reduce)
{
    .glaze-floats, .glaze-beats, .glaze-wobbles, .glaze-spins, .glaze-rainbow-run, .glaze-drops-in, .glaze-pulse::after, .glaze-spinner,
    .glaze-progress > *, .glaze-skeleton::after { animation: none; }
}

/* ============================================================ RANDEN EN DIEPTE

   De verlooprand is de aardigste truc van dit hele blad. Een border kan geen verloop hebben, maar je mag WEL twee
   achtergronden stapelen met elk hun eigen doos: de bovenste vult alleen tot aan de rand (padding-box), de onderste
   vult tot en met de rand (border-box). Maak de rand doorzichtig en je kijkt door de bovenste heen precies op de
   rand van de onderste. Geen extra element, geen pseudo, geen masker. */

.glaze-gradient-border
{
    border: 2px solid transparent; border-radius: var(--glig-radius);
    background:
        linear-gradient(var(--glig-sheet), var(--glig-sheet)) padding-box,
        linear-gradient(128deg, var(--from, #ff6fd8), var(--to, #21d4fd)) border-box;
}

/* En dezelfde truc met een verloop dat rondloopt. conic-gradient begint bovenaan en draait, dus met een animatie op
   de hoek krijg je een lichtstreep die om je doos heen kruipt. */
.glaze-spin-border
{
    border: 2px solid transparent; border-radius: var(--glig-radius);
    background:
        linear-gradient(var(--glig-sheet), var(--glig-sheet)) padding-box,
        conic-gradient(from var(--angle, 0deg), #ff6fd8, #21d4fd, #a78bfa, #ff6fd8) border-box;
    animation: border-spin 4s linear infinite;
}
@property --angle { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
/* Een lange schaduw in één richting, opgebouwd uit een reeks steeds verder verschoven kopieën. Vroeger deed je dit
   met veertig box-shadows; met een enkel verloop op een pseudo is het één regel. */
.glaze-long-shadow { position: relative; }
.glaze-long-shadow::after
{
    content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: -1;
    background: linear-gradient(135deg, color-mix(in srgb, var(--glig-ink) 45%, transparent), transparent 70%);
    transform: translate(14px, 14px);
}

/* Een golvende onderrand, geknipt met een masker. Het masker is een herhalend radiaal verloop: waar het doorzichtig
   is, is de doos weg. Zo hoef je de vorm niet na te tekenen. */
.glaze-wave-edge
{
    --wave: 22px;
    mask: radial-gradient(var(--wave) at 50% 0, transparent 99%, #000 100%) repeat-x bottom / calc(var(--wave) * 2)
          var(--wave), linear-gradient(#000, #000) no-repeat top / 100% calc(100% - var(--wave));
    -webkit-mask: radial-gradient(var(--wave) at 50% 0, transparent 99%, #000 100%) repeat-x bottom /
                  calc(var(--wave) * 2) var(--wave), linear-gradient(#000, #000) no-repeat top / 100%
                  calc(100% - var(--wave));
}

/* ============================================================ ACHTERGRONDEN
   Allemaal patronen uit verlopen, dus ze schalen mee en wegen niets. */

/* Ruitjespapier: twee kruisende strepenlagen. De maat zit in een variabele, want die wil je altijd bijstellen. */
.glaze-checks
{
    --check: 22px;
    background-image:
        linear-gradient(color-mix(in srgb, var(--glig-ink) 9%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--glig-ink) 9%, transparent) 1px, transparent 1px);
    background-size: var(--check) var(--check);
}

.glaze-polka
{
    --check: 18px;
    background-image: radial-gradient(color-mix(in srgb, var(--glig-ink) 18%, transparent) 1.4px, transparent 1.5px);
    background-size: var(--check) var(--check);
}

/* Sterrenhemel: drie lagen stippen met verschillende maat en dichtheid, zodat er diepte in zit. Eén laag leest als
   ruis; drie lagen lezen als ver weg en dichtbij. */
.glaze-starfield
{
    background-color: #0b1020;
    background-image:
        radial-gradient(1.4px 1.4px at 18% 22%, #fff, transparent),
        radial-gradient(1.1px 1.1px at 62% 14%, #fff, transparent),
        radial-gradient(1.6px 1.6px at 81% 47%, #fff, transparent),
        radial-gradient(1px 1px at 33% 68%, #dfe8ff, transparent),
        radial-gradient(1.2px 1.2px at 74% 82%, #fff, transparent),
        radial-gradient(circle at 25% 30%, rgba(120, 90, 255, .28), transparent 55%),
        radial-gradient(circle at 78% 70%, rgba(0, 190, 255, .22), transparent 52%);
    color: #e8ecf6;
}

/* Aurora: grote vage kleurvlekken die langzaam langs elkaar schuiven. Het geheim is dat ze allemaal een ANDERE
   snelheid hebben - lopen ze gelijk, dan beweegt het beeld als geheel en zie je er niets van. */
.glaze-aurora
{
    position: relative; overflow: hidden; background: #0d1224;
}
.glaze-aurora::before, .glaze-aurora::after
{
    content: ""; position: absolute; inset: -40%; filter: blur(46px); opacity: .75;
}
.glaze-aurora::before
{
    background:
        radial-gradient(closest-side, #7b5cff, transparent 70%) 20% 30% / 60% 60% no-repeat,
        radial-gradient(closest-side, #17d1e8, transparent 70%) 70% 20% / 55% 55% no-repeat;
    animation: wander 17s ease-in-out infinite alternate;
}
.glaze-aurora::after
{
    background:
        radial-gradient(closest-side, #ff5fbf, transparent 70%) 65% 75% / 55% 55% no-repeat,
        radial-gradient(closest-side, #ffd166, transparent 72%) 25% 80% / 45% 45% no-repeat;
    animation: wander 23s ease-in-out infinite alternate-reverse;
}
/* ============================================================ TEKST */

/* Een glans die door de letters trekt. Werkt alleen omdat de achtergrond op de TEKST geknipt wordt - op het vlak
   zou het een streep over een blok zijn. */
.glaze-text-gloss
{
    background: linear-gradient(100deg, var(--glig-ink) 38%, #fff 50%, var(--glig-ink) 62%);
    background-size: 260% 100%;
    -webkit-background-clip: text; background-clip: text; color: transparent;
    animation: sweep-shine 3.2s linear infinite;
}

/* Getypt: de breedte gaat in stappen omhoog, één teken per stap. steps() is wat het schokkerig maakt, en schokkerig
   is precies wat typen is - een vloeiende breedte leest als een gordijn. */
.glaze-typed
{
    display: inline-block; overflow: hidden; white-space: nowrap;
    border-right: 2px solid currentColor;
    width: 0; animation: type 2.6s steps(var(--chars, 18)) infinite alternate,
                         blink .8s step-end infinite;
}
/* Een neonbord dat FLIKKERT. Onregelmatig, want een gelijkmatig knipperlicht is een alarm en geen kapotte buis. */
.glaze-neon-sign { color: #fff; animation: flicker 4s linear infinite; }
/* Meerdere regels afkappen met een nette puntjes. Dit kan pas sinds line-clamp; daarvoor was het javascript. */
.glaze-clamped { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--lines, 2);
            line-clamp: var(--lines, 2); overflow: hidden; }

/* ============================================================ RUIMTE EN 3D */

/* Kantelen onder de muis. perspective op de OUDER en rotate op het kind - zet je perspective op het kind zelf, dan
   krijgt elk element zijn eigen vluchtpunt en klopt de scene niet meer. */
.glaze-tilts { perspective: 800px; }
.glaze-tilts > * { transition: transform .3s cubic-bezier(.2, .8, .3, 1); transform-style: preserve-3d; }
.glaze-tilts:hover > * { transform: rotateX(7deg) rotateY(-9deg) translateZ(12px); }

/* Een kaart die omslaat. De achterkant staat een halve slag gedraaid te wachten; backface-visibility verbergt wat
   er van je af wijst, en dat is het hele mechaniek. */
.glaze-cover { perspective: 1000px; }
.glaze-cover > * { position: relative; width: 100%; height: 100%; transition: transform .6s;
              transform-style: preserve-3d; }
.glaze-cover:hover > * { transform: rotateY(180deg); }
.glaze-cover > * > * { position: absolute; inset: 0; backface-visibility: hidden; border-radius: inherit;
                  display: grid; place-items: center; }
.glaze-cover > * > :last-child { transform: rotateY(180deg); }

/* Overlappende rondjes, zoals een rij deelnemers. De negatieve marge maakt de stapel en het randje maakt dat je ze
   nog uit elkaar houdt. */
.glaze-stack { display: inline-flex; }
.glaze-stack > * { width: 34px; height: 34px; border-radius: 50%; box-shadow: 0 0 0 3px var(--glig-sheet);
              display: grid; place-items: center; font: 700 13px system-ui; }
.glaze-stack > * + * { margin-left: -11px; }

/* ============================================================ FORMULIER

   Het zwevende label leunt op :placeholder-shown - het veld weet zelf of het leeg is, dus je hebt er geen javascript
   voor nodig. De placeholder moet dan wel een spatie zijn en geen tekst, anders zie je hem staan. */

.glaze-float-label { position: relative; display: block; }
.glaze-float-label > input
{
    width: 100%; box-sizing: border-box; padding: 20px 12px 8px; font: inherit; color: inherit;
    border: 1px solid color-mix(in srgb, var(--glig-ink) 28%, transparent); border-radius: 10px;
    background: color-mix(in srgb, var(--glig-sheet) 70%, #fff); outline: none;
    transition: border-color .18s, box-shadow .18s;
}
.glaze-float-label > span
{
    position: absolute; left: 13px; top: 15px; font-size: 15px; opacity: .6; pointer-events: none;
    transition: transform .16s ease, font-size .16s ease, opacity .16s;
    transform-origin: left top;
}
.glaze-float-label > input:not(:placeholder-shown) + span,
.glaze-float-label > input:focus + span { transform: translateY(-9px) scale(.76); opacity: .9; }
.glaze-float-label > input:focus { border-color: #3b82f6;
                            box-shadow: 0 0 0 3px color-mix(in srgb, #3b82f6 25%, transparent); }

/* :has() is de ouderselector: hier kleurt het HELE veld rood zodra de invoer ongeldig is. Dat was tot voor kort
   javascript, en het is nu één regel. */
.glaze-float-label:has(input:invalid:not(:placeholder-shown)) > input { border-color: #e11d48; }
.glaze-float-label:has(input:invalid:not(:placeholder-shown)) > span { color: #e11d48; opacity: .95; }

/* Een tooltip uit een attribuut. Hij staat er altijd en is alleen onzichtbaar - dat scheelt een element en het
   voorkomt dat hij bij het verschijnen de opmaak verspringt. */
.glaze-tooltip { position: relative; }
.glaze-tooltip::after
{
    content: attr(data-tip); position: absolute; bottom: calc(100% + 8px); left: 50%;
    transform: translate(-50%, 4px); white-space: nowrap; pointer-events: none;
    background: #1c2230; color: #fff; font: 500 12px system-ui; padding: 5px 9px; border-radius: 7px;
    opacity: 0; transition: opacity .16s, transform .16s;
    box-shadow: 0 6px 16px rgba(0, 0, 0, .35);
}
.glaze-tooltip:hover::after, .glaze-tooltip:focus-visible::after { opacity: 1; transform: translate(-50%, 0); }

/* Een fatsoenlijke focusring, apart omdat de standaard van de browser op gekleurde vlakken vaak wegvalt. Twee
   ringen: een donkere en een lichte, zodat er altijd één contrasteert. */
.glaze-focus-ring:focus-visible { outline: 2px solid #fff; outline-offset: 2px;
                           box-shadow: 0 0 0 5px #1c2230; }

@media (prefers-reduced-motion: reduce)
{
    .glaze-spin-border, .glaze-text-gloss, .glaze-typed, .glaze-neon-sign, .glaze-aurora::before, .glaze-aurora::after { animation: none; }
    .glaze-typed { width: auto; }
}

/* ============================================================ PAPIER EN DRUKWERK

   De postzegel is een masker van rondjes langs alle vier de randen. Het aardige: je knipt de doos weg met
   radial-gradient, dus de tanding volgt automatisch elke maat en elke achtergrond. Met een border zou je de gaatjes
   moeten inkleuren in de kleur van wat erachter ligt, en dan klopt het niet meer zodra je het verplaatst. */

.glaze-stamp
{
    --perf: 9px;
    padding: 12px; background: var(--paper, #fff); color: #222;
    filter: drop-shadow(0 5px 10px color-mix(in srgb, var(--glig-ink) 28%, transparent));
    mask:
        radial-gradient(var(--perf) at 50% 0, #0000 98%, #000) repeat-x top / calc(var(--perf) * 2) var(--perf),
        radial-gradient(var(--perf) at 50% 100%, #0000 98%, #000) repeat-x bottom / calc(var(--perf) * 2) var(--perf),
        radial-gradient(var(--perf) at 0 50%, #0000 98%, #000) repeat-y left / var(--perf) calc(var(--perf) * 2),
        radial-gradient(var(--perf) at 100% 50%, #0000 98%, #000) repeat-y right / var(--perf) calc(var(--perf) * 2),
        linear-gradient(#000, #000) no-repeat center / calc(100% - var(--perf) * 2) calc(100% - var(--perf) * 2);
    -webkit-mask:
        radial-gradient(var(--perf) at 50% 0, #0000 98%, #000) repeat-x top / calc(var(--perf) * 2) var(--perf),
        radial-gradient(var(--perf) at 50% 100%, #0000 98%, #000) repeat-x bottom / calc(var(--perf) * 2) var(--perf),
        radial-gradient(var(--perf) at 0 50%, #0000 98%, #000) repeat-y left / var(--perf) calc(var(--perf) * 2),
        radial-gradient(var(--perf) at 100% 50%, #0000 98%, #000) repeat-y right / var(--perf) calc(var(--perf) * 2),
        linear-gradient(#000, #000) no-repeat center / calc(100% - var(--perf) * 2) calc(100% - var(--perf) * 2);
}

/* Een bon met een zigzagrand onderaan, uit een conic-gradient die zich herhaalt. */
.glaze-receipt
{
    --zigzag: 12px; background: var(--paper, #fff); color: #222; padding: 14px 14px calc(var(--zigzag) + 8px);
    filter: drop-shadow(0 5px 12px color-mix(in srgb, var(--glig-ink) 25%, transparent));
    mask: conic-gradient(from -45deg at bottom, #0000 25%, #000 0) repeat-x bottom / var(--zigzag) var(--zigzag),
          linear-gradient(#000, #000) no-repeat top / 100% calc(100% - var(--zigzag));
    -webkit-mask: conic-gradient(from -45deg at bottom, #0000 25%, #000 0) repeat-x bottom / var(--zigzag) var(--zigzag),
                  linear-gradient(#000, #000) no-repeat top / 100% calc(100% - var(--zigzag));
}

/* Gescheurd papier: een onregelmatige rand uit een reeks toevallige punten. Regelmatig scheuren bestaat niet, dus de
   getallen liggen met opzet rommelig. */
.glaze-torn
{
    background: var(--glig-sheet); padding: 14px;
    clip-path: polygon(0 0, 100% 0, 100% 92%, 94% 97%, 88% 91%, 81% 98%, 73% 92%, 66% 99%, 58% 93%,
                       50% 98%, 42% 92%, 35% 98%, 27% 91%, 19% 97%, 11% 92%, 5% 98%, 0 93%);
    filter: drop-shadow(0 4px 8px color-mix(in srgb, var(--glig-ink) 22%, transparent));
}

/* Een geeltje met een omkrullende hoek. De krul is een schaduw die naar BUITEN valt op een gedraaid pseudo-element -
   dat is wat het van het vlak lostrekt. */
.glaze-sticky-note
{
    position: relative; background: linear-gradient(#fff9a8, #ffe94f); color: #4a4200; padding: 16px;
    box-shadow: 0 6px 14px color-mix(in srgb, var(--glig-ink) 30%, transparent);
}
.glaze-sticky-note::after
{
    content: ""; position: absolute; right: 0; bottom: 0; width: 24px; height: 24px;
    background: linear-gradient(135deg, transparent 50%, #e6cf3a 50%);
    box-shadow: -3px -3px 6px rgba(0, 0, 0, .18);
}

/* Gelinieerd papier met een marge: horizontale lijnen uit een herhalend verloop, en één rode verticaal. */
.glaze-ruled
{
    background:
        linear-gradient(90deg, transparent 37px, #ffb4b4 37px, #ffb4b4 39px, transparent 39px),
        repeating-linear-gradient(#fdfdfb 0 25px, #cfe0f0 25px 26px);
    color: #2a3550;
}

/* Een rubberstempel: schuine hoek, dikke rand, en een lichte doorzichtigheid zodat de ondergrond doorschemert -
   dat laatste is wat inkt van verf onderscheidt. */
.glaze-ink-stamp
{
    display: inline-block; transform: rotate(-11deg);
    border: 4px double currentColor; border-radius: 6px; padding: 6px 14px;
    font: 800 17px system-ui; letter-spacing: .12em; text-transform: uppercase;
    color: #c62828; opacity: .78; mix-blend-mode: multiply;
}

/* Een hanglabel met een gat en een touwtje. */
.glaze-hang-tag
{
    position: relative; background: #e8d9b8; color: #4a3c1f; padding: 12px 16px 12px 30px;
    clip-path: polygon(14px 0, 100% 0, 100% 100%, 14px 100%, 0 50%);
    box-shadow: 0 5px 12px color-mix(in srgb, var(--glig-ink) 26%, transparent);
}
.glaze-hang-tag::before { content: ""; position: absolute; left: 16px; top: 50%; width: 8px; height: 8px;
                     border-radius: 50%; background: var(--glig-sheet); transform: translateY(-50%);
                     box-shadow: inset 0 1px 2px rgba(0, 0, 0, .4); }

/* ============================================================ DRIE DIMENSIES

   De kubus is zes vlakken die elk om een andere as gedraaid en dan naar buiten geschoven worden. Twee dingen maken
   of breken het: transform-style op preserve-3d (anders plet de browser alles terug naar plat) en de VOLGORDE -
   eerst draaien, dan verschuiven. Andersom schuif je in de wereldrichting in plaats van in de richting waar het
   vlak nu heen kijkt, en dan valt de doos uit elkaar. */

.glaze-cube { perspective: 800px; }
.glaze-cube > *
{
    position: relative; width: var(--size, 120px); height: var(--size, 120px);
    transform-style: preserve-3d; animation: cube-spin 12s linear infinite;
}
.glaze-cube > * > *
{
    position: absolute; inset: 0; display: grid; place-items: center;
    border: 1px solid color-mix(in srgb, var(--glig-ink) 25%, transparent);
    backface-visibility: visible;
}
.glaze-cube > * > :nth-child(1) { transform: rotateY(0deg) translateZ(calc(var(--size, 120px) / 2)); }
.glaze-cube > * > :nth-child(2) { transform: rotateY(90deg) translateZ(calc(var(--size, 120px) / 2)); }
.glaze-cube > * > :nth-child(3) { transform: rotateY(180deg) translateZ(calc(var(--size, 120px) / 2)); }
.glaze-cube > * > :nth-child(4) { transform: rotateY(-90deg) translateZ(calc(var(--size, 120px) / 2)); }
.glaze-cube > * > :nth-child(5) { transform: rotateX(90deg) translateZ(calc(var(--size, 120px) / 2)); }
.glaze-cube > * > :nth-child(6) { transform: rotateX(-90deg) translateZ(calc(var(--size, 120px) / 2)); }
/* Dezelfde kubus, maar hij draait alleen als je hem aanwijst - en dan een kwartslag, zodat hij van gezicht wisselt.
   Dat is de bruikbare variant: een paneel dat omdraait in plaats van eindeloos tolt.

   --depth moet de HALVE breedte zijn, anders staat het zijvlak binnen de doos en zie je er in perspectief een punt
   van uitsteken. Dat is geen afstelling maar meetkunde: een kubus heeft nu eenmaal een halve ribbe naar opzij. */
.glaze-cube-flip { perspective: 900px; }
.glaze-cube-flip > * { position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
                   transition: transform .7s cubic-bezier(.6, .05, .3, 1); }
.glaze-cube-flip:hover > * { transform: translateZ(calc(var(--depth, 44px) * -1)) rotateY(-90deg); }
.glaze-cube-flip > * > * { position: absolute; inset: 0; display: grid; place-items: center; border-radius: inherit; }
.glaze-cube-flip > * > :first-child { transform: translateZ(var(--depth, 44px)); }
.glaze-cube-flip > * > :last-child { transform: rotateY(90deg) translateZ(var(--depth, 44px)); }

/* Een munt die tolt. Twee kanten, en de achterkant staat gespiegeld te wachten. */
.glaze-coin { perspective: 900px; }
.glaze-coin > * { position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
            animation: coin-spin 3.4s cubic-bezier(.45, .05, .55, .95) infinite; }
.glaze-coin > * > * { position: absolute; inset: 0; border-radius: 50%; display: grid; place-items: center;
                backface-visibility: hidden; }
.glaze-coin > * > :last-child { transform: rotateY(180deg); }
/* Een deur die opengaat om zijn linkerrand. transform-origin is hier alles: zonder die regel draait hij om zijn
   midden en dan is het geen deur maar een molen. */
.glaze-door { perspective: 900px; }
.glaze-door > * { transform-origin: left center; transition: transform .55s cubic-bezier(.4, 0, .2, 1);
            transform-style: preserve-3d; }
.glaze-door:hover > * { transform: rotateY(-72deg); }

/* Een bladzijde die omslaat, met een schaduw die meeloopt zodat het papier dikte krijgt. */
.glaze-page-flip { perspective: 1200px; }
.glaze-page-flip > * { transform-origin: left center; transition: transform .8s ease, box-shadow .8s;
               transform-style: preserve-3d; }
.glaze-page-flip:hover > * { transform: rotateY(-155deg); box-shadow: 22px 0 34px rgba(0, 0, 0, .4); }

/* Binnenzwenken vanaf de zijkant, met perspectief - dat leest heel anders dan schuiven, want het KOMT ergens
   vandaan in plaats van uit het niets. */
.glaze-swing-in { animation: swing-in .6s cubic-bezier(.2, 1.1, .3, 1) both; transform-origin: left center; }
/* ============================================================ TABBLADEN ZONDER JAVASCRIPT

   Het kan, met radio's: de gekozen radio zet een klasse-achtig gedrag aan via :checked, en met :has() kun je vanaf
   de wrapper het bijbehorende vlak aanwijzen. Dat is echt, het werkt, en het is geen truc met verstopte checkboxes
   die vroeger nodig was.

   MAAR - en dit is waar de javascript-component zijn geld verdient: echte tabbladen hebben role=tablist, pijltjes
   naar links en rechts, Home en End, en aria-selected dat meeverandert. Dat kan CSS niet, want dat is gedrag en geen
   uiterlijk. Deze versie is prima voor een demo of een pagina waar je het toetsenbord niet belooft; voor een product
   neem je glig-tabs. */

.glaze-tabs { display: grid; gap: 12px; }
.glaze-tabs > nav { display: flex; gap: 4px; border-bottom: 2px solid color-mix(in srgb, var(--glig-ink) 14%, transparent); }
.glaze-tabs input { position: absolute; opacity: 0; width: 0; height: 0; }
.glaze-tabs > nav label
{
    padding: 9px 16px; cursor: pointer; border-radius: 9px 9px 0 0; font-weight: 600;
    color: color-mix(in srgb, var(--glig-ink) 60%, var(--glig-sheet));
    border-bottom: 2px solid transparent; margin-bottom: -2px; transition: color .15s, border-color .15s;
}
.glaze-tabs > nav label:hover { color: var(--glig-ink); }
.glaze-tabs > div > section { display: none; }

/* Eén regel per tabblad, en met :has() leest de wrapper welke radio aanstaat. */
.glaze-tabs:has(input:nth-of-type(1):checked) > nav label:nth-of-type(1),
.glaze-tabs:has(input:nth-of-type(2):checked) > nav label:nth-of-type(2),
.glaze-tabs:has(input:nth-of-type(3):checked) > nav label:nth-of-type(3)
{ color: var(--glig-ink); border-bottom-color: #3b82f6; }

.glaze-tabs:has(input:nth-of-type(1):checked) > div > section:nth-of-type(1),
.glaze-tabs:has(input:nth-of-type(2):checked) > div > section:nth-of-type(2),
.glaze-tabs:has(input:nth-of-type(3):checked) > div > section:nth-of-type(3)
{ display: block; animation: fall-in .28s ease both; }

/* Een segmentkiezer uit radio's: dezelfde opzet, andere jas. */
.glaze-segment { display: inline-flex; border-radius: 10px; overflow: hidden;
           border: 1px solid color-mix(in srgb, var(--glig-ink) 24%, transparent); }
.glaze-segment input { position: absolute; opacity: 0; width: 0; height: 0; }
.glaze-segment label { padding: 8px 16px; cursor: pointer; font-weight: 600; background: var(--glig-sheet);
                 transition: background .15s, color .15s; }
.glaze-segment label + label { border-left: 1px solid color-mix(in srgb, var(--glig-ink) 18%, transparent); }
.glaze-segment input:checked + label { background: #3b82f6; color: #fff; }

/* Broodkruimels met een pijlpunt tussen de stappen. */
.glaze-breadcrumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 14px; }
.glaze-breadcrumbs > * + *::before { content: "\203A"; margin-right: 8px; opacity: .45; }

/* Een stappenbalk waarin de gedane stappen ingekleurd zijn. De verbindingslijn is een pseudo op elke stap behalve
   de eerste, zodat je nooit een streepje voor de rij hebt hangen. */
.glaze-steps { display: flex; }
.glaze-steps > * { flex: 1; text-align: center; position: relative; font-size: 13px; }
.glaze-steps > * > i
{
    display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; margin: 0 auto 6px;
    background: color-mix(in srgb, var(--glig-ink) 14%, var(--glig-sheet)); font-style: normal; font-weight: 700;
    position: relative; z-index: 1;
}
.glaze-steps > * + *::before
{
    content: ""; position: absolute; left: -50%; top: 15px; width: 100%; height: 3px;
    background: color-mix(in srgb, var(--glig-ink) 14%, var(--glig-sheet));
}
.glaze-steps > .glaze-done > i { background: #22c55e; color: transparent; position: relative; }
/* Het vinkje is getekend en niet getypt: een glyph hangt af van het lettertype dat toevallig geladen is, en dan
   staat er ineens een leeg vierkantje. Twee randen en een halve slag draaien werken overal. */
.glaze-steps > .glaze-done > i::after { content: ""; position: absolute; left: 8px; top: 5px; width: 5px; height: 9px;
                                border: 2px solid #fff; border-top: 0; border-left: 0; transform: rotate(43deg); }
.glaze-steps > .glaze-done::before { background: #22c55e; }
.glaze-steps > .glaze-current > i { background: #3b82f6; color: #fff;
                     box-shadow: 0 0 0 4px color-mix(in srgb, #3b82f6 28%, transparent); }

/* ============================================================ KNOPPEN EN STATEN */

.glaze-button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; cursor: pointer;
        padding: 10px 18px; border-radius: 10px; border: 0; font: 600 15px system-ui; text-decoration: none;
        transition: transform .12s, box-shadow .18s, background .18s; }
.glaze-button:active { transform: translateY(1px); }

.glaze-button-primary { background: #3b82f6; color: #fff; box-shadow: 0 4px 12px color-mix(in srgb, #3b82f6 45%, transparent); }
.glaze-button-primary:hover { background: #2f74e6; box-shadow: 0 6px 18px color-mix(in srgb, #3b82f6 55%, transparent); }
.glaze-button-soft { background: color-mix(in srgb, var(--glig-ink) 10%, var(--glig-sheet)); color: var(--glig-ink); }
.glaze-button-outline { background: transparent; color: var(--glig-ink);
             box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--glig-ink) 30%, transparent); }
.glaze-button-danger { background: #e11d48; color: #fff; box-shadow: 0 4px 12px color-mix(in srgb, #e11d48 42%, transparent); }
.glaze-button-ghost { background: transparent; color: var(--glig-ink); }
.glaze-button-ghost:hover { background: color-mix(in srgb, var(--glig-ink) 8%, transparent); }

/* Een knop met echte hoogte: de onderrand IS de dikte, en bij indrukken zakt de knop er precies in. Daarom moet de
   translate even groot zijn als het verschil in schaduw - anders zweeft hij of zakt hij door de vloer. */
.glaze-button-thick { background: #22c55e; color: #fff; box-shadow: 0 5px 0 #15803d; }
.glaze-button-thick:active { transform: translateY(5px); box-shadow: 0 0 0 #15803d; }

/* Een golf vanuit het midden bij het indrukken, zonder javascript. De verf staat OMGEKEERD: doorzichtig in het
   hart en licht daarbuiten. In rust is de tegel honderdvijftig keer zo groot als de knop, dus je ziet alleen dat
   doorzichtige hart en de knop is schoon. Bij :active springt de tegel naar ware grootte - dan is bijna alles het
   lichte deel - en de overgang laat hem daarna weer uitdijen. Andersom, met licht in het hart, staat de knop in
   rust onder een witte waas; dat had ik eerst en het is meteen te zien. */
.glaze-ripple-button { background-image: radial-gradient(circle, transparent 1%, #ffffff55 1%);
            background-size: 15000% 15000%; background-position: center; transition: background-size .55s; }
.glaze-ripple-button:active { background-size: 100% 100%; transition: 0s; }

/* Een knop die laadt: de tekst schuift weg en er komt een draaiertje voor in de plaats. */
.glaze-button-loading { position: relative; color: transparent !important; pointer-events: none; }
.glaze-button-loading::after { content: ""; position: absolute; inset: 0; margin: auto; width: 17px; height: 17px;
                     border-radius: 50%; border: 2.5px solid #fff6; border-top-color: #fff;
                     animation: spin .7s linear infinite; }

.glaze-disabled { opacity: .45; pointer-events: none; filter: grayscale(.6); }

/* Een zwevende actieknop met een schaduw die meegroeit - dat is wat hem los van de pagina laat lezen. */
.glaze-fab { width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
             background: #3b82f6; color: #fff; font-size: 24px; border: 0;
             box-shadow: 0 6px 16px rgba(0, 0, 0, .3); transition: transform .18s, box-shadow .18s; }
.glaze-fab:hover { transform: translateY(-2px) scale(1.04); box-shadow: 0 10px 24px rgba(0, 0, 0, .38); }

/* ============================================================ DATA

   De ring is een conic-gradient met een gat erin. Het gat is een masker, niet een wit rondje - zo werkt hij ook op
   een gekleurde of gefotografeerde ondergrond, en dat is precies waar het witte rondje altijd sneuvelt. */

.glaze-ring
{
    --pct: 68; --thick: 10px;
    width: 84px; height: 84px; border-radius: 50%; display: grid; place-items: center;
    background: conic-gradient(var(--ring-color, #3b82f6) calc(var(--pct) * 1%),
                               color-mix(in srgb, var(--glig-ink) 13%, var(--glig-sheet)) 0);
    mask: radial-gradient(farthest-side, #0000 calc(100% - var(--thick)), #000 calc(100% - var(--thick) + 1px));
    -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - var(--thick)),
                                  #000 calc(100% - var(--thick) + 1px));
}
/* Wil je een getal in het midden, dan moet dat BUITEN het masker vallen - vandaar de wikkel. */
.glaze-ring-wrap { position: relative; display: inline-grid; place-items: center; }
.glaze-ring-wrap > span { position: absolute; font: 700 17px system-ui; }

/* Een halve meter: dezelfde conic, maar dan over een halve slag en met de doos afgeknipt. */
.glaze-gauge
{
    --pct: 62;
    width: 110px; height: 55px; overflow: hidden; position: relative;
}
.glaze-gauge::before
{
    content: ""; position: absolute; width: 110px; height: 110px; border-radius: 50%;
    background: conic-gradient(from -90deg, var(--ring-color, #22c55e) calc(var(--pct) * .5%),
                               color-mix(in srgb, var(--glig-ink) 20%, var(--glig-sheet)) 0 50%, #0000 0);
    mask: radial-gradient(farthest-side, #0000 calc(100% - 13px), #000 calc(100% - 12px));
    -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 13px), #000 calc(100% - 12px));
}

/* Sterren: één verloop dat op precies het juiste percentage van goud naar grijs omslaat, en daar vijf stervormen
   uit geknipt. Halve sterren komen er zo gratis bij.

   Dit stond eerst met het teken &#9733; in de tekst, en dat is precies de val: of dat teken bestaat hangt af van
   het lettertype dat toevallig geladen is, en anders staat er een leeg vierkantje. Een vorm in een masker hangt
   nergens van af. */
.glaze-stars
{
    --pct: 72; --star: 21px; display: inline-block;
    width: calc(var(--star) * 5); height: var(--star);
    background: linear-gradient(90deg, var(--filled, #f59e0b) calc(var(--pct) * 1%),
                                color-mix(in srgb, var(--glig-ink) 20%, var(--glig-sheet)) 0);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z'/%3E%3C/svg%3E")
          repeat-x left center / var(--star) var(--star);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z'/%3E%3C/svg%3E")
                  repeat-x left center / var(--star) var(--star);
}

/* Een staafje in een tabelcel: de balk is een achtergrond die tot een percentage loopt. Geen extra element nodig.
   Wel display: block, want een inline element is precies zo breed als zijn tekst en dan is het percentage van de
   verkeerde breedte genomen - een balk van 88% van drie cijfers zegt niets. */
.glaze-data-bar { display: block; background: linear-gradient(90deg,
                       color-mix(in srgb, var(--bar-color, #3b82f6) 32%, transparent) calc(var(--pct, 50) * 1%),
                       color-mix(in srgb, var(--glig-ink) 7%, transparent) 0);
           border-radius: 5px; padding: 3px 8px; }

.glaze-table { border-collapse: collapse; width: 100%; font-size: 14px; }
.glaze-table th, .glaze-table td { padding: 9px 12px; text-align: left; }
.glaze-table thead th { position: sticky; top: 0; background: var(--glig-sheet); font-weight: 700;
                  box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--glig-ink) 18%, transparent); }
.glaze-table tbody tr:nth-child(even) { background: color-mix(in srgb, var(--glig-ink) 5%, transparent); }
.glaze-table tbody tr:hover { background: color-mix(in srgb, #3b82f6 12%, transparent); }

.glaze-status-dot { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; }
.glaze-status-dot::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--state, #22c55e);
                     box-shadow: 0 0 0 3px color-mix(in srgb, var(--state, #22c55e) 22%, transparent); }

.glaze-trend { display: inline-flex; align-items: center; gap: 5px; font: 600 13px system-ui; }
.glaze-trend-up { color: #16a34a; } .glaze-trend-up::before { content: "\25B2"; font-size: 9px; }
.glaze-trend-down { color: #dc2626; } .glaze-trend-down::before { content: "\25BC"; font-size: 9px; }

/* ============================================================ TERUGKOPPELING */

.glaze-alert { display: flex; gap: 11px; padding: 12px 15px; border-radius: 11px; font-size: 14px;
           border-left: 4px solid var(--accent, #3b82f6);
           background: color-mix(in srgb, var(--accent, #3b82f6) 12%, var(--glig-sheet));
           color: color-mix(in srgb, var(--accent, #3b82f6) 55%, var(--glig-ink)); }
.glaze-alert-success { --accent: #16a34a; }
.glaze-alert-warning { --accent: #d97706; }
.glaze-alert-error { --accent: #dc2626; }

.glaze-banner { padding: 11px 16px; text-align: center; font-weight: 600;
          background: linear-gradient(92deg, #ff6fd8, #7b5cff); color: #fff; }

/* Een lege toestand: alles gedempt, want hij moet vertellen dat er niets is zonder zelf iets te worden. */
.glaze-empty { display: grid; place-items: center; gap: 9px; padding: 34px 20px; text-align: center;
          color: color-mix(in srgb, var(--glig-ink) 55%, var(--glig-sheet)); }
.glaze-empty > :first-child { font-size: 36px; opacity: .45; }

/* Drie stuiterende puntjes. Ze delen één animatie en verschillen alleen in vertraging - dat is het hele recept voor
   dit soort dingen, en het scheelt drie keer zoveel code. */
.glaze-typing-dots { display: inline-flex; gap: 5px; }
.glaze-typing-dots > * { width: 8px; height: 8px; border-radius: 50%; background: currentColor;
               animation: bounce 1.1s ease-in-out infinite; }
.glaze-typing-dots > :nth-child(2) { animation-delay: .16s; }
.glaze-typing-dots > :nth-child(3) { animation-delay: .32s; }
/* Balkjes die op en neer gaan, zelfde truc met vertragingen. */
.glaze-equalizer { display: inline-flex; gap: 3px; align-items: flex-end; height: 22px; }
.glaze-equalizer > * { width: 4px; background: currentColor; border-radius: 2px; animation: stretch .9s ease-in-out infinite; }
.glaze-equalizer > :nth-child(2) { animation-delay: .12s; }
.glaze-equalizer > :nth-child(3) { animation-delay: .24s; }
.glaze-equalizer > :nth-child(4) { animation-delay: .36s; }
/* Een onbepaalde voortgang: een stukje dat heen en weer loopt in plaats van vol te lopen, want je weet niet
   hoeveel er nog komt en dat hoor je niet te suggereren. */
.glaze-progress-indeterminate { height: 5px; border-radius: 999px; overflow: hidden; position: relative;
                       background: color-mix(in srgb, var(--glig-ink) 18%, var(--glig-sheet)); }
.glaze-progress-indeterminate::after { content: ""; position: absolute; inset: 0 auto 0 0; width: 38%; border-radius: inherit;
                              background: var(--bar-color, #3b82f6); animation: sweep 1.4s ease-in-out infinite; }
/* ============================================================ INDELING
   Klein spul dat je elke dag nodig hebt en elke keer opnieuw opzoekt. */

.glaze-auto-grid { display: grid; gap: var(--gap, 16px);
              grid-template-columns: repeat(auto-fill, minmax(var(--min, 200px), 1fr)); }
.glaze-row { display: flex; align-items: center; gap: var(--gap, 10px); }
.glaze-row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--gap, 10px); }
.glaze-center { display: grid; place-items: center; }
.glaze-ratio { aspect-ratio: var(--ratio, 16 / 9); object-fit: cover; width: 100%; }
.glaze-measure { max-width: 68ch; }
.glaze-stacked { display: grid; }
.glaze-stacked > * { grid-area: 1 / 1; }
.glaze-sticky-head { position: sticky; top: 0; z-index: 5; background: var(--glig-sheet); }

/* Schaduwen aan de randen die alleen verschijnen als er nog iets te scrollen valt. Dat is een van de mooiste dingen
   die CSS zelf kan: de twee vaste lagen zitten aan de doos vast en de twee schaduwen aan de INHOUD, dus zodra de
   inhoud eronder wegschuift komt de schaduw tevoorschijn. Geen scroll-luisteraar nodig. */
.glaze-scroll-shadow
{
    overflow: auto;
    background:
        linear-gradient(var(--glig-sheet) 30%, transparent) local top / 100% 24px no-repeat,
        linear-gradient(transparent, var(--glig-sheet) 70%) local bottom / 100% 24px no-repeat,
        radial-gradient(farthest-side at 50% 0, color-mix(in srgb, var(--glig-ink) 22%, transparent), transparent)
            scroll top / 100% 12px no-repeat,
        radial-gradient(farthest-side at 50% 100%, color-mix(in srgb, var(--glig-ink) 22%, transparent), transparent)
            scroll bottom / 100% 12px no-repeat;
}

/* Een rij die per kaart inklikt bij het scrollen. */
.glaze-snap-row { display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 6px; }
.glaze-snap-row > * { scroll-snap-align: center; flex: 0 0 auto; }

@media (prefers-reduced-motion: reduce)
{
    .glaze-typing-dots > *, .glaze-equalizer > *, .glaze-progress-indeterminate::after, .glaze-button-loading::after, .glaze-cube > *, .glaze-coin > * {
        animation: none; }
}

/* ============================================================ OOGSNOEP
   Hier houdt het nut op en begint het plezier. Alles hieronder is verf: geen enkele klas verandert wat een element
   DOET, dus je kunt ze overal overheen gooien en weer weghalen zonder dat er iets kapot gaat. */

/* Korrel. Een ruisplaatje in een data-URI, want een echte fotokorrel is het enige wat een verloop van een render
   onderscheidt. Het is een SVG-filter, dus het kost geen enkele byte aan plaatje. */
.glaze-grain { position: relative; isolation: isolate; }
.glaze-grain::after
{
    content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 2; opacity: .13;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='r'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23r)'/%3E%3C/svg%3E");
}

/* Vignettering: donkerder naar de randen. Een inset-schaduw doet dit ook, maar dan met een harde ovaal - de radiale
   verf laat je zelf kiezen waar het inzetten begint. */
.glaze-vignette { position: relative; }
.glaze-vignette::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
                 background: radial-gradient(ellipse at center, transparent 45%, rgba(0, 0, 0, .55) 100%); }

/* Scanlijnen van een oude buis. Een repeating-gradient van twee pixels; groter en het wordt een gordijn. */
.glaze-scanlines { position: relative; }
.glaze-scanlines::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
                     background: repeating-linear-gradient(rgba(0, 0, 0, .22) 0 1px, transparent 1px 3px); }

/* Oude tv: scanlijnen, een bolling en een kleurzweem die net niet goed uitgelijnd is. */
.glaze-old-tv { position: relative; border-radius: 14px / 30px; overflow: hidden; filter: saturate(1.25) contrast(1.1);
          box-shadow: inset 0 0 60px rgba(0, 0, 0, .5); }
.glaze-old-tv::before { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; mix-blend-mode: screen;
                  background: linear-gradient(90deg, #f003 0 33%, #0f03 33% 66%, #00f3 66%); opacity: .16; }
.glaze-old-tv::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
                 background: repeating-linear-gradient(rgba(0, 0, 0, .3) 0 1px, transparent 1px 3px); }

/* Hologram: een blauwgroene zweem met een lichtbalk die traag omhoog loopt. */
.glaze-hologram
{
    position: relative; color: #7ef9ff; text-shadow: 0 0 8px #7ef9ff88;
    background: linear-gradient(160deg, #0b2b3a, #06161f); overflow: hidden;
}
.glaze-hologram::before { content: ""; position: absolute; left: 0; right: 0; height: 40%;
                    background: linear-gradient(transparent, #7ef9ff22, transparent);
                    animation: holo-scan 3.2s linear infinite; }
/* Glitch-tekst. Twee kopieën in rood en blauw die net verkeerd staan en met stukken uitgeknipt springen. De inhoud
   komt uit een attribuut, want dan hoef je de tekst maar op één plek te zetten. */
.glaze-glitch-text { position: relative; font-weight: 800; }
.glaze-glitch-text::before, .glaze-glitch-text::after { content: attr(data-tekst); position: absolute; inset: 0; }
.glaze-glitch-text::before { color: #f0f; clip-path: inset(0 0 55% 0); animation: glitch-a 2.4s steps(2, end) infinite; }
.glaze-glitch-text::after { color: #0ff; clip-path: inset(58% 0 0 0); animation: glitch-b 2.4s steps(2, end) infinite; }
/* Glitter: drie lagen sterretjes op verschillende maat die traag over elkaar heen schuiven. Eén laag ziet er als
   behang uit; het zijn de verschillende snelheden die het laten fonkelen. */
.glaze-glitter { position: relative; }
.glaze-glitter::after
{
    content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; mix-blend-mode: screen;
    background:
        radial-gradient(1.5px 1.5px at 20% 30%, #fff, transparent),
        radial-gradient(1px 1px at 65% 15%, #fff, transparent),
        radial-gradient(1.8px 1.8px at 80% 70%, #fff, transparent),
        radial-gradient(1px 1px at 35% 80%, #fff, transparent);
    background-size: 130px 130px, 90px 90px, 170px 170px, 70px 70px;
    animation: twinkle 4s ease-in-out infinite;
}
/* Vuur onder een element: drie oranje wolken die opstijgen en vervagen. */
.glaze-fire { position: relative; }
.glaze-fire::before
{
    content: ""; position: absolute; left: 10%; right: 10%; bottom: -6px; height: 26px; border-radius: 50%;
    background: radial-gradient(ellipse at center, #ffb020cc, #ff4d0066 55%, transparent 70%);
    filter: blur(6px); animation: flame 1.3s ease-in-out infinite alternate;
}
/* Mist die langs schuift. Twee wolken met verschillende snelheid, anders zie je de herhaling. */
.glaze-fog { position: relative; overflow: hidden; }
.glaze-fog::before, .glaze-fog::after
{
    content: ""; position: absolute; inset: -20%; pointer-events: none;
    background: radial-gradient(ellipse 40% 30% at 30% 50%, #fff5, transparent 70%),
                radial-gradient(ellipse 50% 25% at 70% 40%, #fff4, transparent 70%);
    animation: drift 18s linear infinite;
}
.glaze-fog::after { animation-duration: 27s; animation-direction: reverse; opacity: .6; }
/* Sneeuw: twee lagen vlokken die vallen, met de tweede laag verschoven in tijd zodat er geen gat valt. */
.glaze-snow { position: relative; overflow: hidden; }
.glaze-snow::before, .glaze-snow::after
{
    content: ""; position: absolute; inset: -100% 0 0 0; pointer-events: none;
    background: radial-gradient(2px 2px at 10% 10%, #fff, transparent),
                radial-gradient(2px 2px at 40% 30%, #fff, transparent),
                radial-gradient(1.5px 1.5px at 70% 20%, #fff, transparent),
                radial-gradient(2px 2px at 90% 45%, #fff, transparent);
    background-size: 120px 120px; animation: fall 9s linear infinite;
}
.glaze-snow::after { animation-delay: -4.5s; opacity: .65; }
/* Bubbels die opstijgen; elke bubbel krijgt zijn eigen vertraging en zijmarge via de variabelen. */
.glaze-bubbles { position: relative; overflow: hidden; }
.glaze-bubbles > .glaze-bubble
{
    position: absolute; bottom: -20px; left: var(--x, 50%); width: var(--d, 12px); height: var(--d, 12px);
    border-radius: 50%; pointer-events: none;
    background: radial-gradient(circle at 32% 30%, #ffffffcc, #ffffff22 45%, #ffffff08 60%);
    /* --rise is de hoogte van de doos: een procent in translateY rekent met de bubbel zelf, en die is 12 pixels. */
    box-shadow: inset 0 0 6px #fff6; animation: rise var(--dur, 6s) linear infinite var(--delay, 0s);
}
/* Zeepbel: een doorzichtige bol met een olieachtige regenboog die traag draait. */
.glaze-soap-bubble
{
    border-radius: 50%; aspect-ratio: 1;
    background: radial-gradient(circle at 32% 28%, #fff9, #ffffff10 38%, transparent 55%),
                conic-gradient(from 0deg, #ff6fd8aa, #7bffe0aa, #ffe97baa, #7b9bffaa, #ff6fd8aa);
    box-shadow: inset 0 0 22px #fff6, 0 8px 22px #0003; animation: spin 9s linear infinite;
}

/* Spiegeling onder een element, als op een natte vloer. Het masker laat hem naar onderen wegvallen. */
.glaze-reflected { position: relative; }
.glaze-reflected::after
{
    content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 55%; pointer-events: none;
    background: inherit; transform: scaleY(-1); opacity: .3; filter: blur(1px);
    mask: linear-gradient(#000, transparent 75%); -webkit-mask: linear-gradient(#000, transparent 75%);
}

/* Duotoon: alles naar twee kleuren. Eerst grijs maken, dan er een kleurverloop overheen blenden.

   Het grijs maken MOET met backdrop-filter op een laagje ervoor, niet met filter op het element zelf. Een filter
   werkt namelijk op alles wat het element tekent, en dus ook op de ::after die de kleur weer aanbrengt - dan haal
   je met de ene hand weg wat je met de andere geeft en houd je precies grijs over. Dat had ik eerst, en het is
   dezelfde soort fout als perspectief twee keer toepassen: de volgorde van de lagen is het antwoord. */
.glaze-duotone { position: relative; isolation: isolate; }
.glaze-duotone::before { content: ""; position: absolute; inset: 0; border-radius: inherit;
                   backdrop-filter: grayscale(1) contrast(1.12);
                   -webkit-backdrop-filter: grayscale(1) contrast(1.12); }
.glaze-duotone::after { content: ""; position: absolute; inset: 0; mix-blend-mode: color; border-radius: inherit;
                  background: linear-gradient(135deg, var(--from, #2b2d8f), var(--to, #ff6fd8)); }

/* Zoeklicht dat de muis volgt zonder javascript kan niet - maar een zoeklicht dat over het element loopt wel.
   Een eigen variabele springt van waarde naar waarde tenzij je hem AANMELDT met @property; pas dan weet de browser
   dat er een percentage in zit en kan hij ertussenin rekenen. */
@property --lx { syntax: "<percentage>"; initial-value: 30%; inherits: false; }
.glaze-spotlight { position: relative; overflow: hidden; }
.glaze-spotlight::after { content: ""; position: absolute; inset: 0; pointer-events: none;
                    background: radial-gradient(circle 90px at var(--lx, 30%) var(--ly, 50%), #fff4, transparent 70%);
                    animation: roam 6s ease-in-out infinite alternate; }
/* ============================================================ TEKST */

/* Een sierkapitaal: de eerste letter groot en ingesprongen. Puur CSS, geen span nodig. */
.glaze-drop-cap::first-letter { float: left; font-size: 3.1em; line-height: .82; padding: 4px 9px 0 0; font-weight: 700;
                          color: var(--tint, #7b5cff); }

/* Een markeerstift die achter de tekst door loopt en aan de uiteinden schuin ophoudt - de scheve hoek is precies
   wat het verschil maakt tussen "gemarkeerd" en "achtergrondkleurtje". */
.glaze-highlight { background: linear-gradient(104deg, transparent .5%, var(--marker, #ffe97b) .5%, var(--marker, #ffe97b) 98%,
                       transparent 98.5%); padding: 1px 3px; border-radius: 3px 9px 5px 8px;
           box-decoration-break: clone; -webkit-box-decoration-break: clone; }

/* Een streep die bij hover van links naar rechts groeit. scaleX met een transform-origin die omklapt geeft het
   heen-en-weer-effect: hij groeit vanaf links en trekt zich terug naar rechts. */
.glaze-underline-link { text-decoration: none; color: inherit; position: relative; }
.glaze-underline-link::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
                     background: currentColor; transform: scaleX(0); transform-origin: right;
                     transition: transform .28s; }
.glaze-underline-link:hover::after { transform: scaleX(1); transform-origin: left; }

/* Een verlopende tekst. background-clip: text is het enige wat hiervoor bestaat en het werkt overal. */
.glaze-gradient-text { background: linear-gradient(96deg, var(--from, #ff6fd8), var(--to, #7b5cff));
                -webkit-background-clip: text; background-clip: text; color: transparent; }

/* Tekst waar het beeld doorheen schijnt. Zelfde truc, maar met een plaatje in plaats van een verloop. */
.glaze-image-text { -webkit-background-clip: text; background-clip: text; color: transparent;
              background-size: cover; background-position: center; }

/* Een schaduw die naar rechtsonder wegloopt, opgebouwd uit losse stapjes. */
.glaze-deep-text { color: var(--glig-sheet); text-shadow: 1px 1px 0 #0004, 2px 2px 0 #0004, 3px 3px 0 #0003, 4px 4px 0 #0003,
                                              5px 5px 0 #0002, 6px 6px 0 #0002, 7px 7px 12px #0006; }

/* Tekst die golft, letter voor letter. Elke letter is een span met een eigen vertraging via --i. */
.glaze-wave-text > * { display: inline-block; animation: wave-letter 1.6s ease-in-out infinite;
                 animation-delay: calc(var(--i, 0) * .07s); }
/* Meerdere regels netjes afkappen. -webkit-line-clamp is officieel prefixed en werkt in elke browser. */
.glaze-line-clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--lines, 3);
            overflow: hidden; }

.glaze-small-caps { font-variant-caps: small-caps; letter-spacing: .06em; }
.glaze-tabular { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce)
{
    .glaze-glitter::after, .glaze-fire::before, .glaze-fog::before, .glaze-fog::after, .glaze-snow::before, .glaze-snow::after,
    .glaze-bubbles > .glaze-bubble, .glaze-soap-bubble, .glaze-hologram::before, .glaze-glitch-text::before, .glaze-glitch-text::after,
    .glaze-spotlight::after, .glaze-wave-text > * { animation: none; }
}

/* ============================================================ KLEIN GEREEDSCHAP
   Losse onderdelen die in elke toepassing terugkomen en die je anders elke keer opnieuw uitvindt. */

.glaze-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px;
        font-size: 13px; background: color-mix(in srgb, var(--glig-ink) 9%, var(--glig-sheet));
        box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--glig-ink) 12%, transparent); }
.glaze-chip > button { border: 0; background: none; cursor: pointer; color: inherit; opacity: .5; font-size: 15px;
                 line-height: 1; padding: 0; }
.glaze-chip > button:hover { opacity: 1; }

.glaze-avatar { width: var(--size, 38px); height: var(--size, 38px); border-radius: 50%; display: grid;
          place-items: center; font: 700 14px system-ui; color: #fff; background: var(--tint, #3b82f6);
          box-shadow: 0 0 0 2px var(--glig-sheet); }

/* Een scheidslijn met een woord in het midden. De twee strepen groeien mee, want ze zijn flex-vullingen en geen
   vaste breedtes - dat is het enige wat deze vorm bruikbaar maakt in een kolom die van maat verandert. */
.glaze-divider { display: flex; align-items: center; gap: 12px; font-size: 13px; opacity: .65; }
.glaze-divider::before, .glaze-divider::after { content: ""; flex: 1; height: 1px;
                                      background: color-mix(in srgb, var(--glig-ink) 20%, transparent); }

.glaze-kbd { display: inline-block; padding: 2px 7px; border-radius: 5px; font: 600 12px ui-monospace, monospace;
         background: var(--glig-sheet); box-shadow: 0 1px 0 1px color-mix(in srgb, var(--glig-ink) 18%, transparent),
                                             inset 0 -2px 0 color-mix(in srgb, var(--glig-ink) 10%, transparent); }

.glaze-quote { border-left: 3px solid var(--tint, #7b5cff); padding: 4px 0 4px 14px; font-style: italic;
          color: color-mix(in srgb, var(--glig-ink) 78%, var(--glig-sheet)); }

.glaze-code-block { font: 13px/1.6 ui-monospace, monospace; padding: 12px 14px; border-radius: 10px; overflow-x: auto;
            background: color-mix(in srgb, var(--glig-ink) 92%, #000); color: #e6e6e6; }

/* Een tijdlijn: de streep is een rand op de lijst, de bolletjes zijn de opsommingstekens. Nul extra elementen. */
.glaze-timeline { list-style: none; margin: 0; padding: 0 0 0 22px;
            border-left: 2px solid color-mix(in srgb, var(--glig-ink) 15%, transparent); }
.glaze-timeline > li { position: relative; padding-bottom: 16px; }
.glaze-timeline > li::before { content: ""; position: absolute; left: -29px; top: 5px; width: 10px; height: 10px;
                         border-radius: 50%; background: var(--tint, #3b82f6);
                         box-shadow: 0 0 0 3px var(--glig-sheet); }
.glaze-timeline > li:last-child { padding-bottom: 0; }

/* Knoppen die aan elkaar vastzitten: alleen de buitenste hoeken zijn rond. */
.glaze-button-group { display: inline-flex; }
.glaze-button-group > * { border-radius: 0; }
.glaze-button-group > :first-child { border-radius: 10px 0 0 10px; }
.glaze-button-group > :last-child { border-radius: 0 10px 10px 0; }
.glaze-button-group > * + * { box-shadow: inset 1px 0 0 rgba(255, 255, 255, .25); }

.glaze-search-field { display: flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: 999px;
            background: color-mix(in srgb, var(--glig-ink) 7%, var(--glig-sheet));
            box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--glig-ink) 12%, transparent); }
/* Het vergrootglas is een vorm in een masker en niet een teken uit het lettertype: ontbreekt dat teken, dan staat
   er een leeg vierkantje in je zoekveld. Het moet ook één vorm zijn en geen rondje plus streepje in twee
   pseudo-elementen - in een flexrij komt het tweede stuk aan de andere kant van het invoerveld terecht. */
.glaze-search-field::before
{
    content: ""; width: 15px; height: 15px; flex: none; background: currentColor; opacity: .5;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5 21 21'/%3E%3C/svg%3E") no-repeat center / contain;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5 21 21'/%3E%3C/svg%3E") no-repeat center / contain;
}
.glaze-search-field input { border: 0; background: none; outline: 0; color: inherit; font: inherit; flex: 1; min-width: 0;
                  margin-left: 4px; }
.glaze-search-field:focus-within { box-shadow: inset 0 0 0 2px #3b82f6; }

/* Een eigen aankruisvakje. De echte input blijft staan en blijft bedienbaar met het toetsenbord - hij wordt alleen
   doorzichtig. Hem op display:none zetten is de fout die dit soort recepten zo vaak onbruikbaar maakt: dan haalt de
   browser hem uit de tabvolgorde en is het vakje voor een toetsenbordgebruiker verdwenen. */
.glaze-checkbox { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; position: relative; }
.glaze-checkbox input { position: absolute; opacity: 0; width: 20px; height: 20px; margin: 0; cursor: pointer; }
.glaze-checkbox > i { width: 20px; height: 20px; border-radius: 6px; display: block; position: relative;
                box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--glig-ink) 30%, transparent);
                transition: background .15s, box-shadow .15s; }
.glaze-checkbox:has(input:checked) > i { background: #3b82f6; box-shadow: inset 0 0 0 2px #3b82f6; }
.glaze-checkbox:has(input:checked) > i::after { content: ""; position: absolute; left: 7px; top: 3px; width: 4px;
                                          height: 9px; border: 2px solid #fff; border-top: 0; border-left: 0;
                                          transform: rotate(43deg); }
.glaze-checkbox:has(input:focus-visible) > i { box-shadow: inset 0 0 0 2px #3b82f6, 0 0 0 3px #3b82f680; }

.glaze-radio { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; position: relative; }
.glaze-radio input { position: absolute; opacity: 0; width: 20px; height: 20px; margin: 0; cursor: pointer; }
.glaze-radio > i { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center;
                box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--glig-ink) 30%, transparent); }
.glaze-radio > i::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: #3b82f6;
                       transform: scale(0); transition: transform .16s cubic-bezier(.3, 1.4, .5, 1); }
.glaze-radio:has(input:checked) > i { box-shadow: inset 0 0 0 2px #3b82f6; }
.glaze-radio:has(input:checked) > i::after { transform: scale(1); }

/* Een schuif die er in elke browser hetzelfde uitziet. Dat kost twee losse regels voor de knop, want -webkit en
   -moz noemen hem anders en accepteren elkaars naam niet - ze in één regel zetten maakt de HELE regel ongeldig.
   En eerlijk: de gevulde helft komt uit --pct, en die verzet zichzelf niet. Wil je dat de kleur MEELOOPT terwijl je
   sleept, dan is er één regel javascript nodig. Dit is precies de grens van wat CSS alleen kan. */
.glaze-slider { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: 999px;
          background: linear-gradient(90deg, var(--tint, #3b82f6) calc(var(--pct, 50) * 1%),
                                      color-mix(in srgb, var(--glig-ink) 15%, var(--glig-sheet)) 0); }
.glaze-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; border-radius: 50%;
                                background: var(--glig-sheet); box-shadow: 0 1px 5px #0004, inset 0 0 0 2px
                                var(--tint, #3b82f6); cursor: pointer; }
.glaze-slider::-moz-range-thumb { width: 18px; height: 18px; border: 0; border-radius: 50%; background: var(--glig-sheet);
                            box-shadow: 0 1px 5px #0004, inset 0 0 0 2px var(--tint, #3b82f6); cursor: pointer; }

.glaze-color-dot { width: 22px; height: 22px; border-radius: 50%; display: inline-block; background: var(--tint, #3b82f6);
             box-shadow: inset 0 -3px 6px #0003, 0 0 0 2px var(--glig-sheet), 0 0 0 3px
                         color-mix(in srgb, var(--glig-ink) 15%, transparent); }

/* Uitvergroten bij aanwijzen, met het beeld strak in de doos. overflow: hidden op de doos is wat het netjes houdt. */
.glaze-zoom { overflow: hidden; }
.glaze-zoom > * { transition: transform .45s cubic-bezier(.2, .7, .3, 1); }
.glaze-zoom:hover > * { transform: scale(1.12); }

/* Een prijskaart die zichzelf naar voren duwt als hij de aanbevolen is. */
.glaze-price-card { border-radius: 16px; padding: 22px; background: var(--glig-sheet); text-align: center;
              box-shadow: 0 2px 10px color-mix(in srgb, var(--glig-ink) 12%, transparent);
              transition: transform .2s, box-shadow .2s; }
.glaze-price-card:hover { transform: translateY(-3px);
                    box-shadow: 0 10px 26px color-mix(in srgb, var(--glig-ink) 20%, transparent); }
.glaze-price-card.glaze-featured { box-shadow: 0 0 0 2px #7b5cff, 0 12px 30px color-mix(in srgb, #7b5cff 30%, transparent);
                         transform: scale(1.03); }
.glaze-price-card .glaze-price { font: 800 34px system-ui; letter-spacing: -.02em; }

/* Een afgevinkte taak streept zichzelf door. :has kijkt van de rij naar het vakje erin, en dat is precies de
   richting die tot voor kort niet kon - dit was jarenlang de kleinste reden om javascript aan te zetten. */
.glaze-task-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; }
.glaze-task-row:has(input:checked) { opacity: .5; text-decoration: line-through; }

/* ============================================================ HET BOEK

   Een tabbladenpaneel waarin je bladert in plaats van klikt. Zes losse ideeen die samen moeten komen:

   1. ELK BLAD SCHARNIERT OM DE RUG. transform-origin op de linkerrand, en het blad beslaat de rechterhelft. Draai
      je om het midden, dan is het geen boek maar een molen.
   2. TWEE KANTEN PER BLAD. Recto en verso liggen op elkaar, de verso staat een halve slag gedraaid te wachten, en
      backface-visibility verbergt telkens de kant die van je af kijkt. Zonder dat zie je door het papier heen.
   3. DE STAPELVOLGORDE MOET HALVERWEGE OMKLAPPEN. Dit is de kern. Op de rechterstapel hoort blad 1 bovenop; op de
      linkerstapel hoort het onderop, want blad 2 komt er later bovenop te liggen. Er is dus een moment - precies
      als het blad rechtop staat - waarop de volgorde moet omslaan.

      Dat kan zonder javascript, en dit is het aardigste stukje van de hele pagina: z-index is niet vloeiend te
      animeren, maar WEL te transitionen. Een sprongetje van nul seconden met een vertraging van een halve slag
      landt precies op het moment dat het blad op zijn kant staat en dus onzichtbaar is. Je ziet de sprong nooit,
      omdat er op dat moment niets te zien is.
   4. DE SCHADUW LOOPT MEE. Op de heenweg loopt een verloop over de voorkant vol, op de terugweg loopt er een van de
      achterkant af - twee halve overgangen die op hetzelfde moment aan elkaar geknoopt zitten als de z-index.
   5. HET PAPIER BOLT BIJ DE RUG. Een donker verloopje van een millimeter of vier langs de binnenrand; dat is het
      enige wat een blad van een rechthoek onderscheidt.
   6. JE LEEST IN VOLGORDE. Elk blad heeft een eigen vinkje, dus je slaat om, niet naar een hoofdstuk. Springen naar
      hoofdstuk drie zou betekenen dat een klik drie vinkjes zet, en dat kan CSS niet - hier houdt het op. Voor een
      boek is dat geen gemis maar precies goed. */

.glaze-book
{
    position: relative; width: var(--width, 540px); aspect-ratio: 9 / 5;
    perspective: 1800px; perspective-origin: 50% 50%;
    font: 13px/1.6 system-ui, sans-serif;
}

/* De onderste twee bladzijden liggen vast: de linker zie je voor het eerste omslaan, de rechter na het laatste. */
.glaze-book > .glaze-side { position: absolute; top: 0; width: 50%; height: 100%; }
.glaze-book > .glaze-side.glaze-left { left: 0; }
.glaze-book > .glaze-side.glaze-right { left: 50%; }

.glaze-leaf
{
    position: absolute; top: 0; left: 50%; width: 50%; height: 100%;
    transform-origin: left center; transform-style: preserve-3d;
    transition: transform .95s cubic-bezier(.42, .02, .28, 1), z-index 0s .48s;
    z-index: calc(50 - var(--n, 1));
}
.glaze-leaf > input { position: absolute; opacity: 0; width: 0; height: 0; }
.glaze-leaf:has(> input:checked) { transform: rotateY(-179.5deg); z-index: calc(50 + var(--n, 1)); }

/* Bijna een halve slag en niet precies: op exact 180 graden vallen twee vlakken samen en dan mag de browser zelf
   kiezen welke hij bovenop legt. Een halve graad speling is het verschil tussen "altijd goed" en "meestal goed". */

.glaze-leaf > .glaze-paper { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.glaze-leaf > .glaze-verso { transform: rotateY(180deg); }

/* Het klikvlak is een LEGE label over de bladzijde heen, en niet de bladzijde zelf. Een label mag alleen tekst
   bevatten - een kop en een alinea horen er niet in, en dat is niet muggenzifterij: de browser mag de opmaak dan
   herstellen zoals hij wil, en de tekst is er ook niet meer te selecteren. */
.glaze-leaf label { position: absolute; inset: 0; z-index: 2; cursor: pointer; }

/* Het papier zelf - ook voor de twee vaste zijden. */
.glaze-paper
{
    box-sizing: border-box; padding: 22px 24px; display: flex; flex-direction: column;
    background: #fdfbf5; color: #2f2c26; overflow: hidden;
}
.glaze-paper.glaze-recto, .glaze-paper.glaze-right { border-radius: 3px 9px 9px 3px;
                                box-shadow: inset 13px 0 16px -14px #00000090, 3px 2px 9px #0000002e; }
.glaze-paper.glaze-verso, .glaze-paper.glaze-left { border-radius: 9px 3px 3px 9px;
                               box-shadow: inset -13px 0 16px -14px #00000090, -3px 2px 9px #0000002e; }
.glaze-paper h4 { margin: 0 0 8px; font-size: 15px; letter-spacing: -.01em; }
.glaze-paper p { margin: 0 0 8px; }
.glaze-paper .glaze-folio { margin-top: auto; font-size: 11px; opacity: .45; letter-spacing: .08em; }
.glaze-paper.glaze-verso .glaze-folio, .glaze-paper.glaze-left .glaze-folio { align-self: flex-start; }
.glaze-paper.glaze-recto .glaze-folio, .glaze-paper.glaze-right .glaze-folio { align-self: flex-end; }

/* De schaduw die over het blad loopt terwijl het omslaat. Twee halve overgangen, met dezelfde knip in het midden
   als de z-index - daarom staat er twee keer .48s. */
.glaze-leaf > .glaze-paper::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
                         z-index: 3; }
.glaze-leaf > .glaze-recto::after { opacity: 0; transition: opacity .48s linear;
                        background: linear-gradient(85deg, #0000 35%, #00000073); }
.glaze-leaf > .glaze-verso::after { opacity: 1; transition: opacity .47s linear .48s;
                        background: linear-gradient(275deg, #0000 35%, #00000073); }
.glaze-leaf:has(> input:checked) > .glaze-recto::after { opacity: 1; }
.glaze-leaf:has(> input:checked) > .glaze-verso::after { opacity: 0; }

/* Een leeslint. Het staat ACHTER de bladen (z-index 0), dus je ziet alleen het stuk dat onder het boek uit steekt -
   precies zoals een echt lint tussen de bladzijden zit. Zet je het ervoor, dan is het geen lint maar een streep. */
.glaze-book > .glaze-bookmark { position: absolute; top: 40%; bottom: -34px; left: calc(50% - 6px); width: 12px; z-index: 0;
                    background: linear-gradient(#e11d48, #9f1239); box-shadow: 1px 0 4px #0005;
                    pointer-events: none;
                    clip-path: polygon(0 0, 100% 0, 100% 100%, 50% calc(100% - 11px), 0 100%); }

@media (prefers-reduced-motion: reduce)
{
    .glaze-leaf { transition: transform 0s, z-index 0s; }
    .glaze-leaf > .glaze-paper::after { transition: none; }
}

/* ============================================================ HET KLAPBORD

   Een stationsbord van Solari. Elk vakje is een venster met een strook letters erachter die omhoog rolt en op de
   goede letter blijft staan. Twee dingen maken het mechanisch in plaats van vloeiend:

   - steps() in plaats van een vloeiende overgang. Een letterrol die glijdt is een filmrol; een die klikt is een
     klapbord. Het staat op de KEYFRAME en niet op de animatie, want alleen de rol mag klikken - de rust erna moet
     gewoon stil staan.
   - Elk vakje krijgt zijn eigen vertraging via --i. Zonder die trapsgewijze start klappen alle letters tegelijk om
     en dan is het een lichtkrant. */

.glaze-split-flap { display: inline-flex; gap: 5px; perspective: 500px; }
.glaze-flap-cell
{
    --glig-highlight: 52px;
    position: relative; width: 38px; height: var(--glig-highlight); overflow: hidden; border-radius: 5px;
    background: #14161b; color: #f2efe6; font: 700 32px/var(--glig-highlight) ui-monospace, monospace;
    box-shadow: inset 0 2px 5px #ffffff14, 0 3px 7px #0006;
}
/* De naad in het midden - dat is wat het van een dobbelsteen onderscheidt. */
.glaze-flap-cell::after { content: ""; position: absolute; left: 0; right: 0; top: calc(50% - 1px); height: 2px; z-index: 2;
                  background: #000000b0; box-shadow: 0 1px 0 #ffffff10; }
.glaze-flap-cell > span { position: absolute; left: 0; right: 0; top: 0; display: flex; flex-direction: column;
                  animation: letter-roll 5s infinite; animation-delay: calc(var(--i, 0) * .17s); }
.glaze-flap-cell > span > * { height: var(--glig-highlight); flex: none; text-align: center; }
/* ============================================================ DE KAARTWAAIER

   Kaarten in een hand. De hele truc zit in transform-origin: die ligt ver ONDER de kaart, zodat draaien voelt als
   uitwaaieren om een pols in plaats van tollen om een midden. Verzet dat punt naar het hart van de kaart en het is
   meteen een windmolen. */

.glaze-fan { position: relative; height: 168px; display: flex; justify-content: center; }
.glaze-fan > *
{
    position: absolute; bottom: 0; width: 98px; height: 138px; border-radius: 9px; box-sizing: border-box;
    padding: 9px; display: flex; flex-direction: column; justify-content: space-between; cursor: pointer;
    background: #fdfcf9; color: #23262e; font: 700 15px system-ui; border: 1px solid #0002;
    box-shadow: 0 3px 9px #00000038;
    transform-origin: 50% 210%;
    transform: rotate(calc((var(--i) - var(--mid, 2)) * 7deg));
    transition: transform .38s cubic-bezier(.3, 1.1, .4, 1), box-shadow .3s;
}
.glaze-fan:hover > * { transform: rotate(calc((var(--i) - var(--mid, 2)) * 14deg)) translateY(-6px); }
.glaze-fan > *:hover { transform: rotate(calc((var(--i) - var(--mid, 2)) * 14deg)) translateY(-30px) scale(1.04);
                    box-shadow: 0 14px 26px #00000055; z-index: 9; }
.glaze-fan > * > :last-child { align-self: flex-end; transform: rotate(180deg); }

/* ============================================================ DE LADEKAST

   Laden die opengaan als een kiepbak: het front kantelt naar je toe om zijn onderrand, en daarachter komt de
   binnenkant tevoorschijn.

   Ik heb eerst geprobeerd wat een echte la doet - de bak naar voren schuiven en de bodem achterover leggen. Dat
   klopt natuurkundig precies en je ziet er helemaal niets van, want de bodem van een open la ligt in het verlengde
   van je blik en projecteert dus tot een streep. Kantelen kost geen enkele geloofwaardigheid en levert wel een
   binnenkant op die je kunt lezen. De kast staat daarbij zelf iets achterover, zodat je er van boven op kijkt. */

.glaze-cabinet { perspective: 900px; perspective-origin: 50% 0%; width: 250px; }
.glaze-cabinet > .glaze-case { transform: rotateX(11deg); transform-style: preserve-3d; padding: 12px; border-radius: 8px;
                background: linear-gradient(100deg, #6b4423, #8b5a2b 40%, #5d3a1e); box-shadow: 0 8px 20px #0005; }
.glaze-drawer { position: relative; height: 52px; margin-bottom: 10px; transform-style: preserve-3d; }
.glaze-drawer:last-child { margin-bottom: 0; }
.glaze-drawer input { position: absolute; opacity: 0; width: 0; height: 0; }

/* De binnenkant ligt gewoon in het gat en wordt zichtbaar doordat het front ervoor wegkantelt. */
.glaze-drawer > .glaze-bin { position: absolute; inset: 0; border-radius: 4px; box-sizing: border-box; padding: 7px 10px;
             background: linear-gradient(#241708, #4a3218); color: #ffe1b4; font: 11px/1.35 system-ui;
             box-shadow: inset 0 7px 11px -6px #000, inset 0 -2px 0 #ffffff12; }

.glaze-drawer > label
{
    position: absolute; inset: 0; z-index: 2; cursor: pointer; border-radius: 4px; display: grid;
    place-items: center; font: 600 13px system-ui; color: #f6ecdf; backface-visibility: hidden;
    background: linear-gradient(#a4703f, #7d5228); box-shadow: inset 0 1px 0 #ffffff35, 0 2px 5px #0006;
    transform-origin: bottom center; transition: transform .45s cubic-bezier(.3, 1.1, .4, 1), box-shadow .45s;
}
/* Het handvat. */
.glaze-drawer > label::after { content: ""; position: absolute; bottom: 7px; width: 46px; height: 5px; border-radius: 3px;
                     background: linear-gradient(#f0d9a8, #b4914f); box-shadow: 0 1px 2px #0007; }
.glaze-drawer:has(input:checked) > label { transform: translateZ(30px) rotateX(62deg);
                                 box-shadow: inset 0 1px 0 #ffffff35, 0 16px 22px -8px #000a; }

/* ============================================================ DE CARROUSEL

   Panelen op een denkbeeldige cilinder. Elk paneel wordt eerst gedraaid en dan naar buiten geschoven - dezelfde
   volgorde als bij de kubus, en om dezelfde reden. De straal moet passen bij het aantal panelen: te klein en ze
   snijden door elkaar, te groot en er valt een gat. Voor zes panelen van 150 breed is 150 een nette straal. */

.glaze-carousel { position: relative; height: 118px; perspective: 900px; }
.glaze-carousel > input { position: absolute; opacity: 0; width: 0; height: 0; }
.glaze-carousel > .glaze-axis { position: absolute; inset: 0; transform-style: preserve-3d;
                   transform: translateZ(-150px) rotateY(var(--angle, 0deg));
                   transition: transform .75s cubic-bezier(.4, .05, .25, 1); }
.glaze-carousel .glaze-panel
{
    position: absolute; left: 50%; top: 0; width: 150px; height: 100%; margin-left: -75px; box-sizing: border-box;
    display: grid; place-items: center; text-align: center; padding: 12px; border-radius: 10px;
    font: 600 14px system-ui; color: #fff;
    transform: rotateY(calc(var(--i) * 60deg)) translateZ(150px);
    backface-visibility: hidden;
}
.glaze-carousel:has(> input:nth-of-type(1):checked) > .glaze-axis { --angle: 0deg; }
.glaze-carousel:has(> input:nth-of-type(2):checked) > .glaze-axis { --angle: -60deg; }
.glaze-carousel:has(> input:nth-of-type(3):checked) > .glaze-axis { --angle: -120deg; }
.glaze-carousel:has(> input:nth-of-type(4):checked) > .glaze-axis { --angle: -180deg; }
.glaze-carousel:has(> input:nth-of-type(5):checked) > .glaze-axis { --angle: -240deg; }
.glaze-carousel:has(> input:nth-of-type(6):checked) > .glaze-axis { --angle: -300deg; }
.glaze-carousel-dots { display: flex; gap: 6px; justify-content: center; margin-top: 12px; }
.glaze-carousel-dots label { width: 9px; height: 9px; border-radius: 50%; cursor: pointer;
                          background: color-mix(in srgb, var(--glig-ink) 25%, transparent); }
.glaze-carousel + .glaze-carousel-dots label:hover { background: color-mix(in srgb, var(--glig-ink) 50%, transparent); }

/* ============================================================ DE DRAAITAFEL

   Een plaat met groeven uit een herhalend radiaal verloop en een glans uit een conische. De arm zwenkt in op de
   naald: transform-origin bij het draaipunt, en dat draaipunt is het scharnier rechtsboven - niet het midden van
   de arm, want dan zwaait hij als een wijzer. */

.glaze-turntable { position: relative; width: var(--size, 210px); aspect-ratio: 1; }
.glaze-record
{
    position: absolute; inset: 0; border-radius: 50%; animation: spin 1.8s linear infinite;
    background:
        radial-gradient(circle, #1c1c1c 0 2.4%, #0000 2.6%),
        radial-gradient(circle, #d8c9a0 0 17%, #0000 17.2%),
        radial-gradient(circle, #0000 0 17%, #1a1a1a 17.2% 19%, #0000 19.2%),
        repeating-radial-gradient(circle, #16181c 0 2px, #101215 2px 3.5px);
    box-shadow: 0 6px 18px #0007, inset 0 0 30px #0008;
}
/* De glans is een aparte laag die NIET meedraait - licht blijft waar het is als de plaat draait, en dat is precies
   wat een draaiende plaat er als glas uit laat zien. */
.glaze-turntable > .glaze-sheen { position: absolute; inset: 0; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
                       background: conic-gradient(from 200deg, #0000 0 12%, #ffffff26 20%, #0000 30% 62%,
                                                  #ffffff1c 70%, #0000 80%); }
.glaze-turntable > .glaze-arm
{
    position: absolute; right: 3%; top: 4%; width: 7px; height: 62%; z-index: 3;
    transform-origin: 50% 6px; transform: rotate(9deg); transition: transform .9s cubic-bezier(.4, 0, .2, 1);
    background: linear-gradient(#e9e9ee, #b9bcc6); border-radius: 4px; box-shadow: 0 2px 5px #0007;
}
.glaze-turntable > .glaze-arm::before { content: ""; position: absolute; left: -6px; top: -6px; width: 19px; height: 19px;
                             border-radius: 50%; background: radial-gradient(circle at 35% 30%, #fff, #9aa0ad); }
.glaze-turntable > .glaze-arm::after { content: ""; position: absolute; left: -4px; bottom: -4px; width: 15px; height: 13px;
                            border-radius: 3px; background: linear-gradient(#3b3f4a, #23262d); }
.glaze-turntable:hover > .glaze-arm { transform: rotate(30deg); }

/* ============================================================ DE ZAKLAMP

   Een donker vlak waar een lichtbundel overheen loopt en onthult wat eronder ligt. Het masker is de bundel: waar
   het masker wit is zie je de tekst, daarbuiten niet. Dat is iets anders dan een lichtvlek tekenen - een vlek legt
   iets bovenop, een masker haalt iets weg, en alleen bij het tweede blijft de rest echt onzichtbaar. */

@property --beam-x { syntax: "<percentage>"; initial-value: 18%; inherits: false; }
.glaze-flashlight { position: relative; overflow: hidden; border-radius: 12px; background: #0e1014; }
.glaze-flashlight > .glaze-lower
{
    position: absolute; inset: 0; display: grid; place-items: center; text-align: center; padding: 20px;
    font: 700 20px/1.4 system-ui; color: #ffe9a8; text-shadow: 0 0 22px #ffbb3355;
    mask: radial-gradient(circle 92px at var(--beam-x) 50%, #000 30%, #0000 72%);
    -webkit-mask: radial-gradient(circle 92px at var(--beam-x) 50%, #000 30%, #0000 72%);
    animation: beam-swing 7s ease-in-out infinite alternate;
}
/* Een zweem licht op het donker zelf, zodat de bundel ook op het vlak te zien is en niet alleen in de tekst. */
.glaze-flashlight::after { content: ""; position: absolute; inset: 0; pointer-events: none;
                  background: radial-gradient(circle 92px at var(--beam-x) 50%, #ffdf9e1f, #0000 72%);
                  animation: beam-swing 7s ease-in-out infinite alternate; }
/* ============================================================ HET RADARSCHERM

   De bundel is een conische verf die rondgaat. Het aardige zit in de stipjes: elk stipje licht op met dezelfde
   omlooptijd als de bundel, maar met een vertraging die bij zijn eigen hoek hoort. Daardoor flitst het precies
   wanneer de bundel eroverheen komt - zonder dat er iets iets van iets anders WEET. Twee klokken die op dezelfde
   maat lopen zijn goedkoper dan een gesprek. */

.glaze-radar
{
    position: relative; width: var(--size, 200px); aspect-ratio: 1; border-radius: 50%; overflow: hidden;
    background: radial-gradient(circle, #05170d, #020a06);
    box-shadow: inset 0 0 30px #00ff8814, 0 0 0 2px #0a3a22;
}
/* De ringen en de kruisdraden. */
.glaze-radar::before
{
    content: ""; position: absolute; inset: 0; border-radius: 50%;
    background:
        repeating-radial-gradient(circle, #00ff8800 0 23px, #00ff881f 23px 24px),
        linear-gradient(#00ff8815 0 0) no-repeat center / 100% 1px,
        linear-gradient(#00ff8815 0 0) no-repeat center / 1px 100%;
}
.glaze-radar > .glaze-beam
{
    position: absolute; inset: 0; border-radius: 50%; animation: spin 3.6s linear infinite;
    background: conic-gradient(#00ff8800 0 72%, #00ff8814 88%, #00ff8866 99%, #00ff8800 100%);
}
.glaze-radar > .glaze-blip
{
    position: absolute; left: 50%; top: 50%; width: 7px; height: 7px; margin: -3.5px; border-radius: 50%;
    background: #7dffbe; box-shadow: 0 0 9px #00ff88;
    transform: rotate(var(--angle)) translateY(calc(var(--dist, 60px) * -1));
    animation: blip-flash 3.6s linear infinite;
    animation-delay: calc(var(--angle) / 360deg * 3.6s - 3.6s);
}
/* ============================================================ DE ZANDLOPER

   Twee kegels uit clip-path, en het zand is in beide een gewone rechthoek die groeit of krimpt. Dat is de hele
   truc: je hoeft de vorm van het zand niet te tekenen, want de kegel knipt hem al voor je uit. Een driehoek die
   zelf van vorm verandert zou een pad-animatie zijn; een rechthoek achter een masker is een hoogte. */

.glaze-hourglass { position: relative; width: 96px; height: 150px; }
.glaze-hourglass > .glaze-bulb { position: absolute; left: 0; right: 0; height: 71px; overflow: hidden; }
.glaze-hourglass > .glaze-upper { top: 0; clip-path: polygon(0 0, 100% 0, 54% 100%, 46% 100%); }
.glaze-hourglass > .glaze-lower { bottom: 0; clip-path: polygon(46% 0, 54% 0, 100% 100%, 0 100%); }
.glaze-hourglass > .glaze-bulb > i { position: absolute; left: 0; right: 0; background: linear-gradient(#e8c98b, #c9a35e);
                        animation: sand-empty var(--dur, 8s) linear infinite; }
.glaze-hourglass > .glaze-upper > i { top: 0; height: 100%; transform-origin: top; }
.glaze-hourglass > .glaze-lower > i { bottom: 0; height: 100%; transform-origin: bottom; animation-name: sand-fill; }
/* Het straaltje. Het loopt de hele tijd, want zolang er zand valt is het er. */
.glaze-hourglass::after { content: ""; position: absolute; left: calc(50% - 1px); top: 62px; width: 2px; height: 30px;
                    background: linear-gradient(#e8c98b, #e8c98b00); }
/* Het glas is één omtrek in een svg. Ik heb het eerst met clip-path geprobeerd en dat kan niet: een zandloper is
   een vlinderstrik, en zo'n pad kruist zichzelf - dan mag de browser zelf beslissen wat binnen is. Een omtrek
   tekenen in plaats van een gat knippen omzeilt de hele vraag. */
.glaze-hourglass > .glaze-glass
{
    position: absolute; inset: 0; pointer-events: none;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 150' preserveAspectRatio='none'%3E%3Cpath d='M7 3H89L52 75 89 147H7L44 75Z' fill='none' stroke='rgba(40,40,60,.32)' stroke-width='3' stroke-linejoin='round'/%3E%3Cpath d='M14 9H36L26 30Z' fill='rgba(255,255,255,.45)'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
}
/* De houten kappen boven en onder. */
.glaze-hourglass > .glaze-cap { position: absolute; left: -8px; right: -8px; height: 9px; border-radius: 3px;
                    background: linear-gradient(#9a6b3c, #6b4423); box-shadow: 0 2px 4px #0004; }
.glaze-hourglass > .glaze-cap.glaze-cap-top { top: -4px; }
.glaze-hourglass > .glaze-cap.glaze-cap-bottom { bottom: -4px; }

/* ============================================================ DE LAVALAMP

   De klassieker, en nog steeds het verrassendste wat een filter kan. Losse cirkels vloeien in elkaar over zodra
   ze elkaar naderen - niet doordat er iets berekend wordt, maar door twee filters achter elkaar: blur maakt van
   elke rand een zachte overgang, en een extreem contrast knipt die overgang weer terug tot een harde rand. Twee
   bollen die elkaar overlappen hebben daar samen genoeg dekking voor, en zo ontstaat de brug vanzelf.

   Voorwaarde: de ouder moet zijn EIGEN achtergrond hebben, anders knipt het contrast op wat er toevallig achter
   ligt en krijg je zwarte randen. */

/* De vorm en het filter moeten in TWEE elementen zitten. Zet je het contrast op het element dat ook de ronde hoeken
   heeft, dan eet het filter die hoeken op en houd je een harde zwarte rechthoek over - dat had ik eerst. De
   buitenste doos knipt, de binnenste vloeit. */
.glaze-lava-lamp { position: relative; overflow: hidden; border-radius: 60px / 26px;
            background: linear-gradient(#2a1140, #140823); box-shadow: inset 0 0 0 2px #ffffff1c, 0 8px 22px #0007; }
.glaze-lava-lamp > .glaze-fluid { position: absolute; inset: -16px; background: #0d0616;
                         filter: blur(8px) contrast(15); }
/* Een voet en een kap, zodat het een lamp is en niet een pot. */
.glaze-lava-stand { position: relative; padding: 12px 0; }
.glaze-lava-stand::before, .glaze-lava-stand::after { content: ""; position: absolute; left: 50%; width: 92px; height: 15px;
                                      margin-left: -46px; border-radius: 4px;
                                      background: linear-gradient(#8f8f9c, #4a4a56); box-shadow: 0 2px 5px #0006; }
.glaze-lava-stand::before { top: 4px; }
.glaze-lava-stand::after { bottom: 0; width: 112px; margin-left: -56px; height: 19px;
                   border-radius: 4px 4px 7px 7px; }

/* Een glans over het glas, buiten het filter om. */
.glaze-lava-lamp::after { content: ""; position: absolute; left: 12%; top: 6%; width: 16%; height: 62%; border-radius: 50%;
                   background: linear-gradient(#ffffff30, #ffffff00); pointer-events: none; }
.glaze-lava-lamp .glaze-blob { position: absolute; border-radius: 50%;
                 background: radial-gradient(circle at 36% 32%, #ff9ab4, #ff2e63 62%, #d81b52);
                left: var(--x, 40%); width: var(--d, 44px); height: var(--d, 44px);
                animation: lava-rise var(--dur, 7s) ease-in-out infinite alternate;
                animation-delay: var(--delay, 0s); }

/* ============================================================ DE BEWEGINGEN, BIJ ELKAAR

   Alle keyframes van dit blad staan hier, en dat is met opzet. Negen van de zesendertig worden door meerdere
   klassen gebruikt - spin alleen al door negen, verspreid over vijf secties. Stonden ze bij hun eigen effect, dan
   zou het weghalen van een sectie ergens anders een animatie stilzetten ZONDER FOUTMELDING. Een niet-bestaande
   keyframe is geen fout in CSS, het is gewoon niets.

   Dit blok blijft dus staan, wat je verder ook weghaalt. */

@keyframes beam-swing { from { --beam-x: 16%; } to { --beam-x: 84%; } }

@keyframes blip-flash { 0% { opacity: 1; } 45% { opacity: .18; } 100% { opacity: .05; } }

@keyframes arc-slide { to { background-position: -300% 0; } }

@keyframes bounce { 0%, 60%, 100% { transform: translateY(0); opacity: .5; }
                       30% { transform: translateY(-7px); opacity: 1; } }

@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.045); } }

@keyframes coin-spin { to { transform: rotateY(360deg); } }

@keyframes cube-spin { from { transform: rotateX(-22deg) rotateY(0); }
                          to { transform: rotateX(-22deg) rotateY(360deg); } }

@keyframes drift { from { transform: translateX(-20%); } to { transform: translateX(20%); } }

@keyframes wander { from { transform: translate(-6%, -4%) scale(1); }
                    to { transform: translate(7%, 5%) scale(1.12); } }

@keyframes fall { from { transform: translateY(0); } to { transform: translateY(50%); } }

@keyframes fall-in { from { opacity: 0; transform: translateY(14px) scale(.94); }
                      to { opacity: 1; transform: none; } }

@keyframes flame { from { transform: scaleY(.75) translateY(2px); opacity: .7; }
                  to { transform: scaleY(1.15) translateY(-4px); opacity: 1; } }

@keyframes flicker
{
    0%, 18%, 22%, 25%, 53%, 57%, 100% { text-shadow: 0 0 4px #fff, 0 0 12px var(--neon, #ff5fbf),
                                                     0 0 28px var(--neon, #ff5fbf), 0 0 52px var(--neon, #ff5fbf); }
    20%, 24%, 55% { text-shadow: none; opacity: .55; }
}

@keyframes holo-scan { 0% { top: -40%; } 100% { top: 100%; } }

@keyframes beat { 0%, 62%, 100% { transform: scale(1); } 14% { transform: scale(1.1); }
                     28% { transform: scale(1); } 42% { transform: scale(1.07); } }

@keyframes blink { 50% { border-color: transparent; } }

@keyframes lava-rise { from { bottom: -12%; transform: scale(.85); } to { bottom: 70%; transform: scale(1.15); } }

@keyframes letter-roll
{
    0%   { transform: translateY(calc(var(--glig-highlight) * -6)); animation-timing-function: steps(6); }
    22%  { transform: translateY(0); }
    100% { transform: translateY(0); }
}

@keyframes border-spin { to { --angle: 360deg; } }

@keyframes rise { 0% { transform: translateY(0) translateX(0); opacity: 0; }
                     10% { opacity: .9; }
                     50% { transform: translateY(calc(var(--rise, 130px) * -.5)) translateX(9px); }
                     100% { transform: translateY(calc(var(--rise, 130px) * -1.1)) translateX(-6px);
                            opacity: 0; } }

@keyframes roam { from { --lx: 15%; } to { --lx: 85%; } }

@keyframes sand-empty { 0% { transform: scaleY(1); } 92%, 100% { transform: scaleY(0); } }

@keyframes sand-fill { 0% { transform: scaleY(0); } 92%, 100% { transform: scaleY(1); } }

@keyframes slide { to { background-position: 22.6px 0, 0 0; } }

@keyframes spin { to { transform: rotate(360deg); } }

@keyframes stretch { 0%, 100% { height: 30%; } 50% { height: 100%; } }

@keyframes sweep { 0% { left: -38%; } 100% { left: 100%; } }

@keyframes sweep-shine { from { background-position: 140% 0; } to { background-position: -40% 0; } }

@keyframes swing-in { from { opacity: 0; transform: perspective(700px) rotateY(-55deg) translateX(-24px); }
                       to { opacity: 1; transform: none; } }

@keyframes twinkle { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }

@keyframes type { to { width: calc(var(--chars, 18) * 1ch); } }

@keyframes expand { from { transform: scale(1); opacity: .7; } to { transform: scale(2.6); opacity: 0; } }

@keyframes wave-letter { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }

@keyframes wobble { 0%, 100% { transform: rotate(-2.5deg); } 50% { transform: rotate(2.5deg); } }

@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }

@keyframes glitch-a { 0%, 88%, 100% { transform: none; } 90% { transform: translate(-3px, -1px); }
                     94% { transform: translate(2px, 1px); } }

@keyframes glitch-b { 0%, 88%, 100% { transform: none; } 91% { transform: translate(3px, 1px); }
                     96% { transform: translate(-2px, -1px); } }
