/* INPUT GROUP */
.tt-input-group {
    display: flex;
    flex-wrap: nowrap;
    align-items: stretch;
    width: 100%;
    color: var(--paragraph-color);
}
.tt-input-group input[type="text"],
.tt-input-group input[type="password"],
.tt-input-group input[type="search"]:where(:not(.choices__input)),
.tt-input-group select,
.tt-input-group button,
.tt-input-group .tt-btn,
.tt-input-group .tt-btn-sm,
.tt-input-group .tt-btn-md,
.tt-input-group .tt-btn-lg {
    flex: 1;
    border-radius: 0;
    margin-left: 0;
    margin-right: 0;
}

    /* Radius on children */
    .tt-form .tt-input-group .tt-btn,
    .tt-input-group .tt-btn,
    .tt-form .tt-input-group input[type="file"] {
        border-radius: 0;
    }
    .tt-form .tt-input-group > *:first-child,
    .tt-form .tt-input-group > input[type="file"]:first-child,
    .tt-input-group > :is(*, input[type="text"], input[type="password"], input[type="search"], select):first-child {
        border-top-left-radius: var(--input-border-radius);
        border-bottom-left-radius: var(--input-border-radius);
    }
    .tt-form .tt-input-group > *:last-child,
    .tt-input-group > :is(*, input[type="text"], input[type="password"], input[type="search"], select):last-child {
        border-top-right-radius: var(--input-border-radius);
        border-bottom-right-radius: var(--input-border-radius);
    }
    /* pass right radius through to buttons inside a wrapper div (e.g. reveal-element targets) */
    .tt-input-group > div:last-child > :is(.tt-btn, input[type="button"], input[type="submit"]),
    .tt-form .tt-input-group > div:last-child > :is(.tt-btn, input[type="button"], input[type="submit"]) {
        border-top-right-radius: var(--input-border-radius);
        border-bottom-right-radius: var(--input-border-radius);
    }
    /* when the last-child wrapper div is hidden, round the right side of the visible input/select */
    .tt-input-group:has(> div:last-child[style*="display: none"]) > select,
    .tt-input-group:has(> div:last-child[style*="display: none"]) .choices__inner {
        border-top-right-radius: var(--input-border-radius);
        border-bottom-right-radius: var(--input-border-radius);
    }

    /* A hidden input carries a value, not a slot. It draws nothing, but it is still
       a child, so a group that leads with one hands the group's left edge — the
       radius below, the border further down — to the hidden input instead of to the
       first control anyone can see, and a trailing one takes the right edge the same
       way. Both rules read "the neighbour of a hidden input at the edge IS the edge". */
    .tt-input-group > input[type="hidden"]:first-child + * {
        border-top-left-radius: var(--input-border-radius);
        border-bottom-left-radius: var(--input-border-radius);
    }
    .tt-input-group > *:has(+ input[type="hidden"]:last-child) {
        border-top-right-radius: var(--input-border-radius);
        border-bottom-right-radius: var(--input-border-radius);
    }

    /* Border left 0 on children: a seam between two controls is one line, not two.
       The control after a leading hidden input has nothing to its left to share a
       line with, so it is excluded and keeps the border of its own left edge. */
    .tt-input-group > :is(
        input[type="text"]:not(:first-child),
        input[type="date"]:not(:first-child),
        input[type="checkbox"]:not(:first-child),
        input[type="search"]:not(:first-child),
        .prefix-icon:not(:first-child),
        * + *
    ):not(input[type="hidden"]:first-child + *),
    .tt-form .tt-input-group > * + *:not(input[type="hidden"]:first-child + *) {
        border-left: 0;
    }

    .tt-input-group > * {
        min-height: var(--form-input-height);
    }

/* Input / select styling — works inside and outside .tt-form.
   input[type="search"] skips the inputs Choices.js owns; :where() keeps the guard at
   zero specificity. Same reasoning as the head of form-inputs.css — without it the
   Choices search box renders as a full-height bordered field inside .choices__inner. */
.tt-input-group :is(input[type="text"], input[type="password"], input[type="number"],
                    input[type="date"], input[type="time"], input[type="email"],
                    input[type="tel"], input[type="search"]:where(:not(.choices__input)),
                    select) {
    /* A floor, not a height. A group is align-items: stretch, so every child is meant
       to end up as tall as the tallest one; a fixed height opts out of that and leaves
       a hole at the seam the moment a sibling grows (a Choices multi-select wrapping
       its chips is the only control here that can). height: auto is needed to beat the
       same-weight height in form-inputs.css when the group is inside a .tt-form. */
    height: auto;
    min-height: var(--form-input-height);
    /* Block padding would be measured on top of the line box, and at --sm that put the
       control a pixel over the floor it is supposed to sit on. A single-line control
       centres its own text in whatever box it gets, so it does not need the padding to
       look centred — same bargain as the addons and .tt-sensitive-dots below. */
    padding: var(--form-input-padding);
    padding-block: 0;
    font-size: var(--form-input-font-size);
    background-color: var(--bg-color);
    border: var(--border-thin) solid currentColor;
    color: inherit;
    box-sizing: border-box;
}

/* FOCUS */
.tt-input-group :is(input, select, textarea):focus {
    outline: var(--border-md) solid var(--primary-color);
    outline-offset: calc(var(--border-md) * -1);
    border-color: var(--primary-color);
}

.tt-input-group input::placeholder {
    color: var(--text-muted);
    opacity: 1;
}

/* dropdown wrapper — behaves as a single flex cell */
.tt-input-group > .dropdown {
    display: flex;
    align-items: stretch;
}

/* trigger button fills the wrapper in both axes */
.tt-input-group > .dropdown > button,
.tt-input-group > .dropdown > .tt-btn {
    flex: 1;
    margin: 0;
    border-radius: 0;
    align-self: stretch;
    min-height: var(--form-input-height);
}

/* strip left border from button when dropdown is not the first group item */
.tt-input-group > * + .dropdown > button,
.tt-input-group > * + .dropdown > .tt-btn,
.tt-form .tt-input-group > * + .dropdown > button,
.tt-form .tt-input-group > * + .dropdown > .tt-btn {
    border-left: 0;
}

/* rounded corners pass through to the trigger button */
.tt-input-group > .dropdown:first-child > button,
.tt-input-group > .dropdown:first-child > .tt-btn,
.tt-form .tt-input-group > .dropdown:first-child > button,
.tt-form .tt-input-group > .dropdown:first-child > .tt-btn {
    border-top-left-radius: var(--input-border-radius);
    border-bottom-left-radius: var(--input-border-radius);
}

.tt-input-group > .dropdown:last-child > button,
.tt-input-group > .dropdown:last-child > .tt-btn,
.tt-form .tt-input-group > .dropdown:last-child > button,
.tt-form .tt-input-group > .dropdown:last-child > .tt-btn {
    border-top-right-radius: var(--input-border-radius);
    border-bottom-right-radius: var(--input-border-radius);
}

/* SEGMENT — a part of a group that comes and goes as a unit, e.g. a field and the
   prefix box that names it. The group needs it to behave as one cell, so it is a
   flex box of its own, and the seams and outer corners the group would have given
   its children pass through to the children of the segment instead. Same bargain
   as the .dropdown wrapper above. */
.tt-input-group > .tt-input-group__segment {
    display: flex;
    align-items: stretch;
    flex: 1;
    min-width: 0;
}

/* Seams: between the segment's own children, and where a segment meets the
   sibling before it. A segment whose predecessor is hidden has nothing to its
   left to share a line with, so it keeps the border of its own left edge - same
   reasoning as the hidden-input rules further up. */
.tt-input-group > .tt-input-group__segment > * + *,
.tt-input-group > *:not([style*="display: none"]) + .tt-input-group__segment > *:first-child,
.tt-form .tt-input-group > .tt-input-group__segment > * + *,
.tt-form .tt-input-group > *:not([style*="display: none"]) + .tt-input-group__segment > *:first-child {
    border-left: 0;
}

.tt-input-group > .tt-input-group__segment:first-child > *:first-child,
.tt-input-group > [style*="display: none"]:first-child + .tt-input-group__segment > *:first-child {
    border-top-left-radius: var(--input-border-radius);
    border-bottom-left-radius: var(--input-border-radius);
}

.tt-input-group > .tt-input-group__segment:last-child > *:last-child {
    border-top-right-radius: var(--input-border-radius);
    border-bottom-right-radius: var(--input-border-radius);
}

/* choices */
.tt-input-group .choices {
    flex: 1 1 auto;
}

.prefix-icon,
.addon-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--prefix-icon);
    border: var(--border-thin) solid var(--paragraph-color);
    color: var(--bg-color);
    --form-addon-icon-size: calc(var(--form-input-height) * 0.42);
    /* min-height, so the addon tracks the group and not the size token — see the note
       on the group's controls above. The zero block padding and line-height: 1 below
       are what make that safe: the glyph can no longer push the box past the floor,
       which is why this was a fixed height before. */
    min-height: var(--form-input-height);
    min-width: var(--form-input-height);
    padding-block: 0;
    padding-inline: calc(var(--form-input-height) * 0.2);
    line-height: 1;
    font-size: var(--form-input-font-size);
}

/* A prefix box may be the field's own <label> rather than a decorative span with a
   visually hidden label behind it - the box then IS the accessible name, and there
   is only one copy of the word to keep right. The LABEL rules in form-layout.css
   assume a label stacked above its field, so inside a group they hand the box back
   to .prefix-icon: full width would eat the row, and the label colour and size are
   the ones for text on the page rather than text on the addon's own background. */
.tt-input-group label.prefix-icon,
.tt-form .tt-input-group label.prefix-icon {
    width: auto;
    max-width: none;
    font-size: var(--form-input-font-size);
    line-height: 1;
    color: var(--bg-color);
}

/* form_label() marks a required field with a star after the text. That is sized
   for a label standing over its field; in a prefix box it is a red mark on a dark
   ground crowding a one-word label, and the control still carries its own
   required state for anyone who needs it. */
.tt-input-group label.prefix-icon span {
    display: none;
}

/* svg, not just .tt-icon: some addons render <twig:ux:icon> directly, without the
   default class. The em margin .tt-icon carries is dead weight here — the flex box
   already centres the glyph. */
.prefix-icon svg,
.addon-toggle svg {
    width: var(--form-addon-icon-size);
    height: var(--form-addon-icon-size);
    margin: 0;
}
.addon-toggle.off {
    background-color: var(--bg-muted);
    color: var(--paragraph-color);
}

.addon-toggle.on {
    background-color: var(--primary-color);
    color: var(--bg-color);
}

/* Visually masks a text input's value without switching it to type="password",
   which would trigger the browser's saved-password autofill suggestions. */
.tt-text-masked {
    -webkit-text-security: disc;
    text-security: disc;
}

.tt-sensitive-dots {
    flex: 1;
    display: inline-flex;
    align-items: center;
    padding-block: 0;
    padding-inline: var(--form-input-padding);
    line-height: 1;
    min-height: var(--form-input-height);
    background-color: var(--bg-color);
    border: var(--border-thin) solid currentColor;
    color: inherit;
    font-size: var(--form-input-font-size);
    box-sizing: border-box;
    user-select: none;
}

.tt-input-group input[type="submit"],
.tt-input-group .tt-btn {
    /* height: auto beats .tt-form .tt-btn in form-layout.css — equal weight, and this
       file loads later — so a button at the end of a group follows it the same way.
       padding-block after the shorthand keeps the button's inline padding but drops the
       vertical half: on min-height alone the md/lg block padding pushed the button — and
       with it the whole group — past --form-input-height. Same bargain as the addons:
       the group decides the height, the control only asks for the floor. */
    height: auto;
    min-height: var(--form-input-height);
    padding: var(--form-button-padding);
    padding-block: 0;
    line-height: 1;
    font-size: var(--form-input-font-size);
    width: fit-content;
    flex: 0 0 auto;
    margin: 0;
}
.tt-input-group input[type="submit"]:disabled,
.tt-input-group input[type="password"] {
    border-left: 0;
    border-color: currentColor;
}

.tt-form .tt-input-group button {
    border-color: var(--paragraph-color);
}

.tt-form .tt-input-group button:hover {
    border-color: var(--paragraph-color);
}

.tt.input-group .tt-width-fit-content,
.tt-input-group select.tt-width-fit-content {
    width: fit-content;
    flex: 0 0 auto;
}

/* For mixing tt form and bootstrap input group */
.tt-form .input-group input {
    flex: 1;
}

/* FILTERS */
.tt-filter-menu {
    /*min-width: 260px;*/
    padding: var(--step--2);
    background-color: var(--bg-color);
    color: var(--paragraph-color);
    border-color: var(--border-muted);
}

.tt-filter-group + .tt-filter-group {
    margin-top: var(--step--4);
    padding-top: var(--step--4);
    border-top: var(--border-thin) solid var(--border-muted);
}

.tt-filter-title {
    font-size: var(--step--2);
    color: var(--heading-color);
    font-weight: var(--font-weight-semibold);
    margin-bottom: var(--step--4);
    opacity: 0.75;
}

.tt-filter-option {
    display: flex;
    align-items: center;
    gap: var(--step--4);
    padding: var(--step--4) 0;
    cursor: pointer;
}

.tt-filter-option input {
    /*margin: 0;*/
}

.tt-filter-actions {
    display: flex;
    justify-content: space-between;
    margin-top: var(--step--2);
}

.tt-form .tt-input-group .tt-filter-actions .tt-btn,
.tt-filter-actions .tt-btn {
    flex: initial;
    border-radius: var(--button-radius-sm);
    border-color: transparent;
    height: auto;
    min-height: 0;
    padding: var(--button-padding-sm);
    font-size: var(--button-font-size-sm);
    margin: var(--button-margin-sm);
}

/* The export row: the three narrowing selects, and the option grid under them.

   It is the only action helper that wraps its input group in an element of its
   own, and the helpers are revealed by setting the row to display:flex — so
   without this it lays out as a flex item and shrinks to the width of the
   selects, however wide the row it sits in. It fills the row instead. */
.tt-report-export {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
}

/* Star toggle — swaps between outline and filled on aria-pressed. Shared by the
   report download menus and the ad-hoc salary report selector. */
.tt-star-toggle .tt-star-on,
.tt-star-toggle .tt-star-off,
.tt-star-toggle .tt-icon {
    /* The glyph is the button's whole content — never let the flex box squeeze it
       to nothing when the surrounding menu is narrow. */
    flex: 0 0 auto;
}
.tt-star-toggle .tt-icon {
    width: 0.9em;
    height: 0.9em;
    margin: 0;
}
.tt-star-toggle[aria-pressed="true"] {
    color: var(--accent-color);
}
.tt-star-on,
.tt-star-toggle[aria-pressed="true"] .tt-star-off {
    display: none;
}
.tt-star-toggle[aria-pressed="true"] .tt-star-on {
    display: inline-flex;
}
