/*
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
*/
/* 
    Created on : Feb 3, 2014, 1:41:56 PM
    Author     : alo
*/

/* ─────────────────────────────────────────────────────────────
   Scrollbars, everywhere
   The browser's own are wide and dark, and this application is mostly panes within panes,
   so on a busy screen a dozen of them read as structure the eye has to sort through. The
   same pale pair the concept diagram already used: a light thumb on a lighter track.

   Two spellings of the same thing. scrollbar-width and scrollbar-color are the standard
   properties, and they are what Chrome 121 and newer, and Firefox, will use. The
   ::-webkit- block below is for older Chrome and Safari, which ignore the standard ones —
   and newer Chrome ignores the webkit ones as soon as a standard property is set, so the
   two never fight.

   The declaration is on * rather than on :root because the two properties do not behave
   alike: scrollbar-color inherits, but scrollbar-width does not — measured, html computes
   to thin and body is already back to auto — so declared once at the root the bars keep
   their colour and their full 15px width. On * they come out at 10px.

   The thin keyword also costs the rounded thumb and the hover colour, which only the
   webkit pseudo-elements can express.

   HOW TO REVERT: delete this block. The browser's defaults come straight back — nothing
   else in this file touches a scrollbar.
   ───────────────────────────────────────────────────────────── */
* {
    scrollbar-width: thin;
    scrollbar-color: #d5dbe2 #f7f8fa;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: #f7f8fa;
}

::-webkit-scrollbar-thumb {
    background: #d5dbe2;
    border-radius: 5px;
}

/* Something to aim at: a thumb this pale is easy to lose against its track. */
::-webkit-scrollbar-thumb:hover {
    background: #c2cad3;
}

/* Where a vertical and a horizontal bar meet, otherwise the browser's own grey. */
::-webkit-scrollbar-corner {
    background: #f7f8fa;
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(359deg);
    }
}

@-webkit-keyframes spin {
    from {
        -webkit-transform: rotate(0deg);
    }

    to {
        -webkit-transform: rotate(359deg);
    }
}

.icon-spin {
    animation: 1.5s linear 0s normal none infinite spin;
    -webkit-animation: 1.5s linear 0s normal none infinite spin;
    display: inline-block;
}

i:active {
    background-color: #428bca;
}

.selectable-row:active {
    background-color: #428bca;
    color: white;
}

.popover {
    max-width: 800px;
    min-width: 250px;
}

.jqui-draggable.ui-draggable-dragging {
    color: black;
    background: yellow;
    font: bold;
    z-index: 1000;
}

.bperspective {
    display: none;
}

.dropdown-submenu {
    position: relative;
}

.dropdown-submenu>.dropdown-menu {
    top: 0;
    left: 100%;
    margin-top: -6px;
    margin-left: -1px;
    -webkit-border-radius: 0 6px 6px 6px;
    -moz-border-radius: 0 6px 6px 6px;
    border-radius: 0 6px 6px 6px;
}

.dropdown-submenu:hover>.dropdown-menu {
    display: block;
}

.dropdown-submenu>a:after {
    display: block;
    content: " ";
    float: right;
    width: 0;
    height: 0;
    border-color: transparent;
    border-style: solid;
    border-width: 5px 0 5px 5px;
    border-left-color: #cccccc;
    margin-top: 5px;
    margin-right: -10px;
}

.dropdown-submenu:hover>a:after {
    border-left-color: #ffffff;
}

.dropdown-submenu .pull-left {
    float: none;
}

.dropdown-submenu.pull-left>.dropdown-menu {
    left: -100%;
    margin-left: 10px;
    -webkit-border-radius: 6px 0 6px 6px;
    -moz-border-radius: 6px 0 6px 6px;
    border-radius: 6px 0 6px 6px;
}

.unobtrusive-icon {
    color: #e3e3e3;
}

.unobtrusive-icon:hover {
    color: dodgerblue;
}

/* Tree CSS */
.tree li {
    margin: 0px 0;

    list-style-type: none;
    position: relative;
    padding: 20px 5px 0px 5px;
}

.tree li::before {
    content: '';
    position: absolute;
    top: 0;
    width: 1px;
    height: 100%;
    right: auto;
    left: -20px;
    border-left: 1px solid #ccc;
    bottom: 50px;
}

.tree li::after {
    content: '';
    position: absolute;
    top: 30px;
    width: 25px;
    height: 20px;
    right: auto;
    left: -20px;
    border-top: 1px solid #ccc;
}

.tree li a {
    display: inline-block;
    border: 1px solid #ccc;
    padding: 5px 10px;
    text-decoration: none;
    color: #666;
    font-family: arial, verdana, tahoma;
    font-size: 11px;
    border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
}

/*Remove connectors before root*/
.tree>ul>li::before,
.tree>ul>li::after {
    border: 0;
}

/*Remove connectors after last child*/
.tree li:last-child::before {
    height: 30px;
}

/*Hover effects*/
.tree li a:hover,
.tree li a:hover+ul li a {
    background: #c8e4f8;
    color: #000;
    border: 1px solid #94a0b4;
}

/*Connector styles on hover*/
.tree li a:hover+ul li::after,
.tree li a:hover+ul li::before,
.tree li a:hover+ul::before,
.tree li a:hover+ul ul::before {
    border-color: #94a0b4;
}

/* Clear Search */
.searchclear {
    position: absolute;
    right: 5px;
    top: 0;
    bottom: 0;
    height: 14px;
    margin: auto;
    font-size: 14px;
    cursor: pointer;
    color: #ccc;
}

.highlightEffectiveTime {
    border: 2px solid blue;
    border-style: dashed;
}

.menu-item-active {
    background-color: #99ccff;
}

.selectedRowBs {
    border: 2px solid rgba(82, 168, 236, .8);
}

.selectedRowLight {
    background-color: lightskyblue;
}

.divAsLink:hover {
    cursor: hand;
    cursor: pointer;
}

.selectedRowBlue {
    background-color: #337ab7;
}

.no-padding {
    padding: 0px;
}

/* Expressions language */

.expression-code {
    font-family: "Courier New", monospace;
    white-space: pre;
    /*background-color: #000000;*/
    font-weight: bold;
    font-size: 13px;
}

.exp-brackets {
    color: #3300aa;
}

.exp-operators {
    color: sienna;
}

.exp-pipes {
    color: #086d11;
}

.exp-term {
    color: #086d11;
}

.sct-drag-icon {
    background-color: orange;
    border-color: #E7D6B4;
    color: #8a6d3b;
}

.spelling-error {
    border-bottom: 2px dotted #ba0000;
}

div.textarea {
    width: 100%;
    font-size: 14px;
    line-height: 18px;
    background-color: white;
    min-height: 200px;
}

div.textarea.fixed {
    overflow-y: scroll;
    height: 200px;
}

pre {
    outline: 1px solid #ccc;
    padding: 5px;
    margin: 5px;
}

.string {
    color: green;
}

.number {
    color: darkorange;
}

.boolean {
    color: blue;
}

.null {
    color: magenta;
}

.key {
    color: red;
}

/* D3 styles */
/*.link {*/
/*stroke: #ccc;*/
/*}*/

/*.node text {*/
/*pointer-events: none;*/
/*font: 10px sans-serif;*/
/*}*/

/*circle {*/
/*stroke-width: 1.5px;*/
/*}*/

/*line {*/
/*stroke: #999;*/
/*stroke-width: 1.5px;*/
/*}*/

/*.node circle{*/
/*stroke: #34495e;*/
/*stroke-width: 2px;*/
/*box-sizing: border-box;*/
/*stroke-location: inside;*/
/*}*/

/*.node text {*/
/*font-size: 11px;*/
/*}*/

/*line.link {*/
/*fill: none;*/
/*stroke: #bbb;*/
/*stroke-width: 1.5px;*/
/*}*/

/*Dagre Styles*/
/* This sets the color for "TK" nodes to a light blue green. */
g.type-TK>rect {
    fill: #00ffd0;
}

/*text {*/
/*font-weight: 300;*/
/*font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;*/
/*font-size: 14px;*/
/*}*/

.node rect {
    stroke: #999;
    fill: #fff;
    stroke-width: 1.5px;
}

.edgePath path {
    stroke: #333;
    stroke-width: 1.5px;
}

g.type-primitive>rect {
    fill: #99ccff;
}

g.type-defined>rect {
    fill: #ccccff;
}

/* this element needs tooltip positioning to work */
.graphviz-svg {
    position: relative;
}

/* stop tooltips wrapping */
.graphviz-svg .tooltip-inner {
    white-space: nowrap;
}

/* stop people selecting text on nodes */
.graphviz-svg text {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    cursor: default;
}

.explanation-ids {
    color: #ffbf00
}

.explanation-pipes {
    color: #e83f6f
}

.explanation-brackets {
    color: #2274a5
}

.explanation-symbol {
    color: #32936f
}

.CodeMirror-line {
    outline: none
}

.shortcut-highlight {
    background-color: yellow;
    color: black;
}

.tm-change {
    background-color: yellow;
    color: black;
}

/* Ticker classes */
@keyframes ticker {
    0% {
        margin-top: 0
    }

    25% {
        margin-top: -17%
    }

    50% {
        margin-top: -34%
    }

    75% {
        margin-top: -51%
    }

    100% {
        margin-top: 0
    }
}

.comments-ticker {
    height: 55px;
    margin: 0px auto;
    overflow: hidden;
    border-radius: 4px;
    padding: 3px;
    -webkit-user-select: none
}

.comments-ticker ul {
    float: left;
    padding-left: 5px;
    /*animation: ticker 20s cubic-bezier(1, 0, .5, 0) infinite;*/
    -webkit-user-select: none
}

.comments-ticker ul li {
    list-style: none
}

.notifyjs-bootstrap-base {
    font-size: 15px !important;
    padding: 12px 20px 12px 38px !important;
    max-width: 600px !important;
    background-position: 10px center !important;
    white-space: normal !important;
    word-wrap: break-word !important;
}

.notifyjs-corner {
    left: 50% !important;
    transform: translateX(-50%) !important;
    right: auto !important;
}

.notifyjs-foo-base {
    /*opacity: 0.85;*/
    /*width: 200px;*/
    /*background: #f5f5f5;*/
    /*padding: 5px;*/
    /*border-radius: 30px;*/
    /*border: solid 1px;*/
}

.notifyjs-foo-base .title {
    /*width: 100px;*/
    /*float: left;*/
    margin: 10px 0 0 10px;
    text-align: right;
}

.notifyjs-foo-base .buttons {
    /*width: 70px;*/
    /*float: right;*/
    font-size: 12px;
    padding: 5px;
    margin: 2px;
}

.notifyjs-foo-base button {
    font-size: 12px;
    padding: 5px;
    margin: 2px;
    width: 60px;
}

.axiomCHead.inactive {
    background-color: #f2dede !important;
    color: black !important;
}

.axiomCHead {
    /*.panel-primary.axiomC .panel-heading {*/
    background-color: rgb(153, 204, 255) !important;
    color: black !important;
}

.relTarget.inactive {
    background-color: #f2dede !important;
    color: black !important;
}

.relType.inactive {
    background-color: #f2dede !important;
    color: black !important;
}

.gciCHead.inactive {
    background-color: #f2dede !important;
    color: black !important;
}

tr.inactive > td {
    background-color: #f2dede !important;
}

.gciCHead {
    /*.panel-success.gciC .panel-heading {*/
    background-color: lightgreen !important;
    color: black !important;
}

.noPadding {
    padding: 0;
}

#rmenu.show {
    z-index: 1000;
    position: absolute;
    background-color: rgb(66, 139, 202);
    border: 1px solid rgb(66, 139, 202);
    padding: 2px;
    display: block;
    margin: 0;
    list-style-type: none;
    list-style: none;
    border-radius: 10px;
}

#rmenu.hide {
    display: none;
}

.databaseManagerBox {
    border-width: 3px;
    border-style: solid;
    border-radius: 10px;
    margin-bottom: 5px;
    background-color: #f5f5f5;
    border-color: #ddd;
    /* width: 90%; */
    height: -webkit-fill-available;
}

.databaseManagerBox button {
    margin: 10px;
}

.databaseManagerTitle {
    margin: 5px;
}

.databaseManagerInfo {
    margin: 10px;
    color: gray;
}

.accordionChevron {
    border: 0px;
    background-color: transparent;
}

.tableCAT {
    margin: 0px;
    border-collapse: collapse;
}

.tableCAT td,
table th {
    border: 1px solid black;
}

.tableCAT tr:first-child td {
    border-top: 0;
}

.tableCAT tr:last-child td {
    border-bottom: 0;
}

.tableCAT tr td,
.tableCAT tr th {
    border-left: 0;
}

.tableCAT tr td,
.tableCAT tr th {
    border-right: 0;
}

.standard-table {
    border-collapse: collapse;
    width: 100%;
}

.standard-table th,
.standard-table td {
    border-top: none !important;
    border-left: none !important;
    border-right: none !important;
    padding: 8px;
    text-align: left;
    border-bottom: 1px solid #ddd;
}

h5.collapsableTitle[data-toggle="collapse"]:after {
    display: inline-block;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: "\f054";
    transform: rotate(90deg);
    transition: all linear 0.25s;
    float: right;
}

h5.collapsableTitle[data-toggle="collapse"].collapsed:after {
    transform: rotate(270deg);
}

h5.collapsableTitleLeftIcon[data-toggle="collapse"]:before {
    display: inline-block;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: "\f054";
    transform: rotate(90deg);
    transition: all linear 0.25s;
    float: left;
    margin-right: 5px;
}

h5.collapsableTitleLeftIcon[data-toggle="collapse"].collapsed:before {
    transform: rotate(270deg);
}

h4.collapsableTitle[data-toggle="collapse"]:after {
    display: inline-block;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: "\f054";
    transform: rotate(90deg);
    transition: all linear 0.25s;
    float: right;
}

h4.collapsableTitle[data-toggle="collapse"].collapsed:after {
    transform: rotate(270deg);
}

h4.collapsableTitleLeftIcon[data-toggle="collapse"]:before {
    display: inline-block;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: "\f054";
    transform: rotate(90deg);
    transition: all linear 0.25s;
    float: left;
    margin-right: 5px;
}

h4.collapsableTitleLeftIcon[data-toggle="collapse"].collapsed:before {
    transform: rotate(270deg);
}

h3.collapsableTitle[data-toggle="collapse"]:after {
    display: inline-block;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: small;
    margin-top: 7px;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: "\f054";
    transform: rotate(90deg);
    transition: all linear 0.25s;
    float: right;
}

h3.collapsableTitle[data-toggle="collapse"].collapsed:after {
    transform: rotate(270deg);
}

.batchPretranslationModalTable {
    margin-left: 1%;
    margin-right: 1%;
    border-width: 3px;
    border-style: solid;
    border-radius: 10px;
    margin-bottom: 5px;
    margin-top: 5px;
    background-color: #f5f5f5;
    border-color: #ddd;
    /* width: 90%; */
}


.batchPretranslationBox {
    margin-left: 1%;
    margin-right: 1%;
    border-width: 3px;
    border-style: solid;
    border-radius: 10px;
    margin-bottom: 5px;
    margin-top: 5px;
    background-color: #f5f5f5;
    border-color: #ddd;
    /* width: 90%; */
    height: -webkit-fill-available;
}

.batchPreTranslationStep {
    margin: 10px;
}

.batchPretranslationButton {
    /* float: right; */
    /* margin-right: 10px; */
    /* margin-top: 10px; */
    width: -webkit-fill-available;
}

.batchPreTranslationTable {
    border-collapse: separate;
}

.borderedRow {
    border-style: solid;
    border-color: orange;
    border-width: thin;
    border-radius: 10px;
}

.additionalFilters {
    padding: 10px;
    border-color: gray;
    border-style: solid;
    border-radius: 10px;
    border-width: thin;
    margin-top: 10px;
    margin-left: 10px;
    margin-right: 10px;
}

.batchPretranslationAdditionalFilters {
    padding: 5px;
    border-color: lightgray;
    border-style: solid;
    border-radius: 10px;
    border-width: thin;
    margin-top: 10px;
    margin-left: 10px;
    margin-right: 10px;
}

.batchPretranslationSelector {
    width: -webkit-fill-available;
    float: right;
    /* margin-right: 10px;
    margin-top: 10px; */
    padding-top: 2%;
    padding-left: 2%;
    border-color: lightgray;
    border-style: solid;
    border-radius: 10px;
    border-width: thin;
}

.batchPreTranslationDivider {
    margin-top: 5px;
    margin-bottom: 5px;
}

.unselectable {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.browsableTable tr.descriptionRowInFocus {
    border: 2px solid #ec971f !important;
    font-weight: bold;
    background-color: #ffbe2b38;
}

table.descriptionInfoTable {
    margin-top: 10px;
    border-collapse: separate !important;
    border: 2px solid gray;
    border-radius: 5px;
    border-spacing: 0;
    width: 100%;
}

table.descriptionInfoTable td,
table.descriptionInfoTable th {
    border: 1px solid lightgray;
    padding: 10px;
}

table.descriptionInfoTable tr:last-child>td {
    border-bottom: none;
}

.rotate90 {
    transform: rotate(90deg);
}

.briefcase-container {
    display: flex;
    width: 100%;
    justify-content: center;
}

.briefcase-button-container {
    padding: 0px 12px;
}

.briefcase-button-container:not(:last-child) {
    border-right: 1px solid #ddd;
}

/* Briefcase import and export. Nine full-width blue buttons in a grid outweighed the concept
   list, which is what the modal is for, and the import row sat centred and unnamed right
   above them, so the two read as one block. Each section is named by the small spaced
   uppercase label the Refsets tab and the dashboard use and is set to one left edge with
   one hairline above it; every row keeps the same 6px gap, and the file input is drawn as a
   small button beside the chosen name so it sits at the height of the buttons rather than
   as the browser's own control. The exports keep Bootstrap's blue, small, one row per kind
   of output with the kind at the left in plain muted text, a step below the section label. */
/* The list gives way so the whole dialog fits the screen: everything around it (header,
   counts, import, export, footer, margins) comes to about 480px, so at 768px tall the list
   gets 290px and at 1080px it gets 600px, instead of a fixed 420px that pushed the export
   rows below the fold on a laptop and made the page itself scroll. */
/* The list is the same kind of list as favourites and takes .ts-list-table: the bordered
   table drew a frame inside the modal's frame and its 8px cells plus a 2px border made
   every row taller than its two lines of text. The heading row is the small spaced label
   the Refsets tab uses, and the note under the list loses its cell border. */
#briefcase-panel .ts-list-table > thead > tr > th,
#le-listEditor .ts-list-table > thead > tr > th,
.le-jobs-modal .ts-list-table > thead > tr > th {
    border: 0;
    border-bottom: 1px solid #e7e9ee;
    background-color: transparent;
    padding: 4px 10px 5px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #8a94a0;
}

#briefcase-panel .ts-list-table > tbody > tr > td,
#le-listEditor .ts-list-table > tbody > tr > td,
.le-jobs-modal .ts-list-table > tbody > tr > td {
    padding: 5px 10px;
    line-height: 1.35;
}

#briefcase-panel .ts-list-table > tfoot > tr > td {
    border: 0;
    padding: 6px 10px 2px;
}

#briefcase-panel .briefcase-list {
    overflow: auto;
    max-height: calc(100vh - 480px);
    min-height: 160px;
}

#briefcase-panel .briefcase-section {
    padding: 12px 0 6px;
    border-top: 1px solid #e7e9ee;
}

#briefcase-panel .briefcase-import {
    margin-top: 14px;
}

#briefcase-panel .briefcase-section-label {
    margin: 0 0 8px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #8a94a0;
}

#briefcase-panel .briefcase-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
}

/* The export rows are one grid, four equal button columns after the kind, so every button
   is the same width, the columns line up from row to row and the row runs the width of the
   modal; a row with fewer buttons leaves its remaining columns empty rather than stretching. */
#briefcase-panel .briefcase-exports .briefcase-row {
    display: grid;
    grid-template-columns: 120px repeat(4, minmax(0, 1fr));
}

#briefcase-panel .briefcase-exports .briefcase-row > .btn {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#briefcase-panel .briefcase-export-kind {
    color: #6b7280;
    font-size: 12px;
}

#briefcase-panel .briefcase-import-or {
    color: #8a94a0;
    font-size: 12px;
    margin: 0 2px;
}

/* The native input stays in the DOM (briefcase.js reads its files) but off screen; the
   label is the button that opens it, and the name beside it is filled by briefcase.js. */
#briefcase-panel .briefcase-file {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid #ccc;
    border-radius: 3px;
    overflow: hidden;
}

#briefcase-panel .briefcase-file > input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

#briefcase-panel .briefcase-file > label {
    margin: 0;
    border: 0;
    border-right: 1px solid #ccc;
    border-radius: 0;
    background: #f5f6f8;
}

#briefcase-panel .briefcase-file > input[type="file"]:focus-visible + label {
    outline: 2px solid #5b9bd5;
    outline-offset: -2px;
}

#briefcase-panel .briefcase-file-name {
    padding: 0 10px;
    line-height: 28px;
    font-size: 12px;
    color: #8a94a0;
    min-width: 180px;
    max-width: 260px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#briefcase-panel .briefcase-file-name.has-file {
    color: #333;
}

.help-modal .bootbox-body {
    height: 85vh;
}

.healthFactorsBox {
    margin-left: 1%;
    margin-right: 1%;
    border-width: 3px;
    border-style: solid;
    border-radius: 5px;
    margin-bottom: 5px;
    margin-top: 5px;
    background-color: #f5f5f5;
    border-color: #ddd;
    /* width: 90%; */
    /* height: -webkit-fill-available; */
}

.healthFactorsTable {
    border-collapse: separate;
}

.healthFactorsTitle {
    margin: 5px;
}

.template-item {
    cursor: pointer;
}

.template-item:hover {
    background-color: orange;
}

.health-factor-item {
    cursor: pointer;
}

.health-factor-item:hover {
    background-color: darkturquoise;
}

.template-editor-toolbar {
    float: right;
}

.health-factor-editor-toolbar {
    float: right;
}

/*.comments-ticker ul:hover { animation-play-state: paused }*/

.jiraUpdateDialog .modal-dialog {
    width: 90%;
}

.label-as-badge {
    border-radius: 1em;
}

.resizableCol {
    transition: all 0.3s linear;
    -o-transition: all 0.3s linear;
    -moz-transition: all 0.3s linear;
    -webkit-transition: all 0.3s linear;
}

.dropdown-menu .hide-in-dropdown {
    display: none;
}

.collapsableForm {
    transition: all 0.3s linear;
    -o-transition: all 0.3s linear;
    -moz-transition: all 0.3s linear;
    -webkit-transition: all 0.3s linear;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;

}

.collapsableForm:has(> .collapsableDivWithBorder[aria-expanded="false"]) {
    border-color: transparent !important;
}

.collapsableForm:has(> .collapsableDivWithBorder[aria-expanded="true"]) {
    border-color: lightgray !important;
}

.form-group-thin-margin {
    margin-bottom: 5px;
    margin-top: 5px;
}

.thin-divider {
    margin-top: 5px;
    margin-bottom: 5px;
}

.btn-responsive {
    white-space: normal;
    word-wrap: break-word;
    font-size: 12px;
    padding: 6px 8px;
}

@media (max-width: 1200px) {
    .btn-responsive {
        font-size: 11px;
    }
}

@media (max-width: 992px) {
    .btn-responsive {
        font-size: 10px;
    }
}

.checkbox-responsive {
    display: flex;
    align-items: center;
    margin-bottom: 0;
    /* Remove default margin */
}

.checkbox-responsive input[type="checkbox"] {
    margin-right: 5px;
    margin-top: 0;
    /* Remove default top margin */
    vertical-align: middle;
    /* Align checkbox vertically */
}

.checkbox-responsive span {
    font-size: 12px;
    font-weight: bold;
    vertical-align: middle;
    /* Align label text vertically */
    line-height: 1;
    /* Adjust line height for better alignment */
}

@media (max-width: 1200px) {
    .checkbox-responsive span {
        font-size: 11px;
    }
}

@media (max-width: 992px) {
    .checkbox-responsive span {
        font-size: 10px;
    }
}

.strength-input {
    padding-left: 2px;
    padding-right: 2px;
    text-align: center;
}

.hoverOnDiv:hover {
    background-color: lightgray !important;
    margin: 3px;
}

.originDataLabel {
    color: gray;
    margin: 5px;
    margin-bottom: 0px;
    display: none;
}

/* Opt-in: add `show-origin-data-labels` to a parent (e.g. <body>) to re-enable */
.show-origin-data-labels .originDataLabel {
    display: inline-block;
}

.switch-container {
    display: flex;
    align-items: center;
    gap: 8px;
}

.switch-label {
    font-weight: bold;
    /* Always bold */
    margin: 0;
    user-select: none;
    font-size: 13px;
    color: #999;
    transition: color 0.4s;
    cursor: pointer;
}

/* Label states - only color changes now */
.toggle-input:not(:checked)~.switch-label.left,
.toggle-input:checked~.switch-label.right {
    color: #337ab7;
}

.switch {
    position: relative;
    display: inline-block;
    width: 32px;
    height: 18px;
    cursor: pointer;
}

/* Scoped to .switch: a bare .slider would also hit jQuery UI's slider widget, which
   carries that same class in the Create assignments percentage split. */
.switch .slider {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #bdbdbd;
    transition: .4s;
    border-radius: 18px;
}

.switch .slider:before {
    position: absolute;
    content: "";
    height: 14px;
    width: 14px;
    left: 2px;
    bottom: 2px;
    background-color: white;
    transition: .4s;
    border-radius: 50%;
}

.toggle-input:checked~.switch .slider:before {
    transform: translateX(14px);
}

/* Toggle Switch styles */
.switch-generic {
    position: relative;
    display: inline-block;
    width: 30px;
    height: 16px;
}

.switch-generic input {
    opacity: 0;
    width: 0;
    height: 0;
}

.slider-generic {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #ccc;
    transition: .4s;
}

.slider-generic:before {
    position: absolute;
    content: "";
    height: 12px;
    width: 12px;
    left: 2px;
    bottom: 2px;
    background-color: white;
    transition: .4s;
}

input:checked+.slider-generic {
    background-color: #2196F3;
}

input:checked+.slider-generic:before {
    transform: translateX(14px);
}

.slider-generic.round {
    border-radius: 16px;
}

.slider-generic.round:before {
    border-radius: 50%;
}

.toggle-container {
    display: inline-flex;
    align-items: center;
}

/* Collapsible task comments (inbox activity preview) */
.task-comments-collapsible {
    margin-bottom: 10px;
}

.task-comments-toggle,
.task-comments-toggle:hover,
.task-comments-toggle:focus {
    display: inline-block;
    padding: 4px 0;
    color: #337ab7;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    outline: none;
    outline-offset: 0;
    box-shadow: none;
}

/* the metadata disclosure borrows the comments toggle's look; it stays a
   <button> rather than an <a> because it toggles rather than navigates */
.ts-preview-metadata-toggle {
    border: 0;
    background: none;
}

.task-comments-caret {
    transition: transform 0.2s ease;
    margin-right: 4px;
}

.task-comments-toggle:not(.collapsed) .task-comments-caret {
    transform: rotate(90deg);
}

/* The comments dialog holds a task's whole history plus the composer, and the briefcase a
   list of long terms over a four-column button grid, so modal-lg's 900px leaves them
   cramped on any real screen while the page behind them is unused.
   Only from the breakpoint where Bootstrap gives .modal-lg a fixed width -- below
   it the dialog is already margin-based and fluid. */
@media (min-width: 992px) {
    .ts-comments-modal .modal-dialog,
    #briefcase-modal .modal-dialog {
        width: 92%;
        max-width: 1200px;
        margin: 20px auto;
    }
}

/* The dialog takes the height the window gives it and the history absorbs the
   difference, so the composer stays put at the bottom. With the old fixed
   max-height on the body the whole thing scrolled as one block and the form
   went out of view behind a long comment history. */
.ts-comments-modal .modal-content {
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 40px);
}

.ts-comments-modal .modal-header {
    flex: 0 0 auto;
}

/* the body was the last thing in the dialog once the footer went, so it takes the
   rounded bottom corners the footer used to carry */
.ts-comments-modal .ts-comments-modal-body {
    padding-bottom: 15px;
    border-bottom-right-radius: 6px;
    border-bottom-left-radius: 6px;
}

.ts-comments-modal-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

/* the only part that scrolls */
.ts-comments-modal-body .task-comments-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.ts-comments-modal-body .ts-commentform {
    flex: 0 0 auto;
}

/* Comments list: keeps the historical 80% float for the modal and the standalone
   comment panels, goes full width inside the collapsible activity preview. */
.task-comments-list {
    float: left;
    margin-right: 5px;
    width: 80%;
}

.task-comments-collapsible .task-comments-list,
.ts-comments-full .task-comments-list {
    float: none;
    margin-right: 0;
    width: 100%;
}

/* QA results panel: one frame, two regions. The tree and the results each used to sit in a
   bordered, rounded box of their own inside the panel, and the Content QA / Technical QA
   tabs brought a Bootstrap panel of their own on top (border:none, but its shadow and its
   20px bottom margin stayed). The panel is now the only frame: the regions sit on its
   ground, and the results are set off by a single line, the one the panel heading draws. */
.qa-panel-body > .qa-tree-region {
    padding: 8px 10px 4px;
}

/* The filters over the rule list. They were three full-height selects in bold: two in
   columns, and the language refset in a bare div that fell to a second line because it was
   in no column at all, with the date of the last run in bold beside them. The path and the
   severity are fixed choices and take the segmented control the Classifier and Builds tabs
   pick a path with (.cl-path-switch), so the same question is asked the same way in all
   three. The refset varies with the project and stays a select: it ends the line and takes
   what the two switches leave, and drops to a line of its own, at full width, only once
   that is under 220px, too little to read a refset's name in. The date says when the
   results were produced, not what to show of them, and went up to the heading, beside the
   button that reloads them. */
.qa-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    margin-bottom: 8px;
}

.qa-filters > .qa-filters-refset {
    flex: 1 1 220px;
    min-width: 0;
    height: 30px; /* the switches' height; input-sm is 28px and would sit short beside them */
}

/* the colours the rule list gives its warning and error marks */
.qa-sev-warning {
    color: orange;
}

.qa-sev-error {
    color: red;
}

.qa-last-run {
    margin-right: 6px;
    color: #8a94a0;
    font-size: 11px;
    font-weight: normal;
    vertical-align: middle;
}

.qa-panel-body > .qa-tree-region .panel {
    box-shadow: none;
    margin-bottom: 0;
    background: transparent;
}

/* The rule list scrolls on its own, so the path and severity selects, the Content QA /
   Technical QA tabs and the Legacy/New names switch stay in view while reading down a
   long list. The cap is taken from the window: the region's own max-height:40% never
   resolved, because nothing above the panel has a definite height, and giving the panel
   one is the work that was reverted. A max-height leaves a short list at its own height.
   Where that 40% does resolve, the region would scroll around the list that already
   scrolls, so the cap moves to the list rather than being shared. !important because the
   region's are inline. */
.qa-panel-body > .qa-tree-region {
    max-height: none !important;
    overflow: visible !important;
}

.qa-panel-body > .qa-tree-region .tab-content {
    max-height: 45vh;
    overflow-y: auto;
    /* the region's 10px right padding left the scrollbar standing off the panel's
       edge, with a strip of nothing between it and the splitter. The list reaches
       through the padding so the bar sits against the frame. */
    margin-right: -10px;
    /* inside the scrollbar: keeps the info icons from touching it */
    padding-right: 8px;
}

.qa-panel-body > .qa-results-region {
    border-top: 1px solid #ddd;
    padding: 4px 10px 0;
}

/* QA results table. Scoped to .qa-results-table so it cannot reach the other
   Bootstrap tables in the application. */
.qa-results-table {
    /* position: sticky has no effect on table cells while the table uses collapsed
       borders, so the results table opts out. border-spacing: 0 keeps the rows
       flush - Bootstrap draws the row separators with border-top on each cell. */
    border-collapse: separate;
    border-spacing: 0;
}

.qa-results-table > thead > tr > th {
    /* Neutralises the `table th` selector further up this file, which is missing
       its .tableCAT prefix and so puts a black border on every table header cell
       in the application. Overriding it here rather than fixing it at the source,
       which would change every table at once. */
    border: 0;
}

.qa-results-table thead .qa-results-head th {
    position: sticky;
    top: 0;
    z-index: 2;
    /* Opaque: striped rows scroll underneath. */
    background-color: #fff;
    /* A border on a sticky cell scrolls away with the row it belongs to, so the
       separator is painted inside the cell instead. */
    border-bottom: none;
    box-shadow: inset 0 -2px 0 #ddd;
}

/* A rule in the tree. The whole row selects it, so the whole row answers to the
   pointer. */
.qa-rule-row {
    cursor: pointer;
}

/* The severity icon hangs in the list's left margin (.fa-li), outside the row's box, so a
   background on the row stopped short of it. The spread carries the hover and the
   selection under the icon as well, without moving anything. */
.qa-rule-row:hover {
    background-color: #f2f2f2;
    box-shadow: -2.2em 0 0 #f2f2f2;
}

/* The rule info icon. Quiet by default so it does not compete with the severity
   icon at the other end of the row, and it answers on hover since an icon on its
   own does not say what it does. */
.rule-info {
    color: #999;
    cursor: pointer;
    /* A shade larger than the row text: it is a target, and at inherited size it was
       easy to miss next to a long rule name. */
    font-size: 15px;
    line-height: 1.4;
}

.rule-info:hover {
    color: #337ab7;
}

/* Bootstrap rings every focused link, so clicking a rule left an outline behind
   on top of the selection marker. Dropped for the pointer, kept for the keyboard:
   :focus-visible only matches when the browser judges the focus worth showing,
   which is what Tab navigation needs to stay usable. */
.testsuite-link:focus {
    outline: none;
}

.testsuite-link:focus-visible {
    outline: 2px solid #23527c;
    outline-offset: 2px;
}

/* The rule whose results are on screen. It was reversed out of the primary blue, a block
   that fitted the link alone: a name that ran to two lines left its Whitelisted link
   outside the block, and nothing else in the application marks a selection that way. The
   row takes the wash every other list marks its selection with, and the severity icon,
   both links and the info icon sit on it together.
   A row can carry two links, the rule's open findings and its whitelisted ones, and they
   are separate clicks: within the marked row only the one whose results are on screen is
   set in bold, dark and underlined. That is why Whitelisted is no longer bold by default
   in testsuites.hbs: bold now says "this one", and it could not while one of the two
   always wore it. */
.qa-rule-row.qa-rule-row-selected,
.qa-rule-row.qa-rule-row-selected:hover {
    background-color: #eaf2fb;
    box-shadow: -2.2em 0 0 #eaf2fb;
}

/* between a rule's two links: it belongs to neither, so it takes no part in the mark */
.qa-rule-sep {
    color: #b4bcc6;
}

.testsuite-link.qa-rule-selected,
.testsuite-link.qa-rule-selected:hover,
.testsuite-link.qa-rule-selected:focus {
    font-weight: bold;
    color: #23527c;
    text-decoration: underline;
}

.qa-results-table > tbody > tr {
    /* The whole row opens its concept. */
    cursor: pointer;
}

/* The placeholder shown before a rule is picked. It sat left-aligned in a striped row,
   reading as a result rather than as a prompt. Styled as the tree's own empty message
   ("No rules with findings in this category"): centred, muted, 14px, with room around
   it; and out of the stripe and the pointer, since there is nothing to click. */
.qa-results-table > tbody > tr > td.qa-results-empty {
    text-align: center;
    color: #777;
    font-size: 14px;
    padding: 32px 5px;
    background-color: #fff;
    border-top: 0;
    cursor: default;
}

/* The heading of the results: the rule on screen, and at the far end what can be done
   with it. The two menus used to take a line of their own under the title, in the primary
   blue and the warning orange; neither is the one thing to do here, and orange is what the
   rule list says "warning" with, so both are plain buttons now.
   The name keeps to one line and ends in an ellipsis: it stands in full, and marked, in
   the tree just above, and in its own tooltip. The counts after it are never cut. It is
   not labelled "Rule:" either; nothing else could be standing there. */
.qa-results-table .qa-results-headline {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 6px;
}

.qa-results-table .qa-results-title {
    /* A step up from the 12px this build of Bootstrap sets as the base, enough to
       read as the heading of the pane without competing with the panel title. */
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: baseline;
    font-size: 15px;
}

.qa-results-table .qa-results-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.qa-results-table .qa-results-actions {
    flex: 0 0 auto;
    display: flex;
    gap: 6px;
}

/* how many findings the title's rule has on screen: said after the name, not as part of it */
.qa-results-table .qa-results-count {
    flex: 0 0 auto;
    margin-left: 6px;
    color: #8a94a0;
    font-size: 12px;
    font-weight: normal;
    white-space: nowrap;
}

/* The filters of the results, at the size and weight of the ones over the rule list. They
   sit in a th, which is where their bold came from. They were Bootstrap columns, with 30px
   of gutter between one and the next; a flex row at the 8px the filters above keep, the
   text filter twice the width of a dropdown as it was. */
.qa-results-table > thead .form-control {
    height: 30px;
    font-weight: normal;
}

.qa-results-table .qa-results-filters {
    display: flex;
    gap: 8px;
    margin: 0;
}

.qa-results-table .qa-results-filters:before,
.qa-results-table .qa-results-filters:after {
    display: none;
}

.qa-results-table .qa-results-filters > [class*="col-"] {
    flex: 1 1 0;
    float: none;
    width: auto;
    min-width: 0;
    padding: 0;
}

.qa-results-table .qa-results-filters > .col-md-6 {
    flex-grow: 2;
}

/* The title and the filters are two header rows, each cell padded all round, under a
   region that pads again: 25px of nothing between the rule list and the first result,
   on top of the margins. The rows keep their sides and give up what stood between them. */
.qa-results-table > thead > tr:nth-child(1) > th {
    padding-top: 4px;
    padding-bottom: 0;
    /* A name that may not wrap is as wide as it is long, and a table cell grows to what it
       holds: a long rule stretched the whole table past the panel. With no width of its own
       to claim, the cell takes the columns' and the name is cut to it. */
    max-width: 0;
}

.qa-results-table > thead > tr:nth-child(2) > th {
    padding-top: 0;
    padding-bottom: 6px;
}

.qa-results-table .qa-col-suspects {
    width: 150px;
}

/* room for "Add to whitelist" on one line */
.qa-results-table .qa-col-whitelist {
    width: 140px;
}

/* ─────────────────────────────────────────────────────────────
   Inbox task header bar (open task)
   Two dense rows instead of the old six stacked lines.
   ───────────────────────────────────────────────────────────── */
.ts-taskbar-wrap {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 6px 12px;
    background: #f8f9fb;
    border-bottom: 1px solid #e5e8ee;
}

.ts-taskbar-back {
    flex: 0 0 auto;
    margin-top: 1px;
}

.ts-taskbar-body {
    flex: 1 1 auto;
    min-width: 0;
}

.ts-taskbar {
    font-size: 12px;
    color: #6b7280;
}

.ts-taskbar-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 3px 10px;
    min-height: 24px;
}

/* --- identity --- */
.ts-taskbar-id {
    flex: 0 0 auto;
    padding: 1px 6px;
    border-radius: 3px;
    background: #eef2f7;
    color: #2c3e50;
    font-family: Menlo, Consolas, monospace;
    font-size: 11px;
}

.ts-taskbar-name {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 70ch;
    overflow: hidden;
    font-size: 14px;
    font-weight: 600;
    color: #2c3e50;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.ts-taskbar-metavalue {
    color: #6b7280;
}

/* --- inline link buttons (comments, tags) --- */
.ts-taskbar-linkbtn {
    padding: 0;
    border: none;
    background: none;
    font-size: 12px;
    color: #337ab7;
}

.ts-taskbar-linkbtn:hover,
.ts-taskbar-linkbtn:focus {
    color: #23527c;
    text-decoration: none;
    outline: none;
}

.ts-taskbar-count {
    display: inline-block;
    min-width: 16px;
    padding: 1px 5px;
    border-radius: 8px;
    background: #dce6f2;
    color: #2f6ba8;
    font-size: 10px;
    font-weight: 600;
    text-align: center;
}

.ts-taskbar-tagsmenu {
    display: inline-block;
}

.ts-taskbar-tag {
    padding: 1px 6px;
    border: 1px solid #cfe9f3;
    border-radius: 3px;
    background: #eaf6fb;
    color: #2b7a99;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.4;
}

.ts-taskbar-tag-link {
    cursor: pointer;
}

.ts-taskbar-tag-link:hover {
    background: #d8eef7;
    color: #1f5f78;
    text-decoration: none;
}

/* --- navigation (pushed right) --- */
.ts-taskbar-nav {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: auto;
    white-space: nowrap;
}

.ts-taskbar-navbtn {
    padding: 0;
    border: none;
    background: none;
    font-size: 12px;
    color: #337ab7;
}

.ts-taskbar-navbtn:hover,
.ts-taskbar-navbtn:focus {
    color: #23527c;
    outline: none;
}

.ts-taskbar-counter {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.ts-taskbar-pos {
    color: #6b7280;
    font-size: 12px;
}

.ts-taskbar-check {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin: 0;
    color: #6b7280;
    font-size: 11px;
    font-weight: normal;
}

.ts-taskbar-check input[type="checkbox"] {
    margin: 0;
}

/* --- workflow row --- */
.ts-taskbar-field {
    display: inline-flex;
    align-items: center;
    min-width: 0;
    gap: 6px;
}

.ts-taskbar-fieldlabel {
    color: #9aa3ad;
}

.ts-taskbar-fieldicon {
    color: #9aa3ad;
}

.ts-taskbar-worklist {
    max-width: 32ch;
    overflow: hidden;
    color: #4a5568;
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.ts-taskbar-instructions {
    color: #9aa3ad;
    border-bottom: 1px dotted #c3cad2;
    cursor: help;
}

.ts-taskbar-sep {
    flex: 0 0 1px;
    width: 1px;
    height: 16px;
    background: #e0e4ea;
}

.ts-chip {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
}

.ts-chip-state {
    border: 1px solid #f0dcbb;
    background: #fdf3e2;
    color: #a8701a;
}

.ts-chip-user {
    border: 1px solid #d3e3f5;
    background: #eaf2fb;
    color: #2f6ba8;
}

/* For a chip that names a category rather than reporting a state: the asset's refset type
   sits beside one that does report a state, and two coloured pills in a row read as two
   things worth noticing when only one of them is. */
.ts-chip-neutral {
    border: 1px solid #e0e4ea;
    background: #f2f4f7;
    color: #4a5568;
}

/* task-level action buttons sitting inline in the taskbar: sized to the selects
   beside them instead of to Bootstrap's default button metrics */
.ts-taskbar-btn {
    height: 22px;
    padding: 0 8px;
    border-radius: 3px;
    font-size: 11px;
    font-weight: 600;
    line-height: 20px;
}

.ts-taskbar-select {
    max-width: 190px;
    height: 22px;
    padding: 0 4px;
    border: 1px solid #ccd3dd;
    border-radius: 3px;
    background: #fff;
    color: #4a5568;
    font-size: 11px;
}

/* --- last comment preview, one truncated line --- */
.ts-taskbar-comment {
    display: flex;
    align-items: center;
    min-width: 0;
    max-width: 40%;
    margin-left: auto;
}

.ts-taskbar-commentlink {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    color: #8a929c;
    cursor: pointer;
}

.ts-taskbar-commentlink:hover,
.ts-taskbar-commentlink:focus {
    color: #5a626c;
    text-decoration: none;
}

.ts-taskbar-avatar {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
}

.ts-taskbar-commentmeta {
    flex: 0 0 auto;
    font-size: 11px;
    color: #9aa3ad;
}

.ts-taskbar-commenttext {
    overflow: hidden;
    font-size: 11px;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* Every tag in the bar is the same pale chip, whatever markup produced it:
   .ts-taskbar-tag from the template, or a Bootstrap .label injected by
   loadHashtagsUl and the task-hashtag loops. Only the hue separates the two
   families — blue for concept tags, cyan for task tags — which is the encoding
   the two tag filter selects already use. */
.ts-taskbar #home-tags-hashtagsDetails .label,
.ts-taskbar #home-tags-hashtags .label,
.ts-taskbar #hashtags-details .label,
.ts-taskbar #hashtags-details-unassigned .label {
    display: inline-block;
    margin: 0 4px 0 0;
    padding: 1px 6px;
    border: 1px solid transparent;
    border-radius: 3px;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.4;
}

/* concept tags */
.ts-taskbar #home-tags-hashtagsDetails .label,
.ts-taskbar #home-tags-hashtags .label {
    border-color: #a9c8e8;
    background: #dbe8f8;
    color: #1d4f85;
}

/* task tags, the values .ts-taskbar-tag already carries */
.ts-taskbar #hashtags-details .label,
.ts-taskbar #hashtags-details-unassigned .label {
    border-color: #cfe9f3;
    background: #eaf6fb;
    color: #2b7a99;
}

/* the concept tags are the ones that can be removed, so they keep their X */
.ts-taskbar #home-tags-hashtagsDetails .label .removeTag,
.ts-taskbar #home-tags-hashtags .label .removeTag {
    top: 0;
    display: inline-block;
    margin-left: 4px;
    color: #6a94c4;
    font-size: 9px;
    line-height: 1;
    vertical-align: baseline;
    cursor: pointer;
}

.ts-taskbar #home-tags-hashtagsDetails .label .removeTag:hover,
.ts-taskbar #home-tags-hashtags .label .removeTag:hover {
    color: #1d4f85;
}

/* ─────────────────────────────────────────────────────────────
   Activity preview bar (inbox, task not opened yet)
   Same three-row taskbar language as the open-task header above,
   replacing the six stacked <p style="display:inline-block"> lines.
   ───────────────────────────────────────────────────────────── */
.ts-preview-bar {
    padding: 8px 12px;
    background: #f8f9fb;
    border-bottom: 1px solid #e5e8ee;
}

/* primary action sits with the task it acts on, pushed to the end of row 1 */
.ts-preview-actions {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
}

/* The identity line never wraps: with wrap, a long concept name sent Open task
   down to a line of its own before the name got to shrink, and the button hung
   there alone at narrow widths. Without wrap the name gives way first -- it
   already truncates with an ellipsis -- and the button keeps its place. The
   two lines under it keep wrapping; they hold several fields. */
.ts-preview-bar .ts-taskbar-line:first-child {
    flex-wrap: nowrap;
}

.ts-preview-bar .ts-taskbar-line:first-child .ts-taskbar-name {
    flex: 1 1 0;
    max-width: none;
}

.ts-preview-tags {
    flex-wrap: wrap;
    gap: 4px;
}

/* <p> kept because inbox.js reaches this block via .closest("p") */
.ts-preview-confidence {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    margin: 0;
}

.ts-preview-instructions {
    margin: 8px 0 0;
    padding: 6px 10px;
    border-left: 3px solid #d3e3f5;
    background: #f6f9fd;
    color: #4a5568;
    font-size: 12px;
}

/* inside the band now: it supplies the side padding, so this only needs the gap
   that separates the disclosures from the workflow line above them */
.ts-preview-disclosures {
    margin-top: 8px;
}

/* ─────────────────────────────────────────────────────────────
   Comment form of the task preview and of the comments modal
   Three controls of three different natures used to sit side by side in a
   12-column grid as though they were peers. They are not: the checkbox is a
   modifier of the save, and the summary assist fills the field instead of
   posting. The action cluster has to look finished without the conditional
   buttons, which is the common case.
   ───────────────────────────────────────────────────────────── */
.ts-commentform {
    margin-top: 8px;
}

.ts-commentform-assistrow {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 4px;
}

/* tinted rather than plain: it has to be findable at a glance, but in the blue
   family so it never competes with the green save button below the field */
.ts-commentform-assist {
    padding: 3px 10px;
    border: 1px solid #b9d4ee;
    border-radius: 3px;
    background: #eaf2fb;
    color: #2f6ba8;
    font-size: 12px;
    font-weight: 600;
}

.ts-commentform-assist:hover,
.ts-commentform-assist:focus {
    border-color: #8fb9e0;
    background: #dbe9f8;
    color: #23527c;
    outline: none;
}

.ts-commentform-assist .fa {
    margin-right: 3px;
}

/* the box sizes itself to what is typed (textAreaAdjust in inbox.js), so it needs
   a floor to start from and a ceiling before it starts eating the preview; past
   the ceiling it scrolls. The drag handle would only fight the auto-grow, since
   the next keystroke recomputes the height. */
.ts-commentform-input {
    min-height: 48px;
    max-height: 220px;
    overflow-y: auto;
    font-size: 12px;
    resize: none;
}

.ts-commentform-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 8px 12px;
    margin-top: 8px;
}

/* a label sitting with the button it modifies, not an action of its own */
.ts-commentform-check {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    color: #6b7280;
    font-size: 12px;
    font-weight: normal;
    cursor: pointer;
    user-select: none;
}

.ts-commentform-check input[type="checkbox"] {
    margin: 0;
}

/* ─────────────────────────────────────────────────────────────
   Translation splitter: both halves end on the same line
   The left half is itself a Bootstrap panel, so it fills the splitter's
   height. On the right the white panel is an inner element, and the
   height:100% its author gave it never resolved, because every ancestor
   up to the splitter was auto-height — so it stopped short of the left
   one. Making that chain definite is what lets the existing rule apply.
   ───────────────────────────────────────────────────────────── */
#spliter-ti > .right_panel {
    display: flex;
    flex-direction: column;
}

#spliter-ti > .right_panel > #fh-tabs2-content {
    flex: 1 1 auto;
    min-height: 0;
}

/* Concept Authoring holds the same tabs in its own splitter, and without this its
   concept panel falls back to the 85vh in its template: a height taken from the window
   rather than from the space it has, which leaves a grey strip under the panel on a
   tall screen and pushes past the bottom on a short one. The three rules below, which
   are not tied to either splitter, then size the panel to the half. */
#spliter-fh > .right_panel,
#spliter-le > .right_panel {
    display: flex;
    flex-direction: column;
}

#spliter-fh > .right_panel > #fh-tabs2-content,
#spliter-le > .right_panel > #fh-tabs2-content {
    flex: 1 1 auto;
    min-height: 0;
}

/* QA Reports holds the same tabs in a third splitter. Its concept details render into
   a canvas div rather than a .col-md-12, which the shared rules below do not reach, so
   the panel kept the 85vh of its template and stopped short of the QA results on the
   left. The canvas div joins the chain, and the panel is sized to it like the others.
   flow-root stands in for the float of .col-md-12: without it the panel's top margin
   collapses through the canvas and the pane, pushing the pane 5px down and giving the
   half a scrollbar over nothing. */
/* QA Reports opens into #wrapper, which has no height, and its splitter was written as
   width:100% and height:100% from wherever it happened to start: the height overhung the
   foot of the window by the navbar and the width overhung the right edge, so the page
   scrolled both ways behind the halves' own scrollbars. It is anchored to the viewport as
   Terminology Query is (.qu-fullpage); margin:0 undoes the .row it carries.
   The List Editor's splitter is written the same way and takes the same anchoring. */
#spliter-qa,
#spliter-le {
    position: fixed !important;
    top: 50px;
    left: 15px;
    right: 15px;
    bottom: 0;
    width: auto !important;
    height: auto !important;
    margin: 0;
}

#spliter-qa > .right_panel {
    display: flex;
    flex-direction: column;
}

#spliter-qa > .right_panel > #fh-tabs2-content {
    flex: 1 1 auto;
    min-height: 0;
}

#fh-tabs2-content > .tab-pane.active > #conceptDetails-canvasQA,
#fh-tabs2-content > .tab-pane.active > #conceptDetails-canvasQA-2 {
    height: 100%;
    display: flow-root;
}

#fh-tabs2-content > .tab-pane.active > #conceptDetails-canvasQA > .panel,
#fh-tabs2-content > .tab-pane.active > #conceptDetails-canvasQA-2 > .panel {
    height: calc(100% - 5px) !important;
    margin-bottom: 0 !important;
}

/* the QA results panel on the left keeps its heights (see the revert of the QA panel
   height work); only its bottom margin goes, so that its border meets the foot of the
   half on the same line as the concept details panel rather than 5px above it. */
#spliter-qa #batchQA_canvas > .panel {
    margin-bottom: 0 !important;
}

/* With no rule selected the results table is a single row, so the QA results frame
   stopped halfway down the half while the concept details frame beside it reaches the
   foot. Each level from the half down grows into the space left, and none shrinks below
   its content (flex-shrink 0): the frame reaches the foot when there is room, and when
   there is more than fits the half scrolls as it always did. This is a floor, not a
   height, so the tree and results boxes are not sized against it.
   The panel's inline height:100% and its body's would now resolve against a definite
   flex size, turning the panel into a second scroll region, so both go to auto. */
#spliter-qa > .left_panel {
    display: flex;
    flex-direction: column;
}

#spliter-qa > .left_panel > .tab-content {
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
}

#spliter-qa > .left_panel > .tab-content > #fh-results.active,
#spliter-qa #fh-results.active > #batchQA_canvas {
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
}

#spliter-qa #batchQA_canvas > .panel {
    flex: 1 0 auto;
    height: auto !important;
    overflow: visible !important;
}

#spliter-qa #batchQA_canvas > .panel > .panel-body {
    height: auto !important;
}

/* The Builds tab takes the same floor. Its panel ended under its last row, and with
   overflow:auto that is also where the menu of build types was cut off: a queue of one
   build left room for three of its entries. A dozen <br>s under the table used to buy
   that room. The frame now reaches the foot of the half like the QA results beside it,
   and no longer clips what opens out of it. */
#spliter-qa > .left_panel > .tab-content > #fh-builds.active {
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
}

#spliter-qa #fh-builds > .panel {
    flex: 1 0 auto;
    height: auto !important;
    overflow: visible !important;
    margin-bottom: 0 !important;
}

#spliter-qa #fh-builds > .panel > .panel-body {
    height: auto !important;
}

/* The other two builds lists (Releases manager, release statistics) sit in the flow of a
   page with no height to fill, so they get a floor instead: room for the longest menu of
   build types under a list of one, and the same freedom from clipping. */
#releases-div > .panel,
#rs-builds > .panel {
    min-height: 480px;
    overflow: visible !important;
}

#fh-tabs2-content > .tab-pane.active,
#fh-tabs2-content > .tab-pane.active > .col-md-12 {
    height: 100%;
}

/* the inner white panel declares height:100% and margin:5px inline; now that
   its height resolves, the margins push it 10px past its box and the splitter
   half grows a scrollbar over nothing. !important because both are inline, and
   the template is shared by dozens of plugins that must keep their margins. */
/* the 5px is the panel's own top margin. Its bottom margin is dropped further down,
   so only one of the two is paid for here. */
#fh-tabs2-content > .tab-pane.active > .col-md-12 > .panel {
    height: calc(100% - 5px) !important;
    margin-bottom: 0 !important;
}

/* ─────────────────────────────────────────────────────────────
   Worklist rails (left panel)
   Names are shown in full — they are the only thing distinguishing
   ar_new_drug_english_fsn_TO_ADD_candidate20260520 from its _pt_ sibling —
   so they wrap rather than truncate, and the rows are tightened to pay
   for the extra lines.
   ───────────────────────────────────────────────────────────── */
/* title, search box and the list-group boxes below all sit flush at the full
   width of #groups-panel */
.ts-wl-title {
    margin: 4px 0 8px;
    font-size: 15px;
    font-weight: 700;
    color: #2c3e50;
}

/* the left rail gets the header band the other two panels already had, so the
   three read as one system. No side padding: the title and the search box stay
   flush with the worklist boxes below them. */
.ts-wl-header {
    padding: 4px 0 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid #e0e4ea;
    background: #f8f9fb;
}

.ts-wl-search {
    padding: 0;
}

/* The panel's top actions line up with the search box and the worklist boxes
   under them. The 15px is not an inset: their parent .row already carries
   Bootstrap's -15px margin, so this only cancels it, the same way the search
   wrapper cancels it with its own 15px of padding. */
.ts-wl-actions {
    margin: 8px 0 8px 15px;
}

/* Only the worklist list scrolls. workflowAssignments.js caps the panel with a
   max-height but never sets overflow, so the list used to spill and take the
   whole page with it, carrying Create assignments, the search box and the task
   panel out of view. The panel is a column now and the list is the one child
   allowed to shrink and scroll; everything above and below it stays put. */
#worklists-panel {
    display: flex;
    flex-direction: column;
}

.ts-wl-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
}

#worklists-panel #workflow-worklists {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Same on the right: the task table is the only part that scrolls, so the
   title, the toolbar and the progress charts stay put above it, and the
   worklist rail beside it never moves. */
#tasks-panel {
    display: flex;
    flex-direction: column;
}

/* a bottom edge on the scroll region, so a row cut off at the bottom reads as
   clipped by the frame -- and scrollable -- rather than as the last row */
.ts-tm-tablewrap {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    border-bottom: 1px solid #e0e4ea;
}

#inbox-groups-body .list-group,
#worklists-panel .list-group {
    margin-bottom: 6px;
}

#inbox-groups-body .list-group-item,
#worklists-panel .list-group-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 11px;
    background-color: #f8f8f8;
    font-size: 13px;
    line-height: 1.4;
}

/* a shade under the page ground the items now share, so hover still reads */
#inbox-groups-body a.list-group-item:hover,
#worklists-panel a.list-group-item:hover {
    background-color: #eef1f5;
}

/* selection reads the same as a selected task in the middle panel: accent bar
   and a light tint, instead of Bootstrap's solid blue — which turned white
   text onto a near-white ground as soon as the row was hovered */
#inbox-groups-body a.list-group-item.active,
#inbox-groups-body a.list-group-item.active:hover,
#inbox-groups-body a.list-group-item.active:focus,
#worklists-panel a.list-group-item.active,
#worklists-panel a.list-group-item.active:hover,
#worklists-panel a.list-group-item.active:focus {
    padding-left: 9px;
    border-color: #ddd;
    border-left: 3px solid #337ab7;
    background-color: #eaf2fb;
    color: #23527c;
    font-weight: 600;
}

#inbox-groups-body a.list-group-item.ts-wl-nested.active,
#inbox-groups-body a.list-group-item.ts-wl-nested.active:hover,
#inbox-groups-body a.list-group-item.ts-wl-nested.active:focus,
#worklists-panel a.list-group-item.ts-wl-nested.active,
#worklists-panel a.list-group-item.ts-wl-nested.active:hover,
#worklists-panel a.list-group-item.ts-wl-nested.active:focus {
    padding-left: 26px;
}

/* Bootstrap turns the badge white on an active row, which disappears here */
#inbox-groups-body a.list-group-item.active > .badge,
#worklists-panel a.list-group-item.active > .badge {
    background-color: #777;
    color: #fff;
}

/* the badge stays first in the markup because inbox.js reads the count with
   find("span").first(); only its visual position moves to the end */
#inbox-groups-body .list-group-item > .badge,
#worklists-panel .list-group-item > .badge {
    order: 2;
    flex: 0 0 auto;
    float: none;
    margin-top: 1px;
}

/* The icon holds a column of its own and the name wraps beside it. As inline
   content, a long name broke at the space after the icon -- the one natural
   break available -- and dropped whole onto the next line, leaving the icon
   alone. The text node becomes an anonymous flex item that shrinks and wraps
   within the remaining width; the task manager's progress bar, appended into
   this element, takes the full width on a line of its own. */
#inbox-groups-body .ts-wl-name,
#worklists-panel .ts-wl-name {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    order: 1;
    flex: 1 1 auto;
    gap: 0 6px;
    min-width: 0;
    margin: 0;
    word-break: break-word;
    overflow-wrap: anywhere;
}

#inbox-groups-body .ts-wl-name > .fa,
#worklists-panel .ts-wl-name > .fa {
    flex: 0 0 auto;
    margin-top: 3px;
}

/* nowrap is what forces the name to shrink beside the icon instead of jumping
   to the next line whole; the one time the row must wrap is when the task
   manager appends its progress bar, which then takes a line of its own */
#worklists-panel .ts-wl-name:has(> .progressBar) {
    flex-wrap: wrap;
}

#worklists-panel .ts-wl-name > .progressBar {
    flex: 1 1 100%;
}

#inbox-groups-body .ts-wl-nested,
#worklists-panel .ts-wl-nested {
    padding-left: 28px;
}

/* full width so the collapse caret, which the shared collapsableTitle rule
   floats right, lands at the edge of the panel and not against the text */
#inbox-groups-body .list-group-item > h4,
#worklists-panel .list-group-item > h4 {
    flex: 1 1 auto;
    margin: 0;
    font-size: 13px;
    font-weight: 600;
}

/* set by the worklist search; !important because folder children carry an
   inline display the folder toggle owns */
#inbox-groups-body .ts-wl-hidden,
#worklists-panel .ts-wl-hidden {
    display: none !important;
}

#inbox-groups-body a.list-group-item.ts-wl-match,
#worklists-panel a.list-group-item.ts-wl-match {
    display: flex !important;
}

/* a search hit inside a collapsed section opens it for as long as the search
   lasts, without touching the "in" class the heading's own toggle owns */
#worklists-panel .panel-collapse.ts-wl-forceopen {
    display: block !important;
    height: auto !important;
    visibility: visible !important;
}

/* ─────────────────────────────────────────────────────────────
   Worklist items header and filter bar
   Search, state and the apply/clear buttons stay on one line; the two
   tag selects, which sit at their default value most of the time, move
   into a collapsed panel behind the tags button.
   ───────────────────────────────────────────────────────────── */
.ts-tasks-header {
    padding: 8px 10px;
    border-bottom: 1px solid #e0e4ea;
    background: #f8f9fb;
}

.ts-tasks-title {
    overflow: hidden;
    margin: 0;
    color: #2c3e50;
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.ts-tasks-filterbar {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 8px;
}

.ts-tasks-search {
    flex: 1 1 auto;
    min-width: 70px;
}

.ts-tasks-state {
    flex: 0 1 132px;
    min-width: 0;
}

.ts-tasks-tagpanel {
    margin-top: 6px;
}

/* each select keeps the colour of the family it filters: blue for concept
   tags, cyan for task tags, the same encoding the tags themselves use */
.ts-tagfilter {
    border-width: 2px;
}

.ts-tagfilter + .ts-tagfilter {
    margin-top: 5px;
}

.ts-tagfilter-concept {
    border-color: #337ab7;
}

.ts-tagfilter-task {
    border-color: #5bc0de;
}

/* a bulk action that cannot apply to the current selection stays in place,
   greyed out with the reason on hover, instead of disappearing */
.ts-bulk-unavailable {
    color: #9aa3ad;
    cursor: help;
}

.ts-bulk-unavailable select {
    background: #f5f6f8;
    color: #9aa3ad;
    font-style: italic;
}

/* bulk actions sit under the filters, above the list they act on */
.ts-tasks-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 8px;
}

.ts-tasks-actions:empty {
    display: none;
}

#loadingTags {
    margin-top: 4px;
    color: #9aa3ad;
    font-size: 11px;
    font-style: italic;
}

/* ─────────────────────────────────────────────────────────────
   Worklist items list
   The markup stays a <table> because inbox.js drives it through
   closest("tr"), find("td")[1], #more-row's colspan and the arrow-key
   navigation. Only the presentation changes: each row lays out as a
   block with the concept name on top and its metadata on a second
   line, so five stacked labels no longer cost five lines of height.
   ───────────────────────────────────────────────────────────── */
#tasks-scroll-div #tasks-list > tr {
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr);
    align-items: start;
    column-gap: 4px;
    row-gap: 3px;
    padding: 8px 10px 8px 7px;
    border-left: 3px solid transparent;
}

/* dividers as a top border on every row but the first, so the last visible
   task never carries a trailing line -- the hidden Load more row that follows
   it in the markup contributes nothing */
#tasks-scroll-div #tasks-list > tr + tr {
    border-top: 1px solid #e0e4ea;
}

/* the "No tasks" row and #more-row carry a single colspan cell */
#tasks-scroll-div #tasks-list > tr > td[colspan] {
    grid-column: 1 / -1;
}

#tasks-scroll-div #tasks-list > tr:hover {
    background: #f8fafc;
}

#tasks-scroll-div #tasks-list > tr > td {
    padding: 0;
    border: 0;
    background: none;
}

/* selection reads as an accent bar, not a green fill that collides
   with the green workflow-state label sitting inside the row */
#tasks-scroll-div #tasks-list > tr.success,
#tasks-scroll-div #tasks-list > tr.success > td {
    background: #eaf2fb;
}

#tasks-scroll-div #tasks-list > tr.success {
    border-left-color: #337ab7;
}

#tasks-scroll-div #tasks-list > tr.success .ts-task-name {
    font-weight: 600;
}

/* own gutter, spanning both content rows and centred, so the checkboxes line
   up in a single column and a run of tasks can be ticked straight down */
.ts-task-check {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: center;
    text-align: center;
}

.ts-task-check input[type="checkbox"] {
    width: 14px;
    height: 14px;
    margin: 0;
    cursor: pointer;
}

.ts-task-main {
    grid-column: 2;
    grid-row: 1;
    min-width: 0;
}

.ts-task-meta {
    display: flex;
    grid-column: 2;
    grid-row: 2;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    min-width: 0;
}

/* identity line: SCTID and the person it is assigned to, read together */
.ts-task-idline {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 10px;
    min-width: 0;
}

.ts-task-labels {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 3px 4px;
    min-width: 0;
}

.ts-task-name {
    display: -webkit-box;
    overflow: hidden;
    color: #2c3e50;
    font-size: 12px;
    line-height: 1.4;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}

.ts-task-id {
    color: #6b7280;
    font-family: Menlo, Consolas, monospace;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.ts-task-assignee {
    margin: 0;
    color: #4a5568;
    font-size: 12px;
    font-weight: 600;
}

.ts-task-assignee:empty {
    display: none;
}

.ts-task-meta .label {
    padding: 1px 6px;
    border-radius: 9px;
    font-size: 10px;
    font-weight: 600;
}

.ts-task-meta a {
    text-decoration: none;
}

/* inbox.js injects the concept tags into this anchor; it stays in the markup
   even when the concept has none, so keep it from claiming a flex gap */
.ts-task-tags:empty {
    display: none;
}

.ts-task-tags .label {
    margin-right: 3px;
}

/* the list hangs off the filter block above it: #tasks-scroll-div is a
   container-fluid, whose 15px side padding pushed the rows out of line with
   the filters, and the bulk-action row held a top margin even while its two
   controls were hidden. The rows now share the filter block's left edge and
   the gap belongs to the controls that actually use it. */
/* The header block stays put and only the list under it scrolls: the title and
   the worklist search on the left, the filters in the middle. inbox.js caps each
   panel's height and sets overflow on it, but with the list as the one child
   allowed to shrink, the panel's own scrollbar never comes into play. */
/* Scoped to the inbox because #groups-panel is also the worklist column of the Asset
   Library, which sizes and frames its columns its own way: unscoped, the padding and the
   inset hairlines below reached across and left that column 16px narrower than the band
   above it. */
#x-inbox-panel #groups-panel,
#x-inbox-panel #tasks-list-panel {
    display: flex;
    flex-direction: column;
}

#x-inbox-panel #inbox-groups-body {
    flex: 1 1 auto;
    min-height: 0;
}

/* Each column is a surface of its own, so the three read as columns whatever
   the length of their lists; before, only the content boxes were white and a
   short list left the page ground showing under it. An inset shadow rather
   than a border: the columns are Bootstrap cols sized in percentages and touch,
   so a border would change their width; the two hairlines meet as one seam. */
/* the left and middle columns keep the page ground; their white content boxes
   sit on it, and the seams below are what keep the three reading as columns.
   Only the preview takes a white surface. */
#x-inbox-panel #groups-panel,
#x-inbox-panel #tasks-list-panel,
#x-inbox-panel #task-preview-panel {
    box-shadow: inset 0 0 0 1px #e0e4ea;
}

#x-inbox-panel #task-preview-panel {
    background: #fff;
}

/* the rail sits 15px from the app edge through container-fluid; the same gap
   against the middle column keeps it symmetric instead of flush to the seam */
#x-inbox-panel #groups-panel {
    padding: 1px 15px 1px 1px;
}

/* Below 1600px the inbox grid (col-md-2 / 3 / 7) leaves the worklist rail at
   roughly 228px on a 1366px laptop, crushing worklist names into four lines.
   The rail and the item list take a little from the preview there; at 1600px
   and up the stock grid returns. Bootstrap 3 has no breakpoint between its lg
   (1200px) and a desktop, so this one is our own. */
@media (min-width: 992px) and (max-width: 1599px) {
    #x-inbox-panel #groups-panel {
        width: 20%;
    }

    #x-inbox-panel #tasks-list-panel {
        width: 27%;
    }

    #x-inbox-panel #task-preview-panel {
        width: 53%;
    }
}

/* the outer edges sit on the app's own edge and separate nothing, so the first
   column drops its left hairline and the last one its right; each keeps top,
   bottom and the seam it shares with its neighbour */
#x-inbox-panel #groups-panel {
    box-shadow: inset -1px 0 0 #e0e4ea, inset 0 1px 0 #e0e4ea, inset 0 -1px 0 #e0e4ea;
}

#x-inbox-panel #task-preview-panel {
    box-shadow: inset 1px 0 0 #e0e4ea, inset 0 1px 0 #e0e4ea, inset 0 -1px 0 #e0e4ea;
}

/* the horizontal margins are set to 0 on purpose: this div is a container-fluid,
   whose auto side margins would centre it as a flex item instead of letting it
   stretch, leaving the list narrower than the filters above it */
#tasks-scroll-div {
    flex: 1 1 auto;
    min-height: 0;
    margin: 6px 0 0;
    padding-left: 0;
    padding-right: 0;
    overflow: auto;
}

.ts-bulk-row {
    margin-top: 0;
}

.ts-bulk-row #assign-to-selected-tasks,
.ts-bulk-row #transitions-to-selected-tasks {
    margin-top: 8px;
}

#tasks-scroll-div .table {
    margin: 0;
    border: 0;
}

/* ─────────────────────────────────────────────────────────────
   Task manager table
   This one stays a real table: its columns carry meaning, unlike the
   inbox list. It takes the same chips, dividers, hover and monospaced
   SCTID so the two modules read as one product.
   ───────────────────────────────────────────────────────────── */
/* filters on one wrapping row, bulk actions on their own below, instead of a
   single form-inline soup spaced with &nbsp; */
/* one bounded block with three bands: the filters that are always there, the
   bulk actions that only exist while rows are selected, and the view/export
   actions that used to float loose under the panel */
.ts-tm-toolbar {
    margin-bottom: 10px;
    border: 1px solid #e0e4ea;
    border-radius: 4px;
    background: #f8f9fb;
}

.ts-tm-filterbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 8px;
    padding: 8px 10px;
}

/* no band of its own: every control inside is hidden until rows are selected,
   so a background here would leave an empty stripe the rest of the time */
.ts-tm-bulkbar {
    padding: 0 10px;
}

/* each label + select reads as one contextual unit rather than loose text */
.ts-tm-bulkbar > span {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 0 6px 8px 0;
    padding: 3px 4px 3px 9px;
    border: 1px solid #d3e3f5;
    border-radius: 3px;
    background: #eaf2fb;
    color: #2f6ba8;
    font-size: 12px;
    white-space: nowrap;
}

.ts-tm-bulkbar > button {
    margin: 0 0 8px;
}

.ts-tm-actionbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 10px;
    padding: 5px 10px;
    border-top: 1px solid #e0e4ea;
    background: #f8f9fb;
    border-radius: 0 0 3px 3px;
}

.ts-tm-link {
    padding: 0;
    font-size: 12px;
}

/* exports sit at the far end, away from the read-only progress links */
.ts-tm-exports {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 5px;
    margin-left: auto;
}

/* the task count belongs at the end of the filter row, not mid-sentence */
#tasks-load-text {
    margin-left: auto;
    white-space: nowrap;
}

.ts-tm-search {
    flex: 1 1 160px;
    min-width: 120px;
}

.ts-tm-select {
    flex: 0 1 150px;
    min-width: 0;
}

/* the checkbox options keep their original markup; only the Bootstrap
   block-level margins that broke the row are neutralised */
.ts-tm-opt {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin: 0;
    font-size: 12px;
    white-space: nowrap;
}

/* Bootstrap's .checkbox pulls the input out of flow with position:absolute and
   a -20px margin, paired with 20px of padding on the label. Both are undone so
   the box and its text sit on one baseline in a flex row. */
.ts-tm-opt input[type="checkbox"] {
    position: static;
    margin: 0;
}

.ts-tm-opt label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin: 0;
    padding-left: 0;
    font-weight: normal;
}

.ts-tm-bulkbar > span {
    align-items: center;
    gap: 5px;
    color: #6b7280;
    font-size: 12px;
}

.ts-tm-bulkbar select {
    max-width: 200px;
    height: 28px;
    padding: 0 5px;
    border: 1px solid #ccd3dd;
    border-radius: 3px;
    font-size: 12px;
}

#tasks-panel .table {
    border: 0;
}

#tasks-panel .table > thead > tr > th {
    padding: 6px 8px;
    border: 0;
    border-bottom: 2px solid #e0e4ea;
    background: #f8f9fb;
    color: #6b7280;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .03em;
}

#tasks-panel .table > tbody > tr > td {
    padding: 8px;
    border: 0;
    border-bottom: 1px solid #e0e4ea;
    vertical-align: top;
}

#tasks-panel .table > tbody > tr:hover > td {
    background: #f8fafc;
}

.ts-tm-check {
    width: 30px;
}

.ts-tm-check input[type="checkbox"] {
    width: 14px;
    height: 14px;
    margin: 0;
    cursor: pointer;
}

/* labels flow inline and wrap instead of one per line */
.ts-tm-labels {
    max-width: 200px;
}

.ts-tm-labels .label {
    display: inline-block;
    margin: 0 3px 3px 0;
    padding: 1px 6px;
    border-radius: 9px;
    font-size: 10px;
    font-weight: 600;
}

.ts-tm-labels a {
    text-decoration: none;
}

/* the term takes the slack; the id and the buttons hold fixed slots so they
   line up down the column instead of trailing the end of a wrapped name */
.ts-tm-componentrow {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.ts-tm-term {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.ts-tm-name {
    color: #2c3e50;
    font-size: 13px;
}

.ts-tm-id {
    flex: 0 0 auto;
    width: 122px;
    color: #9aa3ad;
    font-family: Menlo, Consolas, monospace;
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

.ts-tm-componentrow .commentsTask,
.ts-tm-componentrow .showHideBtn {
    flex: 0 0 auto;
    padding: 0;
    line-height: 1.2;
}

/* inert in this table: the handler only exists in the reports panel */
.ts-tm-componentrow .showHideBtn:empty {
    display: none;
}

.ts-tm-instructions:empty {
    display: none;
}

.ts-tm-worklist,
.ts-tm-assignee {
    color: #4a5568;
    font-size: 12px;
}

.ts-tm-date {
    width: 1%;
    color: #6b7280;
    font-size: 11px;
    white-space: nowrap;
}

/* concept name in dynamic authoring/translation tabs: truncate, full text on hover */
.ts-tab-term {
    display: inline-block;
    max-width: 22ch;
    overflow: hidden;
    vertical-align: bottom;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* concept details panel header: never wraps, full term in the title tooltip */
.ts-panel-title {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* QA task header: the suspect id list can be long */
.ts-taskbar-suspects {
    max-width: 90ch;
    overflow: hidden;
    color: #6b7280;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* Rule info modal
   The QA panel's rule-info dialog. Reads top-down: what the rule asks for, how to fix it,
   and only then the identifiers the technical team needs. */
.qa-rule-info-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 14px;
}

.qa-rule-info-chip {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 2px;
    border: 1px solid #d8dee6;
    color: #6b7280;
    background: #f6f7f9;
    white-space: nowrap;
}

.qa-rule-info-chip.severity-error {
    color: #9e2b22;
    border-color: #e0b4b0;
    background: #fdf3f2;
}

.qa-rule-info-chip.severity-warning {
    color: #87590f;
    border-color: #e6cf9e;
    background: #fdf8ee;
}

.qa-rule-info-description {
    font-size: 14px;
    line-height: 1.6;
    color: #333;
    margin: 0 0 14px;
}

.qa-rule-info-resolution {
    border-left: 3px solid #337ab7;
    background: #f4f8fb;
    padding: 10px 14px;
    margin: 0 0 16px;
}

.qa-rule-info-resolution .qa-rule-info-label {
    margin-bottom: 4px;
}

.qa-rule-info-resolution p {
    margin: 0;
    font-size: 13px;
    line-height: 1.55;
    color: #333;
}

.qa-rule-info-label {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: #98a2b0;
}

.qa-rule-info-footer {
    border-top: 1px solid #e6ebf1;
    padding-top: 12px;
}

.qa-rule-info-footer .qa-rule-info-item {
    margin-bottom: 8px;
}

.qa-rule-info-footer .qa-rule-info-item:last-child {
    margin-bottom: 0;
}

.qa-rule-info-footer .qa-rule-info-value {
    font-family: Menlo, Consolas, monospace;
    font-size: 12px;
    line-height: 1.5;
    color: #556070;
    word-break: break-word;
}

.qa-rule-info-note {
    font-size: 12.5px;
    line-height: 1.5;
    color: #8a6d3b;
    background: #fcf8e3;
    border: 1px solid #faebcc;
    border-radius: 2px;
    padding: 9px 12px;
    margin: 0 0 14px;
}

/* QA findings modal, in concept details. One card per rule that fired on the concept:
   what it asks for, how to fix it, and the runner's own name underneath. */
.qa-findings-header {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-bottom: 12px;
    border-bottom: 1px solid #e6ebf1;
    margin-bottom: 4px;
}

.qa-findings-card {
    padding: 16px 0;
    border-bottom: 1px solid #e6ebf1;
}

.qa-findings-card:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.qa-findings-card-name {
    font-size: 15px;
    font-weight: 600;
    line-height: 1.4;
    color: #222;
    margin: 0 0 8px;
}

.qa-findings-card .qa-rule-info-description {
    margin-bottom: 12px;
}

.qa-findings-card .qa-rule-info-footer {
    border-top: none;
    padding-top: 0;
}

.qa-findings-count {
    color: #6b7280;
    background: #f6f7f9;
    border-color: #d8dee6;
}

/* Asserted/inferred switch in the concept details toolbar. A segmented control on a track,
   so the pair reads as one setting rather than as two action buttons, with colour only on
   the segment in use. Scoped to this control: .viewButton is also used elsewhere.
   The radius needs !important because Bootstrap's .btn-group corner rules are more
   specific and would square off the segments. */
/* A grid rather than a flex row, because the segments must all come out the same width:
   placeViewSwitchThumb positions the marker from the segment count alone, so unequal
   segments put it over the wrong label. Under flex the switch shrank to fit, which left no
   free space to hand out, so each segment kept its own text width. grid-auto-columns: 1fr
   sizes every track to the widest one even while the switch is sizing to its content. The
   marker is absolutely positioned, so it stays out of the track count. */
.cd-view-switch {
    position: relative;
    display: inline-grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    background: #e4e7eb;
    border-radius: 4px;
    padding: 2px;
}

/* The vertical padding comes down from btn-sm's 5px so the switch fits the heading row
   every other panel uses — see .ts-panel-headrow. 3.75px leaves each segment 24px tall,
   the floor for a click target, and the horizontal padding is untouched, so the segments
   keep their width. */
.cd-view-switch .viewButton {
    position: relative;
    z-index: 1;
    padding-top: 3.75px;
    padding-bottom: 3.75px;
    border: 0;
    background: transparent;
    color: #666;
    box-shadow: none;
    border-radius: 3px !important;
    transition: color .18s ease;
}

.cd-view-switch .viewButton:hover {
    color: #333;
}

/* The colour of the selected segment comes from the marker below, which slides between
   segments, so the button itself only takes the text colour. */
.cd-view-switch .viewButton.btn-primary {
    background: transparent;
    color: #fff;
}

.cd-view-switch-thumb {
    position: absolute;
    top: 2px;
    bottom: 2px;
    left: 2px;
    width: 0;
    opacity: 0;
    background: #337ab7;
    border-radius: 3px;
    transition: left .18s ease, width .18s ease, opacity .18s ease;
}

/* Asserted and inferred side by side, driven by the "Both" segment of the view switch.
   Everything here is off until the Summary tab carries .cd-both-view, so the single-view
   layout is byte for byte the one that was there before: the inferred columns are hidden
   and the asserted ones keep the Bootstrap widths written on them. Only under
   .cd-both-view do the widths get overridden, which is why the rows declare how many
   columns they end up with rather than each column declaring its own width twice. */
.cd-split-extra,
.cd-split-label {
    display: none;
}

.cd-both-view .cd-split-extra,
.cd-both-view .cd-split-label {
    display: block;
}

.cd-both-view .cd-split-2 > .cd-split-main,
.cd-both-view .cd-split-2 > .cd-split-extra {
    width: 50%;
    float: left;
}

/* A column with no per-form counterpart — the descriptions panel — is not something the two
   sides can be compared on, so under "Both" it takes the whole row and the halves that do
   compare wrap onto the line below it. The columns are floated, so no other rule is needed
   to make them wrap. */
.cd-both-view .cd-split-fixed {
    width: 100%;
    margin-bottom: 10px;
}

/* These boxes cap their height and scroll inside themselves, which suits a single column of
   content. Under "Both" they hold two columns and the caps turn them into small scrolling
   windows stacked inside a tab that already scrolls — scrollbars within scrollbars. The caps
   go, and the tab does the one scroll. The values are written inline on the elements, which
   is why overriding them needs !important. */
.cd-both-view .cd-parents-box,
.cd-both-view .cd-attrs-row,
.cd-both-view .cd-children-box {
    max-height: none !important;
    overflow: visible !important;
}

/* The concept tags and the workflow label above this panel are floated right, and what used
   to keep them off it was its own overflow:auto: that established a block formatting
   context, and such a box is never overlapped by a float. Dropping the scroll dropped that
   side effect with it and the tags landed on top of the panel. Clearing restores the same
   result — the panel starts below them — without bringing the scrollbar back. */
.cd-both-view .cd-parents-box {
    clear: both;
}

/* The count beside the Children heading is the length of the asserted children alone. As the
   heading of a box that holds one column that is what it names, but under "Both" the box
   holds two and a single figure over them names neither, so it is hidden. */
.cd-both-view .cd-children-count {
    display: none;
}

/* The three blocks of the Summary tab are separated by 10px written inline on them, and that
   figure is the same wherever the panel is put. It reads as enough room between two boxes as
   wide as the Concept Authoring panel and as none at all between two as narrow as the ones
   the Asset Library gives the panel, where the borders all but meet. What decides it is the
   width of the panel, not of the window — both cases happen at the same viewport — so a
   media query cannot tell them apart and the tab pane is made a query container instead.
   The threshold is Bootstrap's own md breakpoint: the width at which the grid considers a
   container roomy enough to divide, which is the same judgement being made here. The values
   are inline on the elements, hence !important.
   The container is named off the ids the plugin already writes rather than a class added to
   the template, because the compiled templates are served under a cachebreaker that only a
   release moves: a class put there would not reach a browser that has them cached, and the
   query would then have no container and quietly match nothing. */
[id^="details-tab-content-"] > [id^="home-"] {
    container-type: inline-size;
}

@container (max-width: 991px) {
    .cd-parents-box {
        margin-bottom: 18px !important;
    }

    .cd-children-box {
        margin-top: 18px !important;
    }
}

/* Additional relationships in the Summary: a read-only mirror of the Annotations tab's list,
   under the relationships box and as wide as it. They do not define the concept, so the box
   is dashed and plain rather than the solid blue of the defining ones. They are not stated or
   inferred either, so under "Both" the box takes the whole row instead of picking a side.
   It is a column of the attributes row floated right: a right float cannot sit beside the
   relationships column, so it drops to just under it, next to the concept box when that one
   is taller. As a row of its own it started below the concept box and left a gap. */
.cd-addrels-col {
    margin-top: 10px;
    padding-left: 6px;
    padding-right: 6px;
}

@media (min-width: 992px) {
    .cd-addrels-col {
        float: right;
    }

    /* With the box shown, the concept box beside it reaches down to its bottom, so the left
       side is as tall as the two boxes on the right together. Floats cannot do that, so the
       row becomes a grid where the concept box spans both rows. Only outside "Both", where
       the concept box has a row of its own. The second row takes whatever height the
       concept box needs beyond the relationships, so they never stretch. The row's
       clearfix pseudo-elements would be grid items, hence hidden. */
    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels {
        display: grid;
        grid-template-columns: 1fr 1fr;
        grid-template-rows: auto 1fr;
    }

    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels::before,
    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels::after {
        display: none;
    }

    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels > div {
        width: auto;
    }

    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels > .cd-split-fixed {
        grid-column: 1;
        grid-row: 1 / span 2;
    }

    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels > .cd-split-fixed > div {
        height: 100%;
    }

    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels > .cd-split-main {
        grid-column: 2;
        grid-row: 1;
    }

    :not(.cd-both-view) > .cd-attrs-row.cd-has-addrels > .cd-addrels-col {
        grid-column: 2;
        grid-row: 2;
        align-self: start;
    }
}

.cd-both-view .cd-addrels-col {
    width: 100%;
    float: left;
    clear: both;
}

.cd-addrels-box {
    border: 1px dashed #a9c8e8;
    border-radius: 4px;
    padding: 6px 8px;
    background: #fff;
}

.cd-addrels-head {
    margin-bottom: 4px;
    font-size: 11px;
    font-weight: 600;
    color: #4a5568;
}

.cd-addrels-head span {
    font-weight: normal;
    font-style: italic;
    color: #9aa3ad;
}

.cd-addrels-item {
    padding: 1px 0;
}

.cd-addrels-item .sct-drag-icon {
    line-height: .5;
}

.cd-addrels-item .selectConceptRel {
    cursor: pointer;
}

/* Relationship targets in the Summary (the relationships box and this one) open on a single
   click, so they read as links. The types keep their double click and stay plain text. */
[id^="home-roles-"] .cd-rel-target,
.cd-addrels-item .cd-rel-target {
    color: #337ab7;
    cursor: pointer;
}

[id^="home-roles-"] .cd-rel-target:hover,
.cd-addrels-item .cd-rel-target:hover {
    color: #23527c;
    text-decoration: underline;
}

.cd-addrels-group {
    margin: 4px 0;
    padding: 3px 5px;
    border: 1px solid #e0e4ea;
    border-radius: 3px;
}

/* Reserves the height of the asserted column's "Axiom N" line in the inferred column so the
   two columns start their content on the same line. Hidden rather than removed, because what
   has to match is the height of the real label, not a number guessed here. */
.cd-axiom-spacer {
    visibility: hidden;
}

/* The column headings are the only thing telling the two sides apart once the switch stops
   naming a single form, so they stay put while the column itself scrolls. */
.cd-split-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: #999;
    margin-bottom: 3px;
}

.cd-both-view .cd-split-main {
    border-right: 1px solid #e4e7eb;
}

/* The title and its controls sit on one centred line, the same arrangement .ts-panel-headrow
   uses for the panel header above. Without it the controls column would only centre against
   its own height, not against the title beside it, and the group would need a hand-tuned top
   margin to look level — which is what it had. */
.cd-desc-header {
    display: flex;
    align-items: center;
}

/* the clearfix of .row would count as flex items here */
.cd-desc-header:before,
.cd-desc-header:after {
    display: none;
}

.cd-desc-header > .col-md-8 {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}

/* The concept's own controls: copy, briefcase, favourites, and the fold chevron under "Both",
   with the country flag on its own line beneath them. They were floated, which lines boxes up
   by their tops, so the flag — a block at its own size, against 13px glyphs — sat proud of the
   row and the spacing came from whatever padding each control happened to carry. Stacking the
   flag instead of squeezing it into the line lets it keep the size that makes it readable. */
.cd-concept-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    flex: 0 0 auto;
    width: auto;
}

.cd-concept-buttons {
    display: flex;
    align-items: center;
    gap: 8px;
}

.cd-concept-actions > *,
.cd-concept-buttons > * {
    margin: 0;
}

/* Centring the row is not enough while the boxes being centred are of different shapes: the
   briefcase and the chevron are btn-xs and carry its padding, the star is a bare link, and the
   copy icon sits alone in a zero-padding toggle, so that button centres an empty line box
   while the icon hangs below it. Levelling the boxes here — one line box each, no padding, one
   glyph size, and the 1px lift glyphicons are drawn with turned off — puts the four icons on
   one line, and the row's own align-items keeps them there. */
.cd-concept-buttons > *,
.cd-concept-buttons .dropdown-toggle {
    display: flex;
    align-items: center;
    padding: 0;
    line-height: 1;
}

.cd-concept-buttons .glyphicon,
.cd-concept-buttons .fa {
    top: 0;
    font-size: 13px;
    line-height: 1;
}

/* These are icons on a coloured bar, not text: the ring Bootstrap draws around a focused .btn
   and the underline it puts under a link on hover both land on the white glyph and read as
   damage. The hover colour is left to the inline white each control already carries. */
.cd-concept-buttons a,
.cd-concept-buttons .btn,
.cd-concept-buttons a:hover,
.cd-concept-buttons .btn:hover,
.cd-concept-buttons a:focus,
.cd-concept-buttons .btn:focus,
.cd-concept-buttons .btn.focus,
.cd-concept-buttons .btn:active:focus,
.cd-concept-buttons .btn.active:focus {
    outline: none;
    text-decoration: none;
}

/* The flag is the only one with a size of its own; it must not be squeezed to fit. */
.cd-concept-actions .cd-concept-flag,
.cd-concept-actions .phoca-flagbox {
    flex: none;
    display: block;
}

/* The descriptions panel folds to its title row. The control only exists under "Both": in
   single view the panel shares its row and there is nothing to reclaim by hiding it. */
.cd-desc-toggle {
    display: none;
}

/* flex, not inline-block: this is more specific than the rule that levels the row's controls,
   so inline-block here would leave the chevron alone as a box of its own height. */
.cd-both-view .cd-desc-toggle {
    display: flex;
}

/* The whole title row is the target under "Both". Everything inside it is clickable one way
   or another, so the pointer it inherits is right for the controls too. */
.cd-both-view .cd-desc-header {
    cursor: pointer;
    user-select: none;
}

/* Scoped to "Both" on purpose: the collapsed state is remembered across concept loads, and
   without this the panel would also come up folded in single view, where the control that
   unfolds it is hidden.

   The fold is animated by taking a single grid row from its content height down to nothing.
   display:none cannot be animated and a max-height cap would have to guess a height the
   description list does not have — it varies from a couple of lines to a couple of dozen —
   and would spend most of the transition finishing a move the eye already saw. A 0fr row
   ends up exactly at the content height with nothing measured. Where the transition is not
   supported the row still collapses, just without the animation, which is what this did
   before. The inner wrapper does the clipping; min-height:0 is what lets a grid item shrink
   below its content at all. */
.cd-both-view .cd-desc-body {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows .18s ease;
}

.cd-both-view .cd-desc-collapsed .cd-desc-body {
    grid-template-rows: 0fr;
}

.cd-both-view .cd-desc-body-inner {
    overflow: hidden;
    min-height: 0;
}
/* Concept details header: the toolbar keeps to one line whatever its width, and the title
   gives up the space it needs, shortening with an ellipsis. Without this the grid columns
   split the header by a fixed ratio, so in a narrow panel such as the walker the toolbar
   ran out of room and wrapped onto a second line, making the header taller. */
/* The minimum is what makes every heading the same height whatever its strip holds. The
   panels settled at three: 32px where the controls are btn-links carrying the inline
   padding:2px this app writes on them, 40px in Development Queries, whose help link was
   the one without it and so took Bootstrap's 6px/12px, and 26px in Favorites, which has
   no controls at all and shrank to its line of text — a 6px jump every time that tab was
   picked next to Search and Taxonomy.

   28px, not the 23px the text-only strips sit on, because the row has to fit the largest
   control any heading holds: the asserted/inferred/both switch in Concept Details, which
   left that one panel 7.4px taller than whatever sat beside it. Every heading lands on
   37px, which is as low as the pair can go: the switch gives up 2.5px per button to get
   there and lands exactly on the 24px a click target wants. Holding the old 32px heading
   would have taken the buttons down to 18.5px, a third of their height, to keep a row
   sized for a line of text.
   HOW TO REVERT: 23px here, and the switch's padding-top/bottom back to 5px below; the
   headings then go back to 32px with Concept Details standing 7.4px proud of them. */
.ts-panel-headrow {
    display: flex;
    align-items: center;
    min-height: 28px;
}

/* the same 2px, for any control that was written without it. Direct children only, and
   anything carrying its own inline padding — every control in the concept details
   toolbar — keeps what it has. */
.ts-panel-headrow > .text-right > .btn-link {
    padding: 2px;
}

/* the clearfix of .row would count as flex items here */
.ts-panel-headrow:before,
.ts-panel-headrow:after {
    display: none;
}

.ts-panel-headrow > .ts-panel-title {
    flex: 1 1 auto;
    width: auto;
    min-width: 0; /* lets the ellipsis kick in inside a flex item */
}

.ts-panel-headrow > .text-right {
    flex: 0 0 auto;
    width: auto;
    white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────
   Panels in the left half of the splitter: fill the half, and scroll only once
   The splitter gives its half position:absolute, height:100% and overflow:auto,
   and the concept details panel inside asks for height:85vh with a scrollbar of
   its own. Whenever 85vh plus the tab strip is taller than the half, both scroll.
   Same cure as #spliter-ti > .right_panel above: make the chain a definite height
   so the panel fills the space instead of overflowing it. The 10px pays for the
   panel's inline margin:5px, and !important is needed because its height is inline
   too. Every tab of this half is covered: each one used to stop at the height of its
   own content, leaving the panel border partway down with empty space under it.
   ───────────────────────────────────────────────────────────── */
#spliter-fh > .left_panel,
#spliter-le > .left_panel {
    display: flex;
    flex-direction: column;
}

/* the left half is itself a Bootstrap panel, so it drew a frame around the tab strip
   and the panel inside drew another. The two ran together down the sides, which is
   what made those edges look twice as thick, and at the bottom they showed as two
   lines 5px apart while the right half, which has no outer panel, showed one. The
   outer frame goes: the panel inside is the only one that needs to be seen, and with
   the outer border gone both halves end their panel on the same line. That line used
   to stop 5px above the foot of the splitter bar, which runs the full height and so
   showed as a tail below it, hence the bottom margins dropped on both panels. */
#spliter-fh > .left_panel.panel {
    border: 0;
    box-shadow: none;
}

#spliter-fh > .left_panel > .tab-content,
#spliter-le > .left_panel > .tab-content {
    flex: 1 1 auto;
    min-height: 0;
}

#spliter-fh > .left_panel > .tab-content > .tab-pane.active,
#spliter-le > .left_panel > .tab-content > .tab-pane.active {
    height: 100%;
    display: flex;
    flex-direction: column;
}

/* letting flex size the panel keeps its inline margins inside the box: working the
   height out by hand left a few pixels hanging past the bottom, enough for the half
   to keep a scrollbar of its own. !important because the 85vh is inline. */
#spliter-fh > .left_panel > .tab-content > .tab-pane.active > .panel,
#spliter-le > .left_panel > .tab-content > .tab-pane.active > .panel {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    display: flex;
    flex-direction: column;
    margin-bottom: 0 !important;
}

/* the taxonomy and favorites bodies ask for height:100% inline, which used to
   resolve to auto because the panel had no definite height. Now that it has one,
   that 100% is the whole panel and lands under the heading and the view bar, so
   the panel overflows by exactly their height and shows a scrollbar it does not
   need. Let flex size the body instead, and let it carry the scroll so the
   heading and the view bar stay put. */
#spliter-fh > .left_panel > .tab-content > .tab-pane.active > .panel > .panel-body,
#spliter-le > .left_panel > .tab-content > .tab-pane.active > .panel > .panel-body {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    overflow: auto;
}

/* the tree wrapper inside the taxonomy body played the same trick one level down:
   height:100% of the body plus a 15px bottom margin, which is 15px more than the
   body can hold once the body has a definite height of its own. Those two came off
   the wrapper's inline style and into .ts-tree-root, unchanged, so that the rule
   below can drop them where the body sizes itself. */
.ts-tree-root {
    height: 100%;
    margin-bottom: 15px;
}

#spliter-fh > .left_panel > .tab-content > .tab-pane.active > .panel > .panel-body > .ts-tree-root,
#spliter-le > .left_panel > .tab-content > .tab-pane.active > .panel > .panel-body > .ts-tree-root {
    height: auto;
    margin-bottom: 0;
}

/* ─────────────────────────────────────────────────────────────
   Search panel, left column
   The options were three loose button groups that flowed inline, so their
   different widths left a ragged edge, and each facet was a full panel —
   heading, body and list group — nested inside a column that already had a
   frame of its own. The chrome is stripped here rather than in the template so
   the ids and classes searchPlugin.js binds to stay exactly where they were.
   ───────────────────────────────────────────────────────────── */
.ts-sf-column {
    flex: 0 0 220px;
    min-width: 0;
    height: 100%;
    overflow: auto;
    padding: 8px;
    border: 1px solid #e0e4ea;
    border-radius: 4px;
    background: #fbfcfd;
    transition: flex-basis 0.18s ease, padding 0.18s ease;
}

/* ─────────────────────────────────────────────────────────────
   Collapsing the options column

   The column is 220px of a panel that is mostly a list of terms and their
   translations, and the options in it are set once and then left alone, so it can
   be folded away to a rail: the arrow that brings it back, the word "Options" on
   its side, and a count of the filters the search is carrying. The filter chips
   themselves are moved into the results column by searchPlugin.js, because a chip
   says which filter is applied and the count only says how many.

   The width lives here rather than on the element so the collapsed rule can win
   without !important; that is why .ts-sf-column carries the layout the template
   used to declare inline.
   ───────────────────────────────────────────────────────────── */
.ts-sf-column-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    /* no margin above: the header has to land on the same line as the arrow does on the
       rail, so that folding and unfolding does not shift it */
    margin: 0 0 10px;
    cursor: pointer; /* the title folds the column, not just the arrow beside it */
}

.ts-sf-column-head h4 {
    margin: 0;
}

.ts-sf-toggle {
    padding: 0 4px;
    color: #7b8794;
    line-height: 1.4;
}

.ts-sf-toggle:hover,
.ts-sf-toggle:focus {
    color: #2c3e50;
    text-decoration: none;
}

/* Bootstrap rings the button after a click, which on a control that folds a panel reads as
   a state the panel is in. Only the mouse case is dropped, the way the filter chips do it:
   :focus-visible still matches when the browser judges the focus worth drawing, so a
   keyboard user keeps the outline. */
.ts-sf-toggle:focus:not(:focus-visible),
.ts-sf-toggle:active:focus:not(:focus-visible) {
    outline: none;
}

.ts-sf-column.ts-sf-collapsed {
    flex: 0 0 30px;
    padding: 8px 0;
    overflow: hidden;
    cursor: pointer; /* the whole rail opens it, not just the arrow */
}

/* the state is restored from localStorage once the column is already on screen, so the
   first application of it has to be silent or the panel folds itself as the page opens */
.ts-sf-column.ts-sf-instant {
    transition: none;
}

.ts-sf-collapsed .ts-sf-column-head {
    justify-content: center;
}

.ts-sf-collapsed .ts-sf-column-head h4,
.ts-sf-collapsed .ts-sf-options,
.ts-sf-collapsed .ts-sf-facets {
    display: none;
}

.ts-sf-rail {
    display: none;
    flex-direction: column;
    align-items: center;
}

.ts-sf-collapsed .ts-sf-rail {
    display: flex;
}

.ts-sf-rail-label {
    /* reads down the rail with the letters still upright, rather than the whole word
       turned on its side */
    writing-mode: vertical-rl;
    text-orientation: upright;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-size: 10px;
    color: #7b8794;
    white-space: nowrap;
}

.ts-sf-rail-badge {
    display: block; /* jQuery clears the inline display it is hidden with, so this is what it shows as */
    min-width: 18px;
    margin-bottom: 8px;
    padding: 0 5px;
    border-radius: 9px;
    background: #5b9bd5;
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    line-height: 17px;
    text-align: center;
}

/* the chips, once they are out of the column: a single row above the results
   instead of a stack, and no space taken at all while the column is open. */
.ts-sf-applied-outside:not(:empty) {
    margin: 6px 0 2px;
}

.ts-sf-applied-outside .ts-sf-applied {
    display: inline-block;
    margin: 0 2px 0 0;
}

/* one control per line, all the same width */
.ts-sf-options > .btn-group {
    width: 100%;
    margin-bottom: 8px;
}

.ts-sf-options > .btn-group > .btn {
    width: 100%;
    text-align: left;
    white-space: normal;
}

.ts-sf-options > .btn-group > .btn .caret {
    float: right;
    margin-top: 7px;
}

.ts-sf-options .checkbox {
    margin: 10px 0;
}

.ts-sf-options .checkbox label {
    display: inline-flex;
    align-items: center;
    padding-left: 0;
}

/* Two ways of centring the box against its text, because only one of them applies
   depending on whether the inline-flex above survives the other stylesheets: as a flex
   item align-items does it, and as an inline box vertical-align does. */
.ts-sf-options .checkbox input[type="checkbox"] {
    position: static !important;
    flex: 0 0 auto;
    margin: 0 8px 0 0 !important;
    vertical-align: middle !important;
    top: auto;
}

/* Clicking a filter, or the cross that drops one, should not leave a focus ring behind.
   Only the mouse case is dropped: :focus-visible still matches when the browser judges
   the focus worth showing, so keyboard users keep their outline. */
.ts-sf-chip a:focus:not(:focus-visible),
.ts-sf-section .list-group-item > a:focus:not(:focus-visible) {
    outline: none;
}

.ts-sf-options {
    margin-bottom: 18px !important;
}

/* the column clips anything that leaves it, so the menu stays inside and its longest
   entries wrap instead of being cut off at the edge. */
.ts-sf-options .dropdown-menu {
    width: 100%;
}

.ts-sf-options .dropdown-menu > li > a {
    white-space: normal;
    line-height: 1.35;
    padding: 5px 12px;
}

/* the two dropdowns that show the current setting: blue-grey instead of green,
   which was louder than anything else on the panel */
.ts-sf-setting {
    background: #eef2f7;
    border: 1px solid #cfd8e3;
    color: #2c3e50;
}

.ts-sf-setting:hover,
.ts-sf-setting:focus,
.ts-sf-setting.active,
.open > .ts-sf-setting {
    background: #e3e9f1;
    border-color: #b9c6d6;
    color: #1f2d3d;
}

/* facets read as sections, not as panels inside a panel */
.ts-sf-section.panel {
    border: 0;
    box-shadow: none;
    background: none;
    margin: 0 0 22px;
}

.ts-sf-section > .panel-heading {
    padding: 0 0 6px;
    background: none;
    border: 0;
    border-bottom: 1px solid #e0e4ea;
    margin-bottom: 8px;
}

.ts-sf-section > .panel-heading > .panel-title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #6b7280;
}

.ts-sf-section > .panel-body {
    padding: 0;
}

.ts-sf-section .list-group {
    margin: 0;
}

/* a row per value: the label takes the room it needs and the count sits at the
   end. As a float the count came first in the markup and long labels wrapped
   underneath it. */
.ts-sf-section .list-group-item {
    display: flex;
    align-items: baseline;
    gap: 10px;
    border: 0;
    background: none;
    padding: 6px 0;
    line-height: 1.35;
}

/* the module and refset names run to three lines, so the rows need telling apart */
.ts-sf-section .list-group-item + .list-group-item {
    border-top: 1px solid #f0f2f6;
}

.ts-sf-section .list-group-item > a {
    order: 1;
    flex: 1 1 auto;
    min-width: 0;
    color: #2c3e50;
}

.ts-sf-section .list-group-item > a:hover {
    color: #1f2d3d;
}

.ts-sf-section .list-group-item > .badge {
    order: 2;
    float: none;
    flex: 0 0 auto;
    background: #eef1f5;
    color: #6b7280;
    font-weight: 600;
}

/* filters already applied, as chips rather than red headings */
.ts-sf-applied {
    margin: 0 0 6px;
    font-size: 0; /* swallows the whitespace between chips */
}

.ts-sf-chip {
    display: inline-block;
    font-size: 12px;
    font-weight: 600;
    white-space: normal;
    text-align: left;
    background: #dfe7f0;
    color: #2c3e50;
    border: 1px solid #c6d3e2;
    border-radius: 10px;
    padding: 3px 8px;
    margin: 0 4px 4px 0;
}

.ts-sf-chip a {
    color: #6b7280 !important;
    margin-left: 4px;
}

.ts-sf-chip a:hover {
    color: #c0392b !important;
}

/* The results were a bordered panel holding a fully bordered table, a frame inside a
   frame inside the panel. Rows are told apart by a line between them and the two
   columns by a lighter one, with nothing drawn around the outside. The favorites list
   is the same kind of list and carries the same class, which is why the name is not
   the search panel's. */
.ts-sf-results,
.ts-list-box {
    border: 0;
    box-shadow: none;
    background: none;
}

.ts-list-table {
    margin-bottom: 0;
}

.ts-list-table > tbody > tr > td {
    border: 0;
    border-bottom: 1px solid #eef0f4;
    padding: 7px 10px;
    vertical-align: top;
}

.ts-list-table > tbody > tr > td + td {
    border-left: 1px solid #f2f4f7;
}

/* -------------------------------------------------------------
   Rows that open a concept: search results and favorites

   Both lists behave the same way now — the whole row is the click target, not just
   the term — so both have to look the same on the way in. The paint is Bootstrap's
   own .table-hover, which the favorites table already carried and the two search
   tables now do as well, so an inactive concept keeps its red on hover instead of
   turning grey. .ts-rowclick supplies the one thing that class does not, and marks
   which tables have the behaviour: .resultRow is used by four other plugins whose
   rows respond only on the term, and a pointer over their dead space would lie.
   ------------------------------------------------------------- */
.ts-rowclick > tbody > tr.resultRow,
.ts-rowclick > tbody > tr.fav-row,
.ts-rowclick > tbody > tr.le-row {
    cursor: pointer;
}

/* The favourites toolbar. The three buttons ask for about 390px, more than the column
   usually has, and set inline the third dropped to a line of its own flush under the first,
   with no space between the lines. As a wrapping row they keep their labels and size, and
   whatever wraps sits under the others with the same gap that separates them. */
.fav-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 2px 2px 6px;
}

/* The favourite's remove cross sat floated right in the concept id's cell, which is only as
   wide as the id, so it fell to a line of its own under it, in link blue. It now follows
   the id on the same line, in the grey and the hover red of the remove link on the search
   chips, so it reads as a quiet control of the row rather than as its loudest mark. The
   class the click handler binds to stays on the glyph; only its float is undone. The
   briefcase rows carry the same cross and take the same rules. */
.ts-list-table > tbody > tr.fav-row > td:last-child,
.ts-list-table > tbody > tr.briefcase-item-row > td:last-child {
    width: 1%;
    white-space: nowrap;
}

.fav-row .ts-row-action,
.briefcase-item-row .ts-row-action {
    margin-left: 8px;
    color: #b0b7c1;
}

.fav-row .ts-row-action > .glyphicon,
.briefcase-item-row .ts-row-action > .glyphicon {
    float: none !important;
    top: 2px;
}

.fav-row .ts-row-action:hover,
.fav-row .ts-row-action:focus,
.briefcase-item-row .ts-row-action:hover,
.briefcase-item-row .ts-row-action:focus {
    color: #c0392b;
}

/* A click on a favourite focuses its anchor, and the browser ringed it — across both lines of
   a wrapped term. The whole row is the target, so the ring goes, and a keyboard user is shown
   the focused row with the hover wash instead of an outline around part of it. */
.fav-row .fav-item:focus,
.le-row .listEditor-item:focus,
.fav-row .ts-row-action:focus:not(:focus-visible),
.le-row .ts-row-action:focus:not(:focus-visible),
.briefcase-item-row .ts-row-action:focus:not(:focus-visible) {
    outline: none;
}

.ts-list-table > tbody > tr.fav-row:has(.fav-item:focus-visible) > td,
.ts-list-table > tbody > tr.le-row:has(.listEditor-item:focus-visible) > td {
    background-color: #f5f5f5;
}

/* .panel-body carries Bootstrap's clearfix, and in a flex container those two empty
   pseudo-elements count as items: the 10px gap was being spent before the options
   column and again after the results, wasting it at both edges of the panel. */
.ts-sf-body:before,
.ts-sf-body:after {
    display: none;
}

/* -------------------------------------------------------------
   Panel headers, across the whole application

   Every widget panel here shares one header shape: a .panel-heading whose row
   holds an element whose id ends in "-panelTitle", with a few icon buttons to
   its right. Bootstrap gives that band 10px above and below, which suits a
   header carrying real content but leaves a title and two icons adrift in a tall
   stripe. 71 templates carry the shape, so this matches the shape itself instead
   of a class having to be added to each of them.

   HOW TO REVERT: delete this block and nothing else. No template carries a class
   for it and no script reads it, so every panel returns to Bootstrap's own
   padding on the next build.

   HOW TO NARROW IT: swap the selector for the panels you want to keep compact,
   for instance
       #fh-search_canvas .panel-heading,
       #fh-taxonomy_canvas .panel-heading { padding: 4px 10px; }

   :has() needs Edge or Chrome 105 or newer. An older browser ignores the rule and
   simply shows the previous padding, so nothing depends on it being applied.
   ------------------------------------------------------------- */
.panel-heading:has(> .row > [id$="-panelTitle"]) {
    padding: 4px 10px;
}

/* The row inside carries Bootstrap's -15px side margins, which used to be swallowed by
   the 15px of padding this band had. With the padding down to 10px they poked 5px past
   the panel on either side and gave it a horizontal scrollbar, so they go with it. */
.panel-heading:has(> .row > [id$="-panelTitle"]) > .row {
    margin-left: 0;
    margin-right: 0;
    display: flex;
    align-items: center;
}

/* the title is bare text and the buttons beside it are taller, so with the row laid
   out as columns the title sat against the top of the band. As flex items they line
   up on their centres instead. Laying the row out this way also keeps the title and
   the buttons on one line in a narrow panel, where col-md-6 used to stack them and
   make the header twice as tall. The columns keep their own widths: only the floats
   stop counting.

   The titles themselves used to open with six &nbsp, which is where the indent came
   from. Those are gone from the 71 templates that carried them, so the title now
   starts at the band's own padding like every other panel edge. */
.panel-heading:has(> .row > [id$="-panelTitle"]) > .row:before,
.panel-heading:has(> .row > [id$="-panelTitle"]) > .row:after {
    display: none;
}


/* the columns inside add Bootstrap's own 15px gutter on top of the band's padding,
   which is the rest of the indent: the title landed 25px in while the view bar under
   it starts at 10px. Dropping the gutter puts both edges of the header on the band's
   own padding. */
.panel-heading:has(> .row > [id$="-panelTitle"]) > .row > [class*="col-"] {
    padding-left: 0;
    padding-right: 0;
}


/* below the md breakpoint the col-md-* widths do not apply, and a flex item with no
   width is only as wide as its content, so the buttons ended up against the title
   instead of the far edge. Panels this narrow are the common case, not the exception.
   Letting the title take the free space puts everything after it back on the right at
   any width, and min-width lets a long title shrink rather than push them off. */
.panel-heading:has(> .row > [id$="-panelTitle"]) > .row > [id$="-panelTitle"] {
    flex: 1 1 auto;
    min-width: 0;
}

/* -------------------------------------------------------------
   Panel frames, across the whole application

   The same widget panels carry an inline margin of 5px, so their frame stops
   short of the pane holding them and the gutter on either side is spent showing
   the background. The search panel was the one built without it, which is why it
   reaches the edges. Only the sides are dropped: the top and bottom margins still
   keep two stacked panels apart. !important because the margin is inline, and the
   selector matches the same header shape as the block above so both stay in step.

   HOW TO REVERT: delete this block and nothing else, and the 5px comes back from
   the templates on the next build.

   WORTH KNOWING: where two of these panels sit side by side their frames now meet
   instead of leaving 10px between them. If that turns up somewhere it looks wrong,
   put the gap back for that layout alone, for example
       #some-layout .panel { margin-left: 5px !important; margin-right: 5px !important; }
   ------------------------------------------------------------- */
.panel:has(> .panel-heading > .row > [id$="-panelTitle"]) {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

/* The view bar above the taxonomy tree asks for a bottom border and nothing else, but
   .navbar-default brings a border on all four sides. The side ones land directly on the
   panel's own frame, which reads as a thicker edge, and the top one repeats the line the
   panel heading already draws. Only the bottom one is kept, as the template intended. */
.ts-view-bar {
    border-top: 0;
    border-left: 0;
    border-right: 0;
}


/* -------------------------------------------------------------
   Modal backdrop: cover the window however the modal is scrolled

   Bootstrap 3.3.2 prepends the backdrop to the modal itself and gives it
   position:absolute with a top, a left and a right but no bottom, making up for the
   missing height in script: adjustBackdrop() sets it to the modal's scrollHeight,
   once on show and again on resize. Two things go wrong with that. Anything that
   makes a modal taller in between is missed, so the briefcase ran past the dark
   overlay once the Word export section was opened. And because the backdrop is
   absolutely positioned inside the element that scrolls, scrolling slides it up out
   of the way, leaving the page showing below.

   position:fixed cures the coverage but costs the wheel: a fixed element's scroll
   chain is the viewport, and the viewport cannot scroll while a modal is open, so
   the pointer had to be over the dialog itself to scroll at all. Sticky keeps the
   backdrop in the modal's own scroll flow, which is what the wheel follows, while
   pinning it to the top of the scrollport so it covers the window at any scroll
   position. The height it takes in that flow is given straight back by the negative
   margin, so the dialog sits exactly where it did.

   !important because the height adjustBackdrop writes is inline. The offsets are
   cleared because Bootstrap's left and right would otherwise act as sticky
   constraints; as an ordinary block child the backdrop already spans the width.
   ------------------------------------------------------------- */
.modal-backdrop {
    position: sticky;
    top: 0;
    left: auto;
    right: auto;
    height: 100vh !important;
    margin-bottom: -100vh;
}

/* Concept panel tab strip: thirteen tabs at Bootstrap's 15px padding need ~1075px, and the
   right half of a 1366px screen gives ~825px, so four tabs dropped to a second row. At
   11px and 7px per side the row measures ~790px, with room left for the Metadata count
   badge. Inactive tabs have transparent borders, so dropping the 2px gap is invisible.
   Stepped by window width so a wide screen keeps the normal size: at 1600px the right
   half is ~970px, enough for 12px with 8px sides (~865px); from 1900px it is ~1150px
   and Bootstrap's own size fits. Breakpoints are on the window, not the panel, so a
   narrow host such as the Walker still wraps; nothing fits thirteen tabs in 500px. */
@media (max-width: 1599px) {
    ul.nav-tabs[id^="details-tabs-"] > li > a {
        margin-right: 0;
        padding-left: 7px;
        padding-right: 7px;
        font-size: 11px;
    }
}

@media (min-width: 1600px) and (max-width: 1899px) {
    ul.nav-tabs[id^="details-tabs-"] > li > a {
        margin-right: 0;
        padding-left: 8px;
        padding-right: 8px;
    }
}

/* Clicking a tab should not leave a focus ring on it: the strip already shows which tab
   is active. Only the mouse case is dropped, the way the filter chips do it:
   :focus-visible still matches when the browser judges the focus worth drawing, so a
   keyboard user keeps the outline. Covers .nav-tabs and .nav-pills alike. */
.nav > li > a:focus:not(:focus-visible) {
    outline: none;
}

/* ─────────────────────────────────────────────────────────────
   Asset Library: three columns that end on the same line
   The columns were Bootstrap columns handed a max-height from assetsLibrary.js, so each
   stopped at the height of its own content: the groups column ended a third of the way
   down, the assets list ran to the foot of the window, and the preview ended wherever
   its asset happened to end. Sizing them from the box they sit in instead — which is
   already absolute against the viewport — puts all three on one line whatever they hold.
   Every rule is scoped under #x-library-panel on purpose: #groups-panel is also an id in
   the inbox layout, and #assets-list-panel is close enough to #tasks-list-panel's shape
   to be worth keeping apart.
   ───────────────────────────────────────────────────────────── */
#x-library-panel {
    display: flex;
    flex-direction: column;
    padding: 0;
}

#x-library-panel-left {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

/* head band, optional tool band and one scrolling body — the shape each of the three
   columns has, and the shape the three details templates render into the third one */
#x-library-panel .al-col {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
}

/* the widths the col-md-2 / col-md-3 / col-md-7 classes used to carry. As flex bases they
   hold below the md breakpoint too, where those classes stop applying and the columns
   would otherwise size to their content. */
/* 17% of a 1366px window is 232px, which leaves the rail's labels 156px once the column's
   padding, the row's padding and the count badge are taken out — and "Simple Type Reference
   Set" asks for 193px. Every refset name in the group broke onto a second line on a laptop,
   and did so before this column was ever restyled: the percentage alone starves it below
   about 1500px. The floor is what the widest name needs (206px) plus the ~72px the chrome
   around it takes, rounded up. Above ~1676px the percentage is already larger and this
   does nothing; below it, the width comes out of #asset-details-panel, the one column that
   flexes. */
#x-library-panel #groups-panel {
    flex: 0 0 17%;
    min-width: 285px;
}

#x-library-panel #assets-list-panel {
    flex: 0 0 25%;
}

#x-library-panel #asset-details-panel {
    flex: 1 1 auto;
}

/* a single line between columns, running the full height: with no frame around any of
   them this is what shows that the three now end together. A frame each would have meant
   two borders down the groups column, which already holds framed panels of its own. */
#x-library-panel .al-col + .al-col {
    border-left: 1px solid #e0e4ea;
}

/* A set height rather than padding and a minimum: the three bands hold different
   controls — a bare link in one, nothing in the next, a btn-sm in the third — and sizing
   each to its own contents gave three bands of 40px, 37px and 46px sitting side by side.
   The height is the btn-sm's 30px plus room to breathe; .ts-panel-headrow centres
   whatever is in the band against it. */
#x-library-panel .al-col-head {
    flex: 0 0 auto;
    height: 44px;
    padding: 0 10px;
    border-bottom: 1px solid #e0e4ea;
    background: #f8f9fb;
}

#x-library-panel .al-col-head .ts-panel-title {
    color: #333;
    font-size: 13px;
    font-weight: 600;
}

#x-library-panel .al-col-head .btn-link {
    padding: 0;
}

/* the assets search box: its own band under the head, so it stays in view while the list
   it filters scrolls. It used to be the first row inside the scroll region. */
#x-library-panel .al-col-tools {
    flex: 0 0 auto;
    padding: 8px 10px;
    border-bottom: 1px solid #e0e4ea;
}

/* The Intensional / Extensional filter, on its own row under the search box: the three
   labels and the box do not fit on one line in this column. The three share the width
   evenly so the group reads as one segmented control rather than three buttons of the
   width of whatever each says. Hidden inline in library.hbs and revealed by
   assetsLibrary.js for Authored Refsets, so the display here is what it is revealed to.

   The track carries the same hairline border as the search box directly above it, so the
   two controls in this band read as one pair, and the selected segment is marked the way
   everything else in the module marks a selection — the #eaf2fb wash and the #23527c text
   the chosen asset row, group row and worklist row all use. Nothing here is a material
   this module did not already have: no recessed grey track, no shadow. */
#x-library-panel .al-col-tools .al-asset-filter {
    display: flex;
    width: 100%;
    margin-top: 6px;
    padding: 2px;
    border: 1px solid #e0e4ea;
    border-radius: 5px;
    background: #fff;
}

#x-library-panel .al-asset-filter-btn {
    flex: 1 1 0;
    min-width: 0;
    padding: 4px 6px;
    border: 0;
    border-radius: 3px;
    background: transparent;
    color: #6b7280;
    font-family: inherit;
    font-size: 12px;
    line-height: 1.5;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
}

#x-library-panel .al-asset-filter-btn:hover {
    background: #f4f6f9;
    color: #4a5568;
}

#x-library-panel .al-asset-filter-btn.active,
#x-library-panel .al-asset-filter-btn.active:hover {
    background: #eaf2fb;
    color: #23527c;
    font-weight: 600;
}

/* Same bargain the rail rows strike: the wash already says which segment is chosen, so the
   mouse case drops its ring, while :focus-visible keeps the outline for a keyboard user. */
#x-library-panel .al-asset-filter-btn:focus:not(:focus-visible) {
    outline: none;
}

#x-library-panel .al-col-body {
    flex: 1 1 auto;
    min-height: 0;
    padding: 10px;
    overflow: auto;
}

#x-library-panel .al-col-body > .panel-group:last-child,
#x-library-panel .al-col-body > .table:last-child {
    margin-bottom: 0;
}

/* ─────────────────────────────────────────────────────────────
   The refset editor's column in the shared editor layout
   Its tab strip only ever holds one tab. The other two columns earn theirs — Search has
   Search/Favorites, or Search/Taxonomy/Favorites in Terminology Query, and the right-hand
   one always shows two of its four — but this one offers no choice, and sat above a panel
   that names itself in its own header, so "Refset Editor" was written twice.

   Hidden by CSS rather than deleted, because the <li> is load-bearing: assetsLibrary.js
   activates the pane by clicking the <a> inside it, and a programmatic click still reaches
   Bootstrap's delegated handler on a hidden element. Written as "no li followed by another
   li" so the strip comes back on its own if a second tab is ever added — two of them are
   sitting commented out in the template.
   ───────────────────────────────────────────────────────────── */
#qu-tabs:not(:has(li + li)) {
    display: none;
}

/* With the strip gone the outer panel is a frame drawn around a panel that has one of its
   own. Same two-nested-boxes the left half of the authoring splitter had; the inner one is
   the only one that needs to be seen. */
#qu-tabs-pane:not(:has(#qu-tabs li + li)) {
    border: 0;
    box-shadow: none;
}

/* ─────────────────────────────────────────────────────────────
   Refset editor header
   The refset being edited is named in the panel title rather than in a bordered box of
   its own below it. Not scoped to one layout: this panel is built by the Asset Library,
   the inbox and the big editor's Refset Editor tab, and the header is the same in all.
   ───────────────────────────────────────────────────────────── */
.re-title-name {
    min-width: 0;
    margin-left: 8px;
    padding-left: 8px;
    border-left: 1px solid #d7dce3;
    color: #4a5568;
    font-weight: 600;
}

/* nothing to separate from when no refset is loaded */
.re-title-name:empty {
    display: none;
}

/* the History button, moved up beside the panel's refresh control */
.re-head-history {
    padding: 2px;
}

/* The chooser — drop target and library button — on one line instead of a col-md-1 /
   col-md-8 / col-md-3 row inside a 2px blue frame. It is hidden outright once the panel
   is pointed at an asset; see setToRefsetDef. */
.re-chooser {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
    padding: 8px 10px;
    border: 1px solid #e0e4ea;
    border-radius: 4px;
    background: #fafbfc;
}

.re-chooser-label {
    flex: 0 0 auto;
    color: #9aa3ad;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

/* takes the free space so the drop area is worth aiming at */
.re-chooser-drop {
    flex: 1 1 auto;
    min-width: 0;
}

.re-chooser-drop h5 {
    margin: 0;
    overflow: hidden;
    color: #4a5568;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* ─────────────────────────────────────────────────────────────
   Groups column
   Three Bootstrap panels, each framing items that carry frames of their own, on top of a
   column that is a surface already: three nested boxes for one list. The panels are gone
   and the sections sit on the column's ground, told apart by a label and by the space
   between them. Same shape as the inbox's worklist rail, down to the badge that has to
   stay first in the markup.

   The shape is shared but the density is not, and deliberately so. The worklist rail is
   tight because it has to be: it holds every worklist in the project and scrolls. This
   column holds three sections of a handful of rows each and never fills its own height —
   the tightness was inherited from that rail without inheriting the reason for it, and
   sat oddly beside the assets column's ~52px rows. So the rows here are given room.
   ───────────────────────────────────────────────────────────── */
#x-library-panel .al-group + .al-group {
    margin-top: 20px;
}

#x-library-panel .al-group-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 2px 6px;
}

/* the section label the dashboard uses: small, spaced and quiet, so it names the group
   without competing with the items under it. It follows the rows up by a pixel — held at
   10px under 14px rows, the gap between label and row reads as a bigger step than it is */
#x-library-panel .al-group-title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    color: #8a94a0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    white-space: nowrap;
    text-overflow: ellipsis;
}

#x-library-panel .al-group-actions {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 8px;
}

#x-library-panel .al-group-actions > .btn-link {
    padding: 0;
    font-size: 12px;
    line-height: 1;
    text-decoration: none;
}

#x-library-panel .al-group-items {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* sized as a real row is, so an empty section leaves the hole one would have filled */
#x-library-panel .al-group-empty {
    padding: 10px;
    font-size: 13px;
}

/* the items lose the list-group frame and sit as rows on the column */
/* The horizontal padding and the gap are as tight as they are to buy the label width: at
   14px "Simple Type Reference Set" asks for 193px, and every pixel spent on either side of
   it comes straight off what the label has. Longer names than that do wrap, and are meant
   to — align-items: flex-start is what keeps the badge on the first line when they do. */
#x-library-panel #library-groups-body .list-group-item {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    padding: 10px;
    border: 0;
    border-radius: 3px;
    background-color: #f8f8f8;
    color: #4a5568;
    font-size: 14px;
    line-height: 1.4;
}

#x-library-panel #library-groups-body a.list-group-item:hover {
    background-color: #eef1f5;
}

/* selection as an accent bar and a wash, the pair used by the worklist rail and by the
   assets list beside this one, rather than Bootstrap's solid blue */
#x-library-panel #library-groups-body a.list-group-item.active,
#x-library-panel #library-groups-body a.list-group-item.active:hover,
#x-library-panel #library-groups-body a.list-group-item.active:focus {
    padding-left: 7px;
    border-left: 3px solid #337ab7;
    background-color: #eaf2fb;
    color: #23527c;
    font-weight: 600;
}

/* Bootstrap turns the badge white on an active row, which disappears on this ground */
#x-library-panel #library-groups-body a.list-group-item.active > .badge {
    background-color: #777;
    color: #fff;
}

/* the badge stays first in the markup because assetsLibrary.js reads and writes the count
   with find("span").first(); only its visual position moves to the end */
#x-library-panel #library-groups-body .list-group-item > .badge {
    order: 2;
    flex: 0 0 auto;
    float: none;
    margin-top: 1px;
}

/* Picking a group should not leave a ring around it: the row already shows it is the one
   selected, through the accent bar and the wash. Only the mouse case is dropped — the same
   way the tab strips do it further up — so :focus-visible still draws the outline when the
   browser judges it worth drawing, and a keyboard user keeps it. */
#x-library-panel #library-groups-body a.list-group-item:focus:not(:focus-visible) {
    outline: none;
}

/* the label the click handler rewrites; it had 35px of right padding to clear a badge that
   was floated over it, which the row no longer needs now that the badge is a flex item */
#x-library-panel #library-groups-body .list-group-item > p {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    overflow-wrap: anywhere;
}

/* ─────────────────────────────────────────────────────────────
   Assets list
   The markup stays a <table> because assetsLibrary.js filters it by showing and hiding
   rows, reads data-asset-id off closest("tr") and marks the selected one with .success.
   Only the presentation changes: no cell borders, which is what made the list read as
   boxes inside a box, and each row lays out as a block with the name on top and the
   concept it maps to on a second line.
   ───────────────────────────────────────────────────────────── */
#x-library-panel .al-asset-table {
    margin: 0;
}

#x-library-panel #assets-list > tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 8px;
    padding: 7px 10px;
    border-left: 3px solid transparent;
    cursor: pointer;
}

/* dividers as a top border on every row but the first, so the list never ends on a
   trailing line */
#x-library-panel #assets-list > tr + tr {
    border-top: 1px solid #e9ecf1;
}

#x-library-panel #assets-list > tr > td {
    padding: 0;
    border: 0;
    background: none;
}

/* the spinner and the "No assets" row carry a single cell across both columns */
#x-library-panel #assets-list > tr > td[colspan] {
    grid-column: 1 / -1;
    padding: 10px 0;
    text-align: center;
    cursor: default;
}

/* #eef1f5, the grey the worklist rails hover with, rather than the near-white the task list
   uses: in a column this dense the fainter one was hard to tell from no hover at all */
#x-library-panel #assets-list > tr:hover {
    background: #eef1f5;
}

/* Selection was Bootstrap's .success green, which said "good" about a row that is merely
   the one being looked at, and collided with the green type labels elsewhere in the panel.
   An accent bar and a wash, the same pair the inbox task list uses. */
#x-library-panel #assets-list > tr.success,
#x-library-panel #assets-list > tr.success > td {
    background: #eaf2fb;
}

#x-library-panel #assets-list > tr.success {
    border-left-color: #337ab7;
}

#x-library-panel #assets-list > tr.success .al-asset-row-name {
    color: #24486b;
}

/* Name and id on the first line, the term across the second. A grid so the ids line up in a
   column down the list instead of ending wherever each term happens to stop. */
#x-library-panel .al-asset-row-main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 10px;
    min-width: 0;
}

/* wraps rather than truncating: this is the thing the reader is choosing by */
#x-library-panel .al-asset-row-name {
    grid-column: 1;
    color: #2c3e50;
    font-size: 13px;
    font-weight: 600;
    overflow-wrap: anywhere;
}

/* never shortened either — it is what gets copied out of the row — so it keeps its own
   column and nowrap. Tabular figures so the digits sit in even columns. */
#x-library-panel .al-asset-row-id {
    grid-column: 2;
    align-self: start;
    color: #6b7280;
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* the description spans the row and is the only one allowed an ellipsis; the full text is
   on its title */
#x-library-panel .al-asset-row-concept {
    grid-column: 1 / -1;
    margin-top: 1px;
    overflow: hidden;
    color: #6b7280;
    font-size: 11px;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* The tag cell renders empty: the block that filled it is parked in asset.hbs. It stays in
   the row so the two columns and the colspans that span them still hold, and at no width it
   lets the name column run to the edge, which is what puts every concept id on one line. */
#x-library-panel .al-asset-row-tags {
    display: flex;
    align-items: center;
    white-space: nowrap;
}

/* For the parked block: uncomment it in asset.hbs and put this width back on the cell, so
   the tags do not go back to moving the end of the name column from row to row.
#x-library-panel .al-asset-row-tags-on {
    width: 110px;
}
*/

#x-library-panel .al-asset-tag {
    min-width: 0;
    overflow: hidden;
    color: #6b7280;
    font-size: 11px;
    text-overflow: ellipsis;
}

#x-library-panel .al-asset-tag-toggle {
    padding: 0 0 0 4px;
    color: #9aa3ad;
}

#x-library-panel .al-detail-meta {
    color: #6b7280;
    font-size: 12px;
}

/* The head band can carry a line of metadata between the title and the actions. The title
   gives up the free space for it — .ts-panel-headrow hands that to .ts-panel-title by
   default — and the actions are pinned to the end instead, which is where they sat anyway
   in the bands that have no such line. The gap is what keeps the three apart: the band's
   children have no padding of their own, so without it the title ran straight into the
   sentence beside it. */
#x-library-panel .al-col-head {
    gap: 12px;
}

#x-library-panel .al-col-head > .ts-panel-title {
    flex: 0 0 auto;
}

#x-library-panel .al-col-head > .text-right {
    margin-left: auto;
}

/* A hairline on the leading edge rather than a separator element, so no template has to
   carry one. It is the height of the text, not of the band, which is as much of a divider
   as two kinds of the same sentence need. */
#x-library-panel .al-col-head > .al-detail-meta {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    padding-left: 12px;
    border-left: 1px solid #e0e4ea;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* The query preview: the Development Queries widget fills the body rather than stopping at
   the height of the rule it happens to be showing, which left its frame ending a third of
   the way down an otherwise full column. The scroll moves with it — the widget's own body
   carries it now, so its heading stays put and the column still shows one scrollbar.
   Scoped to this template because the other two put ordinary flow content in the body, and
   a flex column there would take the floats out of the asset details layout. */
/* no bottom padding: the widget's own frame is the last thing in the box, and 10px under it
   would end this column short of the two beside it, whose lists are clipped at the very
   foot. The sides and the top keep theirs, for the two lines above the widget. */
#x-library-panel .al-detail-query {
    display: flex;
    flex-direction: column;
    padding-bottom: 0;
}

#x-library-panel .al-detail-query > #asset-details-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* !important on both because the widget's template writes height:100% and margin:5px
   inline: the height resolved to auto for want of a definite parent, and the margin would
   now push the panel past the bottom of the box that finally sizes it. */
#x-library-panel .al-detail-query > #asset-details-body > .panel {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    margin: 0 !important;
    display: flex;
    flex-direction: column;
    overflow: hidden !important;
}

#x-library-panel .al-detail-query > #asset-details-body > .panel > .panel-body {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    overflow: auto;
}

/* ─────────────────────────────────────────────────────────────
   Loading state
   Each column drew a single fa-3x spinner centred in an empty panel while it waited —
   three of them, at three unrelated points on three blank surfaces, and the layout only
   appeared once the data did. These blocks stand in for the rows that are coming, at the
   size they will be, so the shape is there from the first paint and nothing moves when
   the data lands.
   ───────────────────────────────────────────────────────────── */
#x-library-panel .al-skel {
    height: 11px;
    border-radius: 3px;
    background: #eceff3;
}

/* The sweep says "still working" where a static block would only say "empty". It is one
   animation on a gradient rather than a spinner per column, so the three columns pulse
   together instead of at three unrelated rhythms. */
@media (prefers-reduced-motion: no-preference) {
    #x-library-panel .al-skel {
        background: linear-gradient(90deg, #eceff3 25%, #f4f6f9 50%, #eceff3 75%);
        background-size: 400% 100%;
        animation: al-skel-sweep 1.4s ease-in-out infinite;
    }
}

@keyframes al-skel-sweep {
    from { background-position: 100% 0; }
    to   { background-position: 0 0; }
}

/* The indicator that says the wait is still going, next to the title of whichever column
   is still loading — a 14px ring rather than the fa-3x wheel that used to sit alone in the
   middle of an empty panel. The skeleton says what is coming; this says it has not arrived. */
.ts-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid #dfe4ea;
    border-top-color: #98a2ae;
    border-radius: 50%;
    vertical-align: middle;
    animation: ts-spin .6s linear infinite;
}

/* No reduced-motion exception here, unlike the skeleton sweep: with both of them stilled
   there would be nothing at all left saying the panel is working. A 14px ring is about the
   mildest way to say it. */
@keyframes ts-spin {
    to { transform: rotate(360deg); }
}

/* Over the content, not beside the title: the column is what is loading, so the ring sits
   in the middle of it, larger, with the skeleton showing through around it.
   Shown only while its column still holds a skeleton, so it needs no lifecycle of its own —
   whatever replaces the skeleton takes the spinner's cue with it. */
#x-library-panel .al-col {
    position: relative;
}

#x-library-panel .al-col-spinner {
    display: none;
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 2;
    width: 30px;
    height: 30px;
    border-width: 3px;
    margin: -15px 0 0 -15px;
}

#x-library-panel .al-col:has(.al-skel) .al-col-spinner {
    display: block;
}

#x-library-panel .al-skel-wrap {
    padding: 10px;
}

/* mirrors .al-group + .al-group, so the sections sit where the real ones will */
#x-library-panel .al-skel-group + .al-skel-group {
    margin-top: 20px;
}

/* the section label: shorter and fainter than the rows under it, as the real one is */
#x-library-panel .al-skel-label {
    height: 8px;
    margin: 0 2px 10px;
    background-color: #f2f4f7;
}

/* one skeleton row at the height of a real rail item */
#x-library-panel .al-skel-item {
    display: flex;
    align-items: center;
    height: 40px;
    padding: 0 10px;
    border-radius: 3px;
    background: #fafbfc;
}

/* mirrors .al-group-items' gap, as the height above mirrors a real row */
#x-library-panel .al-skel-item + .al-skel-item {
    margin-top: 4px;
}

#x-library-panel .al-skel-item > .al-skel {
    flex: 0 0 auto;
}

/* assets list: table rows, at the height the real two-line rows have */
#x-library-panel #assets-list > tr.al-skel-row {
    display: block;
    padding: 7px 10px;
    border-left: 3px solid transparent;
    cursor: default;
}

#x-library-panel #assets-list > tr.al-skel-row + tr.al-skel-row {
    border-top: 1px solid #f1f3f6;
}

#x-library-panel #assets-list > tr.al-skel-row > td {
    display: block;
    padding: 0;
    border: 0;
}

#x-library-panel .al-skel-sub {
    height: 8px;
    margin-top: 6px;
}

/* details panel: the asset's name, its two chips and a couple of lines of description */
#x-library-panel .al-skel-title {
    height: 15px;
    margin-bottom: 12px;
}

#x-library-panel .al-skel-chips {
    display: flex;
    gap: 6px;
    margin-bottom: 14px;
}

#x-library-panel .al-skel-chip {
    height: 17px;
    border-radius: 10px;
}

#x-library-panel .al-col-body.al-skel-wrap > .al-skel-line {
    margin-bottom: 8px;
}

/* The bar above an open asset reuses the inbox's .ts-taskbar-wrap. That one aligns to the
   top because it carries two lines and the Back button has to sit level with the first;
   this one is a single line, so it centres. Scoped to #x-assets-panel, which only the
   Asset Library has. */
#x-assets-panel .ts-taskbar-wrap {
    align-items: center;
}

/* ─────────────────────────────────────────────────────────────
   Activity Preview: the asset's identity block
   Four zones — the name, the chips that classify it, the fields, and the actions — where
   this was a col-md-10 beside a col-md-2 with the buttons spread over four lines and the
   fields chained with <br>.
   ───────────────────────────────────────────────────────────── */
/* The name and the actions share a line, and keep sharing it: nowrap, because with wrap the
   row broke as soon as the name's own width plus the pills passed the panel, which on a
   1366px screen was most of the time. The name is the one that gives — it shortens with an
   ellipsis — and the pills keep their size, since a half-legible button is worse than a
   half-legible title that carries its full text in a tooltip. */
#x-library-panel .al-asset-titlerow {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}

/* flex-basis 0, not auto: with auto the title's own length counted as a claim on the row and
   shrinking was shared, so a long name pushed the pills onto a second and third line. At 0
   it asks for nothing and takes what the pills leave, which is what a title that ellipsises
   should do. The floor stops it disappearing on a narrow panel. */
#x-library-panel .al-asset-name {
    flex: 1 1 0;
    min-width: 60px;
    margin: 0;
    overflow: hidden;
    color: #2c3e50;
    font-size: 17px;
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
}

#x-library-panel .al-asset-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 10px;
}

/* the two dates share the chips line. They sit at the far end so the chips keep the left,
   and wrap under them rather than squeezing when the panel is narrow. */
#x-library-panel .al-asset-chipmeta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 16px;
    margin-left: auto;
    font-size: 12px;
    color: #4a5568;
}

#x-library-panel .al-asset-chipfield {
    white-space: nowrap;
}

#x-library-panel .al-asset-chiplabel {
    margin-right: 4px;
    color: #9aa3ad;
}

#x-library-panel .al-asset-desc {
    margin: 0 0 10px;
    color: #4a5568;
}

/* A grid rather than a dl left to flow: the labels line up in a column the eye can run
   down. Two pairs to a row where the panel is wide enough for it, one below that; the
   1fr tracks carry minmax(0,…) so a long url shortens instead of setting the width. */
#x-library-panel .al-asset-meta {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 4px 10px;
    margin: 0 0 12px;
    font-size: 12px;
}

/* Every row of this grid is optional now that the two dates have moved to the chips line,
   so an asset with none of them left an empty box still spending its bottom margin. The
   :has() is the same one the panel-frame rule further up relies on. */
#x-library-panel .al-asset-meta:not(:has(dt)) {
    display: none;
}

@media (min-width: 1600px) {
    #x-library-panel .al-asset-meta {
        grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr);
        column-gap: 24px;
    }
}

#x-library-panel .al-asset-meta > dt {
    color: #9aa3ad;
    font-weight: normal;
}

#x-library-panel .al-asset-meta > dd {
    min-width: 0;
    margin: 0;
    color: #4a5568;
}

/* the only field with no spaces to break at */
#x-library-panel .al-asset-url {
    overflow-wrap: anywhere;
}

/* the select sits in a value cell, so it takes the width of its options rather than the
   50% of the panel it used to be given */
#x-library-panel .al-asset-select {
    width: auto;
    max-width: 100%;
}

/* flex: 0 1 auto with min-width: 0 rather than 0 0 auto: at its natural width the group
   always wins the row, and only where even that will not fit does it wrap inside itself
   instead of pushing the panel into a horizontal scrollbar. */
#x-library-panel .al-asset-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    flex: 0 1 auto;
    min-width: 0;
}

/* Pills rather than Bootstrap buttons: at this size a full .btn-sm in six copies outweighs
   the asset it belongs to. Each colour says what kind of action it is — editing, creating,
   repairing, destroying — which the row could not say when five of the six were grey.
   The fill is solid on purpose: the chips a line below are soft-tinted pills of the same
   size, and these have to read as something you press, not something you read. */
#x-library-panel .al-pill {
    padding: 3px 11px;
    border: 0;
    border-radius: 999px;
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.5;
    transition: background-color .12s ease;
}

#x-library-panel .al-pill:hover,
#x-library-panel .al-pill:focus,
#x-library-panel .al-pill:active {
    color: #fff;
    outline: none;
}

/* the accent palette this facelift uses elsewhere: blue for the tools that open an editor,
   green for the one that makes something new, amber for repair, red for the one that
   cannot be undone */
#x-library-panel .al-pill-edit {
    background: #5b9bd5;
}

#x-library-panel .al-pill-edit:hover,
#x-library-panel .al-pill-edit:focus {
    background: #4a87bd;
}

#x-library-panel .al-pill-create {
    background: #52b788;
}

#x-library-panel .al-pill-create:hover,
#x-library-panel .al-pill-create:focus {
    background: #429a72;
}

#x-library-panel .al-pill-fix {
    background: #e09b3d;
}

#x-library-panel .al-pill-fix:hover,
#x-library-panel .al-pill-fix:focus {
    background: #c8862c;
}

#x-library-panel .al-pill-delete {
    background: #d9534f;
}

#x-library-panel .al-pill-delete:hover,
#x-library-panel .al-pill-delete:focus {
    background: #c0403c;
}

/* it closes the row and it is the only one that cannot be undone, so it gets a gap the
   others do not have */
#x-library-panel .al-pill-delete {
    margin-left: 6px;
}

#x-library-panel .al-pill .glyphicon {
    top: 1px;
    font-size: 10px;
}

/* "Please select an asset". The arrow was absolutely positioned against the panel and the
   branch carried a hard 619px height to leave room for it; in the flow it needs neither. */
#x-library-panel .al-detail-empty > .fa-arrow-left {
    display: block;
    margin-top: 10px;
    color: #eeeeee;
    font-size: 160px;
}

/* ─────────────────────────────────────────────────────────────
   Terminology Query: both halves reach the foot of the window, and scroll once
   refsetsEditor.hbs is written as a flex box of height:100%, which works where the
   Asset Library puts it — inside #asset-work-panel, whose height is definite. Opened as
   a module of its own it goes into #wrapper, which has no height at all, so the whole
   chain resolved to auto and every panel stopped at the height of its content. Anchoring
   the splitter to the viewport is what gives that 100% something to measure against;
   .qu-fullpage marks that case, because assets-query-perspective is also set on the
   embedded copy.
   ───────────────────────────────────────────────────────────── */
#spliter-qu.qu-fullpage {
    position: fixed;
    top: 50px;
    left: 15px;
    right: 15px;
    bottom: 0;
    width: auto !important;
    height: auto !important;
}

/* From here down the rules cover both copies: the panels inside each half fill their tab
   and carry their scroll in the body, so the heading stays put and there is one scrollbar
   rather than two. Same treatment as #spliter-fh in Concept Authoring, and the same
   reason for every !important: the heights being overridden are inline, written as
   85vh, 95% or 100% of a parent that used to have no height of its own. */
#spliter-qu .tab-content > .tab-pane.active {
    height: 100%;
    display: flex;
    flex-direction: column;
}

/* the concept details tab wraps its panel in a column div */
#spliter-qu .tab-content > .tab-pane.active > .col-md-12 {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* overflow:hidden is what takes the scroll off the panel itself: with the body scrolling
   below, a panel that also scrolled gave the half two scrollbars for one list.

   The vertical margins go because the templates disagree about them: the search panel is
   written with margin:0 and every other one with margin:5px, so the two halves started
   their panel — and so their header band — five pixels apart. Flush against the tab strip
   is the search panel's arrangement, and the one that reads right: the strip belongs to
   the panel under it. The sides are already dropped app-wide by the .panel:has(…)
   rule further up. */
/* height:100% rather than auto-plus-flex, because the pane above is not always a flex
   container: in the Asset Library's Open asset layout, setupRefsetsPerspective takes the
   Search and Favorites panes out of Bootstrap's tab toggling — it pins them with
   position:absolute and an inline display:block and switches them by visibility, to avoid
   a reflow on every tab click. An inline display beats the flex we ask for here, so the
   panel stopped being a flex item, `flex: 1 1 auto` had nothing to act on, and an
   auto height left the frame at the height of whatever the search had found. A percentage
   fills in both arrangements: the pane has a definite height either way, and the vertical
   margins are dropped below so it lands exactly on it. The flex properties stay for the
   case where the pane IS a column, where the two agree.

   The .tab-content named here is the splitter half's own, the one whose panes hold a whole
   widget. The concept details widget has a second one inside it for its Summary/Details/…
   tabs, and a loose descendant reached that one too: the Parents box of the Summary tab is
   also a .panel sitting directly in an active pane, so it was collecting a frame's height,
   flex, overflow and flattened margins meant for the widget around it. That is why its two
   boxes touched here and nowhere else, and why its own max-height:300px never scrolled —
   overflow:hidden had replaced it. Excluding the inner one by its id is the distinction the
   selector was always making. */
#spliter-qu .tab-content:not([id^="details-tab-content-"]) > .tab-pane.active > .panel,
#spliter-qu .tab-content:not([id^="details-tab-content-"]) > .tab-pane.active > .col-md-12 > .panel {
    flex: 1 1 auto;
    min-height: 0;
    height: 100% !important;
    display: flex;
    flex-direction: column;
    overflow: hidden !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

#spliter-qu .tab-content:not([id^="details-tab-content-"]) > .tab-pane.active > .panel > .panel-body,
#spliter-qu .tab-content:not([id^="details-tab-content-"]) > .tab-pane.active > .col-md-12 > .panel > .panel-body {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    overflow: auto;
}

/* ==========================================================================
   Concept details: Annotations tab (annotations + additional relationships editor)
   Spec: docs/superpowers/specs/2026-10-01-additional-relationships-editor-design.md
   Two flat sections on the tab's own ground: no panels, no bordered tables
   (design guidelines §1.2, §5.3), the editor's save bar is the band of §5.17,
   the row controls are the quiet controls of §5.18. The colours copy the
   guidelines' tokens; when navigation-shell is merged, the ring, chips and band
   can move to the shared classes (.ts-spinner, .ts-chip-*). Scoped by .ar-tab.
   ========================================================================== */
.ar-tab { padding: 14px 16px 16px; }
.ar-tab .ar-sec + .ar-sec { margin-top: 22px; }
.ar-tab .ar-sec-head { display: flex; align-items: center; gap: 6px; min-height: 26px; }
.ar-tab .ar-fold { display: inline-flex; align-items: center; gap: 6px; color: inherit; text-decoration: none; cursor: pointer; user-select: none; }
.ar-tab .ar-fold:focus:not(:focus-visible) { outline: none; }
.ar-tab .ar-fold .fa-caret-down { width: 10px; font-size: 12px; color: #9aa3ad; transition: transform .15s ease; }
.ar-tab .ar-fold:hover .fa-caret-down, .ar-tab .ar-fold:not(.collapsed) .fa-caret-down { color: #4a5568; }
.ar-tab .ar-fold.collapsed .fa-caret-down { transform: rotate(-90deg); }
.ar-tab .ar-label,
.ar-tab .ar-th > span { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #8a94a0; }
.ar-tab .ar-count { font-size: 10px; font-weight: 700; color: #9aa3ad; }
.ar-tab .ar-edit { margin-left: auto; padding: 2px; font-size: 12px; font-weight: 600; color: #337ab7; }
.ar-tab .ar-edit:hover { color: #23527c; text-decoration: none; }
.ar-tab .ar-edit .fa { margin-right: 4px; }
.ar-tab .ar-editing { margin-left: auto; font-size: 11px; color: #6b7280; }
.ar-tab .ar-empty { padding: 6px 0 0 16px; color: #9aa3ad; }
/* A fact about the context, not an alert (§5.17 .ur-shared): why types and destinations are free. */
.ar-tab .ar-note { margin: 4px 0 6px; padding: 0 0 8px 16px; border-bottom: 1px solid #eef0f4; font-size: 12px; color: #6b7280; }
.ar-tab .ar-note .fa { margin-right: 6px; color: #9aa3ad; }
.ar-tab .ar-load-error { color: #d9534f; }
.ar-tab .ar-retry { padding: 0 0 0 4px; font-size: 12px; vertical-align: baseline; }

/* Rows: CSS grid, hairline between rows, nothing around them (§5.3). */
.ar-tab .ar-grid { display: grid; grid-template-columns: minmax(0, 34%) minmax(0, 1fr) 56px 110px; column-gap: 12px; align-items: center; }
/* Editing adds a column at the row's end for Inactivate / Reactivate / Remove and Undo. */
.ar-tab .ar-list.is-editing .ar-grid { grid-template-columns: minmax(0, 32%) minmax(0, 1fr) 56px 110px 128px; }
.ar-tab .ar-list:not(.is-editing) .ar-end { display: none; }
.ar-tab .ar-end { display: flex; justify-content: flex-end; gap: 10px; white-space: nowrap; }
.ar-tab .ar-th { padding: 8px 8px 6px 16px; border-bottom: 1px solid #e0e4ea; }
.ar-tab .ar-row { position: relative; padding: 7px 8px 7px 16px; }
.ar-tab .ar-row + .ar-row { border-top: 1px solid #eef0f4; }
/* The term truncates; the pencil and the chip after it keep their room. */
.ar-tab .ar-type,
.ar-tab .ar-dest { display: flex; align-items: center; min-width: 0; white-space: nowrap; }
.ar-tab .ar-type { color: #4a5568; }
.ar-tab .ar-dest { color: #2c3e50; font-weight: 600; }
.ar-tab .ar-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ar-tab .ar-group { color: #9aa3ad; }
.ar-tab .ar-pub { font-size: 11px; color: #6b7280; white-space: nowrap; }
.ar-tab .ar-dot { display: inline-block; width: 6px; height: 6px; margin-right: 5px; border-radius: 50%; vertical-align: 1px; background: #e09b3d; }
.ar-tab .ar-dot.is-published { background: #52b788; }
.ar-tab .ar-row.is-inactive .ar-type,
.ar-tab .ar-row.is-inactive .ar-dest { color: #9aa3ad; font-weight: 400; }
.ar-tab .ar-row.is-inactive .ar-text { text-decoration: line-through; }

/* Draft chips: create green, state amber, neutral (guidelines §2). */
.ar-tab .ar-chip { display: inline-block; margin-left: 6px; padding: 0 7px; border: 1px solid; border-radius: 10px; font-size: 10px; font-weight: 600; line-height: 16px; vertical-align: 1px; text-decoration: none; }
.ar-tab .ar-pub .ar-chip { margin-left: 0; }
.ar-tab .ar-chip-new { background: #eff9f4; border-color: #cfeadc; color: #2f7a57; }
.ar-tab .ar-chip-mod { background: #fdf3e2; border-color: #f0dcbb; color: #a8701a; }
.ar-tab .ar-chip-off { background: #f2f4f7; border-color: #e0e4ea; color: #4a5568; }

/* Row hover. The type and destination cells of an editable row are the control themselves: the
   cursor turns into a pencil (its tip at the hot spot, the hand where the image cannot load) and the
   term takes the selection blue. No icon in the cell, so nothing is drawn or moved on hover. */
.ar-tab .ar-row:hover,
.ar-tab .ar-row:focus-within { background: #f4f6f9; }
.ar-tab .ar-cell-edit { cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath d='M2 18l1.2-4.6L14.4 2.2a1.6 1.6 0 0 1 2.3 0l1.1 1.1a1.6 1.6 0 0 1 0 2.3L6.6 16.8z' fill='%23fff' stroke='%232c3e50' stroke-width='1.4' stroke-linejoin='round'/%3E%3Cpath d='M12.6 4l3.4 3.4M3.2 13.4l3.4 3.4' stroke='%232c3e50' stroke-width='1.4'/%3E%3C/svg%3E") 2 18, pointer; }
.ar-tab .ar-cell-edit:hover .ar-text { color: #23527c; }
.ar-tab .ar-cell-edit:focus { outline: none; }
.ar-tab .ar-cell-edit:focus-visible { border-radius: 3px; box-shadow: 0 0 0 3px rgba(51, 122, 183, .13); }
.ar-tab .ar-act { padding: 0; font-size: 11px; font-weight: 600; color: #337ab7; }
.ar-tab .ar-act:hover { color: #23527c; text-decoration: none; }
.ar-tab .ar-act.is-danger { color: #d9534f; }
.ar-tab .ar-act.is-danger:hover { color: #c0403c; }
.ar-tab .ar-choose { font-size: 12px; }
.ar-tab .ar-row.is-error,
.ar-tab .ar-row.is-error:hover { background: #fdf1f0; }
.ar-tab .ar-errmsg { grid-column: 1 / -1; margin-top: 2px; font-size: 11px; color: #d9534f; }

/* Group: quiet at rest, framed on the row's hover, the focus halo on focus (§5.18). */
.ar-tab .ar-group-input { width: 44px; height: 22px; padding: 1px 4px; border: 1px solid transparent; border-radius: 3px; background: transparent; color: #4a5568; font-size: 12px; }
.ar-tab .ar-row:hover .ar-group-input { border-color: #ccd3dd; background: #fff; }
.ar-tab .ar-group-input:focus { outline: none; border-color: #337ab7; background: #fff; box-shadow: 0 0 0 3px rgba(51, 122, 183, .13); }

.ar-tab .ar-add { display: block; width: 100%; padding: 9px 0 0 16px; border-top: 1px solid #eef0f4; border-radius: 0; font-size: 12px; font-weight: 600; text-align: left; color: #337ab7; }
.ar-tab .ar-add:hover { color: #23527c; text-decoration: none; }
.ar-tab .ar-add .fa { margin-right: 5px; }

/* Save bar: the band, bleeding to the tab's edges (§5.7, §5.17). */
.ar-tab .ar-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 14px -16px 0; padding: 9px 16px;
    border-top: 1px solid #e0e4ea; border-bottom: 1px solid #e0e4ea; background: #f8f9fb; }
.ar-tab .ar-bar-msg { color: #6b7280; }
.ar-tab .ar-bar-msg.has-changes { color: #a8701a; font-weight: 600; }
.ar-tab .ar-bar-err { color: #d9534f; }
.ar-tab .ar-bar-sp { margin-left: auto; }
.ar-tab .ar-spinner { display: inline-block; width: 14px; height: 14px; margin: 0 22px; border: 2px solid #dfe4ea; border-top-color: #98a2ae; border-radius: 50%;
    animation: ar-spin .8s linear infinite; }
@keyframes ar-spin { to { transform: rotate(360deg); } }
.ar-tab .ar-skel { width: 60%; height: 11px; margin: 12px 0 0 16px; border-radius: 3px; background: #eceff3; }
.ar-tab .ar-skel-short { width: 35%; }
@media (prefers-reduced-motion: reduce) {
    .ar-tab .ar-fold .fa-caret-down { transition: none; }
    .ar-tab .ar-spinner { animation-duration: 2.4s; }
}

/* Annotations still render through rels-panel.hbs, shared with the other relationship lists;
   flatten it here only. The global `table th { border: 1px solid black }` is undone too. */
.ar-tab .ar-annotations .table { margin: 0; border: 0; background: transparent; }
.ar-tab .ar-annotations .table :where(th, td) { padding: 7px 8px 7px 16px; border: 0; font-size: 12px; }
.ar-tab .ar-annotations .table th { padding-top: 8px; padding-bottom: 6px; border-bottom: 1px solid #e0e4ea;
    font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #8a94a0; }
.ar-tab .ar-annotations .table tbody tr + tr td { border-top: 1px solid #eef0f4; }
.ar-tab .ar-annotations .table td .text-muted { color: #9aa3ad; }

/* ---------------------------------------------------------------------------
   jQuery QueryBuilder rule rows

   The library lays a rule row out as a run of inline-blocks, so .rule-value-container
   shrinks to its content and the rest of the row goes unused — the concept input came
   out 120px wide in a 699px row. Flex lets the value container take the free space.

   The order declarations are load-bearing. The Delete button lives in .rule-header,
   which the library emits FIRST and floats right with .pull-right. Flex neutralises
   that float, so without an explicit order the button jumps to the head of the row,
   ahead of the filter select.
   --------------------------------------------------------------------------- */
.query-builder .rule-container {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}

.query-builder .rule-container > .error-container { order: 1; }
.query-builder .rule-container > .rule-filter-container { order: 2; }
.query-builder .rule-container > .rule-operator-container { order: 3; }

.query-builder .rule-container > .rule-value-container {
    order: 4;
    flex: 1 1 auto;
    min-width: 0;
}

.query-builder .rule-container > .rule-header {
    order: 5;
    margin-left: 8px;
}

/* Relationship rules put their own operator and input inside the value container. Both are
   .form-control, so both are display:block/width:100% — tolerable while the container was
   narrow, wrong once it spans the row, and the reason each control sat on a line of its own.
   Inline-block puts every operator back beside the field it qualifies; the <br> the plugin
   emits between the type pair and the target pair still separates the two lines. */
.query-builder .rule-value-container select.typeOperator,
.query-builder .rule-value-container select.targetOperator,
.query-builder .rule-value-container input.targetOperator {
    display: inline-block;
    width: auto;
    vertical-align: middle;
}

.query-builder .rule-value-container input.typeInput,
.query-builder .rule-value-container input.targetInput {
    display: inline-block;
    vertical-align: middle;
}

/* The library flattens these fields to padding:1px, which leaves the placeholder flush
   against the border. Only the horizontal side is restored, to Bootstrap's own 12px, so the
   hint lines up with the Additional filters inputs below; .form-control fixes height at 34px,
   so the vertical 1px costs nothing and touching it would only risk the row height. */
.query-builder .rule-value-container input[type='text'],
.query-builder .rule-value-container input[type='number'] {
    padding-left: 12px;
}

/* Refsets tab of the concept details. One table per refset family, each headed by a single
   <th>, which the global "table th" rule above frames in black: that frame is what drew the
   dark vertical strokes at both ends of every heading.
   The tab's panel is the only surface. The families are not boxed inside it — a frame per
   table put boxes inside a box, the same thing the Groups column dropped — and are told
   apart by the small spaced uppercase label the dashboard uses, a hairline under it and the
   space between one family and the next. The rows keep one line of controls on the right at
   the height of the text instead of a 35px flag.
   Everything is scoped by the id of the tab pane, not by a class in refset.hbs: the compiled
   templates only reach a browser with a release, and the same template is also rendered
   inside the description editors, which are left as they are. The widths, margins and sizes
   written inline by the template and its helpers are the reason for the !important marks. */
[id^="refsets-"] > .panel {
    padding: 10px 14px 6px;
}

[id^="refsets-"] > .panel > .btn,
[id^="refsets-"] > .panel > .btn-group {
    margin-top: 0 !important;
    margin-bottom: 4px;
}

[id^="refsets-"] > .panel > .table {
    clear: both;
    margin-bottom: 18px;
    border: 0;
}

[id^="refsets-"] > .panel > .table > thead > tr > th {
    border: 0;
    border-bottom: 1px solid #e7e9ee;
    background-color: transparent;
    padding: 6px 2px 5px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #8a94a0;
}

[id^="refsets-"] > .panel > .table > tbody > tr > td {
    padding: 6px 2px;
    vertical-align: middle;
    border-top: 1px solid #f0f2f5;
}

[id^="refsets-"] > .panel > .table > tbody > tr:first-child > td {
    border-top: 0;
}

[id^="refsets-"] > .panel > .table-hover > tbody > tr:hover > td {
    background-color: #fafbfc;
}

[id^="refsets-"] > .panel > .table > tbody > tr.danger > td {
    background-color: #f8e4e4;
    color: #999;
}

/* The mapped code, and any other single value a family keeps beside the refset. */
[id^="refsets-"] .refset-simplemap {
    white-space: nowrap;
    font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
    color: #555;
}

/* Flag, info and edit menu: three floats and a fixed 103px became one right-aligned line. */
[id^="refsets-"] > .panel > .table > tbody > tr > td:last-child {
    width: 1% !important;
    white-space: nowrap;
    text-align: right;
}

[id^="refsets-"] > .panel > .table > tbody > tr > td:only-child {
    width: auto !important;
    text-align: left;
}

[id^="refsets-"] td:last-child > .phoca-flagbox {
    width: 20px !important;
    height: 20px !important;
}

[id^="refsets-"] td:last-child > .more-fields-button,
[id^="refsets-"] td:last-child > .btn-group {
    float: none !important;
    vertical-align: middle;
}

[id^="refsets-"] td:last-child > .more-fields-button {
    padding: 0 4px 0 8px;
}

[id^="refsets-"] td:last-child > .btn-group > .btn {
    padding: 2px 8px;
    margin-left: 4px;
}

/* The Intensional / Extensional cell. A fixed width rather than a shrink-to-fit one, so the
   column sits at the same place in every family, including the ones where the cell stays
   empty; the badge arrives after the table is drawn, and the width also keeps it from
   pushing the row when it does. */
[id^="refsets-"] > .panel > .table > tbody > tr > td.refset-kind-cell {
    width: 96px;
    padding-left: 12px;
    white-space: nowrap;
}

[id^="refsets-"] td.refset-kind-cell > .label {
    margin-left: 0 !important;
}

/* The same template is drawn inside the description editors, which have no use for it. */
td.refset-kind-cell:empty {
    padding: 0;
}

/* Intensional / Extensional, written in after the table by refsetTab.js. Tinted rather than
   solid, in the blue and amber of the dashboard palette, so they qualify the name instead of
   competing with it. */
[id^="refsets-"] .table .label-primary,
[id^="refsets-"] .table .label-warning {
    display: inline-block;
    margin-left: 6px !important;
    padding: 1px 7px 2px;
    border: 1px solid;
    border-radius: 10px;
    font-size: 10px;
    font-weight: 600;
    vertical-align: 1px;
}

[id^="refsets-"] .table .label-primary {
    background-color: #eaf2fa;
    border-color: #c9dcef;
    color: #3a76ad;
}

[id^="refsets-"] .table .label-warning {
    background-color: #fcf3e6;
    border-color: #f0dbb9;
    color: #a4691b;
}

[id^="refsets-"] .table td > .text-muted {
    font-style: italic;
}

/* The values of a refset with a column pattern (a query specification, for one). refsetTab.js
   cut every value at 18 characters whatever the room, so a wide tab showed a short stub of the
   query, a long gap after it and another before "More info". Here the value cells take the
   room the row has and ellipsise only what still does not fit, with the whole value in their
   title; the description editors are narrower and keep the cut. max-width: 0 is what lets an
   auto-layout cell shrink below its text, so the ellipsis can appear at all; the width is the
   share of the row it then claims, about half of it split among the value columns (up to
   three are drawn). The term keeps a floor so the values cannot crush it in a narrow tab, and
   "More info" takes only what it needs. */
[id^="refsets-"] > .panel > .table > tbody > tr > td.columnPattern {
    max-width: 0;
    width: 45%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #555;
}

[id^="refsets-"] > .panel > .table > tbody > tr:has(> td.columnPattern + td.columnPattern) > td.columnPattern {
    width: 24%;
}

[id^="refsets-"] > .panel > .table > tbody > tr:has(> td.columnPattern + td.columnPattern + td.columnPattern) > td.columnPattern {
    width: 17%;
}

[id^="refsets-"] > .panel > .table > tbody > tr:has(> td.columnPattern) > td:first-child {
    min-width: 180px;
}

[id^="refsets-"] > .panel > .table > tbody > tr > td:has(> button[onclick^="showDetailsModal"]) {
    width: 1%;
    padding-left: 12px;
    white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────
   Members tab of the concept details. The same treatment as the Refsets tab above: it was a
   bordered table loose on the tab, History alone above it and the export controls below,
   spaced with <br>s. The panel is now the only surface, with one line on top (the count as a
   section label, the actions at the other end) and rows separated by hairlines.
   The server resolves the whole refset for every page, so a large one takes a minute or more
   whatever the page size. While it works the table shows a notice saying so, the time spent
   so far and skeleton rows where the first page will land (conceptDetailsPlugin.js,
   membersLoadingNotice).
   Scoped by the ids the plugin writes, not by a class in the row template: tabs/members.hbs is
   also drawn in the Asset Library's asset details, which keeps its own look. The inline
   styles of that template and its helpers are the reason for the !important marks.
   ───────────────────────────────────────────────────────────── */
[id^="details-tab-content-"] > [id^="members-"] > .panel {
    padding: 10px 14px 6px;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 10px;
    padding-bottom: 6px;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #8a94a0;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-total {
    margin-left: 2px;
    color: #4a5568;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-actions > .btn-link {
    padding: 2px 6px;
    color: #6b7280;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-actions > .btn-link:hover,
[id^="details-tab-content-"] > [id^="members-"] .cd-members-actions > .btn-link:focus {
    color: #23527c;
    text-decoration: none;
}

/* exportXLSbuttonMetadata writes the Excel icon at 18px, taller than a small button. */
[id^="details-tab-content-"] > [id^="members-"] .cd-members-actions img {
    height: 14px !important;
    margin-left: 4px;
    vertical-align: -2px;
}

[id^="details-tab-content-"] > [id^="members-"] > .panel > .table {
    margin-bottom: 4px;
    border: 0;
}

[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > thead > tr > th {
    border: 0;
    border-bottom: 1px solid #e7e9ee;
    background-color: transparent;
    padding: 6px 2px 5px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #8a94a0;
}

[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > thead > tr > th:last-child {
    text-align: right;
}

[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > tbody > tr > td {
    padding: 5px 2px;
    vertical-align: middle;
    border-top: 1px solid #f0f2f5;
}

[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > tbody > tr:first-child > td {
    border-top: 0;
}

[id^="details-tab-content-"] > [id^="members-"] > .panel > .table-hover > tbody > tr:hover > td {
    background-color: #fafbfc;
}

/* The concept id column: as narrow as an id, right-aligned, the id in the pill of §3. */
[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > tbody > tr > td:last-child:not([colspan]) {
    width: 1%;
    padding-left: 12px;
    white-space: nowrap;
    text-align: right;
}

[id^="details-tab-content-"] > [id^="members-"] .member-id {
    font-family: Menlo, Consolas, monospace;
    font-size: 11px;
    background: #eef2f7;
    color: #2c3e50;
    border-radius: 3px;
    padding: 1px 6px;
}

/* countryIconFlag writes the flag box at 22px inline. */
[id^="details-tab-content-"] > [id^="members-"] td .phoca-flagbox {
    display: inline-block;
    width: 18px !important;
    height: 18px !important;
    margin-right: 4px;
    vertical-align: middle;
}

/* A member whose concept is inactive: the wash of an inactive membership in the Refsets tab,
   and a neutral chip in place of the solid red block the template writes inline, so the
   colour is not the only cue and the row does not shout. */
[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > tbody > tr.member-inactive > td {
    background-color: #f8e4e4;
}

[id^="details-tab-content-"] > [id^="members-"] .member-inactive-chip {
    display: inline-block;
    margin-left: 6px;
    padding: 0 6px;
    border: 1px solid #e0e4ea;
    border-radius: 10px;
    background-color: #f2f4f7 !important;
    color: #4a5568 !important;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    vertical-align: 1px;
}

/* The membership history of each row: a quiet icon at the end of the term rather than a solid
   blue button on every line. */
[id^="details-tab-content-"] > [id^="members-"] .memHistory {
    padding: 0 4px;
    border: 0;
    background: transparent;
    color: #9aa3ad;
    box-shadow: none;
}

[id^="details-tab-content-"] > [id^="members-"] .memHistory:hover,
[id^="details-tab-content-"] > [id^="members-"] .memHistory:focus {
    background: transparent;
    color: #337ab7;
}

[id^="details-tab-content-"] > [id^="members-"] .memHistory:focus:not(:focus-visible) {
    outline: none;
}

/* The value a map or ordered refset keeps beside each member, written by valueInfoMembership
   with an inline margin. Monospaced and grey, like the mapped code in the Refsets tab. */
[id^="details-tab-content-"] > [id^="members-"] td:first-child > span.pull-right {
    margin-right: 6px !important;
    font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
    font-size: 11px;
    color: #555;
}

/* The columns of a custom refset, drawn by the same helper as a bordered table in the cell. */
[id^="details-tab-content-"] > [id^="members-"] td:first-child > .table {
    clear: both;
    margin: 4px 0 0;
    font-size: 11px;
}

[id^="details-tab-content-"] > [id^="members-"] .more-row > td {
    padding-top: 8px !important;
}

[id^="details-tab-content-"] > [id^="members-"] .more-row .btn-link {
    padding: 2px 6px;
    font-size: 12px;
}

/* Loading, empty and error states: one row across the table, not a hover target. */
[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > tbody > tr.cd-members-state > td {
    padding: 12px 2px;
    color: #6b7280;
}

[id^="details-tab-content-"] > [id^="members-"] > .panel > .table-hover > tbody > tr.cd-members-state:hover > td,
[id^="details-tab-content-"] > [id^="members-"] > .panel > .table-hover > tbody > tr.cd-members-skel-row:hover > td,
[id^="details-tab-content-"] > [id^="members-"] > .panel > .table-hover > tbody > tr.more-row:hover > td {
    background-color: transparent;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-loading {
    display: flex;
    align-items: center;
    gap: 10px;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-loading-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-loading-title {
    font-size: 12px;
    font-weight: 600;
    color: #4a5568;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-loading-hint {
    font-size: 11px;
    color: #6b7280;
}

/* Tabular figures so the time does not jitter as it counts. */
[id^="details-tab-content-"] > [id^="members-"] .cd-members-elapsed {
    margin-left: auto;
    font-family: Menlo, Consolas, monospace;
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: #9aa3ad;
}

/* Skeleton rows at the height of a member row (§5.10), with the term at three lengths so the
   block reads as a list rather than a grid. */
[id^="details-tab-content-"] > [id^="members-"] > .panel > .table > tbody > tr.cd-members-skel-row > td {
    padding: 9px 2px;
}

[id^="details-tab-content-"] > [id^="members-"] .cd-members-skel {
    display: block;
    height: 11px;
    border-radius: 3px;
    background: #eceff3;
}

[id^="details-tab-content-"] > [id^="members-"] tr.cd-members-skel-row:nth-child(3n) > td:first-child > .cd-members-skel {
    width: 62%;
}

[id^="details-tab-content-"] > [id^="members-"] tr.cd-members-skel-row:nth-child(3n+1) > td:first-child > .cd-members-skel {
    width: 45%;
}

[id^="details-tab-content-"] > [id^="members-"] tr.cd-members-skel-row:nth-child(3n+2) > td:first-child > .cd-members-skel {
    width: 74%;
}

[id^="details-tab-content-"] > [id^="members-"] tr.cd-members-skel-row > td:last-child > .cd-members-skel {
    width: 118px;
    margin-left: auto;
}

@media (prefers-reduced-motion: no-preference) {
    [id^="details-tab-content-"] > [id^="members-"] .cd-members-skel {
        background: linear-gradient(90deg, #eceff3 25%, #f4f6f9 50%, #eceff3 75%);
        background-size: 400% 100%;
        animation: al-skel-sweep 1.4s ease-in-out infinite;
    }
}

/* Classifier tab. The runs were a bordered table inside a panel inside the tab's own panel:
   three frames for one list, with <br>s and &nbsp;s doing the spacing. The inner panel is
   gone and the list sits on the tab's ground, headed by one line: the path switch, and
   Schedule a run at the other end. The panel already says what the list is, so it carries
   no title of its own. The table keeps only the
   hairlines between rows; the global "table th" rule would otherwise frame its headings in
   black, which table-bordered used to paint over.
   The builds lists (views/releases/body.hbs: Builds, Releases, the statistics builds) were the
   same three frames and take the same classes. */
.cl-runs-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

/* The builds lists end the line with three controls rather than one: the type of build, the
   readme and Schedule a build. They stay together at the far end, also once the line wraps
   under the path switch, and wrap among themselves in the narrow statistics column. */
.cl-runs-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    flex-wrap: wrap;
    margin-left: auto;
}

/* The path switch. It filters the runs below, so it takes the segmented control the Asset
   Library uses for its Intensional / Extensional filter rather than the view switch of the
   concept details: the hairline track, the grey hover and the #eaf2fb wash with #23527c text
   every list in that module marks a selection with. A grid of equal columns gives both
   segments the width of the longer label, and each reserves the width of its label in bold
   so the selected one does not grow. classification.js moves .active between them. */
.cl-path-switch {
    display: inline-grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    padding: 2px;
    border: 1px solid #e0e4ea;
    border-radius: 5px;
    background: #fff;
}

.cl-path-btn {
    padding: 3px 12px;
    border: 0;
    border-radius: 3px;
    background: transparent;
    color: #6b7280;
    font-family: inherit;
    font-size: 12px;
    line-height: 1.5;
    white-space: nowrap;
    cursor: pointer;
}

.cl-path-btn::after {
    content: attr(data-label);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
}

.cl-path-btn:hover {
    background: #f4f6f9;
    color: #4a5568;
}

.cl-path-btn.active,
.cl-path-btn.active:hover {
    background: #eaf2fb;
    color: #23527c;
    font-weight: 600;
}

.cl-path-btn:focus:not(:focus-visible) {
    outline: none;
}

/* The selection slides. In both hairline segmented controls, the path switch above and the
   Asset Library's All / Intensional / Extensional filter, the wash used to go out in one
   segment and come on in the other. It is now a marker on the track that travels between
   them, as the asserted / inferred switch of the concept details has always done. That one
   measures its segments in JS; here the segments are equal by construction (1fr columns, and
   flex: 1 1 0), so the marker is one share of the track wide and moves by its own width per
   place: no script, and nothing to re-place on resize. The selected button gives up its own
   background to it and keeps the colour and the weight; hover stays on the button, above
   the marker. A control that is drawn already selected shows the marker in place: nothing
   transitions on a first paint. */
.cl-path-switch,
#x-library-panel .al-col-tools .al-asset-filter {
    position: relative;
}

.cl-path-switch::before,
#x-library-panel .al-col-tools .al-asset-filter::before {
    content: "";
    position: absolute;
    top: 2px;
    bottom: 2px;
    left: 2px;
    width: calc((100% - 4px) / 2);
    border-radius: 3px;
    background: #eaf2fb;
    transition: transform .18s ease;
}

.cl-path-switch[data-segments="3"]::before,
#x-library-panel .al-col-tools .al-asset-filter::before {
    width: calc((100% - 4px) / 3);
}

.cl-path-switch:not(:has(> .active))::before,
#x-library-panel .al-col-tools .al-asset-filter:not(:has(> .active))::before {
    opacity: 0;
}

.cl-path-switch:has(> :nth-child(2).active)::before,
#x-library-panel .al-col-tools .al-asset-filter:has(> :nth-child(2).active)::before {
    transform: translateX(100%);
}

.cl-path-switch:has(> :nth-child(3).active)::before,
#x-library-panel .al-col-tools .al-asset-filter:has(> :nth-child(3).active)::before {
    transform: translateX(200%);
}

/* A segment that leads with an icon (the severities of the QA results) reserves the icon's
   room along with the bold label, or the segments would all widen when one is chosen.
   fa-fw is 1.28571em wide, of the label's size once .fa's own 14px is set aside. */
.cl-path-btn-icon > .fa {
    margin-right: 3px;
    font-size: inherit;
}

.cl-path-btn-icon::after {
    padding-left: calc(1.28571em + 3px);
}

.cl-path-btn,
#x-library-panel .al-asset-filter-btn {
    position: relative;
    z-index: 1;
    transition: color .18s ease;
}

.cl-path-btn.active,
.cl-path-btn.active:hover,
#x-library-panel .al-asset-filter-btn.active,
#x-library-panel .al-asset-filter-btn.active:hover {
    background: transparent;
}

@media (prefers-reduced-motion: reduce) {
    .cl-path-switch::before,
    #x-library-panel .al-col-tools .al-asset-filter::before {
        transition: none;
    }
}

.cl-runs-table {
    margin-bottom: 0;
}

/* While runs load, the rows give way to the Asset Library's ring at the 30px it uses over
   its columns. The rows are hidden rather than removed, so the list keeps its height and
   nothing below jumps; with no rows yet, the body keeps room enough for the ring. The ring
   sits in the middle of the rows, but no lower than a short panel shows without scrolling:
   thirty runs are taller than the tab. */
.cl-runs-body {
    position: relative;
}

.cl-runs-body.cl-runs-loading,
.cl-runs-loading .cl-runs-body {
    min-height: 120px;
}

.cl-runs-spinner {
    display: none;
    position: absolute;
    top: min(50%, 160px);
    left: 50%;
    z-index: 2;
    width: 30px;
    height: 30px;
    border-width: 3px;
    margin: -15px 0 0 -15px;
}

.cl-runs-loading .cl-runs-spinner {
    display: block;
}

/* the collapsed borders are painted by the table, so hiding the rows leaves their lines */
.cl-runs-loading .cl-runs-table > tbody {
    visibility: hidden;
}

.cl-runs-loading .cl-runs-table > tbody > tr > td {
    border-color: transparent;
}

.cl-runs-table > thead > tr > th {
    border: 0;
    border-bottom: 1px solid #e7e9ee;
    padding: 6px 8px 5px;
    color: #8a94a0;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    white-space: nowrap;
}

.cl-runs-table > tbody > tr > td {
    padding: 7px 8px;
    vertical-align: middle;
    border-top: 1px solid #f0f2f5;
}

/* the narrow statistics column would otherwise drop the word under its badge */
.cl-runs-table > tbody > tr > td.cl-runs-status {
    white-space: nowrap;
}

.cl-runs-table > tbody > tr:first-child > td {
    border-top: 0;
}

.cl-runs-table.table-hover > tbody > tr:hover > td {
    background-color: #fafbfc;
}

/* QA rule wording review (js/v2/qaRuleReview.js): the module shell. Ported from the approved
   mockup (docs/superpowers/specs/assets/2026-09-18-qa-rule-wording-review-mockup.html), whose
   .module/.mhead/.strip/.stack/.legend/.dot become #qa-rule-review/.qrr-head/.qrr-strip/
   .qrr-stack/.qrr-legend/.qrr-dot below, with the mockup's :root custom properties inlined as
   literal values. Every selector is scoped under #qa-rule-review; no new stylesheet, per the
   design doc (app.html links this file already). The list/editor/overview panels that fill
   .qrr-stage are later tasks - only the frame, header and progress strip are here. */
#qa-rule-review {
    background: #fff;
    border: 1px solid #e0e4ea;
    border-radius: 5px;
}

/* The whole-module message shown instead of the panel to anyone who is not a termSpace
   administrator - the same frame, no header/strip/stage underneath it. */
#qa-rule-review .qrr-no-permission {
    padding: 24px;
    color: #5d6875;
    font-size: 12.5px;
}

#qa-rule-review .qrr-head {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 14px;
    border-bottom: 1px solid #e0e4ea;
    background: #f8f9fb;
    border-radius: 5px 5px 0 0;
}

#qa-rule-review .qrr-head h2 {
    font-size: 14px;
    margin: 0;
}

#qa-rule-review .qrr-head-grow {
    flex: 1;
}

#qa-rule-review .qrr-who {
    color: #8a94a0;
    font-size: 11.5px;
}

/* The management group (Assign rules / Export / Reset all) sits apart from the rest of the
   header, as in the mockup's .adm: a hairline on its left. */
#qa-rule-review .qrr-admin-group {
    display: inline-flex;
    gap: 6px;
    align-items: center;
    padding-left: 10px;
    border-left: 1px solid #e0e4ea;
}

/* progress strip: percentage reviewed, the stacked bar by state and the four counts. State is
   never carried by colour alone - the legend beside the bar always names and counts each one. */
#qa-rule-review .qrr-strip {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 10px 14px;
    border-bottom: 1px solid #eef0f3;
}

#qa-rule-review .qrr-strip-big {
    font-size: 22px;
    font-weight: 700;
    line-height: 1;
}

#qa-rule-review .qrr-strip-big small {
    font-size: 12px;
    font-weight: 400;
    color: #8a94a0;
    margin-left: 4px;
}

#qa-rule-review .qrr-stack {
    flex: 1;
    display: flex;
    height: 10px;
    gap: 2px;
}

#qa-rule-review .qrr-stack i {
    display: block;
    height: 100%;
    border-radius: 3px;
    min-width: 2px;
}

#qa-rule-review .qrr-legend {
    display: flex;
    gap: 14px;
    font-size: 12px;
    color: #5d6875;
    white-space: nowrap;
}

#qa-rule-review .qrr-legend b {
    color: #2b3440;
}

#qa-rule-review .qrr-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-right: 5px;
    vertical-align: -1px;
}

/* The four review states, checked for colour-blind separation (design doc): approved, changed,
   discuss and the neutral pending. Shared by the strip's stack and its legend dots. */
#qa-rule-review .qrr-s-approved {
    background: #3d9a5f;
}

#qa-rule-review .qrr-s-changed {
    background: #4a86c5;
}

#qa-rule-review .qrr-s-discuss {
    background: #d98c1f;
}

#qa-rule-review .qrr-s-pending {
    background: #c3cad3;
}

#qa-rule-review .qrr-loading {
    padding: 40px 0;
}

/* Review view (Task 6): list + editor split (layout A) and focus mode (layout B), the same
   editor centred with the list hidden (design doc, "Focus mode"). Ported from the mockup's
   .split/.left/.right/.tools/.list/.item/.fld/.actions/.focus. The height keeps the module
   itself scrolling instead of the page - list and editor scroll inside it, the body never does
   (project_work_panel_layout_traps memory: everything here is measured, nothing is anchored to
   the bottom of the viewport). */
#qa-rule-review .qrr-split {
    display: flex;
    height: calc(100vh - 220px);
    min-height: 480px;
}

#qa-rule-review .qrr-list-pane {
    width: 390px;
    flex: none;
    border-right: 1px solid #e0e4ea;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

#qa-rule-review .qrr-editor-pane {
    flex: 1;
    overflow: auto;
    padding: 14px 18px 18px;
    min-height: 0;
}

/* Search + chips, atop the list (mockup .tools/.chips/.chip). */
#qa-rule-review .qrr-tools {
    padding: 8px 10px;
    border-bottom: 1px solid #eef0f3;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

#qa-rule-review .qrr-tools-focus {
    border-bottom: 1px solid #eef0f3;
}

#qa-rule-review .qrr-search {
    width: 100%;
    height: 30px;
    border: 1px solid #ccd2da;
    border-radius: 4px;
    padding: 0 9px;
    font: inherit;
}

#qa-rule-review .qrr-chips {
    display: flex;
    gap: 5px;
    flex-wrap: wrap;
    align-items: center;
}

#qa-rule-review .qrr-chip {
    border: 1px solid #e0e4ea;
    background: #fff;
    border-radius: 11px;
    padding: 1px 9px;
    font-size: 11.5px;
    color: #5d6875;
}

#qa-rule-review .qrr-chip-on {
    background: #eaf2fb;
    border-color: #b9d2ec;
    color: #23527c;
    font-weight: 600;
}

#qa-rule-review .qrr-assignee-filter {
    font: inherit;
    font-size: 12px;
    height: 24px;
    border: 1px solid #ccd2da;
    border-radius: 4px;
    background: #fff;
}

#qa-rule-review .qrr-shown-count {
    color: #8a94a0;
    font-size: 11.5px;
    margin-left: auto;
}

/* The list itself: sticky suite headings, one row per rule (list.hbs, mockup .list/.suite/.item). */
#qa-rule-review .qrr-list {
    overflow: auto;
    flex: 1;
}

#qa-rule-review .qrr-list-empty {
    padding: 24px;
    color: #8a94a0;
    text-align: center;
}

#qa-rule-review .qrr-suite {
    position: sticky;
    top: 0;
    background: #fff;
    z-index: 2;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #8a94a0;
    padding: 8px 10px 4px;
    border-bottom: 1px solid #eef0f3;
    display: flex;
}

#qa-rule-review .qrr-suite span {
    margin-left: auto;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
}

#qa-rule-review .qrr-item {
    display: flex;
    gap: 8px;
    padding: 6px 10px;
    border-bottom: 1px solid #f4f5f7;
    cursor: pointer;
    align-items: flex-start;
}

#qa-rule-review .qrr-item:hover {
    background: #f4f6f9;
}

#qa-rule-review .qrr-item-selected {
    background: #eaf2fb;
}

#qa-rule-review .qrr-item .qrr-dot {
    margin-top: 4px;
    flex: none;
}

#qa-rule-review .qrr-item-text {
    flex: 1;
    min-width: 0;
}

#qa-rule-review .qrr-item-text b {
    display: block;
    font-weight: 600;
    font-size: 12.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

#qa-rule-review .qrr-item-text small {
    display: block;
    color: #8a94a0;
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A held-back rule's pill is a static label, never built from reviewer/drafter data, so it can
   live in CSS instead of the template (list.hbs only sets the .qrr-item-held class). */
#qa-rule-review .qrr-item-held .qrr-item-text b:after {
    content: "held back";
    margin-left: 6px;
    font-size: 10px;
    font-weight: 400;
    color: #9a6a12;
    background: #fcf3e1;
    padding: 0 5px;
    border-radius: 3px;
}

#qa-rule-review .qrr-flag {
    flex: none;
    font-size: 10px;
    color: #a94442;
    border: 1px solid #ebccd1;
    border-radius: 3px;
    padding: 0 4px;
    margin-top: 2px;
}

/* I2: the row-level half of the "unsaved" marker the design doc promises ("the editor keeps the
   text, the row is marked unsaved") - a subtle left accent on the row itself, PLUS the visible
   word below (.qrr-item-unsaved-mark), never colour alone. */
#qa-rule-review .qrr-item-unsaved {
    box-shadow: inset 3px 0 0 #d98c1f;
}

#qa-rule-review .qrr-item-unsaved-mark {
    flex: none;
    align-self: center;
    font-size: 10px;
    font-weight: 600;
    color: #9a6a12;
    background: #fcf3e1;
    padding: 0 5px;
    border-radius: 3px;
}

/* Assignee avatars, list and editor alike: initials over one of the dashboard's five muted
   accent colours (MEMORY.md, "Section accent colours"); a title always names who it is, since
   the module never tells reviewers apart by colour alone. */
#qa-rule-review .qrr-av {
    flex: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    font-size: 9.5px;
    font-weight: 700;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-transform: uppercase;
}

#qa-rule-review .qrr-av-none {
    background: #fff;
    color: #8a94a0;
    border: 1px dashed #c3cad3;
}

#qa-rule-review .qrr-asg {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
}

/* Editor side (mockup .kicker/.state/.was/.fld/.callout/.cols/.preview).
   The four texts the reviewer has to read - the current name, the proposed name, the
   description and the resolution - carry the type; everything around them (the kicker, the
   field labels, the "as proposed" lines, the preview) is set small and light so it does not
   compete. The name is the largest, the current name reads at the size of the body text
   beside it for the comparison, and the two paragraphs read at paragraph size. */
#qa-rule-review .qrr-kicker {
    display: flex;
    gap: 8px;
    align-items: center;
    color: #a3acb6;
    font-size: 11px;
    margin-bottom: 10px;
}

#qa-rule-review .qrr-state {
    display: inline-flex;
    align-items: center;
    border-radius: 10px;
    padding: 1px 9px 1px 7px;
    font-size: 11.5px;
    font-weight: 600;
    color: #fff;
}

#qa-rule-review .qrr-state-pending {
    color: #5d6875;
    background: #e6e9ee;
}

#qa-rule-review .qrr-state-approved {
    background: #3d9a5f;
}

#qa-rule-review .qrr-state-changed {
    background: #4a86c5;
}

#qa-rule-review .qrr-state-discuss {
    background: #d98c1f;
}

/* I2: the editor-header half of the "unsaved" marker, beside the state badge in the kicker. */
#qa-rule-review .qrr-unsaved-badge {
    display: inline-flex;
    align-items: center;
    border-radius: 10px;
    padding: 1px 9px;
    font-size: 11.5px;
    font-weight: 600;
    color: #9a6a12;
    background: #fcf3e1;
}

/* The current name: what the proposal is compared against. A quiet block rather than a
   line of small monospace, at the size of the text it is compared with. */
#qa-rule-review .qrr-was {
    border-left: 3px solid #b9d2ec;
    background: #f8f9fb;
    border-radius: 0 4px 4px 0;
    padding: 6px 12px 7px;
    margin-bottom: 14px;
}

#qa-rule-review .qrr-was label,
#qa-rule-review .qrr-field label {
    display: block;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #a3acb6;
    margin-bottom: 3px;
}

#qa-rule-review .qrr-was div {
    color: #2b3440;
    font-size: 15px;
    line-height: 1.4;
}

/* The rule's identifiers, under its current name: reference, not reading matter, so it takes
   the label's colour. A flex row because the ids are printed back to back, with no space
   to break at, and a name can cover seven of them. */
#qa-rule-review .qrr-ids {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    margin: 5px 0 0;
    font-size: 11px;
    color: #a3acb6;
}

#qa-rule-review .qrr-ids span {
    margin: 2px 5px 0 0;
    white-space: nowrap;
}

#qa-rule-review .qrr-ids code {
    margin: 2px 8px 0 0;
    padding: 1px 4px;
    font-size: 10.5px;
    color: #5b6673;
    background: #eef1f5;
    white-space: nowrap;
}

#qa-rule-review .qrr-field {
    margin-bottom: 12px;
}

#qa-rule-review .qrr-field textarea {
    width: 100%;
    border: 1px solid #ccd2da;
    border-radius: 4px;
    padding: 8px 11px;
    font: inherit;
    font-size: 14px;
    line-height: 1.5;
    min-height: 4.6em;
    resize: vertical;
    color: #2b3440;
}

/* the proposed name is the one text the reviewer judges first */
#qa-rule-review .qrr-field textarea.qrr-name-field {
    font-size: 18px;
    font-weight: 600;
    line-height: 1.35;
    min-height: 2.9em;
}

#qa-rule-review .qrr-field textarea:focus {
    outline: none;
    border-color: #7aa7d6;
    box-shadow: 0 0 0 3px rgba(51, 122, 183, .13);
}

#qa-rule-review .qrr-field textarea.qrr-edited {
    border-color: #4a86c5;
    background: #f7fbff;
}

#qa-rule-review .qrr-field-meta {
    display: flex;
    justify-content: flex-end;
    gap: 14px;
    font-size: 10.5px;
    color: #a3acb6;
    margin-top: 2px;
}

#qa-rule-review .qrr-name-counter.qrr-over {
    color: #a94442;
    font-weight: 700;
}

#qa-rule-review .qrr-revert {
    color: #337ab7;
    cursor: pointer;
}

#qa-rule-review .qrr-callout {
    background: #fff8e6;
    border: 1px solid #f1dfae;
    border-radius: 4px;
    padding: 7px 10px;
    margin-bottom: 12px;
    font-size: 12.5px;
}

#qa-rule-review .qrr-callout b {
    display: block;
    font-size: 10px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #9a6a12;
    margin-bottom: 1px;
}

#qa-rule-review .qrr-callout-held {
    background: #fcf3e1;
}

#qa-rule-review .qrr-cols {
    display: flex;
    gap: 18px;
}

#qa-rule-review .qrr-cols > div:first-child {
    flex: 1;
    min-width: 0;
}

#qa-rule-review .qrr-cols > div:last-child {
    width: 270px;
    flex: none;
}

/* The preview, folded: a <details> whose summary is the only thing shown until asked. */
#qa-rule-review .qrr-preview {
    border: 1px solid #e0e4ea;
    border-radius: 5px;
    background: #fbfcfd;
    padding: 7px 10px;
    font-size: 12px;
}

#qa-rule-review .qrr-preview summary {
    cursor: pointer;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #8a94a0;
    outline: none;
}

#qa-rule-review .qrr-preview[open] summary {
    margin-bottom: 8px;
}

#qa-rule-review .qrr-preview-row {
    background: #fff;
    border: 1px solid #eef0f3;
    border-radius: 3px;
    padding: 5px 7px;
    color: #337ab7;
    margin-bottom: 8px;
}

#qa-rule-review .qrr-preview-dlg {
    background: #fff;
    border: 1px solid #d5dae1;
    border-radius: 4px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .08);
}

#qa-rule-review .qrr-preview-dlg-head {
    padding: 6px 9px;
    border-bottom: 1px solid #eef0f3;
    font-weight: 700;
}

#qa-rule-review .qrr-preview-dlg-body {
    padding: 7px 9px;
    color: #5d6875;
}

#qa-rule-review .qrr-preview-dlg-body b {
    display: block;
    color: #2b3440;
    font-size: 10.5px;
    margin-top: 5px;
    text-transform: uppercase;
    letter-spacing: .06em;
}

/* Decisions: each button's colour matches the state it produces, but never as the only cue -
   the label already names it, and the dot/badge elsewhere carry a title too (mockup .actions/
   .act). */
#qa-rule-review .qrr-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-top: 6px;
    padding-top: 12px;
    border-top: 1px solid #eef0f3;
    flex-wrap: wrap;
}

#qa-rule-review .qrr-act {
    border: 1px solid;
    border-radius: 4px;
    padding: 7px 14px;
    font-weight: 600;
    background: #fff;
}

/* Every key hint in the module - the three decisions, Prev/Next and Focus mode - gets the same
   quiet treatment: a thin outline in the button's own colour, not Bootstrap's dark filled kbd
   (background #333, white text, inset box-shadow), and a visible gap from the label. One rule
   here rather than a copy per button class: Prev/Next and Focus mode carry plain btn/btn-default
   classes, not qrr-act, so a qrr-act-only rule left their <kbd> flush against the text in
   Bootstrap's default styling (Task 6 fix round 1, finding 1). */
#qa-rule-review kbd {
    display: inline-block;
    margin-left: 6px;
    padding: 0 4px;
    font: 10px Consolas, monospace;
    font-weight: 400;
    color: inherit;
    background: transparent;
    border: 1px solid currentColor;
    border-radius: 3px;
    box-shadow: none;
    opacity: .6;
}

#qa-rule-review .qrr-act-approved {
    color: #3d9a5f;
    border-color: #3d9a5f;
}

#qa-rule-review .qrr-act-approved:hover,
#qa-rule-review .qrr-act-approved.qrr-act-on {
    background: #3d9a5f;
    color: #fff;
}

#qa-rule-review .qrr-act-changed {
    color: #4a86c5;
    border-color: #4a86c5;
}

#qa-rule-review .qrr-act-changed:hover,
#qa-rule-review .qrr-act-changed.qrr-act-on {
    background: #4a86c5;
    color: #fff;
}

#qa-rule-review .qrr-act-discuss {
    color: #b0700f;
    border-color: #d98c1f;
}

#qa-rule-review .qrr-act-discuss:hover,
#qa-rule-review .qrr-act-discuss.qrr-act-on {
    background: #d98c1f;
    color: #fff;
}

#qa-rule-review .qrr-act[disabled] {
    opacity: .4;
    cursor: default;
}

#qa-rule-review .qrr-actions-grow {
    flex: 1;
}

#qa-rule-review .qrr-comment-hint {
    color: #a94442;
    font-size: 12px;
    margin-top: 8px;
}

#qa-rule-review .qrr-comment {
    width: 100%;
    height: 30px;
    border: 1px solid #ccd2da;
    border-radius: 4px;
    padding: 0 9px;
    font: inherit;
    margin-top: 8px;
}

#qa-rule-review .qrr-comment.qrr-required {
    border-color: #a94442;
    box-shadow: 0 0 0 3px rgba(169, 68, 68, .13);
}

#qa-rule-review .qrr-history {
    margin-top: 14px;
    font-size: 12px;
    color: #5d6875;
}

#qa-rule-review .qrr-history h4 {
    margin: 0 0 4px;
    font-size: 10px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #8a94a0;
}

#qa-rule-review .qrr-history-list div {
    padding: 2px 0 2px 12px;
    border-left: 2px solid #e0e4ea;
    margin-left: 3px;
}

/* Focus mode (layout B, design doc "Focus mode"): the same editor, centred, the list traded for
   a compact Prev/Next bar above it. Same height rule as the split, so toggling focus (key F)
   never changes how much of the page the module occupies. */
#qa-rule-review .qrr-focus-view {
    height: calc(100vh - 220px);
    min-height: 480px;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 18px;
    overflow: auto;
}

#qa-rule-review .qrr-focus-nav {
    width: min(860px, 100%);
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
    color: #5d6875;
}

#qa-rule-review .qrr-focus-nav-grow {
    flex: 1;
    text-align: center;
}

#qa-rule-review .qrr-focus-card {
    width: min(860px, 100%);
    background: #fff;
    border: 1px solid #e0e4ea;
    border-radius: 8px;
    padding: 20px 24px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .05);
}

/* The conflict dialog (js/v2/qaRuleReview.js, showConflict/conflictModal): a plain Bootstrap
   .modal, so it only needs the two small adjustments below, not a stylesheet of its own. */
#qa-rule-review .qrr-conflict-diffs dt {
    font-size: 10px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #8a94a0;
    margin-top: 8px;
}

#qa-rule-review .qrr-conflict-diffs dd {
    margin: 2px 0 0;
    color: #2b3440;
}

/* Assign rules / Reset the whole review (views/qaRuleReview/assignDialog.hbs, resetDialog.hbs):
   plain Bootstrap .modal like the conflict dialog above, ported from the approved mockup's
   .modal label.row/.hintline/.plan. Every selector stays scoped under #qa-rule-review, even
   though these dialogs render inside it too, for the same reason as the rest of this file. */
#qa-rule-review .qrr-hintline {
    color: #8a94a0;
    font-size: 12px;
    margin: 6px 0 10px;
}

#qa-rule-review .qrr-dlg-row {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 4px 0;
    font-weight: normal;
}

#qa-rule-review .qrr-asg-only-row {
    margin-top: 8px;
    border-top: 1px solid #eef0f3;
    padding-top: 10px;
}

#qa-rule-review .qrr-asg-plan {
    background: #f8f9fb;
    border-radius: 5px;
    padding: 8px 10px;
    margin-top: 10px;
    font-size: 12.5px;
}

#qa-rule-review .qrr-asg-plan div {
    display: flex;
    justify-content: space-between;
    padding: 1px 0;
}

#qa-rule-review .qrr-dlg-error {
    margin: 10px 0 0;
}

/* Overview (Task 8): tiles, progress by suite, progress by reviewer, decisions over time and
   "where to look first" (views/qaRuleReview/overview.hbs). Ported from the mockup's .dash/.tile/
   .srow/.att, with the mockup's :root custom properties inlined as literal values, the way the
   rest of this block already is. Stacked bars reuse .qrr-stack/.qrr-s-approved/etc. above - state
   is never carried by colour alone here either: every segment keeps its own title, and the suite
   tile repeats the same four-label legend under its own bars. */
#qa-rule-review .qrr-dash {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
    padding: 16px 18px 20px;
    align-content: start;
}

#qa-rule-review .qrr-tile {
    border: 1px solid #e0e4ea;
    border-radius: 6px;
    padding: 12px 14px;
    background: #fff;
}

#qa-rule-review .qrr-tile h3 {
    margin: 0 0 8px;
    font-size: 10px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #8a94a0;
    font-weight: 700;
}

#qa-rule-review .qrr-tile-num {
    font-size: 28px;
    font-weight: 700;
    line-height: 1;
}

#qa-rule-review .qrr-tile-num small {
    font-size: 12px;
    font-weight: 400;
    color: #8a94a0;
    margin-left: 5px;
}

#qa-rule-review .qrr-tile-sub {
    color: #5d6875;
    font-size: 12px;
    margin-top: 4px;
}

#qa-rule-review .qrr-tile-span2 {
    grid-column: span 2;
}

/* Progress-by-suite and progress-by-reviewer rows: label, stacked bar, count, in one grid row -
   a click opens those rules in Review (js/v2/qaRuleReview.js, the .qrr-srow[data-suite]/
   [data-asrow] handlers). The reviewer variant narrows the label column to fit an avatar. */
#qa-rule-review .qrr-srow {
    display: grid;
    grid-template-columns: 210px 1fr 86px;
    gap: 10px;
    align-items: center;
    padding: 4px 0;
    font-size: 12.5px;
    cursor: pointer;
    border-radius: 3px;
}

#qa-rule-review .qrr-srow-reviewer {
    grid-template-columns: 150px 1fr 86px;
}

#qa-rule-review .qrr-srow:hover {
    background: #f4f6f9;
}

#qa-rule-review .qrr-srow .qrr-stack {
    height: 14px;
}

#qa-rule-review .qrr-srow-n {
    text-align: right;
    color: #5d6875;
    font-variant-numeric: tabular-nums;
}

#qa-rule-review .qrr-srow-user {
    display: flex;
    align-items: center;
    gap: 6px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* "Where to look first": one line per attention item, a click filters Review the same way. */
#qa-rule-review .qrr-att {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 5px 0;
    border-bottom: 1px solid #eef0f3;
    cursor: pointer;
}

#qa-rule-review .qrr-att:hover {
    color: #337ab7;
}

#qa-rule-review .qrr-att b {
    font-variant-numeric: tabular-nums;
}

/* The line chart's own text labels (day ticks, point totals) - everything else in the SVG is
   drawn with explicit colours/titles in js/v2/qaRuleReview.js (qrrLineChartSvg). */
#qa-rule-review .qrr-dash svg text {
    font: 11px "Helvetica Neue", Arial, sans-serif;
    fill: #8a94a0;
}

/* Export the reviewed wording (views/qaRuleReview/exportDialog.hbs): plain Bootstrap .modal
   like the other two admin dialogs above, ported from the mockup's #exp .box pre/.f. */
#qa-rule-review .qrr-export-preview {
    margin: 10px 0;
    padding: 10px 12px;
    background: #f7f8fa;
    border: 1px solid #eef0f3;
    border-radius: 5px;
    font: 11.5px/1.5 Consolas, monospace;
    max-height: 320px;
    overflow: auto;
    white-space: pre;
}

#qa-rule-review .qrr-export-leftout {
    max-height: 110px;
    overflow: auto;
    margin: 4px 0 10px;
    padding-left: 18px;
    font-size: 12.5px;
    color: #5d6875;
}

/* ---------------------------------------------------------------------------
   List Editor, and the Bulk Transformers section inside it

   Nothing here is new material: the hairline (#e0e4ea), the band (#f8f9fb), the small spaced
   uppercase label and .ts-list-table are the ones the task manager, the briefcase and the
   favourites already use. Everything is scoped to #le-listEditor, the only place the list
   editor and the bulk transformers mount.

   The toolbar had four buttons on two floated rows. It is one wrapping row now: the count at
   the left, then Promote, Sync and, last and in red, Empty. The button that used to unfold
   the Bulk Transformers is gone: the section is simply there, under the toolbar.
   --------------------------------------------------------------------------- */
#le-listEditor .le-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 10px;
    margin-bottom: 10px;
}

#le-listEditor .le-count {
    flex: 1 1 auto;
    color: #5d6875;
}

#le-listEditor .le-count > strong {
    color: #333;
}

#le-listEditor .le-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

/* The section was a Bootstrap panel inside the list editor's panel: a frame within a frame,
   with a second grey heading. It is the band the task manager's filter bar uses, named by
   the small label. It does not scroll on its own any more, which also stops it from
   clipping the Transform menu. */
#le-listEditor .le-bulk {
    margin-bottom: 12px;
    padding: 10px 12px 0;
    border: 1px solid #e0e4ea;
    border-radius: 4px;
    background: #f8f9fb;
}

#le-listEditor .le-section-label {
    margin: 0 0 10px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #8a94a0;
}

/* Label and control on one line, and the control under its label once the column is too
   narrow for both. The width that matters is the splitter half's, not the window's, so this
   is a wrapping flex row rather than a media query. Controls stop at 520px: a text field
   running the full width of a wide panel says nothing about what goes in it. */
#le-listEditor .le-field {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 12px;
    margin-bottom: 8px;
}

/* 200px holds the longest requirement name, "Find attribute value to inactivate", on one
   line, so every control starts at the same edge. */
#le-listEditor .le-label {
    flex: 0 0 200px;
    margin: 0;
    padding-top: 6px;
    font-weight: normal;
    color: #5d6875;
}

#le-listEditor .le-control {
    flex: 1 1 260px;
    min-width: 0;
    max-width: 520px;
}

/* A concept field is its input, the cross that clears it and Select, on one line: Select
   used to fall under the input. The spinner checkTypeAndSetFields adds is a fa-2x floated
   left; as an item of this row it is brought down to the size of the other two. */
#le-listEditor .le-concept {
    display: flex;
    align-items: center;
    gap: 6px;
}

#le-listEditor .le-concept-input {
    flex: 1 1 auto;
    min-width: 0;
}

#le-listEditor .le-concept > .fa-spinner {
    float: none !important;
    font-size: 16px;
    color: #8a94a0;
}

#le-listEditor .le-options {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    padding-top: 6px;
}

#le-listEditor .le-options > .optionSelect {
    cursor: pointer;
    white-space: nowrap;
}

#le-listEditor .le-options input {
    margin: 0 3px 0 0;
    vertical-align: -2px;
}

/* the same closing strip as .ts-tm-actionbar, bled to the edges of the band */
#le-listEditor .le-bulk-footer {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 10px;
    margin: 12px -12px 0;
    padding: 8px 12px;
    border-top: 1px solid #e0e4ea;
}

/* Both halves of the List Editor reach the foot of the window. The splitter is anchored to
   the viewport and its halves are sized by the rules written for #spliter-qa and #spliter-fh,
   which now name #spliter-le as well: the five tabs on the left are the same panel shells as
   Concept Authoring's. What is left for here is the right half, where the concept details
   render straight into the tab pane, with no column div between them: the pane stands in for
   it. flow-root keeps the panel's 5px top margin from collapsing through the pane, which
   would push it down and give the half a scrollbar over nothing. */
#fh-tabs2-content > #conceptDetails-canvasLE.active {
    display: flow-root;
}

/* Anchoring the splitter to the viewport makes it a stacking context, and every dialog of
   the widgets inside it, the transform requests and the concept details' own, is mounted
   inside the halves. Bootstrap's z-index of 1050 then only counts within the splitter, which
   as a whole sits under the top bar (.navbar-static-top, z-index 1000): the bar stayed lit
   over the dimmed page and covered the top of the dialog, title included. While a dialog is
   open the splitter goes above the bar, and the backdrop, which Bootstrap 3.3.2 puts inside
   the modal, covers it like the rest of the page. 1040 stays under the dialogs bootbox
   appends to the body. */
body.modal-open #spliter-le {
    z-index: 1040;
}

#fh-tabs2-content > #conceptDetails-canvasLE.active > .panel {
    height: calc(100% - 5px) !important;
    margin-bottom: 0 !important;
}

/* The list used to stop at 350px whatever the height of the half, a scroll region inside a
   panel that scrolled too. The panel now has a definite height, so the list takes what the
   toolbar and the transformers leave and is the one thing that scrolls. 160px is a floor
   for a short window with the transformers open: below it the body scrolls instead. */
#spliter-le #le-listEditor > .panel > .panel-body {
    display: flex;
    flex-direction: column;
}

/* .panel-body carries Bootstrap's clearfix, and those two pseudo-elements count as flex items */
#spliter-le #le-listEditor > .panel > .panel-body:before,
#spliter-le #le-listEditor > .panel > .panel-body:after {
    display: none;
}

/* the transformers render inside the wrapper, which is the flex item */
#le-listEditor .le-toolbar,
#le-listEditor [id$="-bulk-modal-body"] {
    flex: 0 0 auto;
}

/* Transform, Dry run and Transform skipping datachecks were three entries of one menu. They
   are three buttons: the choice is visible before the click, Transform is the filled one,
   and the link to the requests keeps to the far end, away from the actions. */
#le-listEditor .le-transform-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

#le-listEditor .le-bulk-footer > .btn-link {
    margin-left: auto;
    padding-right: 0;
}

/* A click left Bootstrap's focus ring around the link until something else was clicked. It
   goes for the pointer and stays for the keyboard, as on the rows of the list. */
#le-listEditor .le-bulk-footer > .btn-link:focus:not(:focus-visible) {
    outline: none;
}

#le-listEditor .le-list {
    flex: 1 1 auto;
    min-height: 160px;
    overflow: auto;
}

/* The cross followed the id on the same line, so it sat wherever the id ended and the
   column of crosses was ragged. It has a cell of its own now: the ids line up at their left
   edge and the crosses at the right edge of the list. No rule between the two, they are
   one column to the eye. */
#le-listEditor .ts-list-table > tbody > tr.le-row > td + td {
    width: 1%;
    white-space: nowrap;
}

/* the concept that is open on the right: the wash of the selected request in the dialog */
#le-listEditor .ts-list-table > tbody > tr.le-row-selected > td,
#le-listEditor .ts-list-table > tbody > tr.le-row-selected:hover > td {
    background-color: #eaf2fb;
}

#le-listEditor .ts-list-table > tbody > tr.le-row > td:last-child {
    border-left: 0;
    padding-left: 0;
    text-align: right;
}

/* the quiet cross of the favourites and briefcase rows, here on the rows and on the
   concept fields */
#le-listEditor .ts-row-action {
    color: #b0b7c1;
    text-decoration: none;
}

#le-listEditor .ts-row-action > .glyphicon {
    top: 2px;
}

/* in the flex row of a concept field the cross is centred by the row, not nudged */
#le-listEditor .le-concept > .ts-row-action {
    display: inline-flex;
}

#le-listEditor .le-concept > .ts-row-action > .glyphicon {
    top: 0;
}

#le-listEditor .ts-row-action:hover,
#le-listEditor .ts-row-action:focus {
    color: #c0392b;
}

/* what the selected transformer does, in the column of the controls */
#le-listEditor .le-help {
    margin: 0;
    font-size: 12px;
    line-height: 1.5;
    color: #5d6875;
}

/* ---------------------------------------------------------------------------
   Transform requests (the dialog of the Bulk Transformers)

   It was a panel inside a bordered well inside the modal, three frames for one table, in a
   body capped at 450px that scrolled requests and results as one block: picking a request
   meant scrolling down to find its results. The dialog now takes the height the window
   gives it, as the comments dialog does, and has two regions that scroll on their own, the
   requests above and the results of the one picked below, so both are always in view.
   Scoped by .le-jobs-modal rather than by #le-listEditor: the rules must hold wherever the
   dialog is mounted.
   --------------------------------------------------------------------------- */
@media (min-width: 992px) {
    .le-jobs-modal .modal-dialog {
        width: 96%;
        max-width: 1600px;
        margin: 20px auto;
    }
}

/* a height, not a ceiling: the dialog is as tall as the window allows from the moment it
   opens, instead of growing once a request is picked and its results arrive */
.le-jobs-modal .modal-content {
    display: flex;
    flex-direction: column;
    height: calc(100vh - 40px);
}

.le-jobs-modal .modal-header,
.le-jobs-modal .modal-footer {
    flex: 0 0 auto;
}

.le-jobs-modal .modal-body,
.le-jobs-modal .le-jobs,
.le-jobs-modal .le-jobs-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
}

.le-jobs-modal .modal-body {
    overflow: hidden;
}

.le-jobs-modal .le-jobs-head {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 4px;
}

/* not .le-section-label: the dialog is mounted inside #le-listEditor, whose rule for that
   class carries an id and would win over anything written here */
.le-jobs-modal .le-jobs-label {
    margin: 0;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #8a94a0;
}

.le-jobs-modal .le-section-note {
    margin-left: 6px;
    font-weight: normal;
    text-transform: none;
    letter-spacing: 0;
}

.le-jobs-modal .le-jobs-head > .btn-link {
    padding-right: 0;
}

/* the heading folds the requests away: they open expanded and fold once one is picked */
.le-jobs-modal .le-jobs-toggle {
    display: flex;
    flex: 1 1 auto;
    align-items: baseline;
    min-width: 0;
    padding: 4px 0;
    border: 0;
    background: none;
    text-align: left;
}

.le-jobs-modal .le-jobs-toggle .le-jobs-label {
    flex: 0 0 auto;
}

.le-jobs-modal .le-jobs-chevron {
    flex: 0 0 auto;
    margin-right: 6px;
    font-size: 9px;
    color: #8a94a0;
    transition: transform .15s ease;
}

.le-jobs-modal .le-jobs-toggle:hover .le-jobs-label,
.le-jobs-modal .le-jobs-toggle:hover .le-jobs-chevron {
    color: #555;
}

/* which request the results below belong to, while the list is folded */
.le-jobs-modal .le-jobs-picked {
    display: none;
    min-width: 0;
    margin-left: 12px;
    overflow: hidden;
    font-size: 12px;
    color: #333;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.le-jobs-modal .le-jobs-collapsed .le-jobs-chevron {
    transform: rotate(-90deg);
}

.le-jobs-modal .le-jobs-collapsed .le-jobs-picked {
    display: inline;
}

.le-jobs-modal .le-jobs-collapsed .le-section-note,
.le-jobs-modal .le-jobs-collapsed .le-jobs-list {
    display: none;
}

/* two fifths of the window at most: twenty requests would otherwise push the results out */
.le-jobs-modal .le-jobs-list {
    flex: 0 1 auto;
    min-height: 90px;
    max-height: 40vh;
    overflow: auto;
    border-bottom: 1px solid #e0e4ea;
}

.le-jobs-modal .le-jobs-results-label {
    flex: 0 0 auto;
    margin: 14px 0 6px;
}

.le-jobs-modal .le-jobs-output {
    flex: 1 1 auto;
    min-height: 140px;
    overflow: auto;
}

/* the headings stay put while their region scrolls. The list heading rule above makes the
   cells transparent and, mounted inside #le-listEditor, reaches these with an id; the second
   selector is there to outweigh it, or the rows would show through the heading. */
.le-jobs-modal .ts-list-table > thead > tr > th,
#le-listEditor .le-jobs-modal .ts-list-table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 1;
    background-color: #fff;
}

.le-jobs-modal .batch-bulk-row {
    cursor: pointer;
}

.le-jobs-modal .ts-list-table > tbody > tr.le-job-selected > td,
.le-jobs-modal .ts-list-table > tbody > tr.le-job-selected:hover > td {
    background-color: #eaf2fb;
}

.le-jobs-modal .le-job-detail {
    margin-top: 2px;
    font-size: 11px;
    color: #8a94a0;
}

.le-jobs-modal .ts-list-table > tbody > tr > td.elapsed,
.le-jobs-modal .ts-list-table > tbody > tr > td.status {
    white-space: nowrap;
}

/* The chip of the rule info dialog (.qa-rule-info-chip), with its error and warning colours.
   The green and the blue are the same recipe on the app's success and link colours. */
.le-jobs-modal .le-chip {
    display: inline-block;
    padding: 2px 8px;
    border: 1px solid #d8dee6;
    border-radius: 2px;
    background: #f6f7f9;
    color: #6b7280;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    line-height: 1.4;
    text-transform: uppercase;
    white-space: nowrap;
}

.le-jobs-modal .le-chip-ok {
    color: #2f6f3a;
    border-color: #b9dcc0;
    background: #f1f9f2;
}

.le-jobs-modal .le-chip-error {
    color: #9e2b22;
    border-color: #e0b4b0;
    background: #fdf3f2;
}

.le-jobs-modal .le-chip-dry {
    color: #87590f;
    border-color: #e6cf9e;
    background: #fdf8ee;
}

.le-jobs-modal .le-chip-running {
    color: #2f6ba8;
    border-color: #d3e3f5;
    background: #eaf2fb;
}

/* the chips that open the detail of a concept */
.le-jobs-modal label.le-chip {
    margin: 0;
    cursor: pointer;
}

.le-jobs-modal label.le-chip:hover {
    border-color: #b0b7c1;
}

/* The changes of a concept fold under a summary. Bootstrap makes <summary> a block, which
   drops the browser's disclosure triangle, so the summary draws its own chevron and takes the
   link colour to read as something to click. */
.le-jobs-modal .le-changes {
    margin-top: 4px;
}

.le-jobs-modal .le-changes-toggle {
    display: inline-block;
    font-size: 11px;
    color: #337ab7;
    cursor: pointer;
    list-style: none;
}

.le-jobs-modal .le-changes-toggle::-webkit-details-marker {
    display: none;
}

.le-jobs-modal .le-changes-toggle:hover {
    color: #23527c;
    text-decoration: underline;
}

.le-jobs-modal .le-changes-chevron {
    margin-right: 5px;
    font-size: 8px;
    transition: transform .15s ease;
}

.le-jobs-modal .le-changes[open] > .le-changes-toggle .le-changes-chevron {
    transform: rotate(90deg);
}

.le-jobs-modal .le-changes-alerts {
    color: #a94442;
}

/* spaces a term should not have (double, leading, trailing), made visible */
.le-space-mark {
    padding: 0 1px;
    border-radius: 2px;
    color: #9e2b22;
    background: #f6d5d1;
    font-weight: 700;
}

.le-alert-term {
    color: #555;
}
