/* The ATS's own CSS: layout only. Loaded after htw-style's htw.css and htw-bootstrap.css
   (vendored in static/htw, never edited here). Colours, fonts, radii and shadows come from
   htw-style; if a page needs one it lacks, add it to HTW-Infra/htw-style and re-sync.

   IP-356 -- desktop only, so the phone menu is exactly as IP-335 left it.
   The signed-in line: below 1400px it is the role badge alone, with the address in its
   tooltip; a firstname.lastname@ address alone was ~200px of a 1280px bar. Wider, a long
   address is cut short BEFORE the badge, never the badge, which is the part that answers
   "why can't I see X". If the tabs still do not fit, they wrap to a second row rather
   than run off the screen. */
@media (min-width: 992px) {
  .htw-nav .navbar-nav { flex-wrap: wrap; justify-content: flex-end; }
  .htw-nav #whoami { display: flex; align-items: center; min-width: 0; max-width: 20rem; }
  .htw-nav #whoami .who-email { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  .htw-nav #whoami .badge { flex-shrink: 0; }
}
@media (min-width: 992px) and (max-width: 1399.98px) {
  .htw-nav #whoami .who-email { display: none; }
}
main.container { max-width: 1400px; }  /* IP-676 -- was 1200px: list pages get the screen width */

/* IP-438 -- the recruitment agency badge: htw-style's chart violet (--chart-3), a colour no
   Bootstrap badge in the app uses, so "Agency" never reads as a flag, a stage or a referral.
   White on #6250D6 is 5.8:1. */
.badge-agency { background-color: var(--chart-3, #6250D6); color: #fff; }

/* IP-439 -- the "Internal" badge: htw-style's chart green (--chart-4), unused by any other badge,
   so "Internal" never reads as Agency (violet), a flag or a stage. Dark text: #111 on #1BAF7A is
   about 6.7:1, where white would be about 2.8:1. */
.badge-internal { background-color: var(--chart-4, #1BAF7A); color: #111; }

/* IP-408 -- the home tab's charts: inline SVG bars, a label and a total beside each. Series
   colours are htw-style 1.2.0's --chart-1..5 (IP-378); the fallbacks are the same values, for
   as long as the vendored copy is 1.1.0. The track is a translucent grey, so it reads on a light
   or a dark card. */
.dash-row { display: grid; grid-template-columns: minmax(0, 14rem) 1fr 3rem; gap: .5rem;
            align-items: center; margin-bottom: .35rem; }
.dash-label { font-size: .875rem; min-width: 0; }
.dash-bar { width: 100%; height: .9rem; display: block; border-radius: 2px;
            background: rgba(127, 127, 127, .14); }
.dash-bar rect { stroke: var(--bs-body-bg); stroke-width: .4; vector-effect: non-scaling-stroke; }
.dash-total { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
.dash-swatch { width: .8rem; height: .8rem; vertical-align: -.05rem; }
.dash-s1 { fill: var(--chart-1, #009FE3); }
.dash-s2 { fill: var(--chart-2, #EE6438); }
.dash-s3 { fill: var(--chart-3, #6250D6); }
.dash-s4 { fill: var(--chart-4, #1BAF7A); }
.dash-s5 { fill: var(--chart-5, #DBA91B); }
/* Series 6-10: the same five, lighter, for a pipeline with more stages than colours. */
.dash-s6 { fill: var(--chart-1, #009FE3); fill-opacity: .45; }
.dash-s7 { fill: var(--chart-2, #EE6438); fill-opacity: .45; }
.dash-s8 { fill: var(--chart-3, #6250D6); fill-opacity: .45; }
.dash-s9 { fill: var(--chart-4, #1BAF7A); fill-opacity: .45; }
.dash-s10 { fill: var(--chart-5, #DBA91B); fill-opacity: .45; }
/* No stage / Other: grey, so it never reads as a stage. */
.dash-s0 { fill: var(--bs-secondary-color); fill-opacity: .6; }
@media (max-width: 575.98px) {
  /* A phone: the label on its own line above the bar, so a long role title is readable. */
  .dash-row { grid-template-columns: 1fr 3rem; }
  .dash-label { grid-column: 1 / -1; }
}

/* IP-512 -- the Vacancies list. On a phone the table keeps a readable width and scrolls
   sideways inside its .table-responsive box; the page itself never scrolls sideways. */
.vacancy-list { min-width: 46rem; }
details > summary.card-header { cursor: pointer; }

/* IP-514 -- the vacancy page: the stage rail beside the cards, stacked above them on a phone.
   min-width: 0 lets a long answer wrap instead of widening the page: no sideways scroll. */
.vacancy-board { display: grid; grid-template-columns: 16rem minmax(0, 1fr); gap: 1.5rem; }
.vacancy-board > * { min-width: 0; }
.vacancy-stages .nav-link.active { color: var(--htw-action-tint-text); background: var(--htw-action-tint);
                                   font-weight: 600; }
.vacancy-avatar {
  flex: 0 0 2.25rem; width: 2.25rem; height: 2.25rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bs-secondary-bg); font-weight: 600;
}
.vacancy-card-main, .vacancy-answers li, .vacancy-note-body { overflow-wrap: anywhere; }
.vacancy-note-body { white-space: pre-wrap; }
.vacancy-card-actions { max-width: 22rem; }
@media (max-width: 767.98px) {
  .vacancy-board { grid-template-columns: minmax(0, 1fr); }
  .vacancy-card .d-flex.gap-2.align-items-start { flex-wrap: wrap; }
  .vacancy-card-actions { max-width: none; width: 100%; justify-content: flex-start !important; }
}

/* IP-515 -- the candidate side panel: a third column beside the cards while it is open (the
   class on the page, or :has() for a panel htmx swapped in), and the cards go compact: no answers.
   Below 1200px the panel goes under the cards, and on a phone everything is one column, the panel
   under the list. The empty slot takes no space. */
.vacancy-panel-slot:empty { display: none; }
.vacancy-board--open, .vacancy-board:has(.candidate-panel) {
  grid-template-columns: 14rem minmax(0, 1fr) minmax(0, 1.25fr);
}
.vacancy-board--open .vacancy-answers, .vacancy-board:has(.candidate-panel) .vacancy-answers,
.vacancy-board--open [data-preferred], .vacancy-board:has(.candidate-panel) [data-preferred] {
  display: none !important;
}
.vacancy-board--open .vacancy-card-actions, .vacancy-board:has(.candidate-panel) .vacancy-card-actions {
  max-width: none; width: 100%; justify-content: flex-start !important;
}
.vacancy-board--open .vacancy-card .d-flex.gap-2.align-items-start,
.vacancy-board:has(.candidate-panel) .vacancy-card .d-flex.gap-2.align-items-start { flex-wrap: wrap; }
.vacancy-card:has(a[aria-current="true"]) { border-color: var(--htw-action); }
.candidate-panel { position: sticky; top: 1rem; max-height: calc(100vh - 2rem); overflow-y: auto; }
.candidate-panel-body, .candidate-panel-answers dd { overflow-wrap: anywhere; }
.candidate-panel-letter { white-space: pre-wrap; }
/* IP-567 -- a CV preview's page images (_preview_pages.html): full width, one under another. */
.preview-page { display: block; max-width: 100%; height: auto; margin-bottom: .75rem;
                border: 1px solid var(--bs-border-color); background: #fff; }
@media (max-width: 1199.98px) {
  .vacancy-board--open, .vacancy-board:has(.candidate-panel) {
    grid-template-columns: 14rem minmax(0, 1fr);
  }
  .vacancy-panel-slot { grid-column: 2; }
  .candidate-panel { position: static; max-height: none; }
}
@media (max-width: 767.98px) {
  .vacancy-board--open, .vacancy-board:has(.candidate-panel) { grid-template-columns: minmax(0, 1fr); }
  .vacancy-panel-slot { grid-column: auto; }
}

/* IP-524 (SEEK redesign R10) -- a candidate's messages as one thread, like a phone: their replies
   on the left in a light neutral bubble, ours on the right tinted with the HTW primary (htw-style's
   --bs-primary-bg-subtle, #E6F3FC, on #0070C0's border). The full candidate page and the side
   panel draw the same partial, _message_thread.html.

   .msg-scroll is a column-reverse flex box with ONE child: the messages keep their order (oldest
   at the top) and the box's scroll starts at the end, on the newest, with no JavaScript. Bodies
   keep their line breaks with pre-wrap (the text is escaped, never turned into markup), and a long
   word or link wraps rather than widen the page: no sideways scroll at 375px. */
.msg-filter .msg-filter-count { opacity: .75; font-variant-numeric: tabular-nums; }
.msg-scroll {
  display: flex; flex-direction: column-reverse; max-height: 36rem; overflow-y: auto;
  overscroll-behavior: contain; padding: .25rem .125rem;
  border-top: 1px solid var(--bs-border-color); border-bottom: 1px solid var(--bs-border-color);
}
.msg-scroll:focus-visible { outline: 2px solid var(--htw-cyan-mid); outline-offset: 2px; }
.msg-list { display: flex; flex-direction: column; gap: .5rem; padding: .5rem 0; }
.msg { display: flex; min-width: 0; }
.msg-in { justify-content: flex-start; }
.msg-out { justify-content: flex-end; }
.msg-bubble {
  max-width: min(85%, 36rem); min-width: 0; padding: .45rem .7rem; border-radius: 1rem;
  border: 1px solid var(--bs-border-color); font-size: .875rem; overflow-wrap: anywhere;
}
.msg-in .msg-bubble { background: var(--bs-tertiary-bg); border-bottom-left-radius: .25rem; }
.msg-out .msg-bubble {
  background: var(--bs-primary-bg-subtle); border-color: var(--bs-primary-border-subtle);
  border-bottom-right-radius: .25rem;
}
.msg-head { display: flex; flex-wrap: wrap; gap: .25rem; align-items: center; margin-bottom: .2rem; }
.msg-out .msg-head { justify-content: flex-end; }
.msg-chip, .msg-status { font-weight: 500; }
.msg-subject { font-weight: 600; }
.msg-text { white-space: pre-wrap; }
.msg-quoted { margin-top: .25rem; }
.msg-quoted > summary { cursor: pointer; font-size: .75rem; color: var(--bs-secondary-color); }
.msg-note {
  display: inline-block; margin-top: .25rem; padding: .05rem .4rem; border-radius: .5rem;
  font-size: .75rem; background: var(--bs-warning-bg-subtle); color: var(--bs-warning-text-emphasis);
  border: 1px solid var(--bs-warning-border-subtle);
}
.msg-waiting {
  margin-top: .35rem; padding: .35rem .5rem; border-radius: .5rem; background: var(--bs-body-bg);
  border: 1px dashed var(--bs-primary);
}
.msg-foot { margin-top: .2rem; font-size: .75rem; color: var(--bs-secondary-color); }
.msg-out .msg-foot { text-align: right; }
/* The SMS box under the thread: the message, with the wording picker and Send beside it; on a
   phone the picker and the buttons go under the message. */
.msg-compose { margin-top: .75rem; }
.msg-compose-row { display: flex; gap: .5rem; align-items: flex-end; }
.msg-compose-text { flex: 1 1 auto; min-width: 0; }
.msg-compose-side { flex: 0 0 14rem; display: flex; flex-direction: column; gap: .35rem; }
.candidate-panel .msg-scroll { max-height: 28rem; }
@media (max-width: 575.98px) {
  .msg-bubble { max-width: 92%; }
  .msg-scroll { max-height: 70vh; }
  .msg-compose-row { flex-direction: column; align-items: stretch; }
  .msg-compose-side { flex-basis: auto; }
}

/* IP-577 (job ad E2) -- the job ad editor: Quill 2's Snow theme (vendored, never edited) in HTW
   dress. quill.snow.css loads after this file (head_extra), so every rule here starts with
   .rich-editor to outrank it. One box like .form-control: Arial, the input border and the field
   radius, the field focus round the whole box while the cursor is in it, and the pressed toolbar
   button in the action colour. No scale, no glow. Headings and lists inside keep the careers
   page's proportions, so what P&C type looks like what candidates read.
   IP-718 -- htw-style 2.0.0: the field radius, focus and action tokens, as .form-control has. */
.rich-editor {
  border: 1px solid var(--htw-input-border); border-radius: var(--radius-field);
  background: var(--bs-body-bg); font-family: var(--font-sans);
}
.rich-editor:focus-within { border-color: var(--htw-cyan-mid); box-shadow: var(--field-focus); }
.rich-editor .ql-toolbar.ql-snow {
  border: 0; border-bottom: 1px solid var(--htw-neutral-300); padding: .35rem .5rem;
  font-family: var(--font-sans); display: flex; flex-wrap: wrap; gap: .15rem;
}
.rich-editor .ql-container.ql-snow { border: 0; font-family: var(--font-sans); font-size: 1rem; }
.rich-editor .ql-snow.ql-toolbar button {
  float: none; width: 2rem; height: 2rem; padding: .3rem; border-radius: var(--radius-sm);
}
.rich-editor .ql-snow.ql-toolbar button:hover { background: var(--htw-neutral-100); }
.rich-editor .ql-snow.ql-toolbar button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.rich-editor .ql-snow.ql-toolbar button.ql-active { background: var(--htw-action-tint); }
.rich-editor .ql-snow.ql-toolbar button.ql-active .ql-stroke,
.rich-editor .ql-snow.ql-toolbar button.ql-active .ql-stroke-miter { stroke: var(--htw-action-tint-text); }
.rich-editor .ql-snow.ql-toolbar button.ql-active .ql-fill { fill: var(--htw-action-tint-text); }
.rich-editor .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,
.rich-editor .ql-snow.ql-toolbar button:focus:not(.ql-active) .ql-stroke { stroke: var(--htw-ink); }
.rich-editor .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,
.rich-editor .ql-snow.ql-toolbar button:focus:not(.ql-active) .ql-fill { fill: var(--htw-ink); }
.rich-editor .ql-snow .ql-editor {
  min-height: 16rem; max-height: 40rem; padding: .75rem 1rem; line-height: 1.6; color: var(--htw-ink);
}
.rich-editor .ql-snow .ql-editor h3 { font-size: 1.25rem; font-weight: 700; margin: 1rem 0 .5rem; }
.rich-editor .ql-snow .ql-editor h4 { font-size: 1.05rem; font-weight: 700; margin: .85rem 0 .4rem; }
.rich-editor .ql-snow .ql-editor > :first-child { margin-top: 0; }
.rich-editor .ql-snow .ql-editor p { margin: 0 0 .5rem; }
.rich-editor .ql-snow .ql-editor ol { padding-left: 1.25rem; margin: 0 0 .5rem; }
.rich-editor .ql-snow .ql-editor.ql-blank::before { color: var(--htw-slate); font-style: normal; }
/* The count under it. Amber is htw-style's warning, as text on its subtle tint (6:1). */
.rich-count { font-variant-numeric: tabular-nums; }
.rich-count-warn {
  display: inline-block; padding: .1rem .5rem; border-radius: var(--radius-sm);
  background: var(--bs-warning-bg-subtle); color: var(--bs-warning-text-emphasis);
  border-left: 3px solid var(--htw-warning);
}
/* The cover-image picker's radio cards (thumbnails from IP-580). */
.cover-options { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: .75rem; }
.cover-option { display: block; border: 1px solid var(--htw-input-border); border-radius: var(--radius-sm);
                padding: .5rem; cursor: pointer; }
.cover-option:has(input:checked) { border-color: var(--htw-action); background: var(--htw-action-tint); }
.cover-option:has(input:focus-visible) { box-shadow: var(--focus-ring); }
/* IP-752 -- every thumbnail at the careers band's own shape (20:7), the six photos' 400x240 cut to
   it, so what the card shows is what the page shows; "None" is the navy band itself. */
.cover-option img, .cover-none { display: block; width: 100%; height: auto; aspect-ratio: 20 / 7;
                                 object-fit: cover; border-radius: 4px; margin-top: .35rem; }
.cover-none { background: var(--htw-navy); }
.banner-thumb { display: block; width: 100%; max-width: 20rem; height: auto; aspect-ratio: 20 / 7;
                object-fit: cover; border-radius: var(--radius-sm); }
/* The internal notes on the Details tab: as typed, escaped, line breaks kept. */
.internal-notes-body { white-space: pre-line; overflow-wrap: anywhere; }

/* IP-676 -- page headers: title and facts on the left, the page's actions on the right, the
   actions dropping under the title on a narrow screen. */
.page-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start;
             gap: .75rem 1.5rem; margin-bottom: 1.25rem; }
.page-head-main { min-width: 0; flex: 1 1 24rem; }
.page-actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; justify-content: flex-end; }
.page-actions form { margin: 0; }
.min-w-0 { min-width: 0; }

/* IP-676 -- the intake page's set-up panels: as many columns as fit (one on a phone), each at
   least 20rem, so roles, POS IDs, documents and regional access sit side by side above the
   applicants. */
.intake-panels { display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
                 gap: 1rem; align-items: start; }
.intake-panels > * { min-width: 0; }
.intake-panels .card { margin: 0 !important; }

/* A filter row: labelled boxes side by side, wrapping, each a sensible width. */
.applicant-filters { display: flex; flex-wrap: wrap; gap: .75rem 1rem; align-items: flex-end; }
.filter-field { display: flex; flex-direction: column; min-width: 10rem; flex: 0 1 12rem; }
.filter-field .form-label { margin-bottom: .2rem; color: var(--bs-secondary-color); }
.filter-field-wide { flex-basis: 16rem; }
.filter-checks { min-width: 0; flex: 0 0 auto; gap: .15rem; padding-bottom: .1rem; }
.filter-buttons { flex-direction: row; gap: .5rem; min-width: 0; flex: 0 0 auto; }

/* One applicant: who they are and the actions on one line, their answers in columns under it. */
.applicant { padding-top: .9rem; padding-bottom: .9rem; }
.applicant-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.applicant-who { min-width: 0; flex: 1 1 auto; }
.applicant-actions { display: flex; flex-direction: column; align-items: flex-end; gap: .35rem;
                     flex: 0 0 auto; }
.answer-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
               gap: .5rem 1.5rem; margin: .75rem 0 0; padding: .75rem; font-size: .875rem;
               background: var(--bs-tertiary-bg); border-radius: var(--radius-sm, .375rem); }
.answer-grid > div { min-width: 0; }
.answer-grid dt { font-weight: 400; font-size: .75rem; color: var(--bs-secondary-color);
                  line-height: 1.3; }
.answer-grid dd { margin: 0; overflow-wrap: anywhere; }

/* The "Add to role" picker: a button that opens a panel of tick boxes beside it. A <details>,
   so it works with no script; the panel floats over the rows below rather than pushing them. */
.role-picker { position: relative; }
.role-picker > summary { list-style: none; }
.role-picker > summary::-webkit-details-marker { display: none; }
.role-picker[open] > summary { background: var(--htw-action); color: var(--htw-action-on); }
.role-picker-panel { position: absolute; right: 0; top: calc(100% + .35rem); z-index: 20;
                     width: min(26rem, 90vw); max-height: 22rem; overflow-y: auto;
                     padding: .75rem; background: var(--bs-body-bg);
                     border: 1px solid var(--bs-border-color); border-radius: var(--radius-sm, .375rem); }
.role-picker-panel fieldset + fieldset { margin-top: .6rem; padding-top: .6rem;
                                         border-top: 1px solid var(--bs-border-color); }
/* The group names are htw-style's uppercase label (.htw-eyebrow, IP-719); this is spacing only. */
.role-picker-panel legend { margin-bottom: .3rem; }
.role-picker-panel .form-check { font-size: .875rem; margin-bottom: .2rem; }
/* IP-831 -- the intake's Preferred location filter: a <details> that looks like the selects
   beside it and opens a panel of office tick boxes over the list, anchored on its left. */
.loc-picker { position: relative; }
.loc-picker > summary { list-style: none; cursor: pointer; white-space: nowrap; overflow: hidden;
                        text-overflow: ellipsis; min-width: 10rem; max-width: 16rem; }
.loc-picker > summary::-webkit-details-marker { display: none; }
.loc-picker-panel { position: absolute; left: 0; top: calc(100% + .35rem); z-index: 20;
                    width: min(18rem, 90vw); max-height: 24rem; overflow-y: auto;
                    padding: .75rem; background: var(--bs-body-bg);
                    border: 1px solid var(--bs-border-color); border-radius: var(--radius-sm, .375rem); }
.loc-picker-panel legend { margin-bottom: .3rem; }
.loc-picker-panel .form-check { font-size: .875rem; margin-bottom: .2rem; }
@media (max-width: 575.98px) {
  .applicant-head { flex-direction: column; }
  .applicant-actions { align-items: flex-start; }
  .role-picker-panel { right: auto; left: 0; }
}

/* IP-676 -- Application questions as a table: one line per question, a <details> each. The
   line is a grid so its columns line up with the heading row; clicking it opens the edit form
   underneath. Below 768px the columns stack. */
.q-table { overflow: hidden; }
.q-row { display: grid; grid-template-columns: 3rem minmax(0, 2.4fr) 7.5rem minmax(0, 1.4fr) 8.5rem 1.5rem;
         gap: .75rem; align-items: center; padding: .65rem 1rem; }
/* The heading row's names are htw-style's uppercase label (.htw-eyebrow, IP-719), as a table's
   header is; the row draws only the band behind them. */
.q-head { background: var(--htw-neutral-50); border-bottom: 1px solid var(--bs-border-color); }
.q-head > span { font-size: .75rem; color: var(--htw-slate); }
.q-item { border-bottom: 1px solid var(--bs-border-color); }
.q-item:last-child { border-bottom: 0; }
.q-item > summary { list-style: none; cursor: pointer; }
.q-item > summary::-webkit-details-marker { display: none; }
.q-item > summary:hover { background: var(--bs-tertiary-bg); }
.q-item > summary:focus-visible { outline: 2px solid var(--htw-cyan-mid); outline-offset: -2px; }
.q-item[open] > summary { background: var(--htw-action-tint); }
.q-item[open] .q-chevron i { display: inline-block; transform: rotate(180deg); }
.q-order { font-variant-numeric: tabular-nums; color: var(--bs-secondary-color); }
.q-label { min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem .5rem; }
.q-text { font-weight: 600; overflow-wrap: anywhere; }
.q-key { font-size: .75rem; }
.q-type, .q-scope { font-size: .875rem; min-width: 0; overflow-wrap: anywhere; }
.q-marks { display: flex; gap: .35rem; align-items: center; flex-wrap: wrap; }
.q-mark { color: var(--bs-secondary-color); }
.q-chevron { color: var(--bs-secondary-color); text-align: right; }
.q-retired .q-text { color: var(--bs-secondary-color); font-weight: 400; }
.q-edit { padding: 1rem 1rem 1.25rem; border-top: 1px solid var(--bs-border-color);
          background: var(--bs-body-bg); }
.q-links { margin-top: 1rem; padding-top: .75rem; border-top: 1px dashed var(--bs-border-color); }
.add-question > summary, .how-it-works > summary, .retired-questions > summary { cursor: pointer; }
.add-question > summary { font-weight: 600; color: var(--htw-action-text); }
@media (max-width: 767.98px) {
  .q-row { grid-template-columns: 2rem minmax(0, 1fr) 1.5rem; }
  .q-type, .q-scope, .q-marks { grid-column: 2; }
  .q-head .q-type, .q-head .q-scope, .q-head .q-marks { display: none; }
}

/* IP-676 -- a folding filter panel (the Candidates list, by role and by person): the name search
   and Filter / Clear in a bar, "More filters" under it with the filters that are on as chips. */
.filter-bar { display: flex; flex-wrap: wrap; gap: .5rem .75rem; align-items: flex-end; }
.filter-search { flex: 1 1 16rem; max-width: 24rem; }
.filter-search .form-label { margin-bottom: .25rem; }
.filter-search-box { position: relative; }
.filter-search-box > .bi { position: absolute; left: .75rem; top: 50%; transform: translateY(-50%);
                            color: var(--bs-secondary-color); pointer-events: none; }
.filter-search .form-control { padding-left: 2.25rem; }
.filter-more { margin-top: .75rem; border-top: 1px solid var(--bs-border-color); padding-top: .6rem; }
.filter-more > summary { cursor: pointer; display: flex; flex-wrap: wrap; align-items: center;
                         gap: .35rem .75rem; list-style: none; }
.filter-more > summary::-webkit-details-marker { display: none; }
.filter-more-label { font-weight: 600; color: var(--htw-action-text); white-space: nowrap; }
.filter-more-label::before { content: "\F282"; font-family: "bootstrap-icons"; display: inline-block;
                             margin-right: .35rem; transition: transform .15s ease; }
.filter-more[open] .filter-more-label::before { transform: rotate(180deg); }
.filter-chips { display: inline-flex; flex-wrap: wrap; gap: .3rem; }
.filter-chip { display: inline-block; padding: .1rem .55rem; border-radius: 999px; font-size: .8125rem;
               background: var(--bs-primary-bg-subtle); color: var(--bs-primary-text-emphasis);
               border: 1px solid var(--bs-primary-border-subtle); }
.filter-none { font-size: .8125rem; color: var(--bs-secondary-color); }

/* =============================================================================================
   IP-676 (PR 2) -- the visual refresh Shane asked for on 29 Oct 2026, cut back to its layout by
   IP-718. Its colours, font, header, cards, buttons, badges, tables and tabs were the ATS's own
   layer over htw-style 1.x; htw-style 2.0.0 (the HTW UI Style Guide v1.0) now draws all of
   those, so they went. What stays is spacing and layout only. Nothing here redefines an --htw-*
   or --bs-* token (tests/test_htw_style_linked.py).
   ============================================================================================= */
main h1.h3, main h1.h4 { font-size: 1.6rem; }
.small, small { font-size: .8125rem; }

/* The header: one row, the HTW mark, as wide as the page. htw-style draws its colours. */
.htw-nav { padding-block: .45rem; }
.htw-nav > .container { max-width: 1400px; }
@media (min-width: 992px) { main.container, .htw-nav > .container { padding-inline: 1.5rem; } }
.htw-nav .navbar-brand { font-weight: 700; font-size: 1.02rem; line-height: 1.15; }
.htw-nav .brand-mark { border-radius: 6px; }
.htw-nav .brand-sub { font-weight: 400; }
@media (min-width: 992px) {
  .htw-nav .navbar-nav { flex-wrap: nowrap; }
}

.btn .bi { vertical-align: -.1em; }
.table > thead th { white-space: nowrap; }
/* 2.0.0's badges are capitals with letter spacing, so a long one ("Trial import - deleted before
   go-live unless kept") is wider than a phone: let it wrap there rather than widen the page.
   A table in a .table-responsive box scrolls sideways instead, so these leave it alone. */
@media (max-width: 575.98px) {
  main .badge:not(.table-responsive .badge) { max-width: 100%; white-space: normal; text-align: start; }
  /* A long address or link in a cell wraps rather than widen the page (the merge preview). */
  main td:not(.table-responsive td) { overflow-wrap: anywhere; }
}
/* htw-style 2.1.0 draws a .text-bg-light label in ink with !important, which loads after
   Bootstrap's .text-muted and so beat it: a retired tag or "stage not recorded" lost its grey.
   Muted stays muted (slate, about 7:1 on the light fill). */
.badge.text-bg-light.text-muted { color: var(--bs-secondary-color) !important; }
/* A card's stage picker shrinks no further than its "Choose a stage…" label. */
.vacancy-card-actions .form-select { min-width: 10rem; }

/* Breadcrumbs: small and quiet above a page title. */
.breadcrumb { font-size: .8125rem; margin-bottom: .5rem; }

/* A header row of buttons wraps instead of widening the page on a phone (IP-335's rule). */
main .d-flex.justify-content-between { flex-wrap: wrap; row-gap: .5rem; }
main select.w-auto { max-width: 100%; }

/* IP-676 (PR 3) -- a bulk-action bar (data-bulk-bar, base.html): folded to "Select all" and the
   count until something is ticked, then its actions show and it stays at the top of the screen
   while the list scrolls under it. With no script nothing is folded. */
.bulk-bar { position: sticky; top: .5rem; z-index: 6; transition: box-shadow var(--duration-fast, 150ms); }
.bulk-bar:not(.bulk-idle) { box-shadow: var(--shadow-3); border-color: var(--htw-blue-200, #CADFF2); }
.bulk-bar.bulk-idle .bulk-actions { display: none !important; }
.bulk-bar:not(.bulk-idle) .bulk-hint { display: none; }
.bulk-actions-inline { display: contents; }
.bulk-count { font-weight: 600; font-variant-numeric: tabular-nums; }
.bulk-bar.bulk-idle .bulk-count { font-weight: 400; color: var(--htw-slate); }
/* A form that opens on its own button (<details class="open-on-demand">): the summary is the
   button, with no disclosure triangle; it reads as pressed while open. */
.open-on-demand > summary { list-style: none; }
.open-on-demand > summary::-webkit-details-marker { display: none; }
.open-on-demand[open] > summary { background: var(--htw-action-tint); }

/* IP-676 (PR 3) -- an info popover (_info.html): a small (i), and the explanation in a panel
   that floats over the form below it rather than pushing it down. */
.info-pop { position: relative; display: inline-block; margin-top: .2rem; }
.info-pop > summary { list-style: none; display: inline-flex; align-items: center; gap: .3rem;
                      font-size: .8125rem; color: var(--htw-action-text); cursor: pointer;
                      border-radius: 4px; padding: 0 .15rem; }
.info-pop > summary::-webkit-details-marker { display: none; }
.info-pop > summary:hover { color: var(--htw-action-text-hover); background: var(--htw-action-tint); }
.info-pop-body { position: absolute; z-index: 25; left: 0; top: calc(100% + .3rem);
                 width: min(24rem, 80vw); margin: 0; padding: .65rem .8rem; background: #fff;
                 border: 1px solid var(--htw-neutral-200); border-radius: var(--radius-sm);
                 box-shadow: var(--shadow-3); line-height: 1.45; }

/* =============================================================================================
   IP-719 -- htw-style 2.0.0's components on the staff and referral pages.
   ============================================================================================= */
/* The signed-in role in the header (base.html's .who-role): a light pill on the navy bar, as it
   was before 2.0.0, which left it as bare capitals on navy. The action tint and its text are
   #E6F3FC and #005C9E, 6.4:1; the pill on the navy bar is 16:1. Capitals come from .badge. */
.htw-nav .who-role { color: var(--htw-action-tint-text); background: var(--htw-action-tint);
                     border-radius: var(--radius-full); }
/* Buttons side by side need 8px or more, or one's trace ring (2px, 5px outside it) runs into the
   next (htw-style's "Buttons"). Bootstrap's .gap-1 is 4px and !important, so a row of them
   holding a button, directly or in its own form, takes .gap-2's 8px instead. */
.gap-1:has(> .btn, > * > .btn) { gap: .5rem !important; }
/* The drop zone in a side panel or a one-line upload row (_drop_zone.html's compact): less
   padding and a smaller icon, so it is not the tallest thing in the row. */
.htw-drop-ready.drop-compact { padding: .875rem 1rem; }
.htw-drop-ready.drop-compact .htw-drop-icon { inline-size: 32px; block-size: 32px; }
.htw-drop-ready.drop-compact .htw-drop-title { margin-top: 8px; }
.htw-drop-ready.drop-compact .htw-drop-btn { margin-top: 10px; }
/* Several files picked (a note's attachments): a little air between one file and the next. */
.htw-drop-file-meta + .htw-drop-file-name { margin-top: 6px; }

/* IP-765 -- the version at the foot of every staff page, and What's new. The line is quiet on
   purpose: secondary slate, small, underlined only on hover. Each change's New / Improved /
   Fixed badge takes the same width so the text beside it lines up, on the page and in the
   popup (IP-779). */
.app-version { font-size: .8125rem; text-align: center; }
.app-version a { color: var(--htw-slate, #475569); text-decoration: none; }
.app-version a:hover, .app-version a:focus-visible { text-decoration: underline; }
.whats-new { max-width: 900px; }
.whats-new .change-kind, .whats-new-popup .change-kind { min-width: 5.5rem; margin-top: .15rem; }

/* IP-815 -- a phone screen's CV beside its questions on a wide screen: it stays in view while the
   questions scroll, and scrolls on its own. Printing hides the panel and the buttons. */
.phone-screen-cv { position: sticky; top: 1rem; max-height: calc(100vh - 2rem); overflow-y: auto; }
@media print {
  .phone-screen-cv, .phone-screen-print .d-print-none { display: none !important; }
}
