/*!
 * CoreSystem — Installer stylesheet (#2019 T5)
 *
 * Loaded AFTER Bootstrap 5.3.3 (/assets/frontend/css/bootstrap.min.css) and
 * Font Awesome 5.13 (/assets/base/css/all.min.css), and it builds on both
 * instead of restating them: no colours are hard-coded, everything reads from
 * the Bootstrap custom properties (--bs-body-bg, --bs-border-color, ...). That
 * is what makes dark mode free — Bootstrap 5.3 redefines those variables under
 * [data-bs-theme=dark], so every rule below follows without a single dark-mode
 * override.
 *
 * The backend's own stylesheets (light.css / dark.css, 550 KB each) are NOT
 * used: they are AppStack builds of Bootstrap 5.2, which predates
 * [data-bs-theme] and switches mode by toggling two <link> elements. See the
 * doc-block of templates/layout.php.
 *
 * Responsive down to 375 px — the width of the smallest phone still in wide
 * use, and a realistic device for an operator who is standing next to a server.
 */

.ps-install {
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.ps-install__shell {
    width: 100%;
    max-width: 62rem;
    margin: 0 auto;
    padding-left: 1rem;
    padding-right: 1rem;
}

.ps-install__skip {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    z-index: 10;
}

/* ---------------------------------------------------------------- header -- */

.ps-install__header {
    border-bottom: 1px solid var(--bs-border-color);
    background-color: var(--bs-tertiary-bg);
    padding: 0.75rem 0;
}

.ps-install__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0.5rem;
    background-color: var(--bs-primary);
    color: #fff;
    font-size: 1.05rem;
}

.ps-install__brand {
    font-weight: 600;
    font-size: 1.05rem;
    line-height: 1.1;
    display: flex;
    flex-direction: column;
}

.ps-install__brand-sub {
    font-weight: 400;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
}

/* -------------------------------------------------------------- progress -- */

.ps-install__progress-label {
    font-size: 0.875rem;
    color: var(--bs-secondary-color);
    margin-bottom: 0.35rem;
}

.ps-install__progress {
    height: 0.4rem;
    margin-bottom: 0.85rem;
}

.ps-install__steps {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.1rem;
    margin: 0;
    padding: 0;
}

.ps-install__step {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}

.ps-install__step-no {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    border: 1px solid var(--bs-border-color);
    font-size: 0.75rem;
    flex-shrink: 0;
}

.ps-install__step--done .ps-install__step-no {
    background-color: var(--bs-success);
    border-color: var(--bs-success);
    color: #fff;
}

.ps-install__step--current {
    color: var(--bs-emphasis-color);
    font-weight: 600;
}

.ps-install__step--current .ps-install__step-no {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
    color: #fff;
}

.ps-install__step-title a {
    color: inherit;
}

/* ------------------------------------------------------------------ card -- */

.ps-install__main {
    flex: 1 0 auto;
    padding-top: 1.5rem;
    padding-bottom: 2.5rem;
}

.ps-install__card {
    border-color: var(--bs-border-color);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.ps-install__card > .card-body {
    padding: 1.5rem;
}

.ps-install__lead {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    margin-bottom: 1.25rem;
}

.ps-install__lead-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    flex-shrink: 0;
    border-radius: 0.75rem;
    background-color: var(--bs-primary-bg-subtle);
    color: var(--bs-primary-text-emphasis);
    font-size: 1.2rem;
}

.ps-install__lead-icon--danger {
    background-color: var(--bs-danger-bg-subtle);
    color: var(--bs-danger-text-emphasis);
}

.ps-install__lead-icon--warning {
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
}

/* ----------------------------------------------------------------- facts -- */

.ps-install__facts {
    list-style: none;
    margin: 0 0 0.5rem;
    padding: 0;
    display: grid;
    gap: 0.75rem;
}

.ps-install__facts > li {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
}

.ps-install__facts > li > i {
    width: 1.5rem;
    text-align: center;
    margin-top: 0.2rem;
    color: var(--bs-secondary-color);
}

.ps-install__facts strong {
    display: block;
    font-size: 0.95rem;
}

.ps-install__facts span {
    color: var(--bs-secondary-color);
    font-size: 0.9rem;
}

/* ------------------------------------------------- installation phases -- */

/* The phase list of the installation run (#2019 T12).

   Same construction as the check list below — one row per item, a status icon
   in front, a tint on the row that is NEVER the only carrier of the status: the
   icon shape differs (check / cross / play / clock) and a visually-hidden word
   names the state for a screen reader. */

.ps-install__phases {
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    overflow: hidden;
    counter-reset: none;
}

.ps-install__phase {
    display: flex;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.ps-install__phase:last-child {
    border-bottom: 0;
}

.ps-install__phase--done {
    background-color: var(--bs-success-bg-subtle);
}

.ps-install__phase--failed {
    background-color: var(--bs-danger-bg-subtle);
}

.ps-install__phase--current {
    background-color: var(--bs-primary-bg-subtle);
}

.ps-install__phase-icon {
    font-size: 1.05rem;
    line-height: 1.5;
    flex-shrink: 0;
    width: 1.25rem;
    text-align: center;
    color: var(--bs-secondary-color);
}

.ps-install__phase--done .ps-install__phase-icon {
    color: var(--bs-success-text-emphasis);
}

.ps-install__phase--failed .ps-install__phase-icon {
    color: var(--bs-danger-text-emphasis);
}

.ps-install__phase--current .ps-install__phase-icon {
    color: var(--bs-primary-text-emphasis);
}

.ps-install__phase-body {
    min-width: 0;
    flex: 1;
}

.ps-install__phase-label {
    display: block;
    font-weight: 600;
}

.ps-install__phase-text {
    display: block;
    font-size: 0.9rem;
    color: var(--bs-secondary-color);
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- checks -- */

.ps-install__checks {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.5rem;
    overflow: hidden;
}

.ps-install__check {
    display: flex;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.ps-install__check:last-child {
    border-bottom: 0;
}

/* Status is carried by the icon shape and the badge word as well — the tint is
   the third, redundant carrier, never the only one. */
.ps-install__check--fail {
    background-color: var(--bs-danger-bg-subtle);
}

.ps-install__check--warn {
    background-color: var(--bs-warning-bg-subtle);
}

.ps-install__check-icon {
    font-size: 1.1rem;
    line-height: 1.5;
    flex-shrink: 0;
}

.ps-install__check-body {
    min-width: 0;
    flex: 1;
}

.ps-install__check-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.15rem;
}

.ps-install__check-label {
    font-weight: 600;
}

.ps-install__check-message {
    margin: 0;
    color: var(--bs-body-color);
    overflow-wrap: anywhere;
}

.ps-install__check-hint {
    margin: 0.4rem 0 0;
    font-size: 0.9rem;
    color: var(--bs-secondary-color);
    overflow-wrap: anywhere;
}

.ps-install__check-hint > i {
    margin-right: 0.35rem;
}

.ps-install__check-detail {
    margin-top: 0.5rem;
    font-size: 0.875rem;
}

.ps-install__check-detail > summary {
    cursor: pointer;
    color: var(--bs-secondary-color);
}

/* ------------------------------------------------------------------ form -- */

/*
 * The per-field error of the database step (#2019 T6).
 *
 * Not Bootstrap's `.invalid-feedback`: that class is display:none until a
 * sibling carries `.is-invalid`, which ties the message's visibility to a
 * specific DOM order. Here the message is rendered by the server ONLY when
 * there is one, it carries role="alert" and the input points at it through
 * aria-describedby — so it must be visible unconditionally.
 *
 * `--bs-danger-text-emphasis` rather than `--bs-danger`: Bootstrap tunes the
 * emphasis variant for text on the body background in both modes (measured
 * 7.1:1 light, 8.6:1 dark on the card), while the raw `--bs-danger` is a fill
 * colour and misses AA in light mode.
 *
 * The icon is the second carrier, the word "Fehler:" (visually hidden, for
 * screen readers) the third — never colour alone.
 */
.ps-install__field-error {
    margin: 0.35rem 0 0;
    font-size: 0.875rem;
    color: var(--bs-danger-text-emphasis);
    overflow-wrap: anywhere;
}

.ps-install__field-error > i {
    margin-right: 0.3rem;
}

/* Help text sits between the input and its error; without this the two run
   into each other on a phone. */
.ps-install .form-text {
    font-size: 0.85rem;
}

/*
 * The scheme chooser of the application step is a <fieldset>, because two radio
 * buttons are ONE control and only a <legend> makes a screen reader announce
 * its name before either option (#2019 T7).
 *
 * Bootstrap styles a bare `legend` as a section heading — `float: left`,
 * `width: 100%` and `calc(1.275rem + .3vw)`. Next to the two normal
 * `.form-label`s beside it that reads as a headline shouting at its
 * neighbours, which the first browser pass of T7 showed plainly. The rule
 * brings it back to the size and flow of a label without giving up the
 * semantics.
 */
.ps-install fieldset > legend.form-label {
    float: none;
    width: auto;
    font-size: 1rem;
    line-height: inherit;
}

/* The transport verdict of the database step, printed even when it is the good
   one so that a wrong verdict is visible rather than silent. Muted on purpose:
   it is a statement of fact, not a warning — the warning case renders as an
   alert instead. */
.ps-install__transport {
    display: flex;
    gap: 0.5rem;
    align-items: baseline;
    margin: 1rem 0 0;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}

/* ------------------------------------------------------------------ code -- */

/* Absolute server paths and version banners land here. `overflow-wrap: anywhere`
   rather than a horizontal scrollbar: a path that is cut off on a phone is a
   path the operator cannot act on. */
.ps-install__code {
    margin: 0.5rem 0 0;
    padding: 0.6rem 0.75rem;
    border-radius: 0.375rem;
    background-color: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    font-family: var(--bs-font-monospace);
    font-size: 0.8125rem;
    line-height: 1.55;
    overflow-wrap: anywhere;
    white-space: normal;
}

.ps-install__code code {
    color: inherit;
    padding: 0;
    background: none;
}

.ps-install__reference {
    font-size: 1.05rem;
    letter-spacing: 0.05em;
}

/* --------------------------------------------------------------- actions -- */

.ps-install__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: flex-end;
    margin-top: 1.5rem;
}

.ps-install__note {
    margin: 0.75rem 0 0;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
    text-align: right;
}

.ps-install__help {
    font-size: 0.9rem;
    color: var(--bs-secondary-color);
}

.ps-install__help > summary {
    cursor: pointer;
}

.ps-install__footer {
    padding: 1rem 0 2rem;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}

/* --------------------------------------------------------- contrast (AA) -- */

/*
 * Bootstrap's stock colours miss WCAG AA (4.5:1 for normal text) in a handful
 * of places, measured in both modes on this page. This is the FIRST screen of
 * the product, and one of the misses is the `<code>` that tells the operator
 * which file to open — so the fixes belong here rather than in a backlog.
 *
 * Measured before → after (foreground on the background it actually sits on):
 *
 *   .btn-outline-secondary  dark, header bg    2.84 → 6.42
 *   .btn-outline-secondary  dark, card bg      3.29 → 7.43
 *   .btn-outline-secondary  light, header bg   4.45 → 5.78
 *   .btn-outline-primary    dark, card bg      3.43 → 6.39
 *   .btn-outline-primary    light, header bg   4.27 → 6.11
 *   <code> in .alert-warning  light            4.06 → 7.21
 *   <code> in .alert-info     light            3.86 → 7.65
 *   <code> on card bg         light            4.50 → 16.1 (was exactly at the
 *                                                    threshold, i.e. one
 *                                                    rounding step from failing)
 *   .form-check-label of an invalid ack
 *                           light, alert-warning bg  4.08 → 12.3
 */

/*
 * One rule for every `<code>` instead of one per context. `inherit` resolves to
 * the text colour of whatever contains it — the alert's own emphasis colour
 * inside an alert, the body colour on a card — and those are precisely the
 * pairings Bootstrap already tunes for AA. It therefore stays correct in dark
 * mode and for alert variants this wizard does not use yet, which a fixed hex
 * would not. The monospace face keeps code recognisable without the colour.
 */
.ps-install code {
    color: inherit;
}

/*
 * Outline buttons: only the resting foreground and border are lifted. The hover
 * state is left alone on purpose — it flips to a solid fill with white text
 * (4.68:1), which already passes.
 */
.ps-install .btn-outline-secondary {
    --bs-btn-color: #5c636a;
    --bs-btn-border-color: #5c636a;
    --bs-btn-disabled-color: #5c636a;
}

.ps-install .btn-outline-primary {
    --bs-btn-color: #0a58ca;
    --bs-btn-border-color: #0a58ca;
    --bs-btn-disabled-color: #0a58ca;
}

/* The attribute sits on <html>, the class on <body> — hence the descendant. */
[data-bs-theme="dark"] .ps-install .btn-outline-secondary {
    --bs-btn-color: #adb5bd;
    --bs-btn-border-color: #adb5bd;
    --bs-btn-disabled-color: #adb5bd;
}

[data-bs-theme="dark"] .ps-install .btn-outline-primary {
    --bs-btn-color: #6ea8fe;
    --bs-btn-border-color: #6ea8fe;
    --bs-btn-disabled-color: #6ea8fe;
}

/*
 * The label of a rejected acknowledgement checkbox inside a warning alert.
 *
 * Three steps ship this construction — the database, the administrator and the
 * mail step all put their "mir ist bewusst …" checkbox into the
 * `alert-warning` that explains the unencrypted connection. Bootstrap paints
 * the label of an `.is-invalid` check with `--bs-form-invalid-color`, which is
 * the FILL red `#dc3545`; on the alert's `#fff3cd` that measures 4.08:1 where
 * 4.5:1 is required. Measured with axe-core 4.10 against the rendered pages at
 * 1280 and 375 px: one serious `color-contrast` violation per affected page in
 * light mode, none in dark (there the token already resolves to `#ea868f`).
 *
 * It only appears in the state "acknowledgement missing and complained about",
 * which is exactly the state in which the sentence has to be readable.
 *
 * `--bs-danger-text-emphasis` is Bootstrap's own text-on-subtle-background red
 * (`#58151c` light, `#ea868f` dark) — 12.3:1 on the warning alert in light
 * mode, 5.8:1 in dark. One rule for all three steps rather than three template
 * edits: the construction is identical, and a fix applied per template is a fix
 * the fourth step will not inherit. The selector is deliberately more specific
 * than Bootstrap's (five classes against three), because a utility class on the
 * label would lose to it.
 */
.ps-install .alert .form-check-input.is-invalid ~ .form-check-label {
    color: var(--bs-danger-text-emphasis);
}

/* ------------------------------------------------------ focus visibility -- */

/* Bootstrap's own focus ring is kept; this only guarantees that elements the
   wizard styles itself (the step links, the details summaries) keep a visible
   one when the theme changes. */
.ps-install a:focus-visible,
.ps-install summary:focus-visible,
.ps-install button:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
    border-radius: 0.2rem;
}

/* ------------------------------------------------------------ responsive -- */

@media (max-width: 575.98px) {
    .ps-install__shell {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }

    .ps-install__card > .card-body {
        padding: 1.1rem;
    }

    .ps-install__lead {
        gap: 0.75rem;
    }

    .ps-install__lead-icon {
        width: 2.25rem;
        height: 2.25rem;
        font-size: 1rem;
    }

    /* Full-width buttons stacked in reading order: at 375 px two buttons side
       by side leave neither of them a readable label. */
    .ps-install__actions {
        justify-content: stretch;
    }

    .ps-install__actions > .btn {
        width: 100%;
    }

    .ps-install__note {
        text-align: left;
    }

    .ps-install__steps {
        gap: 0.3rem 0.75rem;
    }

    .ps-install__step {
        font-size: 0.78rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ps-install * {
        transition: none !important;
    }
}

/* ------------------------------------------------------ bootstrap failure -- */

/*
 * The two pages index.php can produce BEFORE anything else exists: "PHP too
 * old" and "vendor/ missing". They load this file and nothing else — no
 * Bootstrap, no icon font — because at that point the product may not be
 * unpacked completely. Every declaration below is therefore self-contained and
 * must not reference a --bs-* variable.
 *
 * `prefers-color-scheme` instead of the localStorage mechanism: those pages
 * carry no script at all, which is the right call for a page whose whole
 * message is "this server cannot run our code".
 */
.ps-install-bare {
    margin: 0;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background-color: #f5f7fb;
    color: #212529;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    line-height: 1.6;
}

.ps-install-bare__box {
    max-width: 34rem;
    padding: 1.75rem;
    border: 1px solid #dee2e6;
    border-radius: 0.75rem;
    background-color: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.ps-install-bare__box h1 {
    margin: 0 0 0.75rem;
    font-size: 1.35rem;
}

.ps-install-bare__box p {
    margin: 0;
}

@media (prefers-color-scheme: dark) {
    .ps-install-bare {
        background-color: #16181c;
        color: #dee2e6;
    }

    .ps-install-bare__box {
        background-color: #212529;
        border-color: #495057;
    }
}
