/* --- State badges --- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.16em 0.55em;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 550;
  letter-spacing: 0.01em;
  border: 1px solid var(--line-strong);
  color: var(--text-dim);
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 0.44em;
  height: 0.44em;
  border-radius: 999px;
  background: currentcolor;
}

.badge--pos {
  color: var(--pos);
  border-color: color-mix(in srgb, var(--pos) 35%, transparent);
  background: var(--pos-soft);
}

.badge--neg {
  color: var(--neg);
  border-color: color-mix(in srgb, var(--neg) 35%, transparent);
  background: var(--neg-soft);
}

.badge--info {
  color: var(--info);
  border-color: color-mix(in srgb, var(--info) 35%, transparent);
  background: var(--info-soft);
}

.badge--brass {
  color: var(--brass);
  border-color: color-mix(in srgb, var(--brass) 35%, transparent);
  background: var(--brass-soft);
}

/* --- Definition facts --- */
.facts {
  display: grid;
  grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr);
  gap: 0.55rem 1rem;
  margin: 0;
  font-size: 0.88rem;
}

.facts dt {
  color: var(--text-faint);
}

.facts dd {
  margin: 0;
  overflow-wrap: anywhere;
}

pre {
  margin: 0;
  padding: 0.85rem;
  background: var(--sunk);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 0.76rem;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text-dim);
}

/* The report preview keeps its columns rather than reflowing them.

   The plain body is laid out for a mail client with the label in one column and
   the figure in the next, and the global `pre` sets `white-space: pre-wrap`,
   which is right for a stack trace and wrong here: in the detail sheet's width
   every figure's window wrapped onto its own line and the warnings table became
   one value per row. `pre` already carries `overflow-x: auto`; it simply never
   engages while the text is allowed to wrap. */
.report-preview {
  white-space: pre;
  overflow-wrap: normal;
}

.empty {
  padding: 3rem 1rem;
  text-align: center;
  color: var(--text-faint);
  font-size: 0.9rem;
}

/* --- Right-hand drill-in sheet --- */
.sheet {
  position: fixed;
  inset: 0;
  display: flex;
  justify-content: flex-end;
  z-index: 20;
}

.sheet__scrim {
  position: absolute;
  inset: 0;
  background: rgb(6 8 10 / 45%);
}

.sheet__panel {
  position: relative;
  width: min(31rem, 100%);
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  animation: sheet-in 200ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* One sheet, two widths (#551). A split is a row of Objekt, Einheit, Konto,
   Betrag and two dates, and 31 rem leaves that row 496 px. The other callers of
   `#detail` are a column of fields and keep the narrow panel, which is what lets
   the list behind the sheet stay readable while an inbox is worked. */
.sheet__panel--wide {
  width: min(52rem, 100%);
}

@keyframes sheet-in {
  from {
    transform: translateX(2rem);
    opacity: 0;
  }
}

.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.4rem 1.5rem;
  border-bottom: 1px solid var(--line);
}

.sheet__head > .btn {
  flex: none;
}

/* A flex item defaults to min-width: auto and refuses to shrink below its
   content, so a long unbroken title — a filename, a path — pushed straight
   through the close button. */
.sheet__head > div {
  min-width: 0;
}

.sheet__amount {
  font-size: 1.7rem;
  font-weight: 300;
  overflow-wrap: anywhere;
}

/* The line under a sheet's title, which sometimes carries a badge beside the
   text — the Benutzer sheet puts the account's state there rather than across
   the body. Inline they touched, so the row is a flex one with a gap; a lone
   text node renders exactly as it did. */
.sheet__sub {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  color: var(--text-dim);
  font-size: 0.9rem;
  margin-top: 0.15rem;
  overflow-wrap: anywhere;
}

/* A column rather than a grid, and one that fills the panel, so the command row
   can be a footer: `margin-top: auto` on a grid item stays inside its own track
   and cannot reach the bottom of the container, where on a flex column it takes
   every pixel left over.

   The reason it has to be a footer is #562's own measurement. The row was the
   last thing in a body that stopped where its content stopped, so a card
   arriving 34 ms after the sheet opened pushed `Aktionen` down 65 px — and no
   amount of space reserved for a read of unknown length fixes that, because the
   length is unknown. Anchored to the panel, the row does not move whatever
   arrives above it.

   `flex: 0 0 auto` on the children because this box scrolls: flex items shrink
   below their content by default, which would squeeze a long sheet instead of
   letting it scroll. */
.sheet__body {
  padding: 1.5rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: 1.35rem;
}

.sheet__body > * {
  flex: 0 0 auto;
}

/* The command row sits at the foot of the sheet, not at the foot of whatever has
   loaded so far. Where the sheet overflows, `auto` yields nothing and the row
   follows the content into the scroll, which is where it belongs.

   `:last-child` because the row is not always the last thing in a sheet — the
   Benutzer record carries its history below its commands. Pushing a row that
   has siblings after it would open a gap in the middle of a short sheet, which
   is a second defect rather than a fix for the first. */
.sheet__body > .record-form__actions:last-child {
  margin-top: auto;
}

/* --- The shape of what is not yet known --- */

/* Space taken and nothing shown: the shapes are in the container from the first
   tick, so a box is the size it needs before the read lands and a read nobody
   notices moves nothing on the page. `visibility` and not `opacity`, because it
   keeps the layout and takes the sentence out of the screen reader's tree with
   it — at this point there is nothing to announce.

   The reveal at 250 ms only drops this class, so the shapes appear in space that
   was already theirs and the threshold cannot shift a pixel either. */
.is-reserved {
  visibility: hidden;
}

/* Drawn only once a read outlives the threshold in `whileLoading`, and never
   before: at the four milliseconds a local read costs, these would be a grey
   blink on every tab change. Grey blocks in the same grid as the real thing, so
   the page does not jump when the answer lands.

   Built for the helpdesk card in #472 and shared from #562 on, which is why the
   frame is the caller's: one head bar and a few lines sized by whatever holds
   them is the whole of it, and a shape per component is how this becomes a set
   nobody maintains. */
.skeleton {
  display: grid;
  gap: 0.55rem;
  pointer-events: none;
}

.skeleton__head,
.skeleton__line {
  border-radius: 3px;
  background: var(--line);
}

.skeleton__head {
  width: 40%;
  height: 1.1rem;
}

.skeleton__line {
  height: 0.8rem;
}

/* A row of a list, not a card: one line at about the height a `konto-list` row
   draws, so the space held is close to the space taken.

   Approximate, and it cannot be otherwise: `.konto` sets no height, it is its
   text plus 0.7rem of padding and a rule, so there is no token to point at and
   the figure is measured rather than derived. It is worth having anyway — a row
   reserved as a card was 93px against 21px of content, and that overshoot moved
   the page further than reserving nothing had. */
.skeleton--row .skeleton__line {
  height: 1.3rem;
}

.skeleton__line:nth-child(2) {
  width: 85%;
}

.skeleton__line:nth-child(3) {
  width: 60%;
}

/* Slow enough to read as breathing rather than as blinking, and declared only
   where motion is welcome — so under `reduce` there is no animation to shorten
   and `animation-name` computes to `none`, rather than to a keyframe running in
   a millisecond. */
@media (prefers-reduced-motion: no-preference) {
  .skeleton {
    animation: skeleton-breathe 1.6s ease-in-out infinite;
  }

  @keyframes skeleton-breathe {
    0%,
    100% {
      opacity: 1;
    }
    50% {
      opacity: 0.55;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}
