/*
 * The back office's own components — DESIGN.md section 9a, TIER C.
 *
 * Everything here styles markup this project wrote and Django never touches:
 * the dashboard bands, the stat tiles, the data tables and the status pills.
 * That is why it is a separate file from admin-theme.css. Nothing in here
 * can break on a Django upgrade, and nothing in admin-theme.css is free of
 * that risk — keeping them apart is what makes the difference legible.
 *
 * The `zn-` prefix exists so these class names can never collide with
 * Django admin's own, which are unprefixed and numerous.
 */

/* ---- Bands -------------------------------------------------------------
   One band per question the dashboard answers. */
.zn-band {
  margin-block-end: var(--space-4);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--color-surface-soft);
}

.zn-band__title {
  margin: 0 0 var(--space-2);
  font-family: var(--font-display);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-xs);
  letter-spacing: var(--track-ui);
  text-transform: uppercase;
  color: var(--color-text-primary);
}

.zn-band__note {
  margin: 0 0 var(--space-2);
  max-inline-size: var(--measure);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* Spacing between the blocks inside a band, set on the flow rather than on
   each block.

   `.zn-table` used to carry its own top margin, which put the space *inside*
   `.zn-table-scroll` — a scroll container, so the margin never reached the
   gap between siblings. It happened to look right where a table followed
   something, and gave nothing at all where tiles followed a table: measured
   0px in three of the four bands, against 16px everywhere else.

   One rule on the parent means a new block added to a band is spaced
   correctly without anyone remembering to space it. Adjacent margins
   collapse, so the headings' own bottom margins do not add to this. */
.zn-band > * + * {
  margin-block-start: var(--space-3);
}

/* ---- The break between the two halves of the home page -----------------
   Above it: what happened and what needs doing. Below it: the index of
   every record. Different jobs, and without a marker the page reads as
   though it ended and restarted. Deliberately quiet — it is a signpost, not
   a third thing competing with the two it separates. */
.zn-section-break {
  margin-block: var(--space-5) var(--space-3);
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--color-border-soft);
}

.zn-section-break__title {
  margin: 0 0 var(--space-0);
  font-family: var(--font-display);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-lg);
  color: var(--color-text-primary);
}

.zn-section-break__note {
  margin: 0;
  max-inline-size: var(--measure);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ---- Stat tiles --------------------------------------------------------
   auto-fit rather than a fixed column count: the bands hold two to four
   tiles depending on what is wrong today, and a fixed grid would leave a
   hole on the days when nothing is. */
.zn-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--space-2);
}

.zn-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-0);
  padding: var(--space-2);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
  color: var(--color-text-primary);
  text-decoration: none;
}

.zn-stat--linked:hover,
.zn-stat--linked:focus-visible {
  border-color: var(--color-border);
}

/* Every part states its own colour, and none of them inherit.
 *
 * A linked tile is an <a> inside Django's #content, which carries
 * `#content a { color: var(--link-fg) }` — an ID selector at 1-0-1-0 that
 * outranks any plain class. The first version of this file set the colour on
 * `.zn-stat--alarm` and it silently lost: Cocoa text rendered on the rust
 * fill, which is the one combination in the palette that is genuinely
 * unreadable, and only a browser showed it. DESIGN.md section 8b rule 2, for
 * the fourth time in this project.
 *
 * The fix is not to out-specify #content — that would make these rules
 * depend on a Django selector, and they would break silently if it ever
 * changed. Inheritance has no specificity at all, so naming the colour on
 * each child element beats the inherited value whatever the anchor is doing.
 */
.zn-stat__value {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-primary);
}

.zn-stat__label {
  font-size: var(--text-sm);
  color: var(--color-text-primary);
}

.zn-stat__note {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* The three tones. DESIGN.md section 9b: two hues, and everything else is
   fill and weight. Each tone is also always accompanied by its word in the
   label or note — a staff member who cannot separate moss from rust reads
   exactly the same information, which is section 2's rule and is not
   relaxed here. */
.zn-stat--attention {
  border-color: var(--color-attention);
  background: var(--color-attention-soft);
}

.zn-stat--attention .zn-stat__value {
  color: var(--color-attention);
}

/* Alarm is the only solid fill in the system, reserved for states that are
   faults rather than workload: stock below zero, a ledger that disagrees
   with itself, a confirmation call left overnight. If this is ever on
   screen for something routine, the tone is wrong, not the design. */
.zn-stat--alarm {
  border-color: var(--color-attention);
  background: var(--color-attention);
}

.zn-stat--alarm .zn-stat__value,
.zn-stat--alarm .zn-stat__label {
  color: var(--sand);
}

.zn-stat--alarm .zn-stat__note {
  color: color-mix(in srgb, var(--sand) 85%, transparent);
}

.zn-stat--positive {
  border-color: var(--color-positive);
  background: var(--color-positive-soft);
}

.zn-stat--positive .zn-stat__value {
  color: var(--color-positive);
}

/* ---- Tables ------------------------------------------------------------
   Owned tables, not Django's changelist — this is the inline detail under a
   band. */
.zn-table {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.zn-table th,
.zn-table td {
  padding-block: var(--space-1);
  padding-inline: var(--space-1);
  text-align: start;
  border-block-end: 1px solid var(--color-border-soft);
}

.zn-table thead th {
  font-family: var(--font-display);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-xs);
  letter-spacing: var(--track-ui);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.zn-table tbody th {
  font-weight: var(--font-weight-regular);
}

/* Numbers line up on their last digit or the column is decoration.
 *
 * Qualified with `.zn-table` and the element, because the bare `.zn-num`
 * (0-0-1-0) loses to `.zn-table th, .zn-table td` (0-0-2-0) above and every
 * figure silently rendered left-aligned. Same trap as the stat tiles, in a
 * file written the same afternoon — DESIGN.md section 8b rule 2 does not
 * care that you have just read it. Caught by measuring computed style, not
 * by looking at a screenshot, where a column of similar-length numbers looks
 * plausible either way. */
.zn-num,
.zn-table th.zn-num,
.zn-table td.zn-num {
  text-align: end;
  font-variant-numeric: tabular-nums;
}

/* A wide table scrolls inside its own box rather than pushing the page
   sideways. The back office is desktop-first, but a laptop at 1024px still
   meets the six-column stock table. */
.zn-table-scroll {
  overflow-x: auto;
}

/* ---- Pills -------------------------------------------------------------
   A status word with a wash behind it. The word is the message; the wash
   only makes it findable in a column. */
.zn-pill {
  display: inline-block;
  padding-block: var(--space-0);
  padding-inline: var(--space-1);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  white-space: nowrap;
}

.zn-pill--attention {
  background: var(--color-attention-soft);
  color: var(--color-attention);
}

.zn-pill--alarm {
  background: var(--color-attention);
  color: var(--sand);
}

.zn-pill--positive {
  background: var(--color-positive-soft);
  color: var(--color-positive);
}

/* Quiet by default — a finished state should recede, not compete with the
   things that still need doing. */
.zn-pill--quiet {
  border: 1px solid var(--color-border-soft);
  color: var(--color-text-muted);
}

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

/* An uploaded photo shown inside a form — review photos today. Was an inline
   style with a hardcoded 6px radius, which is not one of the three radius
   tiers and so quietly disagreed with everything around it. */
.zn-thumb {
  max-block-size: 7.5rem;
  border-radius: var(--radius-sm);
}

/* ---- The confirmation call queue ---------------------------------------
   One card per call, worked top to bottom. Not a table: a table is for
   comparing rows, and nobody compares calls — they make one, then the next.
   Each card holds who to ring, what they ordered, and the two decisions. */

.zn-queue-head__note {
  margin: 0 0 var(--space-3);
  max-inline-size: var(--measure);
  color: var(--color-text-muted);
}

.zn-calls {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}

/* Three columns on a desktop — who / what / decide — collapsing to one
   below 60rem. The back office is desktop-first, but the confirmation call
   is the one screen genuinely likely to be made from a phone, so it has to
   survive a narrow window. */
.zn-call {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
}

@media (min-width: 60rem) {
  .zn-call {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) auto;
    align-items: start;
    gap: var(--space-3);
  }
}

/* A left edge, not a fill. This card is still ordinary work — the marker
   says "read the note before you dispatch", not "something is wrong". A
   full attention wash here would make every third card shout. */
.zn-call--care {
  border-inline-start: 3px solid var(--color-attention);
}

.zn-call__name {
  margin: 0;
  font-size: var(--text-base);
}

/* The number is the largest thing on the card, because dialling it is the
   entire purpose of the screen. */
.zn-call__phone {
  display: inline-flex;
  align-items: center;
  margin-block: var(--space-0);
  font-size: var(--text-lg);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
}

.zn-call__phone:hover,
.zn-call__phone:focus-visible {
  text-decoration: underline;
}

.zn-call__address,
.zn-call__waiting,
.zn-call__note {
  margin: var(--space-0) 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.zn-call__order {
  margin: 0 0 var(--space-1);
  font-size: var(--text-base);
}

.zn-call__items {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--text-sm);
}

.zn-call__items li {
  margin-block-end: var(--space-0);
}

.zn-call__waiting {
  display: flex;
  align-items: center;
  margin-block-start: var(--space-1);
}

/* Overdue is stated in the text as well as the colour. */
.zn-call__waiting--stale {
  color: var(--color-attention);
}

.zn-call__note {
  display: flex;
  align-items: center;
}

.zn-call__note--flag {
  color: var(--color-attention);
}

.zn-call__note--good {
  color: var(--color-positive);
}

.zn-call__decide {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-inline-size: 12rem;
}

/* Confirm is the primary action and cancel is folded away behind a
   disclosure. Both are one click from here, but they are not equals: most
   calls succeed, and cancelling restores stock and ends the order, so it
   should take a deliberate second step rather than sit under the thumb. */
.zn-btn {
  display: inline-block;
  padding-block: var(--space-1);
  padding-inline: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: none;
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background-color var(--duration-fast) ease-out,
    border-color var(--duration-fast) ease-out;
}

.zn-btn--confirm {
  inline-size: 100%;
  border-color: var(--color-positive);
  background: var(--color-positive);
  color: var(--sand);
}

.zn-btn--confirm:hover,
.zn-btn--confirm:focus-visible {
  background: color-mix(in srgb, var(--color-positive) 85%, black);
}

.zn-btn--cancel {
  inline-size: 100%;
  margin-block-start: var(--space-1);
  border-color: var(--color-attention);
  color: var(--color-attention);
}

.zn-btn--cancel:hover,
.zn-btn--cancel:focus-visible {
  background: var(--color-attention-soft);
}

.zn-call__cancel > summary {
  padding-block: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  cursor: pointer;
  text-align: center;
}

.zn-call__cancel label {
  display: block;
  margin-block: var(--space-1) var(--space-0);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.zn-call__cancel input[type="text"] {
  inline-size: 100%;
  padding-block: var(--space-1);
  padding-inline: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--text-sm);
}

/* The result of a decision. Announced as well as drawn — the row it refers
   to has just been removed, so there is nothing left on screen to look at. */
.zn-flash {
  margin: 0 0 var(--space-2);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-soft);
  font-size: var(--text-sm);
}

.zn-flash--positive {
  border-color: var(--color-positive);
  background: var(--color-positive-soft);
}

.zn-flash--attention {
  border-color: var(--color-attention);
  background: var(--color-attention-soft);
}

.zn-flash--alarm {
  border-color: var(--color-attention);
  background: var(--color-attention);
  color: var(--sand);
}

.zn-empty {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-surface-soft);
  color: var(--color-text-muted);
}

/* ---- Stock screens ------------------------------------------------------
   Goods-in and stocktake are the same shelf, entered into for opposite
   reasons: one adds to it, the other checks it. */

.zn-shelf-search {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-block-end: var(--space-3);
  font-size: var(--text-sm);
}

.zn-shelf-search input[type="text"] {
  inline-size: 18rem;
  padding-block: var(--space-1);
  padding-inline: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: inherit;
}

.zn-field {
  display: block;
  margin-block-end: var(--space-0);
  font-size: var(--text-xs);
  letter-spacing: var(--track-ui);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.zn-band input[type="text"] {
  inline-size: min(100%, 24rem);
  padding-block: var(--space-1);
  padding-inline: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--text-sm);
}

/* A number typed into a table cell. Narrow and right-aligned so a column of
   them reads as a column, and tabular so the digits line up while typing.

   The element is named in the selector because `.zn-cell-input` alone
   (0-0-1-0) loses to Django admin's own `input[type="text"]` rules — the
   specificity trap this project has now hit five times. */
input[type="text"].zn-cell-input {
  inline-size: 5rem;
  padding-block: var(--space-0);
  padding-inline: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  text-align: end;
  font-variant-numeric: tabular-nums;
}

/* A submit button that is not filling a card's width. */
.zn-btn--inline {
  inline-size: auto;
}

/* ---- Scanning -----------------------------------------------------------
   A scan box is an ordinary text input. That is the whole design: a shop
   scanner is a keyboard, so the same box works whether the code arrives from
   a scanner in three milliseconds or from somebody typing it because the
   scanner is flat. */
.zn-scan {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-block-end: var(--space-3);
  padding: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
}

input[type="text"].zn-scan__input {
  inline-size: 16rem;
  padding-block: var(--space-1);
  padding-inline: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--text-base);
  letter-spacing: 0.04em;
  transition: background-color var(--duration-fast) ease-out,
    border-color var(--duration-fast) ease-out;
}

/* Momentary colour rather than a dialog: the hands are holding a parcel, and
   anything that needs dismissing stops the flow. Both states also change the
   border, so the feedback is not colour alone — DESIGN.md section 2. */
.zn-scan--hit {
  border-color: var(--color-positive);
  background: var(--color-positive-soft);
}

.zn-scan--miss {
  border-width: 2px;
  border-color: var(--color-attention);
  background: var(--color-attention-soft);
}

.zn-scan__hint {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* A row the scanner has just jumped to. */
.zn-table tbody tr:focus-within {
  background: var(--color-surface-soft);
}

.zn-verify__actions {
  display: flex;
  gap: var(--space-1);
  margin-block-start: var(--space-3);
}

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