/* ============================================================
   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:
     · (since 27-Oct-2026, the Zak ONE kit) Paper White cards on Warm Chalk,
       Ink Black type, a soft shadow under a card
     · one accent, Burnt Orange, as rules and rings; words on it are Deep Orange
     · red is danger only
     · 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 than --bar and its hairline, for the shell only */
  --bar2: #282622;
  --bar-line: #3a3630;

  --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 BY DEFAULT, AND SAID TO THE BROWSER.

   Since the Elevation revision the system DOES have a dark palette — dusk graphite, in
   zak-colours.css — which retunes every token under html[data-bs-theme="dark"] and flips
   this color-scheme with it (its selectors live there so this file keeps its promise
   that every selector here starts with a z- class).

   What this line fixes in light mode is unchanged: a .z-root surface inside a dark panel
   otherwise inherited color-scheme: dark, so the browser painted the checkboxes, the
   <select> and the scrollbars dark — dark controls on a light surface. 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); font-weight: var(--w-label); 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: var(--w-head); line-height: 1.3; letter-spacing: -.01em; margin: 0; color: var(--ink); }
.z-page__say   { font-size: 13px; 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-pill);
  background: var(--card); color: var(--muted);
  font-size: 11.5px; font-weight: var(--w-strong); padding: 4px 12px; cursor: pointer;
}
.z-chip:hover { border-color: var(--brand); color: var(--accent-text); }
.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(--accent-text); }
button.z-link:focus-visible { outline: var(--focus-ring); 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(--accent-text); }
/* 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(--accent-text); }

/* ------------------------------------------------------------
   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(--muted); opacity: .55; }
.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-lg); padding: var(--s2) var(--s3);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .35);
}
.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(--ink-danger-text); }
.z-selbar__act--danger:hover:not(:disabled) { background: var(--ink-danger-text); color: var(--bar); }

.z-selbar__esc { font-size: var(--size-xs); color: var(--bar-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-lg);
  background: var(--card); color: var(--ink);
  padding: 0; max-width: 32.5rem; width: calc(100vw - var(--s6));
  box-shadow: 0 18px 50px rgba(20, 20, 20, .22);
  font: inherit;
}
.z-dialog::backdrop { background: rgba(20, 20, 20, .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(--brand); }
.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); }
/* A toast is Ink with white words, in both themes (the kit); its kind is the left rule. */
.z-toast {
  border: 1px solid var(--bar-line); border-left: 3px solid var(--brand);
  background: var(--bar); color: var(--on-bar);
  border-radius: var(--r); padding: var(--s2) var(--s3);
  font-size: var(--size-sm); max-width: 28rem; box-shadow: 0 8px 26px rgba(0, 0, 0, .35);
}
.z-toast--ok   { border-left-color: var(--ink-good); }
.z-toast--warn { border-left-color: var(--ink-warn); }
.z-toast--bad  { border-left-color: var(--ink-danger); }

/* ------------------------------------------------------------
   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; }
}

/* ------------------------------------------------------------
   THE BRAND'S ELEMENTS (2027 guidelines, section 06)
   "A small kit of recurring devices gives every layout the same rhythm.
   Reuse these rather than inventing new ones." Four of them belong on a
   screen; the event card's ghost number is used only in lists of events.

   Since 27-Oct-2026 they follow the Zak ONE UI kit (docs/ZAK-ONE-UI.md):

   z-kicker    the eyebrow over a heading: Medium, 11px, +0.08em, capitals,
               muted, as the kit sets eyebrows and kickers.
   z-rule      the Burnt Orange rule under a heading: 52 x 4, rounded. A rule
               is orange's job; words never are.
   z-lockup    the stat lockup: a Heavy figure and a Bold capitals caption.
   z-masthead  the masthead panel: an Ink block with a Burnt Orange left
               border, for one event's header. White heading, chalk text, the
               small orange (#f0834f) kicker, in both themes, because the
               masthead is Ink in both.

   Usage:
     <p class="z-kicker">Registration · 4 of 7</p>
     <h1 class="z-h1">Riyadh 2026</h1>
     <span class="z-rule"></span>
   ------------------------------------------------------------ */
.z-kicker {
  display: block;
  font: var(--w-label) var(--size-xs)/1.3 var(--font);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--kicker);
  margin: 0 0 var(--s2);
}
.z-rule {
  display: block;
  width: 52px; height: 4px;
  border-radius: 2px;
  background: var(--brand);
  margin: var(--s3) 0 var(--s4);
}
.z-rule--tight { margin: var(--s2) 0 var(--s3); }

.z-lockup { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.z-lockup b {
  font-weight: var(--w-num);
  font-size: var(--size-num);
  line-height: 1;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.z-lockup span {
  font-size: var(--size-th);
  font-weight: var(--w-strong);
  letter-spacing: var(--track-th);
  text-transform: uppercase;
  color: var(--muted);
}
/* The one figure that needs somebody: danger, in its text value. */
.z-lockup.is-bad b { color: var(--red-text); }

.z-masthead {
  --mast-ink: var(--on-bar);
  --mast-muted: var(--bar-muted);
  background: var(--bar);
  color: var(--bar-body);
  border-left: 6px solid var(--brand);
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
  padding: var(--s5) var(--s6) var(--s5) var(--s5);
}
.z-masthead .z-kicker { color: var(--brand-2); }
.z-masthead .z-h1,
.z-masthead h1 { color: var(--mast-ink); font-size: var(--size-2xl); font-weight: var(--w-head); letter-spacing: -.02em; line-height: 1.05; margin: 0; }
.z-masthead .z-muted,
.z-masthead p { color: var(--mast-muted); margin: var(--s2) 0 0; }
.z-masthead .z-lockup b { color: var(--mast-ink); }
.z-masthead .z-lockup span { color: var(--mast-muted); }
@media (max-width: 575.98px) {
  .z-masthead { padding: var(--s4); }
  .z-masthead .z-h1,
  .z-masthead h1 { font-size: var(--size-xl); }
}

/* ── Phase pill (<x-phase-pill>, EventPhase; the owner, 28-Oct-2026: "live must be green blinking") ──
   Preparation amber, Testing blue, Live green with a softly pulsing dot, Completed grey. The words never blink;
   the dot's ring pulses, and stands still under reduced motion. Scripts draw the same pill with these classes. */
.z-phase { display: inline-flex; align-items: center; gap: 6px; font-size: .6875rem; font-weight: 700; line-height: 1;
  padding: 4px 9px; border-radius: var(--r-pill, 999px); white-space: nowrap; background: var(--gray-soft); color: var(--gray-text); }
.z-phase--amber { background: var(--amber-soft); color: var(--amber-text); }
.z-phase--blue  { background: var(--blue-soft);  color: var(--blue-text); }
.z-phase--green { background: var(--green-soft); color: var(--green-text); }
.z-phase--grey  { background: var(--gray-soft);  color: var(--gray-text); }
.z-phase-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: 0 0 7px; }
.z-phase-dot.is-live { animation: z-phase-live 1.6s ease-out infinite; }
@keyframes z-phase-live {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 60%, transparent); }
  100% { box-shadow: 0 0 0 7px color-mix(in srgb, currentColor 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .z-phase-dot.is-live { animation: none; } }
