/* ============================================================================
   SHIFFA — design system
   Apple "Liquid Glass" language: translucent layered materials, specular edge
   highlights, squircle radii, grouped inset lists, system colours, dark mode.
   Fully logical-property based so RTL mirrors without any per-direction rules.
   ========================================================================== */

/* ---------------------------------------------------------------- tokens */
:root {
  /* iOS system palette */
  --sys-blue:   #007AFF;
  --sys-green:  #34C759;
  --sys-indigo: #5856D6;
  --sys-orange: #FF9500;
  /* The verification badge. Chosen to clear 4.5:1 on both grounds. */
  --verified:   #1D74D0;
  --sys-pink:   #FF2D55;
  --sys-purple: #AF52DE;
  --sys-red:    #FF3B30;
  --sys-teal:   #30B0C7;
  --sys-mint:   #00C7BE;
  --sys-yellow: #FFCC00;

  /* Brand accent — the green of the wordmark.
     Sampled from the calligraphy in public/img/logo.png rather than picked:
     the mark carries the national flag's green, and an interface in a
     different green beside it reads as two brands on one screen. */
  --accent:      #0B6A2A;
  --accent-2:    #2E9247;
  --accent-deep: #0B5320;
  --on-accent:   #ffffff;

  /* surfaces */
  --bg:          #EFEFF4;
  --bg-tint-a:   rgba(46, 146, 71, .15);
  --bg-tint-b:   rgba(88, 86, 214, .10);
  --surface:     #ffffff;
  --surface-2:   #F7F7FA;
  --glass:       rgba(255, 255, 255, .62);
  --glass-strong:rgba(255, 255, 255, .80);
  --glass-edge:  rgba(255, 255, 255, .70);
  --glass-shade: rgba(0, 0, 0, .05);

  /* text */
  --label:   #000000;
  --label-2: rgba(60, 60, 67, .62);
  --label-3: rgba(60, 60, 67, .34);
  --label-4: rgba(60, 60, 67, .20);

  /* fills & separators */
  --fill:     rgba(120, 120, 128, .12);
  --fill-2:   rgba(120, 120, 128, .18);
  --fill-3:   rgba(120, 120, 128, .24);
  --separator:rgba(60, 60, 67, .13);

  /* tinted badge backgrounds */
  --tint-green:  rgba(52, 199, 89, .16);
  --tint-orange: rgba(255, 149, 0, .18);
  --tint-red:    rgba(255, 59, 48, .15);
  --tint-blue:   rgba(0, 122, 255, .14);
  --tint-purple: rgba(175, 82, 222, .15);
  --tint-accent: rgba(11, 106, 42, .14);

  --on-green:  #1D7F35;
  --on-orange: #A85B00;
  --on-red:    #C7241B;
  --on-blue:   #0058B8;
  --on-purple: #7B2FA8;
  --on-accent-tint: #0A5524;

  /* geometry */
  --r-xs:  8px;
  --r-sm:  11px;
  --r:     16px;
  --r-lg:  22px;
  --r-xl:  30px;
  --r-pill: 999px;

  /* elevation — soft and wide, never harsh */
  --sh-1: 0 1px 2px rgba(0,0,0,.04), 0 4px 14px rgba(0,0,0,.05);
  --sh-2: 0 2px 6px rgba(0,0,0,.05), 0 12px 34px rgba(0,0,0,.08);
  --sh-3: 0 8px 24px rgba(0,0,0,.10), 0 32px 76px rgba(0,0,0,.20);

  /* the specular top highlight that sells the glass */
  --spec: inset 0 1px 0 rgba(255,255,255,.65);

  --blur: saturate(180%) blur(30px);
  --sidebar-w: 262px;
  --ease: cubic-bezier(.32, .72, 0, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:          #000000;
    --bg-tint-a:   rgba(46, 146, 71, .14);
    --bg-tint-b:   rgba(88, 86, 214, .18);
    --surface:     #1C1C1E;
    --surface-2:   #2C2C2E;
    --glass:       rgba(30, 30, 32, .60);
    --glass-strong:rgba(30, 30, 32, .82);
    --glass-edge:  rgba(255, 255, 255, .10);
    --glass-shade: rgba(0, 0, 0, .30);

    --label:   #FFFFFF;
    --label-2: rgba(235, 235, 245, .62);
    --label-3: rgba(235, 235, 245, .34);
    --verified:   #5AA9F5;
    --label-4: rgba(235, 235, 245, .18);

    --fill:     rgba(120, 120, 128, .24);
    --fill-2:   rgba(120, 120, 128, .32);
    --fill-3:   rgba(120, 120, 128, .40);
    --separator:rgba(84, 84, 88, .60);

    --accent:      #46C46A;
    --accent-2:    #77DC93;
    --accent-deep: #1E8C42;
    --on-accent:   #052012;

    --tint-green:  rgba(52, 199, 89, .22);
    --tint-orange: rgba(255, 149, 0, .22);
    --tint-red:    rgba(255, 69, 58, .22);
    --tint-blue:   rgba(10, 132, 255, .22);
    --tint-purple: rgba(191, 90, 242, .22);
    --tint-accent: rgba(47, 217, 188, .20);

    --on-green:  #4BE06B;
    --on-orange: #FFB23F;
    --on-red:    #FF6961;
    --on-blue:   #64AEFF;
    --on-purple: #D9A0FF;
    --on-accent-tint: #77DC93;

    --sh-1: 0 1px 2px rgba(0,0,0,.35), 0 4px 14px rgba(0,0,0,.30);
    --sh-2: 0 2px 6px rgba(0,0,0,.40), 0 12px 34px rgba(0,0,0,.44);
    --sh-3: 0 8px 24px rgba(0,0,0,.50), 0 32px 76px rgba(0,0,0,.60);
    --spec: inset 0 1px 0 rgba(255,255,255,.10);
  }
}

/* ---------------------------------------------------------------- base */
* { box-sizing: border-box; }
html, body { height: 100%; }

body {
  margin: 0;
  color: var(--label);
  background: var(--bg);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
               "Segoe UI Variable Text", "Segoe UI", system-ui, "Noto Sans Arabic", sans-serif;
  font-size: 15px;
  line-height: 1.47;
  letter-spacing: -.01em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Ambient colour wash behind the glass — this is what the blur samples. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(58rem 42rem at 12% -8%, var(--bg-tint-a), transparent 62%),
    radial-gradient(48rem 38rem at 96% 4%, var(--bg-tint-b), transparent 60%),
    radial-gradient(40rem 40rem at 70% 108%, rgba(11,106,42,.10), transparent 62%);
}

body[dir="rtl"] {
  font-family: "SF Arabic", -apple-system, "Segoe UI", "Noto Naskh Arabic", Tahoma, sans-serif;
}

/* Author `display` rules beat the UA stylesheet, so components that set
   display (.alert, .card, …) would otherwise ignore the hidden attribute. */
[hidden] { display: none !important; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -.022em; }
a { color: var(--accent-deep); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font: inherit; color: inherit; }
input, select, textarea { font: inherit; color: inherit; }
.icn { flex: none; vertical-align: -.2em; }

::selection { background: var(--tint-accent); }

/* iOS-style thin scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--fill-3) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-thumb { background: var(--fill-3); border-radius: var(--r-pill);
  border: 2.5px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-track { background: transparent; }

/* ---------------------------------------------------------------- layout */
#app { min-height: 100vh; }

/*  Grid follows the inline axis, so `dir="rtl"` mirrors the whole shell —
    sidebar to the right, content to the left — with no direction-specific
    rules. Overriding the column order here would flip it a second time.  */
.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
}

/* ---------------------------------------------------------------- sidebar */
.sidebar {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 10px;
  background: var(--glass);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border-inline-end: 1px solid var(--glass-edge);
  box-shadow: var(--spec);
}

.brand { display: flex; align-items: center; gap: 11px; padding: 12px 12px 16px; }
.brand-mark {
  width: 38px; height: 38px; border-radius: 12px; flex: none;
  background: linear-gradient(160deg, var(--accent-2), var(--accent) 55%, var(--accent-deep));
  display: grid; place-items: center; color: #fff;
  box-shadow: 0 4px 12px rgba(11,106,42,.35), inset 0 1px 0 rgba(255,255,255,.45);
}
.brand-name { font-size: 17px; font-weight: 650; letter-spacing: -.03em; line-height: 1.15; }
.brand-sub {
  font-size: 11px; color: var(--label-2); font-weight: 550;
  letter-spacing: .01em; margin-top: 1px;
}

.nav { flex: 1; overflow-y: auto; padding: 0 2px; }
.nav-group {
  margin: 16px 0 6px; padding-inline: 12px;
  font-size: 11.5px; font-weight: 600; color: var(--label-3);
  letter-spacing: .02em;
}
.nav a {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 12px; margin-bottom: 2px;
  border-radius: var(--r-sm);
  color: var(--label); font-size: 14.5px; font-weight: 480;
  text-decoration: none;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.nav a .icn { color: var(--label-2); transition: color .18s var(--ease); }
.nav a:hover { background: var(--fill); text-decoration: none; }
.nav a.active {
  background: linear-gradient(150deg, var(--accent-2), var(--accent) 60%, var(--accent-deep));
  color: var(--on-accent); font-weight: 560;
  box-shadow: 0 3px 10px rgba(11,106,42,.30), inset 0 1px 0 rgba(255,255,255,.35);
}
.nav a.active .icn { color: var(--on-accent); }

.sidebar-foot { padding: 8px 4px 4px; border-top: 1px solid var(--separator); margin-top: 8px; }
.who { display: flex; align-items: center; gap: 10px; padding: 10px 8px; }
.avatar {
  width: 34px; height: 34px; border-radius: var(--r-pill); flex: none;
  background: linear-gradient(160deg, var(--accent-2), var(--accent-deep));
  color: #fff; display: grid; place-items: center;
  font-weight: 600; font-size: 13px; letter-spacing: -.02em;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35);
}
.who-name { font-size: 14px; font-weight: 550; }
.who-role { font-size: 12px; color: var(--label-2); }

/* ---------------------------------------------------------------- topbar */
.main { display: flex; flex-direction: column; min-width: 0; }

.topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 14px;
  min-height: 62px; padding: 10px 26px;
  background: var(--glass);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border-bottom: 1px solid var(--separator);
  box-shadow: var(--spec);
}
.topbar h1 { font-size: 21px; font-weight: 680; letter-spacing: -.032em; }
.topbar .sub { color: var(--label-2); font-size: 13px; margin-top: 1px; }
.topbar-actions { margin-inline-start: auto; display: flex; align-items: center; gap: 8px; }

.content { flex: 1; width: 100%; max-width: 1560px; padding: 24px 26px 40px; }

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 16px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: var(--fill);
  color: var(--label);
  font-size: 14px; font-weight: 550; letter-spacing: -.01em;
  white-space: nowrap; cursor: pointer;
  transition: transform .16s var(--ease), background .18s var(--ease), opacity .18s;
}
.btn:hover { background: var(--fill-2); }
.btn:active { transform: scale(.96); }
.btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }
.btn:focus-visible { outline: 3px solid var(--tint-accent); outline-offset: 2px; }

.btn-primary {
  background: linear-gradient(150deg, var(--accent-2), var(--accent) 55%, var(--accent-deep));
  color: var(--on-accent); font-weight: 600;
  box-shadow: 0 3px 12px rgba(11,106,42,.32), inset 0 1px 0 rgba(255,255,255,.35);
}
.btn-primary:hover { filter: brightness(1.06); }

.btn-danger {
  background: var(--sys-red); color: #fff; font-weight: 600;
  box-shadow: 0 3px 12px rgba(255,59,48,.30), inset 0 1px 0 rgba(255,255,255,.30);
}
.btn-danger:hover { filter: brightness(1.06); }

.btn-ghost { background: transparent; }
.btn-ghost:hover { background: var(--fill); }
.btn-sm { padding: 6px 12px; font-size: 13px; }
.btn-icon { padding: 8px; width: 38px; height: 38px; }
.btn-block { width: 100%; }

/* ---------------------------------------------------------------- cards */
.card {
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  overflow: hidden;
}
@media (prefers-color-scheme: dark) {
  .card { box-shadow: var(--sh-1), inset 0 0 0 1px rgba(255,255,255,.055); }
}
.card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--separator);
}
.card-head h3 { font-size: 16px; font-weight: 620; letter-spacing: -.024em; }
.card-head .spacer { margin-inline-start: auto; }
.card-body { padding: 20px; }
.card-body.tight { padding: 0; }

.grid { display: grid; gap: 18px; }
.g2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
.g-2-1 { grid-template-columns: 2fr 1fr; }
.g-1-2 { grid-template-columns: 1fr 2fr; }

/* ---------------------------------------------------------------- stats */
.stat {
  position: relative; overflow: hidden;
  padding: 17px 19px;
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
}
@media (prefers-color-scheme: dark) {
  .stat { box-shadow: var(--sh-1), inset 0 0 0 1px rgba(255,255,255,.055); }
}
/* A soft tinted glow instead of a hard rule — reads as material, not chrome. */
.stat::after {
  content: ''; position: absolute; inset-block: 0; inset-inline-start: 0;
  width: 46%;
  background: radial-gradient(circle at 0% 50%, var(--tint-accent), transparent 72%);
  pointer-events: none;
}
.stat.warn::after { background: radial-gradient(circle at 0% 50%, var(--tint-orange), transparent 72%); }
.stat.bad::after  { background: radial-gradient(circle at 0% 50%, var(--tint-red), transparent 72%); }
.stat.info::after { background: radial-gradient(circle at 0% 50%, var(--tint-blue), transparent 72%); }
.stat > * { position: relative; z-index: 1; }

.stat-label {
  font-size: 12.5px; font-weight: 570; color: var(--label-2);
  letter-spacing: -.005em;
}
.stat-value {
  font-size: 30px; font-weight: 680; letter-spacing: -.038em;
  margin-top: 4px; line-height: 1.12;
  font-variant-numeric: tabular-nums;
}
.stat-value small { font-size: 15px; color: var(--label-2); font-weight: 550; }
.stat-note { font-size: 12.5px; color: var(--label-2); margin-top: 4px; }

/* ---------------------------------------------------------------- tables */
.table-wrap { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: 14px; }
.tbl th {
  text-align: start; white-space: nowrap;
  padding: 11px 20px;
  font-size: 12.5px; font-weight: 570; color: var(--label-2);
  letter-spacing: -.005em;
  background: transparent;
  border-bottom: 1px solid var(--separator);
}
.tbl td {
  padding: 13px 20px;
  vertical-align: middle;
  border-bottom: 1px solid var(--separator);
}
/* Grouped-list convention: separators stop short of the container edge. */
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr { transition: background .15s var(--ease); }
.tbl tbody tr:hover { background: var(--fill); }
.tbl .num { text-align: end; font-variant-numeric: tabular-nums; }
.tbl .actions { text-align: end; white-space: nowrap; }
.row-click { cursor: pointer; }
.t-strong { font-weight: 570; color: var(--label); }
.t-muted { color: var(--label-2); font-size: 13px; }
.t-mono {
  font-family: "SF Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 13px; letter-spacing: -.02em;
}

/* ---------------------------------------------------------------- badges */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: var(--fill-2); color: var(--label-2);
  font-size: 12.5px; font-weight: 570; white-space: nowrap;
}
.badge.green  { background: var(--tint-green);  color: var(--on-green); }
.badge.amber  { background: var(--tint-orange); color: var(--on-orange); }
.badge.red    { background: var(--tint-red);    color: var(--on-red); }
.badge.blue   { background: var(--tint-blue);   color: var(--on-blue); }
.badge.violet { background: var(--tint-purple); color: var(--on-purple); }
.badge.teal   { background: var(--tint-accent); color: var(--on-accent-tint); }
.dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* ---------------------------------------------------------------- forms */
.field { margin-bottom: 16px; }
.field > label {
  display: block; margin-bottom: 6px;
  font-size: 13.5px; font-weight: 550; color: var(--label-2);
}
.field .hint { margin-top: 6px; font-size: 12.5px; color: var(--label-3); }

.input, .select, .textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--fill);
  color: var(--label);
  outline: none;
  transition: background .16s var(--ease), box-shadow .16s var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--label-3); }
.input:hover, .select:hover, .textarea:hover { background: var(--fill-2); }
.input:focus, .select:focus, .textarea:focus {
  background: var(--surface);
  box-shadow: 0 0 0 4px var(--tint-accent), inset 0 0 0 1px var(--accent);
}
.textarea { min-height: 84px; resize: vertical; }

.select {
  appearance: none; padding-inline-end: 34px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%238A8A8E' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
}
body[dir="rtl"] .select { background-position: left 12px center; }

.form-row { display: grid; gap: 16px; grid-template-columns: repeat(2, minmax(0,1fr)); }
.form-row.three { grid-template-columns: repeat(3, minmax(0,1fr)); }

.check { display: flex; align-items: center; gap: 9px; font-size: 14px; }
.check input { width: 18px; height: 18px; accent-color: var(--accent); flex: none; }

.toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 18px; }
.toolbar .grow { flex: 1; min-width: 200px; }

.search { position: relative; }
.search .input { padding-inline-start: 38px; }
.search::before {
  content: ''; position: absolute; inset-inline-start: 13px; top: 50%;
  width: 17px; height: 17px; margin-top: -8.5px; opacity: .45;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'><circle cx='10.8' cy='10.8' r='6.2'/><path d='M15.4 15.4l4.2 4.2'/></svg>") center/contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'><circle cx='10.8' cy='10.8' r='6.2'/><path d='M15.4 15.4l4.2 4.2'/></svg>") center/contain no-repeat;
  pointer-events: none;
}

/* ---------------------------------------------------------------- segmented */
.segmented {
  display: inline-flex; gap: 2px; padding: 2px;
  background: var(--fill); border-radius: var(--r-pill);
}
.segmented button {
  border: 0; background: transparent; cursor: pointer;
  padding: 7px 15px; border-radius: var(--r-pill);
  font-size: 13.5px; font-weight: 550; color: var(--label-2);
  transition: background .2s var(--ease), color .2s var(--ease), transform .16s var(--ease);
}
.segmented button:active { transform: scale(.96); }
.segmented button.active {
  background: var(--surface); color: var(--label);
  box-shadow: 0 1px 4px rgba(0,0,0,.10), var(--spec);
}

/* ---------------------------------------------------------------- modal */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center; padding: 22px;
  overflow-y: auto;
  background: rgba(0,0,0,.32);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: fade .22s var(--ease);
}
@keyframes fade { from { opacity: 0; } }

.modal {
  width: min(700px, 100%);
  max-height: 90vh;
  display: flex; flex-direction: column;
  background: var(--glass-strong);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-3), var(--spec), 0 0 0 1px var(--glass-edge);
  animation: sheet .34s var(--ease);
}
.modal.wide { width: min(1040px, 100%); }
@keyframes sheet { from { opacity: 0; transform: translateY(22px) scale(.97); } }

/* iOS sheet grabber */
.modal-head {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  padding: 20px 22px 14px;
  border-bottom: 1px solid var(--separator);
}
.modal-head::before {
  content: ''; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
  width: 38px; height: 5px; border-radius: var(--r-pill);
  background: var(--fill-3);
}
.modal-head h3 { font-size: 18px; font-weight: 650; letter-spacing: -.028em; }
.modal-body { padding: 22px; overflow-y: auto; }
.modal-foot {
  display: flex; gap: 10px; justify-content: flex-end;
  padding: 16px 22px;
  border-top: 1px solid var(--separator);
}

/* ---------------------------------------------------------------- toast */
#toasts {
  position: fixed; z-index: 200;
  bottom: 24px; inset-inline-end: 24px;
  display: flex; flex-direction: column; gap: 10px;
}
.toast {
  display: flex; gap: 10px; align-items: flex-start;
  max-width: 400px; padding: 13px 17px;
  border-radius: var(--r-lg);
  background: rgba(28,28,30,.82);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  color: #fff; font-size: 14px; font-weight: 500;
  box-shadow: var(--sh-3), inset 0 1px 0 rgba(255,255,255,.14);
  animation: toastIn .38s var(--ease);
}
@keyframes toastIn { from { opacity: 0; transform: translateY(16px) scale(.94); } }
.toast.ok   { background: rgba(0,122,90,.88); }
.toast.err  { background: rgba(190,40,32,.88); }
.toast.warn { background: rgba(170,100,0,.88); }

/* ---------------------------------------------------------------- misc */
.empty { padding: 54px 24px; text-align: center; color: var(--label-2); }
.empty .big {
  display: grid; place-items: center;
  width: 74px; height: 74px; margin: 0 auto 14px;
  border-radius: var(--r-lg);
  background: var(--fill);
  color: var(--label-3);
}
.empty h4 { margin-bottom: 5px; font-size: 16px; font-weight: 600; color: var(--label); }

.spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 2.5px solid var(--fill-2); border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading { display: grid; place-items: center; padding: 64px; }

.divider { height: 1px; background: var(--separator); margin: 18px 0; }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 10px 18px; font-size: 14px; }
.kv dt { color: var(--label-2); font-weight: 500; }
.kv dd { margin: 0; font-weight: 520; }

.alert {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 13px 16px; border-radius: var(--r);
  font-size: 14px; font-weight: 480;
}
.alert.warn { background: var(--tint-orange); color: var(--on-orange); }
.alert.err  { background: var(--tint-red);    color: var(--on-red); }
.alert.ok   { background: var(--tint-green);  color: var(--on-green); }
.alert.info { background: var(--tint-blue);   color: var(--on-blue); }

/* ---------------------------------------------------------------- charts */
.chart { display: flex; align-items: flex-end; gap: 5px; height: 132px; padding-top: 8px; }
.chart .bar {
  flex: 1; min-height: 4px;
  border-radius: var(--r-xs) var(--r-xs) 3px 3px;
  background: linear-gradient(180deg, var(--accent-2), var(--accent));
  opacity: .45;
  transition: opacity .18s var(--ease), transform .18s var(--ease);
}
.chart .bar:hover { opacity: 1; transform: scaleY(1.03); transform-origin: bottom; }
.chart .bar.alt { background: linear-gradient(180deg, var(--sys-indigo), #4340B5); opacity: .5; }
.chart-x { display: flex; gap: 5px; margin-top: 8px; }
.chart-x span { flex: 1; text-align: center; font-size: 11px; color: var(--label-3); }

.ranks { display: flex; flex-direction: column; gap: 13px; }
.rank { display: grid; grid-template-columns: 1fr auto; gap: 5px 12px; font-size: 14px; }
.rank .track {
  grid-column: 1 / -1; height: 7px; border-radius: var(--r-pill);
  background: var(--fill); overflow: hidden;
}
.rank .fill {
  height: 100%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
}

/* ---------------------------------------------------------------- rx code */
.rx-code {
  display: inline-block;
  padding: 5px 12px; border-radius: var(--r-xs);
  background: var(--tint-accent); color: var(--on-accent-tint);
  font-family: "SF Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 13.5px; font-weight: 620; letter-spacing: .02em;
}
.rx-code.big {
  padding: 16px 24px; border-radius: var(--r);
  font-size: 25px; letter-spacing: .1em;
  background: linear-gradient(150deg, var(--accent-2), var(--accent) 55%, var(--accent-deep));
  color: var(--on-accent);
  box-shadow: 0 6px 20px rgba(11,106,42,.32), inset 0 1px 0 rgba(255,255,255,.35);
}

/* ---------------------------------------------------------------- line items */
.line-item {
  display: grid; gap: 12px;
  grid-template-columns: 2.2fr 1fr 1.2fr .7fr .7fr auto;
  align-items: end;
  padding: 15px; margin-bottom: 12px;
  border-radius: var(--r);
  background: var(--fill);
}
.line-item .field { margin: 0; }
.line-item .input, .line-item .select { background: var(--surface); }

/* ---------------------------------------------------------------- autocomplete */
.ac { position: relative; }
.ac-list {
  position: absolute; z-index: 40; top: 100%; inset-inline: 0;
  margin-top: 6px; max-height: 280px; overflow-y: auto;
  border-radius: var(--r);
  background: var(--glass-strong);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  box-shadow: var(--sh-2), 0 0 0 1px var(--glass-edge);
  animation: sheet .2s var(--ease);
}
.ac-item {
  padding: 10px 14px; cursor: pointer; font-size: 14px;
  border-bottom: 1px solid var(--separator);
}
.ac-item:last-child { border-bottom: 0; }
.ac-item:hover, .ac-item.sel { background: var(--fill); }

/* ---------------------------------------------------------------- auth */
.auth-wrap { min-height: 100vh; display: grid; grid-template-columns: 1.05fr .95fr; }
.auth-art {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; justify-content: center;
  padding: 60px;
  color: #fff;
  background: linear-gradient(155deg, #0B5320 0%, #0B6A2A 42%, #2E9247 100%);
}
.auth-art::before {
  content: ''; position: absolute; width: 34rem; height: 34rem; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.30), transparent 68%);
  top: -9rem; inset-inline-end: -9rem;
}
.auth-art::after {
  content: ''; position: absolute; width: 26rem; height: 26rem; border-radius: 50%;
  background: radial-gradient(circle, rgba(88,86,214,.35), transparent 70%);
  bottom: -8rem; inset-inline-start: -6rem;
}
.auth-art > * { position: relative; z-index: 1; }
.auth-art h2 {
  max-width: 15ch; margin-bottom: 16px;
  font-size: 34px; font-weight: 700; line-height: 1.14; letter-spacing: -.04em;
}
.auth-art p { max-width: 46ch; line-height: 1.6; color: rgba(255,255,255,.86); }

.auth-features { margin-top: 38px; display: flex; flex-direction: column; gap: 16px; }
.auth-feature { display: flex; gap: 14px; align-items: flex-start; }
.auth-feature .ico {
  flex: none; width: 40px; height: 40px; border-radius: 12px;
  display: grid; place-items: center;
  background: rgba(255,255,255,.18);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3);
}
.auth-feature b { display: block; font-size: 14.5px; font-weight: 600; }
.auth-feature span { font-size: 13.5px; color: rgba(255,255,255,.80); }

.auth-form { display: grid; place-items: center; padding: 44px 26px; background: var(--bg); }
.auth-inner { width: min(420px, 100%); }
.auth-inner .brand { padding: 0 0 28px; }

.demo-accounts { margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--separator); }
.demo-accounts h4 {
  margin-bottom: 11px; font-size: 12.5px; font-weight: 570; color: var(--label-2);
}
.demo-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.demo-btn {
  padding: 10px 13px; text-align: start; cursor: pointer;
  border: 0; border-radius: var(--r-sm);
  background: var(--surface); box-shadow: var(--sh-1);
  transition: transform .16s var(--ease), background .18s var(--ease);
}
.demo-btn:hover { background: var(--tint-accent); }
.demo-btn:active { transform: scale(.97); }
.demo-btn b { display: block; font-size: 13.5px; font-weight: 570; }
.demo-btn span { font-size: 12px; color: var(--label-2); }

/* ---------------------------------------------------------------- bidi
   Medicine names, codes and identifiers always render in English. Inside an
   RTL page they must read left-to-right internally but still sit on the start
   (right) edge of their cell, so the column stays tidy. */
[dir="ltr"] { unicode-bidi: isolate; }
body[dir="rtl"] div[dir="ltr"],
body[dir="rtl"] b[dir="ltr"],
body[dir="rtl"] dd[dir="ltr"] { text-align: right; }

/* Latin-only inputs (prescription codes, catalog search) stay left-aligned:
   the user is typing Latin characters into them. */
body[dir="rtl"] input[dir="ltr"],
body[dir="rtl"] textarea[dir="ltr"] { text-align: left; }

/* The bar chart reads left-to-right as a timeline in every locale. */
body[dir="rtl"] .chart,
body[dir="rtl"] .chart-x { direction: ltr; }

/* ---------------------------------------------------------------- motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ---------------------------------------------------------------- print */
@media print {
  body::before { display: none; }
  .sidebar, .topbar, .toolbar, .tabbar, .no-print, .modal-foot { display: none !important; }
  .shell { grid-template-columns: 1fr; }
  .content { padding: 0; }
  .modal-backdrop { position: static; display: block; padding: 0;
                    background: none; backdrop-filter: none; }
  .modal { width: 100%; max-height: none; background: #fff;
           box-shadow: none; backdrop-filter: none; animation: none; }
  .modal-head::before { display: none; }
  .card { box-shadow: none; }
  body { background: #fff; }
}
.print-only { display: none; }
@media print { .print-only { display: block; } }

/* ---------------- prescription token ---------------- */
.rx-token { margin-top: 10px; text-align: center; }
.rx-token svg { max-width: 100%; height: auto; border-radius: 6px; }

/* Solar Hijri echo under a Gregorian date input */
.shamsi-echo { margin-top: 5px; color: var(--accent-deep); font-weight: 550; min-height: 1em; }

/* ============================================================
   Reports — screen preview and print/PDF layout
   ============================================================ */
.report-doc { color: var(--label); }

.report-head {
  display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap;
  padding-bottom: 16px; margin-bottom: 16px;
  border-bottom: 2px solid var(--accent);
}
.report-brand { display: flex; align-items: center; gap: 11px; }
.report-mark {
  width: 42px; height: 42px; border-radius: 12px; flex: none;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(160deg, var(--accent-2), var(--accent-deep));
}
.report-org { font-weight: 650; font-size: 15px; }
.report-country { font-size: 12.5px; color: var(--label-2); }
.report-titles { margin-inline-start: auto; text-align: end; }
.report-titles h1 { font-size: 21px; font-weight: 680; letter-spacing: -.03em; }
.report-titles p { margin: 3px 0 0; font-size: 13px; color: var(--label-2); }

.report-meta {
  display: flex; flex-wrap: wrap; gap: 10px 28px;
  margin: 0 0 18px; padding: 12px 16px;
  background: var(--fill); border-radius: var(--r);
  font-size: 12.5px;
}
.report-meta div { display: flex; gap: 7px; }
.report-meta dt { color: var(--label-2); font-weight: 550; }
.report-meta dd { margin: 0; font-weight: 570; }

.report-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.report-table th {
  text-align: start; padding: 9px 10px; font-weight: 600; font-size: 11.5px;
  color: #fff; background: var(--accent-deep);
  border: 1px solid var(--accent-deep);
}
.report-table td {
  padding: 7px 10px; border: 1px solid var(--separator); vertical-align: top;
}
/* A long unbreakable word sets a column's minimum width, and enough of those
   push a wide report past the edge of the paper - where the last column is
   simply not printed. Values may break mid-word to keep the table on the page;
   headings may not, because a heading broken as "Manufactur / er" is harder to
   read than the narrow column it saves. */
.report-table td { overflow-wrap: anywhere; }
.report-table th { overflow-wrap: normal; }
/* Past ten columns, evenly divided space is too little for the text in it, so
   the whole table steps down a size rather than losing a column off the end. */
.report-table.dense { font-size: 11.5px; }
.report-table.dense th, .report-table.dense td { padding: 5px 6px; }
.report-table tbody tr:nth-child(even) { background: var(--fill); }
.report-table .num { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
.report-table tfoot td { background: var(--tint-accent); border-color: var(--accent); }
.report-table .alt { display: block; font-size: 10.5px; color: var(--label-2); }

.report-empty { padding: 40px; text-align: center; color: var(--label-2); }

.report-foot {
  display: none;
  justify-content: space-between; gap: 16px;
  padding-top: 10px; margin-top: 18px;
  border-top: 1px solid var(--separator);
  font-size: 10.5px; color: var(--label-2);
}

/* The preview sheet gets more room than a normal modal. */
.report-modal .modal { width: min(1180px, 100%); }
.report-modal .modal-body { background: var(--surface); }

/* ---------------- print / PDF ----------------
   No @page rule here on purpose. A stylesheet-level @page applies to every
   print the application ever does, and these documents do not agree on one
   page setup: a report wants landscape, a prescription upright, a label sheet
   the margins of its label stock, a counter receipt an 80 mm roll. The setup is
   injected for the duration of the print instead — see printPage() in ui.js. */
@media print {
  /* Only the report survives; the application chrome does not. */
  body > *:not(#modal-root) { display: none !important; }
  #modal-root, .modal-backdrop, .modal, .modal-body { display: block !important; }

  .modal-backdrop {
    position: static !important; padding: 0 !important;
    background: none !important; backdrop-filter: none !important;
    overflow: visible !important;
  }
  .modal {
    width: 100% !important; max-height: none !important;
    box-shadow: none !important; border-radius: 0 !important;
    background: #fff !important; backdrop-filter: none !important; animation: none !important;
  }
  .modal-head, .modal-foot { display: none !important; }
  .modal-body { padding: 0 !important; overflow: visible !important; background: #fff !important; }

  .report-doc { color: #000; }
  .report-mark { background: #0B5320 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .report-head { border-bottom-color: #0B5320; }
  .report-meta { background: #f2f4f4 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  .report-table { font-size: 9.5pt; table-layout: auto; }
  .report-table.dense { font-size: 7.6pt; }
  .report-table.dense th, .report-table.dense td { padding: 3px 4px; }
  .report-table th {
    background: #0B5320 !important; color: #fff !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .report-table tbody tr:nth-child(even) { background: #f6f8f8 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .report-table tfoot td { background: #e6f5f2 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  /* Repeat the header on every page and never split a row across pages. */
  .report-table thead { display: table-header-group; }
  .report-table tfoot { display: table-footer-group; }
  .report-table tr { page-break-inside: avoid; break-inside: avoid; }
  .report-head, .report-meta { page-break-after: avoid; break-after: avoid; }

  /* A fixed footer repeats on every printed page in Chrome. */
  .report-foot {
    display: flex;
    position: fixed; bottom: 0; inset-inline: 0;
    background: #fff; border-top: 1px solid #ccc;
  }
}

/* ================================================================ field use
 * Connection state, the offline queue, the retail counter, pack verification
 * and dosing pictograms. These are the parts of the interface used standing
 * up, often on a shared machine with a customer waiting, so targets are larger
 * and state is louder than elsewhere in the app.
 * ========================================================================== */

/* ---------------------------------------------------------------- connection */
.conn-pill { position: relative; }
.conn-pill.is-offline { color: var(--sys-red); }
.conn-pill.is-waiting { color: var(--sys-orange); }
.conn-count {
  position: absolute; top: 2px; inset-inline-end: 2px;
  min-width: 16px; height: 16px; padding: 0 4px;
  display: grid; place-items: center;
  font-size: 10.5px; font-weight: 700; line-height: 1;
  color: #fff; background: var(--sys-orange);
  border-radius: 999px; box-shadow: 0 0 0 2px var(--glass);
}
.conn-pill.is-failed .conn-count { background: var(--sys-red); }

/* The offline pill pulses rather than sitting still: on a shared counter
   machine it has to be noticed without anyone having gone looking for it. */
.conn-pill.is-offline::after {
  content: ''; position: absolute; inset: -2px;
  border-radius: inherit; border: 1.5px solid var(--sys-red);
  opacity: 0; animation: connPulse 2.4s var(--ease) infinite;
}
@keyframes connPulse {
  0%   { opacity: .55; transform: scale(.94); }
  70%  { opacity: 0;   transform: scale(1.18); }
  100% { opacity: 0;   transform: scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
  .conn-pill.is-offline::after { animation: none; opacity: .5; }
}

.topbar .sub.is-stale {
  color: var(--sys-orange); font-weight: 600;
}
.topbar .sub.is-stale::before {
  content: '●'; font-size: 8px; vertical-align: 2px; margin-inline-end: 5px;
}

.queue-row {
  display: flex; gap: 10px; align-items: center;
  padding: 12px 0; border-bottom: 1px solid var(--separator);
}
.queue-row:last-child { border-bottom: 0; }
.queue-row.failed { --queue-accent: var(--sys-red); }

/* ---------------------------------------------------------------- counter */
.ac-btn {
  display: flex; flex-direction: column; align-items: stretch; gap: 2px;
  width: 100%; text-align: start; background: none; border: 0;
  font: inherit; color: inherit;
}
.ac-btn:disabled { opacity: .55; cursor: not-allowed; }
.ac-btn .t-muted { font-size: 12px; }

.cart-table td { vertical-align: middle; }
.cart-table .input-sm {
  padding: 6px 8px; font-size: 13.5px; height: auto;
}
.cart-table .input-sm.num { text-align: end; font-variant-numeric: tabular-nums; }
.cart-table tfoot td {
  border-top: 1.5px solid var(--separator); padding-top: 12px; font-size: 15px;
}

.btn-lg { padding: 13px 20px; font-size: 15.5px; font-weight: 600; }
.input-lg { padding: 13px 14px; font-size: 16px; letter-spacing: .02em; }

.back-link {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 13.5px; font-weight: 550; color: var(--label-2);
}
.back-link:hover { color: var(--accent); }
/* The arrow is written LTR in the markup; in RTL it has to point the other way. */
body[dir="rtl"] .back-link { transform: scaleX(1); }
body[dir="rtl"] .back-link::first-letter { unicode-bidi: bidi-override; }

/* ---------------------------------------------------------------- receipt */
.receipt { max-width: 380px; margin: 0 auto; font-size: 13.5px; }
.receipt h2 { text-align: center; font-size: 19px; margin-bottom: 4px; }
.receipt .r-meta {
  display: grid; gap: 3px; margin: 12px 0;
  padding: 10px 0; border-block: 1px dashed var(--separator);
}
.receipt .r-meta > div { display: flex; justify-content: space-between; gap: 12px; }
.receipt .r-meta span { color: var(--label-2); }
.receipt table { width: 100%; border-collapse: collapse; }
.receipt td { padding: 5px 0; vertical-align: top; }
.receipt .num { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
.receipt tr.total td { border-top: 1px solid var(--separator); padding-top: 9px; font-size: 15px; }
.receipt .r-note {
  margin-top: 12px; padding: 8px 10px; border-radius: 8px;
  background: var(--tint-orange); color: var(--on-orange); font-size: 12.5px;
}

/* ---------------------------------------------------------------- pack check */
.pack-verdict { margin-top: 14px; }
.pack-reasons {
  margin: 10px 0 0; padding: 0; list-style: none;
  display: grid; gap: 6px;
}
.pack-reasons li {
  position: relative; padding-inline-start: 22px;
  font-size: 13.5px; color: var(--label);
}
.pack-reasons li::before {
  content: '!'; position: absolute; inset-inline-start: 0; top: 1px;
  width: 15px; height: 15px; border-radius: 999px;
  display: grid; place-items: center;
  font-size: 10.5px; font-weight: 800;
  background: var(--sys-orange); color: #fff;
}
.pack-verdict.blocked .pack-reasons li::before { background: var(--sys-red); }

.pack-facts {
  display: grid; grid-template-columns: auto 1fr; gap: 6px 14px;
  margin: 14px 0; font-size: 13.5px;
}
.pack-facts dt { color: var(--label-2); }
.pack-facts dd { margin: 0; font-weight: 600; }

/* ---------------------------------------------------------------- pictograms
 * Sized and spaced to survive a photocopy and a 200-afghani thermal printer:
 * heavy strokes, high contrast, and no meaning carried by colour alone.
 */
.pict-strip {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px; margin-top: 8px;
  border-radius: var(--r-sm);
  background: var(--fill);
}
.pict-slot, .pict-food {
  flex: 1 1 0; min-width: 74px;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 8px 4px; border-radius: var(--r-sm);
  text-align: center; font-size: 11.5px; font-weight: 600;
  color: var(--label-2);
  border: 1.5px solid transparent;
}
.pict-slot.on, .pict-food.on {
  color: var(--label); background: var(--surface);
  border-color: var(--accent);
}
/* Off slots keep their glyph but lose all weight - the contrast between a
   taken dose and a skipped one is the entire message. */
.pict-slot.off { opacity: .32; }
.pict-slot .pict-none { font-style: normal; color: var(--label-3); }
.pict-food { border-color: var(--separator); }

.pict-count { display: inline-flex; align-items: center; gap: 1px; }
.pict-count b { font-size: 12px; margin-inline-start: 2px; }


/* The prescriber's schedule picker: the same glyphs the patient will be given,
   so what is chosen here and what is printed there cannot drift apart. */
.sched-picker {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: stretch;
}
.sched-box {
  position: relative; flex: 0 0 auto; min-width: 72px;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 8px 10px; cursor: pointer;
  border: 1.5px solid var(--separator); border-radius: var(--r-sm);
  font-size: 11.5px; font-weight: 600; color: var(--label-2);
  background: var(--surface);
  transition: border-color .15s var(--ease), color .15s var(--ease), background .15s var(--ease);
}
.sched-box:hover { border-color: var(--label-3); }
.sched-box.on { border-color: var(--accent); color: var(--accent); background: var(--tint-accent); }
.sched-box input { position: absolute; opacity: 0; pointer-events: none; }
.sched-box:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.sched-any { font-size: 22px; line-height: 26px; height: 26px; }
.sched-sep { flex: 0 0 1px; align-self: stretch; background: var(--separator); margin: 0 6px; }

/* ---------------------------------------------------------------- label print
 * A dispensing label, sized to Avery L7166 / J8166 stock — 99.1 x 93.1 mm, six
 * to an A4 sheet, two across. Everything is in absolute units so the sheet on
 * screen is the sheet that comes out of the printer, and a pharmacy with real
 * label stock can feed it straight through. The same geometry as the server's
 * label document, so a printed sheet and a downloaded PDF are the same sheet.
 */
.label-sheet { display: grid; grid-template-columns: repeat(2, 99.1mm); justify-content: center; }

.med-label {
  width: 99.1mm; height: 93.1mm; padding: 5mm;
  display: flex; flex-direction: column;
  border: 1px dashed #999; border-radius: 2mm;
  color: #000; background: #fff;
  overflow: hidden;
}
/* Copies, beside the print button rather than left to the print dialog: three
   of one label and one of another is a normal request at a counter, and the
   dialog's copy count cannot express it. */
.label-copies {
  display: flex; align-items: center; gap: 8px;
  margin-inline-end: auto; font-size: 13px; color: var(--label-2);
}
.label-copies .input { width: 74px; }
.med-label .l-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding-bottom: 8px; margin-bottom: 10px; border-bottom: 1.5px solid #000;
}
.med-label .l-head > :last-child { flex: 0 0 auto; white-space: nowrap; }
.med-label .l-name {
  font-size: 15px; font-weight: 700; line-height: 1.2;
  direction: ltr; text-align: start; unicode-bidi: isolate;
  /* Clipped rather than allowed to push the dose instruction off the label,
     which is the one thing on it that must survive. */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.med-label .l-sub { font-size: 11px; color: #333; }
.med-label .l-instruction {
  margin: 3mm 0 0; padding: 2mm 3mm;
  border: 1.5px solid #000; border-radius: 2mm;
  font-size: 14px; font-weight: 700; line-height: 1.3;
}
.med-label .l-token { direction: ltr; }
.med-label .l-token svg { display: block; height: 26px; width: auto; }
.med-label .l-foot > div:first-child { line-height: 1.5; }
.med-label .pict-strip { background: none; padding: 0; gap: 6px; }
.med-label .pict-slot.on,
.med-label .pict-food.on { background: none; border-color: #000; color: #000; }
.med-label .pict-slot.off { opacity: .25; }
.med-label .l-foot {
  margin-top: auto; padding-top: 2mm; border-top: 1px solid #999;
  font-size: 10px; color: #333;
  display: flex; justify-content: space-between; align-items: flex-end; gap: 8px;
}
.med-label .l-warn { font-size: 11.5px; margin-top: 2mm; }
.med-label .l-warn b { color: #A85B00; }

@media print {
  /* Everything outside the open sheet is already hidden by the print block
     above - a label and a receipt print alone, like a report does. */
  .med-label { page-break-inside: avoid; break-inside: avoid; }
  /* The grid is already the label stock's own pitch; the page margins that
     line it up come from printPage() at the moment of printing. */
  .label-sheet { justify-content: start; }
  /* The receipt keeps its width. Stretched across a sheet it stops looking like
     a receipt, and on the 80 mm roll a counter actually uses it would overflow. */
  .receipt { max-width: 80mm; margin: 0; }
}

/* ================================================================ branding
 * An organisation's own logo, and a prescriber's stamp. A prescription here is
 * not considered complete without the seal, so these are not decoration - the
 * stamp is what a pharmacy looks for before it dispenses.
 * ========================================================================== */

/* The sidebar mark. A supplied logo is shown on a plain plate rather than the
   accent gradient, because a logo already carries its own colour. */
.brand-mark.has-logo {
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--separator);
  padding: 4px;
}
.brand-mark.has-logo img {
  width: 100%; height: 100%; object-fit: contain; display: block;
}

/* ---------------------------------------------------------------- editor */
.brand-slot {
  display: flex; gap: 14px; align-items: center;
  padding: 14px 0; border-bottom: 1px solid var(--separator);
}
.brand-slot:last-of-type { border-bottom: 0; }
.brand-meta { flex: 1; min-width: 0; }
.brand-meta b { display: block; margin-bottom: 2px; }
.brand-actions { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }

.brand-preview {
  flex: 0 0 96px; width: 96px; height: 96px;
  display: grid; place-items: center; padding: 8px;
  border-radius: var(--r-sm);
  /* A checkerboard, so a transparent stamp reads as transparent rather than as
     a white square that will print over the text beneath it. */
  background-color: var(--surface);
  background-image:
    linear-gradient(45deg, var(--fill) 25%, transparent 25%),
    linear-gradient(-45deg, var(--fill) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--fill) 75%),
    linear-gradient(-45deg, transparent 75%, var(--fill) 75%);
  background-size: 12px 12px;
  background-position: 0 0, 0 6px, 6px -6px, -6px 0;
  box-shadow: inset 0 0 0 1px var(--separator);
}
.brand-preview.stamp { border-radius: 50%; }
.brand-preview img { max-width: 100%; max-height: 100%; object-fit: contain; }
.brand-empty { color: var(--label-3); }
.brand-preview.busy { opacity: .45; }

/* ---------------------------------------------------------------- record */
.rx-letterhead {
  display: flex; gap: 12px; align-items: center;
  padding-bottom: 12px; margin-bottom: 14px;
  border-bottom: 2px solid var(--accent);
}
.rx-letterhead img { max-height: 44px; max-width: 140px; object-fit: contain; }

/* The signature block. The rule is drawn whether or not a stamp exists, so a
   printed copy always leaves somewhere to sign. */
.rx-sign {
  display: flex; justify-content: flex-end;
  margin-top: 22px; page-break-inside: avoid; break-inside: avoid;
}
.rx-sign .sign-block { text-align: center; min-width: 190px; }
.rx-sign .rule { border-bottom: 1px solid var(--label-3); height: 32px; }
.rx-sign .cap { font-size: 12px; color: var(--label-2); margin-top: 3px; }
.rx-sign .stamp { display: block; margin: 0 auto -10px; object-fit: contain; }

@media print {
  .rx-letterhead { border-bottom-color: #0B5320; }
  .rx-sign .rule { border-bottom-color: #666; }
  .rx-letterhead img, .rx-sign .stamp,
  .brand-mark.has-logo img {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
}

/* The organisation's mark on a report header and on a till receipt. Same
   treatment as the sidebar: a plain plate, because a logo brings its own
   colour and the accent gradient would fight it. */
.report-mark.has-logo {
  background: #fff; padding: 3px;
  box-shadow: inset 0 0 0 1px var(--separator);
}
.report-mark.has-logo img { width: 100%; height: 100%; object-fit: contain; display: block; }

.receipt .r-logo { text-align: center; margin-bottom: 8px; }
.receipt .r-logo img { max-height: 46px; max-width: 190px; object-fit: contain; }

@media print {
  .report-mark.has-logo, .receipt .r-logo img {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .report-mark.has-logo { background: #fff !important; }
}

/* ================================================================ verification
 * The Ministry's approval badge. Blue rather than the app's teal on purpose:
 * it is a statement about an organisation's standing, not app chrome, and it
 * should read the same wherever it appears.
 * ========================================================================== */
.verified-tick {
  display: inline-flex; align-items: center; gap: 4px;
  vertical-align: -5px; margin-inline-start: 6px;
  color: var(--verified);
  /* A faint halo so the badge separates from a bold name behind it. Its own
     colour, so it stays right in both themes. */
  filter: drop-shadow(0 1px 1px rgba(29, 116, 208, .28));
}
.verified-tick > span {
  font-size: 12.5px; font-weight: 600; letter-spacing: .01em;
}
/* The tick is meaningful, so it never shrinks away inside a cramped cell. */
.verified-tick svg { flex: 0 0 auto; }

/* ---------------------------------------------------------------- signature */
/* A signature is written ON the line, not above it. Stacked above a blank rule
   it reads as an unsigned document with a picture on it. */
.rx-sign .rule { position: relative; }
.rx-sign .autograph {
  position: absolute; inset-inline: 0; bottom: -1px;
  max-height: 40px; max-width: 100%; object-fit: contain;
  margin: 0 auto; display: block;
}
.brand-preview.signature { border-radius: var(--r-sm); }

/* ---------------------------------------------------------------- accent */
.accent-row { display: flex; gap: 8px; flex-wrap: wrap; }
.accent-swatch {
  width: 30px; height: 30px; padding: 0; cursor: pointer;
  border-radius: 50%; border: 2px solid transparent;
  background: var(--swatch);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
  transition: transform .12s var(--ease), border-color .12s var(--ease);
}
.accent-swatch:hover { transform: scale(1.08); }
.accent-swatch.on {
  border-color: var(--label);
  box-shadow: inset 0 0 0 2px var(--surface), inset 0 0 0 3px rgba(0, 0, 0, .12);
}
.accent-swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media print {
  .verified-tick { color: #1D74D0 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ================================================================ stewardship
 * The AWaRe indicator: one number against one target. Everything else on that
 * page exists to answer "where is it coming from", so the headline gets the
 * weight and the breakdowns stay quiet.
 * ========================================================================== */
.aware-headline.on  { box-shadow: var(--sh-1), inset 3px 0 0 var(--sys-green); }
.aware-headline.off { box-shadow: var(--sh-1), inset 3px 0 0 var(--sys-orange); }
body[dir="rtl"] .aware-headline.on  { box-shadow: var(--sh-1), inset -3px 0 0 var(--sys-green); }
body[dir="rtl"] .aware-headline.off { box-shadow: var(--sh-1), inset -3px 0 0 var(--sys-orange); }

.aware-figure { display: flex; gap: 24px; align-items: center; flex-wrap: wrap; }
.aware-pct {
  font-size: 44px; font-weight: 700; line-height: 1.05;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}

/* A single stacked bar rather than a pie: the reader is comparing one segment
   against a threshold, which a line does and a circle does not. */
.aware-bar {
  position: relative; flex: 1; min-width: 240px; height: 26px;
  display: flex; border-radius: 999px; overflow: hidden;
  background: var(--fill);
}
.aware-bar .seg { height: 100%; }
.aware-bar .seg.access  { background: var(--sys-green); }
.aware-bar .seg.watch   { background: var(--sys-orange); }
.aware-bar .seg.reserve { background: var(--sys-red); }
/* The 70% mark, drawn on top so the gap to the target is readable at a glance. */
.aware-bar .target {
  position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: var(--label); border-radius: 2px;
}

.aware-legend {
  display: flex; gap: 18px; flex-wrap: wrap; margin-top: 12px;
  font-size: 12.5px; color: var(--label-2);
}
.aware-legend i {
  display: inline-block; width: 10px; height: 10px; border-radius: 3px;
  margin-inline-end: 6px; vertical-align: -1px;
}
.aware-legend i.access  { background: var(--sys-green); }
.aware-legend i.watch   { background: var(--sys-orange); }
.aware-legend i.reserve { background: var(--sys-red); }

/* ---------------------------------------------------------------- signals */
.signal {
  display: flex; gap: 14px; align-items: center;
  padding: 12px 16px; border-bottom: 1px solid var(--separator);
}
.signal:last-child { border-bottom: 0; }
.signal-count {
  flex: 0 0 46px; height: 46px; border-radius: 12px;
  display: grid; place-items: center;
  font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--tint-orange); color: var(--on-orange);
}
/* An immediate-notification disease is red on one case; a weekly one only
   turns red once it is running above its own baseline. */
.signal.immediate .signal-count { background: var(--tint-red); color: var(--on-red); }

/* A plain label/value row, for panels that are a short list of counts rather
   than a table. */
.kv-row {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--separator);
}
.kv-row:last-of-type { border-bottom: 0; }

/* ================================================================ messages */
/*  Two panes on a wide screen, one at a time on a phone. The `data-open`
    attribute on .chat says which pane a narrow layout is showing; on a wide
    one it is ignored, because both are visible anyway.  */
.chat {
  display: grid;
  grid-template-columns: minmax(260px, 340px) 1fr;
  gap: 16px;
  /* Fills what is left under the top bar so the thread scrolls inside itself
     rather than pushing the page down - a compose box that walks off the
     bottom of a long conversation is the classic web-chat mistake.

     The calc is a fallback for the exact height, which comes from the rule
     below: subtracting fixed numbers means guessing how tall the top bar is,
     and it is taller whenever a page title wraps. */
  height: calc(100dvh - 126px);
  min-height: 420px;
}

/* The content column is already a flex child of a full-height shell, so
   letting the chat be a flex item of it gives the exact remaining height -
   top bar, page padding and tab bar all accounted for by the layout itself
   rather than by arithmetic. */
.content:has(> .chat) { display: flex; flex-direction: column; }
.content > .chat { flex: 1; min-height: 0; }
.chat-list, .chat-thread {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  overflow: hidden;
}
.chat-list-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid var(--separator);
}
.chat-list-head b { font-size: 15px; font-weight: 620; }
.chat-list-head .btn { margin-inline-start: auto; }
.chat-rows { flex: 1; overflow-y: auto; }

.chat-row {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 12px 14px; border: 0; background: none; cursor: pointer;
  border-bottom: 1px solid var(--separator);
  text-align: start; color: inherit; font: inherit;
}
.chat-row:hover { background: var(--fill); }
.chat-row.active { background: var(--tint-accent); }
.chat-row-text { min-width: 0; flex: 1; }
.chat-row-top { display: flex; gap: 8px; align-items: baseline; }
.chat-row-top b { font-size: 14.5px; font-weight: 570; }
.chat-row-top .t-muted { margin-inline-start: auto; font-size: 12px; white-space: nowrap; }
.chat-row-preview {
  font-size: 13px; color: var(--label-2); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-unread {
  flex: none; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: var(--r-pill); background: var(--accent); color: var(--on-accent);
  font-size: 12px; font-weight: 640; display: grid; place-items: center;
  font-variant-numeric: tabular-nums;
}
.chat-avatar {
  width: 38px; height: 38px; border-radius: var(--r-pill); flex: none;
  background: linear-gradient(160deg, var(--accent-2), var(--accent-deep));
  color: #fff; display: grid; place-items: center;
  font-weight: 600; font-size: 13.5px; letter-spacing: -.02em;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35);
}

.chat-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid var(--separator);
}
.chat-head b { font-size: 15px; font-weight: 600; }
/* The back arrow only exists in the one-pane layout. */
.chat-back { display: none; }
body[dir="rtl"] .chat-back .icn { transform: scaleX(-1); }

.chat-scroll {
  flex: 1; overflow-y: auto; padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
  /* Contained rather than smooth: a new message must not animate the reader
     away from the line they were on. */
  overscroll-behavior: contain;
}
.chat-empty { padding: 40px 20px; text-align: center; color: var(--label-2); font-size: 14px; }
.chat-placeholder { margin: auto; padding: 40px 24px; text-align: center; color: var(--label-2); }
.chat-placeholder .big { color: var(--label-3); margin-bottom: 10px; }
.chat-placeholder h4 { font-size: 16px; font-weight: 600; color: var(--label); margin-bottom: 4px; }

.chat-msg { max-width: min(560px, 78%); align-self: flex-start; }
.chat-msg.mine { align-self: flex-end; }
.chat-msg-who {
  font-size: 12px; font-weight: 560; color: var(--label-2);
  margin: 0 4px 3px; 
}
.chat-bubble {
  padding: 9px 13px; border-radius: 17px;
  background: var(--fill); color: var(--label);
  font-size: 14.5px; line-height: 1.45;
  /* Preserves the line breaks somebody typed - a dosing list written across
     three lines has to arrive as three lines. */
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.chat-msg.mine .chat-bubble {
  background: linear-gradient(160deg, var(--accent-2), var(--accent) 60%, var(--accent-deep));
  color: var(--on-accent);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3);
}
.chat-msg.withdrawn .chat-bubble {
  background: transparent; border: 1px dashed var(--separator); color: var(--label-3);
}
.chat-msg-time {
  font-size: 11.5px; color: var(--label-3); margin: 3px 6px 0;
  font-variant-numeric: tabular-nums;
}
.chat-msg.mine .chat-msg-time { text-align: end; }
/* Not yet acknowledged by the server. Dimmed rather than hidden: the person
   has to be able to see that what they wrote is still on its way. */
.chat-msg.pending, .chat-msg.queued { opacity: .6; }
.chat-msg.failed .chat-msg-time { color: var(--on-red); }

.chat-compose {
  display: flex; gap: 10px; align-items: flex-end;
  padding: 12px 14px; border-top: 1px solid var(--separator);
  background: var(--surface);
}
.chat-compose .textarea {
  min-height: 42px; max-height: 160px; resize: none; padding: 10px 14px;
  border-radius: 21px;
}
.chat-compose .btn-icon { flex: none; width: 42px; height: 42px; }
body[dir="rtl"] .chat-compose .btn-icon .icn { transform: scaleX(-1); }

.chat-contact {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 10px 8px; border: 0; background: none; cursor: pointer;
  border-bottom: 1px solid var(--separator); color: inherit; font: inherit;
  border-radius: var(--r-sm);
}
.chat-contact:hover { background: var(--fill); }
.chat-contact b { font-size: 14.5px; font-weight: 550; }

/* A count on a top-bar icon: messages, and anything else that needs one. */
.badge-count {
  position: absolute; top: 2px; inset-inline-end: 2px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: var(--r-pill);
  background: var(--sys-red); color: #fff;
  font-size: 11px; font-weight: 650; line-height: 17px; text-align: center;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--glass);
}

/* ============================================================================
   RESPONSIVE — last in the file on purpose.

   This is a single stylesheet with no build step and no layers, so the only
   thing that separates a phone rule from the desktop rule it overrides is
   source order. Keeping every breakpoint here, at the end, means a component
   added later cannot silently win against the layout it is meant to fold into.
   ========================================================================== */

/* ---------------------------------------------------------------- responsive
   Three layouts, not one that degrades.

     desktop  (> 1080px)  sidebar with labels, two-pane screens, wide tables
     tablet   (721-1080)  sidebar collapses to an icon rail; grids halve
     phone    (<= 720px)  sidebar gone, a bottom tab bar in its place, tables
                          restacked as cards, modals as full-height sheets

   The phone layout is the one that had to change most. A wrapping list of
   every nav item above the content was tolerable at seven entries and is a
   wall of chips at seventeen; the tab bar carries four, and the rest live in a
   sheet behind "More" - which is also where a thumb can actually reach them.
*/

/* ---- fluid grids, all sizes ---- */
@media (max-width: 1180px) {
  .g4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .g3, .g-2-1, .g-1-2 { grid-template-columns: 1fr; }
  .line-item { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .auth-wrap { grid-template-columns: 1fr; }
  .auth-art { display: none; }
}

/* ---------------------------------------------------------------- tablet */
@media (max-width: 1080px) and (min-width: 721px) {
  :root { --sidebar-w: 68px; }

  /* An icon rail. The labels are still in the DOM for screen readers and for
     the title attribute, they simply have nowhere to go at this width. */
  .sidebar { padding: 10px 8px; }
  .nav a { justify-content: center; padding: 11px 0; }
  .nav a span, .nav-group, .brand > div, .who > div:last-child { display: none; }
  .brand { justify-content: center; padding: 12px 0 16px; }
  .who { justify-content: center; padding: 10px 0; }
  .sidebar-foot .btn-block { font-size: 12px; padding: 6px 4px; }

  .content { padding: 20px 18px 32px; }
  .g2 { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------- phone */
@media (max-width: 720px) {
  .g2, .g4 { grid-template-columns: 1fr; }
  .form-row, .form-row.three { grid-template-columns: 1fr; }
  .line-item { grid-template-columns: 1fr; }

  .shell { grid-template-columns: 1fr; }
  .sidebar { display: none; }
  /* The tab bar is switched on at the bottom of this file, after its own
     rules - source order is the only thing separating them. */

  .topbar { padding: 8px 14px; min-height: 54px; gap: 8px; }
  .topbar h1 { font-size: 18px; }
  .topbar .sub { font-size: 12px; }
  /* The language selector is the widest thing up here and the least often
     used, so on a phone it moves into the account sheet. */
  .topbar [data-act="locale"] { display: none; }

  /* Room for the tab bar, plus the home indicator on a notched device. */
  .content {
    padding: 16px 14px calc(84px + env(safe-area-inset-bottom));
  }

  /* ---- tables become cards ---- */
  .table-wrap { overflow-x: visible; }
  .tbl, .tbl tbody, .tbl tr, .tbl td { display: block; width: 100%; }
  .tbl thead { display: none; }
  .tbl tr {
    background: var(--surface);
    border: 1px solid var(--separator);
    border-radius: var(--r-sm);
    margin-bottom: 10px;
    padding: 4px 14px;
  }
  .tbl tbody tr:hover { background: var(--surface); }
  .tbl td {
    display: flex; gap: 14px; align-items: baseline; justify-content: space-between;
    padding: 8px 0; border-bottom: 1px solid var(--separator);
    text-align: start; white-space: normal;
  }
  .tbl tr td:last-child { border-bottom: 0; }
  .tbl td::before {
    content: attr(data-label);
    flex: none; max-width: 45%;
    font-size: 12.5px; font-weight: 550; color: var(--label-2);
  }
  /* A column with no heading (an actions column, a chevron) needs no label
     and should keep the full width. */
  .tbl td[data-label=""]::before { display: none; }
  .tbl .num, .tbl .actions { text-align: end; }
  .tbl .actions { flex-wrap: wrap; justify-content: flex-end; gap: 8px; }

  /* ---- modals become sheets ---- */
  .modal-backdrop { padding: 0; align-items: flex-end; }
  .modal {
    width: 100%; max-height: 92vh;
    border-end-start-radius: 0; border-end-end-radius: 0;
    padding-bottom: env(safe-area-inset-bottom);
  }
  .modal.wide { width: 100%; }
  @keyframes sheet { from { transform: translateY(100%); } }
  .modal-foot { flex-wrap: wrap; }
  .modal-foot .btn { flex: 1 1 auto; }

  .toolbar .grow { min-width: 100%; }
  #toasts { inset-inline: 14px; bottom: calc(80px + env(safe-area-inset-bottom)); }
  .toast { width: 100%; }

  /* ---- one pane at a time ---- */
  .chat {
    height: calc(100dvh - 210px - env(safe-area-inset-bottom));
    min-height: 320px;
    grid-template-columns: 1fr;
  }
  .chat[data-open="list"] .chat-thread,
  .chat[data-open="thread"] .chat-list { display: none; }
  .chat-back { display: inline-flex; }
  .chat-msg { max-width: 86%; }
}

/* ---------------------------------------------------------------- tab bar
   Hidden by default and switched on in the phone block above, so it costs
   nothing on the layouts that do not use it. */
.tabbar {
  display: none;
  position: fixed; inset-inline: 0; bottom: 0; z-index: 40;
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  background: var(--glass);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border-top: 1px solid var(--glass-edge);
}
.tabbar a, .tabbar button {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 2px; border: 0; background: none; cursor: pointer;
  color: var(--label-2); font-size: 10.5px; font-weight: 550;
  text-decoration: none; position: relative;
  /* Apple's minimum comfortable target, which is also roughly the width of a
     thumb on the phones this will actually run on. */
  min-height: 44px;
}
.tabbar a span, .tabbar button span {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tabbar a.active { color: var(--accent-deep); }
.tabbar a:active, .tabbar button:active { opacity: .5; }
.tabbar .badge-count { top: 0; inset-inline-end: max(6px, 22%); }

/* The "More" sheet: every section, including the ones the tab bar could not
   carry, as a plain grouped list. */
.more-sheet { display: flex; flex-direction: column; gap: 2px; }
.more-sheet .nav-group { display: block; margin: 14px 0 4px; padding-inline: 4px; }
.more-sheet a {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 12px; border-radius: var(--r-sm);
  color: var(--label); font-size: 15.5px; text-decoration: none;
}
.more-sheet a:active { background: var(--fill); }
.more-sheet a.active { background: var(--tint-accent); color: var(--on-accent-tint); font-weight: 570; }

/* ---------------------------------------------------------------- pointer
   A coarse pointer gets larger controls whatever the screen size - a tablet
   in a pharmacy is used standing up, with one hand, sometimes gloved. */
@media (pointer: coarse) {
  .btn { padding: 11px 18px; }
  .btn-sm { padding: 8px 14px; }
  .btn-icon { width: 44px; height: 44px; }
  .input, .select, .textarea { padding: 12px 14px; font-size: 16px; }
  .nav a { padding: 12px; }
}

/* The one rule that has to come after everything the tab bar defines. */
@media (max-width: 720px) {
  .tabbar { display: flex; }
}

/* ================================================ appointments & results */
/* A patient has few appointments and needs all of one at once — when, where,
   and how to reach the place. A table row would put the address behind a
   horizontal scroll on the phone most of them are holding. */
.appt-list { display: flex; flex-direction: column; }
.appt-card {
  display: flex; gap: 16px; align-items: flex-start;
  padding: 16px 20px; border-bottom: 1px solid var(--separator);
}
.appt-card:last-child { border-bottom: 0; }
.appt-card.cancelled, .appt-card.no_show { opacity: .55; }
.appt-when {
  flex: 0 0 auto; min-width: 92px; text-align: center;
  padding: 10px 12px; border-radius: var(--r-sm);
  background: var(--tint-accent); color: var(--on-accent-tint);
}
.appt-date { font-size: 13px; font-weight: 600; line-height: 1.3; }
.appt-time { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; margin-top: 2px; }
.appt-body { flex: 1; min-width: 0; }
.appt-top { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 3px; }
.appt-actions { flex: 0 0 auto; }

.sect-head {
  font-size: 11.5px; font-weight: 650; color: var(--label-2);
  letter-spacing: .03em; text-transform: uppercase;
  padding-bottom: 5px; margin-bottom: 8px;
  border-bottom: 1px solid var(--separator);
}

.dx-list { display: flex; flex-direction: column; }
.dx-row {
  display: flex; gap: 13px; align-items: center; width: 100%;
  padding: 14px 20px; border: 0; border-bottom: 1px solid var(--separator);
  background: none; color: inherit; font: inherit; cursor: pointer; text-align: start;
}
.dx-row:last-child { border-bottom: 0; }
.dx-row:hover:not(:disabled) { background: var(--fill); }
.dx-row:disabled { cursor: default; opacity: .8; }
.dx-icon {
  flex: 0 0 38px; height: 38px; border-radius: var(--r-sm);
  display: grid; place-items: center;
  background: var(--tint-blue); color: var(--on-blue);
}
.dx-icon.imaging { background: var(--tint-purple); color: var(--on-purple); }

.dx-values tr.flagged td { background: var(--tint-orange); }
/* A value against its range. The bar is the point: a number and two other
   numbers ask the reader to compare three things; a mark inside or outside a
   band asks them to look. Drawn in outline so it survives a mono photocopy. */
.dx-range {
  position: relative; height: 10px; min-width: 110px; margin-bottom: 3px;
  border-radius: var(--r-pill); background: var(--fill-2);
}
.dx-band {
  position: absolute; left: 25%; width: 50%; top: 0; bottom: 0;
  border-radius: var(--r-pill); background: var(--tint-green);
  box-shadow: inset 0 0 0 1px var(--sys-green);
}
.dx-mark {
  position: absolute; top: -3px; width: 4px; height: 16px; margin-left: -2px;
  border-radius: 2px; background: var(--label);
}
.dx-mark.out { background: var(--sys-red); }

/* Reporting a result: one row per analyte, because a reference range belongs to
   the laboratory that ran the test and cannot be pasted in from elsewhere. */
.dx-input-row {
  display: grid; gap: 8px; margin-bottom: 8px; align-items: center;
  grid-template-columns: 1.6fr 1fr .8fr .8fr .8fr 1.1fr auto;
}
.dx-input-row .input, .dx-input-row .select { padding: 8px 10px; font-size: 13.5px; }

@media (max-width: 720px) {
  .appt-card { flex-wrap: wrap; }
  .appt-actions { width: 100%; }
  .dx-input-row { grid-template-columns: 1fr 1fr; }
  .dx-input-row [data-f="analyte"] { grid-column: 1 / -1; }
}

/* ================================================================ paid access
 * The lock replaces the application rather than covering it. A dialog you can
 * see the work behind invites people to hunt for a way round, and half a
 * working screen is worse than an honest stop.
 */
.paywall {
  min-height: 100vh; display: grid; place-items: center; padding: 24px;
  background: linear-gradient(160deg, var(--bg-tint-a), transparent 60%), var(--bg);
}
.paywall-card {
  width: min(460px, 100%); padding: 32px;
  background: var(--surface); border-radius: var(--r-xl);
  box-shadow: var(--sh-2); text-align: center;
}
.paywall-mark {
  width: 62px; height: 62px; margin: 0 auto 16px; border-radius: 18px;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(160deg, var(--sys-orange), #C77700);
}
.paywall-card h1 { font-size: 21px; font-weight: 680; letter-spacing: -.03em; margin-bottom: 6px; }
.paywall-card > p { margin: 0 0 18px; }
.paywall-meta {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 10px 14px; margin-bottom: 18px;
  background: var(--fill); border-radius: var(--r-sm); font-size: 13.5px;
}
/* Numbered because the way out is a sequence of things to do in the world —
   go, pay, come back — not a button to press. */
.paywall-steps {
  text-align: start; margin: 0 0 20px; padding-inline-start: 22px;
  color: var(--label-2); font-size: 13.5px; line-height: 1.7;
}
.paywall-foot { margin-top: 14px; }

/* Copied off a piece of paper by hand, so it is spaced like one. */
.token-input {
  font-family: Consolas, 'Courier New', monospace;
  font-size: 19px; font-weight: 600; letter-spacing: .12em; text-align: center;
}
.token-display {
  font-family: Consolas, 'Courier New', monospace;
  font-size: 27px; font-weight: 700; letter-spacing: .14em; text-align: center;
  padding: 18px 12px; border: 2px solid var(--accent); border-radius: var(--r);
  background: var(--tint-accent); color: var(--on-accent-tint);
  direction: ltr; unicode-bidi: isolate; overflow-wrap: anywhere;
}
/* The banner slots live above the outlet so they survive navigation, which
   means they also have to carry their own gutter - and none of it when there
   is nothing to say. */
[data-access-banner]:not(:empty),
[data-acting-banner]:not(:empty) { padding: 16px 26px 0; }

.access-banner { margin-bottom: 16px; }
.access-banner a { font-weight: 600; }

/* --------------------------------------------------- somebody else's record
   The switcher and the strip that goes with it.

   Whose record is on screen is the one thing that must never be in doubt, so
   the control changes colour the moment it stops being your own - a borrowed
   record looks different from across the room, not on close reading. */
.record-switch { max-width: 210px; gap: 6px; }
.record-switch-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550;
}
.record-switch.borrowed {
  background: var(--tint-orange); color: var(--on-orange);
  border-color: color-mix(in srgb, var(--on-orange) 26%, transparent);
}
.record-switch.borrowed .icn { color: var(--on-orange); }

.acting-banner { align-items: center; }
.acting-banner .btn { flex: none; }

.record-list { display: flex; flex-direction: column; gap: 2px; }
.record-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 11px 12px; border: 1px solid transparent; border-radius: var(--r);
  background: transparent; color: inherit; font: inherit; cursor: pointer;
  text-align: start;
}
.record-row:hover { background: var(--fill); }
.record-row.here { background: var(--tint-accent); border-color: var(--accent); }

/* On a phone the top bar has no room for a name beside every other control,
   so the switcher keeps only its icon and the strip below carries the name. */
@media (max-width: 640px) {
  .record-switch { max-width: none; padding-inline: 9px; }
  .record-switch-name { display: none; }
}

/* ------------------------------------------------- readings between visits
   The trend is the object on the screen; the table under it is the detail.
   A single reading says almost nothing, and the layout should say so. */
.kind-tabs { display: flex; gap: 4px; flex-wrap: wrap; }
.kind-tab {
  padding: 7px 13px; border-radius: var(--r-pill); font-size: 13px; font-weight: 550;
  color: var(--label-2); text-decoration: none; white-space: nowrap;
}
.kind-tab:hover { background: var(--fill); }
.kind-tab.on { background: var(--tint-accent); color: var(--on-accent-tint); }

.vital-chart-wrap { margin-bottom: 14px; }
.vital-chart { width: 100%; height: 170px; display: block; overflow: visible; }
.vital-chart .axis { stroke: var(--separator); stroke-width: 1; }
.vital-chart .ln {
  fill: none; stroke: var(--accent); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
/* Diastolic, drawn lighter: it is the same measurement, not a second one. */
.vital-chart .ln.second { stroke: var(--accent-2); stroke-dasharray: 4 3; opacity: .8; }
.vital-chart .pt { fill: var(--accent); stroke: var(--bg); stroke-width: 1.5; }
.vital-chart .pt.second { fill: var(--accent-2); }
/* A reading that needs attention keeps its colour on the line as well as in
   the table — the eye finds the outlier before it reads any label. */
.vital-chart .pt.lvl-high { fill: var(--sys-red); }
.vital-chart .pt.lvl-raised,
.vital-chart .pt.lvl-low { fill: var(--sys-orange); }
.vital-scale {
  display: flex; justify-content: space-between;
  font-size: 12px; color: var(--label-2); padding: 0 24px;
}

.vital-latest {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 16px; border-radius: var(--r); background: var(--fill);
}
.vital-latest.high { background: var(--tint-red); }
.vital-latest.raised, .vital-latest.low { background: var(--tint-orange); }
.vital-big { font-size: 30px; font-weight: 640; letter-spacing: -.02em; line-height: 1.1; }
.vital-unit { font-size: 14px; font-weight: 500; color: var(--label-2); }

/* The clinical view: one line per kind, newest value, where it came from. */
.vital-row {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: 1.2fr .8fr auto auto 1fr auto;
  padding: 10px 0; border-bottom: 1px solid var(--separator);
}
.vital-row:last-child { border-bottom: 0; }
.vital-row-name { font-weight: 550; }
.vital-row-value { font-weight: 640; font-size: 16px; }

/* What a prescriber is told before deciding on a repeat. A warning, never a
   block: whether to repeat an antibiotic is a clinical judgement. */
.refill-flag {
  display: inline-block; font-size: 12px; font-weight: 550;
  padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--fill); color: var(--label-2); margin-bottom: 3px;
}
.refill-flag.warn { background: var(--tint-orange); color: var(--on-orange); }

@media (max-width: 760px) {
  .vital-row { grid-template-columns: 1fr auto; row-gap: 4px; }
  .vital-row-name { grid-column: 1 / -1; }
  .vital-big { font-size: 26px; }
}

/* ------------------------------------------------------- the report builder
   Composing a question, in chips and rows rather than in SQL. */
.qb-section { padding: 12px 0; border-top: 1px solid var(--separator); }
.qb-section:first-of-type { border-top: 0; padding-top: 0; }
.qb-head {
  display: flex; align-items: center; gap: 10px;
  font-size: 12px; font-weight: 620; text-transform: uppercase;
  letter-spacing: .04em; color: var(--label-2); margin-bottom: 9px;
}
.qb-head .btn { margin-inline-start: auto; text-transform: none; letter-spacing: 0; }

.chip-picker { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  padding: 6px 12px; border-radius: var(--r-pill);
  border: 1px solid var(--separator); background: var(--bg-2);
  font: inherit; font-size: 12.5px; font-weight: 520; color: var(--label);
  cursor: pointer;
}
.chip:hover { background: var(--fill); }
.chip.on {
  background: var(--tint-accent); color: var(--on-accent-tint);
  border-color: var(--accent);
}

.qb-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 7px 10px; border-radius: var(--r-sm);
  background: var(--fill); margin-bottom: 6px;
}
.qb-label { font-weight: 600; }
.qb-op { color: var(--label-2); font-size: 13px; }
.qb-val { font-weight: 600; }
.qb-row .btn { margin-inline-start: auto; }

.qb-actions {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding-top: 14px; border-top: 1px solid var(--separator);
}

/* The query that produced the rows. Shown because a number somebody will order
   stock against ought to be checkable. */
.sql-box { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--separator); }
.sql-box pre {
  margin: 0; padding: 12px 14px; border-radius: var(--r-sm);
  background: var(--fill); overflow-x: auto;
  font-family: Consolas, 'Courier New', monospace; font-size: 12px; line-height: 1.55;
  white-space: pre; color: var(--label);
}

.saved-list { list-style: none; margin: 0; padding: 0; }
.saved-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 4px; border-bottom: 1px solid var(--separator);
}
.saved-item:last-child { border-bottom: 0; }
.saved-item.pinned .saved-name { color: var(--on-accent-tint); }
.saved-name { font-weight: 600; overflow-wrap: anywhere; }

/* --------------------------------------------------------- horizontal bars
   One chart shape, used for expiry buckets and value by category. Hand-drawn
   for the same reason as the vitals trend: a chart library would outweigh the
   entire application on a slow connection. */
.hbars { display: flex; flex-direction: column; gap: 9px; }
.hbar-row { display: grid; grid-template-columns: 8.5rem 1fr auto; align-items: center; gap: 10px; }
.hbar-label { font-size: 13px; color: var(--label-2); overflow-wrap: anywhere; }
.hbar-track { height: 9px; border-radius: 999px; background: var(--fill); overflow: hidden; }
.hbar-fill {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
  min-width: 2px;
}
.hbar-fill.red { background: var(--sys-red); }
.hbar-fill.amber { background: var(--sys-orange); }
.hbar-note { font-size: 12px; color: var(--label-2); white-space: nowrap; }

@media (max-width: 720px) {
  .hbar-row { grid-template-columns: 1fr auto; }
  .hbar-track { grid-column: 1 / -1; order: 3; }
}

/* ----------------------------------------------------------- visit summary
   Read at home, alone, often aloud. Four questions with the answers under
   them, and the one part that asks the patient to DO something is the part
   that stands out — because it is the part that gets forgotten. */
.visit-block { padding: 12px 0; border-bottom: 1px solid var(--separator); }
.visit-block:last-of-type { border-bottom: 0; }
.visit-label {
  font-size: 12px; font-weight: 620; text-transform: uppercase;
  letter-spacing: .04em; color: var(--label-2); margin-bottom: 5px;
}
.visit-text { font-size: 15px; line-height: 1.6; white-space: pre-wrap; }
.visit-block.plan {
  background: var(--tint-accent); border-radius: var(--r);
  padding: 14px 16px; border-bottom: 0; margin-top: 6px;
}
.visit-block.plan .visit-label { color: var(--on-accent-tint); }
.visit-block.plan .visit-text { font-size: 16px; font-weight: 520; }

.visit-followup {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 14px;
  padding: 12px 14px; border-radius: var(--r); background: var(--fill);
}

/* ------------------------------------------------------------- what is due
   Overdue reads differently from upcoming at a glance: somebody scanning this
   on a phone should not have to read a date to know which is which. */
.due-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--separator);
}
.due-row:last-child { border-bottom: 0; }
.due-mark {
  width: 26px; height: 26px; border-radius: var(--r-pill); flex: none;
  display: grid; place-items: center; font-size: 13px;
  background: var(--fill); color: var(--label-2);
}
.due-row.overdue .due-mark { background: var(--tint-red); color: var(--on-red); }
.due-row.done .due-mark { background: var(--tint-green); color: var(--on-green); }
.due-row.done { opacity: .62; }
.due-row.done .due-label { text-decoration: line-through; }
.due-label { font-weight: 600; }

/* -------------------------------------------------------- health summary */
.hs-head {
  display: flex; gap: 24px; flex-wrap: wrap;
  align-items: flex-start; justify-content: space-between;
}
.hs-list { list-style: none; margin: 0; padding: 0; }
.hs-list li { padding: 7px 0; border-bottom: 1px solid var(--separator); }
.hs-list li:last-child { border-bottom: 0; }
/* An allergy panel is the one block on this page a clinician must not miss. */
.hs-danger { background: var(--tint-red); border-radius: 0 0 var(--r) var(--r); }
.hs-danger .hs-list li { border-bottom-color: color-mix(in srgb, var(--on-red) 18%, transparent); }

/* ------------------------------------------------------------ the wordmark
   The supplied logo is a wordmark on its own cream ground, not a symbol on a
   coloured tile — so it gets no gradient behind it and no drop shadow of ours.
   It brings its own. */
.brand-mark.is-logo {
  background: none;
  box-shadow: none;
  border-radius: 8px;
  padding: 0;
}

/* On the sign-in page there is room to show it at a size where the lettering
   is actually readable, which is the whole point of a wordmark.

   The artwork is a torn paper cutout on a cream ground, and the hero panel it
   sits on is a saturated teal. Left flat, the cream reads as a washed-out
   patch; given a shadow it reads as what it is — a piece of paper laid on the
   panel — which is what the artwork was drawn to be. */
.auth-brand { padding: 0 0 22px; }
.auth-brand img {
  margin-inline-start: -14px;
  filter: drop-shadow(0 6px 16px rgba(0, 0, 0, .28));
}
/* The panel behind this is dark, so the muted grey the tagline uses everywhere
   else is all but invisible here. */
.auth-brand .brand-sub {
  font-size: 13px; margin-top: 2px; margin-inline-start: 2px;
  color: rgba(255, 255, 255, .82); font-weight: 600; letter-spacing: .02em;
}

/* The sidebar carries the wordmark itself rather than a tile plus the name in
   text: the artwork already says the name, twice over, in two scripts. */
.brand-wordmark {
  flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 10px 12px 14px;
}
.brand-wordmark .brand-mark.is-logo { width: auto; height: auto; margin-inline-start: -8px; }
.brand-wordmark .brand-sub { display: flex; align-items: center; gap: 5px; }

/* The sign-in page's own top row: the mark on one side, the language on the
   other. The mark only appears once the hero panel beside it has gone, so the
   logo is never shown twice on one screen. */
.auth-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 18px;
}
.auth-brand-sm { display: none; }
@media (max-width: 900px) {
  .auth-brand-sm { display: block; margin-inline-start: -6px; }
}

/* ------------------------------------------------------------- the purge
   Laid out to slow somebody down. The row states what will go and how much of
   it exists before there is any button, and the button never deletes — it
   opens a count. */
.purge-row {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 13px 0; border-bottom: 1px solid var(--separator);
}
.purge-row:last-child { border-bottom: 0; }
.purge-row .btn { flex: none; margin-top: 2px; }
.purge-name { font-weight: 600; margin-bottom: 2px; }
.purge-meta {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-top: 6px; font-size: 12px; color: var(--label-2);
}
.purge-chip {
  padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--fill); font-weight: 550;
}
.purge-chip.warn { background: var(--tint-orange); color: var(--on-orange); }

/* The audit and erasure groups are the two whose consequences do not undo, so
   they are marked as such before the reading starts. */
.purge-row.audit, .purge-row.erasure { border-inline-start: 3px solid var(--sys-red); padding-inline-start: 12px; }

/* The number is the whole point of the confirmation step, so it is the largest
   thing in the dialog. */
.purge-total { text-align: center; padding: 10px 0 4px; }
.purge-count {
  font-size: 30px; font-weight: 680; letter-spacing: -.02em;
  color: var(--sys-red); line-height: 1.2; margin: 4px 0;
}

.never-list { list-style: none; margin: 0; padding: 0; }
.never-list li { padding: 9px 0; border-bottom: 1px solid var(--separator); }
.never-list li:last-child { border-bottom: 0; }
.never-list code {
  font-family: Consolas, 'Courier New', monospace; font-size: 13px;
  font-weight: 600; color: var(--label);
}

/* ==========================================================================
   STOCK CONTROL
   Locations and the cold chain, stocktakes, the equipment register, scanning.
   ========================================================================== */

/* ------------------------------------------------------------- the scan box
   Built on .search so it sits in a toolbar like every other input, but the
   magnifier is replaced with the scanner glyph: a person reaches for this by
   its icon, and a magnifying glass says "type here to look something up",
   which is the slower thing next to it. */
.scanbox { flex: 0 1 240px; min-width: 170px; }
.scanbox::before { display: none; }
.scanbox .icn {
  position: absolute; inset-inline-start: 12px; top: 50%;
  margin-top: -8px; opacity: .5; pointer-events: none;
}
.scanbox .input {
  padding-inline-start: 36px;
  font-family: Consolas, 'Courier New', monospace; font-size: 13px;
  letter-spacing: .01em;
}
.scanbox .input:focus { border-color: var(--accent); }

/* What a scan turned out to say, echoed back before anything is decided. */
.scan-echo {
  font-family: Consolas, 'Courier New', monospace; font-size: 12.5px;
  padding: 10px 12px; border-radius: var(--r-sm);
  background: var(--fill); color: var(--label-2);
  word-break: break-all;
}
.scan-fields { display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 12px; }
.scan-field { display: flex; flex-direction: column; gap: 1px; font-size: 13px; }

/* ----------------------------------------------------------- the count sheet
   A narrow box per row, because the number typed into it is a quantity and a
   full-width field invites a sentence. `saved` flashes once rather than
   staying green: a permanent tick on two hundred rows is not information. */
.count-input {
  max-width: 108px; text-align: end;
  font-variant-numeric: tabular-nums;
}
.count-input.saved { animation: count-saved .9s var(--ease); }
.count-input.bad { border-color: var(--sys-red); }
@keyframes count-saved {
  0%   { background: var(--tint-accent); border-color: var(--accent); }
  100% { background: var(--surface); border-color: var(--fill-2); }
}

/* A row a scan just found. Flashed rather than filtered to, so the shelf
   around it stays on screen. */
tr.flash > td { animation: row-flash 1.6s var(--ease); }
@keyframes row-flash {
  0%, 30% { background: var(--tint-accent); }
  100%    { background: transparent; }
}

/* -------------------------------------------------------- temperature chart
   A column chart of fridge temperatures is nearly useless — every bar is the
   same height. What matters is the relationship to the allowed band, so the
   band is a shaded stripe and the readings are dots against it. A dot outside
   the stripe is the whole message, which is why it is the only red thing. */
.temp-chart {
  position: relative; height: 110px; margin: 4px 0 16px;
  border-radius: var(--r-sm); overflow: hidden;
  background: var(--surface-2);
}
.temp-plot, .temp-dots { position: absolute; inset: 0; width: 100%; height: 100%; }
.temp-band { fill: var(--tint-accent); }
.temp-line {
  fill: none; stroke: var(--label-3); stroke-width: .6;
  vector-effect: non-scaling-stroke;
}
.temp-dots circle { stroke: var(--surface); stroke-width: .5; }
.temp-ok  { fill: var(--accent); }
.temp-bad { fill: var(--sys-red); }
.temp-axis {
  position: absolute; inset-block: 4px; inset-inline-end: 8px;
  display: flex; flex-direction: column; justify-content: space-between;
  font-size: 10.5px; color: var(--label-3); font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* ------------------------------------------------------------- purge/asset
   The location and asset lists carry more columns than most; on a phone the
   table restacks and these two get the same treatment as everywhere else. */
@media (max-width: 720px) {
  .scanbox { flex: 1 1 100%; }
  .count-input { max-width: 100%; }
}
