/* ══════════════════════════════════════════════════════════════════════════
   ANUPET ACADEMY — portal (admin + trainee)
   Shares the marketing site's tokens; adds the shell, tables and forms.
   ══════════════════════════════════════════════════════════════════════════ */

@font-face{font-family:'Azonix';src:url('../fonts/azonix.woff2') format('woff2');font-display:swap}
@font-face{font-family:'beIN';src:url('../fonts/bein.woff2') format('woff2');font-display:swap}

:root{
  color-scheme:light;
  --navy:#00428d; --deep:#003366; --sapphire:#0f52ba; --azure:#1466e0;
  --sky:#58b0f5; --orange:#ff6b35; --green:#0e9f6e; --red:#d33;
  --bg:#f1f3f7; --bg2:#fff; --bg3:#e7eaf1;
  --ink:#081426; --ink-rgb:8,20,38; --mut:#566880;
  --line:rgba(8,20,38,.10); --line2:rgba(8,20,38,.18);
  --shadow:0 14px 36px rgba(8,20,38,.08);
  --ff-x:'Azonix','Inter Tight',sans-serif;
  --ff-a:'IBM Plex Sans Arabic','Inter Tight',sans-serif;
  --ff-b:'Inter','IBM Plex Sans Arabic',sans-serif;
  /* 'IBM Plex Sans Arabic' sits AFTER 'Inter Tight' so every Latin glyph a
     code, a date or a figure needs still comes from Inter Tight — the stack
     is unchanged for "ANP-0002". It is here at all because .mono/.kpi b/.num
     also carry Arabic prose (the no-data fallbacks), and without an Arabic
     face those fell through to Consolas, which does not SHAPE Arabic: the
     letters rendered isolated and evenly spaced instead of joined. */
  --ff-m:'Inter Tight','IBM Plex Sans Arabic',ui-monospace,monospace; /* --ff-m is the FIGURE face (tabular numbers, codes), deliberately proportional — NOT for code listings; code panes declare their own true-mono stack (see lms-trainee360.css --tf-code-font). */
  --ease:cubic-bezier(.16,1,.3,1);
  --pad:clamp(16px,3vw,40px);

  /* ── semantic layer (D-029) ───────────────────────────────────────────
     A vocabulary ON TOP of the 25 tokens above, not a replacement — every
     name below aliases an existing custom property (or a fixed shade of
     one) so the 24 lms-*.css files and 80+ views that reference --bg/--ink/
     --navy/etc. directly keep working unchanged. New code and the sweep
     below reach for these instead of a raw hex, and reach for these
     instead of the raw physical names, so a surface/text/state change is
     one edit in one place rather than a grep across 24 files. */
  --surface-0:var(--bg);         /* page background */
  --surface-1:var(--bg2);        /* card / panel */
  --surface-2:var(--bg3);        /* raised / hovered row / active pill rest-state */
  --text-strong:var(--ink);      /* headings, the one figure in a KPI */
  --text:rgba(var(--ink-rgb),.82); /* body copy — one tier softer than a heading, still readable */
  --text-muted:var(--mut);
  --border:var(--line);
  --border-strong:var(--line2);
  --brand:var(--navy);
  --brand-soft:rgba(0,66,141,.09);
  /* --brand-ink: the brand colour used as TEXT or as an icon stroke on a
     page/soft ground — never as a fill. It exists because --brand does two
     jobs that pull in opposite directions once the theme flips: it is also
     the FILLED surface (.btn--pri, the sidebar pill, .lms-navlink.on) that
     carries #fff on top, so it has to stay dark enough for white ink, and
     on the near-black dark ground that same value is then too dark to read
     AS ink. Measured (fix-chrome r4): the breadcrumb, .crumb, is 11px
     var(--azure) on var(--bg) and scores 3.85:1 in the dark theme, under
     the 4.5:1 an 11px line needs — the one label that says where you are
     was the faintest text on the page. In light it stays exactly what it
     was; in dark it lifts to --sky, which is 8.6:1 on --bg and 7.0:1 on
     --brand-soft over it, while --brand keeps its white-ink contrast. */
  --brand-ink:var(--azure);
  /* --brand-on-soft: the SECOND ink token, and a separate one on purpose —
     it is brand ink on `--brand-soft`, not on the page. The two grounds pull
     the light value apart: --brand-ink is the deliberately lighter blue the
     breadcrumb has always been (4.7:1 on --bg, right); that same azure on
     the light --brand-soft tint measures 4.49:1, i.e. it would FAIL the very
     bar this batch is enforcing. So the tint's ink stays exactly what
     `color:var(--brand)` already resolved to in light — a byte-identical
     light theme — and lifts to --sky in dark, where the pair
     `background:var(--brand-soft); color:var(--brand)` measured 3.14:1 on
     every screen that uses it. */
  --brand-on-soft:var(--navy);
  --accent:var(--orange);
  /* state colors are semantic (ok/warn/danger/info) and deliberately
     SEPARATE from --accent (the orange brand highlight) — a warning tag
     must not shift meaning if the brand accent ever changes. The *-soft
     pair is a tinted background; the bare name is the ink color used as
     text on that background or as an icon/border stroke. Every lms-*.css
     file that hand-rolled its own "a green"/"a red" (nine different reds
     were found in the sweep) collapses onto these four pairs. */
  --ok:#0b7d57; --ok-soft:rgba(14,159,110,.13);
  --warn:#a04a17; --warn-soft:rgba(255,107,53,.14);
  --danger:var(--red); --danger-soft:rgba(211,51,51,.12);
  --info:var(--navy); --info-soft:rgba(0,66,141,.1);
  --focus-ring:0 0 0 2px var(--sky);
  /* The one "×" glyph the platform paints as a MASK rather than as text —
     used to replace WebKit's own un-themeable search-cancel button, and
     available to any other control that needs a clear affordance without
     shipping a font character that renders differently under the Arabic and
     Latin faces this platform loads. */
  --x-glyph:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='m6 6 12 12M18 6 6 18'/%3E%3C/svg%3E");
  --r-sm:10px; --r-md:14px; --r-lg:20px;
  --shadow-1:var(--shadow);
  --shadow-2:0 24px 64px rgba(var(--ink-rgb),.18);
  --scrim:rgba(8,20,38,.5);         /* the one dimming veil every backdrop shares (wave2 gate) */

  /* ── z-index ladder (D1) ──────────────────────────────────────────────
     Before this scale every overlay surface picked its own number and two
     of them collided by accident: the bell panel shipped at 61 and was
     therefore painted OVER by the admin sidebar at 70 (the panel opened
     behind the rail), the bell backdrop tied the sticky header at 60, and
     the PWA strip tied both. Numbers are spaced so a future surface can
     slot between two tiers without renumbering the others, and the ORDER
     is the contract: chrome < drawer scrim < sidebar < bell < search <
     modal. Every layered rule in the LMS stylesheets must reference a name
     here rather than a literal, so the ordering is readable in one place. */
  --z-header:60;    /* .abar, the sticky topbar */
  --z-strip:62;     /* .pwa-strip, dismissible install chrome */
  --z-backdrop:68;  /* .lms-nav__backdrop, the mobile drawer scrim */
  --z-sidebar:70;   /* .lms-sidebar (desktop rail AND mobile drawer) */
  --z-bell:72;      /* .cm-bell__backdrop; the panel itself is +1 */
  --z-overlay:80;   /* .gsearch__overlay, the global search */
  --z-modal:84;     /* .tmodal__backdrop; the dialog itself is +1 */
}
html[data-theme="dark"]{
  color-scheme:dark;
  --bg:#04070e; --bg2:#0a1120; --bg3:#111c30;
  --ink:#eaf2fc; --ink-rgb:234,242,252; --mut:#93aac9;
  --line:rgba(234,242,252,.11); --line2:rgba(234,242,252,.2);
  --shadow:0 14px 36px rgba(0,0,0,.5);

  /* semantic layer, dark counterparts — every rule above that resolves to
     one of these names flips automatically; nothing outside this block
     needs its own dark override for the semantic tier. */
  /* --brand had no dark override at all, so it stayed var(--navy) #00428d
     while its own --brand-soft partner flipped to a sky tint — the pair
     that exists to be used together (`background:var(--brand-soft);
     color:var(--brand)`) resolved to navy ink on a sky wash over a
     near-black page. var(--azure) rather than var(--sky) because --brand
     is also a FILLED surface (the sidebar pill, .btn--pri, .lms-navlink.on)
     that carries #fff text: azure keeps ~5:1 against white where sky
     (#58b0f5) drops under 3:1 and would make every active nav item
     unreadable. Same blue family as --brand-soft, one step lighter than
     navy — a lightened navy, not a new hue. */
  --brand:var(--azure);
  --brand-soft:rgba(88,176,245,.15);
  /* the ink half of the pair — see the note beside --brand-ink on :root.
     --brand stays azure because it is also a filled surface under white
     text; the same azure AS text on this ground is 3.85:1, so brand-coloured
     TEXT lifts one step to --sky (8.6:1 on --bg, 7.0:1 on --brand-soft). */
  --brand-ink:var(--sky);
  /* …and the tint's ink, same lift for the same reason: azure ON the dark
     --brand-soft wash is 3.14:1 (measured on .ttag--answered, .staffwho__av,
     .subjectchip and the file button), --sky is 7.0:1 over --bg and 6.3:1
     over --bg2. */
  --brand-on-soft:var(--sky);
  --ok:#39d39e; --ok-soft:rgba(57,211,158,.16);
  /* dark --warn matches var(--orange) exactly — lms-auth.css and
     lms-account.css each independently wrote this same override
     (html[data-theme="dark"] .note--warn / .acct-result--warn {color:
     var(--orange)}) for the identical warn-soft-background pattern before
     the token existed; folding their agreed value in here instead of
     inventing a new shade keeps the dark sweep a formalization, not a
     visible colour change. */
  --warn:var(--orange); --warn-soft:rgba(255,107,53,.2);
  /* dark --danger is deliberately lighter than the light-mode var(--red)
     (#d33) it inherits from, matching the same lighten-for-dark-legibility
     treatment app.css's own .tag--ok already applies to green (#0b7d57 ->
     #39d39e) — the state palette had that treatment for ok/info but never
     for danger, so every dark-mode danger tag today renders the light-mode
     red at low contrast against the near-black background. Declared fix,
     not a silent drift. */
  --danger:#ff7a7a; --danger-soft:rgba(255,122,122,.16);
  --info:var(--sky); --info-soft:rgba(88,176,245,.15);
  --shadow-2:0 24px 64px rgba(0,0,0,.6);
  --scrim:rgba(0,0,0,.62);
}

/* --chev is the select arrow's own colour (see the select block below).
   Registering it as a real <color> is what lets it TRANSITION between the
   rest / hover / focus / invalid states instead of snapping; an engine that
   does not support @property simply snaps, which is the behaviour that
   shipped before this rule existed. inherits:false keeps a select's arrow
   colour from leaking onto nested content. */
@property --chev{syntax:'<color>';inherits:false;initial-value:#566880}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{background:var(--bg);color:var(--ink);font-family:var(--ff-b);font-size:16px;
  line-height:1.7;-webkit-font-smoothing:antialiased;min-height:100vh;
  display:flex;flex-direction:column}
img,svg{display:block;max-width:100%}
.ico{width:1em;height:1em;flex:0 0 auto}
a{color:inherit;text-decoration:none}
button,input,textarea,select{font:inherit;color:inherit}
:where(h1,h2,h3,h4){font-family:var(--ff-a);font-weight:600;line-height:1.35;letter-spacing:-.01em}
table{border-collapse:collapse;width:100%}

/* ═══════════════════════════════════════════════════════════════ shell ══ */
.abar{background:var(--bg2);border-block-end:1px solid var(--line);position:sticky;
  inset-block-start:0;z-index:var(--z-header)}
.abar__in{max-width:1600px;margin-inline:auto;padding:12px var(--pad);
  display:flex;align-items:center;gap:clamp(10px,1.6vw,26px)}
.abar__brand{display:flex;align-items:center;gap:11px;flex-shrink:0}
.abar__brand .m{width:36px;color:var(--brand)}
.abar__brand b{font-family:var(--ff-x);font-size:15px;letter-spacing:.1em;display:block;line-height:1.1}
.abar__brand span{font-family:var(--ff-x);font-size:8px;letter-spacing:.3em;color:var(--azure)}
/* .anav (the trainee topbar link strip) is DELETED, not restyled — D-080
   moved the trainee onto the shared sidebar rail and the layout no longer
   renders the strip. The filled-pill `#fff` precedent its .on rule used to
   set now lives in lms-nav.css's .lms-sidebar__link.on. */
.abar__end{display:flex;align-items:center;gap:8px;flex-shrink:0}
.who{font-size:13px;color:var(--mut);text-align:end;line-height:1.35}
.who b{display:block;color:var(--ink);font-size:14px}

.iconbtn{width:40px;height:40px;display:grid;place-items:center;border-radius:999px;cursor:pointer;
  background:transparent;color:var(--mut);box-shadow:inset 0 0 0 1px var(--line);border:0;
  transition:.25s}
.iconbtn:hover{color:var(--brand);box-shadow:inset 0 0 0 1px var(--line2)}
.iconbtn .ico{width:18px;height:18px}

main{flex:1;max-width:1600px;width:100%;margin-inline:auto;padding:clamp(22px,3vw,42px) var(--pad)}
.afoot{border-block-start:1px solid var(--line);background:var(--bg2);font-size:13px;color:var(--mut)}
.afoot div{max-width:1600px;margin-inline:auto;padding:16px var(--pad);
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap}

/* ══════════════════════════════════════════════════════════════ pieces ══ */
.phead{display:flex;align-items:flex-end;justify-content:space-between;gap:18px;flex-wrap:wrap;
  margin-block-end:clamp(18px,2.4vw,30px)}
.phead h1{font-size:clamp(1.5rem,2.6vw,2.2rem)}
.phead p{color:var(--mut);font-size:.96rem;margin-block-start:5px}
/* (fix-chrome r4) --brand-ink, not the raw --azure: this is 11px text on the
   page ground and the raw token measured 3.85:1 in the dark theme. */
.crumb{font-family:var(--ff-m);font-size:11px;letter-spacing:.14em;color:var(--brand-ink);
  display:block;margin-block-end:8px}
/* the display:block above outranks the UA [hidden] rule — the convert flow
   hides its «Step 1 of 2» crumb for a free seat (no plan step). */
.crumb[hidden]{display:none}

/* `min-width:0` on the card and on every grid child, plus minmax(0,1fr)
   tracks instead of a bare 1fr, is the P2 fix: a flex/grid item's default
   min-width is `auto`, i.e. "never shrink below your content". A `.tbl`
   wrapper nested inside one therefore never got the chance to scroll — its
   `table{min-width:640px}` child pushed the card, the column and finally
   the document past a 375px viewport (measured docW 736 on /admin) instead
   of scrolling inside its own box. The scroll container only works once its
   ancestors are allowed to be narrower than their content. */
.card{background:var(--bg2);border-radius:20px;box-shadow:inset 0 0 0 1px var(--line);
  padding:clamp(18px,2vw,28px);min-width:0}
.card + .card{margin-block-start:16px}
.card h2,.card h3{font-size:1.15rem;margin-block-end:14px}
.grid{display:grid;gap:16px}
.grid > *{min-width:0}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
.split{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:16px;align-items:start}
.split > *{min-width:0}

/* The KPI card is the convergence target for the four bespoke stat-card
   families the inventory found (.sys-stat, .pay-kpis, .imp-stats,
   .lms-dash__tile) — the --ok/--warn/--danger modifiers below exist so a
   screen that needs a coloured accent (an overdue total, a failed import
   row) can express it here instead of forking the component again. */
.kpi{background:var(--bg2);border-radius:20px;box-shadow:inset 0 0 0 1px var(--line);
  padding:22px;display:flex;gap:16px;align-items:center;min-width:0}
/* (fix-chrome r4) --brand-on-soft: identical in light, and the 22px glyph
   goes from 3.14:1 to 7:1 on the dark wash. */
.kpi__i{width:46px;height:46px;border-radius:14px;display:grid;place-items:center;flex-shrink:0;
  background:var(--brand-soft);color:var(--brand-on-soft)}
.kpi__i .ico{width:22px;height:22px}
.kpi b{display:block;font-family:var(--ff-m);font-size:1.9rem;line-height:1;color:var(--ink)}
.kpi span{font-size:13px;color:var(--mut)}
.kpi--ok .kpi__i{background:var(--ok-soft);color:var(--ok)}
.kpi--warn .kpi__i{background:var(--warn-soft);color:var(--warn)}
.kpi--danger .kpi__i{background:var(--danger-soft);color:var(--danger)}
.kpi--ok b{color:var(--ok)}
.kpi--warn b{color:var(--warn)}
.kpi--danger b{color:var(--danger)}

.tag{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;
  font-size:12.5px;font-weight:600;background:var(--bg3);color:var(--mut)}
.tag--ok{background:var(--ok-soft);color:var(--ok)}
.tag--warn{background:var(--warn-soft);color:var(--warn)}
.tag--info{background:var(--info-soft);color:var(--info)}
.tag--off{background:var(--danger-soft);color:var(--danger)}
.mono{font-family:var(--ff-m);letter-spacing:.04em}

/* tables */
.tbl{overflow-x:auto;border-radius:18px;box-shadow:inset 0 0 0 1px var(--line);background:var(--bg2)}
.tbl table{min-width:640px}
.tbl th,.tbl td{padding:14px 16px;text-align:start;border-block-end:1px solid var(--line);
  font-size:.94rem;vertical-align:middle}
.tbl th{font-size:12px;letter-spacing:.06em;color:var(--mut);font-weight:700;
  background:var(--bg3);white-space:nowrap}
.tbl tr:last-child td{border-block-end:0}
.tbl tbody tr:hover{background:var(--bg3)}
.tbl .num{font-family:var(--ff-m)}

/* forms */
.f{display:grid;gap:13px}
.f label{display:block;font-size:13px;color:var(--mut);margin-block-end:6px;font-weight:600}
.f input[type=text],.f input[type=url],.f input[type=email],.f input[type=tel],.f input[type=password],
.f input[type=number],.f input[type=date],.f select,.f textarea{
  width:100%;padding:12px 15px;border-radius:13px;background:var(--bg);border:0;
  box-shadow:inset 0 0 0 1px var(--line);font-size:.97rem;outline:none;transition:box-shadow .25s}
.f textarea{min-height:110px;resize:vertical;line-height:1.7}
.f input:focus,.f select:focus,.f textarea:focus{box-shadow:inset 0 0 0 2px var(--brand)}

/* ── native control parity (P6, re-cut by design-system) ─────────────────
   `<select>` and `<input type=date>` were the two controls that opted out
   of the design system: a browser-default select renders ~24px tall beside
   40px buttons on every admin filter bar, and the old two-gradient chevron
   reserved no inline-end padding, so a long option label ran straight into
   the arrow ("AFE-0❰" on /admin/exports). One chevron, painted at the
   inline END of the field with matching reserved padding, replaced it.

   WHAT CHANGED IN THIS PASS. That fix baked the arrow's stroke colour into
   an inline-SVG data URI, and a data URI cannot read a custom property — so
   the dark theme needed a whole second copy of the rule, and the chevron
   could not answer hover, focus, or the invalid state at all: it sat at the
   light-mode --mut grey whatever the field underneath it was doing. The
   arrow is now DRAWN IN CSS, as two diagonal bars cut out of a pair of
   linear-gradients, because a gradient — unlike a data URI — resolves
   `var()`. That single change buys every state for the price of redefining
   one property:

     --chev  the arrow's own colour, independent of the select's TEXT colour
             (tinting `color` would drag the closed control's label along
             with it, which is why currentColor is not used directly here).

   The public site's own select (site.css, `.field:has(select)::after`)
   paints its chevron as a mask over currentColor on a pseudo-element. That
   works there because every public select sits alone inside a `.field`
   wrapper the pseudo-element can be anchored to. The platform's selects sit
   in `.f` wrappers that also hold a <label> above and — since this wave —
   an error slot below, so a wrapper pseudo-element has no reliable line to
   sit on. Same design, same tokens, same behaviour under RTL/dark/hover/
   focus; the mechanism differs because the markup does.

   GEOMETRY. Each layer is a 6×6 tile carrying one 2px-thick diagonal bar.
   Layer 1 is "\", layer 2 is "/", and the two tiles are positioned to abut,
   so together they read as a 12×6 "v". The RTL branch mirrors the offsets
   AND swaps which tile is nearer the edge — a "v" is symmetric, so mirroring
   the offsets alone would build a "^". */
/* appearance:none is deliberately NOT applied to input[type=date]: it
   strips the calendar button in WebKit, leaving a date field with no way to
   open a picker. The date field is brought into line by height and border
   tokens only. */
.f select,.fbar select,.lms-field select{appearance:none;-webkit-appearance:none;cursor:pointer}
.f select,.fbar select,.lms-field select{
  --chev:var(--text-muted);
  background-image:
    linear-gradient(45deg,transparent calc(50% - 1px),var(--chev) calc(50% - 1px),var(--chev) calc(50% + 1px),transparent calc(50% + 1px)),
    linear-gradient(-45deg,transparent calc(50% - 1px),var(--chev) calc(50% - 1px),var(--chev) calc(50% + 1px),transparent calc(50% + 1px));
  background-repeat:no-repeat;background-size:6px 6px;
  background-position:right 20px center,right 14px center;
  padding-inline-end:40px;
  transition:box-shadow .25s,--chev .2s}
[dir="rtl"] .f select,[dir="rtl"] .fbar select,[dir="rtl"] .lms-field select{
  background-position:left 14px center,left 20px center}
/* Hover and focus now REACH the chevron, in both themes, because --chev is
   an alias and both sides of the alias flip with the theme. */
.f select:hover,.fbar select:hover,.lms-field select:hover{--chev:var(--text-strong)}
.f select:focus,.fbar select:focus,.lms-field select:focus{--chev:var(--brand)}
.f select:disabled,.fbar select:disabled,.lms-field select:disabled{--chev:var(--text-muted);opacity:.55;cursor:not-allowed}
/* The date field's own calendar button is a UA shadow-DOM element: it
   cannot inherit currentColor, so in the dark theme it paints a black glyph
   on a near-black field and disappears. invert() is the only lever a
   no-build stylesheet has on it. */
html[data-theme="dark"] .f input[type=date]::-webkit-calendar-picker-indicator,
html[data-theme="dark"] .fbar input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.85)}

.f .row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:13px}
.f .row3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:13px}

/* Compact variant for toolbar filter bars, where a 46px-tall field stacked
   next to a .btn--sm reads as a form rather than a toolbar. Height, not
   padding, is the constraint: 38px lines up with .btn--sm's own box. */
.f--compact input[type=text],.f--compact input[type=email],.f--compact input[type=tel],
.f--compact input[type=password],.f--compact input[type=number],.f--compact input[type=date],
.f--compact select,
.fbar input[type=text],.fbar input[type=url],.fbar input[type=email],.fbar input[type=tel],
.fbar input[type=number],.fbar input[type=date],.fbar input[type=search],.fbar select{
  /* background-COLOR, never the shorthand: the shorthand resets the select
     chevron background-image declared on the base select rule above. */
  width:100%;min-height:38px;padding:7px 13px;border-radius:var(--r-sm);background-color:var(--bg);
  border:0;box-shadow:inset 0 0 0 1px var(--line);font-size:.92rem;outline:none;
  transition:box-shadow .25s}
.fbar input:focus,.fbar select:focus{box-shadow:inset 0 0 0 2px var(--brand)}
.fbar select{padding-inline-end:38px}

/* datetime-local joins the .f kit beside input[type=date] (moved here from
   lms-comms.css at the wave2 gate — a platform-wide form primitive lives in
   app.css, not in the one area file that first needed it). The
   picker-indicator invert matches the date branch: the calendar glyph is UA
   shadow-DOM and cannot inherit currentColor, so dark theme needs the filter. */
.f input[type="datetime-local"]{
  width:100%;padding:12px 15px;border-radius:13px;background:var(--bg);border:0;
  box-shadow:inset 0 0 0 1px var(--line);font-size:.97rem;outline:none;
  transition:box-shadow .25s var(--ease)}
.f input[type="datetime-local"]:focus{box-shadow:inset 0 0 0 2px var(--brand)}
html[data-theme="dark"] .f input[type="datetime-local"]::-webkit-calendar-picker-indicator{filter:invert(.85)}

.check{display:inline-flex;align-items:center;gap:9px;font-size:.94rem;cursor:pointer}
.check input,.fbar input[type=checkbox]{width:18px;height:18px;accent-color:var(--brand);cursor:pointer}

/* ── the sweep: every OTHER native control ───────────────────────────────
   The kit above dressed the controls the platform reaches for most — text,
   email, password, number, date, datetime-local, select, textarea — and
   left the rest wearing whatever the browser drew. The audit for this wave
   found six of them still undesigned on real screens, and one of those (the
   focus ring) on EVERY screen. Each block below is one of those six; none
   of them replaces a native control with a JavaScript imitation, because a
   native checkbox, a native date picker and a native file dialog are the
   accessible, offline, keyboard-complete versions and nothing here would
   beat them.

   1 · CHECKBOX + RADIO, everywhere and not only inside `.check`. The
   accent-color property is what paints the checked box in the brand blue
   under both themes with a single declaration; `color-scheme` is what stops
   an UNCHECKED box from rendering as a white chip on a near-black form. */
input[type=checkbox],input[type=radio]{
  width:17px;height:17px;flex:0 0 auto;accent-color:var(--brand);
  color-scheme:light dark;cursor:pointer}
input[type=checkbox]:disabled,input[type=radio]:disabled{cursor:not-allowed;opacity:.55}

/* 2 · A RAW <input type=file>. The platform's answer is <x-upload> (D-074)
   and every remaining raw file input was converted to it in this wave — but
   the rule stays, because the browser's own "Choose File" button is the one
   piece of UI in this product that reappears the moment someone adds a file
   field without reaching for the component, and it must not land on a
   screen looking like Windows 98 while we wait to notice. */
input[type=file]{
  width:100%;padding:9px 12px;border-radius:var(--r-sm);background:var(--surface-0);
  box-shadow:inset 0 0 0 1px var(--border);font-size:.9rem;color:var(--text-muted);cursor:pointer}
input[type=file]::file-selector-button{
  margin-inline-end:12px;padding:7px 15px;border:0;border-radius:999px;cursor:pointer;
  /* (fix-chrome r4) --brand-on-soft — 13.8px bold is NOT "large text", so
     this label owes 4.5:1 and was reading 3.14:1 in the dark theme. */
  background:var(--brand-soft);color:var(--brand-on-soft);font:inherit;font-weight:700;font-size:.86rem;
  transition:.22s var(--ease)}
input[type=file]::file-selector-button:hover{background:var(--brand);color:#fff}

/* 3 · NUMBER SPINNERS, dropped platform-wide. <x-field> never emits
   type=number for an integer rule precisely because of these buttons; the
   handful of hand-authored number inputs that remain (a payment amount, an
   attendance percentage) get the same treatment rather than a second
   appearance. They are also the control whose position RTL engines disagree
   about, so the field's inline-end changed shape by browser. The min/max
   attributes still constrain the value exactly as before. */
input[type=number]{-moz-appearance:textfield;appearance:textfield}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;appearance:none;margin:0}

/* 4 · THE DATE/TIME PICKER BUTTON. It is UA shadow DOM and cannot inherit
   currentColor — the dark-theme invert already lived here for `date` and
   `datetime-local`; `time` and `month` were missing, and none of the four
   showed a pointer cursor, so the one affordance that says "this opens a
   picker" was absent. */
input[type=date]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator,
input[type=month]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.65}
input[type=date]:hover::-webkit-calendar-picker-indicator,
input[type=time]:hover::-webkit-calendar-picker-indicator,
input[type=month]:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator{opacity:1}
html[data-theme="dark"] input[type=time]::-webkit-calendar-picker-indicator,
html[data-theme="dark"] input[type=month]::-webkit-calendar-picker-indicator{filter:invert(.85)}
/* `time` and `month` never joined the .f kit's box treatment either, so they
   rendered at the browser's own height beside 46px siblings in the same row. */
.f input[type=time],.f input[type=month]{
  width:100%;padding:12px 15px;border-radius:13px;background:var(--bg);border:0;
  box-shadow:inset 0 0 0 1px var(--border);font-size:.97rem;outline:none;
  transition:box-shadow .25s var(--ease)}
.f input[type=time]:focus,.f input[type=month]:focus{box-shadow:inset 0 0 0 2px var(--brand)}

/* 5 · SEARCH. WebKit paints its own round "x" that ignores the theme, and
   the field itself was only in the `.fbar` list — a search box in a `.f`
   form rendered as an undressed native control. */
input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none;
  width:14px;height:14px;cursor:pointer;background:currentColor;opacity:.45;
  -webkit-mask:var(--x-glyph) center/12px 12px no-repeat;mask:var(--x-glyph) center/12px 12px no-repeat}
input[type=search]::-webkit-search-cancel-button:hover{opacity:.9}
.f input[type=search]{
  width:100%;padding:12px 15px;border-radius:13px;background:var(--bg);border:0;
  box-shadow:inset 0 0 0 1px var(--border);font-size:.97rem;outline:none;
  transition:box-shadow .25s var(--ease)}
.f input[type=search]:focus{box-shadow:inset 0 0 0 2px var(--brand)}

/* 6 · RANGE and COLOR — the two controls with no styling anywhere in the
   product. The colour picker pair on the catalogue screens is a real
   <input type=color> beside a text field, and it rendered as a raw OS swatch
   with a 1px black frame. */
input[type=range]{width:100%;accent-color:var(--brand);cursor:pointer;background:transparent}
input[type=color]{
  inline-size:46px;block-size:38px;padding:3px;cursor:pointer;background:var(--surface-0);
  border:0;border-radius:var(--r-sm);box-shadow:inset 0 0 0 1px var(--border)}
input[type=color]::-webkit-color-swatch-wrapper{padding:0}
input[type=color]::-webkit-color-swatch{border:0;border-radius:7px}
input[type=color]::-moz-color-swatch{border:0;border-radius:7px}

/* 7 · THE BROWSER'S DEFAULT FOCUS RING, retired. Every control the kit
   styles sets `outline:none` and paints its own inset ring, but everything
   the kit does NOT style — a bare <button>, a link, a summary, a
   [contenteditable], a [tabindex] island — still showed the UA's own
   two-tone outline, which is invisible on the dark theme's near-black
   ground and reads as a rendering artefact on the light one.
   :focus-visible, never :focus, so a pointer click never leaves a ring
   behind; and the ring is painted with `outline`, never box-shadow, so it
   survives on elements whose box-shadow is already carrying a border. */
:focus-visible{outline:2px solid var(--sky);outline-offset:2px}
/* Controls that draw their own inset ring keep it and take no outline — the
   two together read as a double border. */
.f :is(input,select,textarea):focus-visible,
.fbar :is(input,select,textarea):focus-visible,
.lms-field :is(input,select,textarea):focus-visible{outline:none}

/* 8 · The resize grip is a native affordance worth keeping, but a textarea
   that can be dragged WIDER breaks every grid it sits in. */
textarea{resize:vertical}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;border:0;cursor:pointer;
  padding:12px 22px;border-radius:999px;font-weight:700;font-size:.95rem;transition:.28s var(--ease)}
.btn .ico{width:17px;height:17px}
.btn--pri{background:var(--brand);color:#fff}
.btn--pri:hover{background:var(--sapphire)}
/* #2a0c02 stays a literal on purpose: it is ink ON the fixed orange accent,
   which does not flip between themes, so a token would only add a level of
   indirection over a value that must not move. */
.btn--acc{background:var(--accent);color:#2a0c02}
.btn--acc:hover{filter:brightness(1.06)}
.btn--ghost{background:transparent;box-shadow:inset 0 0 0 1.5px var(--border-strong)}
.btn--ghost:hover{box-shadow:inset 0 0 0 1.5px var(--brand);color:var(--brand)}
.btn--danger{background:transparent;color:var(--danger);
  box-shadow:inset 0 0 0 1.5px color-mix(in srgb,var(--danger) 35%,transparent)}
.btn--danger:hover{background:color-mix(in srgb,var(--danger) 10%,transparent)}
/* D-074 — the FILLED danger weight, reserved for the confirming button of a
   destructive dialog (lmsConfirm) and for nothing that sits on an ordinary
   toolbar: outline .btn--danger stays the in-page treatment. */
.btn--danger-solid{background:var(--danger);color:#fff}
.btn--danger-solid:hover{background:color-mix(in srgb,var(--danger) 82%,#000 18%)}
.btn--sm{padding:8px 15px;font-size:.87rem}
.btn--block{width:100%}
.btns{display:flex;gap:9px;flex-wrap:wrap}

/* notices */
.note{padding:14px 18px;border-radius:14px;font-size:.95rem;margin-block-end:16px}
.note--ok{background:var(--ok-soft);color:var(--ok);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ok) 30%,transparent)}
.note--err{background:var(--danger-soft);color:var(--danger);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--danger) 30%,transparent)}
.note--info{background:var(--info-soft);color:var(--info);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--info) 22%,transparent)}
/* --warn / --warn-soft already flip per theme (dark = orange), so no
   separate dark rule. Before this, a .note--warn on any admin screen that
   loads neither lms-auth.css nor lms-ide.css rendered as bare text. */
.note--warn{background:var(--warn-soft);color:var(--warn);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--warn) 30%,transparent)}
.note b{font-family:var(--ff-m);letter-spacing:.05em}

/* progress */
.bar{height:9px;border-radius:999px;background:var(--bg3);overflow:hidden}
.bar i{display:block;height:100%;border-radius:999px;
  background:linear-gradient(90deg,var(--brand),var(--sky));transition:width .8s var(--ease)}
/* the second stop is a fixed tint of the accent rather than the old #ffb08a
   literal — mixed toward white so it stays the same peach in both themes,
   which is what the literal was doing implicitly */
.bar--acc i{background:linear-gradient(90deg,var(--accent),color-mix(in srgb,var(--accent) 58%,#fff))}

/* course cards in the trainee dashboard */
.ccard{background:var(--bg2);border-radius:22px;box-shadow:inset 0 0 0 1px var(--line);
  overflow:hidden;transition:box-shadow .3s,transform .4s var(--ease);display:block}
.ccard:hover{box-shadow:inset 0 0 0 1px var(--line2),var(--shadow);transform:translateY(-3px)}
.ccard__top{padding:22px 24px;border-block-end:1px solid var(--line);position:relative}
.ccard__top::before{content:'';position:absolute;inset-block-start:0;inset-inline-start:0;
  width:100%;height:3px;background:var(--accent,var(--navy))}
.ccard__n{font-family:var(--ff-m);font-size:12px;color:var(--accent,var(--navy))}
.ccard h3{font-size:1.2rem;margin-block:8px 4px}
.ccard__b{padding:20px 24px;display:grid;gap:14px}
.ccard__row{display:flex;justify-content:space-between;font-size:.9rem;color:var(--mut)}

/* module checklist */
.mlist{display:grid;gap:8px}
.mrow{display:flex;align-items:center;gap:14px;padding:13px 16px;border-radius:14px;
  background:var(--bg);box-shadow:inset 0 0 0 1px var(--line)}
.mrow.done{background:color-mix(in srgb,var(--ok) 8%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ok) 25%,transparent)}
.mrow__n{font-family:var(--ff-m);font-size:12px;color:var(--mut);min-width:26px}
.mrow__t{flex:1;font-weight:600;font-size:.97rem}
.mrow__h{font-family:var(--ff-m);font-size:11.5px;color:var(--mut)}
.mrow__topics{padding:0 16px 14px calc(16px + 40px);color:var(--mut);font-size:.88rem;
  display:grid;gap:5px}

/* material reader */
.reader{max-width:900px;margin-inline:auto}
.reader h1{font-size:clamp(1.5rem,3vw,2.2rem);margin-block-end:10px}
.prose{background:var(--bg2);border-radius:20px;box-shadow:inset 0 0 0 1px var(--line);
  padding:clamp(22px,3vw,44px);font-size:1.05rem;line-height:1.95;white-space:pre-wrap;
  word-wrap:break-word}
.prose a{color:var(--brand);text-decoration:underline}

/* login */
.auth{min-height:100vh;display:grid;place-items:center;padding:24px}
.auth__box{width:min(460px,100%);background:var(--bg2);border-radius:26px;
  box-shadow:inset 0 0 0 1px var(--line),var(--shadow);padding:clamp(26px,3.4vw,44px)}
.auth__mark{width:66px;color:var(--brand);margin-inline:auto;margin-block-end:22px}
.auth h1{font-size:1.5rem;text-align:center}
.auth p.sub{text-align:center;color:var(--mut);font-size:.94rem;margin-block:6px 24px}
.auth__back{display:block;text-align:center;margin-block-start:20px;font-size:.9rem;color:var(--mut)}

/* creds table after bulk create */
.creds{font-family:var(--ff-m);font-size:12.5px}

/* ═══════════════════════════════════════════ shared primitives (D1) ══
   Three components the inventory found re-implemented once per screen.
   Each is ADDITIVE — nothing that exists today is removed — so a Wave-2
   screen adopts them by swapping its own class for these, one screen at a
   time, instead of everything having to move at once. */

/* ── .fbar — the filter bar above a list ─────────────────────────────────
   Replaces six divergent implementations of one job (.audit-filters,
   .cohort-filters, .exp-form and three separate inline-styled <form> rows).
   Wrapping flex rather than a fixed grid because the field count differs
   per screen (1 on /admin/trainees, 4 on /admin/audit) and a grid would
   need a per-screen column count; the actions block is pushed to the
   inline end so the submit button lands in the same place on every list.
   Compact field sizing comes from the .fbar branches in the form kit above. */
/* Its own margin, for the same reason .pgn got one: a primitive always followed
   by the list it filters should not make every call site restate the gap. */
.fbar{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px;margin-block-end:16px}
.fbar__field{display:grid;gap:5px;min-width:0;flex:1 1 180px;max-width:100%}
.fbar__field > label{font-size:12.5px;color:var(--mut);font-weight:600}
.fbar__actions{display:flex;gap:8px;flex-wrap:wrap;margin-inline-start:auto}

/* ── .empty — the standard empty state ───────────────────────────────────
   Replaces the 32 `<div class="card"><p style="color:var(--mut)">` copies
   and the 6 `<td colspan=N style="color:var(--mut)">` copies. `.empty--row`
   is the in-table variant: same voice, no card chrome, because it renders
   inside a <td> that already has the table's border and background. */
.empty{display:grid;gap:8px;justify-items:center;text-align:center;
  padding:clamp(28px,5vw,56px) 20px;color:var(--mut);font-size:.95rem}
.empty__icon{width:44px;height:44px;border-radius:var(--r-md);display:grid;place-items:center;
  background:var(--surface-2);color:var(--text-muted)}
.empty__icon .ico{width:22px;height:22px}
.empty__title{font-size:1.02rem;font-weight:600;color:var(--text-strong)}
.empty--row{padding:26px 16px}

/* ── .pgn — the paginator ────────────────────────────────────────────────
   Consumed by resources/views/vendor/pagination/tailwind.blade.php, which
   overrides Laravel's default view for every ->links() call site at once.
   Before the override the app shipped the framework's Tailwind markup into
   a project with no Tailwind build: the `w-5 h-5` chevrons painted at
   ~600x420px and the labels rendered as the literal strings
   "pagination.previous" / "pagination.next". */
.pgn{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:6px;
  margin-block-start:18px}
.pgn__link,.pgn__gap{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-width:40px;min-height:40px;padding:0 12px;border-radius:var(--r-sm);
  font-size:.9rem;font-weight:600;color:var(--text-muted);
  box-shadow:inset 0 0 0 1px var(--border);transition:color .22s var(--ease),box-shadow .22s var(--ease)}
.pgn__link:hover{color:var(--text-strong);box-shadow:inset 0 0 0 1px var(--border-strong)}
.pgn__link:focus-visible{outline:none;box-shadow:var(--focus-ring)}
.pgn__link.is-current{background:var(--brand);color:#fff;box-shadow:none}
.pgn__link.is-disabled{color:var(--text-muted);opacity:.45;pointer-events:none}
.pgn__gap{box-shadow:none;padding:0 4px;min-width:0}
.pgn__ico{width:16px;height:16px;flex:0 0 auto}
/* One chevron glyph, mirrored by the writing direction instead of shipping
   two icons: "previous" points at the start edge, which is the RIGHT edge
   under dir="rtl". */
[dir="rtl"] .pgn__ico{transform:scaleX(-1)}
@media (prefers-reduced-motion:reduce){
  .pgn__link{transition:none}
}
@media (max-width:520px){
  /* On a phone the numbered window costs more width than it earns — the
     prev/next pair plus the current-page marker is the whole control. */
  .pgn__link--num:not(.is-current),.pgn__gap{display:none}
}

/* ── .nowrap-data (P8) ───────────────────────────────────────────────────
   For an atomic Latin datum inside Arabic prose: a trainee code, an ISO
   date, a time range (money uses lms-payments.css's `.money`, see there).
   `nowrap` stops "ANP-0008" breaking
   after the hyphen mid-cell; `direction:ltr` + `unicode-bidi:isolate` stop
   the bidi algorithm reordering "18:00 - 20:00" into "20:00 - 18:00" or
   dragging a trailing punctuation mark to the wrong end. Wave 2 applies it
   in the views; it is defined here so all of them apply the same one. */
.nowrap-data{white-space:nowrap;direction:ltr;unicode-bidi:isolate}

/* ── Arabic typography (P7) ──────────────────────────────────────────────
   Arabic is a cursive script: letter-spacing forces gaps BETWEEN joined
   letters, so "دفتر الدرجات" renders as "د ف ت ر  ا ل د ر ج ا ت". Every
   tracked style in this file was written for Latin small-caps labels and
   is simply wrong once the same element holds Arabic. Scoped to
   `html[lang="ar"]` — the layout sets `<html lang="{{ lms_lang() }}">`, so
   this follows the real request locale and leaves the English rendering of
   the same components untouched.
   `.mono` is the one exception worth spelling out: it is often genuinely
   Latin (a code, a serial) even on an Arabic page, and tracking helps
   there. So the reset skips any element that has also declared itself
   Latin data via `.nowrap-data`, which is what that class means. */
html[lang="ar"] :is(.crumb,.tbl th){letter-spacing:0}
html[lang="ar"] .mono:not(.nowrap-data){letter-spacing:0}

@media (max-width:1100px){ .split,.g4{grid-template-columns:repeat(2,1fr)} }
@media (max-width:820px){
  .g2,.g3,.g4,.split,.f .row,.f .row3{grid-template-columns:1fr}
  .who{display:none}
}

@media print{
  .abar,.afoot,.no-print,.btns{display:none!important}
  body{background:#fff}
  main{padding:0;max-width:none}
}

/* ── .cell-actions ───────────────────────────────────────────────────
   For the action column of a list table. The cell, not the button,
   carries the nowrap so a cell holding two buttons keeps them side by
   side. Deliberately NOT .nowrap-data — that class also forces
   direction:ltr, right for a code and wrong for an Arabic button label. */
.tbl td.cell-actions{white-space:nowrap}

/* ── styled HTTP error pages (final walk, admin D4 / portal D9) ──────────
   resources/views/errors/_shell.blade.php is a standalone document — it
   cannot use layouts.app, since 403 and 404 are exactly the states where
   layouts.app's "there is an authenticated $u" assumption may not hold. It
   links this file for tokens, fonts and .btn, and these are the only rules
   it needs on top. Both themes come free: every colour below is a token
   that already has its dark companion. */
body.errpg{min-height:100dvh;display:grid;place-items:center;padding:var(--pad);
  background:var(--bg);color:var(--ink)}
.errpg__box{max-width:520px;text-align:center}
/* The status code is the one thing a visitor recognises before reading
   anything, so it leads — large, but muted, because it is a label and not
   the message. */
.errpg__code{display:block;font-family:var(--ff-x);font-size:clamp(64px,16vw,120px);
  line-height:1;letter-spacing:.04em;color:var(--border-strong)}
.errpg__title{font-size:clamp(22px,4vw,30px);margin-block-start:10px}
.errpg__lead{color:var(--mut);margin-block-start:10px;line-height:1.7}
/* The abort() reason, set apart from our own copy: it is written by a
   policy, not by this page, and it may arrive in either language. */
.errpg__detail{margin-block-start:16px;padding:12px 14px;border-radius:12px;
  background:var(--bg2);box-shadow:inset 0 0 0 1px var(--line);line-height:1.7}
/* The countdown on a 429 (and on a 503 started with --retry): the one line
   on those pages a visitor can act on, so it is tinted rather than muted —
   --warn is the "come back later" tier, not the "something failed" one. It
   sits between the lead and the actions, which is the reading order the
   sentence itself implies. */
.errpg__wait{margin-block-start:16px;padding:10px 16px;border-radius:999px;
  display:inline-block;max-width:100%;font-weight:600;color:var(--warn);
  background:var(--warn-soft);line-height:1.6}
.errpg__acts{margin-block-start:24px;display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
/* The companion toggle joins that row wearing .btn--ghost, never the primary
   weight: what this page is FOR is the way back, and a control that only
   quiets a cat must not outrank it. .btn already zeroes the border and sets
   the cursor, radius, weight and size, so the only thing left to strip is the
   native button appearance — a Safari push-button re-imposes its own font and
   centring over all of that. */
.errpg__toggle{-webkit-appearance:none;appearance:none}


/* ── people lists: a floor under the NAME column (responsive sweep R4) ────
   `.tbl table` uses auto layout, and auto layout hands the surplus to the
   widest inflexible cell — here the nowrap email column, measured at 276px,
   which starved the name column to 83px from 360 all the way to 1120. A
   three-word Arabic name then wrapped onto three lines and the row grew to
   80px tall. The name is the column a reader actually scans, so it gets the
   floor. Nothing is clipped by this: `.tbl` is an overflow-x:auto wrapper
   with a real scrollbar (app.css:226 suppresses none), so the table is free
   to be wider than the viewport rather than crushing a column to fit it.
   Opt-in via `.tbl-people` rather than `th:first-child` blanket-wide — most
   admin tables lead with a code or a date, which needs no floor. */
.tbl table.tbl-people th:first-child,
.tbl table.tbl-people td:first-child { min-width: 160px; }


/* ── bootcamp desk (owner 2026-10: «الأدمن هو اللي بيعملّهم assign») ─────
   The applications inbox's per-offering chips, the bulk-assign bar and its
   confirm dialog, the one-time credentials sheet and the handover banner.
   Tokens only — every colour below flips with the theme on its own; all
   insets are logical, so RTL and LTR mirror from one declaration. */

/* offering chips: the seats figure and «مكتمل» ride inside the pill */
.atabs .atabs__seats{display:inline-block;margin-inline-start:6px;font-size:11px;
  font-family:var(--ff-m);letter-spacing:.02em;opacity:.7}
.atabs .atabs__full{display:inline-block;margin-inline-start:6px;padding:1px 7px;border-radius:999px;
  font-size:10.5px;font-weight:700;background:var(--warn-soft);color:var(--warn)}
.atabs a.on .atabs__full{background:rgba(255,255,255,.22);color:#fff}

/* the pick on each card, ahead of the name */
.appcard__head{display:flex;align-items:flex-start;gap:10px;min-width:0}
.appcard__pick{display:inline-grid;place-items:center;inline-size:28px;block-size:28px;flex:none;
  margin-block-start:2px;border-radius:9px;cursor:pointer;background:var(--surface-2);
  box-shadow:inset 0 0 0 1px var(--border)}
.appcard__pick input{inline-size:17px;block-size:17px;margin:0;accent-color:var(--brand);cursor:pointer}
.appcard--pickable:has(input[data-bulk-pick]:checked){box-shadow:var(--shadow-1),inset 0 0 0 2px var(--brand)}
.bdesk-sr{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* the sticky bar: inside the content column (never over the rail), centred
   and capped. Its data-lms-sync wrapper must not be a box of its own, or the
   sticky bar could only ever stick inside its own height — i.e. never.
   Layer: ONE above the floating companion (#anupet-companion, 65 — wherever
   the reader dragged it, it stands BEHIND the bar and never on its button)
   and below the drawer scrim (--z-backdrop), so the mobile nav still covers it. */
[data-lms-sync="applications-bulk"]{display:contents}
.bdesk-bar{position:sticky;inset-block-end:12px;z-index:calc(var(--z-header) + 6);
  display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;
  margin:0 auto 14px;max-inline-size:min(880px,100%);padding:10px 14px;border-radius:var(--r-lg);
  background:var(--surface-1);box-shadow:var(--shadow-1),inset 0 0 0 1px var(--border)}
.bdesk-bar.is-active{box-shadow:var(--shadow-1),inset 0 0 0 2px var(--brand)}
.bdesk-bar__lead{display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-width:0}
.bdesk-bar__count{font-weight:700;white-space:nowrap}
.bdesk-bar__all{display:inline-flex;align-items:center;gap:7px;font-size:.88rem;color:var(--text-muted);cursor:pointer}
.bdesk-bar__all[hidden]{display:none}
.bdesk-bar__fields{display:flex;flex-wrap:wrap;align-items:flex-end;gap:10px;flex:1 1 320px;min-width:0;margin:0}
.bdesk-bar__go{margin-inline-start:auto}
.bdesk-bar__room{flex-basis:100%;margin:0;font-size:.86rem;color:var(--text-muted);line-height:1.6}
.bdesk-field{display:grid;gap:4px;font-size:.82rem;color:var(--text-muted);min-width:0;flex:1 1 150px}
.bdesk-field input{inline-size:100%}
.bdesk-check{display:inline-flex;align-items:center;gap:8px;font-size:.88rem;cursor:pointer}
.bdesk-check input{accent-color:var(--brand)}
/* the toasts stack above the bar instead of on it */
body:has(.bdesk-bar) .lms-toasts{inset-block-end:96px}

@media (max-width:640px){
  .bdesk-bar{inset-block-end:8px;padding:10px 12px}
  .bdesk-bar__go{inline-size:100%;margin-inline-start:0;justify-content:center}
  body:has(.bdesk-bar) .lms-toasts{inset-block-end:150px}
}

/* the confirm dialog (native <dialog>, top layer, own backdrop) */
/* margin:auto restated: the global reset zeroes the UA's own centring. */
.bdesk-dialog{inline-size:min(520px,calc(100vw - 32px));max-block-size:calc(100dvh - 32px);overflow:auto;
  margin:auto;padding:22px;border:0;border-radius:var(--r-lg);
  background:var(--surface-1);color:var(--ink);box-shadow:var(--shadow-1),inset 0 0 0 1px var(--border)}
.bdesk-dialog::backdrop{background:rgba(4,7,14,.55)}
.bdesk-dialog__title{font-size:1.15rem;margin-block-end:4px}
.bdesk-dialog__count{margin:0 0 14px;color:var(--text-muted);font-weight:600}
.bdesk-dialog .bdesk-bar__fields{display:grid;gap:12px}
.bdesk-dialog__acts{display:flex;gap:9px;flex-wrap:wrap;margin-block-start:18px}

/* the one-time credentials sheet */
.bdesk-counts{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin-block-end:14px}
.bdesk-count{display:grid;gap:4px;padding:14px 16px}
.bdesk-count b{font-size:1.6rem;line-height:1}
.bdesk-count span{color:var(--text-muted);font-size:.88rem}
.bdesk-count--created b{color:var(--ok,var(--green))}
.bdesk-count--waitlisted b{color:var(--warn)}
.bdesk-count--refused b{color:var(--danger,var(--red))}
.bdesk-warn{margin-block-end:14px}
.creds .bdesk-prose{font-family:inherit;font-size:.9rem}
.creds td{vertical-align:middle}
.creds .tag,.creds .btn{white-space:nowrap}

/* the login handover banner (layouts/app.blade.php) */
.note--creds{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;justify-content:space-between}
.note--creds > span{min-width:0;flex:1 1 280px;line-height:1.8}

/* the dashboard's «طلبات البوت كامب» tile */
/* The tile lives in the board's narrow column: the track's name wraps, the
   numbers never do, so all four columns fit without a sideways scroll. */
.bdesk-tile__table{inline-size:100%}
.bdesk-tile__table th,.bdesk-tile__table td.num{white-space:nowrap;inline-size:1%}
.bdesk-tile__table td:first-child{white-space:normal;line-height:1.5}
.tbl .bdesk-tile__table th,.tbl .bdesk-tile__table td{padding-inline:8px}
.bdesk-tile__track{font-weight:700;color:inherit;text-decoration:none}
.bdesk-tile__track:hover{color:var(--brand-ink,var(--brand))}
.bdesk-tile__num{display:inline-block;min-inline-size:34px;padding:3px 9px;border-radius:999px;text-align:center;
  font-weight:700;color:inherit;text-decoration:none;background:var(--surface-2)}
.bdesk-tile__num:hover,.bdesk-tile__num:focus-visible{box-shadow:inset 0 0 0 1px var(--brand)}
.bdesk-tile__num--hot{background:var(--warn-soft);color:var(--warn)}
