/*
 | portalworks brand tokens, and the Bootstrap overrides built on them.
 |
 | Every brand constant here (the blue, the font) was read out of the live
 | portalworks.de site so this application looks like it belongs to the same
 | company rather than approximating it. If the brand changes there, it changes
 | here — in one file.
 |
 | Loaded AFTER vendor/bootstrap/bootstrap.min.css. Bootstrap 5.3 exposes its own
 | palette and typography as CSS custom properties, so it is themed by
 | redeclaring those variables — no Sass, no build step. See ADR 13.
 |
 | TWO KINDS OF TOKEN, and the distinction matters:
 |
 |   Brand constants   blue, gradients, radii, fonts. Identical in both themes.
 |                     These are the company, not the interface.
 |   Semantic tokens   surface, text, line, state. Defined once per theme.
 |
 | A screen only ever uses a semantic token. Reaching for a brand constant to
 | paint a surface is how a theme ends up half broken — see ADR 14.
 */

/* ===================================================================== brand */

:root {
    /* --- brand constants, verbatim from portalworks.de --- */
    --sn-blue: #0b5fff;
    --sn-blue-deep: #0090c0;
    --sn-blue-bright: #33c5f5;

    --sn-gradient: linear-gradient(90deg, var(--sn-blue-bright) 0%, var(--sn-blue) 100%);
    --sn-gradient-deep: linear-gradient(90deg, var(--sn-blue-deep) 0%, var(--sn-blue) 100%);
    --sn-btn-gradient: linear-gradient(to right, #0b5fff 0%, #0090c0 51%, #0b5fff 100%);

    --sn-radius: 20px;
    --sn-radius-sm: 10px;
    --sn-radius-pill: 50px;

    /* One height for everything that sits on a field row: text input, select, and
       the button that submits them. Bootstrap sizes each of those from its own
       padding, so a row of three arrives as three heights — which is exactly what
       the /sites filter looked like. A single value is the only way the row stays
       aligned as fields are added. */
    --sn-field-h: 3.05rem;

    --sn-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --sn-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

    /* Always white, because it always sits on the blue gradient. */
    --sn-on-blue: #ffffff;
}

/* ============================================================= light theme */
/* The default, and the brand's own surface: white body, #3D3D3D headings. */

:root {
    color-scheme: light;

    --sn-bg: #ffffff;
    --sn-panel: #ffffff;
    --sn-panel-2: #f7f8f9;

    --sn-line: #e4e6ea;
    --sn-line-soft: #e9eaef;

    --sn-title: #3d3d3d;
    --sn-text: #666e7a;
    --sn-muted: #8b93a0;
    --sn-faint: #9aa2ae;
    --sn-ghost: #c3c8d1;

    /* Blue as a readable foreground, and as a tint behind content. */
    --sn-blue-fg: #0951d9;
    --sn-blue-tint: #f0f5ff;
    --sn-blue-tint-line: #bbd2ff;

    --sn-shadow: 0 4px 114px 0 rgba(0, 0, 0, 0.09);
    --sn-shadow-sm: 0 2px 18px 0 rgba(37, 37, 37, 0.06);
    --sn-focus-ring: rgba(11, 95, 255, 0.16);

    /* Status colours sit outside the brand palette on purpose: blue already
       means "portalworks", so it cannot be the only signal for "healthy" either. */
    --sn-ok: #287d3c;
    --sn-warn: #b95000;
    --sn-crit: #da1414;

    --sn-ok-tint: #f2f7f3;
    --sn-ok-line: #bad5c1;
    --sn-warn-tint: #fbf4f0;
    --sn-warn-line: #e9c7ad;
    --sn-crit-tint: #fdf1f1;
    --sn-crit-line: #f3b4b4;
    --sn-crit-fg: #b31010;
    --sn-ok-fg: #216631;
}

/* ============================================================== dark theme */
/* Not an inversion. Surfaces are a cool near-black with a slight blue bias so
   the brand blue sits on them instead of vibrating against them, and the blue
   is lifted for foreground use where #0B5FFF would be too dim on dark. */

@media (prefers-color-scheme: dark) {
    /* Follows the browser — unless the reader has chosen light explicitly. */
    :root:not([data-theme="light"]) {
        color-scheme: dark;

        --sn-bg: #0b0f17;
        --sn-panel: #121826;
        --sn-panel-2: #182030;

        --sn-line: #232c3d;
        --sn-line-soft: #1c2433;

        --sn-title: #eef1f5;
        --sn-text: #a8b0bc;
        --sn-muted: #8991a0;
        --sn-faint: #77808f;
        --sn-ghost: #4d5566;

        --sn-blue-fg: #6097ff;
        --sn-blue-tint: #0d1526;
        --sn-blue-tint-line: #1f3a70;

        --sn-shadow: 0 4px 114px 0 rgba(0, 0, 0, 0.55);
        --sn-shadow-sm: 0 2px 18px 0 rgba(0, 0, 0, 0.35);
        --sn-focus-ring: rgba(11, 95, 255, 0.28);

        --sn-ok: #9ec4a7;
        --sn-warn: #d89f73;
        --sn-crit: #e76666;

        --sn-ok-tint: #0d100d;
        --sn-ok-line: #2c372f;
        --sn-warn-tint: #110d09;
        --sn-warn-line: #3c2d20;
        --sn-crit-tint: #120808;
        --sn-crit-line: #411d1d;
        --sn-crit-fg: #ef9c9c;
        --sn-ok-fg: #c0d9c6;
    }
}

/* Chosen by hand. Must beat the media query in both directions, which is why
   these come after it and why the query excludes an explicit light choice. */
:root[data-theme="dark"] {
    color-scheme: dark;

    --sn-bg: #0b0f17;
    --sn-panel: #121826;
    --sn-panel-2: #182030;

    --sn-line: #232c3d;
    --sn-line-soft: #1c2433;

    --sn-title: #eef1f5;
    --sn-text: #a8b0bc;
    --sn-muted: #8991a0;
    --sn-faint: #77808f;
    --sn-ghost: #4d5566;

    --sn-blue-fg: #6097ff;
    --sn-blue-tint: #0d1526;
    --sn-blue-tint-line: #1f3a70;

    --sn-shadow: 0 4px 114px 0 rgba(0, 0, 0, 0.55);
    --sn-shadow-sm: 0 2px 18px 0 rgba(0, 0, 0, 0.35);
    --sn-focus-ring: rgba(11, 95, 255, 0.28);

    --sn-ok: #9ec4a7;
    --sn-warn: #d89f73;
    --sn-crit: #e76666;

    --sn-ok-tint: #0d100d;
    --sn-ok-line: #2c372f;
    --sn-warn-tint: #110d09;
    --sn-warn-line: #3c2d20;
    --sn-crit-tint: #120808;
    --sn-crit-line: #411d1d;
    --sn-crit-fg: #ef9c9c;
    --sn-ok-fg: #c0d9c6;
}

/* ======================================================= Bootstrap retuning */
/* Every value points at a semantic token, so Bootstrap follows the theme with
   no second definition to keep in sync. */

:root {
    --bs-primary: var(--sn-blue);
    --bs-primary-rgb: 11, 95, 255;
    --bs-primary-text-emphasis: var(--sn-blue-fg);
    --bs-primary-bg-subtle: var(--sn-blue-tint);
    --bs-primary-border-subtle: var(--sn-blue-tint-line);

    --bs-body-font-family: var(--sn-font);
    --bs-body-font-size: 0.95rem;
    --bs-body-font-weight: 400;
    --bs-body-line-height: 1.6;
    --bs-body-color: var(--sn-text);
    --bs-body-bg: var(--sn-bg);

    --bs-emphasis-color: var(--sn-title);
    --bs-secondary-color: var(--sn-muted);
    --bs-secondary-bg: var(--sn-panel-2);
    --bs-tertiary-bg: var(--sn-panel-2);

    --bs-border-color: var(--sn-line);
    --bs-border-radius: var(--sn-radius-sm);
    --bs-border-radius-sm: 8px;
    --bs-border-radius-lg: var(--sn-radius);
    --bs-border-radius-pill: var(--sn-radius-pill);

    --bs-link-color: var(--sn-blue-fg);
    --bs-link-hover-color: var(--sn-blue);

    --bs-heading-color: var(--sn-title);
    --bs-dropdown-link-hover-bg: var(--sn-panel-2);
    --bs-box-shadow: var(--sn-shadow);
}

/* ---------------------------------------------------------------- typography */

body {
    background-color: var(--sn-bg);
    color: var(--sn-text);
    font-family: var(--sn-font);
    font-feature-settings: 'kern' 1;
    -webkit-font-smoothing: antialiased;
}

h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 {
    color: var(--sn-title);
    font-weight: 700;
    letter-spacing: -0.015em;
}

h1, .h1 {
    font-size: clamp(1.6rem, 3.4vw, 2.1rem);
    line-height: 1.15;
}

h2, .h2 {
    font-size: clamp(1.25rem, 2.4vw, 1.5rem);
    line-height: 1.2;
}

.sn-eyebrow {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--sn-text);
}

.sn-mono {
    font-family: var(--sn-mono);
    font-size: 0.82em;
}

.sn-num {
    font-variant-numeric: tabular-nums;
}

.sn-gradient-text {
    background: var(--sn-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* --------------------------------------------------------------------- logo */

.sn-logo {
    display: block;
    width: auto;
    height: 30px;
}

.sn-logo-sm {
    height: 24px;
}

/* The wordmark is #252525, unreadable on a dark surface. The light variant is a
   separate file, swapped by CSS so no template has to know about themes. */
.sn-logo-dark {
    display: none;
}

:root[data-theme="dark"] .sn-logo-light {
    display: none;
}

:root[data-theme="dark"] .sn-logo-dark {
    display: block;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .sn-logo-light {
        display: none;
    }

    :root:not([data-theme="light"]) .sn-logo-dark {
        display: block;
    }
}

/* --------------------------------------------------------------- buttons */
/* Pill shape, 200% gradient that slides on hover — copied from the theme's
   .btn / .btn-primary so a button here behaves like a button there. */

.btn {
    --bs-btn-padding-y: 0.85rem;
    --bs-btn-padding-x: 1.9rem;
    --bs-btn-font-size: 0.875rem;
    --bs-btn-font-weight: 500;
    --bs-btn-line-height: 1.2;
    --bs-btn-border-radius: var(--sn-radius-pill);
    transition: background-position 0.3s ease, color 0.2s ease, border-color 0.2s ease;
}

.btn-primary {
    --bs-btn-color: var(--sn-on-blue);
    --bs-btn-hover-color: var(--sn-on-blue);
    --bs-btn-active-color: var(--sn-on-blue);
    --bs-btn-border-color: transparent;
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-border-color: transparent;
    --bs-btn-bg: transparent;
    --bs-btn-hover-bg: transparent;
    --bs-btn-active-bg: transparent;
    background-image: var(--sn-btn-gradient);
    background-size: 200% auto;
    background-position: right center;
    border: 0;
}

.btn-primary:hover,
.btn-primary:focus-visible {
    background-position: left center;
}

.btn-outline-secondary {
    --bs-btn-color: var(--sn-text);
    --bs-btn-border-color: var(--sn-line);
    --bs-btn-bg: transparent;
    --bs-btn-hover-color: var(--sn-title);
    --bs-btn-hover-bg: var(--sn-panel-2);
    --bs-btn-hover-border-color: var(--sn-blue);
    --bs-btn-active-color: var(--sn-title);
    --bs-btn-active-bg: var(--sn-panel-2);
    --bs-btn-active-border-color: var(--sn-blue);
}

.btn-sm {
    --bs-btn-padding-y: 0.5rem;
    --bs-btn-padding-x: 1.1rem;
    --bs-btn-font-size: 0.8rem;
}

.btn:focus-visible {
    outline: 2px solid var(--sn-blue);
    outline-offset: 2px;
    box-shadow: none;
}

/* --------------------------------------------------------------- severity marks */

/*
 * Version distance, shown as a mark rather than only a colour.
 *
 * Status colour is not brand colour: blue already means portalworks, so it cannot be the
 * only signal for "healthy" either. Every one of these carries a word — "Major behind" — as well
 * as a tone, which is also what makes the screen readable to somebody who cannot
 * distinguish the two warm tones.
 *
 * Built entirely from semantic tokens, so both themes are covered by the definitions
 * above rather than by a second set of rules here.
 */
.sn-sev {
    display: inline-block;
    padding: 0.32rem 0.85rem;
    border-radius: var(--sn-radius-pill);
    border: 1px solid var(--sn-line);
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--sn-text);
}

.sn-sev-crit {
    border-color: var(--sn-crit-line);
    background: var(--sn-crit-tint);
    color: var(--sn-crit);
}

.sn-sev-warn {
    border-color: var(--sn-warn-line);
    background: var(--sn-warn-tint);
    color: var(--sn-warn);
}

.sn-sev-ok {
    border-color: var(--sn-ok-line);
    background: var(--sn-ok-tint);
    color: var(--sn-ok);
}

/* Unknown is not good news. It is drawn as its own state rather than as "fine". */
.sn-sev-ghost {
    border-style: dashed;
    color: var(--sn-muted);
}

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

.form-label {
    margin-bottom: 0.45rem;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--sn-title);
}

/* A select is a field, so it is styled with the fields. Only .form-control was,
   which left every <select> on Bootstrap's smaller default padding: on the /sites
   filter the input, the two selects and the button came out as four heights, and
   because the row is bottom-aligned the labels above them landed at three
   different heights too. */
.form-control,
.form-select {
    min-height: var(--sn-field-h);
    padding: 0.75rem 1rem;
    border-color: var(--sn-line);
    border-radius: var(--sn-radius-sm);
    font-size: 0.94rem;
    line-height: 1.5;
    color: var(--sn-title);
    background-color: var(--sn-panel);
    transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

/* Room for the chevron. Bootstrap draws it as a background image, so only the
   colour is overridden above — never background, which would remove it. */
.form-select {
    padding-right: 2.75rem;
}

.form-select:focus {
    border-color: var(--sn-blue);
    box-shadow: 0 0 0 3px var(--sn-focus-ring);
}

/* A button that submits a field row, sized to the row rather than to itself.
   Deliberately not a change to .btn: elsewhere — the sign-in screen, the inbox —
   a button is not standing next to a field and should keep its own proportions. */
.btn-field {
    --bs-btn-padding-y: 0.75rem;
    min-height: var(--sn-field-h);
}

.form-control::placeholder {
    color: var(--sn-faint);
}

.form-control:focus {
    background-color: var(--sn-panel);
    border-color: var(--sn-blue);
    box-shadow: 0 0 0 3px var(--sn-focus-ring);
    color: var(--sn-title);
}

.form-control.is-invalid {
    border-color: var(--sn-crit);
    background-image: none;
    padding-right: 1rem;
}

.form-control.is-invalid:focus {
    box-shadow: 0 0 0 3px var(--sn-crit-tint);
}

.form-text {
    font-size: 0.78rem;
    color: var(--sn-muted);
}

.invalid-feedback {
    font-size: 0.8rem;
    color: var(--sn-crit);
}

.form-check-input {
    background-color: var(--sn-panel);
    border-color: var(--sn-line);
}

.form-check-input:checked {
    background-color: var(--sn-blue);
    border-color: var(--sn-blue);
}

.form-check-input:focus {
    border-color: var(--sn-blue);
    box-shadow: 0 0 0 3px var(--sn-focus-ring);
}

.form-check-label {
    font-size: 0.88rem;
}

/* ------------------------------------------------------------------- alerts */

.alert {
    border: 1px solid transparent;
    border-radius: var(--sn-radius-sm);
    padding: 0.8rem 1rem;
    font-size: 0.88rem;
}

.alert-danger {
    background: var(--sn-crit-tint);
    border-color: var(--sn-crit-line);
    color: var(--sn-crit-fg);
}

.alert-success {
    background: var(--sn-blue-tint);
    border-color: var(--sn-blue-tint-line);
    color: var(--sn-ok-fg);
}

.alert ul {
    margin: 0;
    padding-left: 1.1rem;
}

/* -------------------------------------------------------------------- cards */

.sn-card {
    background: var(--sn-panel);
    border: 1px solid var(--sn-line);
    border-radius: var(--sn-radius);
    box-shadow: var(--sn-shadow-sm);
}

.sn-badge {
    display: inline-block;
    padding: 0.2rem 0.6rem;
    border-radius: var(--sn-radius-pill);
    border: 1px solid var(--sn-line);
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sn-text);
    white-space: nowrap;
}

.sn-badge-approved {
    border-color: var(--sn-ok-line);
    background: var(--sn-ok-tint);
    color: var(--sn-ok);
}

.sn-badge-rejected {
    border-color: var(--sn-crit-line);
    background: var(--sn-crit-tint);
    color: var(--sn-crit);
}

.sn-badge-pending {
    border-color: var(--sn-warn-line);
    background: var(--sn-warn-tint);
    color: var(--sn-warn);
}

/* ------------------------------------------------------- theme switch */
/* Three states, because "follow the browser" is a real answer and not the
   absence of one. Auto is the default and stays selectable. */

.theme-switch {
    display: inline-flex;
    padding: 2px;
    gap: 2px;
    background: var(--sn-panel-2);
    border: 1px solid var(--sn-line);
    border-radius: var(--sn-radius-pill);
}

.theme-switch button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: var(--sn-radius-pill);
    background: transparent;
    color: var(--sn-faint);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.theme-switch button:hover {
    color: var(--sn-title);
}

.theme-switch button[aria-checked="true"] {
    background: var(--sn-panel);
    color: var(--sn-blue-fg);
    box-shadow: var(--sn-shadow-sm);
}

.theme-switch button:focus-visible {
    outline: 2px solid var(--sn-blue);
    outline-offset: 1px;
}

.theme-switch svg {
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* On the blue panel the switch has to read against the gradient. */
.auth-aside .theme-switch {
    background: rgba(0, 0, 0, 0.16);
    border-color: rgba(255, 255, 255, 0.28);
}

.auth-aside .theme-switch button {
    color: rgba(255, 255, 255, 0.75);
}

.auth-aside .theme-switch button:hover {
    color: var(--sn-on-blue);
}

.auth-aside .theme-switch button[aria-checked="true"] {
    background: rgba(255, 255, 255, 0.92);
    color: var(--sn-blue-deep);
    box-shadow: none;
}

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

/* ---------------------------------------------------------------- pagination */
/* Laravel renders Bootstrap 5 markup (see AppServiceProvider). Retuned to the brand,
   because Bootstrap's default is its own blue and this application has one accent. */

.pagination {
    --bs-pagination-color: var(--sn-text);
    --bs-pagination-bg: var(--sn-panel);
    --bs-pagination-border-color: var(--sn-line);
    --bs-pagination-hover-color: var(--sn-title);
    --bs-pagination-hover-bg: var(--sn-panel-2);
    --bs-pagination-hover-border-color: var(--sn-blue);
    --bs-pagination-focus-color: var(--sn-title);
    --bs-pagination-focus-bg: var(--sn-panel-2);
    --bs-pagination-focus-box-shadow: 0 0 0 3px var(--sn-focus-ring);
    --bs-pagination-active-color: var(--sn-on-blue);
    --bs-pagination-active-bg: var(--sn-blue);
    --bs-pagination-active-border-color: var(--sn-blue);
    --bs-pagination-disabled-color: var(--sn-ghost);
    --bs-pagination-disabled-bg: var(--sn-panel);
    --bs-pagination-disabled-border-color: var(--sn-line);
    --bs-pagination-border-radius: var(--sn-radius-sm);
    --bs-pagination-font-size: 0.86rem;
    --bs-pagination-padding-y: 0.4rem;
    --bs-pagination-padding-x: 0.7rem;
    margin-bottom: 0;
    flex-wrap: wrap;
    gap: 4px;
}

/* Laravel's Bootstrap-5 view also emits a "Showing x to y of z" paragraph. Ours is
   already above the table, so the duplicate is hidden rather than restyled. */
.pagination-wrap p.small {
    display: none;
}
