/* ═══════════════════════════════════════════════════════════════════════════
   Sanad UI · the component library — BINDING

   design/app/README.md § "معايير الواجهة المعتمدة" is the specification; this
   file is its implementation, and it is the only place these shapes are
   defined. A new screen is ASSEMBLED from these classes. A new pattern is
   added here first and then used — never invented inside one screen.

   With 396 screens the alternative is not untidiness, it is divergence: every
   developer's own button, and no way to change a rule once.

   ── Direction ─────────────────────────────────────────────────────────────
   Every rule uses LOGICAL properties — inline-start/inline-end, margin-inline,
   border-inline — never left/right. The application runs in Arabic RTL and
   English LTR from the same stylesheet: setting dir on <html> flips the entire
   interface, and no rule here has to know which way it is facing.

   The two exceptions are deliberate and marked: numeric cells force LTR
   because a negative sign or a currency symbol flips away from its digits in
   an RTL run, and the Latin-name column does the same for the same reason.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────
   1 · BUTTONS
   Every clickable thing is a <button> or an <a>. Never a div with a click
   handler: the review found those throughout and they take no focus, ignore
   Enter and Space, and are invisible to a screen reader — which means the
   system cannot be operated by keyboard at all, on a keyboard-first product.
   ───────────────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  block-size: var(--h-btn);
  padding-inline: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  background: var(--panel);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-sm);
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}

.btn:hover:not(:disabled) { border-color: var(--brand); color: var(--brand); }

/* Never removed. This outline is how somebody driving by keyboard knows where
   they are, and on this product that is most operators most of the time. */
.btn:focus-visible,
.field__input:focus-visible,
.grid__cell--edit:focus-visible,
.tab:focus-visible,
.rail-btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

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

.btn--primary {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--accent-fg);
  font-weight: 600;
}
.btn--primary:hover:not(:disabled) {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--accent-fg);
}

.btn--danger { color: var(--bad); border-color: color-mix(in oklab, var(--bad) 45%, transparent); }
.btn--danger:hover:not(:disabled) { background: var(--bad); border-color: var(--bad); color: var(--on-dark); }

.btn--ghost { background: transparent; border-color: transparent; color: var(--ink-muted); }
.btn--ghost:hover:not(:disabled) { background: var(--hover); color: var(--brand); }

/* The shortcut hint inside a toolbar button. Dimmed, never removed: it is how
   an operator learns the keyboard without opening a help screen. */
.btn__key {
  font-family: var(--font-num);
  font-size: var(--fs-key);
  opacity: 0.6;
}

/* A blocked save says how many errors, in the colour of the problem. */
.btn--blocked {
  background: var(--bad);
  border-color: var(--bad);
  color: var(--on-dark);
}

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-5);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}

.toolbar__sep {
  inline-size: 1px;
  block-size: 18px;
  background: var(--line);
  margin-inline: var(--sp-2);
}

.toolbar__spacer { margin-inline-start: auto; }

/* The document's own name, at the top of its own toolbar (README §Screens 1.2: 14px/700). */
.toolbar__title {
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--text);
}

/* The name in the OTHER language. Small, quiet, and never competing with the title -- an
   operator reading Arabic should not have their eye pulled to the English beside it. */
.toolbar__subtitle {
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

/* The legacy screen number. Operators quote it down the phone, so it is monospaced and
   selectable rather than decorative. */
.toolbar__id {
  font-size: var(--fs-xs);
  color: var(--faint);
  padding-inline: var(--sp-2);
  border: 1px solid var(--line2);
  border-radius: var(--r-badge);
}

/* Document navigation -- README §Screens 1.2, «‹ 1184/1192 ›». It sits at the far end of the
   toolbar, and it is quiet on purpose: an operator walking a run of invoices uses it constantly,
   and a control used constantly should not shout. The two steps are real <button>s so the keyboard
   reaches them (§6: every clickable is focusable), and the count between them is monospaced
   because it changes under the eye -- proportional digits make it jump. */
.docnav {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding-inline: var(--sp-2);
  border: 1px solid var(--line2);
  border-radius: var(--r-badge);
}

.docnav__step {
  min-inline-size: 20px;
  block-size: 22px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-muted);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--r-badge);
}

.docnav__step:hover:not(:disabled) {
  background: var(--panel2);
  color: var(--text);
}

/* Disabled at the ends rather than hidden: the arrow staying put is what tells the operator the
   list has an end. A control that vanishes reads as a control that broke. */
.docnav__step:disabled {
  opacity: 0.35;
  cursor: default;
}

.docnav__count {
  font-size: var(--fs-xs);
  color: var(--faint);
  padding-inline: var(--sp-1);
}

/* The glyph on an action button. Sized under the label on purpose: it is a landmark for the eye
   scanning a row of buttons, not the thing being read. */
.btn__glyph {
  font-size: 13px;
  line-height: 1;
}

/* A toolbar of secondary actions -- README §Screens 1.3. Quieter than the main bar: no panel,
   no border of its own, and its buttons are 27px rather than 30. */
.toolbar--secondary {
  padding-block: var(--sp-2);
  background: transparent;
  border: 0;
  border-radius: 0;
}

.toolbar--secondary .btn {
  block-size: 27px;
  padding-inline: var(--sp-4);
  color: var(--ink-muted);
}

/* ─────────────────────────────────────────────────────────────────────────
   2 · FIELDS
   The rule the review put first: REQUIRED IS NOT AN ERROR. The asterisk on
   the label means required. The red border means wrong, and it appears only
   after the field is left or a save is attempted — never on a form the
   operator has just opened, which is how a new document used to come up red.
   ───────────────────────────────────────────────────────────────────────── */

.field {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-block-size: var(--h-field);
}

.field__req {
  inline-size: 8px;
  flex: 0 0 auto;
  color: var(--bad);
  font-size: var(--fs-sm);
}

.field__label {
  flex: 0 0 auto;
  min-inline-size: 84px;
  max-inline-size: 132px;
  color: var(--ink-muted);
  font-size: var(--fs-xs);
  text-align: start;
}

.field__input {
  flex: 1;
  min-inline-size: 0;
  block-size: var(--h-field);
  padding-inline: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  background: var(--input);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-sm);
}

.field__input::placeholder { color: var(--faint); }

/* A code field: fixed width, tabular, centred — so a column of them lines up
   whichever language the interface is in. */
.field__input--code {
  flex: 0 0 auto;
  inline-size: 72px;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.field__input--code-wide { inline-size: 112px; }

/* Read-only: out of the tab order, still selectable and copyable. An operator
   tabbing through a document should not stop on a number they cannot change. */
.field__input[readonly] {
  background: var(--panel2);
  border-color: transparent;
  color: var(--ink-muted);
}

.field__input--invalid,
.field__input[aria-invalid='true'] { border-color: var(--bad); }

.field__input:disabled {
  background: var(--panel2);
  color: var(--ink-muted);
  cursor: not-allowed;
}

/* The message line, with its space RESERVED. Without min-block-size the layout
   jumps every time an error appears or clears, and a form that moves under the
   cursor is a form that gets mis-typed. */
.field__msg {
  min-block-size: 15px;
  padding-inline-start: calc(84px + var(--sp-3) + 8px + var(--sp-3));
  color: var(--bad);

  /* 11px, not the 10.5 the component spec suggests. The review is the later
     document and its floor is concrete: Arabic dots and hamzas disappear below
     it, and this line carries the sentence that tells an operator what is wrong
     with their document. Where the two specs disagree the readable one wins. */
  font-size: var(--fs-xs);
  line-height: 1.4;
}

.field__hint { color: var(--faint); }

/* Named groups inside a document header. Twelve fields in one undifferentiated
   grid read as a wall; three named groups read as three questions. */
.fieldgroup { display: flex; flex-direction: column; gap: var(--sp-2); }

.fieldgroup__name {
  color: var(--faint);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.03em;
  padding-block-end: var(--sp-1);
  border-block-end: 1px solid var(--line2);
}

/* ─────────────────────────────────────────────────────────────────────────
   3 · TABLES AND GRIDS
   ───────────────────────────────────────────────────────────────────────── */

.tablewrap {
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--panel);
}

.tbl { inline-size: 100%; border-collapse: collapse; font-size: var(--fs-sm); }

.tbl thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  padding: var(--sp-2) var(--sp-4);
  background: var(--head);
  color: var(--ink-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-align: start;
  white-space: nowrap;
  border-block-end: 1px solid var(--line);
}

.tbl tbody td {
  block-size: var(--h-row);
  padding: 0 var(--sp-4);
  border-block-end: 1px solid var(--line2);
}

.tbl tbody tr:hover { background: var(--hover); }

.tbl tbody tr[aria-selected='true'] {
  background: var(--sel);
  box-shadow: inset 2px 0 0 var(--brand);
}

/* NUMBERS. The one place direction is forced, and it has to be: in an RTL run
   a minus sign or a currency symbol detaches from its digits and renders on
   the wrong end — "12,900-" instead of "-12,900". Every amount, date, code
   and quantity in the system carries this class. */
.num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  direction: ltr;
  text-align: end;
  white-space: nowrap;
}

.num--neg { color: var(--bad); }

/* Latin text in an Arabic interface, for the same reason. */
.lat { direction: ltr; text-align: start; }

/* Editable versus not, visible BEFORE the click. The review found operators
   discovering which cells could be typed in by trying them. */
.grid__cell--edit { background: var(--panel); cursor: text; }
.grid__cell--read { background: var(--panel2); color: var(--ink-muted); }

/* Identity columns stay put while the rest scrolls. With fourteen columns the
   item number leaves the screen exactly when the operator reaches the tax and
   total — so they are editing a number without knowing whose it is. */
.grid__cell--sticky {
  position: sticky;
  z-index: 2;
  background: inherit;
}
.grid__cell--sticky-3 { box-shadow: -1px 0 0 var(--line); }

.tbl--rows tbody tr { background: var(--panel); }

/* A row with a problem: a bar on its number, a tint across it, and the
   offending cell coloured. Three signals, because colour alone excludes
   anybody who cannot distinguish it. */
.row--bad { background: var(--bad-soft); }
.row--bad .grid__cell--n { box-shadow: inset 3px 0 0 var(--bad); color: var(--bad); }

.row--ok .grid__cell--n { box-shadow: inset 3px 0 0 var(--ok); }

.tbl__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-2) var(--sp-4);
  background: var(--panel2);
  border-block-start: 1px solid var(--line);
  color: var(--ink-muted);
  font-size: var(--fs-xs);
}

/* ─────────────────────────────────────────────────────────────────────────
   4 · BADGES · four levels, one shape each
   ───────────────────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 2px var(--sp-3);
  border-radius: var(--r-badge);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
}

.badge--ok     { background: var(--ok-soft);     color: var(--ok); }
.badge--warn   { background: var(--warn-soft);   color: var(--warn); }
.badge--bad    { background: var(--bad-soft);    color: var(--bad); }
.badge--info   { background: var(--accent-soft); color: var(--brand); }
.badge--muted  { background: var(--panel2);      color: var(--ink-muted); }

/* ─────────────────────────────────────────────────────────────────────────
   5 · VALIDATION · four levels, and each has exactly one form
   The rule that keeps 396 screens from becoming a fairground: a level's shape
   is never borrowed by another level, and only red blocks a save.
   ───────────────────────────────────────────────────────────────────────── */

.alert {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid;
  border-inline-start-width: 3px;
  border-radius: var(--r-card);
  font-size: var(--fs-sm);
  line-height: 1.8;
}

.alert__head { display: flex; align-items: center; gap: var(--sp-3); font-weight: 700; }
.alert__spacer { margin-inline-start: auto; }

.alert--bad {
  background: var(--bad-soft);
  border-color: color-mix(in oklab, var(--bad) 45%, transparent);
  border-inline-start-color: var(--bad);
}
.alert--bad .alert__head { color: var(--bad); }

.alert--warn {
  background: var(--warn-soft);
  border-color: color-mix(in oklab, var(--warn) 45%, transparent);
  border-inline-start-color: var(--warn);
}
.alert--warn .alert__head { color: var(--warn); }

.alert--info {
  background: var(--accent-soft);
  border-color: color-mix(in oklab, var(--brand) 40%, transparent);
  border-inline-start-color: var(--brand);
}
.alert--info .alert__head { color: var(--brand); }

/* Each item jumps focus to the thing it is about. An error the operator cannot
   reach is an error they cannot fix. */
.alert__item {
  display: block;
  inline-size: 100%;
  padding: 2px 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: transparent;
}
.alert__item:hover { text-decoration-color: currentColor; }

/* ─────────────────────────────────────────────────────────────────────────
   6 · SCREEN STATES · loading, empty, error, no permission
   Every screen implements all four. An empty state without an action is a
   dead end, so each carries exactly one.
   ───────────────────────────────────────────────────────────────────────── */

.state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  min-block-size: 220px;
  padding: var(--sp-7);
  color: var(--ink-muted);
  text-align: center;
}

.state__glyph { font-size: 26px; opacity: 0.5; }
.state__title { color: var(--text); font-size: var(--fs-base); font-weight: 600; }
.state__body  { max-inline-size: 46ch; font-size: var(--fs-sm); line-height: 1.9; }

.skeleton {
  background: linear-gradient(90deg, var(--line2), var(--panel2), var(--line2));
  background-size: 200% 100%;
  border-radius: var(--r-field);
  animation: sk 1.2s linear infinite;
}

@keyframes sk { to { background-position: -200% 0; } }

@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
  * { transition-duration: 1ms !important; }
}

/* ─────────────────────────────────────────────────────────────────────────
   7 · DIALOGS
   ───────────────────────────────────────────────────────────────────────── */

.scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-scrim);
  background: rgb(11 17 26 / 44%);

  /* It is a <button> -- see QuickSearch -- so a button's own chrome has to go:
     a border, a system background and a pointer cursor over the whole viewport. */
  border: 0;
  padding: 0;
  cursor: default;
}

.dialog {
  position: fixed;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  translate: 50% -50%;
  z-index: var(--z-dialog);
  display: flex;
  flex-direction: column;
  max-block-size: 88vh;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-dialog);
  box-shadow: var(--shadow);
}

/* RTL translates the other way; one rule per direction and no duplicated
   dialog styles. */
:dir(ltr) .dialog { translate: -50% -50%; }

.dialog__head {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6);
  border-block-end: 1px solid var(--line);
}

.dialog__title { font-size: var(--fs-base); font-weight: 700; }
.dialog__ctx   { color: var(--ink-muted); font-size: var(--fs-xs); }

/* The row the arrows are on. Not :hover — the mouse and the keyboard would then disagree about
   what Enter will open, and the keyboard is the one being driven. */
.dialog__body .alert__item[aria-selected='true'] {
  background: var(--sel);
  box-shadow: inset 2px 0 0 var(--brand);
}

.dialog__body .alert__item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-field);
}

.dialog__body .alert__item .num {
  min-inline-size: 3.5rem;
  color: var(--brand);
}
.dialog__body  { overflow: auto; padding: var(--sp-6); }

.dialog__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-6);
  background: var(--panel2);
  border-block-start: 1px solid var(--line);
}

/* ── tabs, with the error count the review asked for ─────────────────────
   A form with five tabs hides its own errors: the save is blocked by a field
   on a tab nobody is looking at, and the button gives no reason. */
.tabs { display: flex; gap: var(--sp-1); border-block-end: 1px solid var(--line); }

.tab {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  border: 0;
  border-block-end: 2px solid transparent;
  background: none;
  color: var(--ink-muted);
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
}

.tab--active { color: var(--text); border-block-end-color: var(--brand); font-weight: 600; }

.tab__errors {
  min-inline-size: 16px;
  padding-inline: 5px;
  border-radius: 999px;
  background: var(--bad);
  color: var(--on-dark);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-align: center;
}

/* ─────────────────────────────────────────────────────────────────────────
   8 · TOAST · success only. A validation failure is never a popup.
   ───────────────────────────────────────────────────────────────────────── */

.toast {
  position: fixed;
  inset-block-end: var(--sp-7);
  inset-inline-start: var(--sp-7);
  z-index: var(--z-toast);
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-6);
  background: var(--panel);
  border: 1px solid var(--line);
  border-inline-end: 3px solid var(--ok);
  border-radius: var(--r-card);
  box-shadow: var(--shadow);
  font-size: var(--fs-sm);
}

.toast--bad { border-inline-end-color: var(--bad); }

/* ─────────────────────────────────────────────────────────────────────────
   9 · TOTALS · four boxes, and the net is the largest number on the screen
   The review found ten boxes of equal weight forcing a horizontal scroll at
   1366px — so the one figure everybody opens the screen for was the one being
   cut off.
   ───────────────────────────────────────────────────────────────────────── */

.totals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-4);
}

.total {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--sp-4) var(--sp-5);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}

.total__label { color: var(--ink-muted); font-size: var(--fs-xs); }
.total__value { font-family: var(--font-num); font-variant-numeric: tabular-nums;
                direction: ltr; text-align: start; font-size: var(--fs-base); font-weight: 600; }

/* خصم اضافي types into the totals row rather than beside it, because it IS a total —
   putting an editable box in the strip keeps the number the operator changes next to the
   numbers it changes. Sized to the value it holds, not to a form field's habits. */
.total-edit { display: inline-flex; align-items: center; gap: var(--sp-2); }
.total-edit__label { color: var(--ink-muted); font-size: var(--fs-xs); }
.total-edit__input {
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
  direction: ltr; text-align: start; font-size: var(--fs-base); font-weight: 600;
  inline-size: 8ch; padding: 2px 4px; color: var(--text);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-field);
}
.total-edit__input:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

.total--grand { border-color: color-mix(in oklab, var(--brand) 40%, transparent); }
.total--grand .total__value { color: var(--brand); font-size: var(--fs-xl); font-weight: 700; }

/* ─────────────────────────────────────────────────────────────────────────
   10 · UTILITIES — few on purpose. A utility that encodes a decision belongs
   in a component class, not here.
   ───────────────────────────────────────────────────────────────────────── */

.row    { display: flex; align-items: center; gap: var(--sp-4); }
.col    { display: flex; flex-direction: column; gap: var(--sp-4); }
.spacer { margin-inline-start: auto; }
.muted  { color: var(--ink-muted); }
.sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────────────────
   THE MODULE PANEL — README §Layout Shell

   640px, from the rail's side, over the scrim. It slides from inline-end because that is where
   the rail is in Arabic — and inline-end follows the direction, so in English it comes from the
   left without a second rule.
   ───────────────────────────────────────────────────────────────────────── */

/* The panel is anchored TO the rail, so the scrim must not cover it. With inset:0 the rail goes
   dead the moment the panel opens: no switching module, and no closing by clicking the entry you
   are already on -- which is the first thing anybody tries. Found by the acceptance suite, whose
   click timed out against the scrim rather than reaching the rail. */
.scrim--beside-rail { inset-inline-start: var(--w-rail); }

.megamenu {
  position: fixed;
  inset-block: var(--h-title) var(--h-status);
  inset-inline-start: var(--w-rail);
  z-index: var(--z-dialog);
  display: flex;
  flex-direction: column;
  inline-size: min(640px, calc(100vw - var(--w-rail)));
  background: var(--panel);
  border-inline-end: 1px solid var(--line);
  box-shadow: var(--shadow);
}

.megamenu__head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-block-end: 1px solid var(--line);
  background: var(--panel2);
}

.megamenu__glyph { font-size: var(--fs-lg); line-height: 1; }
.megamenu__title { font-size: var(--fs-lg); font-weight: 700; color: var(--text); }

.megamenu__body {
  flex: 1;
  min-block-size: 0;
  overflow: auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
  padding: var(--sp-5);
}

/* One column per sub-list. Below 900px the panel is most of the window and three columns of
   Arabic at this size wrap to one word each. */
@media (max-width: 900px) {
  .megamenu__body { grid-template-columns: 1fr 1fr; }
}

.megamenu__heading {
  margin: 0 0 var(--sp-2);
  /* The handoff says 10.5px. The review's 11px floor for Arabic wins -- below it the dots on
     ت ث ب stop resolving -- and the same decision was taken for every other label. */
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--faint);
}

.megamenu__item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 7px 9px;
  border-radius: var(--r-field);
  color: var(--text);
  font-size: var(--fs-sm);
  text-decoration: none;
}

.megamenu__item .num { min-inline-size: 3.2rem; color: var(--brand); }
.megamenu__item:hover { background: var(--hover); }

/* The row the arrows are on. Not :hover -- the mouse and the keyboard would then disagree about
   what Enter opens, and the keyboard is the one being driven. */
.megamenu__item[aria-current] {
  background: var(--sel);
  box-shadow: inset 2px 0 0 var(--brand);
}

.megamenu__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-5);
  border-block-start: 1px solid var(--line);
  background: var(--panel2);
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

/* ─────────────────────────────────────────────────────────────────────────
   THE WORKSPACE — README §Layout Shell

   A hidden pane is DISPLAY:NONE, not visibility or opacity. The screens behind the active tab
   must not take a click, must not take focus, and must not be read out — a keyboard-driven
   product where Tab walks through three invoices you cannot see would be unusable.
   ───────────────────────────────────────────────────────────────────────── */

.workspace__pane { display: contents; }
.workspace__pane--hidden { display: none; }

.tab {
  display: flex;
  align-items: center;
  block-size: 30px;
  border-radius: var(--r-field) var(--r-field) 0 0;
  color: var(--ink-muted);
}

.tab--active {
  background: var(--bg);
  border: 1px solid var(--line);
  border-block-end-color: transparent;
  color: var(--text);
}

.tab__pick {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  block-size: 100%;
  padding-inline: var(--sp-4);
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
}

.tab__name { white-space: nowrap; }
.tab__id { font-size: var(--fs-xs); color: var(--faint); }

/* Saved is quiet, unsaved is warm. The dot is the one thing an operator reads before reaching
   for the ✕, so it is never absent -- a missing dot would read as "no state" rather than "saved". */
.tab__dot {
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: var(--line);
}

.tab__dot--dirty { background: var(--warn); }

.tab__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 20px;
  block-size: 20px;
  margin-inline-end: var(--sp-2);
  border: 0;
  border-radius: var(--r-badge);
  background: none;
  color: var(--faint);
  font: inherit;
  cursor: pointer;
}

.tab__close:hover { background: var(--bad-soft); color: var(--bad); }

/* ─────────────────────────────────────────────────────────────────────────
   THE FILTER ROW AND THE PAGER

   One box under each heading, and the pager beside the count. Both narrow or
   move the QUERY: filtering the fetched page would be a lie on any entity with
   more rows than a page, and most master-data screens have thousands.
   ───────────────────────────────────────────────────────────────────────── */

.grid__filters {
  position: sticky;
  inset-block-start: var(--h-row);
  z-index: 1;
  background: var(--panel2);
  border-block-end: 1px solid var(--line);
}

.grid__filter {
  inline-size: 100%;
  min-inline-size: 0;
  block-size: 22px;
  padding-inline: var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  background: var(--input);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-xs);
}

.grid__filter:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

.pager {
  display: inline-flex;
  gap: var(--sp-1);
}

.pager .btn {
  inline-size: 30px;
  padding-inline: 0;
}


/* ════════════════════════════════════════════════════════════════════════════
   المركز المالي — the hub (design handoff §3).

   No shadows on any of it: the handoff says cards are separated by BORDERS, and
   a shadow here would be the one place in the system that disagrees. Radius 7px
   for cards, per the same scale.
   ════════════════════════════════════════════════════════════════════════════ */

.hub {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-3);
}

.hub__kpis {
  display: grid;
  /* Four across on a desk, folding to two and then one. auto-fit rather than a
     media query, so it folds at the width the CONTENT needs rather than at a
     number somebody picked. */
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
  gap: var(--sp-3);
}

.kpi {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto auto;
  align-items: center;
  gap: 2px var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 7px;
}

.kpi__glyph {
  grid-row: 1 / span 3;
  font-size: 20px;
  opacity: 0.75;
}

.kpi__label {
  font-size: 11.5px;
  color: var(--ink-muted);
}

.kpi__value {
  /* 22px/600 mono — the handoff's KPI size. */
  font-size: 22px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.15;
}

.kpi__delta {
  font-size: 11.5px;
  font-weight: 500;
}

.kpi__delta--up   { color: var(--ok); }
.kpi__delta--down { color: var(--bad); }
.kpi__delta--flat { color: var(--ink-muted); }

.hub__grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: var(--sp-3);
}

@media (max-width: 1100px) {
  .hub__grid { grid-template-columns: 1fr; }
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 7px;
  overflow: hidden;
}

.card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  background: var(--head);
  border-block-end: 1px solid var(--line);
}

.card__title { font-size: 12.5px; font-weight: 600; color: var(--text); }
.card__note  { font-size: 11px; color: var(--ink-muted); }

/* One grid column per month, each holding its bar pair AND its label — so the two
   cannot drift apart. They did when the bars were an SVG with its own coordinate
   space: the viewBox letterboxed to fit the height and the bars ended up 74px
   apart against the labels' 113px. */
.chart {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: end;
  block-size: 168px;
  padding: var(--sp-2) var(--sp-2) 0;
}

.chart__slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  block-size: 100%;
}

.chart__pair {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 3px;
  inline-size: 100%;
  flex: 1;
  border-block-end: 1px solid var(--line);
}

.chart__bar {
  inline-size: 15px;
  min-block-size: 1px;
  border-radius: 2px 2px 0 0;
}

.chart__bar--sales     { background: var(--brand); }
.chart__bar--purchases { background: var(--warn); }

.chart__month {
  font-size: 11px;
  color: var(--ink-muted);
  padding-block-end: var(--sp-1);
}

.chart__legend {
  display: flex;
  gap: var(--sp-4);
  padding: 0 var(--sp-3) var(--sp-2);
}

.chart__key { font-size: 11px; color: var(--ink-muted); display: inline-flex; align-items: center; gap: 6px; }

.chart__key::before {
  content: "";
  inline-size: 10px;
  block-size: 10px;
  border-radius: 2px;
}

.chart__key--sales::before     { background: var(--brand); }
.chart__key--purchases::before { background: var(--warn); }

.hub__alerts { list-style: none; margin: 0; padding: 0; }

.hub__alert { border-block-end: 1px solid var(--line2); }

.hub__alert-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  inline-size: 100%;
  padding: var(--sp-2) var(--sp-3);
  font: inherit;
  font-size: 12px;
  text-align: start;
  color: var(--text);
  background: none;
  border: 0;
  cursor: pointer;
}

.hub__alert-btn:hover:not(:disabled) { background: var(--hover); }
.hub__alert-btn:disabled { cursor: default; color: var(--ink-muted); }

/* The severity shows as a stripe on the inline start edge, not as a coloured
   background: the row still has to be readable, and a tinted row makes the text
   on it the second thing you see. */
.hub__alert--bad  { box-shadow: inset 2px 0 0 var(--bad); }
.hub__alert--warn { box-shadow: inset 2px 0 0 var(--warn); }
.hub__alert--info { box-shadow: inset 2px 0 0 var(--brand); }

.hub__alert-go { color: var(--ink-muted); }

.hub__clear { padding: var(--sp-3); margin: 0; font-size: 12px; color: var(--ink-muted); }

.hub__stock {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-block-start: auto;
  padding: var(--sp-2) var(--sp-3);
  background: var(--panel2);
  border-block-start: 1px solid var(--line);
}

.hub__stock-label { font-size: 11.5px; color: var(--ink-muted); }
.hub__stock-value { font-size: 14px; font-weight: 600; }

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: var(--sp-2);
  padding: var(--sp-3);
}

.tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: var(--sp-3) var(--sp-2);
  font: inherit;
  color: var(--text);
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 7px;
  cursor: pointer;
}

.tile:hover { background: var(--accent-soft); border-color: var(--brand); }

.tile:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.tile__glyph { font-size: 19px; }
.tile__name  { font-size: 11.5px; text-align: center; line-height: 1.25; }
.tile__id    { font-size: 11px; color: var(--ink-muted); }

/* The recent-documents table spans both columns: it is a table, and a table in a
   third of the width wraps every account name. */
.hub__recent { grid-column: 1 / -1; }


/* ─────────────────────────────────────────────────────────────────────────
   KEY SHEET · «?» — every key the screen in front actually answers, grouped.
   ───────────────────────────────────────────────────────────────────────── */

.dialog--keys { inline-size: min(760px, 94vw); }
.dialog--keys:focus { outline: none; }

.keysheet {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: var(--sp-6);
}

.keysheet__group { display: flex; flex-direction: column; gap: var(--sp-2); }
.keysheet__title { margin: 0; font-size: var(--fs-xs); font-weight: 700; color: var(--ink-muted); }
.keysheet__list  { display: flex; flex-direction: column; gap: var(--sp-2); margin: 0; }
.keysheet__row   { display: flex; align-items: baseline; gap: var(--sp-3); }
.keysheet__row dt { flex: 0 0 8.5rem; }
.keysheet__row dd { margin: 0; }

.keysheet kbd {
  display: inline-block;
  padding: 1px 6px;
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  background: var(--panel2);
  font-size: var(--fs-xs);
  font-weight: 600;
  direction: ltr;
  unicode-bidi: isolate;
  white-space: nowrap;
}
