/*
 * Nur, was es in gg-design nicht gibt.
 *
 * Farben, die zwei Themes, die Umfärbung von Bootstrap (Knöpfe, Verweise,
 * Navigationsleiste, Flächen, Ränder, Formularfelder, Seitenzahlen), der
 * Seitenhintergrund (`body.gg-backdrop`) und die Kartenform (`.card gg-card`,
 * `gg-card--action` für eine Karte, die selbst ein Bedienelement ist) kommen
 * aus dem WebJar de.codefish:gg-design, dasselbe, das UTINNI und ISB laden.
 * `frontend/index.html` bindet es nach Bootstrap und vor dieser Datei ein.
 *
 * Eine Änderung am gemeinsamen Erscheinungsbild gehört dorthin und kommt als
 * neue Version (`gg-design.version` in pom.xml). Hier noch einmal gehalten,
 * liefe sie wieder auseinander — genau das war diese Datei bis dahin: eine
 * Abschrift von UTINNIs style.css, die ihre eigenen Werte behielt.
 *
 * Das Theme steht an `<html>` als `data-bs-theme` UND `data-gg-theme`, beide
 * aus einem Wert (`SETTINGS.apply`). Der dunkle Block von gg-design verlangt
 * beide; die dunklen Blöcke unten verlangen dasselbe Paar, damit hier nichts
 * dunkel wird, was gg-design für hell hält.
 *
 * Schrift auf GG-Blau ist dunkel (`--gg-on-primary`, #212529, 7,1:1), nie weiß
 * (2,1:1). Das gilt auch für jede Klasse unten, die GG-Blau als Fläche nimmt.
 */

/* ===== Was gg-design nicht setzt ===== */

:root {
    /* Die `-rgb`-Form von --bs-light gehoert dazu und wurde dreimal vergessen.
       Saemtliche Farb-Hilfsklassen (`.bg-light`, `.text-light`,
       `.border-light`) lesen **nur** diese Form; gg-design kippt --bs-light im
       dunklen Theme, die `-rgb`-Form aber nicht. `.bg-light` bliebe deshalb im
       dunklen Thema fastweiss, und `text-muted` darauf — das kippt sehr wohl
       mit dem Thema — stuende mit 1,17:1 praktisch unsichtbar da. */
    --bs-light-rgb: 248, 249, 250;

    /* Bernstein trägt zwei Zeichen: „intern" in der Antragsansicht und
       „wartet auf uns" in der Liste. Zwei Seiten, und an beiden steht ein
       Symbol daneben, damit die Farbe nicht allein spricht. */
    --amber-border: #e0a800;
    --amber-bg: #fff8e1;
    --amber-color: #7a5c00;
}

[data-gg-theme="dark"][data-bs-theme="dark"] {
    --bs-light-rgb: 33, 37, 41;

    --amber-border: #b08400;
    --amber-bg: rgba(255, 193, 7, 0.07);
    --amber-color: #ffd666;
}

/* ===== Base ===== */

/* Die feste Navigationsleiste (`fixed-top`) liegt über dem Seitenanfang. */
body {
    padding-top: 56px;
}

/*
 * Der Kopf einer Tabelle, abgesetzt vom Rumpf und in beiden Themen.
 *
 * Bootstraps `.table-light` stand hier und ist fest verdrahtet
 * (`--bs-table-bg: #f8f9fa`, `--bs-table-color: #000`) — im dunklen Thema ein
 * fastweisses Band ueber einer dunklen Tabelle, lesbar, aber verkehrt herum.
 * Dieselben zwei Variablen, besetzt mit Werten, die mit dem Thema kippen:
 * eine Regel fuer beide.
 */
.thead-enlist {
    --bs-table-bg: var(--bs-secondary-bg);
    --bs-table-color: var(--bs-body-color);
    color: var(--bs-table-color);
}

/* The GMOs' signature on the landing page is blue ink on a transparent
 * ground; on the dark page the same blue is a little too dark to read
 * comfortably, so it is lifted there and only there. */
[data-gg-theme="dark"][data-bs-theme="dark"] .gmo-signature {
    filter: brightness(1.4);
}

/* btn-enlist = accent button for CTAs. Dieselbe Fläche und dieselbe dunkle
 * Schrift wie gg-designs Primärknopf. */
.btn-enlist {
    background-color: var(--bs-primary) !important;
    border-color: var(--bs-primary) !important;
    color: var(--gg-on-primary) !important;
}

.btn-enlist:hover {
    background-color: var(--bs-primary-hover) !important;
    border-color: var(--bs-primary-hover) !important;
    color: var(--gg-on-primary) !important;
}

/* ===== Enlist-specific components ===== */

/*
 * Ein Abzeichen ist eine Pille und bleibt eine: `nowrap` hält das Etikett
 * in einer Zeile. Die Klasse steht nirgends neben Bootstraps `.badge` —
 * sie wird immer allein gesetzt (`status-badge`, `status-badge me-1`) —,
 * erbt dessen `white-space: nowrap` also nicht. Zusammen mit mehrwortigen
 * Etiketten („Antrag eingereicht", „Warten auf 2. GMO") und dem Bindestrich
 * in „GWL-Bearbeitung" brach die Pille auf 320 px mitten im Etikett um, und
 * weil die Klasse auch kein `display` setzt, zerfiel sie dabei in zwei halbe
 * Pillen mit Rundung an den falschen Enden. `nowrap` unterdrückt jede weiche
 * Umbruchstelle, den Bindestrich eingeschlossen.
 *
 * Umbrechen darf dafür die Zeile um das Abzeichen: in der Tabelle trägt
 * `table-responsive` den waagerechten Lauf, an den drei anderen Stellen
 * steht das Abzeichen in einem `flex-wrap` oder hinter Text, der vorher
 * bricht. Das längste Etikett („Warten auf 2. GMO") misst damit 151 px und
 * bleibt auf 320 px überall im Bild — in der Filterliste des Auswahlfelds,
 * der engsten Stelle, stehen 218 px zur Verfügung. Deshalb braucht es hier
 * keine Media Query; `enlist.css` hätte sonst ihre erste.
 *
 * Teurer wird nur der Lauf, den die Tabelle schon vorher hatte: auf 320 px
 * wächst er von 160 px auf 174 px. Nichts scrollt neu, es scrollt etwas
 * länger. Messung und Vorher/Nachher-Bild:
 * `docs/ux/prototypes/status-abzeichen-schmale-handys.html`.
 *
 * Das fehlende `display` war damit benannt, aber nicht behoben, und es wirkt
 * auch ohne Umbruch: ohne `display` ist die Pille ein `inline`-Kasten. Ihre
 * Höhe kommt dann aus den Metriken der Schrift statt aus dem Stilblatt, und
 * — der teurere Teil — in einem Flex-Kasten ist sie überhaupt kein
 * `inline`-Kasten mehr, sondern wird blockartig und erbt die Zeilenhöhe 1,5.
 * Dieselbe Klasse war damit in jedem Kontext anders hoch: gemessen 20,0 px
 * in Tabellenzelle und Kartenüberschrift, 16,2 px in der Filterliste und
 * 20,8 px im Verlauf (`ApplicationTimeline.vue`, `d-flex`). Die echte
 * Bootstrap-Pille daneben ist dort 17,7 px hoch — 3,1 px Unterschied, und im
 * Mitarbeiterbrett stehen beide Arten in **derselben Karte**: die
 * Schnellfilter (`StaffDashboard.vue:105` und `:118`) sind echte
 * `badge rounded-pill`-Pillen, Filterliste und Tabelle darunter nicht.
 *
 * `display: inline-block` plus `line-height: 1` ist das Paar, das Bootstrap
 * 5.3.8 auf `.badge` setzt, und es gehört zusammen: `inline-block` allein
 * erbt die Zeilenhöhe 1,5 und bläst die Pille auf 24 px auf. Dazu kommt
 * Bootstraps senkrechte Polsterung — 0,35em statt 0,25em —, und zwar nicht
 * als Geschmacksfrage: ohne sie misst das Abzeichen 18,0 px gegen
 * Bootstraps 20,4 px und wäre nach der Korrektur weiter weg als vorher.
 * Mit allen drei Werten ist die Pille in jedem Kontext und auf jeder
 * Schriftgröße **deckungsgleich** mit einer echten Bootstrap-Pille daneben:
 * 20,38 px hoch auf 0,75 rem, 17,66 px auf 0,65 rem, und auf derselben Lage
 * zur Grundlinie — Abweichung 0,00 px an allen fünf nachgemessenen Stellen.
 * Die Lage zur Grundlinie steht hier bewusst als Unterschied und nicht als
 * absolute Zahl: wo genau die Grundlinie einer Zeile liegt, rundet der
 * Browser je nach Schriftgröße des Elternelements, der Abstand zwischen den
 * beiden Pillen tut es nicht.
 *
 * Waagerecht bleibt alles, wie es war: 0,75em Polsterung links und rechts
 * statt Bootstraps 0,65em, weil die flache, breite Form gewollt ist und zu
 * Großbuchstaben mit `letter-spacing` gehört. Die Breiten ändern sich
 * dadurch um **kein** Pixel, und die Messungen für schmale Handys weiter
 * oben gelten unverändert.
 *
 * `vertical-align: baseline` setzt Bootstrap zusätzlich, hier steht es
 * nicht: für `inline-block` ist es der Vorgabewert, `vertical-align` erbt
 * nicht, und das `vertical-align: middle` der Tabellenzelle greift auf die
 * Zelle und nicht auf ihr Inline-Kind — an allen vier Einbaustellen
 * nachgemessen. Eine Zeile, die nichts tut, verschweigt beim nächsten Lesen,
 * dass sie nichts tut.
 */
.status-badge {
    display: inline-block;
    font-size: 0.75rem;
    line-height: 1;
    padding: 0.35em 0.75em;
    border-radius: 999px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    white-space: nowrap;
}

/*
 * Die Schrift richtet sich nach dem Grundton und nicht nach dem Geschmack:
 * heller Ton traegt schwarze Schrift, dunkler Ton weisse. Zwei Abzeichen
 * hielten sich nicht daran und waren in **beiden** Themen unlesbar —
 * „eingereicht" mit weiss auf GG-Blau (2,18:1) und „Rueckfragen" mit weiss
 * auf Orange (2,57:1). Beide tragen jetzt Schwarz, 9,61:1 und 8,17:1.
 * Die Abzeichen sind themenunabhaengig: sie bringen Grund und Schrift
 * selbst mit, deshalb steht hier kein zweiter Satz fuers dunkle Thema.
 */
.status-eingereicht { background-color: var(--gg-blue); color: #000; }
.status-warten_gmo { background-color: #0dcaf0; color: #000; }
.status-review { background-color: #ffc107; color: #000; }
.status-rueckfragen { background-color: #fd7e14; color: #000; }
.status-ready_for_duty { background-color: #20c997; color: #000; }
.status-warten_gwl { background-color: #6f42c1; color: #fff; }
.status-gwl_bearbeitung { background-color: #0d6efd; color: #fff; }
.status-abgeschlossen { background-color: #198754; color: #fff; }
.status-archiviert { background-color: #6c757d; color: #fff; }
.status-terminal { background-color: #dc3545; color: #fff; }
/* The eleventh state: carried over from the old portal, matching no step.
   Grey and not red — it is not a fault of the application. */
.status-unbekannt { background-color: #5c636a; color: #fff; }

/*
 * A message body, as it comes out of `MessageBodyRenderer`.
 *
 * The content is foreign HTML from a 2021 portal, 34.841 times over: images
 * at full size, tables wider than the column, lines that never wrap. Without
 * these four rules a single old message pushes the whole page to the right.
 * This is presentation and replaces no sanitising — that happened on the
 * server.
 */
.message-body img { max-width: 100%; height: auto; }
.message-body table { max-width: 100%; display: block; overflow-x: auto; }
.message-body pre { white-space: pre-wrap; word-break: break-word; }
.message-body { overflow-wrap: anywhere; }

.hero-section {
    background-color: var(--bs-primary);
    color: var(--gg-on-primary);
    padding: 4rem 0;
    margin-top: -56px;
    padding-top: calc(4rem + 56px);
}

.timeline-item {
    position: relative;
    padding-left: 2rem;
    padding-bottom: 1.5rem;
    border-left: 2px solid #dee2e6;
}

.timeline-item:last-child {
    border-left: 2px solid transparent;
}

.timeline-item::before {
    content: '';
    position: absolute;
    left: -6px;
    top: 0;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--bs-primary);
}

/* An internal note, set apart as a note on amber — the colour osTicket gave
   them, so the handlers who came from there know it on sight. Muted on
   purpose: the solid yellow of `alert-warning` means „Achtung" elsewhere in
   enlist. The lock and the word stay beside it, so the colour is never the
   only sign. */
.timeline-item.is-internal::before {
    background: var(--amber-border);
}

.message-internal,
.composer-internal {
    border: 1px solid var(--amber-border);
    border-left-width: 4px;
    border-radius: 0.375rem;
    background: var(--amber-bg);
}

.message-internal {
    margin-left: -0.5rem;
    padding: 0.5rem 0.75rem 0.75rem;
}

.composer-internal {
    padding: 0.5rem;
}

.text-internal {
    color: var(--amber-color);
}

.badge-internal {
    color: var(--amber-color);
    border: 1px solid var(--amber-border);
    background: transparent;
}

/* An application that waits for an answer from us, in the staff list: a
   stripe at the row's left edge and an icon beside the subject, never a
   tinted row — a table in which half the rows glow is one nobody reads. */
.row-awaiting > td:first-child {
    box-shadow: inset 4px 0 0 var(--amber-border);
}

/* The same stripe on the phone's card. */
.card-awaiting {
    box-shadow: inset 4px 0 0 var(--amber-border);
}

.icon-awaiting {
    color: var(--amber-border);
}

.step-indicator {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    margin-bottom: 2rem;
}

.step-indicator .step {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    border: 2px solid #dee2e6;
    color: #6c757d;
    background: #fff;
    transition: all 0.3s;
}

.step-indicator .step.active {
    border-color: var(--bs-primary);
    background: var(--bs-primary);
    color: var(--gg-on-primary);
}

.step-indicator .step.completed {
    border-color: var(--bs-success);
    background: var(--bs-success);
    color: var(--gg-on-fill);
}

.step-connector {
    width: 40px;
    height: 2px;
    background: #dee2e6;
    align-self: center;
}

.step-connector.completed {
    background: var(--bs-success);
}

.photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1rem;
}

.photo-grid img {
    width: 100%;
    height: 200px;
    object-fit: cover;
    border-radius: 8px;
    cursor: pointer;
    transition: transform 0.2s;
}

.photo-grid img:hover {
    transform: scale(1.05);
}

.approval-chain {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
}

.approval-step {
    flex: 1;
    min-width: 150px;
    padding: 1rem;
    border-radius: 8px;
    border: 2px solid #dee2e6;
    text-align: center;
}

.approval-step.pending { border-color: #6c757d; }
.approval-step.approved { border-color: var(--bs-success); background: rgba(25, 135, 84, 0.05); }
.approval-step.rejected { border-color: var(--bs-danger); background: rgba(220, 53, 69, 0.05); }

/* ===== Spinner: the garrison's crest as a spinning coin =====
 * The same motion as ISB's (isb.css, .isb-spinner): the crest turns about the
 * vertical axis, narrows to its edge, comes back mirrored and turns home.
 * Pure CSS, so index.html can draw it before Vue has loaded, with the same
 * markup EnlistSpinner.vue renders. */

.enlist-spinner {
    --enlist-coin-size: 3rem;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
}

.enlist-spinner-sm {
    --enlist-coin-size: 1.25rem;
    flex-direction: row;
    gap: 0.5rem;
    vertical-align: middle;
}

.enlist-spinner-lg {
    --enlist-coin-size: 6rem;
}

.enlist-spinner-coin {
    width: var(--enlist-coin-size);
    height: var(--enlist-coin-size);
    border-radius: 50%;
    animation: enlist-coin-flip 1.6s linear infinite;
}

.enlist-spinner-label {
    color: var(--bs-secondary-color);
}

@keyframes enlist-coin-flip {
    0% {
        transform: perspective(calc(var(--enlist-coin-size) * 4)) rotateY(0deg);
        filter: brightness(1);
    }
    25% {
        transform: perspective(calc(var(--enlist-coin-size) * 4)) rotateY(90deg);
        filter: brightness(0.6);
    }
    50% {
        transform: perspective(calc(var(--enlist-coin-size) * 4)) rotateY(180deg);
        filter: brightness(1);
    }
    75% {
        transform: perspective(calc(var(--enlist-coin-size) * 4)) rotateY(270deg);
        filter: brightness(0.6);
    }
    100% {
        transform: perspective(calc(var(--enlist-coin-size) * 4)) rotateY(360deg);
        filter: brightness(1);
    }
}

/* Whoever switched motion off gets a quiet pulse instead of the turn. */
@media (prefers-reduced-motion: reduce) {
    .enlist-spinner-coin {
        animation: enlist-coin-pulse 2s ease-in-out infinite;
    }
}

@keyframes enlist-coin-pulse {
    50% {
        opacity: 0.5;
    }
}

/* ===== Textfarben im Beitrag (Issue #27) =====
 *
 * Five colours, and every rule below declares `color` and nothing else.
 *
 * That restriction is the reason a class is allowed here at all. A writer
 * chooses a name out of a closed list (`frontend/src/lib/text-color.ts`) and
 * the stylesheet decides what the name means, so nothing a writer types ever
 * reaches a declaration. The moment one of these rules also set
 * `background`, `position` or `content`, the class would be the hole that a
 * `style` attribute would have been: text laid over the page, a false button,
 * a sentence the author never wrote appearing through `content`. **Add a
 * colour by adding a variable and a rule of one line. Add nothing else.**
 *
 * The values are mid-tones rather than Bootstrap's `-text-emphasis`
 * colours, which are so dark that a coloured word reads as black — the point
 * of the palette is to be seen as a colour. Each one carries at least 4.5:1
 * against both backgrounds of its theme (WCAG AA for body text): light
 * against #fff and #f8f9fa, dark against #212529 and #181818. The dark
 * values are Bootstrap's own dark-theme emphasis tones where there is one,
 * so a coloured word sits with the rest of the surface instead of beside it.
 *
 * The class is also what the server's renderer emits — `OwnMarkupResolver`,
 * out of the closed Java enum `TextColour` — which is why this lives in the
 * global stylesheet and not in the editor's own chunk: a message body is drawn
 * on pages that never load the editor.
 *
 * **Both halves of that are nailed down.** `TheColourPaletteIsOneListTest`
 * reads the five names out of `text-color.ts` and fails when they and the Java
 * enum disagree, and it reads the rules below and fails when one of them
 * declares anything but `color`. The restriction above is therefore the test
 * and not only this paragraph.
 */

:root {
    --enl-color-rot: #b02a37;
    --enl-color-orange: #a55200;
    --enl-color-gruen: #146c43;
    --enl-color-blau: #0a58ca;
    --enl-color-grau: #595f66;
}

[data-gg-theme="dark"][data-bs-theme="dark"] {
    --enl-color-rot: #ea868f;
    --enl-color-orange: #ffb366;
    --enl-color-gruen: #75b798;
    --enl-color-blau: #6ea8fe;
    --enl-color-grau: #adb5bd;
}

.enl-c-rot {
    color: var(--enl-color-rot);
}

.enl-c-orange {
    color: var(--enl-color-orange);
}

.enl-c-gruen {
    color: var(--enl-color-gruen);
}

.enl-c-blau {
    color: var(--enl-color-blau);
}

.enl-c-grau {
    color: var(--enl-color-grau);
}

/*
 * Eine Erwähnung im gelesenen Beitrag.
 *
 * `OwnMarkupResolver.MENTION_CLASS` setzt diese Klasse auf das `<strong>`, das
 * die Hervorhebung schon ist — die Auszeichnung braucht also kein Stilblatt, um
 * sichtbar zu sein, und was hier steht, ist der Haken dafür, dass eine
 * Erwähnung im Beitrag so aussieht wie im Editor (`.md-mention` in
 * `RichMarkdownEditor.vue`). Beides ruhig und beides mit
 * Bootstrap-Variablen, die mit `data-bs-theme` kippen: eine Erwähnung ist ein
 * Name und kein Alarm.
 *
 * **Keine `color`.** Die Schrift bleibt die des Absatzes, damit die Farbe die
 * eine Bedeutung behält, die ihr `enl-c-*` gibt.
 */
.enl-mention {
    background-color: var(--bs-secondary-bg);
    border-radius: 0.2rem;
    padding: 0 0.2rem;
}
