@props([
    // Das Ticket, das der Browser einlöst. Dreißig Sekunden, genau einmal.
    'ticket' => '',
    // Was auf der Bühne steht, wenn die Seite aufgeht.
    'title' => '',
    'note' => '',
    // Die Meldungen, die erst der Browser kennt (Schließcodes der Brücke).
    'messages' => [],
    // Ob ein neuer Versuch überhaupt etwas ändern kann.
    'retry' => false,
    'retryLabel' => '',
])
{{-- Schirm und Bühne für eine Terminalsitzung — geteilt von beiden Fenstern.

     Das gab es zuerst nur einmal, für einen Host. Als das Terminal zum
     CluPilot-Server dazukam, waren zwei Wege möglich: abschreiben oder
     herausziehen. Abgeschrieben wäre der Vorspann zweimal da und würde einmal
     gepflegt — und was hier steht, ist zum guten Teil AM BILDSCHIRM GEMESSEN
     (Zellbreiten, Schriftgrößen, welche Klasse welche schlägt). Genau solche
     Zeilen überleben eine Abschrift nicht.

     Was NICHT hierher gehört: die Texte. Die kommen von der Seite, die diese
     Bühne benutzt — ein Fenster spricht von einem Host, das andere vom Server,
     und ein Bauteil, das beides selbst entscheidet, hätte einen Grund, ihre
     Sprachdateien zu kennen.

     resources/js/terminal.js bleibt davon unberührt: es hängt an den
     data-Attributen unten, nicht an einer Seite. --}}

{{-- Die Bühne liegt ÜBER dem Terminal, nicht daneben.

     Bis hierher waren es zwei Geschwister, von denen abwechselnd eines
     `hidden` trug: erst der Vorspann, dann der Schirm. Das trug genau einmal —
     beim Aufbau. Für alles danach fehlte die Rückfahrkarte, und was der
     Betreiber beim Abbruch sah, war eine rote ANSI-Zeile mitten in der eigenen
     Ausgabe: die einzige Stelle im Produkt, an der eine Meldung nicht gestaltet
     war, sondern getippt.

     Als Überlagerung kann dieselbe Bühne dreimal auftreten — beim Verbinden,
     beim Abbruch, beim Ende — und die Sitzung darunter bleibt stehen, statt
     gelöscht zu werden. Was auf ihr steht, kommt aus den Sprachdateien; die
     Meldungen, die erst der Browser kennt, reisen als JSON in
     `data-stage-messages` mit, damit auch sie dort stehen und nicht im Skript. --}}
<div class="relative flex h-screen w-screen flex-col overflow-hidden bg-ink"
     data-terminal
     data-ticket="{{ $ticket }}">

    {{-- wire:ignore: xterms eigener DOM-Baum liegt in einem von Livewire
         verwalteten Baum. Heute hat keine der beiden Komponenten eine Aktion,
         die einen Re-Render auslöst — aber das erste `wire:`-irgendwas auf so
         einer Seite würde xterm sonst beim nächsten Umlauf löschen. --}}
    <div data-terminal-screen wire:ignore class="flex-1 overflow-hidden"></div>

    <div data-terminal-stage
         class="absolute inset-0 z-10 flex flex-col items-center justify-center gap-6 bg-ink px-6 text-center"
         data-stage-messages="{{ json_encode($messages, JSON_UNESCAPED_UNICODE) }}">

        {{-- Die Wortmarke als Schriftgrafik.

             `role="img"` mit lesbarem Namen statt `aria-hidden`: ein
             Screenreader soll „CluPilot" hören, nicht die einzelnen Zeichen der
             Zeichnung.

             Selbst gezeichnet, nicht aus einer Figlet-Schrift übernommen. Die
             übernommene Fassung hatte im Bogen des `P` einen Überhang — eine
             Zelle in der zweiten Zeile, unter der in der ersten nichts stand —
             und der stand als loser Klotz mitten im Wort. Figlet-Schriften sind
             für echte Terminalschriften gezeichnet und tragen hier nicht. Jeder
             Buchstabe ist acht Zellen breit (das `I` zwei), mit einer Zelle
             Abstand, und keine Zelle steht ohne Nachbarn darüber. Nicht von Hand
             abgezählt, sondern aus einer Buchstabentabelle gesetzt — von Hand
             hatte ich mich prompt verzählt, und die Buchstaben liefen ineinander.

             `█` füllt seine Zelle ganz aus und stapelt deshalb in jeder Schrift
             sauber — anders als `_ / \ |`, die auf Berührung zwischen den Zeilen
             angewiesen sind. Bei enger Zeilenhöhe verschmierte das Wort damit,
             bei weiter zerfiel es. Beides im Browser durchgemessen.

             Immer Akzentfarbe, auch im Fehlerfall: Dunkelrot auf Fast-Schwarz
             hatte kaum Kontrast, und eine Wortmarke, die ihre Farbe wechselt, ist
             ohnehin keine Statuslampe — was los ist, sagt die Zeile darunter.

             Acht Zellen pro Buchstabe, nicht sechs: bei sechs standen sie hoch
             und schmal da. Acht trifft die Proportion der Wortmarke.

             Zwei Größen: die Zeichnung ist 65 Zellen breit, und eine Zelle ist
             gut 0,6 der Schriftgröße. 13px ergeben rund 500px — auf dem Schirm
             eine Wortmarke, kein Etikett. Am Telefon sind es 7px und damit rund
             270px, was neben den Rändern noch hineinpasst. --}}
        <pre data-stage-mark
             class="select-none font-mono text-[7px] leading-none text-accent sm:text-[13px]"
             role="img" aria-label="CluPilot"> ██████  ██       ██    ██ ████████ ██ ██        ██████  ████████
██       ██       ██    ██ ██    ██ ██ ██       ██    ██    ██   
██       ██       ██    ██ ████████ ██ ██       ██    ██    ██   
██       ██       ██    ██ ██       ██ ██       ██    ██    ██   
 ██████  ████████  ██████  ██       ██ ████████  ██████     ██   </pre>

        {{-- aria-live: die Bühne tauscht ihren Text aus, ohne dass die Seite neu
             lädt. Ohne diesen Hinweis erführe ein Screenreader vom Abbruch
             nichts — für ihn stünde das Fenster weiter beim Vorspann. --}}
        <div class="max-w-sm space-y-2" aria-live="polite">
            <p data-stage-title class="text-sm font-semibold text-bg">{{ $title }}</p>
            <p data-stage-note class="text-xs leading-relaxed text-bg opacity-70">{{ $note }}</p>
        </div>

        {{-- Neu laden statt neu verbinden: das Ticket gilt dreißig Sekunden und
             genau einmal, ein zweiter Anlauf mit demselben wäre keiner. Der
             Knopf ist beim Vorspann verborgen und kommt erst, wenn ein neuer
             Versuch überhaupt etwas ändern kann — bei „kein Schlüssel
             hinterlegt" ändert er nichts, dort bleibt er weg. Was er tut, hängt
             terminal.js an; ein `onclick` im Markup wäre Verhalten an der
             Stelle, an der sonst nur Gestalt steht.

             `hidden` sitzt am Wrapper, nicht am Knopf. Nicht, weil es dort nicht
             wirkte — Tailwind gibt `.hidden` als letzte der Display-Klassen aus
             und schlägt `inline-flex` damit —, sondern weil die Klassen des
             Knopfes aus einem geteilten Bauteil kommen und an dieser Stelle
             niemandem gehören. Die Bühne selbst trägt `hidden` und `flex`
             durchaus gemeinsam: das ist ein Element, das hier steht und hier
             bleibt. --}}
        <div data-stage-retry @class(['hidden' => ! $retry])>
            <x-ui.button data-stage-retry-button variant="secondary" size="sm">
                {{ $retryLabel }}
            </x-ui.button>
        </div>
    </div>
</div>
