@charset "utf-8";
/* ==========================================================================
   admin.css — the staff console.
   Arabic, RTL, logical properties only (SPEC §10). No physical left/right
   anywhere: a reviewer greps for it, and more importantly a mirrored rule is
   how an RTL table quietly grows a first column on the wrong side.

   Every token this file consumes is aliased once, here, against the names in
   tokens.css and with a fallback that matches that file's own value. tokens.css
   is owned by another pass: if it fails to load on a VPS with no outbound
   internet, or renames a variable, the console still renders in the intended
   shapes and colours and the repair is one line in this block rather than a
   hunt through 600 lines of rules.

   Dark mode needs no work below: the colour aliases resolve through tokens.css,
   which redefines every one of them. The guarded block at the end of this file
   only covers the aliases tokens.css has no equivalent for, plus the case where
   tokens.css is absent entirely.
   ========================================================================== */

:root {
  --ad-bg:          var(--bg, #FBF7F0);
  --ad-surface:     var(--surface, #FFFFFF);
  --ad-surface-2:   var(--surface-2, #F4EDE1);
  --ad-text:        var(--ink, #1B1710);
  --ad-muted:       var(--ink-mute, #7A6E5C);
  --ad-border:      var(--line, #D9CBB0);
  --ad-primary:     var(--accent, #0E6F63);
  --ad-primary-hi:  var(--accent-hover, #0A554C);
  --ad-primary-ink: var(--on-accent, #FFFFFF);
  --ad-primary-sub: var(--accent-soft, #E2F1EE);
  --ad-danger:      var(--danger, #B23B2E);
  --ad-danger-sub:  var(--danger-soft, #FBE9E6);
  --ad-warn:        var(--warn, #9A6B15);
  --ad-warn-sub:    var(--warn-soft, #FBF1DC);
  --ad-ok:          var(--ok, #2E7D44);
  /* No --ok-soft in tokens.css; the dark block at the end of this file owns it. */
  --ad-ok-sub:      #E7F2EA;
  --ad-focus:       var(--accent-hover, #0A554C);
  --ad-scrim:       var(--scrim, rgba(20, 17, 12, .62));
  /* Behind the live camera preview: near-black in both themes, so the
     letter's edges read against it. */
  --ad-stage:       var(--stage-bg, #14110C);
  /* Bookings. A booked / refused ROW is tinted a step lighter than the
     green / red badges inside it, or the badge would vanish into its row;
     the official hours are a band on the timeline, and a refused block is
     hatched so it differs from a booked one in more than hue. No tokens.css
     equivalents: the dark block at the end of this file owns them too. */
  --ad-book-ok-tint: #F3F9F4;
  --ad-book-no-tint: #FDF3F1;
  --ad-book-work:    rgba(14, 111, 99, .07);
  --ad-book-hatch:   rgba(178, 59, 46, .12);
  --ad-tl-half:      rgba(122, 110, 92, .16);

  --ad-r-sm: var(--r-sm, 8px);
  --ad-r-md: var(--r-md, 14px);
  --ad-r-lg: var(--r-lg, 22px);

  --ad-s1: var(--sp-1, 4px);
  --ad-s2: var(--sp-2, 8px);
  --ad-s3: var(--sp-3, 12px);
  --ad-s4: var(--sp-4, 16px);
  --ad-s5: var(--sp-5, 24px);
  --ad-s6: var(--sp-6, 32px);

  /* Type is the one axis the console does NOT inherit wholesale. The kiosk
     scale floors body text at 20px (SPEC §10) because a visitor reads it
     standing an arm's length back; an operator reads a seven-column permit
     table sitting at a desk, and 20px there would fit four columns on a laptop
     and push the rest off-screen. Same family, same colours, same spacing —
     smaller text, on purpose. Only the headings borrow the shared scale. */
  --ad-fs-sm:  0.9375rem;              /* 15px — table cells, labels, help text */
  --ad-fs-md:  var(--fs-sm, 1rem);     /* 16px — console body */
  --ad-fs-lg:  1.25rem;                /* 20px — panel headings */
  --ad-fs-xl:  var(--fs-lead, 1.5rem); /* 24px — view titles */
  --ad-fs-xxl: 2.25rem;                /* 36px — the day's counters */

  --ad-font: var(--font-ar, "Cairo", "IBM Plex Sans Arabic", "Noto Sans Arabic", "Segoe UI", Tahoma, system-ui, sans-serif);
  /* Serials and national IDs get the same tabular face the kiosk gives them,
     so a number read off this screen looks like the number on the slip. */
  --ad-font-num: var(--font-ltr, ui-monospace, "SF Mono", Menlo, Consolas, monospace);

  --ad-shadow: var(--shadow-md, 0 2px 6px rgba(27, 23, 16, .07), 0 12px 28px rgba(27, 23, 16, .09));
  --ad-topbar-h: 58px;
  --ad-nav-w: 236px;
}

/* --------------------------------------------------------------------- */
/* Reset-ish                                                             */
/* --------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body { block-size: 100%; }

body {
  margin: 0;
  background: var(--ad-bg);
  color: var(--ad-text);
  font-family: var(--ad-font);
  font-size: var(--ad-fs-md);
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }

/* Serials, national IDs and IPs are Latin runs inside Arabic text. They are
   emitted in <bdi dir="ltr">; this gives them tabular digits so a column of
   14-digit numbers lines up and a transposed digit is visible. */
bdi, .num {
  font-family: var(--ad-font-num);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}

:focus-visible {
  outline: 3px solid var(--ad-focus);
  outline-offset: 2px;
  border-radius: var(--ad-r-sm);
}

.visually-hidden {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------- */
/* Boot splash                                                           */
/* --------------------------------------------------------------------- */
.boot {
  min-block-size: 100vh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--ad-s4);
  color: var(--ad-muted);
}
.boot__spinner {
  inline-size: 34px; block-size: 34px;
  border: 3px solid var(--ad-border);
  border-block-start-color: var(--ad-primary);
  border-radius: 50%;
  animation: ad-spin .8s linear infinite;
}
@keyframes ad-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .boot__spinner { animation-duration: 3s; }
}

/* --------------------------------------------------------------------- */
/* Controls                                                              */
/* --------------------------------------------------------------------- */
.btn {
  font: inherit;
  font-weight: 600;
  padding-block: var(--ad-s2);
  padding-inline: var(--ad-s4);
  border: 1px solid transparent;
  border-radius: var(--ad-r-md);
  background: var(--ad-surface-2);
  color: var(--ad-text);
  cursor: pointer;
  min-block-size: 40px;
  transition: background-color .12s ease, border-color .12s ease, opacity .12s ease;
}
.btn:hover:not(:disabled) { background: var(--ad-border); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn--primary { background: var(--ad-primary); color: var(--ad-primary-ink); }
.btn--primary:hover:not(:disabled) { background: var(--ad-primary-hi); }
.btn--danger { background: var(--ad-danger); color: #fff; }
.btn--danger:hover:not(:disabled) { filter: brightness(1.12); background: var(--ad-danger); }
.btn--ghost { background: transparent; border-color: var(--ad-border); }
.btn--sm { min-block-size: 34px; padding-block: var(--ad-s1); font-size: var(--ad-fs-sm); }
.btn--block { inline-size: 100%; }

.iconbtn {
  font: inherit;
  line-height: 1;
  inline-size: 38px; block-size: 38px;
  display: inline-grid; place-items: center;
  border: 1px solid transparent;
  border-radius: var(--ad-r-md);
  background: transparent;
  color: inherit;
  cursor: pointer;
}
.iconbtn:hover { background: rgba(127, 127, 127, .14); }

.field { display: flex; flex-direction: column; gap: var(--ad-s1); min-inline-size: 0; }
.field--grow { flex: 1 1 260px; }
.field__label { font-size: var(--ad-fs-sm); font-weight: 600; color: var(--ad-muted); }
.field__input, .select {
  font: inherit;
  inline-size: 100%;
  min-block-size: 40px;
  padding-block: var(--ad-s2);
  padding-inline: var(--ad-s3);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  background: var(--ad-surface);
  color: var(--ad-text);
}
.field__input[readonly], .field__input:disabled, .select:disabled {
  background: var(--ad-surface-2);
  color: var(--ad-muted);
}
.field__help { font-size: var(--ad-fs-sm); color: var(--ad-muted); }

.check {
  display: inline-flex; align-items: center; gap: var(--ad-s2);
  font-size: var(--ad-fs-sm);
  /* The filter row bottom-aligns its controls; a checkbox with no label above
     it needs the same height as an input to land on that baseline. */
  min-block-size: 40px;
  white-space: nowrap;
}
.check input { inline-size: 18px; block-size: 18px; accent-color: var(--ad-primary); }

.alert {
  margin-block-start: var(--ad-s3);
  padding-block: var(--ad-s2);
  padding-inline: var(--ad-s3);
  border-radius: var(--ad-r-md);
  font-size: var(--ad-fs-sm);
  background: var(--ad-surface-2);
  border-inline-start: 4px solid var(--ad-border);
}
.alert--error { background: var(--ad-danger-sub); color: var(--ad-danger); border-inline-start-color: var(--ad-danger); }
.alert--ok    { background: var(--ad-ok-sub);     color: var(--ad-ok);     border-inline-start-color: var(--ad-ok); }
.alert--warn  { background: var(--ad-warn-sub);   color: var(--ad-warn);   border-inline-start-color: var(--ad-warn); }

.badge {
  display: inline-block;
  padding-block: 2px; padding-inline: var(--ad-s2);
  border-radius: 999px;
  font-size: var(--ad-fs-sm);
  font-weight: 600;
  background: var(--ad-primary-sub);
  color: var(--ad-primary);
  white-space: nowrap;
}
.badge--muted  { background: var(--ad-surface-2); color: var(--ad-muted); border: 1px solid var(--ad-border); }
.badge--warn   { background: var(--ad-warn-sub);  color: var(--ad-warn); }
.badge--danger { background: var(--ad-danger-sub);color: var(--ad-danger); }
.badge--ok     { background: var(--ad-ok-sub);    color: var(--ad-ok); }

/* --------------------------------------------------------------------- */
/* 1. Login                                                              */
/* --------------------------------------------------------------------- */
.login {
  min-block-size: 100vh;
  display: grid; place-items: center;
  padding: var(--ad-s5);
}
.login__card {
  inline-size: min(420px, 100%);
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-lg);
  box-shadow: var(--ad-shadow);
  padding: var(--ad-s6);
  display: flex; flex-direction: column; gap: var(--ad-s4);
}
.login__title { font-size: var(--ad-fs-xl); }
.login__sub { color: var(--ad-muted); font-size: var(--ad-fs-sm); margin-block-end: var(--ad-s2); }

/* --------------------------------------------------------------------- */
/* Shell: topbar + side nav + content                                    */
/* --------------------------------------------------------------------- */
.shell { min-block-size: 100vh; display: flex; flex-direction: column; }

.topbar {
  block-size: var(--ad-topbar-h);
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--ad-s3);
  padding-inline: var(--ad-s4);
  background: var(--ad-surface);
  border-block-end: 1px solid var(--ad-border);
  position: sticky; inset-block-start: 0; z-index: 30;
}
.topbar__burger { display: none; }
.topbar__brand { display: flex; align-items: center; gap: var(--ad-s2); font-weight: 700; }
.topbar__mark {
  inline-size: 30px; block-size: 30px;
  display: grid; place-items: center;
  border-radius: var(--ad-r-sm);
  background: var(--ad-primary); color: var(--ad-primary-ink);
  font-size: var(--ad-fs-md);
}
.topbar__spacer { flex: 1 1 auto; }
/* Every topbar child must be allowed to shrink. A select sized to its widest
   option ("الجمعة، 18 سبتمبر 2026 (مفتوحة)") is wider than a phone, and a
   non-shrinking flex item there pushes the whole RTL page into horizontal
   scroll rather than clipping itself. */
.topbar__brand { flex: 0 0 auto; }
.topbar__period { display: flex; align-items: center; gap: var(--ad-s2); min-inline-size: 0; flex: 0 1 auto; }
.topbar__period-label { font-size: var(--ad-fs-sm); color: var(--ad-muted); flex: 0 0 auto; }
.topbar__period .select {
  min-block-size: 34px;
  min-inline-size: 0;
  inline-size: auto;
  max-inline-size: 260px;
  text-overflow: ellipsis;
}
.topbar__who {
  font-size: var(--ad-fs-sm); color: var(--ad-muted);
  min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.shell__body { flex: 1 1 auto; display: flex; min-block-size: 0; }

.sidenav {
  flex: 0 0 var(--ad-nav-w);
  inline-size: var(--ad-nav-w);
  padding: var(--ad-s3);
  background: var(--ad-surface);
  border-inline-end: 1px solid var(--ad-border);
  display: flex; flex-direction: column; gap: var(--ad-s1);
  position: sticky;
  inset-block-start: var(--ad-topbar-h);
  block-size: calc(100vh - var(--ad-topbar-h));
  overflow-y: auto;
}
.sidenav__build {
  margin-block-start: auto;
  padding: var(--ad-s2);
  color: var(--ad-muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}
.sidenav__item {
  display: flex; align-items: center; gap: var(--ad-s3);
  padding-block: var(--ad-s3); padding-inline: var(--ad-s3);
  border-radius: var(--ad-r-md);
  color: inherit; text-decoration: none;
  font-weight: 600;
}
.sidenav__item:hover { background: var(--ad-surface-2); }
.sidenav__item[aria-current="page"] {
  background: var(--ad-primary-sub);
  color: var(--ad-primary);
  /* The active marker sits on the inline-start edge, which in RTL is the
     edge nearest the content — never a hard-coded side. */
  box-shadow: inset 3px 0 0 0 var(--ad-primary);
}
html[dir="rtl"] .sidenav__item[aria-current="page"] { box-shadow: inset -3px 0 0 0 var(--ad-primary); }
.sidenav__icon { opacity: .75; }

.content {
  flex: 1 1 auto;
  min-inline-size: 0;
  padding: var(--ad-s5);
  display: flex; flex-direction: column; gap: var(--ad-s5);
}

.view { display: flex; flex-direction: column; gap: var(--ad-s5); }
.view__head { display: flex; align-items: center; gap: var(--ad-s3); flex-wrap: wrap; }
.view__title { font-size: var(--ad-fs-xl); flex: 1 1 auto; }
.view__actions { display: flex; gap: var(--ad-s2); }

.scrim {
  position: fixed; inset: 0;
  background: var(--ad-scrim);
  z-index: 40;
}

/* --------------------------------------------------------------------- */
/* Panels + grids                                                        */
/* --------------------------------------------------------------------- */
.panel {
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-lg);
  padding: var(--ad-s5);
  display: flex; flex-direction: column; gap: var(--ad-s3);
  min-inline-size: 0;
}
.panel--danger { border-color: var(--ad-danger); background: var(--ad-danger-sub); }
.panel__title { font-size: var(--ad-fs-lg); }
.panel__hint { font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.panel__body { min-inline-size: 0; }
.panel__foot { display: flex; align-items: center; gap: var(--ad-s3); flex-wrap: wrap; }
.panel__foot .alert { margin-block-start: 0; }

.grid { display: grid; gap: var(--ad-s5); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }

/* --------------------------------------------------------------------- */
/* 2. Dashboard — counters                                               */
/* --------------------------------------------------------------------- */
.counters { display: grid; gap: var(--ad-s4); grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.counter {
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-lg);
  padding: var(--ad-s4);
  display: flex; flex-direction: column; gap: var(--ad-s1);
}
.counter--total { background: var(--ad-primary); color: var(--ad-primary-ink); border-color: var(--ad-primary); }
.counter__label { font-size: var(--ad-fs-sm); opacity: .85; }
.counter__value { font-size: var(--ad-fs-xxl); font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.counter__meta { font-size: var(--ad-fs-sm); opacity: .7; }

/* Location breakdown: a label, a proportional track, a count. */
.bars { display: flex; flex-direction: column; gap: var(--ad-s3); }
.bar { display: grid; grid-template-columns: minmax(7rem, 11rem) 1fr auto; gap: var(--ad-s3); align-items: center; }
.bar__label { font-size: var(--ad-fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar__track { block-size: 12px; border-radius: 999px; background: var(--ad-surface-2); overflow: hidden; }
.bar__fill { block-size: 100%; background: var(--ad-primary); border-radius: 999px; min-inline-size: 2px; }
.bar__value { font-size: var(--ad-fs-sm); font-variant-numeric: tabular-nums; min-inline-size: 2.5rem; text-align: end; }

/* --------------------------------------------------------------------- */
/* 2. Dashboard — hour histogram                                         */
/*                                                                       */
/* Pure CSS, no chart library and no CDN: the VPS may have no outbound    */
/* internet (SPEC §10). The bar row is a plain flex row, so the document  */
/* direction places hour 00 at the inline start — the right edge — and    */
/* time reads right-to-left like the rest of the page.                    */
/* --------------------------------------------------------------------- */
.hours { display: flex; align-items: flex-end; gap: 2px; block-size: 160px; padding-block-start: var(--ad-s3); }
.hours__col { flex: 1 1 0; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: var(--ad-s1); block-size: 100%; min-inline-size: 0; }
.hours__bar {
  inline-size: 100%;
  background: var(--ad-primary);
  border-start-start-radius: var(--ad-r-sm);
  border-start-end-radius: var(--ad-r-sm);
  min-block-size: 2px;
  transition: filter .12s ease;
}
.hours__col:hover .hours__bar { filter: brightness(1.25); }
.hours__col--empty .hours__bar { background: var(--ad-border); }
.hours__count { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--ad-muted); min-block-size: 1em; }
.hours__axis { display: flex; gap: 2px; border-block-start: 1px solid var(--ad-border); padding-block-start: var(--ad-s1); }
.hours__tick { flex: 1 1 0; text-align: center; font-size: 11px; color: var(--ad-muted); font-variant-numeric: tabular-nums; min-inline-size: 0; overflow: hidden; }

/* --------------------------------------------------------------------- */
/* 3. Tables                                                             */
/*                                                                       */
/* In an RTL document a table lays its first column at the RIGHT on its   */
/* own. Nothing here re-anchors a cell to a physical side; `text-align`   */
/* uses start/end so a column's alignment follows the document direction. */
/* --------------------------------------------------------------------- */
.filters {
  display: flex; flex-wrap: wrap; gap: var(--ad-s3);
  align-items: flex-end;
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-lg);
  padding: var(--ad-s4);
}
.filters .field { min-inline-size: 160px; }

.tablewrap {
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-lg);
  overflow-x: auto;
  /* A table that outgrows the viewport must scroll inside its own card,
     not push the whole RTL page sideways. */
  -webkit-overflow-scrolling: touch;
}
.table { inline-size: 100%; border-collapse: collapse; font-size: var(--ad-fs-sm); }
.table caption { caption-side: top; }
.table th, .table td {
  padding-block: var(--ad-s3);
  padding-inline: var(--ad-s3);
  text-align: start;
  border-block-end: 1px solid var(--ad-border);
  vertical-align: middle;
  white-space: nowrap;
}
.table thead th {
  position: sticky; inset-block-start: 0; z-index: 1;
  background: var(--ad-surface-2);
  color: var(--ad-muted);
  font-weight: 700;
}
.table tbody tr:last-child td { border-block-end: 0; }
.table tbody tr.row--click { cursor: pointer; }
.table tbody tr.row--click:hover { background: var(--ad-surface-2); }
.table tbody tr.row--click:focus-visible { background: var(--ad-primary-sub); }
.table td.cell--wrap { white-space: normal; min-inline-size: 12rem; }

.thumb {
  inline-size: 44px; block-size: 44px;
  border-radius: var(--ad-r-sm);
  object-fit: cover;
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
  display: block;
}
.thumb--missing { display: grid; place-items: center; font-size: 11px; color: var(--ad-muted); }

.state-msg {
  padding-block: var(--ad-s6);
  text-align: center;
  color: var(--ad-muted);
}

.pager {
  display: flex; align-items: center; gap: var(--ad-s3); flex-wrap: wrap;
  justify-content: center;
  font-size: var(--ad-fs-sm);
}
.pager__info { color: var(--ad-muted); }

/* --------------------------------------------------------------------- */
/* 4. Detail drawer                                                      */
/* --------------------------------------------------------------------- */
.scrim--drawer { z-index: 50; }
.drawer {
  position: fixed;
  inset-block: 0;
  inset-inline-end: 0;
  inline-size: min(560px, 100%);
  z-index: 60;
  background: var(--ad-surface);
  border-inline-start: 1px solid var(--ad-border);
  box-shadow: var(--ad-shadow);
  display: flex; flex-direction: column;
  animation: ad-fade .14s ease-out;
}
@keyframes ad-fade { from { opacity: 0; } to { opacity: 1; } }
.drawer__head {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--ad-s3);
  padding: var(--ad-s4);
  border-block-end: 1px solid var(--ad-border);
}
.drawer__title { font-size: var(--ad-fs-lg); flex: 1 1 auto; }
.drawer__body { flex: 1 1 auto; overflow-y: auto; padding: var(--ad-s5); display: flex; flex-direction: column; gap: var(--ad-s5); }

.media { display: grid; gap: var(--ad-s4); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.media__item { display: flex; flex-direction: column; gap: var(--ad-s2); }
.media__cap { font-size: var(--ad-fs-sm); color: var(--ad-muted); font-weight: 600; }
.media__img {
  inline-size: 100%;
  aspect-ratio: 4 / 3;
  object-fit: contain;
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
}
.media__fail {
  display: grid; place-items: center;
  aspect-ratio: 4 / 3;
  background: var(--ad-surface-2);
  border: 1px dashed var(--ad-border);
  border-radius: var(--ad-r-md);
  color: var(--ad-muted);
  font-size: var(--ad-fs-sm);
  text-align: center;
  padding: var(--ad-s3);
}

.kv { display: grid; grid-template-columns: minmax(8rem, 12rem) 1fr; gap: var(--ad-s2) var(--ad-s4); align-items: baseline; }
.kv__k { font-size: var(--ad-fs-sm); color: var(--ad-muted); font-weight: 600; }
.kv__v { min-inline-size: 0; overflow-wrap: anywhere; }
.kv__v--big { font-size: var(--ad-fs-lg); font-weight: 700; }

.flags { display: flex; flex-wrap: wrap; gap: var(--ad-s2); }

.raw {
  margin: 0;
  padding: var(--ad-s3);
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  font-family: var(--ad-font-num);
  font-size: 12px;
  direction: ltr;
  text-align: start;
  max-block-size: 260px;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------- */
/* 5. Reset                                                              */
/* --------------------------------------------------------------------- */
.reset__current {
  display: grid; gap: var(--ad-s3);
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  padding: var(--ad-s4);
}
.reset__consequences { display: flex; flex-direction: column; gap: var(--ad-s2); }
.reset__consequences li {
  padding-inline-start: var(--ad-s4);
  position: relative;
  font-size: var(--ad-fs-sm);
}
.reset__consequences li::before {
  content: "•";
  position: absolute;
  inset-inline-start: 0;
  color: var(--ad-danger);
  font-weight: 700;
}
.reset__note { font-size: var(--ad-fs-sm); }
.reset__phrase {
  background: var(--ad-surface);
  border: 1px dashed var(--ad-danger);
  border-radius: var(--ad-r-sm);
  padding-inline: var(--ad-s2);
}
#reset-confirm-field { max-inline-size: 320px; }
/* Destructive and full-bleed is an invitation. Sized to its text instead. */
#reset-btn { align-self: flex-start; padding-inline: var(--ad-s6); }

/* --------------------------------------------------------------------- */
/* 8. Settings                                                           */
/* --------------------------------------------------------------------- */
.settings { display: grid; gap: var(--ad-s5); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.setting { display: flex; flex-direction: column; gap: var(--ad-s1); }
.setting__key { font-size: 12px; color: var(--ad-muted); font-family: var(--ad-font-num); direction: ltr; text-align: start; }

/* --------------------------------------------------------------------- */
/* 9. OCR diagnostics                                                    */
/*                                                                       */
/* Logical properties only, like the rest of this file. The drop zone is  */
/* the one new interactive shape here; everything else reuses .panel,     */
/* .table, .kv and .badge so this screen cannot drift from the console.   */
/* --------------------------------------------------------------------- */
.drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ad-s2);
  padding: var(--ad-s6) var(--ad-s4);
  border: 2px dashed var(--ad-border);
  border-radius: var(--ad-r-md);
  background: var(--ad-surface-2);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--dur, 180ms) var(--ease, ease),
              background var(--dur, 180ms) var(--ease, ease);
}
.drop:hover { border-color: var(--ad-primary); }
/* Dragging over and holding a file both read as "armed", in the accent
   colour, so the operator can tell the zone took the file before they
   press the button. */
.drop--over { border-color: var(--ad-primary); background: var(--ad-primary-sub); }
.drop--filled { border-style: solid; border-color: var(--ad-primary); background: var(--ad-primary-sub); }
.drop__icon { font-size: var(--ad-fs-xl); color: var(--ad-muted); }
.drop__main { font-weight: 600; overflow-wrap: anywhere; }
.drop__hint { font-size: var(--ad-fs-sm); color: var(--ad-muted); }

#ocr-result { display: flex; flex-direction: column; gap: var(--ad-s5); }

/* The warped card is the evidence, not decoration: give it the panel's full
   width and never crop it. A card shown small enough to look fine is exactly
   the failure this screen exists to catch. */
.ocr__warped {
  inline-size: 100%;
  block-size: auto;
  max-block-size: none;
  object-fit: contain;
  background: var(--ad-surface-2);
}

.ocr__headline {
  display: grid;
  gap: var(--ad-s1) var(--ad-s3);
  grid-template-columns: auto 1fr;
  align-items: center;
  padding: var(--ad-s4);
  margin-block-end: var(--ad-s4);
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
}
.ocr__label { font-size: var(--ad-fs-sm); color: var(--ad-muted); font-weight: 600; }
.ocr__value { font-size: var(--ad-fs-lg); font-weight: 700; overflow-wrap: anywhere; }
/* Read at arm's length against the card itself, so bigger than anything else
   on the screen and in tabular figures — a transposed digit has to be visible
   without leaning in. */
.ocr__value--nid { font-size: var(--ad-fs-xxl); line-height: 1.15; }
.ocr__headline .badge { grid-column: 2; justify-self: start; }
.ocr__roi {
  margin-inline-start: var(--ad-s2);
  font-size: 12px;
  color: var(--ad-muted);
}

#ocr-detections td { vertical-align: top; }

@media (max-width: 860px) {
  .ocr__headline { grid-template-columns: 1fr; }
  .ocr__headline .badge { grid-column: auto; }
  .ocr__value--nid { font-size: var(--ad-fs-xl); }
}

/* --------------------------------------------------------------------- */
/* 10. Tickets — lookup, the ticket, and the company's letter             */
/*                                                                       */
/* The employee's main screen. Built from the console's own parts         */
/* (.panel, .table, .kv, .badge, .drop, .media) so it cannot drift from   */
/* them; the new shapes are the lookup bar, the match list, the camera,    */
/* the editable visits table and its two-way during/after switch.          */
/* --------------------------------------------------------------------- */
.lookup { gap: var(--ad-s2); }
.lookup__label { font-size: var(--ad-fs-sm); font-weight: 700; color: var(--ad-muted); }
.lookup__row { display: flex; flex-wrap: wrap; gap: var(--ad-s3); }
/* Big and in the serial's own tabular face: the number is read off a slip
   held in the other hand, and a transposed digit has to show. */
.lookup__input {
  flex: 1 1 15rem;
  inline-size: auto;
  min-inline-size: 0;
  min-block-size: 56px;
  font-family: var(--ad-font-num);
  font-size: var(--ad-fs-xl);
  font-weight: 700;
  letter-spacing: .04em;
}
.lookup__input::placeholder { color: var(--ad-muted); opacity: .55; font-weight: 400; }
.lookup__btn { min-block-size: 56px; padding-inline: var(--ad-s6); font-size: var(--ad-fs-lg); }

.matches-box { display: flex; flex-direction: column; gap: var(--ad-s2); }
.matches__head { font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.matches__scope { margin-block-start: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--ad-s2); }
.matches { display: flex; flex-direction: column; gap: var(--ad-s2); }
.match {
  font: inherit;
  color: inherit;
  text-align: start;
  inline-size: 100%;
  display: grid;
  grid-template-columns: minmax(7.5rem, auto) minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--ad-s2) var(--ad-s4);
  padding-block: var(--ad-s3);
  padding-inline: var(--ad-s4);
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  cursor: pointer;
  transition: border-color .12s ease, background-color .12s ease;
}
.match:hover { border-color: var(--ad-primary); background: var(--ad-primary-sub); }
.match__serial { font-size: var(--ad-fs-lg); font-weight: 700; }
.match__main { display: flex; flex-direction: column; min-inline-size: 0; }
.match__name { font-weight: 700; overflow-wrap: anywhere; }
.match__company { font-size: var(--ad-fs-sm); color: var(--ad-muted); overflow-wrap: anywhere; }
.match__meta { display: flex; flex-direction: column; font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.match__badges { display: flex; flex-wrap: wrap; gap: var(--ad-s1); justify-content: flex-end; }

.empty {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--ad-s2);
  padding-block: var(--ad-s6);
  padding-inline: var(--ad-s4);
  text-align: center;
  background: var(--ad-surface);
  border: 1px dashed var(--ad-border);
  border-radius: var(--ad-r-lg);
}
.empty__icon { font-size: 2.5rem; line-height: 1; color: var(--ad-muted); }
.empty__title { font-size: var(--ad-fs-lg); font-weight: 700; }
.empty__hint { font-size: var(--ad-fs-sm); color: var(--ad-muted); max-inline-size: 38rem; }

/* The ticket itself. Wide screens put the two photos in a column beside the
   details instead of two 4:3 images the width of the page. */
.ticket { display: flex; flex-direction: column; gap: var(--ad-s5); }
.panel__head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--ad-s2) var(--ad-s3); }
.panel__head .panel__title { flex: 1 1 auto; }
.panel__meta { display: inline-flex; align-items: center; gap: var(--ad-s2); font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.ticket__detail { display: grid; gap: var(--ad-s4) var(--ad-s5); grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 1100px) {
  .ticket__detail { grid-template-columns: minmax(220px, 340px) minmax(0, 1fr); }
  .ticket__detail > .media { grid-row: 1 / span 4; grid-template-columns: 1fr; }
  .ticket__detail > :not(.media) { grid-column: 2; }
}
.kv__v--strong { font-size: var(--ad-fs-lg); font-weight: 700; }
.drawer__actions { display: flex; flex-wrap: wrap; gap: var(--ad-s2); }
/* Print / save PDF and Excel, at the end of the ticket's heading row. */
.panel__actions { display: inline-flex; flex-wrap: wrap; gap: var(--ad-s2); }
/* aria-disabled rather than disabled (admin.js syncTicketActions): it still
   takes focus and shows its tooltip, it just looks unavailable. */
.btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.btn--ghost[aria-disabled="true"]:hover { background: transparent; }

/* The ticket's print sheet (#ticket-print) exists only on paper: admin.js
   fills it just before window.print() and empties it after. Its layout is
   in the print block below. */
.tprint { display: none; }

/* Photos open full size (lightbox below). The button is the image's frame. */
.media__zoom {
  font: inherit;
  display: block;
  inline-size: 100%;
  padding: 0;
  border: 0;
  border-radius: var(--ad-r-md);
  background: none;
  cursor: zoom-in;
}

/* Two equal ways in: the camera and a file. */
.scan { display: grid; gap: var(--ad-s4); grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.scan__btn {
  font: inherit;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--ad-s2);
  min-block-size: 9rem;
  padding-block: var(--ad-s5);
  padding-inline: var(--ad-s4);
  border: 2px solid var(--ad-primary);
  border-radius: var(--ad-r-md);
  background: var(--ad-primary-sub);
  color: var(--ad-primary);
  text-align: center;
  cursor: pointer;
  transition: background-color .12s ease, color .12s ease;
}
.scan__btn:hover:not(:disabled) { background: var(--ad-primary); color: var(--ad-primary-ink); }
.scan__btn:disabled { opacity: .5; cursor: not-allowed; }
.scan__icon { font-size: 2rem; line-height: 1; }
.scan__main { font-size: var(--ad-fs-lg); font-weight: 700; }
.scan__hint { font-size: var(--ad-fs-sm); opacity: .85; }
.scan .drop { min-block-size: 9rem; justify-content: center; padding-block: var(--ad-s5); }
.scan .drop__main { font-size: var(--ad-fs-lg); font-weight: 700; }
.drop--disabled, .drop--disabled:hover { opacity: .5; cursor: not-allowed; border-color: var(--ad-border); }

/* Live preview. The stage takes the frame's own aspect (set from JS once the
   stream reports its size) so the A4 guide sits where the pixels are. */
.cam { display: flex; flex-direction: column; align-items: center; gap: var(--ad-s3); }
.cam__stage {
  position: relative;
  inline-size: 100%;
  max-inline-size: 960px;
  aspect-ratio: 16 / 9;
  background: var(--ad-stage);
  border-radius: var(--ad-r-md);
  overflow: hidden;
}
.cam__video { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: contain; }
/* Centred with inset + auto margins rather than translate(-50%): a
   translate is physical and would push the guide sideways in RTL. */
.cam__guide {
  position: absolute;
  inset: 0;
  margin: auto;
  inline-size: 36%;
  block-size: 90%;
  border: 3px dashed rgba(255, 255, 255, .92);
  border-radius: 6px;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .38);
  pointer-events: none;
}
.cam__hint { font-size: var(--ad-fs-sm); color: var(--ad-muted); text-align: center; }
.cam__bar { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--ad-s3); }
.cam__shutter { min-block-size: 52px; padding-inline: var(--ad-s6); font-size: var(--ad-fs-lg); }
.cam__count { align-self: center; font-weight: 700; color: var(--ad-primary); font-variant-numeric: tabular-nums; }
/* The shutter's answer: the stage blinks white, so a page that was taken
   is seen to be taken while the camera stays open for the next. The stage
   is dark in both themes, hence the literal white. */
.cam__stage.is-flash::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  pointer-events: none;
  animation: cam-flash .35s ease-out forwards;
}
@keyframes cam-flash { from { opacity: .7; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .cam__stage.is-flash::after { animation-duration: .01s; }
}

/* The letter's pages before they are read: a numbered list in reading
   order, each with a thumbnail, what it is, and earlier / later / remove. */
.tray {
  display: flex; flex-direction: column; gap: var(--ad-s2);
  padding: var(--ad-s3);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  background: var(--ad-surface-2);
}
.tray__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--ad-s1) var(--ad-s3); }
.tray__title { font-size: var(--ad-fs-md); font-weight: 700; }
.tray__count { font-size: var(--ad-fs-sm); color: var(--ad-muted); font-variant-numeric: tabular-nums; }
.tray__hint { font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.tray__list { display: flex; flex-direction: column; gap: var(--ad-s1); list-style: none; margin: 0; padding: 0; }
.tray__item {
  display: flex; align-items: center; gap: var(--ad-s3);
  min-inline-size: 0;
  padding: var(--ad-s2);
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
}
.tray__item.is-error { border-color: var(--ad-danger); background: var(--ad-danger-sub); }
.tray__n {
  flex: 0 0 auto;
  min-inline-size: 1.75rem;
  font-weight: 700; color: var(--ad-muted); text-align: center;
  font-variant-numeric: tabular-nums;
}
.tray__thumb {
  font: inherit;
  flex: 0 0 auto;
  inline-size: 48px; block-size: 64px;
  display: grid; place-items: center;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-sm);
  background: var(--ad-surface-2);
  color: var(--ad-muted);
  cursor: zoom-in;
}
.tray__thumb--file { cursor: default; font-size: 12px; font-weight: 700; }
.tray__img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
.tray__body { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }
.tray__name { font-weight: 700; overflow-wrap: anywhere; }
.tray__meta { font-size: 12px; color: var(--ad-muted); }
.tray__err { font-size: 12px; font-weight: 700; color: var(--ad-danger); }
.tray__btns { flex: 0 0 auto; display: flex; gap: 2px; }
.tray__btn { inline-size: 36px; block-size: 36px; border-color: var(--ad-border); }
.tray__btn:disabled { opacity: .35; cursor: not-allowed; }
.tray__bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ad-s3); }
.tray__read { min-block-size: 48px; padding-inline: var(--ad-s5); font-size: var(--ad-fs-lg); }
@media (max-width: 600px) {
  .tray__item { flex-wrap: wrap; }
  .tray__body { flex-basis: calc(100% - 7rem); }
  .tray__btns { margin-inline-start: auto; }
}

.busy {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: var(--ad-s3);
  padding: var(--ad-s5);
  border-radius: var(--ad-r-md);
  background: var(--ad-primary-sub);
  color: var(--ad-primary);
  font-weight: 700;
}
.busy .boot__spinner { inline-size: 26px; block-size: 26px; }
.busy__time { font-weight: 400; font-variant-numeric: tabular-nums; opacity: .8; }

.dochist { display: flex; flex-direction: column; gap: var(--ad-s2); }
.dochist__title { font-size: var(--ad-fs-md); font-weight: 700; }
.dochist__list { display: flex; flex-direction: column; gap: var(--ad-s1); }
.dochist__item {
  font: inherit;
  color: inherit;
  text-align: start;
  inline-size: 100%;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--ad-s1) var(--ad-s3);
  padding-block: var(--ad-s2);
  padding-inline: var(--ad-s3);
  font-size: var(--ad-fs-sm);
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  cursor: pointer;
}
.dochist__item:hover { background: var(--ad-surface-2); }
.dochist__item.is-current { border-color: var(--ad-primary); background: var(--ad-primary-sub); }
.dochist__company { flex: 1 1 10rem; min-inline-size: 0; font-weight: 700; overflow-wrap: anywhere; }
.dochist__meta { color: var(--ad-muted); }

/* --- The read: status, company, summary, visits, page -------------- */
/* scroll-margin: scrolled into view after a scan, the top must clear the
   sticky topbar or the reviewed/unreviewed status is the line it hides. */
.docres { display: flex; flex-direction: column; gap: var(--ad-s4); scroll-margin-block-start: calc(var(--ad-topbar-h) + var(--ad-s3)); }
.docres__head { display: flex; flex-direction: column; gap: var(--ad-s2); }
.docres .alert { margin-block-start: 0; }
.docstatus { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ad-s2) var(--ad-s3); }
.docstatus__meta { font-size: var(--ad-fs-sm); color: var(--ad-muted); }
/* A badge that carries a sentence (a flag, the visitor's own words) must
   wrap rather than widen the row past a phone's edge. */
.badge--wrap { white-space: normal; overflow-wrap: anywhere; }

.company { flex-direction: row; align-items: flex-start; gap: var(--ad-s5); }
.company__logo {
  flex: 0 0 auto;
  inline-size: 140px;
  block-size: 140px;
  display: grid; place-items: center;
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  overflow: hidden;
}
.company__logo-zoom {
  font: inherit;
  inline-size: 100%; block-size: 100%;
  display: grid; place-items: center;
  padding: var(--ad-s2);
  border: 0;
  background: none;
  cursor: zoom-in;
}
.company__logo-img { display: block; max-inline-size: 100%; max-block-size: 100%; object-fit: contain; }
.company__initial { font-size: 3.25rem; font-weight: 700; line-height: 1; color: var(--ad-muted); }
.company__body { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: var(--ad-s2); }
/* The company is the headline of the letter: as large as a view title. */
.company__name { min-block-size: 54px; font-size: var(--ad-fs-xl); font-weight: 700; }
.company__badges { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ad-s2); }
.company__conf { display: inline-flex; align-items: center; gap: var(--ad-s1); font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.company__asread { font-size: var(--ad-fs-sm); color: var(--ad-muted); overflow-wrap: anywhere; }
.company__visitor { display: flex; flex-wrap: wrap; gap: var(--ad-s2); }
.company__extra { display: grid; gap: var(--ad-s3); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin-block-start: var(--ad-s1); }

/* Summary chips: the letter in one line before the table. */
.chips { display: flex; flex-wrap: wrap; gap: var(--ad-s2); }
.chip {
  display: inline-flex; flex-direction: column;
  min-inline-size: 6.5rem;
  padding-block: var(--ad-s2);
  padding-inline: var(--ad-s3);
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
}
.chip__label { font-size: 12px; font-weight: 600; color: var(--ad-muted); }
.chip__value { font-size: var(--ad-fs-lg); font-weight: 700; font-variant-numeric: tabular-nums; }
.chip--primary { background: var(--ad-primary); border-color: var(--ad-primary); color: var(--ad-primary-ink); }
.chip--primary .chip__label { color: inherit; opacity: .85; }
.chip--ok { background: var(--ad-ok-sub); border-color: transparent; }
.chip--ok .chip__value { color: var(--ad-ok); }
.chip--warn { background: var(--ad-warn-sub); border-color: var(--ad-warn); }
.chip--warn .chip__value { color: var(--ad-warn); }
.chip--site { background: var(--ad-primary-sub); border-color: transparent; }
.chip--after { border-color: var(--ad-text); }

/* Table beside the page on a wide screen; the page drops under it below. */
.docgrid { display: grid; gap: var(--ad-s4); grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 1360px) {
  /* The page beside the table is for orientation (a click opens it full
     size), so the table gets the width: at 1440px it fits unscrolled. */
  .docgrid { grid-template-columns: minmax(0, 1fr) minmax(240px, 24%); }
  .docpage { position: sticky; inset-block-start: calc(var(--ad-topbar-h) + var(--ad-s4)); }
}
.docvisits .tablewrap { border-radius: var(--ad-r-md); }
.docvisits__foot { display: flex; gap: var(--ad-s2); }
.docvisits__note { resize: vertical; min-block-size: 64px; }

.doctable th, .doctable td { padding-block: var(--ad-s2); padding-inline: 6px; vertical-align: top; }
.doctable .field__input, .doctable .select {
  min-block-size: 38px;
  padding-block: var(--ad-s1);
  padding-inline: var(--ad-s2);
  border-radius: var(--ad-r-sm);
  font-size: var(--ad-fs-sm);
}
.doctable__n { padding-block-start: var(--ad-s3); color: var(--ad-muted); font-variant-numeric: tabular-nums; text-align: center; }
.doctable__date { inline-size: 9.25rem; }
.doctable__wd { display: block; min-block-size: 1.3em; margin-block-start: 2px; font-size: 12px; font-weight: 600; color: var(--ad-muted); }
.doctable__stack { display: flex; flex-direction: column; gap: var(--ad-s1); }
.doctable__loc, .doctable__loctext { inline-size: 10rem; }
.doctable__src { max-inline-size: 10rem; font-size: 12px; color: var(--ad-muted); white-space: normal; }
.doctable__time { inline-size: 7.25rem; }
.doctable__auto { display: block; margin-block-start: 2px; font-size: 11px; color: var(--ad-muted); text-align: center; }
.doctable__row.is-flagged .doctable__n { color: var(--ad-warn); font-weight: 700; }
.doctable__row.is-error .doctable__n { color: var(--ad-danger); font-weight: 700; }
/* The note row belongs to the row above it: no rule between them. */
.doctable__row.has-note td { border-block-end-color: transparent; padding-block-end: var(--ad-s1); }
.doctable__note td { padding-block-start: 0; white-space: normal; }
.doctable__flags { gap: var(--ad-s1); }
.doctable__flags .badge { font-size: 12px; }

/* A cell the reader was unsure of: amber until someone edits it. */
.doctable .is-unsure { outline: 2px solid var(--ad-warn); outline-offset: 1px; background-color: var(--ad-warn-sub); }
.is-invalid { outline: 2px solid var(--ad-danger); outline-offset: 1px; }
.doctable .is-invalid, .company__name.is-invalid { background-color: var(--ad-danger-sub); }

.linkbtn {
  font: inherit;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ad-primary);
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}

/* during / after — the console's .viewswitch pill, as a radio group. */
.seg {
  display: inline-grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
}
.seg__opt {
  position: relative;
  display: grid; place-items: center;
  min-block-size: 32px;
  padding-inline: var(--ad-s3);
  border-radius: 999px;
  color: var(--ad-muted);
  font-size: var(--ad-fs-sm);
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .12s ease, color .12s ease;
}
.seg__opt:hover { color: var(--ad-text); }
.seg__opt.is-on { background: var(--ad-primary); color: var(--ad-primary-ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .14); }
/* After-hours inverts instead of turning amber: it is a different kind of
   visit, not a problem, but it must not look like the default. */
.seg__opt--after.is-on { background: var(--ad-text); color: var(--ad-bg); }
.seg__opt:has(.seg__input:focus-visible) { outline: 3px solid var(--ad-focus); outline-offset: 1px; }
.seg__opt:has(.seg__input:disabled) { cursor: default; }
.seg__input { position: absolute; inline-size: 1px; block-size: 1px; opacity: 0; pointer-events: none; }

.docpage { display: flex; flex-direction: column; gap: var(--ad-s2); margin: 0; }
.docpage__zoom {
  font: inherit;
  display: block;
  inline-size: 100%;
  padding: 0;
  overflow: hidden;
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  cursor: zoom-in;
}
.docpage__img { display: block; inline-size: 100%; block-size: auto; max-block-size: 80vh; object-fit: contain; }
/* A letter's pages one below the other, read as one long page. Beside the
   table on a wide screen the column scrolls on its own, so a row's «صفحة ٢»
   can bring page 2 up without moving the table away. */
.docpages { display: flex; flex-direction: column; gap: var(--ad-s3); }
@media (min-width: 1360px) {
  .docpages {
    max-block-size: calc(100vh - var(--ad-topbar-h) - 5rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-inline-end: 2px;
  }
}
.docpages__page { margin: 0; display: flex; flex-direction: column; gap: var(--ad-s1); scroll-margin-block-start: var(--ad-s2); }
.docpages__label { font-size: var(--ad-fs-sm); font-weight: 700; color: var(--ad-muted); }
.docpages__page.is-pointed .docpage__zoom { animation: page-pointed 1.6s ease-out; }
@keyframes page-pointed {
  from { outline: 3px solid var(--ad-primary); outline-offset: 2px; }
  to { outline: 3px solid transparent; outline-offset: 2px; }
}
@media (prefers-reduced-motion: reduce) {
  .docpages__page.is-pointed .docpage__zoom { animation: none; outline: 3px solid var(--ad-primary); outline-offset: 2px; }
}

/* «صفحة ٢» under a row's number: quiet until wanted. */
.doctable__page {
  font: inherit;
  display: block;
  margin-block-start: 2px;
  margin-inline: auto;
  padding: 0 4px;
  border: 0;
  border-radius: var(--ad-r-sm);
  background: none;
  color: var(--ad-muted);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: underline dotted;
  cursor: pointer;
}
.doctable__page:hover { color: var(--ad-primary); background: var(--ad-primary-sub); }

/* Always reachable at the bottom of a long table. */
.savebar {
  position: sticky;
  inset-block-end: var(--ad-s2);
  z-index: 5;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--ad-s3);
  padding-block: var(--ad-s3);
  padding-inline: var(--ad-s4);
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-lg);
  box-shadow: var(--ad-shadow);
}
.savebar__save { min-inline-size: 9rem; min-block-size: 46px; font-size: var(--ad-fs-lg); }
.savebar__dirty { font-size: var(--ad-fs-sm); font-weight: 700; color: var(--ad-warn); }
.savebar .alert { flex: 1 1 14rem; margin-block-start: 0; }

/* Full-size image. Fit to screen first; a click shows actual pixels, which
   is what reading a letter's small print needs. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex; flex-direction: column;
  background: var(--ad-scrim);
  animation: ad-fade .14s ease-out;
}
.lightbox__bar {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--ad-s3);
  padding-block: var(--ad-s2);
  padding-inline: var(--ad-s4);
  background: var(--ad-surface);
  border-block-end: 1px solid var(--ad-border);
}
.lightbox__hint { flex: 1 1 auto; font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.lightbox__stage { flex: 1 1 auto; min-block-size: 0; overflow: auto; display: grid; place-items: center; padding: var(--ad-s4); }
.lightbox__img {
  display: block;
  max-inline-size: 100%;
  max-block-size: calc(100vh - 7rem);
  object-fit: contain;
  background: #fff;
  border-radius: var(--ad-r-sm);
  box-shadow: var(--ad-shadow);
  cursor: zoom-in;
}
/* Actual size scrolls from the start edge: a centred overflow would put the
   far side of the page out of scroll reach. */
.lightbox--zoom .lightbox__stage { place-items: start; }
.lightbox--zoom .lightbox__img { max-inline-size: none; max-block-size: none; cursor: zoom-out; }

@media (max-width: 860px) {
  .match { grid-template-columns: auto minmax(0, 1fr); }
  .match__meta, .match__badges { grid-column: 1 / -1; }
  .match__badges { justify-content: flex-start; }
}
@media (max-width: 600px) {
  .lookup, .ticket .panel, .docres .panel { padding: var(--ad-s4); }
  .lookup__btn { flex: 1 1 100%; }
  .company { flex-direction: column; align-items: stretch; }
  .company__logo { inline-size: 100%; block-size: 110px; }
  .company__name { font-size: var(--ad-fs-lg); }
  .scan__btn, .scan .drop { min-block-size: 7rem; }
  /* Eight chips at desktop size are two screens of a phone before the table. */
  .chip { min-inline-size: 0; padding-block: var(--ad-s1); }
  .chip__value { font-size: var(--ad-fs-md); }
  .savebar { padding-block: var(--ad-s2); padding-inline: var(--ad-s3); }
  .savebar__save { min-block-size: 42px; }
}

/* --------------------------------------------------------------------- */
/* Bookings — a row's place in the schedule on the ticket screen, the     */
/* day timeline and the conflicts list. Green holds its slot; red was     */
/* refused for a lower ticket. Always ✓ / ✕ and words with the colour,    */
/* and a hatch on a refused block: never hue alone.                       */
/* --------------------------------------------------------------------- */
.bookrule { font-weight: 600; }
.booknote {
  padding-block: var(--ad-s1);
  padding-inline: var(--ad-s3);
  border-radius: var(--ad-r-md);
  border-inline-start: 4px solid var(--ad-border);
  background: var(--ad-surface-2);
  color: var(--ad-muted);
  font-size: var(--ad-fs-sm);
}
.booknote--draft { background: var(--ad-warn-sub); color: var(--ad-warn); border-inline-start-color: var(--ad-warn); }
.booknote--error { background: var(--ad-danger-sub); color: var(--ad-danger); border-inline-start-color: var(--ad-danger); }

/* The status, first on the line under its row: the badge, then the
   neutral «طلبته أيضاً …» and the amber «يتداخل مع الصف …». */
.doctable__book {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--ad-s1) var(--ad-s3);
  margin-block-end: var(--ad-s1);
  transition: opacity .12s ease;
}
.doctable__book.is-pending { opacity: .5; }
.doctable__bookwait { font-size: 12px; color: var(--ad-muted); }
.book__badge { font-size: 12px; line-height: 1.55; }
.book__note { font-size: 12px; line-height: 1.45; color: var(--ad-muted); overflow-wrap: anywhere; }
.book__note--self { color: var(--ad-warn); font-weight: 600; }
/* ✓ / ✕ under the row number, so the column reads at a glance. */
.doctable__bookicon { display: block; font-weight: 700; line-height: 1.2; }
.doctable__bookicon--accepted { color: var(--ad-ok); }
.doctable__bookicon--refused { color: var(--ad-danger); }
.doctable__bookicon--incomplete, .doctable__bookicon--not_in_schedule { color: var(--ad-muted); }
.booklink { color: inherit; font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
.booklink:hover { color: var(--ad-primary); }
/* The whole row says it, and its edge says it again for a glance down the
   table: green or red on the side the row number is on. */
.doctable__row.is-book-accepted > td, .doctable__note.is-book-accepted > td { background-color: var(--ad-book-ok-tint); }
.doctable__row.is-book-refused > td, .doctable__note.is-book-refused > td { background-color: var(--ad-book-no-tint); }
.doctable__row.is-book-accepted > .doctable__n { border-inline-start: 4px solid var(--ad-ok); }
.doctable__row.is-book-refused > .doctable__n { border-inline-start: 4px solid var(--ad-danger); }

.chip--danger { background: var(--ad-danger-sub); border-color: var(--ad-danger); }
.chip--danger .chip__value { color: var(--ad-danger); }
.chip--muted { background: var(--ad-surface-2); }
.chip--muted .chip__value { color: var(--ad-muted); font-size: var(--ad-fs-md); }

/* Refused requests from today on, in the side menu. */
.sidenav__badge {
  margin-inline-start: auto;
  min-inline-size: 1.7em;
  padding-inline: 6px;
  border-radius: 999px;
  background: var(--ad-danger);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.6;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* --- the day timeline ------------------------------------------------- */
.bkbar__nav { display: flex; flex-wrap: wrap; gap: var(--ad-s2); }
.bklegend { display: flex; flex-wrap: wrap; gap: var(--ad-s2) var(--ad-s4); font-size: var(--ad-fs-sm); color: var(--ad-muted); }
.bklegend li { display: inline-flex; align-items: center; gap: var(--ad-s2); }
.bklegend__swatch {
  inline-size: 1.6rem; block-size: 1.15rem;
  display: inline-grid; place-items: center;
  border: 1px solid var(--ad-border);
  border-radius: 4px;
  font-size: 11px; font-weight: 700;
}
.bklegend__swatch--accepted { background: var(--ad-ok-sub); border-color: var(--ad-ok); color: var(--ad-ok); }
.bklegend__swatch--refused {
  background: repeating-linear-gradient(135deg, var(--ad-book-hatch) 0 3px, transparent 3px 6px), var(--ad-danger-sub);
  border-color: var(--ad-danger); color: var(--ad-danger);
}
.bklegend__swatch--self { border: 2px dashed var(--ad-warn); color: var(--ad-warn); }
.bklegend__swatch--work { background: var(--ad-book-work); }

/* Scrolls sideways inside its card when the sites do not fit; the page
   never does. The corner and the axis are the inline-start column — the
   right edge in Arabic — like a table's first column. */
.tl {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-md);
  background: var(--ad-surface);
}
/* 12.5rem a site: two blocks side by side still fit «10:00–11:00»
   (11 characters of the 11px tabular face, ~73px) on one line. */
.tl__grid {
  --tl-axis: 4.25rem;
  --tl-colw: 12.5rem;
  display: grid;
  grid-template-columns: var(--tl-axis) repeat(var(--tl-cols, 1), minmax(var(--tl-colw), 1fr));
  min-inline-size: calc(var(--tl-axis) + var(--tl-cols, 1) * var(--tl-colw));
}
.tl__corner, .tl__head {
  padding-block: var(--ad-s2);
  padding-inline: var(--ad-s2);
  background: var(--ad-surface-2);
  border-block-end: 1px solid var(--ad-border);
  font-size: var(--ad-fs-sm);
  font-weight: 700;
}
.tl__corner { color: var(--ad-muted); }
.tl__head { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; border-inline-start: 1px solid var(--ad-border); }
.tl__site { overflow-wrap: anywhere; }
.tl__count { font-size: 12px; font-weight: 600; color: var(--ad-muted); }
.tl__axis { position: relative; block-size: var(--tl-h); }
.tl__tick { position: absolute; inset-inline-start: var(--ad-s2); transform: translateY(-50%); font-size: 11px; color: var(--ad-muted); }
.tl__tick:first-child { transform: none; }
.tl__tick:last-child { transform: translateY(-100%); }
/* An hour line every two half hours, a fainter one between. */
.tl__col {
  position: relative;
  block-size: var(--tl-h);
  border-inline-start: 1px solid var(--ad-border);
  background-image:
    repeating-linear-gradient(to bottom, var(--ad-border) 0 1px, transparent 1px calc(var(--tl-half) * 2)),
    repeating-linear-gradient(to bottom, var(--ad-tl-half) 0 1px, transparent 1px var(--tl-half));
}
.tl__work { position: absolute; inset-inline: 0; background: var(--ad-book-work); pointer-events: none; }
.tl__block {
  position: absolute;
  z-index: 1;
  display: flex; flex-direction: column;
  padding-block: 2px;
  padding-inline: 5px;
  overflow: hidden;
  border: 1px solid var(--ad-ok);
  border-inline-start-width: 4px;
  border-radius: 6px;
  background: var(--ad-ok-sub);
  color: var(--ad-text);
  font-size: 12px;
  line-height: 1.25;
  text-decoration: none;
  /* Two blocks side by side keep a hairline between them. */
  box-shadow: 0 0 0 1px var(--ad-surface);
}
.tl__block--refused {
  border-color: var(--ad-danger);
  background: repeating-linear-gradient(135deg, var(--ad-book-hatch) 0 6px, transparent 6px 12px), var(--ad-danger-sub);
}
.tl__block--self { outline: 2px dashed var(--ad-warn); outline-offset: -4px; }
.tl__block:hover, .tl__block:focus-visible { z-index: 2; box-shadow: var(--ad-shadow); }
.tl__block:focus-visible { outline: 3px solid var(--ad-focus); outline-offset: 1px; }
/* Lines wrap rather than lose their start: an ellipsis on a time cuts the
   «10:» off «10:00–11:00» in a narrow lane. The block clips what does not
   fit below, and its tooltip and the ticket have the rest. */
.tl__line { overflow-wrap: anywhere; }
.tl__ticket { font-weight: 700; }
.tl__time bdi { font-size: 11px; }
.tl__company { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl__block--accepted .tl__ticket { color: var(--ad-ok); }
.tl__block--refused .tl__ticket { color: var(--ad-danger); }
.tl__company { color: var(--ad-muted); }

/* --- the conflicts list ----------------------------------------------- */
.cfsummary { font-size: var(--ad-fs-sm); font-weight: 600; color: var(--ad-muted); }
.conflicts { display: flex; flex-direction: column; gap: var(--ad-s3); margin: 0; padding: 0; list-style: none; }
.conf {
  display: flex; flex-direction: column; gap: var(--ad-s2);
  padding-block: var(--ad-s3);
  padding-inline: var(--ad-s4);
  background: var(--ad-surface);
  border: 1px solid var(--ad-border);
  border-radius: var(--ad-r-lg);
}
.conf__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--ad-s1) var(--ad-s3); font-weight: 700; }
.conf__site { color: var(--ad-primary); overflow-wrap: anywhere; }
.conf__span { font-size: var(--ad-fs-sm); font-weight: 600; color: var(--ad-muted); }
.conf__list { display: flex; flex-direction: column; gap: var(--ad-s1); }
.conf__item {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--ad-s1) var(--ad-s3);
  padding-block: var(--ad-s1);
  padding-inline: var(--ad-s3);
  border-radius: var(--ad-r-md);
  border-inline-start: 4px solid var(--ad-ok);
  background: var(--ad-ok-sub);
  font-size: var(--ad-fs-sm);
}
.conf__item--refused { border-inline-start-color: var(--ad-danger); background: var(--ad-danger-sub); }
.conf__icon { font-weight: 700; color: var(--ad-ok); }
.conf__item--refused .conf__icon, .conf__item--refused .conf__status { color: var(--ad-danger); }
.conf__item--accepted .conf__status { color: var(--ad-ok); }
.conf__company { color: var(--ad-muted); overflow-wrap: anywhere; }
.conf__status { font-weight: 600; overflow-wrap: anywhere; }

@media (max-width: 600px) {
  .tl__grid { --tl-axis: 3.5rem; --tl-colw: 11rem; }
  .conf { padding-inline: var(--ad-s3); }
}

/* --------------------------------------------------------------------- */
/* View switch — kiosk <-> console. Same component as kiosk.css, sized    */
/* for a 58px topbar. Both pages name the thumb for a cross-document view  */
/* transition, so where supported it glides from one side to the other.   */
/* --------------------------------------------------------------------- */
.viewswitch {
  position: relative;
  flex: 0 0 auto;
  display: inline-grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding: 3px;
  border-radius: 999px;
  background: var(--ad-surface-2);
  border: 1px solid var(--ad-border);
  isolation: isolate;
  view-transition-name: viewswitch;
}
.viewswitch__thumb {
  position: absolute;
  z-index: 0;
  inset-block: 3px;
  inset-inline-start: 3px;
  inline-size: calc(50% - 3px);
  border-radius: 999px;
  background: linear-gradient(150deg, var(--ad-primary) 0%, var(--ad-primary-hi) 100%);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .14), 0 6px 14px -6px var(--ad-primary);
  transition: transform .26s cubic-bezier(0.2, 0, 0.13, 1);
  view-transition-name: viewswitch-thumb;
}
/* RTL: the second option sits to the LEFT of the first. */
.viewswitch[data-current="admin"] .viewswitch__thumb { transform: translateX(-100%); }
.viewswitch:dir(ltr)[data-current="admin"] .viewswitch__thumb { transform: translateX(100%); }
.viewswitch__opt {
  position: relative;
  z-index: 1;
  display: grid; place-items: center;
  min-block-size: 36px;
  padding-inline: var(--ad-s4);
  border-radius: 999px;
  color: var(--ad-muted);
  font-size: var(--ad-fs-sm);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: color .18s ease;
}
.viewswitch__opt:hover { color: var(--ad-text); }
.viewswitch__opt.is-current { color: var(--ad-primary-ink); }
.viewswitch__opt:focus-visible { outline: 3px solid var(--ad-focus); outline-offset: 2px; }

.login__switch {
  position: absolute;
  inset-block-start: var(--ad-s4);
  inset-inline: 0;
  display: flex; justify-content: center;
}
.login { position: relative; }

@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: .2s; }
::view-transition-group(viewswitch-thumb) {
  animation-duration: .32s;
  animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1);
}

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .viewswitch__thumb { transition: none; }
}

@media (max-width: 860px) {
  .viewswitch__opt { padding-inline: var(--ad-s3); }
}
/* On a phone the switch cannot share one row with the burger, the period
   picker and the badges: it will not shrink (two words each side), so the
   period picker collapsed to nothing and the burger — the only way to the
   other sections there — was pushed past the inline-start edge, which an RTL
   page cannot scroll to. The topbar becomes two rows and the switch takes the
   second, full width. The fixed side nav follows --ad-topbar-h down. */
@media (max-width: 600px) {
  :root { --ad-topbar-h: 108px; }
  .topbar {
    flex-wrap: wrap;
    row-gap: var(--ad-s2);
    padding-block: var(--ad-s2);
    align-content: center;
  }
  .topbar__spacer { display: none; }
  .topbar__period { flex: 1 1 0; }
  .topbar .viewswitch { order: 10; flex: 1 1 100%; }
  .viewswitch__opt { padding-inline: var(--ad-s2); }
}
/* A short landscape phone: the login card would slide under the absolutely
   placed switch, so the switch joins the normal flow above it. */
@media (max-height: 600px) {
  .login { grid-template-rows: auto 1fr; gap: var(--ad-s4); }
  .login__switch { position: static; }
}

/* --------------------------------------------------------------------- */
/* Toasts                                                                */
/* --------------------------------------------------------------------- */
.toasts {
  position: fixed;
  inset-block-end: var(--ad-s5);
  inset-inline-start: var(--ad-s5);
  z-index: 80;
  display: flex; flex-direction: column; gap: var(--ad-s2);
  max-inline-size: min(380px, calc(100vw - 2 * var(--ad-s5)));
}
.toast {
  padding-block: var(--ad-s3); padding-inline: var(--ad-s4);
  border-radius: var(--ad-r-md);
  background: var(--ad-text);
  color: var(--ad-bg);
  box-shadow: var(--ad-shadow);
  font-size: var(--ad-fs-sm);
  animation: ad-fade .14s ease-out;
}
.toast--error { background: var(--ad-danger); color: #fff; }
.toast--ok { background: var(--ad-ok); color: #fff; }

/* --------------------------------------------------------------------- */
/* Narrow screens — a supervisor checking the day on a phone.            */
/* --------------------------------------------------------------------- */
@media (max-width: 860px) {
  .content { padding: var(--ad-s4); }
  .topbar__burger { display: inline-grid; }
  .topbar__name { display: none; }
  .topbar__period-label { display: none; }
  .sidenav {
    position: fixed;
    inset-block: var(--ad-topbar-h) 0;
    inset-inline-start: 0;
    z-index: 45;
    box-shadow: var(--ad-shadow);
    block-size: auto;
  }
  .sidenav[hidden] { display: none !important; }
  .kv { grid-template-columns: 1fr; gap: var(--ad-s1); }
  .hours { block-size: 130px; }
  .topbar__who { display: none; }
  .topbar__period .select { max-inline-size: 180px; }
  /* Stacked filters read as one column; half-width selects next to a full-width
     search box look like a broken row rather than a deliberate one. */
  .filters .field { flex: 1 1 100%; min-inline-size: 0; }
}

/* --------------------------------------------------------------------- */
/* Print: an operator printing the day's list wants the table, not the    */
/* chrome. Not the permit slip — that is print.css on the kiosk.          */
/* --------------------------------------------------------------------- */
@media print {
  .topbar, .sidenav, .filters, .pager, .view__actions, .toasts, .drawer, .scrim, .viewswitch, .lightbox, .savebar { display: none !important; }
  body { background: #fff; }
  .tablewrap { border: 0; overflow: visible; }
  .table th, .table td { white-space: normal; }
}

/* --------------------------------------------------------------------- */
/* Print: one ticket (admin.js printTicket). While body carries           */
/* .is-printing-ticket the sheet is the only thing on paper — no topbar,  */
/* side menu, lookup bar, form or toast — on A4 portrait, black on white  */
/* whatever the screen's theme. Without the class, printing the console   */
/* behaves as above.                                                      */
/* --------------------------------------------------------------------- */
@page ticket {
  size: A4 portrait;
  margin: 14mm 12mm 16mm;
  /* Page numbers where the browser draws margin boxes (Chromium); elsewhere
     the rule is ignored and the sheet prints without them. */
  @bottom-center {
    content: counter(page) " / " counter(pages);
    /* "1 / 3", not the "3 / 1" the page's right-to-left would make of it. */
    direction: ltr;
    font-size: 9pt;
    color: #444;
  }
}

@media print {
  body.is-printing-ticket { background: #fff; }
  body.is-printing-ticket > :not(#ticket-print) { display: none !important; }
  body.is-printing-ticket > #ticket-print { display: block; }

  .tprint {
    page: ticket;
    /* Paper is white and ink is black in both themes: the dark palette the
       screen may be using stops at the sheet's edge. */
    --ad-text: #000;
    --ad-muted: #333;
    --ad-border: #777;
    --ad-surface: #fff;
    --ad-surface-2: #eee;
    color: var(--ad-text);
    background: var(--ad-surface);
    font-family: var(--ad-font);
    font-size: 10.5pt;
    line-height: 1.45;
    /* An Arabic letter that opens a line (the ر of «رقم») overhangs its box
       a little; at the page's edge that much would be cut off. */
    padding-inline: 1mm;
  }
  .tprint h1, .tprint h2, .tprint p, .tprint dl, .tprint dd { margin: 0; }

  .tprint__head {
    display: flex; flex-direction: column; gap: 1mm;
    padding-block-end: 3mm;
    margin-block-end: 5mm;
    border-block-end: 2px solid var(--ad-text);
  }
  .tprint__app { font-size: 10pt; color: var(--ad-muted); font-weight: 700; }
  .tprint__title { font-size: 18pt; font-weight: 700; line-height: 1.2; }
  /* The number the visitor holds, as large as it is on the slip. */
  .tprint__serial { font-size: 24pt; letter-spacing: .03em; }
  .tprint__meta { font-size: 10pt; }
  .tprint__draft {
    margin-block-start: 2mm;
    padding: 2mm 3mm;
    border: 2px solid var(--ad-text);
  }

  .tprint__section { margin-block-end: 5mm; }
  .tprint__h {
    font-size: 12.5pt;
    font-weight: 700;
    padding-block-end: 1mm;
    margin-block-end: 2mm;
    border-block-end: 1px solid var(--ad-border);
    break-after: avoid;
  }
  .tprint__visitor { break-inside: avoid; }
  .tprint__visitor-body { display: flex; align-items: flex-start; gap: 5mm; }
  .tprint__photo {
    flex: 0 0 auto;
    inline-size: 30mm;
    block-size: 40mm;
    object-fit: cover;
    border: 1px solid var(--ad-border);
  }
  .tprint__kv {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 1mm 4mm;
    align-content: start;
  }
  .tprint__kv dt { font-weight: 700; color: var(--ad-muted); }
  .tprint__kv dd { overflow-wrap: anywhere; }
  .tprint__cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3mm 6mm;
    margin-block: 2mm 3mm;
    break-inside: avoid;
  }
  .tprint__status { font-weight: 700; margin-block-end: 2mm; }
  .tprint__status--draft,
  .tprint__status--machine {
    padding: 1mm 3mm;
    border: 1.5px dashed var(--ad-text);
  }

  .tprint__table { inline-size: 100%; border-collapse: collapse; font-size: 9.5pt; margin-block-start: 2mm; }
  .tprint__caption { caption-side: top; text-align: start; font-weight: 700; padding-block-end: 1mm; }
  /* The header row again at the top of every page the table runs onto. */
  .tprint__table thead { display: table-header-group; }
  .tprint__table th,
  .tprint__table td {
    padding-block: 1mm;
    padding-inline: 1.5mm;
    border: 1px solid var(--ad-border);
    text-align: start;
    vertical-align: top;
  }
  .tprint__table th {
    background: var(--ad-surface-2);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  /* A visit (its row and its notes) is never split across two pages. */
  .tprint__visit, .tprint__table tr { break-inside: avoid; }
  .tprint__n { inline-size: 7mm; text-align: center; }
  .tprint__wd { font-weight: 700; }
  .tprint__note td { font-size: 8.5pt; border-block-start-style: dotted; }
  /* On paper the words carry it: a refused row's status is bold. */
  .tprint__book { font-size: 8.5pt; }
  .tprint__book--refused { font-weight: 700; }

  .tprint__foot {
    margin-block-start: 4mm;
    padding-block-start: 2mm;
    border-block-start: 1px solid var(--ad-border);
    font-size: 9pt;
    color: var(--ad-muted);
  }
}

/* --------------------------------------------------------------------- */
/* Dark mode.                                                             */
/*                                                                        */
/* Almost nothing to do: every colour alias resolves through tokens.css,   */
/* which redefines the semantic names for dark itself. This block exists   */
/* for two cases — the one alias tokens.css has no equivalent for          */
/* (--ad-ok-sub), and a console served without tokens.css at all, where    */
/* the fallbacks below are what the page actually uses.                    */
/*                                                                        */
/* Guarded the same way tokens.css guards its own dark block, so a forced  */
/* light theme wins and an explicit dark theme is honoured.                */
/* --------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ad-bg:          var(--bg, #12100B);
    --ad-surface:     var(--surface, #1E1A13);
    --ad-surface-2:   var(--surface-2, #272117);
    --ad-text:        var(--ink, #F3ECDE);
    --ad-muted:       var(--ink-mute, #A2977F);
    --ad-border:      var(--line, #3B3427);
    --ad-primary:     var(--accent, #3FB3A2);
    --ad-primary-hi:  var(--accent-hover, #55C6B5);
    --ad-primary-ink: var(--on-accent, #06211E);
    --ad-primary-sub: var(--accent-soft, #10332F);
    --ad-danger:      var(--danger, #E0705F);
    --ad-danger-sub:  var(--danger-soft, #3A1B16);
    --ad-warn:        var(--warn, #E0B25C);
    --ad-warn-sub:    var(--warn-soft, #322611);
    --ad-ok:          var(--ok, #6FCB8A);
    --ad-ok-sub:      #16301F;
    --ad-focus:       var(--accent-hover, #55C6B5);
    --ad-scrim:       var(--scrim, rgba(0, 0, 0, .66));
    --ad-stage:       var(--stage-bg, #000000);
    --ad-shadow: var(--shadow-md, 0 2px 8px rgba(0, 0, 0, .55), 0 14px 32px rgba(0, 0, 0, .45));
    --ad-book-ok-tint: #142319;
    --ad-book-no-tint: #2A1714;
    --ad-book-work:    rgba(63, 179, 162, .08);
    --ad-book-hatch:   rgba(224, 112, 95, .16);
    --ad-tl-half:      rgba(162, 151, 127, .14);
  }
  /* A dark toast on a dark page needs an edge to sit on. */
  :root:not([data-theme="light"]) .toast {
    background: var(--ad-surface-2); color: var(--ad-text); border: 1px solid var(--ad-border);
  }
}

:root[data-theme="dark"] {
  --ad-bg:          var(--bg, #12100B);
  --ad-surface:     var(--surface, #1E1A13);
  --ad-surface-2:   var(--surface-2, #272117);
  --ad-text:        var(--ink, #F3ECDE);
  --ad-muted:       var(--ink-mute, #A2977F);
  --ad-border:      var(--line, #3B3427);
  --ad-primary:     var(--accent, #3FB3A2);
  --ad-primary-hi:  var(--accent-hover, #55C6B5);
  --ad-primary-ink: var(--on-accent, #06211E);
  --ad-primary-sub: var(--accent-soft, #10332F);
  --ad-danger:      var(--danger, #E0705F);
  --ad-danger-sub:  var(--danger-soft, #3A1B16);
  --ad-warn:        var(--warn, #E0B25C);
  --ad-warn-sub:    var(--warn-soft, #322611);
  --ad-ok:          var(--ok, #6FCB8A);
  --ad-ok-sub:      #16301F;
  --ad-focus:       var(--accent-hover, #55C6B5);
  --ad-scrim:       var(--scrim, rgba(0, 0, 0, .66));
  --ad-stage:       var(--stage-bg, #000000);
  --ad-shadow: var(--shadow-md, 0 2px 8px rgba(0, 0, 0, .55), 0 14px 32px rgba(0, 0, 0, .45));
  --ad-book-ok-tint: #142319;
  --ad-book-no-tint: #2A1714;
  --ad-book-work:    rgba(63, 179, 162, .08);
  --ad-book-hatch:   rgba(224, 112, 95, .16);
  --ad-tl-half:      rgba(162, 151, 127, .14);
}
:root[data-theme="dark"] .toast {
  background: var(--ad-surface-2); color: var(--ad-text); border: 1px solid var(--ad-border);
}
