/* Kassekladde (slice 104): the staging grid — the grid's cells, their error state,
   the voucher tint and the small chrome around them — and, since slice 107 (the
   import wizard's review retired into the grid), the import's own pieces: the amber
   VAT block, the errors card, the scroll sentinel, the mapper's greyed column and
   the landing modal. The pinned bulk bar is tables.css's. */

@layer components {
  /* The pinned bulk bar floats over the page bottom — keep the last voucher reachable.
     The page runs the full width of the view and no wider (CEO): the card is capped at
     the view, the grid scrolls sideways inside it (.table-scroll), the card grows with
     the grid, and the page scrolls vertically. The header cannot use position: sticky
     across that sideways scroll box, so the grid controller rides it along
     (translateY) as the page scrolls past the table's top. */
  .kk-page {
    max-width: none;
    padding-bottom: 6rem;
  }

  .kk-table {
    min-width: 100%;
    border-collapse: separate; /* a sticky header keeps its bottom border only when the table is not collapsed */
    border-spacing: 0;
  }

  .kk-table td {
    padding: 1px 2px; /* very small — a spreadsheet, not a report (CEO) */
    vertical-align: middle;
    border-bottom: 0;
  }

  .kk-table thead {
    position: relative;
    z-index: 2; /* over the rows it rides across */
  }

  .kk-table th {
    padding: var(--space-1-5) 2px;
    white-space: nowrap;
  }

  /* One voucher is one <tbody>; a hairline between vouchers, none between their lines. */
  .kk-voucher {
    border-top: 1px solid var(--color-border);
  }

  .kk-voucher--rejected > tr {
    background: var(--color-red-50);
  }

  /* A cell's input: compact, the house hairline, the house focus halo. */
  .kk-input {
    --form-border-size: 1px;
    --form-focus-halo-size: 3px;
    width: 100%;
    min-width: 6rem;
    box-sizing: border-box;
    min-height: var(--space-8);
    padding: 0 var(--space-2);
    border: var(--form-border-size) solid var(--color-slate-300);
    border-radius: var(--radius-sm);
    background: var(--color-white);
    color: var(--color-slate-900);
    font: inherit;
    font-size: var(--text-xs);
    transition: border-color var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
  }

  .kk-input::placeholder {
    color: var(--color-slate-400);
  }

  .kk-input:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 var(--form-focus-halo-size) color-mix(in oklab, var(--color-primary) 20%, transparent);
  }

  .kk-input:disabled {
    background: var(--color-slate-50);
    color: var(--color-slate-500);
    cursor: not-allowed;
  }

  .kk-input--number { min-width: 3.25rem; width: 3.25rem; padding: 0 var(--space-1); }
  .kk-input--type   { min-width: 5.5rem; }
  .kk-input--date   { min-width: 7.25rem; width: 7.25rem; padding: 0 var(--space-1); }
  .kk-input--text   { min-width: 9rem; }
  .kk-input--amount { min-width: 6rem; text-align: right; font-variant-numeric: tabular-nums; }

  /* The red border — on the cell the voucher's errors name (kassekladde_stream_actions.js
     sets the class; the initial render sets it the same way). The title carries the words. */
  .kk-cell--error .kk-input,
  .kk-cell--error .kk-check {
    border-color: var(--color-red-500);
    box-shadow: inset 0 0 0 1px var(--color-red-500);
  }

  /* Text that resolved to nothing (picker#blur) — the cell says so itself, before the
     gate does: "999999" is not an account, and the reader sees that where they typed it. */
  .kk-input.picker--unresolved {
    border-color: var(--color-red-500);
    box-shadow: inset 0 0 0 1px var(--color-red-500);
  }

  .kk-cell--error .kk-input:focus {
    box-shadow: inset 0 0 0 1px var(--color-red-500),
                0 0 0 var(--form-focus-halo-size) color-mix(in oklab, var(--color-red-500) 20%, transparent);
  }

  .kk-col--narrow {
    width: 1%;
    white-space: nowrap;
  }

  .kk-check {
    width: 1rem;
    height: 1rem;
    margin: 0;
    accent-color: var(--color-primary);
  }

  /* A value the grid computes (VAT amount, Difference) or fixes (DKK): boxed like a
     disabled field, dimmed — the eye reads "not yours to type" (CEO). */
  .kk-readonly {
    display: block;
    box-sizing: border-box;
    min-width: 4rem;
    min-height: var(--space-8);
    padding: 0 var(--space-2);
    border: 1px solid var(--color-slate-200);
    border-radius: var(--radius-sm);
    background: var(--color-slate-50);
    color: var(--color-slate-500);
    font-size: var(--text-xs);
    line-height: var(--space-8);
    white-space: nowrap;
  }

  .kk-readonly--numeric {
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  /* A voucher cell repeated on its second line onward: the dimmed box (.kk-readonly),
     each as wide as the input above it, so the columns read as one (CEO drive 2026-09-08). */
  .kk-repeat--number   { min-width: 2.75rem; text-align: right; font-variant-numeric: tabular-nums; }
  .kk-repeat--type     { min-width: 5.5rem; }
  .kk-repeat--date     { min-width: 7.25rem; }
  .kk-repeat--document { min-width: 6rem; }

  .kk-diff {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .kk-diff--off {
    color: var(--color-red-600);
    font-weight: 600;
  }

  /* × and + on a row, and the who-panel's toggle: quiet icon buttons out of the Tab flow. */
  .kk-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-7);
    height: var(--space-7);
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-slate-500);
    font: inherit;
    line-height: 1;
    cursor: pointer;
  }

  .kk-icon-btn:hover {
    background: var(--color-white);
    border-color: var(--color-border);
    color: var(--color-text-heading);
  }

  .kk-icon-btn svg {
    width: 1rem;
    height: 1rem;
  }

  .kk-table form.button_to {
    display: inline;
  }

  .kk-number {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
  }

  .kk-empty {
    padding: var(--space-6) var(--space-4);
    text-align: center;
  }

  .kk-add {
    padding: var(--space-2) var(--space-3);
  }

  .kk-add form.button_to {
    display: inline;
  }

  .kk-difference {
    font-size: var(--text-xs);
  }

  /* The ⋮ menu: the modal triggers read as menu items. It sits at the page's right edge
     (the page is as wide as the grid), so the panel opens to the LEFT of the trigger and
     never past the viewport (CEO drive, 2026-09-08). */
  .kk-menu .modal-wrap {
    display: block;
  }

  .kk-menu .dropdown__panel {
    left: auto;
    right: 0;
  }

  /* A refused file's rows: every one named (the reader must not guess), in a box that
     scrolls rather than a page that does. */
  .import-refused-rows {
    max-height: 24rem;
    overflow-y: auto;
  }

  /* The # is the kassekladde's to appoint (CEO, slice 107): a dimmed box, narrow. Amber
     when the voucher will post past the VAT wall — the one thing a reader must be able
     to tell apart from any other green row. */
  .kk-readonly--number {
    min-width: 2.75rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  .kk-readonly--bypass {
    border-color: color-mix(in oklab, var(--color-warning) 45%, white);
    background: color-mix(in oklab, var(--color-warning) 12%, white);
    color: var(--color-amber-800);
    font-weight: 600;
  }

  /* --- The import's pieces (slice 94 → 107) ------------------------------------ */

  /* The amber VAT block: on the landing modal the consent beside its consequences; on
     the grid's summary the count that will post past the wall. Amber (slice 101 §7) —
     it is the one consent that makes the VAT return wrong, and neutral chrome did not
     say so. */
  .import-vat-bypass {
    margin-top: var(--space-3);
    padding: var(--space-3);
    border: 1px solid color-mix(in oklab, var(--color-warning) 32%, white);
    border-radius: var(--radius-md);
    background: color-mix(in oklab, var(--color-warning) 8%, white);
    color: var(--color-slate-900);
  }

  /* The count leads — the error and its remedy read as one thing. */
  .import-vat-bypass__lead {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
    color: var(--color-amber-800);
  }

  .import-vat-bypass__icon {
    width: 1.15rem;
    height: 1.15rem;
    flex: none;
  }

  /* The landing modal: what a landing replaces, and the box that accepts the bypass. */
  .import-landing__replace {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    color: var(--color-amber-800);
  }

  .import-landing__bypass {
    margin: 0 0 var(--space-2);
  }

  /* A mapped-but-informational file column (account name — inherited from the
     chart by number, never imported): acknowledged, greyed, not skipped. */
  .import-column--informational {
    opacity: 0.45;
  }

  /* The errors card: what is wrong across the whole kladde (or a refused file), and on
     how many journal entries. */
  .import-issues__title {
    font-size: var(--text-base);
    margin: 0 0 var(--space-3);
  }
  .import-issues__list {
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .import-issues__item {
    padding: 0.35rem 0;
    border-top: 1px solid var(--color-border);
  }
  .import-issues__item:first-child {
    border-top: 0;
  }
  .import-issues__fix {
    margin: 0.25rem 0 0;
  }

  /* A refused file's rows, named under the card. */
  .import-refused-rows {
    margin: 0;
    padding-left: 1.1rem;
    color: var(--color-red-600);
  }
  .import-refused-rows li {
    margin: 0.1rem 0;
  }

  /* The bottom of the rendered journal entries: the button that loads the next page
     when it scrolls into view. */
  .import-sentinel {
    display: flex;
    justify-content: center;
    padding: var(--space-3);
  }
}
