/*
  Controls, forms, tables and the small pieces of furniture.

  Buttons and fields keep the Bootstrap class names the templates already use, so that every screen
  is restyled at once rather than half of them being redrawn and half left behind. The names are a
  vocabulary; nothing here is Bootstrap.
*/

@layer components {
  .backlink {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    margin-bottom: var(--s-3);
    padding: var(--s-1) var(--s-2);
    margin-inline-start: calc(var(--s-2) * -1);
    border-radius: var(--radius);
    font-size: var(--text-sm);
    color: var(--ink-2);
    text-decoration: none;
  }

  .backlink:hover {
    color: var(--ink);
    background: var(--surface-sunk);
    text-decoration: none;
  }

  .backlink .icon { color: var(--ink-3); }
  .backlink:hover .icon { color: inherit; }

  /* Records ---------------------------------------------------------------- */

  /* A record reads as a ruled list: the field name on the left, the value on the right. */
  .datum-row {
    display: grid;
    grid-template-columns: minmax(9rem, 16ch) 1fr;
    gap: var(--s-1) var(--s-4);
    align-items: baseline;
    padding-block: var(--s-2);
    border-bottom: 1px solid var(--rule);
  }

  .datum-row:last-child { border-bottom: 0; }

  .datum-row .label { display: inline-flex; align-items: baseline; gap: var(--s-2); }
  .datum-row .label .icon { align-self: center; color: var(--ink-3); }

  .section-heading {
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--ink-2);
    margin-block: var(--s-5) var(--s-2);
    padding-bottom: var(--s-1);
    border-bottom: 1px solid var(--rule-strong);
  }

  .blank-slate {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-2);
    padding: var(--s-5) var(--s-4);
    border: 1px dashed var(--rule-strong);
    border-radius: var(--radius-lg);
    color: var(--ink-2);
    margin-block: var(--s-3) var(--s-5);
  }

  .blank-slate p { margin: 0; }
  .blank-slate .icon { color: var(--ink-3); }

  /* A list of places to go, each with its own mark. */
  .cardlist { list-style: none; padding: 0; margin: 0; max-width: 40rem; }

  .cardlist__item {
    display: flex;
    align-items: flex-start;
    gap: var(--s-3);
    padding: var(--s-4) var(--s-2);
    border-bottom: 1px solid var(--rule);
    text-decoration: none;
    color: var(--ink);
  }

  .cardlist__item:hover { background: var(--surface-sunk); }
  .cardlist__item .icon { margin-top: 2px; color: var(--ink-3); }
  .cardlist__title { display: block; font-weight: 700; }
  .cardlist__note { display: block; font-size: var(--text-sm); color: var(--ink-2); }

  /* Buttons ---------------------------------------------------------------- */

  .btn {
    --btn-face: var(--surface);
    --btn-ink: var(--ink);
    --btn-rule: var(--rule-strong);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    min-height: var(--tap);
    padding: var(--s-2) var(--s-4);
    border: 1px solid var(--btn-rule);
    border-radius: var(--radius);
    background: var(--btn-face);
    color: var(--btn-ink);
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease;
  }

  .btn:hover { background: color-mix(in oklab, var(--btn-face) 92%, var(--ink)); }

  .btn:disabled, .btn.disabled { opacity: 0.5; cursor: not-allowed; }

  .btn-sm { min-height: 2rem; padding: var(--s-1) var(--s-3); font-size: var(--text-sm); }
  .btn-lg { min-height: 2.75rem; padding: var(--s-3) var(--s-5); font-size: var(--text-lg); }
  .btn-block { display: flex; width: 100%; }

  /* The one filled button on a screen is the thing to do next. */
  .btn-primary {
    --btn-face: var(--accent);
    --btn-ink: var(--accent-ink);
    --btn-rule: var(--accent);
  }

  .btn-success {
    --btn-face: var(--money);
    --btn-ink: var(--money-ink);
    --btn-rule: var(--money);
  }

  .btn-danger {
    --btn-face: var(--owing);
    --btn-ink: var(--owing-ink);
    --btn-rule: var(--owing);
  }

  .btn-secondary, .btn-dark {
    --btn-face: var(--surface-sunk);
    --btn-ink: var(--ink);
  }

  .btn-light, .btn-outline-secondary {
    --btn-face: var(--surface);
    --btn-ink: var(--ink-2);
    --btn-rule: var(--rule);
  }

  .btn-outline-primary { --btn-face: var(--surface); --btn-ink: var(--accent); --btn-rule: var(--accent); }
  .btn-outline-success { --btn-face: var(--surface); --btn-ink: var(--money); --btn-rule: var(--money); }
  .btn-outline-danger  { --btn-face: var(--surface); --btn-ink: var(--owing); --btn-rule: var(--owing); }

  .btn-link {
    --btn-face: transparent;
    --btn-rule: transparent;
    --btn-ink: var(--ink);
    text-decoration: underline;
    text-underline-offset: 0.2em;
    font-weight: 400;
  }

  .btn-group {
    display: inline-flex;
  }

  /* A split button's menu is the group's last child, so the rounding has to count buttons only. */
  .btn-group > .btn { border-radius: 0; margin-inline-start: -1px; }

  .btn-group > .btn:nth-child(1 of .btn) {
    border-start-start-radius: var(--radius);
    border-end-start-radius: var(--radius);
    margin-inline-start: 0;
  }

  .btn-group > .btn:nth-last-child(1 of .btn) {
    border-start-end-radius: var(--radius);
    border-end-end-radius: var(--radius);
  }

  /* Forms ------------------------------------------------------------------ */

  .form-group { margin-bottom: var(--s-4); }

  label, .col-form-label {
    display: inline-block;
    font-weight: 700;
    font-size: var(--text-sm);
    margin-bottom: var(--s-1);
  }

  .col-form-label { padding-top: calc(var(--s-2) + 1px); margin-bottom: 0; }

  legend { font-weight: 700; font-size: var(--text-sm); padding: 0; }

  .form-control, .form-control-file, .custom-select, .selectize-input {
    display: block;
    width: 100%;
    min-height: var(--tap);
    padding: var(--s-2) var(--s-3);
    border: 1px solid var(--rule-strong);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--ink);
  }

  textarea.form-control { min-height: 5rem; resize: vertical; }

  select.form-control, .custom-select {
    appearance: none;
    padding-inline-end: var(--s-6);
    background-image: linear-gradient(45deg, transparent 50%, currentcolor 50%),
                      linear-gradient(135deg, currentcolor 50%, transparent 50%);
    background-position: right 1.05rem center, right 0.8rem center;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
  }

  .form-control:focus, .custom-select:focus {
    border-color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: 1px;
  }

  .form-control.is-invalid { border-color: var(--owing); }

  .invalid-feedback { color: var(--owing); font-size: var(--text-sm); margin-top: var(--s-1); }

  .form-text { display: block; font-size: var(--text-sm); color: var(--ink-2); margin-top: var(--s-1); }

  .text-muted { color: var(--ink-2); }

  .form-check, .custom-control {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--s-2);
    min-height: var(--tap);
  }

  .form-check-label, .custom-control-label { cursor: pointer; }
  .form-check-input, .custom-control-input { cursor: pointer; }

  .form-check-inline, .custom-control-inline { display: inline-flex; margin-inline-end: var(--s-4); }

  .form-check-input, .custom-control-input {
    width: 1.15rem;
    height: 1.15rem;
    margin: 0;
    accent-color: var(--money);
    flex: none;
  }

  .form-check-label, .custom-control-label {
    margin-bottom: 0;
    font-weight: 400;
    font-size: var(--text);
  }

  .input-group { display: flex; }
  .input-group > .form-control { border-radius: 0; }
  .input-group > :first-child, .input-group > :first-child .input-group-text { border-start-start-radius: var(--radius); border-end-start-radius: var(--radius); }
  .input-group > :last-child, .input-group > :last-child .input-group-text { border-start-end-radius: var(--radius); border-end-end-radius: var(--radius); }

  .input-group-text {
    display: flex;
    align-items: center;
    padding: var(--s-2) var(--s-3);
    border: 1px solid var(--rule-strong);
    background: var(--surface-sunk);
    color: var(--ink-2);
    white-space: nowrap;
  }

  .input-group-prepend > .input-group-text { border-inline-end: 0; }
  .input-group-append  > .input-group-text { border-inline-start: 0; }

  /* A form's buttons sit together with air above them, not jammed under the last field. */
  .form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin-top: var(--s-5);
    padding-top: var(--s-4);
    border-top: 1px solid var(--rule);
  }

  .prose-form { max-width: 34rem; }

  /* Numbered because these really are steps, taken in order. */
  .steps { list-style: none; counter-reset: step; padding: 0; margin: 0 0 var(--s-6); }

  .steps__step {
    counter-increment: step;
    position: relative;
    padding-inline-start: var(--s-6);
    padding-block: var(--s-3);
    border-top: 1px solid var(--rule);
  }

  .steps__step::before {
    content: counter(step);
    position: absolute;
    inset-inline-start: 0;
    top: var(--s-3);
    width: 1.5rem;
    height: 1.5rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: var(--text-sm);
    font-weight: 700;
  }

  .steps__title { font-size: var(--text); margin-bottom: var(--s-1); }

  /* A row of filters. Each control keeps room for its longest option and the row wraps rather
     than squeezing one of them until its text is cut off. */
  .filterbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
    align-items: center;
    margin-bottom: var(--s-5);
  }

  .filterbar__field { flex: 1 1 12rem; min-width: 12rem; }
  .filterbar__field--wide { flex: 2 1 18rem; }
  .filterbar__field .form-group { margin-bottom: 0; }
  .filterbar__actions { flex: 0 0 auto; }

  @media (max-width: 35.99em) {
    .filterbar__field, .filterbar__field--wide { flex-basis: 100%; min-width: 0; }
    .filterbar__actions, .filterbar__actions .btn { width: 100%; }
  }

  /* Tables ----------------------------------------------------------------- */

  /* A wide table scrolls inside its own box rather than pushing the page sideways. */
  .table-responsive, .table-sm-responsive { overflow-x: auto; }

  .table {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
  }

  .table th, .table td {
    padding: var(--s-3);
    text-align: start;
    vertical-align: top;
    border-bottom: 1px solid var(--rule);
  }

  .table thead th {
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--ink-2);
    border-bottom: 1px solid var(--rule-strong);
    white-space: nowrap;
  }

  .table-sm th, .table-sm td { padding: var(--s-2) var(--s-3); }

  .table tbody tr:hover { background: var(--surface-sunk); }

  /* Rules, not boxes: striping and outer borders only add noise to a ruled list. */
  .table-striped tbody tr:nth-of-type(odd) { background: none; }
  .table-bordered th, .table-bordered td { border-inline: 0; }
  .table-clear td { border: 0; }

  /* Sort headings carry the direction as a caret, and the sorted one is set in ink. */
  a.sort_link { color: var(--ink-2); text-decoration: none; white-space: nowrap; }
  a.sort_link:hover { color: var(--ink); }
  a.sort_link.asc, a.sort_link.desc { color: var(--ink); }

  /* Never set this on the cell itself: a table cell told to be a flex container leaves the table
     layout, and the row's rules stop short of the column edge. */
  .cell-with-mark {
    display: flex;
    align-items: baseline;
    gap: var(--s-2);
  }

  .cell-with-mark > .icon,
  .cell-with-mark > .roundtag__dot { align-self: center; color: var(--ink-3); }

  /* Row controls sit together at the end of a row and never wrap onto two lines. */
  .row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    justify-content: flex-end;
    white-space: nowrap;
  }

  .section-heading--flush { margin-block: 0 0; border-bottom: 0; }

  /* Cards ------------------------------------------------------------------ */

  .card {
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--radius-lg);
  }

  .card + .card { margin-top: var(--s-3); }
  .card-body { padding: var(--s-4); }
  .card-header { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--rule); }
  .card-footer { padding: var(--s-3) var(--s-4); border-top: 1px solid var(--rule); }
  .card-title { font-size: var(--text-sm); font-weight: 700; color: var(--ink-2); margin-bottom: var(--s-2); }
  .card-text { margin: 0; }

  /* Badges ----------------------------------------------------------------- */

  .badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25em;
    padding: 0.15em 0.5em;
    border-radius: var(--radius);
    font-size: var(--text-xs);
    font-weight: 700;
    line-height: 1.4;
    background: var(--surface-sunk);
    color: var(--ink-2);
    vertical-align: baseline;
  }

  .badge-success { background: var(--money-soft); color: var(--money); }
  .badge-danger  { background: var(--owing-soft); color: var(--owing); }
  .badge-warning { background: var(--owing-soft); color: var(--owing); }
  /* A customer's status is not money, so it takes the accent rather than the money colour. */
  .badge-info, .badge-primary { background: var(--accent-soft); color: var(--accent); }
  .badge-secondary, .badge-light, .badge-dark { background: var(--surface-sunk); color: var(--ink-2); }

  /* Alerts ----------------------------------------------------------------- */

  .alert {
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--rule);
    border-inline-start: 3px solid var(--accent);
    border-radius: var(--radius);
    background: var(--surface-sunk);
    margin-bottom: var(--s-4);
  }

  .alert-success { border-inline-start-color: var(--money); background: var(--money-soft); color: var(--money); }
  .alert-danger, .alert-error { border-inline-start-color: var(--owing); background: var(--owing-soft); color: var(--owing); }
  .alert-warning { border-inline-start-color: var(--owing); background: var(--owing-soft); color: var(--owing); }
  .alert a { color: inherit; }

  /* The flash sits above the page card on desktop, so it takes the card's spacing rather than
     sitting tight under the top bar. */
  @media (min-width: 48em) {
    #flash_messages .alert {
      margin-top: var(--s-5);
      padding: var(--s-4) var(--s-6);
    }
  }

  .alert-dismissible { display: flex; align-items: flex-start; gap: var(--s-3); }
  .alert-dismissible .close {
    margin-inline-start: auto;
    background: none;
    border: 0;
    font-size: var(--text-lg);
    line-height: 1;
    cursor: pointer;
    color: inherit;
  }

  /* Tabs ------------------------------------------------------------------- */

  .nav-tabs {
    display: flex;
    gap: var(--s-1);
    list-style: none;
    margin: 0 0 var(--s-5);
    padding: 0;
    border-bottom: 1px solid var(--rule);
    overflow-x: auto;
  }

  .nav-tabs .nav-link {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    padding: var(--s-2) var(--s-3);
    text-decoration: none;
    color: var(--ink-2);
    white-space: nowrap;
  }

  .nav-tabs .nav-link:hover { color: var(--ink); }

  .nav-tabs .nav-link.active {
    color: var(--accent);
    font-weight: 700;
    box-shadow: inset 0 -2px 0 var(--accent);
  }

  /* Dropdowns -------------------------------------------------------------- */
  /* Bootstrap's JavaScript toggles .show, so that is the contract these honour. */

  .dropdown, .btn-group { position: relative; }

  .dropdown-menu {
    display: none;
    position: absolute;
    inset-inline-start: 0;
    top: 100%;
    z-index: 40;
    min-width: 12rem;
    padding: var(--s-1);
    margin-top: var(--s-1);
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sheet);
  }

  .dropdown-menu.show { display: block; }
  .dropdown-menu-right { inset-inline-start: auto; inset-inline-end: 0; }

  .dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    width: 100%;
    padding: var(--s-2) var(--s-3);
    border: 0;
    border-radius: var(--radius);
    background: none;
    text-align: start;
    text-decoration: none;
    color: var(--ink);
    cursor: pointer;
  }

  .dropdown-item:hover { background: var(--surface-sunk); }

  .dropdown-divider { height: 1px; margin: var(--s-1) 0; background: var(--rule); }

  .dropdown-heading {
    padding: var(--s-1) var(--s-3);
    font-size: var(--text-xs);
    color: var(--ink-3);
  }

  .dropdown-item[aria-current="true"] { font-weight: 700; }
  .dropdown-item[aria-current="true"]::after { content: "\2713"; margin-inline-start: auto; }

  .dropdown-toggle::after {
    content: "";
    display: inline-block;
    margin-inline-start: var(--s-2);
    border: 4px solid transparent;
    border-top-color: currentcolor;
    translate: 0 2px;
  }

  /* Collapse --------------------------------------------------------------- */

  .collapse:not(.show) { display: none; }
  .collapsing { overflow: hidden; height: 0; transition: height 0.2s ease; }

  /* Modals ----------------------------------------------------------------- */

  .modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1050;
    overflow-y: auto;
    padding: var(--s-4);
  }

  .modal-dialog {
    width: min(100%, 34rem);
    margin-inline: auto;
    margin-block: var(--s-6) var(--s-7);
  }

  .modal-lg .modal-dialog, .modal-dialog.modal-lg { width: min(100%, 52rem); }

  .modal-content {
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sheet);
    overflow: hidden;
  }

  .modal-header {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-4);
    border-bottom: 1px solid var(--rule);
  }

  .modal-title { font-size: var(--text-lg); font-weight: 700; margin: 0; }

  .modal-header .close {
    margin-inline-start: auto;
    background: none;
    border: 0;
    font-size: var(--text-xl);
    line-height: 1;
    cursor: pointer;
    color: var(--ink-2);
  }

  .modal-body { padding: var(--s-4); }

  .modal-footer {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    justify-content: flex-end;
    padding: var(--s-4);
    border-top: 1px solid var(--rule);
  }

  .modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1040;
    /* Near-black in both themes: at 45% the difference between the two was not visible. */
    background: #0c110f;
    opacity: 0;
  }

  .modal-backdrop.show { opacity: 0.45; }

  body.modal-open { overflow: hidden; }

  .fade { transition: opacity 0.15s linear; }
  .fade:not(.show) { opacity: 0; }
  .modal.fade .modal-dialog { transition: translate 0.2s ease; translate: 0 -0.75rem; }
  .modal.show .modal-dialog { translate: 0 0; }

  /* Pagination ------------------------------------------------------------- */

  .pagination {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1);
    list-style: none;
    padding: 0;
    margin: var(--s-5) 0 0;
  }

  .page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--tap);
    min-height: var(--tap);
    padding-inline: var(--s-2);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    text-decoration: none;
    color: var(--ink-2);
  }

  .page-link:hover { background: var(--surface-sunk); color: var(--ink); }

  .page-item.active .page-link {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
    font-weight: 700;
  }

  .page-item.disabled .page-link { opacity: 0.4; pointer-events: none; }
}
