/* ============================================================================
 * UI Fixes — apparnaai panel
 * Loaded globally into every layout <head> by the UI Fixes extension.
 * All panel UI fixes live here so the core theme/views are not edited.
 *
 * Every rule below traces to a finding in docs/UI-AUDIT.md; the finding id is
 * quoted with each section, so the two stay easy to diff.
 *
 * Direction handling: the theme puts `ltr`/`rtl` on <body> and Laravel puts
 * `dir` on <html>. Selectors match both, so a fix cannot silently stop applying
 * if one of the two is ever dropped.
 *
 * `!important` is used deliberately and only where the theme's own rule is
 * itself `!important` or wins on specificity — this file loads after the theme
 * bundle but cannot outrank a more specific selector without it.
 * ==========================================================================*/

/* ------------------------------------------------------------------ *
 * Section index
 *   1. RTL layout geometry            (D-1, B-7)
 *   2. Typography and fonts           (B-4, B-11, B-12)
 *   3. Direction-neutral defaults     (body text-align)
 *   4. Directional icons              (B-8)
 *   5. Horizontal overflow            (D-2, A-1)
 *   6. Forms and inputs               (D-5)
 *   7. Images                         (A-3)
 *   8. Tables                         (C-1b, paired with ui-fixes.js)
 *   9. Viewport units and tap targets (C-1c, D-4)
 * ------------------------------------------------------------------ */


/* ==========================================================================
 * 1. RTL layout geometry — D-1 (CRITICAL), B-7
 *
 * The theme offsets dashboard content by the sidebar width only from 768px up:
 *     @media (min-width: 768px) { .app-content { margin-left: 270px } }
 * but scss/custom/rtl.scss mirrors it with no media query at all:
 *     .rtl .app-content { margin-left: 0; margin-right: 250px }
 * `.rtl .app-content` outranks the plain `.app-content` rule, so on a 375px
 * phone the Persian dashboard kept a 250px offset it could not afford: the
 * sidebar sat over the right 270px of the screen and content was pushed to
 * [-250 .. 125] — a quarter of a screen wide, and clipped.
 *
 * Below: no offset under 768px (matching LTR), and the correct 270px above it
 * (the sidebar measures 270px, not the 250px the theme assumed).
 * ==========================================================================*/

@media (max-width: 767.98px) {
  body.rtl .app-content,
  [dir="rtl"] .app-content {
    margin-right: 0 !important;
    margin-left: 0 !important;
  }
}

@media (min-width: 768px) {
  body.rtl .app-content,
  [dir="rtl"] .app-content {
    margin-right: 270px !important;
    margin-left: 0 !important;
  }
}

/* The sidebar itself is parked off-canvas in LTR at mobile widths via a
 * negative left offset. In RTL rtl.scss sets `right: 0` with no off-canvas
 * state, so it stayed on screen. Park it symmetrically and let the theme's own
 * toggle classes bring it back exactly as they do in LTR.
 *
 * Parked unconditionally, NOT behind `.sidebar-gone`: that class is added by
 * jQuery on DOM ready (themes/default/js/custom.js), which is long after the
 * first paint. Keying the off-canvas state to it meant every page in the panel
 * opened with the drawer sitting over the content until the scripts finished —
 * the closing frame of every navigation on a phone. LTR never had the flash
 * because its off-canvas offset is plain CSS with no class on it. */
@media (max-width: 767.98px) {
  body.rtl .app-sidebar,
  [dir="rtl"] .app-sidebar {
    right: -270px;
  }

  body.rtl.sidenav-toggled .app-sidebar,
  body.rtl.sidebar-mini.sidenav-toggled1 .app-sidebar,
  body.rtl.sidebar-show .app-sidebar {
    right: 0;
  }
}


/* ==========================================================================
 * 1b. Sidebar labels overflow in Persian
 *
 * The theme sizes every sidebar row at a fixed `height: 38px` and forbids the
 * label from wrapping (`.side-menu__label { white-space: nowrap }`). That holds
 * for short English labels, but Persian translations are longer — "دستیار تولید
 * مقاله با هوش مصنوعی" against "AI Article Wizard" — so the text runs straight
 * out of the 270px sidebar and over the page behind it.
 *
 * Letting the label wrap and the row grow to fit is the fix; the row keeps a
 * 44px floor so touch targets do not shrink. Scoped to RTL, because the English
 * sidebar fits as designed and should keep its exact density.
 * ==========================================================================*/

body.rtl .side-menu .side-menu__item,
body.rtl .side-menu .slide-item,
[dir="rtl"] .side-menu .side-menu__item,
[dir="rtl"] .side-menu .slide-item {
  height: auto;
  min-height: 44px;
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
}

body.rtl .side-menu__label,
[dir="rtl"] .side-menu__label {
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.6;
  min-width: 0;
}


/* ==========================================================================
 * 1c. Backdrop behind the mobile sidebar
 *
 * The sidebar opens as an overlay on a phone with nothing behind it, so the
 * page shows through at full contrast and the half-covered content reads as
 * broken layout rather than as a drawer sitting on top of it. There is also no
 * way to dismiss it except finding the toggle again.
 *
 * The theme already puts `sidenav-toggled` on <body> while the drawer is open,
 * so a pseudo-element on <body> is enough — no markup, and it disappears with
 * the class. ui-fixes.js closes the drawer when the backdrop is tapped.
 * ==========================================================================*/

@media (max-width: 767.98px) {
  body.sidenav-toggled::after,
  body.sidenav-toggled1::after {
    content: '';
    position: fixed;
    inset: 0;
    background: rgba(15, 15, 25, 0.45);
    /* Under the sidebar (the theme uses z-index 1000+ there), above content. */
    z-index: 999;
    opacity: 1;
    transition: opacity 0.2s ease;
  }
}


/* ==========================================================================
 * 2. Typography and fonts — B-4 (CRITICAL), B-11, B-12
 *
 * B-4: the theme sets `font-family: 'Poppins', sans-serif` on <body> and the
 * codebase contains no Persian family at all, so every Persian glyph fell back
 * to an unspecified system face that differs per device. Vazirmatn is now
 * self-hosted (see fonts.css) and put in front of Poppins for RTL pages.
 * Poppins stays as the Latin fallback so mixed strings keep their look.
 *
 * The family is applied to the elements that most often carry their own
 * font-family in this theme — form controls, buttons, tables, placeholders —
 * because a bare `body` rule does not reach them.
 * ==========================================================================*/

body.rtl,
[dir="rtl"] body,
body.rtl input,
body.rtl select,
body.rtl textarea,
body.rtl button,
body.rtl .btn,
body.rtl .form-control,
body.rtl table,
body.rtl th,
body.rtl td,
body.rtl .card-title,
body.rtl .side-menu__label,
body.rtl .modal-title,
body.rtl .dropdown-item,
body.rtl .nav-link,
body.rtl label,
body.rtl h1, body.rtl h2, body.rtl h3,
body.rtl h4, body.rtl h5, body.rtl h6 {
  font-family: 'Vazirmatn', 'Poppins', sans-serif;
}

body.rtl ::placeholder,
[dir="rtl"] ::placeholder,
body.rtl ::-webkit-input-placeholder {
  font-family: 'Vazirmatn', 'Poppins', sans-serif;
}

/* The theme declares a font-family in ~20 further places (Poppins, Lato, Open
 * Sans, Niconne, and a bare `sans-serif !important` in the side menu), each of
 * which beat the body rule on its own elements and left islands of Latin-metric
 * text in the Persian panel. Rather than chase each selector, every element on
 * an RTL page inherits Vazirmatn — except the ones where a specific family is
 * the point: icon fonts, the Ace editor, and monospace content. */
body.rtl *:not(i):not(.fa):not(.fas):not(.far):not(.fab):not([class*="fa-"]):not(.material-icons):not(.ace_editor):not(.ace_editor *):not(code):not(pre):not(kbd):not(samp) {
  font-family: 'Vazirmatn', 'Poppins', sans-serif !important;
}

/* Code and monospace content must stay monospace even in RTL. */
body.rtl code,
body.rtl pre,
body.rtl kbd,
body.rtl samp,
body.rtl .ace_editor {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* B-11: theme ships `line-height: 1.5`. Persian ascenders and descenders need
 * more room; 1.5 reads cramped. Scoped to RTL so the Latin baseline is left
 * exactly as designed. */
body.rtl,
[dir="rtl"] body {
  line-height: 1.75;
}

/* Persian needs more size than Latin to stay legible: its letters carry dots
 * and diacritics that vanish below ~12px, and the script has no capitals to
 * anchor a word's shape. The theme labels a lot of UI at 9-11px — measured
 * across a 96-run sweep, 216 sidebar section headers at 10px, plus button
 * captions at 9px and switch descriptions at 10px. Raised to a 12px floor for
 * Persian only; the Latin side keeps the density it was designed with.
 *
 * The utilities are named after their pixel size, so raising the class is the
 * same edit as raising every element that uses it. */
body.rtl .fs-9,
body.rtl .fs-10,
body.rtl .fs-11,
body.rtl .side-item-category,
body.rtl .dataTables_info,
body.rtl .dataTables_length,
body.rtl .dataTables_length label,
body.rtl .breadcrumb-item,
body.rtl .breadcrumb-item a,
body.rtl .page-leftheader a,
body.rtl .page-rightheader a,
body.rtl .footer-links p.m-2,
body.rtl footer p.m-2,
body.rtl .title p.m-2,
[dir="rtl"] .fs-9,
[dir="rtl"] .fs-10,
[dir="rtl"] .fs-11 {
  font-size: 12px !important;
}

/* Headings set at 12-14px with a 1.1 line-height clip Persian descenders
 * against the line below. Measured: h4.fs-12 rendered 13.2px of line box for a
 * 12px font. */
body.rtl h1, body.rtl h2, body.rtl h3,
body.rtl h4, body.rtl h5, body.rtl h6,
body.rtl p,
[dir="rtl"] h4, [dir="rtl"] h5, [dir="rtl"] h6 {
  line-height: 1.6;
}

/* B-12: five unscoped `letter-spacing` declarations in the theme land on
 * Persian text, where extra tracking breaks the cursive letter joining that
 * makes a word readable. Reset for Persian only — Latin keeps its tracking,
 * since those same rules style Latin headings in the LTR build. Icon fonts are
 * excluded: Font Awesome positions some glyphs with tracking. */
body.rtl,
body.rtl *:not([class*="fa-"]):not(.fa):not(.fas):not(.far):not(.fab) {
  letter-spacing: normal !important;
}


/* ==========================================================================
 * 3. Direction-neutral defaults — body text-align
 *
 * scss/custom/_style.scss hard-codes `text-align: left` on <body>. In RTL the
 * theme corrects it for `.app-content` only, so anything outside that wrapper
 * (auth pages, modals rendered at body level, toasts) stayed left-aligned.
 * `start` follows `dir` in both directions and needs no per-locale override.
 * ==========================================================================*/

body {
  text-align: start;
}

body.rtl .app-content,
[dir="rtl"] .app-content {
  text-align: start;
}


/* ==========================================================================
 * 4. Directional icons — B-8
 *
 * rtl.scss swaps exactly one glyph (`.fa-angle-right:before` inside the side
 * menu). The templates use fa-angle-right 71×, fa-angle-left 71×, plus
 * chevrons and share icons, all of which keep pointing the wrong way in
 * Persian. Mirroring by transform handles every instance without touching
 * markup and — unlike a blanket `svg { transform: scaleX(-1) }` — names only
 * icons whose meaning is directional. Clock, search, check, user, bell and
 * trash are deliberately absent.
 * ==========================================================================*/

body.rtl .fa-angle-right,
body.rtl .fa-angle-left,
body.rtl .fa-angles-right,
body.rtl .fa-angles-left,
body.rtl .fa-chevrons-right,
body.rtl .fa-chevrons-left,
body.rtl .fa-arrow-turn-right,
body.rtl .fa-arrow-turn-left,
body.rtl .fa-turn-right,
body.rtl .fa-turn-left,
body.rtl .fa-angle-double-right,
body.rtl .fa-angle-double-left,
body.rtl .fa-chevron-right,
body.rtl .fa-chevron-left,
body.rtl .fa-arrow-right,
body.rtl .fa-arrow-left,
body.rtl .fa-arrow-right-long,
body.rtl .fa-arrow-left-long,
body.rtl .fa-long-arrow-right,
body.rtl .fa-long-arrow-left,
body.rtl .fa-caret-right,
body.rtl .fa-caret-left,
body.rtl .fa-circle-chevron-right,
body.rtl .fa-circle-chevron-left,
body.rtl .fa-circle-arrow-right,
body.rtl .fa-circle-arrow-left,
body.rtl .fa-reply,
body.rtl .fa-share,
body.rtl .fa-share-from-square,
body.rtl .fa-right-to-bracket,
body.rtl .fa-right-from-bracket,
body.rtl .fa-sign-in,
body.rtl .fa-sign-out,
body.rtl .fa-sign-in-alt,
body.rtl .fa-sign-out-alt {
  transform: scaleX(-1);
}

/* The side menu already swaps its own glyph in rtl.scss; mirroring it a second
 * time would point it back the wrong way. */
body.rtl .side-menu__item .fa-angle-right {
  transform: none;
}


/* ==========================================================================
 * 5. Horizontal overflow — D-2, A-1
 *
 * Dashboard pages scroll 12px horizontally at 1440 in both locales. The cause
 * is Bootstrap's grid contract: `.row` applies negative inline margins of half
 * a gutter (12px per side) and expects its parent to carry the matching
 * padding. `.app-content .side-app` sets `padding: 20px 0 0 0` — no horizontal
 * padding — so every row hangs 12px past the content box.
 *
 * Restoring the gutter padding fixes the overflow at its source instead of
 * hiding it. The theme also sets `overflow-x: hidden` on <body>, which is why
 * this presented as a stray scrollbar rather than visibly broken layout.
 * ==========================================================================*/

.app-content .side-app {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

/* The homepage overflows by a further 40px, and for a different reason: AOS
 * stages its entrance animations by translating elements sideways before they
 * scroll into view. Measured on the features row at 1440, the two columns sit
 * at -40..620 and 820..1480 — each displaced 100px from its grid position, and
 * the right-hand one past the viewport edge. They snap into place only once
 * they are scrolled to, so the page carries a phantom scrollbar until then.
 *
 * Clipping the frontend page wrapper is the right answer: the overflow is
 * deliberate, purely decorative and never meant to be reachable. `clip` is
 * preferred over `hidden` because it does not turn the element into a scroll
 * container, which would break `position: sticky` inside it.
 * ==========================================================================*/

body.frontend-body .page {
  overflow-x: clip;
}

@supports not (overflow-x: clip) {
  body.frontend-body .page {
    overflow-x: hidden;
  }
}


/* ==========================================================================
 * 6. Forms and inputs — D-5
 *
 * Inputs below 16px make iOS Safari zoom the viewport on focus. Three inputs
 * on the dashboard and four on the plans screen were under that threshold, and
 * with pinch-zoom disabled (fixed in ui-fixes.js) the user could not zoom back
 * out. Raised at mobile widths only, so desktop density is untouched.
 * ==========================================================================*/

@media (max-width: 767.98px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  select,
  textarea,
  .form-control,
  .form-select {
    font-size: 16px !important;
  }
}


/* ==========================================================================
 * 6b. Login method tabs
 *
 * The auth page renders one tab per enabled login extension inside
 * `ul#authMethodTabs`. The list is a flex row with `flex-wrap: wrap` and the
 * items size to their own text, so the pair only fits when the labels happen to
 * be short: at 1440 the English labels measure 187px + 193px against a 364px
 * list and the second tab wraps onto its own line, and at 375 each item takes
 * the full 303px so they always stack.
 *
 * Making the items share the row equally keeps them side by side at every
 * width, in both locales. The label shrinks rather than wrapping, and truncates
 * only if a future extension ships a very long name.
 * ==========================================================================*/

#authMethodTabs {
  flex-wrap: nowrap;
}

#authMethodTabs .nav-item {
  flex: 1 1 0;
  width: auto !important;
  min-width: 0;
}

#authMethodTabs .nav-link {
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  /* Scales with the viewport so both labels fit a 375px phone without wrapping,
   * and never grows past the tab type size the theme uses on desktop. */
  font-size: clamp(0.75rem, 3.1vw, 0.9375rem);
}

#authMethodTabs .nav-link i {
  margin-right: 0.35rem;
}

body.rtl #authMethodTabs .nav-link i {
  margin-right: 0;
  margin-left: 0.35rem;
}


/* ==========================================================================
 * 6c. Buttons stack on narrow screens
 *
 * The theme gives every primary button `min-width: 180px`. Two of them side by
 * side need 360px plus the gap, which does not fit inside a padded card on a
 * phone, so pairs like the announcement banner's "داکیومنت" / "بستن پیام" drop
 * onto separate lines and sit flush against each other.
 *
 * Releasing the floor below the small breakpoint lets a pair share one row and
 * size to its own label. The buttons keep their padding, so short labels still
 * look like buttons rather than links.
 * ==========================================================================*/

@media (max-width: 575.98px) {
  .btn-primary,
  .btn-cancel,
  .btn-cancel-black,
  .announcement-action-button,
  .announcement-cancel-button {
    min-width: 0;
  }
}

/* Adjacent buttons should never touch. Logical margin, so the gap lands on the
 * correct side in both directions. */
.btn + .btn,
.btn + .action-button,
.action-button + .btn {
  margin-inline-start: 0.5rem;
}

/* The announcement banner sets `display:flex` inline, so its content column and
 * image sit on one row and the buttons inherit whatever width is left. Allowing
 * the row to wrap gives the buttons the full card width on a phone, and the
 * padding — also inline, hence the !important — stops eating it. */
.announcement-banner {
  flex-wrap: wrap;
  gap: 1rem;
}

@media (max-width: 767.98px) {
  .announcement-banner {
    padding: 1.25rem !important;
  }
}

.announcement-content .announcement-action-button,
.announcement-content .announcement-cancel-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}


/* ==========================================================================
 * 7. Images — A-3
 *
 * 466 <img> tags across the templates, zero uses of `img-fluid`. Any image
 * wider than its container pushed the layout instead of scaling. A global
 * max-width is the smallest rule that covers all of them.
 *
 * `height` is intentionally left alone: several logos and avatars in this theme
 * are sized by CSS height with width auto, and forcing `height: auto` collapses
 * them. Constraining width alone is enough to stop the overflow.
 * ==========================================================================*/

img {
  max-width: 100%;
}

/* Images that now carry their intrinsic size as attributes must keep their
 * aspect ratio when CSS narrows them, or the reserved box squashes the picture.
 * Scoped to the attribute pair so images sized purely by CSS height — logos and
 * avatars, which have no attributes — are untouched. */
img[width][height] {
  height: auto;
}


/* ==========================================================================
 * 8. Tables — C-1b
 *
 * 77 Blade files contain a <table>; five use `.table-responsive`. On the live
 * dashboard every table measured was unwrapped. ui-fixes.js wraps them at
 * runtime; this rule gives the wrapper its scroll behaviour and keeps momentum
 * scrolling on iOS.
 * ==========================================================================*/

.ui-fixes-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}

/* A `text-right` numeric column means "trailing edge". In RTL the trailing edge
 * is the left one, so the physical class has to be flipped back. */
body.rtl table td.text-right,
body.rtl table th.text-right {
  text-align: left !important;
}


/* ==========================================================================
 * 9. Viewport units and tap targets — C-1c, D-4
 *
 * `100vh` on mobile browsers includes the collapsing URL bar, so a full-height
 * pane is taller than the visible viewport and pushes content under the chrome.
 * `dvh` tracks the actual visible height. The `@supports` guard keeps older
 * browsers on the original `vh` behaviour.
 * ==========================================================================*/

@supports (height: 100dvh) {
  .app-content {
    min-height: calc(100dvh - 100px);
  }

  .horizontalMenucontainer {
    min-height: 100dvh;
  }
}

/* D-4: 123 controls on the dashboard are under the 44×44px touch guideline.
 * Sidebar rows are the ones actually thumbed on a phone and can grow without
 * reflowing anything else. Buttons elsewhere are left alone on purpose —
 * forcing a min-size on all of them would change desktop density too. */
@media (max-width: 767.98px) {
  .side-menu .side-menu__item,
  .side-menu .slide-item {
    min-height: 44px;
    display: flex;
    align-items: center;
  }
}

/* The rest of the small targets are icon-only controls in the header and card
 * toolbars. Growing them on every screen would change the panel's density on a
 * desktop, where a mouse hits a 24px icon fine — so the floor applies only to
 * coarse pointers, which is exactly the case the guideline is about. */
@media (pointer: coarse) {
  .app-header .nav-link.icon,
  .app-header .header-icon,
  .card-options a,
  .table-action-buttons a,
  .table-action-buttons button,
  .btn-icon,
  .btn,
  .dropdown-toggle {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}


/* ==========================================================================
 * 10. Colour contrast — WCAG AA
 *
 * Measured with axe-core over six pages in both locales: 102 failing nodes,
 * eleven distinct colour pairs, all of them small text. Three root colours
 * account for every failure, and each is a near miss rather than a bad choice —
 * which is why they survived design review and only a measurement catches them.
 *
 *   #728096 muted grey on white   4.00:1   (81 nodes)
 *   #007bff primary blue on white 3.98:1   (12 nodes, and white-on-blue is the
 *                                           same pair inverted, so buttons fail too)
 *   #007bff on #e1f0ff badge      3.43:1
 *   #00bc7e on #e6f8f2 badge      2.25:1   (worst on the site)
 *
 * The replacements below are the *smallest* darkening that clears 4.5:1 — each
 * was computed rather than eyeballed, so the palette shifts as little as it can
 * while becoming readable. Large text keeps the original colours: WCAG asks 3:1
 * there, which the originals already meet, and headings are where the brand
 * colour actually reads as the brand.
 *
 * This section is not RTL-specific — the failures are identical in English —
 * but it matters more in Persian, where the panel now renders a lot of UI text
 * at the 12px floor and thin Persian strokes lose more to low contrast than
 * Latin ones do.
 * ==========================================================================*/

/* Muted body text: 4.00 -> 4.54 on white */
.text-muted,
.dataTables_info,
.side-menu__label,
small.text-muted,
p.text-muted,
span.text-muted,
h6.text-muted,
.fs-9, .fs-10, .fs-11, .fs-12, .fs-13 {
  --ui-fixes-muted: #6a778b;
}

.text-muted,
.dataTables_info,
small.text-muted,
p.text-muted,
span.text-muted,
h6.text-muted {
  color: #6a778b !important;
}

/* Primary blue used as small text: 3.98 -> 4.54 on white */
.text-info,
.text-primary,
.breadcrumb-item a,
.breadcrumb-item.active a,
a.fs-9, a.fs-10, a.fs-11, a.fs-12, a.fs-13,
.fs-11 a, .fs-12 a, .fs-13 a {
  color: #0072ed !important;
}

/* Headings and display text keep the brand blue — they clear 3:1 already, which
 * is the AA threshold for large text. */
h1 .text-primary, h2 .text-primary, h3 .text-primary, h4 .text-primary,
h1.text-primary, h2.text-primary, h3.text-primary, h4.text-primary,
.fs-20 .text-primary, .fs-24 .text-primary, .fs-30 .text-primary {
  color: #007bff !important;
}

/* White on the primary button is the same near-miss pair inverted.
 *
 * Excluding the buttons that carry .btn-primary for shape but paint their own
 * colours: the announcement's cancel button is white with dark text, and taking
 * its background over dropped it to 3.62:1 — a contrast fix creating a contrast
 * failure. */
.btn-primary:not(.announcement-cancel-button):not(.btn-cancel):not(.btn-white),
.btn-primary:not(:disabled):not(.disabled):not(.announcement-cancel-button):not(.btn-cancel):not(.btn-white) {
  background-color: #0072ed;
  border-color: #0072ed;
}

/* Status pills: the green one was the worst pair on the site at 2.25:1 */
.cell-box.payment-monthly,
.cell-box.payment-yearly {
  color: #0068d8 !important;
}

.cell-box.plan-active,
.badge-success,
.text-success {
  color: #007f55 !important;
}

/* The last seven nodes, each a selector the rules above did not reach. */

/* Homepage section eyebrows and their links */
.title p,
.title p.m-2,
.title a {
  color: #0072ed !important;
}

/* Sortable table headers carry the muted grey at bold 12px */
table thead th.sorting,
table thead th.sorting_asc,
table thead th.sorting_desc,
.dataTable thead th {
  color: #6a778b !important;
}

/* The active sidebar row sits on #e1f0ff, where the brand blue drops to 3.43:1 */
.side-menu__item.active .side-menu__label,
.side-menu__item.active .side-menu__icon,
li.active > .side-menu__item {
  color: #0068d8 !important;
}

/* Frontend pill buttons are links, not .btn-primary, so they need the same
 * background darkening to carry white text. */
.action-button,
a.action-button {
  background-color: #0072ed;
}

/* The pricing period toggle and pagination both paint white on the brand blue
 * at 12px, which is the same 3.97:1 pair as the primary button. */
.tabs-menu li a.active,
.tabs-menu .nav li a.active,
.page-item.active .page-link {
  background-color: #0072ed;
  border-color: #0072ed;
}

/* ==========================================================================
 * 11. Generator settings panels on small screens
 *
 * `#image-settings-wrapper` is `position: fixed; width: 300px` with no media
 * query anywhere in the theme, and the content beside it compensates with a
 * fixed `margin: 284px`. That pairing only works while the viewport is wide
 * enough to hold both. Measured on the images page in Persian:
 *
 *     360px : panel 0..300 fixed, content 12..348   -> 288px of overlap
 *     768px : panel 0..300 fixed, content 12..486   -> 288px of overlap
 *    1440px : panel 0..300 fixed, content 296..1158 -> fine
 *
 * The panel sits on top of the prompt box and the generate button on every
 * phone and tablet, which is what makes this screen unusable rather than merely
 * cramped. Below the desktop breakpoint the panel joins the flow instead: full
 * width, scrolling with the page, stacked above the generator.
 *
 * Direction-neutral on purpose — the same overlap happens in English, mirrored.
 * ==========================================================================*/

@media (max-width: 991.98px) {
  /* `:not(.shrink-main-settings)` matters: the theme collapses this panel by
   * setting `width: 0 !important` on that class, and an unconditional
   * `width: 100% !important` here outranks it — which is what stopped the
   * collapse toggle doing anything below 992px while it still worked on
   * desktop. Collapsing is handled separately, just below. */
  #image-settings-wrapper:not(.shrink-main-settings),
  #video-settings-wrapper:not(.shrink-main-settings),
  .video-settings-wrapper:not(.shrink-main-settings),
  #advanced-settings-wrapper:not(.shrink-main-settings) {
    position: static !important;
    width: 100% !important;
    max-width: 100% !important;
    max-height: none !important;
    overflow-y: visible !important;
    border-left: 0 !important;
    border-right: 0 !important;
    border-bottom: 1px solid #ebecf1;
    top: auto !important;
    bottom: auto !important;
  }

  #image-side-space,
  #video-side-space,
  .image-side-space {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }

  /* The panel is a scroll container on desktop; in the flow it must not keep a
   * viewport-height cap or it collapses to a sliver. */
  #image-settings-wrapper:not(.shrink-main-settings) .image-settings,
  #video-settings-wrapper:not(.shrink-main-settings) .video-settings {
    width: 100% !important;
    height: auto !important;
  }

  /* Collapsed, and now part of the flow rather than a fixed column: a zero
   * width would leave an empty block taking vertical space, so hide it. The
   * minimized toggle stays visible to bring it back — the theme shows that one
   * unconditionally below 940px. */
  #image-settings-wrapper.shrink-main-settings,
  #video-settings-wrapper.shrink-main-settings {
    display: none !important;
  }

  /* Two identical slider icons show at once below 940px: one in the panel
   * header and one in the content toolbar, both toggling the same thing. The
   * panel's copy also vanishes with the panel it lives in, so it cannot reopen
   * what it closed — the content one is the useful half, and the only one kept.
   */
  #image-settings-wrapper #main-settings-toggle-minimized,
  #video-settings-wrapper #main-settings-toggle-minimized {
    display: none !important;
  }
}

/* The prompt row on the image generator is `display: flex; flex-wrap: nowrap`
 * with the button beside the field. At 360px that leaves the field 206px against
 * a 130px button, so the placeholder is cut mid-sentence — the user cannot read
 * what the field is for while typing into it. Below 480px the two stack, which
 * gives the field the full width and the button a comfortable target. */
@media (max-width: 479.98px) {
  .image-prompt.d-flex,
  .video-prompt.d-flex {
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  .image-prompt.d-flex > *,
  .video-prompt.d-flex > * {
    flex: 1 1 100%;
    width: 100% !important;
  }
}

/* ==========================================================================
 * 12. Polish
 * ==========================================================================*/

/* The drawer used to start 75px down so the app header stayed visible, which
 * left a band of page showing above it and made the drawer read as a panel that
 * had slipped rather than one that had opened. It now covers the full height,
 * above the header, the way a drawer is expected to behave — the backdrop and
 * tap-to-close added earlier are what make that safe. */
@media (max-width: 767.98px) {
  .app-sidebar {
    margin-top: 0 !important;
    top: 0 !important;
    height: 100% !important;
    z-index: 1001;
  }

  body.sidenav-toggled::after,
  body.sidenav-toggled1::after {
    z-index: 1000;
  }
}

/* The search icon sits 20px inside the leading edge while the field pads only
 * 10px, so a long query slides under the icon. Reserving the icon's width keeps
 * text clear of it — in both directions, since the field is symmetric. */
.search-wrapper .form-control,
#main-search,
#main-search-banner {
  padding-inline-start: 42px;
}

/* perfect-scrollbar computes its rail position inline and lands 12px outside the
 * sidebar in RTL, so the scrollbar floats over the page next to the panel. */
body.rtl .app-sidebar .ps__rail-y,
[dir="rtl"] .app-sidebar .ps__rail-y {
  left: 0 !important;
  right: auto !important;
}

/* ==========================================================================
 * 13. Controls that must not mirror
 *
 * A number stepper follows the number line, not the text. Persian readers write
 * right to left but still expect − on the left and + on the right, the way the
 * value grows. The generated mirror does not know that: it saw two absolutely
 * positioned children and swapped their offsets, so in Persian the plus landed
 * on the left and the minus on the right — measured on the images page, minus at
 * [178..202] and plus at [98..122], the reverse of English.
 *
 * The control is pinned back to its English arrangement, and its content flows
 * LTR so the value and its buttons stay in the order a number implies.
 * ==========================================================================*/

body.rtl .quantity,
[dir="rtl"] .quantity {
  direction: ltr;
}

body.rtl .quantity .decrease,
[dir="rtl"] .quantity .decrease {
  left: 8px;
  right: 88px;
}

body.rtl .quantity .increase,
[dir="rtl"] .quantity .increase {
  left: 88px;
  right: 8px;
}

/* Same reasoning for any other numeric spinner the theme ships. */
body.rtl .number-spinner,
body.rtl .input-number-group,
[dir="rtl"] .number-spinner,
[dir="rtl"] .input-number-group {
  direction: ltr;
}


/* ==========================================================================
 * 14. `white-space: nowrap` where the text can outgrow its box — C-1d
 *
 * The theme declares `nowrap` 28 times. Most are correct and are left alone:
 * `.sr-only`, the `.text-nowrap`/`.text-truncate` utilities, the marquee
 * track, the horizontally-scrolling tab strips, and every rule that already
 * pairs `nowrap` with `overflow: hidden; text-overflow: ellipsis`.
 *
 * Two do not survive translation, because a Persian label is routinely half
 * again as long as its English source:
 *
 * 1. `.side-menu__label` sets `nowrap` with no overflow rule at all. The
 *    sidebar is a fixed 270px, so a long label runs out past the panel edge
 *    instead of being contained. Truncating is the behaviour the neighbouring
 *    `.app-sidebar__user-name` already has, so the panel stays consistent —
 *    and `min-width: 0` is required for it to take effect at all, since the
 *    label is a flex item and flex items refuse to shrink below content width
 *    by default.
 *
 * 2. `.dropdown-item` inherits Bootstrap's `nowrap`. A menu sizes to its
 *    widest item, so one long Persian entry can make the menu wider than a
 *    phone. The clamp in ui-fixes.js then has nowhere to put it. Allowing
 *    wrapping below the phone breakpoint keeps the menu inside the viewport;
 *    desktop keeps single-line items.
 * ==========================================================================*/

.side-menu__label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (max-width: 575.98px) {
  .dropdown-menu .dropdown-item,
  .dropdown-menu .dropdown-header {
    white-space: normal;
  }
}


/* ==========================================================================
 * 15. The Persian line-height floor, where Phase 8's pass did not reach
 *
 * Phase 8 raised headings and body text. A public-page sweep at six widths
 * (2026-08-06) found three places still under the 1.5 floor in Persian, all of
 * them at every width, because the rule that sets them is more specific than
 * the floor:
 *
 *   - the hero heading, `.text-container h1` / `h2.ah-headline`, at
 *     `line-height: 1em` on a 70px face. One line of Latin display type is
 *     fine at 1em; Persian hangs descenders below the baseline, so they meet
 *     the line below as soon as the heading wraps — which it does on a phone.
 *     1.25 is the smallest value that separates them without turning a display
 *     heading into a paragraph.
 *   - `.fs-12` and its neighbours, which the theme pairs with a 15px line box
 *     (1.25), and `.fs-14` at 1.4 — the register wizard's step labels.
 *
 * Controls are excluded. A button, badge or tab sizes itself from its line
 * box, so raising it there changes the control's height rather than its
 * legibility, and those are single short words that were never at risk.
 * ==========================================================================*/

/* The theme writes this as `#main .text-container h1`, so the ID has to be
 * carried here too — without it the override loses on specificity and the
 * measured line-height stays at 1.00. */
body.rtl #main .text-container h1,
body.rtl #main .text-container h2.ah-headline,
[dir="rtl"] #main .text-container h1,
[dir="rtl"] #main .text-container h2.ah-headline {
  line-height: 1.25;
}

body.rtl .fs-11:not(.btn):not(.badge):not(.nav-link),
body.rtl .fs-12:not(.btn):not(.badge):not(.nav-link),
body.rtl .fs-13:not(.btn):not(.badge):not(.nav-link),
body.rtl .fs-14:not(.btn):not(.badge):not(.nav-link),
[dir="rtl"] .fs-11:not(.btn):not(.badge):not(.nav-link),
[dir="rtl"] .fs-12:not(.btn):not(.badge):not(.nav-link),
[dir="rtl"] .fs-13:not(.btn):not(.badge):not(.nav-link),
[dir="rtl"] .fs-14:not(.btn):not(.badge):not(.nav-link) {
  line-height: 1.6;
}

body.rtl .btn .fs-11, body.rtl .btn .fs-12,
body.rtl .btn .fs-13, body.rtl .btn .fs-14,
body.rtl .badge .fs-11, body.rtl .badge .fs-12,
[dir="rtl"] .btn .fs-11, [dir="rtl"] .btn .fs-12,
[dir="rtl"] .btn .fs-13, [dir="rtl"] .btn .fs-14 {
  line-height: inherit;
}


/* ==========================================================================
 * 16. The language menu hangs off the phone, in both locales
 *
 * Measured on `/` and `/fa` at 360 and 414 (2026-08-06), after opening the
 * navbar and then the language switcher:
 *
 *     EN  menu 305..433  viewport 360  → 73px past the right edge
 *     FA  menu -73..55   viewport 360  → 73px past the left edge
 *
 * The theme pins the menu with `.header-languages .dropdown-menu.show
 * { left: 0 !important }` below 768px, which positions it from its toggle's
 * leading edge. That works when the toggle sits near the leading edge of a
 * wide header; on a phone the toggle is the last item in the bar, so a 128px
 * menu hung from it lands outside. The RTL mirror flips the same rule to
 * `right: 0`, producing the exact mirror of the bug.
 *
 * Aligning the menu's near edge to the toggle's *same* edge is the standard
 * answer, and here it is also sufficient: the toggle is against the trailing
 * viewport edge, so the menu opens inward. The page is `overflow-x: clip`, so
 * the overflowing part was not merely off-screen — it was unreachable.
 * ==========================================================================*/

@media (max-width: 768px) {
  .header-languages .dropdown-menu.show {
    left: auto !important;
    right: 0 !important;
  }

  body.rtl .header-languages .dropdown-menu.show,
  [dir="rtl"] .header-languages .dropdown-menu.show {
    left: 0 !important;
    right: auto !important;
  }
}


/* ==========================================================================
 * 17. No logo inside the sidebar drawer on a phone
 *
 * The theme parks the sidebar's brand block outright below 768px:
 *
 *     @media (max-width: 767px) { .app-sidebar__logo { display: none } }
 *
 * On a desktop that block is the fixed 270px header strip above the menu, and
 * hiding it on a phone makes sense for the theme's own layout — the top bar
 * carries the brand there. It stops making sense once the drawer is the app's
 * main navigation, which is what it is in the installed app: the menu opens
 * with no logo at all, so nothing in the drawer says whose app it is.
 *
 * Brought back as a normal block at the top of the drawer rather than as the
 * desktop's fixed strip: `position: fixed` with `width: 270px` would sit over
 * the page instead of scrolling with the menu it belongs to.
 *
 * Only the full logo is shown. Below 768px the theme's own rule hiding
 * `.mobile-logo` (the collapsed mark) is itself inside a `min-width: 768px`
 * query, so without the line below both images would render, one under the
 * other.
 * ==========================================================================*/

@media (max-width: 767.98px) {
  .app-sidebar .app-sidebar__logo,
  .app-sidebar__logo {
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    position: static;
    width: 100%;
    height: auto;
    padding: 14px 16px;
    text-align: start;
    border: 0;
    border-bottom: 1px solid rgba(120, 130, 160, 0.18);
  }

  .app-sidebar__logo .header-brand {
    display: inline-flex;
    align-items: center;
    min-width: 0;
  }

  .app-sidebar__logo .header-brand-img.mobile-logo {
    display: none;
  }

  .app-sidebar__logo .header-brand-img.desktop-lgo {
    display: block;
    max-height: 34px;
    width: auto;
    margin: 0;
  }
}


/* ==========================================================================
 * 18. `fa-sharp` renders as the classic style
 *
 * The templates section asks for the Sharp cut on its badges:
 *
 *     <i class="fa-sharp fa-solid fa-crown"></i>      (frontend/templates)
 *
 * and the Sharp webfonts are on disk under the theme's fontawesome directory.
 * What is missing is the stylesheet that joins the two: the theme's icons.css
 * imports fontawesome, brands, regular and solid only, and none of those four
 * declares the Sharp family or an @font-face for it. `.fa-sharp` therefore
 * matches no font-family rule, `.fa-solid` supplies the classic one, and every
 * badge quietly draws in the wrong cut.
 *
 * Not blank — the classic glyph exists for all of them — which is why it has
 * gone unnoticed; it is a wrong-typeface bug, not a missing-icon one.
 *
 * Font Awesome ships a sharp-solid.css for exactly this, but it is not in this
 * copy, so the two declarations it would contribute are inlined here. Weight
 * 900 is the only Sharp weight licensed in this build (fa-sharp-solid-900),
 * so `fa-sharp fa-light` and friends deliberately stay on the classic family
 * rather than falling back to a font that is not there.
 *
 * The URL is theme-relative and hard-codes `default`: this is a stylesheet, so
 * it cannot ask which theme is active. It resolves against this file's own
 * published location, public/extensions/ui-fixes/.
 * ==========================================================================*/

@font-face {
  font-family: "Font Awesome 6 Sharp";
  font-style: normal;
  font-weight: 900;
  font-display: block;
  src: url("../../themes/default/icons/fontawesome/webfonts/fa-sharp-solid-900.woff2") format("woff2"),
       url("../../themes/default/icons/fontawesome/webfonts/fa-sharp-solid-900.ttf") format("truetype");
}

.fa-sharp.fa-solid,
.fa-sharp.fas,
.fass {
  font-family: "Font Awesome 6 Sharp";
  font-weight: 900;
}
