/* ============================================================
   ZAK UI — zak-ui.css
   Layer 2 for reg.zakwof.com.

   zak-theme.css owns the palette, the type, and the primitives: buttons,
   tables, pills, strips, fields, tabs and the three loaders. It does not know
   about an application shell, a selection bar, a dialog or a toast. This file
   adds those, using the same tokens and the same z- prefix, so it sits on the
   Laravel panel beside Bootstrap without a collision.

   Load order:
     1. bootstrap
     2. zak-theme.css   tokens + primitives
     3. zak-ui.css      shell, data, feedback
   z- wins where they overlap, and nothing here targets a bare element outside
   .z-root, so a page that has not been converted is untouched.

   ── PROVENANCE ──────────────────────────────────────────────
   Written from the Zakwof Design System spec (claude.ai design project
   9f39665a), not copied from its zak-ui.css: that file could not be extracted
   through the browser — the editor virtualises its rows, clipboard reads are
   refused, and the GetFile RPC returns protobuf. Every value below is taken
   from the published spec or from zak-theme.css, which the repo already has.
   If the original is ever exported, prefer it over this file.

   The house rules this obeys, all of them from the spec:
     · no pure white — paper, paper2, card are the only three grounds
     · ink is not black
     · depth comes from rules, not shadows
     · five meanings, no sixth — ink, red, green, amber, gold
     · red is the brand AND stop, so nothing else may be red
     · destructive is outlined, never filled
     · colour is never the only carrier — rows take a left rule too
     · every number carries a label and a sentence
   ============================================================ */

/* ------------------------------------------------------------
   0. ADDITIONS TO THE TOKEN SET
   Only what the shell genuinely needs and the base sheet lacks.
   ------------------------------------------------------------ */
.z-root {
  --sidebar-w: 232px;
  --sidebar-w-collapsed: 56px;
  --bar-h: 52px;
  --context-h: 40px;

  /* one step lighter and one darker than --bar, for the shell only */
  --bar2: #23272d;
  --bar-line: #33383f;

  --z-max: 1480px;

  /* The second sticky column's offset — the width of the checkbox column in front of it.
     A token rather than a fallback inside var(), so it can be found by reading the token
     block: a property that exists only as `var(--x, 34px)` is indistinguishable from a
     typo, and a typo'd custom property is dropped in silence. */
  --stick-2: 34px;
}

/*
   LIGHT, DELIBERATELY, AND SAID TO THE BROWSER.

   The ZAK system is paper with ink and opens with "NO PURE WHITE"; it has no dark
   palette, and zak-bridge.css already ruled on that — the bridge stands down under
   [data-bs-theme="dark"] and Sneat's own dark mode keeps running, because "that is a gap
   to close with the theme's author, not something to guess at here". The same holds
   here, so no dark token set is invented below.

   What this line fixes is the part that was actually broken rather than merely light: a
   .z-root surface inside a dark panel still inherited color-scheme: dark, so the browser
   painted the checkboxes, the <select> and the scrollbars dark — dark controls on cream
   paper. Declaring the scheme makes the UA agree with the surface it is drawing on.
*/
.z-root { color-scheme: light; }

/* ------------------------------------------------------------
   1. PAGE HEAD
   A heading, and a sentence saying what the screen is for. The sentence is
   not decoration: it is where "what counts as confirmed" gets said once,
   instead of in everybody's head.
   ------------------------------------------------------------ */
.z-page { max-width: var(--z-max); margin: 0 auto; }

.z-page__eyebrow {
  font-size: var(--size-xs); text-transform: uppercase; letter-spacing: var(--track);
  color: var(--muted); margin-bottom: var(--s1);
}

.z-page__head {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  justify-content: space-between; gap: var(--s4);
  padding-bottom: var(--s4); margin-bottom: var(--s4);
  border-bottom: 1px solid var(--line);
}

.z-page__title { font-size: var(--size-xl); font-weight: 700; line-height: 1.2; margin: 0; }
.z-page__say   { font-size: var(--size-md); color: var(--muted); margin: var(--s2) 0 0; max-width: 62ch; }
.z-page__acts  { display: flex; flex-wrap: wrap; gap: var(--s2); }

/* ------------------------------------------------------------
   2. FILTER RAIL
   .z-tabs in the base sheet already carries the counts. This is the row it
   sits in, with the search and the column control beside it.
   ------------------------------------------------------------ */
.z-rail {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2);
  padding: var(--s2) 0; border-bottom: 1px solid var(--line2);
}
.z-rail__spacer { flex: 1 1 auto; }
.z-rail__search { min-width: 220px; flex: 0 1 320px; }

/* What is currently excluded, said out loud. A filtered table that looks like
   an unfiltered one is how "where did those rows go?" happens. */
.z-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); padding: var(--s2) 0; }
.z-chip {
  display: inline-flex; align-items: center; gap: var(--s1);
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--paper2); color: var(--ink);
  font-size: var(--size-sm); padding: 2px var(--s2); cursor: pointer;
}
.z-chip:hover { border-color: var(--ink); }
.z-chip__x { color: var(--muted); font-weight: 700; }

/* Said to a screen reader, not drawn. `display:none` would remove it from the
   accessibility tree as well, which is the opposite of the point. */
.z-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* A sortable column header, and a row action, are BUTTONS — they act on the page, they
   do not go anywhere, and a keyboard has to be able to reach them. zak-theme.css styles
   .z-link for an <a>, so on a <button> the browser's own chrome came through: a grey
   outset box, 10px text and no letter-spacing, in a header row that is otherwise small
   caps. This is the reset that was missing, not a rule about this screen. */
button.z-link {
  appearance: none; -webkit-appearance: none;
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  color: inherit; cursor: pointer; text-align: inherit;
}
button.z-link:hover { color: var(--red); }
button.z-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* The row's own controls.
   NOT hover-revealed: an action that only exists while the pointer is over it cannot be
   found by reading and cannot be reached by tabbing. They are quiet instead of hidden.
   nowrap is load-bearing — .z-row wraps, and three wrapped buttons turned a 33px row
   into 60px, which is the whole dense table gone. */
/* The declared column widths are the truth.
   Without this the browser sizes columns from their content, and a cell with
   `max-width: 0` — which is how an ellipsis is done in a table — asks for almost nothing
   and loses its width to whichever neighbour has the longest word. That is why the Ticket
   column read "STO…" while Organisation had room to spare. */
.z-table--cols { table-layout: fixed; }

/* One line, or an ellipsis and a tooltip.
   A job title like "Technical Customer Support" wrapped to three lines and took the row
   with it: every row in the table was sized by its longest free-text field, which is the
   opposite of a dense table. The full value stays reachable — the cell carries it as its
   title — so nothing is lost, only folded. */
.z-clip { max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.z-acts { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--s2); white-space: nowrap; }
.z-acts button { font-size: var(--size-xs); text-transform: uppercase; letter-spacing: var(--track); color: var(--muted); }
.z-acts button:hover { color: var(--red); }
/* Anchored on .z-table, not on a bare `tr`, so the sheet keeps its promise: every
   selector in this file begins with a z- class. */
.z-table tr:hover .z-acts button { color: var(--ink); }
.z-table tr:hover .z-acts button:hover { color: var(--red); }

/* ------------------------------------------------------------
   3. DENSE TABLE
   33px rows. The base .z-table is comfortable; this is the working density
   for a list somebody reads all day.
   ------------------------------------------------------------ */
.z-table--dense th { padding: var(--s1) var(--s2); }
.z-table--dense td { padding: var(--s1) var(--s2); height: 33px; }
/* A two-line cell: the thing, and the quieter thing under it. Deliberately NOT scoped to
   --dense — the density toggle removes that class at runtime, and a name that loses its
   email halfway through a session is worse than either density. */
.z-table__two { line-height: 1.25; }
.z-table__two > * { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.z-table__two small { color: var(--muted); font-size: var(--size-xs); }

/* The status rail. Colour is never the only carrier of meaning — the pill
   says it in words, and this says it again at the edge so the table still
   reads when the colour does not. */
.z-table td.z-rule { border-left: 3px solid transparent; padding-left: var(--s2); }
.z-table td.z-rule--ink   { border-left-color: var(--ink); }
.z-table td.z-rule--red   { border-left-color: var(--red); }
.z-table td.z-rule--green { border-left-color: var(--green); }
.z-table td.z-rule--amber { border-left-color: var(--amber); }
.z-table td.z-rule--gold  { border-left-color: var(--gold); }
.z-table td.z-rule--none  { border-left-color: var(--line); }

/* Who the row is, kept on screen while the rest scrolls.

   The offset lives HERE, not in the markup. It was on the <th> as an inline style, which
   pinned the header and left every <td> with `position: sticky` and no `left` — so the
   column header stayed put while the names underneath it scrolled away and the pinned
   header sat on top of whatever had scrolled under it. Sticky with no offset is not an
   error and draws no warning; it simply does nothing.

   A screen that needs a different first column sets --stick-2 on the table. */
.z-table .z-stick { position: sticky; left: 0; z-index: 2; background: var(--card); }
.z-table .z-stick--2 { position: sticky; left: var(--stick-2, 34px); z-index: 2; background: var(--card); border-right: 1px solid var(--line); }
.z-table thead .z-stick, .z-table thead .z-stick--2 { z-index: 4; background: var(--paper2); }
.z-table tr:hover .z-stick, .z-table tr:hover .z-stick--2 { background: var(--paper2); }

/* Three letters, not three pills: the channel column says what was sent
   without spending three badges on it. */
.z-sew { font-family: var(--font-mono); font-size: var(--size-xs); letter-spacing: .08em; color: var(--line); }
.z-sew b { font-weight: 700; font-style: normal; }
.z-sew .is-on   { color: var(--green-text); }
.z-sew .is-fail { color: var(--red-text); }

/* ------------------------------------------------------------
   4. SELECTION BAR
   Replaces a bulk dropdown. It states what each action can act on BEFORE it
   is pressed, because an action that can reach nobody still returns 200.
   ------------------------------------------------------------ */
.z-selbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; justify-content: center; padding: var(--s3);
  pointer-events: none;
  opacity: 0; transform: translateY(8px);
  transition: opacity var(--fast) ease, transform var(--fast) ease;
}
.z-selbar.is-on { opacity: 1; transform: none; }

.z-selbar__in {
  pointer-events: auto;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2);
  background: var(--bar); color: var(--on-bar);
  border-radius: var(--r); padding: var(--s2) var(--s3);
  box-shadow: var(--shadow);
}
.z-selbar__count { font-weight: 700; font-variant-numeric: tabular-nums; }
.z-selbar__sep { width: 1px; align-self: stretch; background: var(--bar-line); }

.z-selbar__act {
  background: transparent; color: var(--on-bar);
  border: 1px solid var(--bar-line); border-radius: var(--r);
  font: inherit; font-size: var(--size-sm); padding: var(--s1) var(--s2); cursor: pointer;
}
.z-selbar__act:hover:not(:disabled) { background: var(--bar2); }

/* Disabled stays READABLE and says why. The point of the bar is to show what
   you cannot do; a button dimmed past legibility defeats it. Spec: 45%. */
.z-selbar__act:disabled { border-color: transparent; opacity: .45; cursor: not-allowed; }
.z-selbar__act b { font-weight: 400; font-variant-numeric: tabular-nums; opacity: .8; margin-left: var(--s1); }

/* Destructive is outlined, never filled: a red block invites the click it is
   warning about. */
.z-selbar__act--danger { border-color: var(--red); color: var(--red); }
.z-selbar__act--danger:hover:not(:disabled) { background: var(--red); color: var(--on-bar); }

.z-selbar__esc { font-size: var(--size-xs); color: var(--muted); margin-left: var(--s2); }

/* ------------------------------------------------------------
   5. EMPTY STATES
   Two situations that mean opposite things, so two sentences.
   ------------------------------------------------------------ */
.z-empty { text-align: center; padding: var(--s6) var(--s4); }
.z-empty__what { font-weight: 700; }
.z-empty__why  { color: var(--muted); font-size: var(--size-sm); margin-top: var(--s1); }

/* ------------------------------------------------------------
   6. FEEDBACK — four dialogs, one toast, one strip
   Replaces SweetAlert2, Notyf and the inline Bootstrap banners. The base
   sheet already owns .z-strip; this adds the other two.

   A confirm before an act, a result after it, a refusal when it could not
   happen, and the armed delete. The button says the act and the count —
   never OK, never Yes.
   ------------------------------------------------------------ */
.z-dialog {
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--card); color: var(--ink);
  padding: 0; max-width: 30rem; width: calc(100vw - var(--s6));
  font: inherit;
}
.z-dialog::backdrop { background: rgba(22, 24, 28, .45); }
.z-dialog__kind {
  font-size: var(--size-xs); text-transform: uppercase; letter-spacing: var(--track);
  color: var(--muted); padding: var(--s3) var(--s4) 0;
}
.z-dialog__title { font-size: var(--size-lg); font-weight: 700; margin: var(--s1) 0 0; padding: 0 var(--s4); }
.z-dialog__body  { font-size: var(--size-md); color: var(--ink); margin: var(--s2) 0 0; padding: 0 var(--s4); }
.z-dialog__foot  {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s4); margin-top: var(--s3); border-top: 1px solid var(--line2);
}
.z-dialog__esc { margin-left: auto; font-size: var(--size-xs); color: var(--muted); }

/* The four kinds differ by a single top rule, not by a coloured ring. */
.z-dialog--confirm { border-top: 3px solid var(--ink); }
.z-dialog--done    { border-top: 3px solid var(--green); }
.z-dialog--refused { border-top: 3px solid var(--amber); }
.z-dialog--delete  { border-top: 3px solid var(--red); }

.z-toasts { position: fixed; top: var(--s4); right: var(--s4); z-index: 60; display: flex; flex-direction: column; gap: var(--s2); }
.z-toast {
  border: 1px solid var(--line); border-left: 3px solid var(--ink);
  background: var(--card); color: var(--ink);
  border-radius: var(--r); padding: var(--s2) var(--s3);
  font-size: var(--size-sm); max-width: 28rem; box-shadow: var(--shadow);
}
.z-toast--ok   { border-left-color: var(--green); }
.z-toast--warn { border-left-color: var(--amber); }
.z-toast--bad  { border-left-color: var(--red); }

/* ------------------------------------------------------------
   7. PRINT
   Rules survive, colour does not. The left rule is the reason the table is
   still readable here.
   ------------------------------------------------------------ */
@media print {
  .z-selbar, .z-toasts, .z-rail, .z-chips { display: none !important; }
  .z-table--dense td { height: auto; }
}
