/*
    House palette, taken from iq2-development.de — the site declares these as
    custom properties, so these are its own tokens rather than an approximation.
*/
:root {
    --iq-primary: #76ab22;
    --iq-headlines: #8ccb29;
    --iq-primary-hover: #64911d;
    --iq-dark: #222222;
    /* Not from the site — Bootstrap's danger red, so the error bar matches the
       text-danger the app already uses to mean "failed". */
    --iq-danger: #dc3545;
}

/*
    The bar every page title sits in: white on the brand green. Controls that
    belong to the page as a whole (a port selector, a Clear button) go in it
    beside the title, which is why it is a flex row rather than a coloured h1.
*/
.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 1rem;
    padding: 0.5rem 1rem;
    border-radius: 0.375rem;
    background: var(--iq-primary);
    color: #fff;
}

.page-header h1 {
    margin-bottom: 0;
}

/* text-muted is grey on grey here; the subtitles need to lift off the green. */
.page-header .text-muted {
    color: rgba(255, 255, 255, 0.85) !important;
}

/* The error page keeps the bar's shape so the layout matches every other page,
   but not its colour: the red is what says "something failed". */
.page-header--error {
    background: var(--iq-danger);
}

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/*
    Editors for device data — the parameter tree on /iodd and the process-data
    output fields on /process-data.

    Bootstrap borders both in #dee2e6, the same colour as a table's own rules, so
    a control reads as another cell rather than as something you can change. The
    dropdown's chevron moves into a brand-green well, which makes a writable row
    findable by colour alone in a tree that can run to sixty rows.

    These are opt-in by class, not by element: page chrome that happens to be a
    select — the Language and Role pickers, a port number — keeps Bootstrap's
    defaults. They live here rather than in a scoped stylesheet because two
    components now render the same editors and a third would want them too.
*/

.param-select {
    /* Room for the well, which is wider than Bootstrap's bare chevron needs. */
    padding-right: 2.25rem;

    border: 1px solid #6c757d;

    /* Two layers: the chevron over a solid block of brand green. The chevron is
       a data URI and cannot read a custom property, so it is drawn white to sit
       on the green; the block itself uses the token, so changing --iq-primary
       still changes this. */
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E"),
        linear-gradient(var(--iq-primary), var(--iq-primary));
    background-position: right 0.625rem center, right center;
    background-size: 0.75rem, 1.875rem 100%;
    background-repeat: no-repeat, no-repeat;
}

.param-select:focus {
    border-color: var(--iq-primary-hover);
    /* Bootstrap's focus ring is blue; this is #76ab22 at the same opacity. The
       literal is unavoidable — rgba() cannot take a hex custom property. */
    box-shadow: 0 0 0 0.25rem rgba(118, 171, 34, 0.3);
}

/*
    Value text boxes, given the same border and focus as the dropdowns. There is
    no well to add — a text box has no caret — so the border carries the contrast
    on its own.
*/
.param-input {
    border: 1px solid #6c757d;
}

.param-input:focus {
    border-color: var(--iq-primary-hover);
    box-shadow: 0 0 0 0.25rem rgba(118, 171, 34, 0.3);
}

.param-input:disabled {
    border-color: #adb5bd;
}

/* Disabled rows are grey everywhere else on the page; a green well would claim
   the control is live while it is not. */
.param-select:disabled {
    border-color: #adb5bd;
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%236c757d' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E"),
        linear-gradient(#e9ecef, #e9ecef);
}

/*
    A checkbox is the one editor Bootstrap draws as a shape rather than a box of
    text, and at 1em with a #dee2e6 outline on a white card it is close to
    invisible. Same border as the rest, and the checked state uses the brand
    green instead of Bootstrap's blue so it agrees with the dropdowns beside it.
*/
.param-check {
    border: 1px solid #6c757d;
}

.param-check:checked {
    background-color: var(--iq-primary);
    border-color: var(--iq-primary);
}

.param-check:focus {
    border-color: var(--iq-primary-hover);
    box-shadow: 0 0 0 0.25rem rgba(118, 171, 34, 0.3);
}

.param-check:disabled {
    border-color: #adb5bd;
}

/*
    A polled value that came back different from the read before it. Process data
    updates once a second with no other signal that anything moved, so the change
    itself is what needs marking — the value is already on screen.

    Brand green at low alpha, fading to nothing over the second before the next
    read. The page applies this through a key that changes with the value: an
    animation runs when its element is created and never again, so re-applying
    the class alone would flash once and then go quiet.
*/
@keyframes iq-value-changed {
    from { background-color: rgba(118, 171, 34, 0.55); }
    to   { background-color: transparent; }
}

.value-changed {
    animation: iq-value-changed 1s ease-out;
}
/*
    The validation table. A run is a hundred rows long, so an unselected row is
    one line of the height a line needs and no more. Selecting a row is what
    opens it: the full account of what it did, its members and its parts, all
    tinted as one block so the parameter reads as a unit rather than as a parent
    and some loose lines below it.

    Every row is selectable, so the pointer is on the row, not on the chevron.
*/
.validation-table {
    table-layout: fixed;
}

.validation-table tbody tr {
    cursor: pointer;
}

/* The open row's account of its checks: read, not clicked. */
.validation-table tbody tr.validation-detail {
    cursor: default;
}

.validation-table td {
    padding-top: 0.15rem;
    padding-bottom: 0.15rem;
}

/*
    One line means one line: an unselected row clips rather than wraps, whatever
    it holds. The selected row and its account below are the only ones allowed to
    grow, and the full title of a clipped row is on its tooltip and in the
    Parameter column.
*/
.validation-table tbody tr:not(.validation-selected):not(.validation-detail) > td {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Keeps titles aligned whether or not the row has a chevron. */
.validation-chevron {
    display: inline-block;
    width: 1rem;
    color: #6c757d;
}

.validation-child {
    padding-left: 2.25rem !important;
}

.validation-open > td {
    background-color: rgba(118, 171, 34, 0.07);
}

.validation-selected > td {
    background-color: rgba(118, 171, 34, 0.16);
}
