/* ═══════════════════════════════════════════════════════════════════════════
   The new design's structure, translated from its Tailwind classes.

   The design app is a Tailwind build and this application is not, so every
   utility is written out with the value Tailwind gives it — h-14 is 3.5rem,
   w-60 is 15rem, gap-2 is .5rem, px-3 is .75rem, text-[11px] is 11px. Nothing
   here is a judgement about spacing; the judgements were made in the design and
   this is the transcription. Where a number came from a class the class is
   named beside it, so the two can be checked against each other later.

   Everything is under .app-v2, which also carries the token set.
   ═══════════════════════════════════════════════════════════════════════════ */

.app-v2 {
    display: flex;                       /* flex h-dvh overflow-hidden */
    block-size: 100dvh;
    overflow: hidden;
    background: var(--background);
    color: var(--foreground);
    font-family: var(--font-sans);
    font-size: 13px;
    line-height: 1.45;
}

.app-v2 *,
.app-v2 *::before,
.app-v2 *::after { box-sizing: border-box; }

/* Numbers are LTR inside an RTL page, always. A negative sign or a currency
   symbol flips to the wrong end otherwise, and a column of figures stops
   lining up — which is the one thing a column of figures is for. */
.app-v2 .num {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    direction: ltr;
    text-align: left;
}

/* ── the sidebar ───────────────────────────────────────────────────────────
   aside.hidden.lg:flex.w-60 — a 240px column of NAMED rows with icons, not a
   72px strip of glyphs. Two sections: the modules, each with a chevron that
   opens its screens, and a short list of the screens somebody opens all day.
   Below 1024px it is gone entirely and the content takes the width. */
.v2-side {
    display: none;
    inline-size: 15rem;                  /* w-60 */
    flex-shrink: 0;
    flex-direction: column;
    block-size: 100%;
    background: var(--sidebar);
    color: var(--sidebar-foreground);
}

@media (min-width: 1024px) { .v2-side { display: flex; } }
@media print { .v2-side { display: none; } }

.v2-side__head {
    display: flex;
    block-size: 3.5rem;                  /* h-14 */
    align-items: center;
    gap: .5rem;
    padding-inline: .75rem;
    border-block-end: 1px solid var(--sidebar-border);
}

.v2-side__mark {
    display: grid;
    place-items: center;
    inline-size: 2rem;                   /* size-8 */
    block-size: 2rem;
    flex-shrink: 0;
    border-radius: var(--radius);
    background: var(--sidebar-accent);
    color: var(--sidebar-primary);
}

.v2-side__title {
    font-size: .875rem;                  /* text-sm */
    font-weight: 600;
    color: var(--sidebar-accent-foreground);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.v2-side__sub { font-size: 10px; color: color-mix(in oklab, var(--sidebar-foreground) 70%, transparent); }

.v2-side__nav {
    min-block-size: 0;
    flex: 1;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: .5rem;
    scrollbar-width: thin;
}

/* text-[10px] font-semibold tracking-wide text-sidebar-foreground/50 */
.v2-side__group {
    margin: 0;
    padding-inline: .625rem;             /* px-2.5 */
    padding-block: .5rem .25rem;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .025em;
    color: color-mix(in oklab, var(--sidebar-foreground) 50%, transparent);
}

.v2-side__group + .v2-side__items { margin-block-end: .25rem; }
.v2-side__items > * + * { margin-block-start: .125rem; }   /* space-y-0.5 */

/* The row is the link AND its chevron, so the chevron is a sibling of the link
   rather than inside it: a click on «open the module's screens» must not also
   be a click on «go to the module». */
.v2-side__row { display: flex; align-items: center; }

.v2-side__link {
    display: flex;
    min-inline-size: 0;
    flex: 1;
    align-items: center;
    gap: .625rem;                        /* gap-2.5 */
    padding: .5rem .625rem;              /* py-2 px-2.5 */
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: color-mix(in oklab, var(--sidebar-foreground) 85%, transparent);
    font: inherit;
    font-size: .875rem;                  /* text-sm */
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}

.v2-side__link:hover,
.v2-side__toggle:hover {
    background: var(--sidebar-accent);
    color: var(--sidebar-accent-foreground);
}

.v2-side__link--on {
    background: var(--sidebar-accent);
    color: var(--sidebar-accent-foreground);
}

.v2-side__label {
    flex: 1;
    min-inline-size: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 500;
}

.v2-side__toggle {
    display: inline-flex;
    padding: .25rem;
    border: 0;
    border-radius: calc(var(--radius) - 2px);
    background: none;
    color: color-mix(in oklab, var(--sidebar-foreground) 60%, transparent);
    cursor: pointer;
}

/* The screens under an open module. Indented by the icon's width so their names
   line up with the module's name above them rather than with its icon. */
.v2-side__sublist {
    display: flex;
    flex-direction: column;
    gap: .125rem;
    margin-block: .125rem .25rem;
    padding-inline-start: 1.125rem;
}

.v2-side__sublink {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .3125rem .625rem;
    border-radius: var(--radius);
    color: color-mix(in oklab, var(--sidebar-foreground) 72%, transparent);
    font-size: 12.5px;
    text-decoration: none;
}

.v2-side__sublink:hover {
    background: color-mix(in oklab, var(--sidebar-accent) 70%, transparent);
    color: var(--sidebar-accent-foreground);
}

.v2-side__no {
    margin-inline-start: auto;
    font-size: 10px;
    color: color-mix(in oklab, var(--sidebar-foreground) 55%, transparent);
}

.v2-side__foot {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem;
    border-block-start: 1px solid var(--sidebar-border);
}

.v2-side__card {
    flex: 1;
    min-inline-size: 0;
    padding: .75rem;
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--sidebar-accent) 60%, transparent);
}

.v2-side__cardtitle {
    margin: 0;
    font-size: 11px;
    font-weight: 600;
    color: var(--sidebar-accent-foreground);
}

.v2-side__cardline {
    margin: .25rem 0 0;
    font-size: 12px;
    color: color-mix(in oklab, var(--sidebar-foreground) 80%, transparent);
}

.v2-side__dot { opacity: .55; margin-inline: .25rem; }

.v2-side__out {
    display: grid;
    place-items: center;
    inline-size: 2.25rem;
    block-size: 2.25rem;
    flex-shrink: 0;
    border-radius: var(--radius);
    color: color-mix(in oklab, var(--sidebar-foreground) 70%, transparent);
    text-decoration: none;
}

.v2-side__out:hover { background: var(--sidebar-accent); color: var(--sidebar-accent-foreground); }

/* ── the icons ─────────────────────────────────────────────────────────────
   One size on the sidebar and the app bar — size-4 — and the fold is the
   chevron pointing at the section it would open rather than down at nothing.
   Rotated by 90deg because the page is RTL: a closed row points to the start
   edge, which is the right. */
.v2-icon { inline-size: 1.25rem; block-size: 1.25rem; flex-shrink: 0; }
.v2-icon--sm { inline-size: 1rem; block-size: 1rem; opacity: .8; }
.v2-icon--folded { transform: rotate(90deg); }

/* ── the column beside it ──────────────────────────────────────────────── */
.v2-main {
    display: flex;
    min-inline-size: 0;
    flex: 1;
    flex-direction: column;
}

.v2-appbar {
    display: flex;
    block-size: 3rem;                    /* h-12 */
    flex-shrink: 0;
    align-items: center;
    gap: .75rem;
    padding-inline: 1rem;
    border-block-end: 1px solid var(--border);
    background: var(--surface);
}

@media print { .v2-appbar { display: none; } }

.v2-appbar__end { margin-inline-start: auto; display: flex; align-items: center; gap: .5rem; }

/* A square button that is only an icon. h-9 w-9, and it gets the accent on
   hover like every other quiet control in this design. */
.v2-iconbtn {
    display: inline-grid;
    place-items: center;
    inline-size: 2.25rem;                /* h-9 w-9 */
    block-size: 2.25rem;
    flex-shrink: 0;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--foreground);
    cursor: pointer;
}

.v2-iconbtn:hover { background: var(--accent); color: var(--accent-foreground); }

/* The installation-wide search. A button shaped like a field, which is the
   design's own choice and the honest one: it opens a dialog, and a field that
   opens a dialog when you type in it is a field that lies about what it is. */
.v2-search {
    display: flex;
    block-size: 2.25rem;                 /* h-9 */
    inline-size: 100%;
    max-inline-size: 24rem;              /* max-w-sm */
    align-items: center;
    gap: .5rem;
    padding-inline: .75rem;
    border: 1px solid var(--field);
    border-radius: var(--radius);
    background: var(--background);
    color: var(--muted-foreground);
    font: inherit;
    font-size: .875rem;
    cursor: pointer;
}

.v2-search:hover { background: color-mix(in oklab, var(--muted) 50%, transparent); }

.v2-search__text {
    flex: 1;
    min-inline-size: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    text-align: start;
}

.v2-kbd {
    display: none;
    padding: .125rem .375rem;
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) - 2px);
    background: var(--muted);
    font-size: 10px;
    color: var(--muted-foreground);
}

@media (min-width: 640px) { .v2-kbd { display: inline; } }

/* Who is signed in. The initials tile is the design's; the two lines beside it
   are the name and the operator number, and the number is there because it is
   what a colleague on the phone will ask for. */
.v2-user {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .1875rem .5rem .1875rem .1875rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
}

.v2-user__mark {
    display: grid;
    place-items: center;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border-radius: 999px;
    background: var(--accent);
    color: var(--accent-foreground);
    font-size: 10.5px;
    font-weight: 700;
}

.v2-user__who { display: flex; flex-direction: column; line-height: 1.2; }
.v2-user__name { font-size: 11.5px; font-weight: 600; }
.v2-user__meta { font-size: 10px; color: var(--muted-foreground); }

@media (max-width: 767px) { .v2-user__who { display: none; } }

/* The open-windows strip, separate from the document bar. In the old shell the
   two were one row; here a window is a tab and a document is a heading, and
   they answer different questions. */
.v2-tabs {
    display: flex;
    align-items: stretch;
    gap: .25rem;
    padding-inline: .5rem;
    border-block-end: 1px solid var(--border);
    background: color-mix(in oklab, var(--surface) 80%, transparent);
}

@media print { .v2-tabs { display: none; } }

.v2-tabs__list {
    display: flex;
    min-inline-size: 0;
    flex: 1;
    align-items: stretch;
    gap: .25rem;
    overflow-x: auto;
    padding-block: .25rem;
    scrollbar-width: thin;
}

.v2-tab {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .25rem .625rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: none;
    color: var(--muted-foreground);
    font: inherit;
    font-size: 12px;
    white-space: nowrap;
    cursor: pointer;
}

.v2-tab--on {
    border-color: var(--border);
    background: var(--surface);
    color: var(--foreground);
    font-weight: 600;
}

.v2-tabs__empty { padding: .25rem .5rem; font-size: 11.5px; color: var(--muted-foreground); }

/* ── the document bar ─────────────────────────────────────────────────── */
.v2-docbar {
    flex-shrink: 0;
    padding: .625rem 1rem;               /* py-2.5 px-4 */
    border-block-end: 1px solid var(--border);
    background: var(--surface);
}

@media print { .v2-docbar { border: 0; padding-inline: 0; } }

.v2-docbar__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .375rem 1rem;
}

.v2-crumbs {
    display: flex;
    align-items: center;
    gap: .25rem;
    font-size: 11px;
    color: var(--muted-foreground);
}

@media print { .v2-crumbs { display: none; } }

.v2-crumbs__sep { opacity: .5; }

.v2-doctitle {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .125rem .75rem;
}

.v2-doctitle__name { font-size: 1rem; font-weight: 700; }
.v2-doctitle__hint { font-size: 11.5px; color: var(--muted-foreground); }

.v2-docactions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
@media print { .v2-docactions { display: none; } }

/* ── the work area ────────────────────────────────────────────────────── */
.v2-body {
    min-block-size: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 1rem;                           /* space-y-4 */
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 1rem;
    scrollbar-width: thin;
}

@media print { .v2-body { overflow: visible; padding: 0; } }

.v2-chips { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; font-size: 11px; }

/* ── buttons ──────────────────────────────────────────────────────────── */
.v2-btn {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .3125rem .625rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--foreground);
    font: inherit;
    font-size: 12px;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
}

.v2-btn:hover { background: var(--muted); }
.v2-btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.v2-btn[disabled] { opacity: .5; cursor: not-allowed; }

.v2-btn--primary {
    border-color: transparent;
    background: var(--primary);
    color: var(--primary-foreground);
    font-weight: 600;
}

.v2-btn--primary:hover { background: color-mix(in oklab, var(--primary) 88%, black); }

.v2-btn--ghost { border-color: transparent; background: none; color: var(--muted-foreground); }
.v2-btn--ghost:hover { background: var(--muted); color: var(--foreground); }

.v2-btn__key {
    font-family: var(--font-mono);
    font-size: 9.5px;
    opacity: .6;
}

/* ── badges ───────────────────────────────────────────────────────────── */
.v2-badge {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .0625rem .375rem;
    border-radius: var(--radius);
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
}

.v2-badge--muted   { background: var(--muted);   color: var(--muted-foreground); }
.v2-badge--ok      { background: color-mix(in oklab, var(--success) 16%, var(--surface));     color: var(--success); }
.v2-badge--signal  { background: color-mix(in oklab, var(--signal) 20%, var(--surface));      color: var(--signal-foreground); }
.v2-badge--bad     { background: color-mix(in oklab, var(--destructive) 14%, var(--surface)); color: var(--destructive); }
.v2-badge--accent  { background: var(--accent); color: var(--accent-foreground); }

/* ── the header field grid ────────────────────────────────────────────────
   One column, then two at 768px, then three at 1280px — md:grid-cols-2 and
   xl:grid-cols-3. Each field is its own [88px 1fr] grid: the label column is
   FIXED, so the value columns line up down the page whatever the label says. */
.v2-fields {
    display: grid;
    gap: .375rem 1rem;
    grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 768px)  { .v2-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .v2-fields { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.v2-field {
    display: grid;
    grid-template-columns: minmax(0, 88px) minmax(0, 1fr);
    align-items: center;
    gap: .5rem;
}

.v2-field--wide { grid-column: 1 / -1; align-items: start; }

.v2-field--note {
    margin-block-start: .5rem;
    border-block-start: 1px solid var(--border);
    padding-block-start: .5rem;
}

.v2-field__label {
    display: flex;
    align-items: center;
    gap: .25rem;
    font-size: 11.5px;
    color: var(--muted-foreground);
}

/* Required, NOT error. The standard is explicit that the two must not share a
   colour cue on the same element: the star says «you have to fill this in» and
   a red border says «what you filled in is wrong». */
.v2-field__req { color: var(--destructive); font-weight: 700; }

.v2-field__value { display: flex; min-inline-size: 0; align-items: center; gap: .5rem; }

.v2-input {
    inline-size: 100%;
    min-inline-size: 0;
    block-size: 1.75rem;
    padding-inline: .5rem;
    border: 1px solid var(--field);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--foreground);
    font: inherit;
    font-size: 12.5px;
}

.v2-input:focus-visible { outline: 2px solid var(--ring); outline-offset: -1px; border-color: var(--ring); }
.v2-input[readonly] { background: var(--muted); color: var(--muted-foreground); }
.v2-input--code { inline-size: 72px; flex: 0 0 auto; text-align: center; }
.v2-input--code-wide { inline-size: 112px; }

textarea.v2-input { block-size: auto; min-block-size: 3.5rem; padding-block: .375rem; resize: vertical; }

/* ── the lines panel ──────────────────────────────────────────────────── */
.v2-panel {
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-panel);
}

.v2-panel__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding: .375rem .75rem;
    border-block-end: 1px solid var(--border);
    background: color-mix(in oklab, var(--muted) 50%, transparent);
    font-size: 12px;
    font-weight: 600;
}

.v2-panel__end { margin-inline-start: auto; display: flex; align-items: center; gap: .25rem; }
.v2-panel__body { overflow: auto; scrollbar-width: thin; }

.v2-panel__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem 1.25rem;
    padding: .375rem .75rem;
    border-block-start: 1px solid var(--border);
    background: color-mix(in oklab, var(--muted) 60%, transparent);
    font-size: 11.5px;
    color: var(--muted-foreground);
}

.v2-lines { inline-size: 100%; min-inline-size: 1080px; border-collapse: collapse; }

.v2-lines th {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
    padding: .375rem .5rem;
    border-block-end: 1px solid var(--border);
    background: var(--muted);
    color: var(--muted-foreground);
    font-size: 11px;
    font-weight: 600;
    text-align: start;
    white-space: nowrap;
}

.v2-lines td {
    padding: .3125rem .5rem;
    border-block-end: 1px solid var(--border);
    font-size: 12.5px;
    vertical-align: middle;
}

.v2-lines tbody tr:hover { background: color-mix(in oklab, var(--accent) 40%, transparent); }

/* The active row, and the two cues are not redundant: the fill says WHICH row
   and the inset rule says which EDGE the reading starts from, which is what
   tells an operator the row is being edited rather than merely selected. */
.v2-lines tr.is-current { background: var(--accent); box-shadow: inset 2px 0 0 var(--primary); }

.v2-lines .cell-total { background: color-mix(in oklab, var(--muted) 50%, transparent); font-weight: 600; }

.v2-lines__empty td {
    padding-block: .75rem;
    border-block-end: 1px dashed var(--border);
    color: var(--muted-foreground);
    font-size: 11.5px;
    text-align: center;
}

/* ── the sticky totals ────────────────────────────────────────────────────
   One row, not a grid of ten boxes. The four that are always there run inline
   and «النهائي» sits in its own tinted box at the far end beside the save. */
.v2-totals {
    position: sticky;
    inset-block-end: 0;
    z-index: 20;
    margin-block-start: auto;
    margin-inline: -1rem;
    border-block-start: 1px solid var(--border);
    background: color-mix(in oklab, var(--surface) 95%, transparent);
    backdrop-filter: blur(8px);
}

.v2-totals__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1.5rem;
    padding: .5rem 1rem;
}

.v2-total { display: flex; align-items: baseline; gap: .375rem; font-size: 11.5px; }
.v2-total__label { color: var(--muted-foreground); }
.v2-total__value { font-size: 13px; font-weight: 600; }

.v2-totals__end { margin-inline-start: auto; display: flex; align-items: center; gap: .75rem; }

.v2-total--final {
    padding: .25rem .75rem;
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--accent) 50%, transparent);
    text-align: center;
}

.v2-total--final .v2-total__value { font-size: 1.3125rem; font-weight: 700; }

/* ── the status bar ───────────────────────────────────────────────────── */
.v2-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .25rem 1rem;
    padding: .375rem .75rem;
    border-block-start: 1px solid var(--border);
    background: color-mix(in oklab, var(--surface) 95%, transparent);
    font-size: 11px;
    color: var(--muted-foreground);
    backdrop-filter: blur(8px);
}

@media print { .v2-status { display: none; } }

.v2-status__group { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem 1rem; }
.v2-status__item { display: inline-flex; align-items: baseline; gap: .25rem; }
.v2-status__value { color: var(--foreground); }

/* ── cards, list links and chips ─────────────────────────────────────────
   The module page draws three panels side by side and a row of chips under
   them. The panels wrap to one column below 900px rather than shrinking, so a
   list of screen names never has to be read two words at a time. */
.v2-cards {
    display: grid;
    gap: 1rem;
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
}

@media (min-width: 900px)  { .v2-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1400px) { .v2-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.v2-listlink {
    display: flex;
    inline-size: 100%;
    align-items: center;
    gap: .5rem;
    padding: 7px .75rem;                 /* py-[7px] px-3 */
    color: inherit;
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
}

.v2-listlink:hover { background: var(--muted); }
.v2-listlink__id { margin-inline-start: auto; font-size: 11px; color: var(--muted-foreground); }

.v2-chip {
    display: inline-flex;
    align-items: center;
    padding: .25rem .625rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: inherit;
    font-size: 12px;
    text-decoration: none;
}

.v2-chip:hover {
    border-color: color-mix(in oklab, var(--primary) 50%, transparent);
    background: var(--muted);
}

/* ── list screens ────────────────────────────────────────────────────────
   A 15px box, from customers.html. It is a state, not a control: the row's own
   toggle lives in the record's form, and a tick here that could be clicked
   would be a way to deactivate a customer by mis-aiming. */
.v2-tick {
    display: inline-grid;
    place-items: center;
    inline-size: 15px;
    block-size: 15px;
    border: 1px solid var(--border-strong);
    border-radius: calc(var(--radius) / 2);
    font-size: 10px;
    line-height: 1;
}

.v2-tick--on { border-color: var(--success); background: var(--success); color: var(--success-foreground); }

/* A negative balance, and only where the column says it is money. Red on a
   quantity would read as an error rather than as a direction. */
.v2-negative { color: var(--destructive); }

/* ── لوحة اليوم ─────────────────────────────────────────────────────────
   Four cards across, two on a tablet, one on a phone — sm:grid-cols-2 and
   xl:grid-cols-4 from dashboard.html. */
.v2-kpis {
    display: grid;
    gap: .75rem;
    grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px)  { .v2-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .v2-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.v2-kpi {
    position: relative;
    overflow: hidden;
    padding: .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-panel);
}

/* The rail down the START edge — 4px, full height, and its colour is the card's
   tone. It is what makes four cards read as four KINDS of number instead of
   four of the same one. */
.v2-kpi__rail {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    inline-size: .25rem;                 /* w-1 */
}

.v2-kpi__rail--primary     { background: var(--primary); }
.v2-kpi__rail--success     { background: var(--success); }
.v2-kpi__rail--signal      { background: var(--signal); }
.v2-kpi__rail--destructive { background: var(--destructive); }

/* The first card is filled, because a row of four equal cards has no answer to
   «which one first». Its rail is the same colour as its ground on purpose — the
   design keeps the element so the four cards stay the same shape. */
.v2-kpi--filled {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--primary-foreground);
}

.v2-kpi--filled .v2-kpi__label,
.v2-kpi--filled .v2-kpi__unit,
.v2-kpi--filled .v2-kpi__hint,
.v2-kpi--filled .v2-kpi__delta {
    color: color-mix(in oklab, var(--primary-foreground) 78%, transparent);
}

.v2-kpi--filled .v2-icon { opacity: .7; }

.v2-kpi__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: .5rem;
}

.v2-kpi__label { margin: 0; font-size: 12px; font-weight: 600; color: var(--muted-foreground); }

/* 22px, the design's «الرقم الأهم في الشاشة». Everything else on the card is
   smaller than the number, which is what makes it the number. */
.v2-kpi__value {
    display: flex;
    align-items: baseline;
    gap: .25rem;
    margin: .375rem 0 0;
    font-size: 1.5rem;                   /* text-2xl */
    font-weight: 600;
}

.v2-kpi__unit  { font-size: 11.5px; font-weight: 400; color: var(--muted-foreground); }
.v2-kpi__hint  { margin: .25rem 0 0; font-size: 11px; color: var(--muted-foreground); }
.v2-kpi__delta { margin: .25rem 0 0; font-size: 11.5px; color: var(--muted-foreground); }
.v2-kpi__delta--up   { color: var(--success); }
.v2-kpi__delta--down { color: var(--destructive); }

/* «مستندات معلقة» and «تنبيهات ورفض» — 1.4fr to 1fr, so the table gets the room
   and the alerts stay readable rather than square. */
.v2-split {
    display: grid;
    gap: .75rem;
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
}

@media (min-width: 1024px) {
    .v2-split { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
}

.v2-alert {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .625rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-block-end: .375rem;
    font-size: 12.5px;
}

/* The two tones say two different things — one refuses, one asks — so they are
   named for that rather than for how alarming they look. */
.v2-alert--bad {
    border-color: color-mix(in oklab, var(--destructive) 40%, transparent);
    background: color-mix(in oklab, var(--destructive) 10%, var(--surface));
}

.v2-alert--signal {
    border-color: color-mix(in oklab, var(--signal) 45%, transparent);
    background: color-mix(in oklab, var(--signal) 14%, var(--surface));
}

.v2-module {
    display: block;
    padding: .625rem .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: inherit;
    text-decoration: none;
}

.v2-module:hover { border-color: color-mix(in oklab, var(--primary) 50%, transparent); background: var(--muted); }

/* ── a share, as a bar and a number ─────────────────────────────────────
   Both, deliberately. The number is what somebody quotes and the bar is what
   they compare — a column of percentages has to be read one row at a time. */
.v2-share { display: flex; align-items: center; gap: .5rem; }

.v2-share__bar {
    block-size: 6px;
    min-inline-size: 2px;
    max-inline-size: 100%;
    border-radius: 3px;
    background: var(--primary);
}

.v2-share__value { font-size: 11px; color: var(--muted-foreground); }

/* ── the picker ─────────────────────────────────────────────────────────
   A dialog because it takes the whole keyboard while it is open: arrows move,
   Enter takes, Esc leaves the line as it was. The overlay is #0b111a70 from the
   design's Modals note. */
.v2-overlay {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: grid;
    place-items: start center;
    padding-block-start: 12vh;
    background: #0b111a70;
}

.v2-picker {
    inline-size: min(760px, 92vw);
    max-block-size: 70vh;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    padding: .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--popover);
    color: var(--popover-foreground);
    box-shadow: var(--shadow-float);
}

.v2-picker__head { display: flex; align-items: center; gap: .5rem; font-size: 12.5px; font-weight: 600; }
.v2-picker__count { font-size: 11px; color: var(--muted-foreground); }
.v2-picker__hint  { margin-inline-start: auto; font-size: 11px; color: var(--muted-foreground); }

.v2-picker__list {
    min-block-size: 0;
    flex: 1;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
    scrollbar-width: thin;
}

.v2-picker__row {
    display: grid;
    grid-template-columns: 132px minmax(0, 1fr) 100px 90px;
    align-items: center;
    gap: .5rem;
    padding: .375rem .5rem;
    border-radius: var(--radius);
    font-size: 12.5px;
    cursor: pointer;
}

.v2-picker__row:hover { background: var(--muted); }

/* The current row, and it is a FILL rather than an outline: the list is scrolled
   with arrows and a fill is what stays visible at the edge of the viewport. */
.v2-picker__row--on { background: var(--accent); color: var(--accent-foreground); }

.v2-picker__row--empty {
    display: block;
    padding-block: .75rem;
    color: var(--muted-foreground);
    text-align: center;
    cursor: default;
}

.v2-picker__price,
.v2-picker__stock { font-size: 11.5px; color: var(--muted-foreground); }

/* An account row has three columns, not four: a code, a name, and whether it
   carries VAT. There is no stock figure to show about an account. */
.v2-picker__row--account { grid-template-columns: 132px minmax(0, 1fr) 110px; }

/* ── the record editor ───────────────────────────────────────────────────────
   The design draws the list toolbar and never draws the dialog behind «إضافة»,
   so the editor borrows the chrome the picker already established rather than
   inventing a second kind of overlay. Wider than the picker because a form is
   read across, and its list scrolls because a screen with forty fields must
   not push its own save button off the bottom. */
.v2-picker--form { inline-size: min(1020px, 94vw); }

.v2-picker--form .v2-fields { padding: .25rem .125rem; }

/* On a tab strip inside the dialog there is no app bar under it to divide from. */
.v2-tabs--form {
    padding-inline: 0;
    border-block-end: 1px solid var(--border);
    background: none;
}

.v2-picker__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .5rem;
    padding-block-start: .5rem;
    border-block-start: 1px solid var(--border);
}

.v2-picker--confirm {
    inline-size: min(420px, 92vw);
    gap: .75rem;
}

/* Destructive, and it says so in colour rather than only in the word. */
.v2-btn--danger {
    border-color: var(--destructive);
    background: var(--destructive);
    color: var(--destructive-foreground, #fff);
}

.v2-btn--danger:hover { background: color-mix(in oklab, var(--destructive) 88%, black); }

/* ── allowed, and waiting to be approved ─────────────────────────────────────
   Not a refusal, so not the destructive colour: a red card tells an operator
   they are stuck, and this one exists precisely because they are not. It sits
   above the fields because the answer to it is a button, not a correction. */
.v2-alert {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .5rem .625rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    font-size: 12.5px;
}

.v2-alert--warn {
    border-color: color-mix(in oklab, var(--signal) 55%, var(--border));
    background: color-mix(in oklab, var(--signal) 10%, var(--surface));
}

.v2-alert__head { display: flex; align-items: center; gap: .5rem; font-weight: 600; }

/* The button is pushed to the far end so it is never mistaken for part of the sentence. */
.v2-alert__head .v2-approve { margin-inline-start: auto; }

.v2-alert__item { color: var(--muted-foreground); }

/* ── a screen that has not been redrawn yet ────────────────────────────────
   Its own body, inside the new shell. The old rules still apply to it — they
   are still loaded and they still work — and they now resolve to the new
   palette, because tokens.css maps every name they ask for.

   Two things have to be undone here and only here. The old body assumed it was
   the page: it set its own scroll and its own padding against a viewport it no
   longer owns. Inside .v2-body it is a block among others. */
.v2-legacy {
    min-block-size: 0;
    margin: calc(var(--sp-4) * -1);
}

.v2-legacy .workspace__pane { min-block-size: 0; }

/* The old shell's own chrome, if any of it reaches this far: the rail, the
   title bar and the status line all exist above this now. Hidden rather than
   deleted, because the components that draw them are still the ones serving
   /workspace and the print pages. */
.v2-legacy .rail,
.v2-legacy .titlebar,
.v2-legacy .statusbar { display: none; }

/* The theme word is a ghost button and stays one width whichever word is in it,
   so the bell and the user chip do not shuffle sideways on every toggle. */
.v2-theme { min-inline-size: 3.5rem; justify-content: center; }

/* ── the dashboard's own pieces ────────────────────────────────────────────
   From design/app-v2/pages/dashboard.html. Three shapes, and each is a target
   rather than a decoration: a tile is a screen, a module card is a section, an
   alert row is a thing to go and fix. */
.v2-panel--pad { padding: .75rem; }

.v2-panel__title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
}

.v2-panel__title h2 { margin: 0; font-size: .875rem; font-weight: 600; }
.v2-panel__note { font-size: 11px; color: var(--muted-foreground); }

/* Eight across at 1280px, four at 640, two below. The design's own breakpoints,
   and the count matters: eight is what fits one row of the operator's morning. */
.v2-tiles {
    display: grid;
    gap: .5rem;
    margin-block-start: .5rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 640px)  { .v2-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .v2-tiles { grid-template-columns: repeat(8, minmax(0, 1fr)); } }

.v2-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .375rem;
    padding: .75rem .5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: inherit;
    text-align: center;
    text-decoration: none;
}

.v2-tile:hover {
    border-color: color-mix(in oklab, var(--primary) 50%, transparent);
    background: color-mix(in oklab, var(--muted) 50%, transparent);
}

/* The icon fills with the primary colour on hover, which is the design's way of
   saying «this is the thing you are about to open» before the click lands. */
.v2-tile__mark {
    display: grid;
    place-items: center;
    inline-size: 2.25rem;                /* size-9 */
    block-size: 2.25rem;
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--primary) 10%, transparent);
    color: var(--primary);
}

.v2-tile:hover .v2-tile__mark { background: var(--primary); color: var(--primary-foreground); }
.v2-tile__name { font-size: 12px; font-weight: 600; line-height: 1.25; }

/* ── the module cards ─────────────────────────────────────────────────────── */
.v2-modules {
    display: grid;
    gap: .5rem;
    margin-block-start: .5rem;
    grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px)  { .v2-modules { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .v2-modules { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.v2-module {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: inherit;
    text-decoration: none;
}

.v2-module:hover {
    border-color: color-mix(in oklab, var(--primary) 50%, transparent);
    background: color-mix(in oklab, var(--muted) 50%, transparent);
}

.v2-module__mark {
    display: grid;
    place-items: center;
    inline-size: 2.5rem;                 /* size-10 */
    block-size: 2.5rem;
    flex-shrink: 0;
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--primary) 10%, transparent);
    color: var(--primary);
}

.v2-module:hover .v2-module__mark { background: var(--primary); color: var(--primary-foreground); }

.v2-module__who { display: flex; min-inline-size: 0; flex: 1; flex-direction: column; }
.v2-module__name { font-size: 13px; font-weight: 600; }

.v2-module__hint {
    margin-block-start: .125rem;
    font-size: 11px;
    color: var(--muted-foreground);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.v2-module__go { color: var(--muted-foreground); }

/* ── the alert rows ────────────────────────────────────────────────────────
   The WHOLE row is the link. An alert exists to be acted on, and making the
   sentence itself clickable puts the action where the eye already is. */
.v2-alerts { display: flex; flex-direction: column; gap: .5rem; margin: .5rem 0 0; padding: 0; list-style: none; }

.v2-alertrow {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    padding: .5rem;
    border: 1px solid;
    border-radius: var(--radius);
    font-size: 13px;
    text-decoration: none;
}

.v2-alertrow__text { flex: 1; min-inline-size: 0; }
.v2-alertrow__count { font-size: 11px; opacity: .8; }
.v2-alertrow__go { flex-shrink: 0; margin-block-start: .0625rem; font-size: 11px; opacity: .7; }

/* Red REFUSES and amber ASKS, and the dashboard says so in words underneath.
   Two tones, not two shades of the same worry. */
.v2-alertrow--bad {
    border-color: color-mix(in oklab, var(--destructive) 40%, transparent);
    background: color-mix(in oklab, var(--destructive) 10%, var(--surface));
    color: var(--destructive);
    font-weight: 500;
}

.v2-alertrow--bad:hover { background: color-mix(in oklab, var(--destructive) 16%, var(--surface)); }

.v2-alertrow--signal {
    border-color: color-mix(in oklab, var(--signal) 50%, transparent);
    background: color-mix(in oklab, var(--signal) 15%, var(--surface));
    color: var(--signal-foreground);
}

.v2-alertrow--signal:hover { background: color-mix(in oklab, var(--signal) 25%, var(--surface)); }

.v2-alertrow--muted {
    border-color: var(--border);
    background: var(--muted);
    color: var(--foreground);
}

/* ── sign-in ───────────────────────────────────────────────────────────────
   design/app-v2/pages/root.html: two columns, the brand panel taking what is
   left and the form column a fixed 480px. Below 1024px the brand panel is gone
   entirely — nobody signs in on a phone to read a tagline. */
.v2-login {
    display: grid;
    min-block-size: 100dvh;
    background: var(--background);
    color: var(--foreground);
    font-family: var(--font-sans);
    grid-template-columns: minmax(0, 1fr);
}

.v2-login__brand {
    position: relative;
    display: none;
    overflow: hidden;
    flex-direction: column;
    justify-content: space-between;
    padding: 2.5rem;                     /* p-10 */
    background: var(--sidebar);
    color: var(--sidebar-foreground);
}

/* AFTER the rule it overrides, not before it. Both selectors have the same
   specificity, so a media query placed above simply loses — the panel was
   display:none at every width and the page rendered as a card on an empty
   field. A media query is not a specificity bump. */
@media (min-width: 1024px) {
    .v2-login { grid-template-columns: minmax(0, 1fr) 480px; }
    .v2-login__brand { display: flex; }
}

/* 28px squares at 7%, drawn rather than shipped: it stays sharp at any density
   and follows the sidebar's own foreground in both themes. */
.v2-login__grid {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: .07;
    background-image:
        linear-gradient(var(--sidebar-foreground) 1px, transparent 1px),
        linear-gradient(90deg, var(--sidebar-foreground) 1px, transparent 1px);
    background-size: 28px 28px;
}

.v2-login__lockup { position: relative; display: flex; align-items: center; gap: .75rem; }
.v2-login__mark { inline-size: 3rem; block-size: 3rem; }   /* size-12 */

.v2-login__name {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--sidebar-accent-foreground);
}

.v2-login__edition {
    margin: 0;
    font-size: .75rem;
    color: color-mix(in oklab, var(--sidebar-foreground) 70%, transparent);
}

.v2-login__pitch { position: relative; max-inline-size: 32rem; }

.v2-login__pitch h2 {
    margin: 0;
    font-size: 1.875rem;                 /* text-3xl */
    font-weight: 600;
    line-height: 1.375;
    color: var(--sidebar-accent-foreground);
    text-wrap: balance;
}

.v2-login__pitch p {
    margin: 1rem 0 0;
    font-size: .875rem;
    line-height: 1.7;
    color: color-mix(in oklab, var(--sidebar-foreground) 80%, transparent);
}

.v2-login__stats {
    display: grid;
    gap: 1rem;
    margin: 2rem 0 0;
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.v2-login__stats > div {
    padding: .75rem;
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--sidebar-accent) 50%, transparent);
}

.v2-login__stats dt { font-size: 11px; color: color-mix(in oklab, var(--sidebar-foreground) 80%, transparent); }

.v2-login__stats dd {
    margin: .25rem 0 0;
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--sidebar-accent-foreground);
}

.v2-login__foot {
    position: relative;
    margin: 0;
    font-size: .75rem;
    color: color-mix(in oklab, var(--sidebar-foreground) 60%, transparent);
}

/* ── the card ──────────────────────────────────────────────────────────── */
.v2-login__side { display: grid; place-items: center; padding: 1.5rem; }

.v2-login__card {
    inline-size: 100%;
    max-inline-size: 24rem;              /* max-w-sm */
    padding: 1.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-panel);
}

.v2-login__title { margin: 0; font-size: 1.125rem; font-weight: 600; }
.v2-login__hint  { margin: .25rem 0 0; font-size: .75rem; color: var(--muted-foreground); }
.v2-login__error { margin-block-start: 1rem; }

.v2-login__fields { display: flex; flex-direction: column; gap: 1rem; margin-block-start: 1.5rem; }
.v2-login__field  { display: flex; flex-direction: column; gap: .375rem; }
.v2-login__label  { font-size: .75rem; font-weight: 600; }

/* The field is 36px here rather than the grid's 28px: this screen is typed once
   a day on whatever device is to hand, and it is the one place in the system
   where density is worth less than a comfortable target. */
.v2-login__field .v2-input { block-size: 2.25rem; }

.v2-login__msg { font-size: 11px; color: var(--destructive); }

.v2-login__actions { display: flex; gap: .5rem; margin-block-start: 1.5rem; }
.v2-login__actions .v2-btn { flex: 1; justify-content: center; block-size: 2.25rem; }

.v2-login__end {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-block-start: 1rem;
    padding-block-start: 1rem;
    border-block-start: 1px solid var(--border);
}

/* An answer that is not a row: a refusal, an empty result, a screen that is not
   built. Centred and quiet — it is the whole panel's content, so it should read
   as a statement rather than as a missing table. */
.v2-state { padding: 2.5rem 1rem; text-align: center; }
.v2-state__title { display: block; font-size: 13px; font-weight: 600; }
.v2-state p { margin: .5rem 0 0; font-size: 12px; color: var(--muted-foreground); }

/* ── the profile menu ──────────────────────────────────────────────────────
   The design makes the chip a menu trigger and its content is rendered on open,
   so the trigger is transcribed and the panel is built in the design's own
   language: a popover surface, the float shadow, one radius. */
.v2-profile { position: relative; }

.v2-user { border: 1px solid var(--border); cursor: pointer; font: inherit; color: inherit; }
.v2-user:hover { background: color-mix(in oklab, var(--accent) 50%, transparent); }

/* Under everything and over nothing: one click anywhere closes the menu. A menu
   whose only exit is its own trigger is one people stop opening. */
.v2-profile__scrim { position: fixed; inset: 0; z-index: 40; }

.v2-menu {
    position: absolute;
    z-index: 50;
    inset-block-start: calc(100% + .375rem);

    /* Anchored at the END edge, so the panel grows INWARD from the chip. The chip
       is pushed to the far end of the bar by ms-auto; anchoring at the start edge
       sends a 17rem panel straight off the side of the window, which is where the
       first version put it — labels on screen and every value past the edge. */
    inset-inline-end: 0;
    inline-size: 17rem;
    padding: .5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--popover);
    color: var(--popover-foreground);
    box-shadow: var(--shadow-float);
}

.v2-menu__head { padding: .375rem .5rem .5rem; border-block-end: 1px solid var(--border); }
.v2-menu__name { display: block; font-size: 13px; font-weight: 600; }

.v2-menu__mail {
    display: block;
    margin-block-start: .125rem;
    font-size: 11px;
    color: var(--muted-foreground);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* Which books this session writes into. The part worth opening the menu for —
   an operator with two activities has no other way to see which one their next
   document lands in. */
.v2-menu__facts {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .5rem;
    border-block-end: 1px solid var(--border);
    font-size: 11.5px;
}

.v2-menu__facts > div { display: flex; align-items: baseline; gap: .5rem; }
.v2-menu__key { flex-shrink: 0; inline-size: 5.5rem; color: var(--muted-foreground); }

.v2-menu__val {
    min-inline-size: 0;
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 500;
}

/* ── أدوات المستند ─────────────────────────────────────────────────────────
   The design's DropdownMenu of secondary actions, on the profile menu's panel:
   grouped under small labels, one row per action, the key dimmed at the end. */
.v2-tools { position: relative; }

.v2-tools__menu { inline-size: 18rem; padding: .25rem; font-size: 12.5px; }

.v2-tools__label {
    padding: .5rem .5rem .25rem;
    font-size: 11px;
    color: var(--muted-foreground);
}

.v2-tools__label:not(:first-child) { margin-block-start: .25rem; border-block-start: 1px solid var(--border); }

.v2-tools__item {
    display: flex;
    align-items: center;
    gap: .5rem;
    inline-size: 100%;
    padding: .375rem .5rem;
    border: 0;
    border-radius: calc(var(--radius) - 2px);
    background: none;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}

.v2-tools__item .v2-btn__key { margin-inline-start: auto; }
.v2-tools__item:hover:not(:disabled),
.v2-tools__item:focus-visible { background: var(--accent); color: var(--accent-foreground); outline: none; }
.v2-tools__item:disabled { color: var(--muted-foreground); cursor: default; }

/* ── القيد المحاسبي ────────────────────────────────────────────────────────
   Read, not keyed — a plain table in the picker's chrome, debit and credit in
   their own aligned columns so the two totals can be compared at a glance. */
.v2-journal { inline-size: min(820px, 94vw); }
.v2-journal__wrap { min-block-size: 0; overflow: auto; }

.v2-journal__table { inline-size: 100%; border-collapse: collapse; font-size: 12.5px; }
.v2-journal__table th,
.v2-journal__table td { padding: .375rem .5rem; border-block-end: 1px solid var(--border); text-align: start; }
.v2-journal__table thead th { font-size: 11px; font-weight: 500; color: var(--muted-foreground); }
.v2-journal__table .num { text-align: end; font-variant-numeric: tabular-nums; inline-size: 7.5rem; }
.v2-journal__table tfoot th { font-weight: 700; border-block-end: 0; }

.v2-menu__no { margin-inline-start: .375rem; font-size: 10px; color: var(--muted-foreground); }

.v2-menu__warn {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    margin-block-start: .5rem;
    padding: .5rem;
    border: 1px solid color-mix(in oklab, var(--signal) 50%, transparent);
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--signal) 15%, var(--popover));
    color: var(--signal-foreground);
    font-size: 11.5px;
}

.v2-menu__items { display: flex; flex-direction: column; gap: .125rem; margin-block-start: .5rem; }

.v2-menu__item {
    display: flex;
    align-items: center;
    gap: .5rem;
    inline-size: 100%;
    padding: .4375rem .5rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: inherit;
    font: inherit;
    font-size: 12.5px;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}

.v2-menu__item:hover { background: var(--accent); color: var(--accent-foreground); }
.v2-menu__item--out { color: var(--destructive); }
.v2-menu__item--out:hover { background: color-mix(in oklab, var(--destructive) 12%, var(--popover)); color: var(--destructive); }

/* ── the panes ─────────────────────────────────────────────────────────────
   One per open window. The inactive ones are HIDDEN and not unmounted: a tab is
   a screen that is still loaded, and the invoice behind the tab you left has to
   still have its lines in it. display:none rather than visibility, so a hidden
   pane takes no space and its scroll position is its own. */
.v2-pane { display: contents; }
.v2-pane--hidden { display: none; }

/* ── the window strip ──────────────────────────────────────────────────────
   A tab and its close are SIBLINGS. Nesting a button inside a button is invalid
   HTML and the browser un-nests it, which puts the close where nobody aimed. */
.v2-tab { display: inline-flex; align-items: stretch; }

.v2-tab__pick {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .25rem .5rem;
    border: 1px solid transparent;
    border-start-start-radius: var(--radius);
    border-start-end-radius: var(--radius);
    background: none;
    color: var(--muted-foreground);
    font: inherit;
    font-size: 12px;
    white-space: nowrap;
    cursor: pointer;
}

.v2-tab--on .v2-tab__pick {
    border-color: var(--border);
    border-block-end-color: transparent;
    background: var(--surface);
    color: var(--foreground);
    font-weight: 600;
}

/* The dot is the part operators actually read: warm while a document is holding
   unsaved work. A tab with a lit dot is a tab you cannot close without losing
   something, and the close button says so before it does it. */
.v2-tab__dot {
    inline-size: .375rem;
    block-size: .375rem;
    flex-shrink: 0;
    border-radius: 999px;
    background: color-mix(in oklab, var(--muted-foreground) 40%, transparent);
}

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

.v2-tab__name { max-inline-size: 11rem; overflow: hidden; text-overflow: ellipsis; }

.v2-tab__close {
    display: inline-grid;
    place-items: center;
    inline-size: 1.5rem;
    border: 1px solid transparent;
    border-inline-start: 0;
    border-start-end-radius: var(--radius);
    background: none;
    color: var(--muted-foreground);
    font-size: 11px;
    cursor: pointer;
}

.v2-tab--on .v2-tab__close {
    border-color: var(--border);
    border-block-end-color: transparent;
    background: var(--surface);
}

.v2-tab__close:hover { background: var(--destructive); color: var(--destructive-foreground); }

/* A sidebar row is a <button> inside a workspace and an <a> outside one — the two
   must be indistinguishable, so the button is given back what a button takes away. */
button.v2-side__link,
button.v2-side__sublink { inline-size: 100%; border: 0; background: none; font: inherit; text-align: start; cursor: pointer; }
button.v2-side__sublink { font-size: 12.5px; }

/* ── نافذة عرض المستندات ───────────────────────────────────────────────────
   The browse window, from design/app-v2/pages/sales-invoices.html.

   Two columns: the list, and «المستند المحدد» beside it. The side panel is a
   COLUMN and not an overlay because it is read while the list is being moved
   through — an operator arrows down the rows and watches the panel change. An
   overlay would cover the rows it is describing. */
.v2-browse {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 17rem;
    align-items: start;
    gap: .5rem;
}

/* «إخفاء التفاصيل», and every narrow viewport. The list is the screen; the
   panel is the luxury, so the panel is what goes. */
.v2-browse--wide { grid-template-columns: minmax(0, 1fr); }

@media (max-width: 1100px) {
    .v2-browse { grid-template-columns: minmax(0, 1fr); }
    .v2-browse__side { display: none; }
}

.v2-browse__side { position: sticky; inset-block-start: .5rem; }

/* ── the advanced filter ──────────────────────────────────────────────── */
.v2-filters {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .5rem .75rem;
    padding: .625rem .75rem;
    border-block-end: 1px solid var(--border);
    background: color-mix(in oklab, var(--muted) 40%, transparent);
}

.v2-filter { display: flex; flex-direction: column; gap: .25rem; min-inline-size: 0; }

.v2-filter__label {
    font-size: 10.5px;
    font-weight: 600;
    color: var(--muted-foreground);
    letter-spacing: .01em;
}

.v2-filter .v2-input { inline-size: 100%; }

.v2-filters__end {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: .5rem;
}

/* ── «المستند المحدد» ─────────────────────────────────────────────────── */
.v2-detail__no {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding: .5rem .75rem .25rem;
}

.v2-detail__num { font-size: 1.0625rem; font-weight: 700; }
.v2-detail__who {
    padding: 0 .75rem .5rem;
    font-size: 11.5px;
    color: var(--muted-foreground);
    overflow-wrap: anywhere;
}

.v2-detail__rows {
    display: flex;
    flex-direction: column;
    gap: .1875rem;
    padding: .5rem .75rem;
    border-block-start: 1px solid var(--border);
    font-size: 11.5px;
}

.v2-detail__row { display: flex; align-items: baseline; gap: .5rem; }
.v2-detail__key { flex: 1 1 auto; color: var(--muted-foreground); }
.v2-detail__val { font-weight: 600; text-align: end; overflow-wrap: anywhere; }

.v2-detail__acts {
    display: flex;
    flex-direction: column;
    gap: .375rem;
    padding: .5rem .75rem .75rem;
    border-block-start: 1px solid var(--border);
}

.v2-detail__acts .v2-btn { justify-content: center; }

/* ── sortable columns ─────────────────────────────────────────────────── */
.v2-lines th.is-sortable { cursor: pointer; user-select: none; }
.v2-lines th.is-sortable:hover { color: var(--foreground); }
.v2-lines th .v2-sort { margin-inline-start: .1875rem; font-size: 9px; opacity: .8; }

/* ── the key line ─────────────────────────────────────────────────────── */
.v2-keys { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .75rem; }
.v2-key { display: inline-flex; align-items: center; gap: .25rem; }
.v2-key__what { color: var(--muted-foreground); }

/* ── شريط الصنف ────────────────────────────────────────────────────────────
   The live bar under the entry grid, from design/app-v2/pages/sales-invoices_new.html.

   One row, and it sits BETWEEN the lines and the totals because that is where
   the eye already is while a quantity is being typed. Every figure is about the
   part the caret is on and is scoped to the warehouse in front of the operator —
   «do we own one somewhere» answers yes while the shelf is empty. */
.v2-itembar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem 0;
    padding: .375rem .5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--muted) 45%, transparent);
    font-size: 11.5px;
}

.v2-itembar__cell {
    display: inline-flex;
    align-items: baseline;
    gap: .3125rem;
    padding-inline: .625rem;
    border-inline-end: 1px solid var(--border);
    white-space: nowrap;
}

.v2-itembar__cell:last-child { border-inline-end: 0; }
.v2-itembar__label { color: var(--muted-foreground); }
.v2-itembar__label::after { content: ":"; }
.v2-itembar__value { font-weight: 600; }

/* Out of stock is the one figure worth colouring: it is the difference between
   a sale and a promise. */
.v2-itembar__value--bad { color: var(--destructive); }

/* A standing note takes the reserved cell's place — NewPoint's own if/else — so
   it is coloured to say that something is being said, not counted. */
.v2-itembar__cell--note { max-inline-size: 22rem; }
.v2-itembar__cell--note .v2-itembar__value {
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--signal-foreground);
}

.v2-itembar__cell--denied .v2-itembar__value { color: var(--muted-foreground); font-weight: 400; }

.v2-itembar__end { margin-inline-start: auto; display: flex; align-items: center; gap: .375rem; }

/* ── اقتراحات الأصناف ──────────────────────────────────────────────────────
   The list that opens under the item-code cell as it is typed, from
   design/app-v2 — matching parts, and beneath them the alternates of whatever
   matched. «الصنف غير متوفر» is the moment a sale is lost, and the alternates
   are the answer to it; they were a table nobody had ever put on this screen. */
.v2-lines td { position: relative; }

.v2-suggest {
    position: absolute;
    z-index: 30;
    inset-block-start: 100%;
    inset-inline-start: 0;
    min-inline-size: 32rem;
    max-block-size: 20rem;
    overflow-y: auto;
    margin: 0;
    padding: .25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--popover);
    box-shadow: 0 12px 32px rgb(0 0 0 / .18);
    list-style: none;
    scrollbar-width: thin;
}

.v2-suggest__head {
    padding: .25rem .5rem;
    color: var(--muted-foreground);
    font-size: 10.5px;
    font-weight: 600;
}

.v2-suggest__row {
    display: grid;
    grid-template-columns: 140px minmax(0, 1fr) 72px 72px;
    align-items: center;
    gap: .5rem;
    padding: .3125rem .5rem;
    border-radius: var(--radius);
    font-size: 12px;
    cursor: pointer;
}

.v2-suggest__row:hover { background: var(--muted); }
.v2-suggest__row--on { background: var(--accent); color: var(--accent-foreground); }
.v2-suggest__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-suggest__stock { text-align: end; color: var(--success); }
.v2-suggest__stock--out { color: var(--destructive); }
.v2-suggest__price { text-align: end; color: var(--muted-foreground); }

/* «بديل» — the badge that says this row is not what was asked for. */
.v2-suggest__tag {
    padding: .0625rem .3125rem;
    border-radius: calc(var(--radius) - 2px);
    background: color-mix(in oklab, var(--signal) 22%, var(--surface));
    color: var(--signal-foreground);
    font-size: 10px;
}

/* While the item-code suggestions are open, neither the panel nor its body may clip
   them — the panel hides overflow for its rounded corners and the body scrolls the
   table, and an absolutely-positioned dropdown is cut off by both. */
.v2-panel--open,
.v2-panel--open .v2-panel__body { overflow: visible; }

/* A header field that carries a dropdown has to be the thing it is measured from. */
.v2-field__value { position: relative; }

/* The header lists are the item list in a narrower shape: a code, a name, and one
   fact about it — the series a branch numbers from, the branch an employee works
   in, the account a tender settles to, the customer a price was given to. */
.v2-suggest--field { min-inline-size: 24rem; }
.v2-suggest--field .v2-suggest__row { grid-template-columns: 64px minmax(0, 1fr) auto; }

/* آخر أسعار البيع: the same customer's own prices, which is the question an
   argument at the counter is actually about. */
.v2-suggest__row--same .v2-suggest__name,
.v2-suggest__row--same .num { color: var(--success); font-weight: 600; }

/* ── تثبيت النافذة ──────────────────────────────────────────────────────────
   The pin is against EVICTION: the strip caps at eight and drops the oldest clean
   tab, which is exactly the window somebody keeps open all day. Shown on hover
   like the design does, and always once it is on — a pinned tab has to say so
   when nothing is hovering it. */
.v2-tab__pin {
    display: inline-flex;
    align-items: center;
    padding: .125rem;
    border: 0;
    border-radius: calc(var(--radius) - 2px);
    background: none;
    color: var(--muted-foreground);
    cursor: pointer;
    opacity: 0;
    transition: opacity .12s, color .12s;
}

.v2-tab:hover .v2-tab__pin,
.v2-tab__pin:focus-visible { opacity: 1; }
.v2-tab__pin:hover { background: var(--accent); color: var(--accent-foreground); }

.v2-tab__pin--on { opacity: 1; color: var(--primary); }
.v2-tab--pinned .v2-tab__pick { font-weight: 600; }

/* Alt+N, as the design labels every window. */
.v2-tab__key {
    font-size: 9.5px;
    color: color-mix(in oklab, var(--muted-foreground) 70%, transparent);
}

/* ── foundations from the design's system (design styles.css) ──────────────── */

/* A visible focus ring on EVERY control, not only .v2-btn and .v2-input.
   :where() carries zero specificity, so a component that styles its own focus
   still wins — this only fills in where nothing did. A keyboard-first ERP with
   invisible focus is an ERP whose operators lose their place. */
:where(button, a[href], input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 2px solid var(--ring);
    outline-offset: 2px;
}

/* The design's «label-caps». Its letter-spacing and uppercase apply to LATIN only:
   letter-spacing on Arabic script pulls apart the cursive joins and renders the
   word as disconnected letters. The design sets it unconditionally; Arabic is this
   application's first language, so the rule is scoped to :lang(en). */
.v2-label-caps {
    font-size: 11px;
    font-weight: 600;
    color: var(--muted-foreground);
}

:lang(en) .v2-label-caps {
    letter-spacing: .08em;
    text-transform: uppercase;
}

/* The design's «grid-zebra» and «row-hover», for long lists read across. */
.v2-zebra > tbody > tr:nth-child(even) { background: color-mix(in oklab, var(--muted) 55%, transparent); }
.v2-row-hover > tbody > tr:hover { background: color-mix(in oklab, var(--accent) 45%, transparent); }

/* Alt+N tips appear while Alt is HELD (quick-search.js toggles .alt-held) — a
   small badge over the tab's corner, so showing it never reflows the strip. */
.v2-tab { position: relative; }

.v2-tab__key {
    position: absolute;
    inset-block-start: 1px;
    inset-inline-end: 2px;
    padding: 0 .25rem;
    border-radius: var(--radius-sm);
    background: var(--foreground);
    color: var(--background);
    font-size: 9.5px;
    line-height: 1.5;
    opacity: 0;
    pointer-events: none;
    transition: opacity .1s;
}

.alt-held .v2-tab__key { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
    .v2-tab__key { transition: none; }
}

/* ── طيّ القائمة ────────────────────────────────────────────────────────────
   data-sidebar on <html>, written by ui.js before first paint. Collapsed, the
   rail keeps its icons and nothing else; every row carries a title, so the
   name is one hover away. */
.v2-side { transition: inline-size .18s ease; }

:root[data-sidebar="collapsed"] .v2-side { inline-size: 3.5rem; }

:root[data-sidebar="collapsed"] :is(.v2-side__head > div, .v2-side__group, .v2-side__label,
    .v2-side__toggle, .v2-side__sublist, .v2-side__card, .v2-side__no) {
    display: none;
}

:root[data-sidebar="collapsed"] :is(.v2-side__head, .v2-side__foot, .v2-side__row, .v2-side__link) {
    justify-content: center;
}

:root[data-sidebar="collapsed"] :is(.v2-side__head, .v2-side__link) { padding-inline: 0; }

/* One glyph per state. Only LEFT-panel glyphs exist in lucide, and in RTL the
   rail sits on the right — so the glyph is mirrored, rather than borrowing the
   design's left-pointing icon on a right-hand panel. */
.v2-collapse__open { display: none; }
:root[data-sidebar="collapsed"] .v2-collapse__shut { display: none; }
:root[data-sidebar="collapsed"] .v2-collapse__open { display: inline; }
[dir="rtl"] .v2-collapse .v2-icon { transform: scaleX(-1); }

/* Below 1024px the rail is not drawn at all, so there is nothing to collapse. */
@media (max-width: 1023.98px) { .v2-collapse { display: none; } }

@media (prefers-reduced-motion: reduce) { .v2-side { transition: none; } }

/* ── قائمة النوافذ ──────────────────────────────────────────────────────────
   The count badge becomes the window menu; it reuses the profile menu's panel. */
.v2-winmenu { position: relative; }
.v2-winmenu > .v2-btn { gap: .25rem; }
.v2-menu__item--rule {
    margin-block-start: .25rem;
    padding-block-start: .5rem;
    border-block-start: 1px solid var(--border);
}
/* The window menu's scrim is a button (so it is a labelled control), not the
   profile menu's div — strip the button chrome so it stays invisible. */
.v2-winmenu .v2-profile__scrim { background: transparent; border: 0; padding: 0; cursor: default; }

/* A date the field could not read: said in colour as well as in its title, because the document
   will not post until it is corrected and the operator should see why before pressing save. */
.v2-input--invalid { border-color: var(--destructive); color: var(--destructive); }

/* ── LookupField — one box, «الكود · الاسم», searchable (doc-screen.tsx HeaderLookup) ──────── */
.v2-lookup { position: relative; display: flex; flex: 1 1 auto; min-inline-size: 0; align-items: center; }
.v2-lookup__input { flex: 1 1 auto; }

.v2-lookup__list {
    position: absolute;
    inset-block-start: 100%;
    inset-inline: 0;
    z-index: 50;
    margin-block-start: .25rem;
    min-inline-size: 320px;
    max-block-size: 18rem;
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-float);
    font-size: 12px;
    scrollbar-width: thin;
}

.v2-lookup__group {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
    padding: .25rem .5rem;
    border-block-end: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
    background: color-mix(in oklab, var(--muted) 90%, transparent);
    color: var(--muted-foreground);
    font-size: 11px;
    font-weight: 600;
}

.v2-lookup__row {
    display: flex;
    inline-size: 100%;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .25rem .5rem;
    border: 0;
    border-block-end: 1px solid color-mix(in oklab, var(--border) 50%, transparent);
    background: none;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}

.v2-lookup__row:last-child { border-block-end: 0; }
.v2-lookup__row:hover { background: color-mix(in oklab, var(--accent) 60%, transparent); }
.v2-lookup__row.is-on { background: color-mix(in oklab, var(--accent) 70%, transparent); }
.v2-lookup__name { display: flex; min-inline-size: 0; flex: 1 1 auto; align-items: center; gap: .375rem; overflow: hidden; }
.v2-lookup__branch { inline-size: .75rem; flex: 0 0 auto; }
.v2-lookup__text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-lookup__hint { flex: 0 0 auto; margin-inline-start: .375rem; color: var(--muted-foreground); font-size: 10.5px; }
.v2-lookup__code { flex: 0 0 auto; color: var(--muted-foreground); font-size: 11px; direction: ltr; }
.v2-lookup__empty { margin: 0; padding: .75rem .5rem; color: var(--muted-foreground); text-align: center; }

/* ── the document grid as the design draws it: flat cells, zebra rows, small row tools ───────── */
.v2-lines td { padding: .125rem .25rem; }
.v2-lines tbody tr:nth-child(even):not(.is-current):not(.v2-lines__empty) {
    background: color-mix(in oklab, var(--muted) 25%, transparent);
}
.v2-lines td .v2-input:not([readonly]) {
    block-size: 1.5rem;
    border-color: transparent;
    background: transparent;
    padding-inline: .375rem;
}
.v2-lines td .v2-input:not([readonly]):focus-visible { border-color: var(--ring); background: var(--surface); }

.v2-rowtools { white-space: nowrap; }
.v2-rowbtn {
    display: inline-grid;
    place-items: center;
    inline-size: 1.25rem;
    block-size: 1.25rem;
    margin-inline-end: .125rem;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) - 3px);
    background: var(--surface);
    color: var(--muted-foreground);
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
}
.v2-rowbtn:hover { background: color-mix(in oklab, var(--accent) 60%, transparent); color: var(--foreground); }
.v2-rowbtn:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.v2-rowbtn--danger:hover { border-color: color-mix(in oklab, var(--destructive) 50%, transparent); color: var(--destructive); }

/* ── the records screen ────────────────────────────────────────────────────
   The design's MasterScreen: a sortable heading, a filter under each column,
   an «إجراء» column, and a stopped record read as out of use rather than hidden. */
.v2-sorthead {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.v2-sorthead:hover { color: var(--foreground); }
.v2-sorthead:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: 2px; }

.v2-lines__filters th { padding-block: .25rem; background: var(--muted); }
.v2-lines__filters .v2-input { block-size: 1.625rem; font-size: 11.5px; }

.v2-lines tr.is-off > td { color: var(--muted-foreground); }

.v2-records__count { font-size: 12px; color: var(--muted-foreground); white-space: nowrap; }

.v2-records__audit {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1.25rem;
    padding: .375rem .75rem;
    font-size: 11.5px;
    color: var(--muted-foreground);
}

.v2-records__audit b { font-weight: 600; color: var(--foreground); }

/* One line per record, zebra, as the design's MasterScreen table (grid-zebra): a name that wraps
   into three lines makes a list of forty customers a page of eight. */
.v2-records__table td { white-space: nowrap; }
.v2-records__table thead th { font-size: 11px; font-weight: 600; white-space: nowrap; }
.v2-records__table thead tr { background: var(--muted); }
.v2-records__table tbody tr { background: var(--surface); }

/* Opaque, and as specific as the grid's own zebra rule so this one wins: the pinned «إجراء» cell below
   takes its row's colour, and a translucent one would show the columns scrolling underneath it. */
.v2-records__table tbody tr:nth-child(even):not(.is-current):not(.v2-lines__empty) {
    background: color-mix(in oklab, var(--muted) 55%, var(--surface));
}

/* «إجراء» stays in view. A customer list is thirteen columns wide and scrolls sideways, and the design
   keeps the row's actions where they can be reached without scrolling to find them. */
.v2-records__table th:last-child,
.v2-records__table td:last-child {
    position: sticky;
    inset-inline-end: 0;
    z-index: 1;
    border-inline-start: 1px solid var(--border);
    background: inherit;
}

.v2-records__bar { justify-content: space-between; gap: .75rem; }
.v2-records__search { inline-size: min(20rem, 100%); }

.v2-records__state { font-size: 12px; }
.v2-records__state.v2-stopped { color: var(--muted-foreground); }

/* ── the key line (the design's KeyBar) ─────────────────────────────────────── */
.v2-keyhints { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .875rem; }
.v2-keyhint { display: inline-flex; align-items: center; gap: .375rem; }

.v2-keyhint kbd {
    padding: 0 .375rem;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--muted);
    color: var(--foreground);
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 10.5px;
    font-weight: 600;
}

/* ── the window strip, as window-tabs.tsx draws it ──────────────────────────────
   One box per window, open at the bottom and sitting on the strip's line: the title, «Alt+N»
   dimmed, a pin that shows on hover and ✕. The earlier rules drew the tab AND its two buttons as
   boxes of their own, which is where the double frame came from. */
.v2-tabs__list { align-items: flex-end; padding-block: .25rem 0; }

.v2-tab {
    align-items: center;
    gap: .25rem;
    padding: .25rem .5rem;
    border: 1px solid transparent;
    border-block-end: 0;
    border-radius: var(--radius) var(--radius) 0 0;
    background: color-mix(in oklab, var(--muted) 50%, transparent);
    color: var(--muted-foreground);
    font-size: 12px;
    font-weight: 400;
}

.v2-tab:hover { background: var(--muted); }

.v2-tab--on,
.v2-tab--on:hover {
    border-color: var(--border);
    background: var(--surface);
    color: var(--foreground);
    font-weight: 600;
}

.v2-tab__pick,
.v2-tab--on .v2-tab__pick {
    gap: .25rem;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    color: inherit;
    font-weight: inherit;
}

.v2-tab__name { max-inline-size: 180px; }
/* Always shown, in place, as the design writes it beside each title — not a badge that appears only
   while Alt is held. */
.v2-tab .v2-tab__key {
    position: static;
    inset: auto;
    padding: 0;
    border: 0;
    background: none;
    opacity: 1;
    transform: none;
    font-size: 10px;
    font-weight: 400;
    color: color-mix(in oklab, var(--muted-foreground) 70%, transparent);
}

/* The unsaved-work dot stays, and only when there is unsaved work: a dot on every tab says nothing. */
.v2-tab__dot { display: none; }
.v2-tab__dot--dirty { display: inline-block; }

.v2-tab__pin,
.v2-tab__close,
.v2-tab--on .v2-tab__close {
    display: inline-grid;
    place-items: center;
    inline-size: auto;
    padding: .125rem;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--muted-foreground);
    font-size: 10px;
    cursor: pointer;
}

.v2-tab__pin { opacity: 0; }
.v2-tab:hover .v2-tab__pin,
.v2-tab__pin--on,
.v2-tab__pin:focus-visible { opacity: 1; }
.v2-tab__pin:hover { background: var(--accent); color: var(--accent-foreground); }

.v2-tab__close:hover {
    background: color-mix(in oklab, var(--destructive) 10%, transparent);
    color: var(--destructive);
}

.v2-tabs__end { padding-block: .25rem; }

.v2-tabs__end .v2-btn {
    block-size: auto;
    gap: .25rem;
    padding: .25rem .5rem;
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) - 1px);
    background: none;
    color: var(--muted-foreground);
    font-size: 11px;
    text-decoration: none;
}

.v2-tabs__end .v2-btn:hover { background: var(--muted); color: var(--foreground); }

/* ── the record form, as master-screen.tsx's EditDialog draws it ────────────────
   A grey head with the title and ✕, folder tabs, the fields three across with the label ABOVE
   the box, and a grey foot that says what the star means beside «إلغاء» and «حفظ». */
.v2-form { inline-size: min(56rem, 94vw); gap: 0; padding: 0; overflow: hidden; }

.v2-form__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .5rem .75rem;
    border-block-end: 1px solid var(--border);
    background: color-mix(in oklab, var(--muted) 70%, transparent);
}

.v2-form__title { margin: 0; font-size: 14px; font-weight: 600; }

.v2-form__close {
    display: inline-grid;
    place-items: center;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--muted-foreground);
    cursor: pointer;
}

.v2-form__close:hover { background: var(--muted); color: var(--foreground); }

.v2-form__tabs {
    display: flex;
    gap: .25rem;
    padding: .5rem .5rem 0;
    border-block-end: 1px solid var(--border);
    background: var(--surface);
}

.v2-form__tab {
    margin-block-end: -1px;
    padding: .375rem .75rem;
    border: 1px solid transparent;
    border-block-end: 0;
    border-radius: calc(var(--radius) - 2px) calc(var(--radius) - 2px) 0 0;
    background: none;
    color: var(--muted-foreground);
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
}

.v2-form__tab:hover { background: color-mix(in oklab, var(--accent) 40%, transparent); }

.v2-form__tab--on,
.v2-form__tab--on:hover {
    border-color: var(--border);
    background: var(--surface);
    color: var(--primary);
    font-weight: 600;
}

.v2-form__missing {
    padding: .5rem .75rem;
    border-block-end: 1px solid color-mix(in oklab, var(--destructive) 30%, transparent);
    background: color-mix(in oklab, var(--destructive) 10%, transparent);
    color: var(--destructive);
    font-size: 12px;
}

.v2-form__body { min-block-size: 0; max-block-size: 60vh; overflow-y: auto; padding: .75rem; }

.v2-form__grid { display: grid; gap: .625rem; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 768px) { .v2-form__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.v2-form__grid .v2-field { display: flex; flex-direction: column; align-items: stretch; gap: .125rem; }
.v2-form__grid .v2-field__label { font-size: 11px; font-weight: 500; }
.v2-form__grid .v2-input { block-size: 2rem; }

.v2-form__grid .v2-field--flag {
    flex-direction: row-reverse;
    justify-content: flex-end;
    align-items: center;
    align-self: end;
    gap: .5rem;
    padding-block-end: .25rem;
}

.v2-form__grid .v2-field--flag .v2-field__label { font-size: 12.5px; color: var(--foreground); }

.v2-form__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .5rem .75rem;
    border-block-start: 1px solid var(--border);
    background: color-mix(in oklab, var(--muted) 60%, transparent);
}

.v2-form__hint { font-size: 11px; color: var(--muted-foreground); }
.v2-form__actions { display: flex; gap: .5rem; }

/* «+ نافذة» and the window menu on ONE line. The strip's end had no rule of its own and
   the count used to be an inline badge; the menu is a block, and it wrapped under the
   button. */
.v2-tabs__end { display: flex; align-items: center; gap: .25rem; flex-shrink: 0; }

/* «الاختصارات ?» on the status bar — a quiet control on a quiet bar. */
.v2-status__keys {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: 0 .25rem;
    border: 0;
    border-radius: calc(var(--radius) - 2px);
    background: transparent;
    color: inherit;
    font: inherit;
    cursor: pointer;
}
.v2-status__keys:hover { background: var(--muted); color: var(--foreground); }

/* ── a report — ReportScreenV2 ───────────────────────────────────────────
   The design's ReportScreen: the criteria in one panel (not its bottom tabs), then the
   result as a page — company, report and period, the table, the figures, who printed it.
   On paper only the page goes: the criteria, the buttons and the shell are furniture. */
.v2-report { display: flex; flex-direction: column; gap: 1rem; }

.v2-report__hint { font-size: 11px; font-weight: 400; color: var(--muted-foreground); }

.v2-report__fields {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: .75rem 1rem;
    padding: .875rem 1rem 1rem;
}
.v2-report__field { display: flex; flex-direction: column; gap: .3125rem; min-inline-size: 0; }
.v2-report__field--wide { grid-column: span 2; }
@media (max-width: 560px) { .v2-report__field--wide { grid-column: auto; } }

/* The result is a PAGE, as the design draws it: paper on a muted ground, the letterhead in its
   own ruled box, the figures closing the table with a heavier rule. */
.v2-report__sheet {
    padding: 1.25rem;
    background: var(--surface);
    box-shadow: 0 1px 2px color-mix(in oklab, var(--foreground) 8%, transparent);
}
.v2-report__sheet > .v2-panel__body { border: 1px solid var(--border); border-block-end: 0; }

/* The document's totals bar sticks and bleeds to the panel's edges; on a page it closes the
   table and stays inside the page's rule. */
.v2-report .v2-totals { position: static; margin-inline: 0; backdrop-filter: none; }
.v2-report__sheet > .v2-totals {
    border: 1px solid var(--border);
    border-block-start: 2px solid var(--primary);
    background: color-mix(in oklab, var(--muted) 60%, var(--surface));
}

.v2-report__letterhead {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: .5rem 1rem;
    margin-block-end: .75rem;
    padding: .75rem 1rem;
    border: 1px solid var(--border);
}
.v2-report__company strong { color: var(--primary); }
.v2-report__company,
.v2-report__heading { display: flex; flex-direction: column; gap: .125rem; }
.v2-report__company strong { font-size: 13px; }
.v2-report__company span,
.v2-report__heading span { font-size: 11.5px; color: var(--muted-foreground); }
.v2-report__heading { align-items: center; text-align: center; }
.v2-report__heading strong { font-size: 1.0625rem; }
.v2-report__verdict { display: flex; justify-content: flex-end; }
@media (max-width: 640px) {
    .v2-report__letterhead { grid-template-columns: 1fr; }
    .v2-report__heading { align-items: flex-start; text-align: start; }
    .v2-report__verdict { justify-content: flex-start; }
}

.v2-report__lead { border-block-end: 1px solid var(--border); }
.v2-report__alert { margin: .75rem 1rem 0; }

.v2-report__table th,
.v2-report__table td { white-space: nowrap; }
.v2-report__table td:nth-child(2) { white-space: normal; min-inline-size: 12rem; }
.v2-report__table tbody tr:nth-child(even):not(.v2-lines__empty) {
    background: color-mix(in oklab, var(--muted) 55%, var(--surface));
}

/* The row classes carry meaning, so each looks like what it says. */
.v2-report__table tr.is-opening td { font-weight: 600; background: var(--muted); }
.v2-report__table tr.is-section td {
    font-weight: 700;
    background: color-mix(in oklab, var(--primary) 10%, var(--surface));
    color: var(--primary);
}
.v2-report__table tr.is-noncost td { color: var(--muted-foreground); font-style: italic; }
.v2-report__table tr.is-negative td { color: var(--destructive); }

.v2-report__foot {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: .25rem 1rem;
    padding: .5rem .25rem 0;
    font-size: 11px;
    color: var(--muted-foreground);
}

/* ── a ledger document — VoucherScreenV2 on the design's LedgerScreen ────
   The header is one bordered panel with the label ABOVE each box (Field: text-[11px] semibold
   muted), four to a row; the note keeps its label beside it across the full width. The foot sits
   INSIDE the lines panel: four figure boxes, the count, and the document's figure with its save. */
.v2-ledger__head { padding: .75rem; }
.v2-fields--stacked { gap: .5rem; }
@media (min-width: 640px)  { .v2-fields--stacked { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .v2-fields--stacked { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.v2-fields--stacked .v2-field { grid-template-columns: minmax(0, 1fr); gap: .125rem; align-items: start; }
.v2-fields--stacked .v2-field__label { font-size: 11px; font-weight: 600; color: var(--muted-foreground); }
.v2-fields--stacked .v2-input { block-size: 2rem; font-size: 12.5px; }
.v2-fields--stacked .v2-field--note {
    grid-template-columns: minmax(0, 88px) minmax(0, 1fr);
    align-items: center;
    gap: .5rem;
}
.v2-fields--stacked .v2-field--note .v2-field__label { font-size: 12px; font-weight: 500; color: var(--foreground); }
.v2-input--amount { font-weight: 700; text-align: end; }

.v2-ledger__title { font-size: 13px; font-weight: 700; }

.v2-ledger__foot {
    position: sticky;
    inset-block-end: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem;
    margin: 0;
    padding: .5rem .75rem;
    border-block-start: 1px solid var(--border);
    background: color-mix(in oklab, var(--surface) 95%, transparent);
}
.v2-ledger__foot .v2-chips { font-size: 11px; }
.v2-ledger__count { font-size: 11.5px; color: var(--muted-foreground); }
.v2-ledger__end { display: flex; align-items: center; gap: .75rem; margin-inline-start: auto; }
.v2-ledger__foot .v2-total--final {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: .25rem .75rem;
    border: 0;
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--accent) 50%, var(--surface));
}
.v2-ledger__foot .v2-total--final .v2-total__label { font-size: 10.5px; font-weight: 600; }
.v2-ledger__foot .v2-total--final .v2-total__value { font-size: 1.5rem; font-weight: 700; line-height: 1.2; }

/* Fig — a figure in its own tinted box, the tone saying which side it is. */
.v2-fig {
    display: flex;
    flex-direction: column;
    padding: .25rem .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--muted) 40%, var(--surface));
}
.v2-fig__label { font-size: 10.5px; color: var(--muted-foreground); }
.v2-fig__value { font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
.v2-fig--debit  { border-color: color-mix(in oklab, var(--primary) 40%, transparent); background: color-mix(in oklab, var(--primary) 10%, var(--surface)); }
.v2-fig--credit { border-color: color-mix(in oklab, var(--signal) 40%, transparent); background: color-mix(in oklab, var(--signal) 10%, var(--surface)); }
.v2-fig--danger { border-color: color-mix(in oklab, var(--destructive) 50%, transparent); background: color-mix(in oklab, var(--destructive) 10%, var(--surface)); }

/* الرصيد الافتتاحي — the filters sit in the panel's band beside its title. */
.v2-ob { display: flex; flex-direction: column; gap: 1rem; }
.v2-ob__bar { flex-wrap: wrap; justify-content: flex-start; gap: .5rem; }
.v2-ob__filters { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.v2-ob__search { inline-size: 14rem; block-size: 1.75rem; font-size: 12px; }
.v2-ob__select { inline-size: auto; block-size: 1.75rem; font-size: 12px; }
.v2-ob .v2-panel__end { margin-inline-start: auto; }
.v2-ob__entry td { background: color-mix(in oklab, var(--primary) 5%, var(--surface)); }
.v2-ob .v2-panel__body { max-block-size: 46vh; }
.v2-confirm kbd { margin-inline: .25rem; }

/* شريط بيانات المستند. */
.v2-audit {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem 1.25rem;
    padding: .375rem .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: color-mix(in oklab, var(--muted) 40%, var(--surface));
    font-size: 11px;
    color: var(--muted-foreground);
}
.v2-audit b { font-weight: 600; color: var(--foreground); }

@media print { .v2-audit, .v2-ledger__foot .v2-btn { display: none; } }

/* ── the account lists' figure cards — AccountsScreen's Kpi ────────────
   grid-panel p-3: a small caps label and a text-xl semibold figure, green for open and red for
   stopped. Plain cards — not the dashboard's railed KPI. */
.v2-kpis { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.v2-kpicard {
    padding: .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}
.v2-kpicard__label {
    margin: 0;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--muted-foreground);
}
.v2-kpicard__value { margin: .25rem 0 0; font-size: 1.25rem; font-weight: 600; }
.v2-kpicard__value--ok { color: var(--success); }
.v2-kpicard__value--bad { color: var(--destructive); }
.v2-records__status { inline-size: auto; min-inline-size: 8rem; block-size: 2rem; font-size: 12.5px; }

/* ── found by photographing every screen on the customer's data, light and dark ──────────── */

/* Native controls follow the theme: without it an unticked checkbox, a date picker and a
   scrollbar stay white on the dark page. */
:root[data-theme="dark"] { color-scheme: dark; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { color-scheme: dark; } }

/* A tinted badge's text is the tint itself, lifted toward the foreground in the dark: the light
   theme's dark-on-pale reads as dark-on-dark there («خاضع للضريبة», a refusal). */
:root[data-theme="dark"] .v2-badge--signal { color: color-mix(in oklab, var(--signal) 70%, var(--foreground)); }
:root[data-theme="dark"] .v2-badge--bad { color: color-mix(in oklab, var(--destructive) 55%, var(--foreground)); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .v2-badge--signal { color: color-mix(in oklab, var(--signal) 70%, var(--foreground)); }
    :root:not([data-theme="light"]) .v2-badge--bad { color: color-mix(in oklab, var(--destructive) 55%, var(--foreground)); }
}

/* A number box's placeholder is words: the mono face has no Arabic, so the letters came apart. */
.app-v2 .num::placeholder { font-family: var(--font-sans); letter-spacing: normal; }

/* «الأسطر 3», not «الأسطر3». The figure is LTR, so its margin-inline-start lands on its LEFT —
   away from the label. A gap on the pair holds in both directions. */
.v2-panel__foot span:has(> .num) { display: inline-flex; align-items: baseline; gap: .375rem; }
.v2-panel__foot span > .num { margin-inline-start: 0 !important; }

/* «الحالة» keeps its width: with the actions column sticky and every cell nowrap, the auto
   table layout squeezed it to one clipped letter on a wide list. */
.v2-records__statecol { min-inline-size: 4.25rem; }

/* …and it stays in view beside «إجراء». On a list wider than its panel the sticky actions column
   covered the state column and left one clipped letter of «نشط» showing between them. The actions
   column gets a fixed width so the state column can sit exactly against it. */
.v2-records__table th:last-child,
.v2-records__table td:last-child { inline-size: 92px; min-inline-size: 92px; max-inline-size: 92px; }
.v2-records__table th.v2-records__statecol,
.v2-records__table td.v2-records__statecol {
    position: sticky;
    inset-inline-end: 92px;
    z-index: 1;
    background: inherit;
}
.v2-records__table thead th.v2-records__statecol { z-index: 2; background: var(--muted); }

.v2-tenants__toggle { padding-block: 0; block-size: 1.5rem; }

/* The list's two date boxes, the width the browser's inputs had. */
.v2-list__date { display: inline-block; inline-size: 150px; }

/* ── the printed document — Print.razor on the design's print sheet ─────
   doc-print.tsx and the design's print rules. On screen the sheet is the paper it will be — white,
   black ink, ruled tables — whatever the theme; on paper the actions go and only the sheet prints. */
.v2-print {
    min-block-size: 100vh;
    padding: 1rem;
    background: var(--background);
    color: var(--foreground);
    font-family: var(--font-sans);
}
.v2-print .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; direction: ltr; }
.v2-print__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    max-inline-size: 210mm;
    margin: 0 auto .75rem;
}
.v2-print__hint { font-size: 11.5px; color: var(--muted-foreground); }
.v2-print .print-sheet {
    max-inline-size: 210mm;
    margin: 0 auto;
    padding: 12mm;
    border: 1px solid var(--border);
    background: #fff;
    color: #000;
    font-size: 11px;
    box-shadow: 0 1px 3px rgb(0 0 0 / 12%);
}
.v2-print .print-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-block-end: 3mm;
    padding-block-end: 3mm;
    border-block-end: 2px solid #000;
}
.v2-print .print-org { font-size: 18px; font-weight: 700; }
.v2-print .print-sub { font-size: 10px; }
.v2-print .print-title { text-align: end; }
.v2-print .print-title h1 { margin: 0; font-size: 15px; font-weight: 700; }
.v2-print .print-meta,
.v2-print .print-grid,
.v2-print .print-totals { inline-size: 100%; border-collapse: collapse; }
.v2-print .print-meta th, .v2-print .print-meta td,
.v2-print .print-grid th, .v2-print .print-grid td,
.v2-print .print-totals th, .v2-print .print-totals td {
    padding: 1.2mm 2mm;
    border: 1px solid #555;
    text-align: start;
}
.v2-print .print-meta th, .v2-print .print-grid th, .v2-print .print-totals th {
    background: #eee;
    font-weight: 600;
    white-space: nowrap;
}
.v2-print .print-meta { margin-block-end: 3mm; }
.v2-print .print-grid td.num, .v2-print .print-grid th.num,
.v2-print .print-totals td.num { text-align: end; }
.v2-print .print-foot {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 4mm;
    margin-block-start: 3mm;
}
.v2-print .print-totals { inline-size: 70mm; }
.v2-print .print-grand th, .v2-print .print-grand td { background: #ddd; font-weight: 700; }
.v2-print .print-words { flex: 1; display: flex; flex-direction: column; gap: 2mm; }
.v2-print .print-sign { display: flex; flex-wrap: wrap; gap: 8mm; margin-block-start: 6mm; font-size: 10px; }
.v2-print .print-qr img { display: block; inline-size: 26mm; block-size: 26mm; }

/* The list print: its letterhead choice and layout beside the buttons, the letterhead image across
   the sheet, the list's title, what it was narrowed by, and who printed it at the foot. */
.v2-print__choice { display: inline-flex; align-items: center; gap: .375rem; font-size: 12px; color: var(--muted-foreground); }
.v2-print__choice .v2-input { inline-size: auto; block-size: 1.875rem; font-size: 12px; }
.v2-print__letterhead { display: block; inline-size: 100%; block-size: auto; margin-block-end: 3mm; }
.v2-print__report-title { margin: 0 0 2mm; font-size: 15px; font-weight: 700; text-align: center; }
.v2-print__narrowed { margin-block-end: 2mm; font-size: 10px; text-align: center; }
/* A list is as wide as its columns: the customers list is thirteen of them, and on a portrait
   210mm sheet with every cell on one line it ran off both edges of the paper. So a list prints
   landscape — a named page, so the invoice stays portrait — and its cells may wrap. */
/* inline-size: the legacy .sheet still fixes its width at 190mm, which held the list sheet portrait
   whatever its max. Codes and figures stay on one line — breaking «1210010001» into four lines
   makes a number nobody can read; only the words wrap, and only between words. */
.v2-print .print-sheet { inline-size: 100%; }
.v2-print .sheet--list { max-inline-size: 297mm; page: list; }
.v2-print .sheet--list .print-grid { font-size: 10px; }
.v2-print .sheet--list .print-grid td { white-space: normal; overflow-wrap: normal; }
.v2-print .sheet--list .print-grid td.num,
.v2-print .sheet--list .print-grid th { white-space: nowrap; }
@page list { size: A4 landscape; margin: 10mm; }
.v2-print__foot {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 1mm 4mm;
    margin-block-start: 3mm;
    padding-block-start: 2mm;
    border-block-start: 1px solid #555;
    font-size: 9.5px;
}

@media print {
    .v2-print { padding: 0; background: #fff; min-block-size: 0; }
    .v2-print .no-print { display: none !important; }
    .v2-print .print-sheet { max-inline-size: none; padding: 0; border: 0; box-shadow: none; }
    @page { margin: 12mm; }
}

/* ── the whole menu — Menu.razor on the new shell ─────────────────────────
   One module page (ModuleScreenV2's panels) per module. It keeps the legacy class names the suites
   use, so the legacy rules for them in app.css — a 220px grid, a tinted heading bar, a tall link —
   are undone here rather than left to fight the panels. */
.v2-allmenu { display: flex; flex-direction: column; gap: 1.25rem; }
.v2-allmenu__module { display: flex; flex-direction: column; gap: .625rem; }
.v2-allmenu__title { display: flex; align-items: center; gap: .5rem; margin: 0; font-size: 14px; font-weight: 700; }
.v2-allmenu__title a { color: inherit; text-decoration: none; }
.v2-allmenu__title a:hover { color: var(--primary); }
@media (min-width: 900px) { .v2-allmenu .v2-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.v2-allmenu .menu__group { border-radius: var(--radius); overflow: visible; }
.v2-allmenu .menu__heading {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0;
}
.v2-allmenu .menu__module { color: var(--muted-foreground); font-weight: 500; }
.v2-allmenu .menu__link { min-block-size: 0; padding: 7px .75rem; border-radius: 0; }
.v2-allmenu .menu__link:hover { background: var(--muted); }
.v2-btn.menu__platform { color: inherit; font-size: 12.5px; text-decoration: none; }

.v2-wasted__empty { align-self: end; padding-block: .375rem; }
.v2-report__field.v2-check { flex-direction: row; align-items: center; gap: .5rem; }

/* ── users, grants and period locks ────────────────────────────────────
   بيانات المستخدمين: the records list and the tabbed dialog, with ticked lists for screens and
   permissions. صلاحيات المستخدمين: a bar of four, then the matrix with tinted group rows. الإقفالات
   الفترية: the periods table beside a 24rem panel. */
.v2-form__section {
    margin: .75rem 0 .25rem;
    font-size: 12px;
    font-weight: 700;
    color: var(--primary);
}
.v2-form__section:first-child { margin-block-start: 0; }
.v2-form__checks { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
.v2-check { display: flex; align-items: center; gap: .5rem; padding: .25rem 0; font-size: 12.5px; cursor: pointer; }
.v2-check input { accent-color: var(--primary); }
.v2-check .num { margin-inline-start: auto; font-size: 11px; color: var(--muted-foreground); }
.v2-check__hint { margin-inline-start: auto; font-size: 10.5px; color: var(--signal); }
.v2-users__nosignin { color: var(--signal); font-weight: 600; }

.v2-grants { display: flex; flex-direction: column; gap: .75rem; }
.v2-grants__bar { display: grid; align-items: end; gap: .75rem; padding: .75rem; }
@media (min-width: 640px)  { .v2-grants__bar { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .v2-grants__bar { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.v2-grants__field { display: flex; flex-direction: column; gap: .25rem; }
.v2-grants__field .v2-input { block-size: 2rem; font-size: 12.5px; }
.v2-grants__count { font-size: 12.5px; color: var(--muted-foreground); text-align: end; }
.v2-grants__count b { color: var(--foreground); }
.v2-grants .v2-panel__body { max-block-size: 30rem; }
.v2-grants__table thead th { position: sticky; inset-block-start: 0; z-index: 1; background: var(--muted); }
.v2-grants__box { inline-size: 5rem; text-align: center; }
.v2-grants__box input { accent-color: var(--primary); }
.v2-grants__group td { font-weight: 600; background: color-mix(in oklab, var(--primary) 6%, var(--surface)); }
.v2-grants__status { color: var(--muted-foreground); }
.v2-grants__status--bad { color: var(--destructive); }

.v2-locks { display: grid; gap: .75rem; min-inline-size: 0; }
@media (min-width: 1024px) { .v2-locks { grid-template-columns: minmax(0, 1fr) 24rem; align-items: start; } }
.v2-locks__period { display: inline-flex; align-items: center; gap: .375rem; font-weight: 500; }
.v2-locks__glyph { inline-size: .875rem; block-size: .875rem; color: var(--signal); }
.v2-locks__note {
    margin: 0;
    padding: .5rem .75rem;
    border-block-start: 1px solid var(--border);
    background: color-mix(in oklab, var(--muted) 30%, var(--surface));
    font-size: 11.5px;
    line-height: 1.25rem;
    color: var(--muted-foreground);
}
.v2-locks .v2-settings__row { grid-template-columns: minmax(0, 1fr) 12rem; }

/* ── a settings page — SettingsScreenV2 ──────────────────────────────────
   accounts.settings / SettingsList: a centred panel (max-w-3xl), the group's title beside a
   settings glyph on a muted band, and a row per setting — label and hint, then a 14rem control. */
.v2-settings {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    inline-size: 100%;
    max-inline-size: 48rem;
    margin-inline: auto;
}
.v2-settings__state { display: flex; justify-content: flex-end; }
.v2-settings__head { justify-content: flex-start; gap: .5rem; background: color-mix(in oklab, var(--muted) 50%, var(--surface)); }
.v2-settings__glyph { inline-size: 1rem; block-size: 1rem; color: var(--primary); }
.v2-settings__row {
    display: grid;
    align-items: center;
    gap: .5rem;
    padding: .625rem .75rem;
}
.v2-settings__row + .v2-settings__row { border-block-start: 1px solid color-mix(in oklab, var(--border) 60%, transparent); }
@media (min-width: 640px) { .v2-settings__row { grid-template-columns: minmax(0, 1fr) 14rem; } }
.v2-settings__row--dirty { background: color-mix(in oklab, var(--signal) 9%, var(--surface)); }
.v2-settings__label { font-size: 13px; font-weight: 500; }
.v2-settings__help { margin: .125rem 0 0; font-size: 11.5px; line-height: 1.25rem; color: var(--muted-foreground); }
.v2-settings__control { block-size: 2rem; font-size: 12.5px; }
.v2-settings__control.num { text-align: end; }

@media print {
    /* The pager is a control, not a figure: paper has no next page to press. What page this is
       still shows, because «1 – 200 من 1,591» is printed as part of the totals bar. */
    .v2-report__criteria, .v2-report .v2-refusal, .v2-report__pager .v2-btn { display: none; }
    .v2-report__sheet { border: 0; box-shadow: none; }
    .v2-report__table th, .v2-report__table td { white-space: normal; }
    .v2-panel__body { overflow: visible; }
}

/* ── the report pager ─────────────────────────────────────────────────────
   Under the rows and above the totals, because that is the order it is read
   in: these are the rows, this is where they sit in the whole, and this is
   what the whole adds up to. The totals bar stays sticky beneath it. */
.v2-report__pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .75rem;
    padding: .5rem 1rem;
    border-block-start: 1px solid var(--border);
}

.v2-report__page {
    display: flex;
    align-items: baseline;
    gap: .375rem;
    font-size: 12px;
    color: var(--muted-foreground);
}

.v2-report__page .num { font-weight: 600; color: var(--foreground); }

/* The named periods, beside the two date boxes rather than instead of them. */
.v2-report__presets { display: flex; flex-wrap: wrap; gap: .375rem; }

/* A refusal is a sentence, not a chip. Every server message is rendered into a badge, and a badge
   is nowrap — so a long refusal pushed the whole body sideways instead of wrapping onto a second
   line. The badge stays compact everywhere else. */
.v2-refusal {
    display: flex;
    white-space: normal;
    line-height: 1.5;
    font-size: 12px;
}
