/* Helper text rendered under a form input. */
.form-hint {
  font-size: 12px;
  color: var(--muted-color, var(--muted));
  margin-top: 5px;
  line-height: 1.5;
}

/* Repeatable line editor shared by the purchase and sale forms. */
.line-editor-input { height: 38px; font-size: 13px; }

.line-editor-total {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  text-align: right;
  white-space: nowrap;
}

.line-editor-empty { text-align: center; color: var(--muted-color, var(--muted)); padding: 24px 12px; }

.line-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--danger, #e11d48);
  background: transparent;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.line-remove:hover { background: rgba(225, 29, 72, 0.08); border-color: var(--danger, #e11d48); }

/* ============================================================================
   Invenza POS — application styles
   Additions layered on top of the Invenza template (app.css + tailwind.css).
   ========================================================================== */

/* Accessibility ------------------------------------------------------------ */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* Tables ------------------------------------------------------------------- */
.table-wrap { width: 100%; overflow-x: auto; }

.data-table tbody td { vertical-align: middle; }

.data-table .cell-actions { width: 60px; text-align: right; }

.table-empty {
  padding: 56px 24px;
  text-align: center;
  color: var(--muted);
}

.table-empty-icon {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 14px;
  background: var(--background);
  color: var(--muted);
}

.table-empty h4 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
}

.table-empty p { font-size: 13px; }

/* Product thumbnail -------------------------------------------------------- */
.product-thumb {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  object-fit: cover;
  flex-shrink: 0;
  border: 1px solid var(--border);
  background: var(--background);
}

.product-thumb-initials {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  flex-shrink: 0;
  color: var(--primary);
  background: var(--primary-light);
}

.product-thumb-lg { width: 96px; height: 96px; border-radius: 14px; font-size: 26px; }

/* Forms -------------------------------------------------------------------- */
.form-input.is-invalid,
.form-select.is-invalid,
.form-textarea.is-invalid { border-color: var(--danger); }

.field-error {
  font-size: 12px;
  color: var(--danger);
  margin-top: 5px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.form-hint { font-size: 12px; color: var(--muted); margin-top: 5px; }

/* --- File / image field ----------------------------------------------------
   A bare <input type="file"> gives no clue what is already stored and no way
   to clear it, so the field is a small stack: current file, replace input, and
   an inline preview of whatever the user just picked. */
.file-field { display: flex; flex-direction: column; gap: 10px; }

.file-field input[type="file"] {
  padding: 8px 10px;
  background: var(--surface, #fff);
}

.file-field-current {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius, 10px);
  background: var(--background-alt, rgba(0, 0, 0, 0.02));
}

.file-field-preview {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--background);
  flex: none;
}

.file-field-preview-new { width: 96px; height: 96px; }

.file-field-remove {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
}

.file-field-remove:hover span { color: var(--danger); }

.file-field input.is-over { border-color: var(--primary); }

.form-required::after { content: ' *'; color: var(--danger); }

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
}

.form-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding-top: 18px;
  margin-top: 18px;
  border-top: 1px solid var(--border);
}

/* Line item editor --------------------------------------------------------- */
.line-items-table { width: 100%; min-width: 720px; border-collapse: collapse; }

.line-items-table th {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
  font-weight: 600;
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  background: var(--background);
}

.line-items-table td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}


/* ============================================================================
   Spacing scale
   ============================================================================
   tailwind.css is a prebuilt file, generated from the classes that happened to
   be in use when it was built. Classes added to a view afterwards are simply
   absent from it, so the element renders with no margin at all and the page
   ends up with a gap that does not match its neighbours. These are the ones the
   views actually reference.

   They are declared here rather than in tailwind.css because that file is
   generated and would be overwritten by the next build.

   4px increments, matching the Tailwind scale the rest of the UI already uses.
   ========================================================================== */

.mt-0\.5 { margin-top: 2px; }
.mt-1    { margin-top: 4px; }
.mt-2    { margin-top: 8px; }
.mt-3    { margin-top: 12px; }
.mt-4    { margin-top: 16px; }
.mt-5    { margin-top: 20px; }
.mt-6    { margin-top: 24px; }
.mt-7    { margin-top: 28px; }

.mb-0\.5 { margin-bottom: 2px; }
.mb-1    { margin-bottom: 4px; }
.mb-1\.5 { margin-bottom: 6px; }
.mb-2    { margin-bottom: 8px; }
.mb-3    { margin-bottom: 12px; }
.mb-4    { margin-bottom: 16px; }
.mb-5    { margin-bottom: 20px; }
.mb-6    { margin-bottom: 24px; }

.ml-1    { margin-left: 4px; }
.ml-2    { margin-left: 8px; }
.mr-1    { margin-right: 4px; }
.mr-2    { margin-right: 8px; }

.p-2     { padding: 8px; }
.p-4     { padding: 16px; }
.p-5     { padding: 20px; }
.p-6     { padding: 24px; }

.pt-2    { padding-top: 8px; }
.pb-2    { padding-bottom: 8px; }
.pt-3    { padding-top: 12px; }
.pb-3    { padding-bottom: 12px; }
.pt-4    { padding-top: 16px; }
.pb-4    { padding-bottom: 16px; }

/* Logical inline-axis padding. The physical pr-* cannot be reused here: the
   utility that stood for it has no RTL override, so it would pad the wrong
   side of an Arabic label. */
.ps-1    { padding-left: 4px; padding-right: 4px; }
.ps-2    { padding-left: 8px; padding-right: 8px; }
.ps-3    { padding-left: 12px; padding-right: 12px; }

.gap-1    { gap: 4px; }
.gap-3    { gap: 12px; }
.gap-4    { gap: 16px; }
.gap-5    { gap: 20px; }
.gap-x-2  { column-gap: 8px; }
.gap-x-3  { column-gap: 12px; }
.gap-x-4  { column-gap: 16px; }
.gap-x-8  { column-gap: 32px; }
.gap-y-1  { row-gap: 4px; }
.gap-y-2  { row-gap: 8px; }
.gap-y-3  { row-gap: 12px; }

/* Colour utilities the prebuilt file does not carry. Each one is used in a
   status pill, where falling back to the inherited colour would make a
   "failed" badge look identical to a "paid" one. */
.text-\[var\(--text\)\]    { color: var(--text); }
.text-\[var\(--muted\)\]   { color: var(--muted); }
.text-\[var\(--primary\)\] { color: var(--primary); }
.text-\[var\(--danger\)\]  { color: var(--danger); }

/* Remaining one-off values. The error-page code and the auth logo are sized
   directly rather than through the scale, so they are declared here too. */
.p-1     { padding: 4px; }
.p-1\.5  { padding: 6px; }

.text-\[64px\]  { font-size: 64px; }
.text-\[10px\]  { font-size: 10px; }
.text-\[13px\]  { font-size: 13px; }

.shadow-\[0_4px_14px_rgba\(34\,181\,115\,0\.35\)\] {
  box-shadow: 0 4px 14px rgba(37, 99, 235, 0.35);
}

.text-\[var\(--success\)\] { color: var(--success); }
.border-\[var\(--border\)\] { border-color: var(--border); }

.w-\[44px\] { width: 44px; }
.h-\[44px\] { height: 44px; }

.line-items-table .form-input,
.line-items-table .form-select { height: 38px; font-size: 13px; }

.line-items-table .li-amount { font-size: 13px; font-weight: 600; color: var(--text); text-align: right; }

.line-items-table tfoot td { font-size: 13px; border-bottom: none; padding: 6px 12px; }
.line-items-table tfoot tr.total-row td { font-size: 15px; font-weight: 700; color: var(--text); }

.totals-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 260px;
}

.totals-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  color: var(--muted);
}

.totals-row span:last-child { font-weight: 600; color: var(--text); }

.totals-row.grand {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.totals-row.grand span:last-child { color: var(--primary); font-size: 18px; }


/* ============================================================================
   Header, navigation and page transitions
   ========================================================================== */

/* The action group sits at the trailing edge of the bar. The physical
   margin-left would push it the wrong way in RTL, so this uses the logical
   side: it resolves to the left edge in Arabic and to the right in English. */
#app-header .header-actions { margin-right: auto; }

/* Brand artwork -----------------------------------------------------------
   The supplied logo.png is a wide Arabic wordmark with the tagline set
   underneath it, drawn in black and grey on a transparent background. Two
   published variants exist per artwork so it stays legible on a light or a
   dark surface, and four files appear in the markup:

     logo-on-light / logo-mark-on-light   black artwork, for a light surface
     logo-on-dark  / logo-mark-on-dark    white artwork, for a dark surface

   All four are hidden by default and exactly one is shown, chosen by the
   sidebar's collapsed state and the active theme. Doing the swap in CSS means
   toggling either one costs no network round trip.

   The artwork must not be mirrored in RTL: the Arabic inside it is already
   set right-to-left, so flipping the image would spell the word backwards. */
.brand-logo {
  display: none;
  height: 39px;
  width: auto;
}

/* Expanded sidebar shows the wordmark; collapsed shows the square mark.

   The light variants are guarded by html:not(.dark). Without that guard a rule
   that only tests the collapsed state would still match under the dark theme,
   and the black and white wordmarks would render on top of each other. */
html:not(.dark) #sidebar:not(.collapsed) .brand-logo--full.brand-logo--on-light,
html:not(.dark) #sidebar.collapsed .brand-logo--mark.brand-logo--on-light {
  display: block;
}

.dark #sidebar:not(.collapsed) .brand-logo--full.brand-logo--on-dark,
.dark #sidebar.collapsed .brand-logo--mark.brand-logo--on-dark {
  display: block;
}

/* 72px when collapsed, so the mark is centred rather than pinned to the edge. */
#sidebar.collapsed .brand-logo--mark {
  height: 36px;
  width: 36px;
  margin-inline: auto;
}

/* Auth screens: the square mark only. Hidden by default so that both
   variants never occupy the page at once — as a plain .auth-logo rule would,
   which stacked the black and white artwork on top of each other.
   It sits in the brand panel's header row now, so it keeps its own column
   (flex: none) instead of the text wrapping around it, and it is sized as a
   square rather than by width alone so it aligns with the two-line identity
   block beside it. */
.auth-logo {
  display: none;
  width: 56px;
  height: 56px;
  flex: 0 0 auto;
  margin: 0;
}

html:not(.dark) .auth-logo.brand-logo--on-light { display: block; }
.dark .auth-logo.brand-logo--on-dark             { display: block; }

/* Page transitions -------------------------------------------------------
   Every internal link fades the content out before the browser leaves, and
   the incoming content rises into place. Vertical only, so nothing has to be
   mirrored when the document direction changes. */
main {
  animation: pageIn 0.26s cubic-bezier(0.22, 1, 0.36, 1);
  transition: opacity 0.16s ease, transform 0.16s ease;
}
@keyframes pageIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
body.is-leaving main { opacity: 0; transform: translateY(-8px); }

/* Active menu marker ------------------------------------------------------ */
.nav-item.active::after {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 60%;
  background: var(--primary);
  border-radius: 0 3px 3px 0;
  animation: fadeIn 0.2s ease;
}

/* Keep the pressed state winning over the hover lift added in app.css. */
.btn:active:not(:disabled):not(.btn-ghost) { transform: scale(0.97); }
/* The chart hosts are sized by their wrapper, so the element ApexCharts
    mounts into has to inherit that height instead of collapsing to zero. */
.chart-container > div { height: 100%; }

/* Arabic font override – applies when HTML lang attribute is "ar".
   Sora leads the stack so digits render in Sora; it has no Arabic glyphs, so
   the Arabic text still falls through to IBM Plex Sans Arabic. */
html[lang="ar"] body, [dir="rtl"] body {font-family: var(--font-num) !important; }

/* Mobile responsive tweaks */
@media (max-width: 640px) {
  /* Content is full width; the sidebar offset is cleared in rtl.css, which
     loads after this file. */
  #main-wrapper { margin-left: 0 !important; }

  /* Header: the bar is a fixed 64px, so the children wrap rather than stack —
     a column would push the search box and the action group outside it. The
     search takes the full first row, the icon buttons share the second. */
  #app-header {
    height: auto;
    min-height: var(--header-height);
    flex-wrap: wrap;
    align-items: center;
    padding: 10px 12px;
    gap: 8px 10px;
  }
  #app-header form.search-box {
    flex: 1 0 100%;
    max-width: none;
    order: -1;
  }
  #app-header .header-actions {
    margin: 0;
    margin-inline-start: auto;
  }

  /* A dropdown hangs off the trailing edge of its trigger. On a phone the
     header has wrapped onto two rows, so the trigger sits near the viewport
     edge and the panel spills off the opposite side. Anchoring the panel to
     the header instead — the wrapper stops being its containing block, and the
     sticky header becomes one — lets it drop straight below the bar and
     stretch across the screen, wherever the button that opened it sits. */
  #notification-dropdown-wrapper,
  #user-dropdown-wrapper { position: static; }

  #notification-dropdown,
  #user-dropdown {
    inset-inline: 12px;
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
  }

  /* Welcome banner layout */
  .welcome-banner { flex-direction: column; align-items: flex-start; }
  .welcome-actions { flex-direction: column; align-items: stretch; gap: 8px; }
  .welcome-actions a, .welcome-actions form { width: 100%; }
  .welcome-actions a { text-align: center; }

  /* Collapse grids to single column */
  .page-section .grid { grid-template-columns: 1fr !important; }

  /* Card spacing */
  .card { margin-bottom: 1rem; }
}
