/* ============================================================
   NexusCommerce v16 — design system layer
   ============================================================
   Loaded AFTER style.css, so it only adds and overrides.

   Contents
     1. Typography  — Bangla + English font pairing, scale
     2. Design tokens (spacing / radius / shadow / colour)
     3. Cards, tables, buttons, forms, badges — one consistent look
     4. Daily Book (the new simple income/expense page)
     5. Product share buttons
     6. Floating contact buttons (WhatsApp + Messenger)
     7. Print / invoice polish (reports + wholesale memo)
     8. Responsive pass (mobile: sidebar, tables, forms, buttons)

   Everything is expressed with variables from :root so one value
   changes the whole app — this is the "sob kisu alo melo lagse" fix.
   ============================================================ */

/* ---------------------------------------------------------------
   1. TYPOGRAPHY — Bangla + English pairing
   ---------------------------------------------------------------
   English headings/UI:  'Inter'       (clean, neutral, very legible)
   English body:         'Inter'
   Bangla (both):        'Hind Siliguri'  ->  'Noto Sans Bengali'
   Numerals stay LTR and tabular where money is shown so columns line up.

   The webfonts are requested with display=swap and a full system
   fallback, so the site still renders correctly on a server with no
   outbound internet — it simply uses the local fonts.
--------------------------------------------------------------- */
:root {
    --nx-font-en: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --nx-font-bn: 'Hind Siliguri', 'Noto Sans Bengali', 'SolaimanLipi', 'Kalpurush', var(--nx-font-en);
    --nx-font-stack: var(--nx-font-en);

    /* Type scale (1.250 major third, 16px base) */
    --nx-fs-xs:   .78rem;
    --nx-fs-sm:   .875rem;
    --nx-fs-base: 1rem;
    --nx-fs-md:   1.125rem;
    --nx-fs-lg:   1.375rem;
    --nx-fs-xl:   1.75rem;
    --nx-fs-2xl:  2.125rem;

    /* Spacing scale */
    --nx-sp-1: .25rem;
    --nx-sp-2: .5rem;
    --nx-sp-3: .75rem;
    --nx-sp-4: 1rem;
    --nx-sp-5: 1.5rem;
    --nx-sp-6: 2rem;
    --nx-sp-7: 2.5rem;

    /* Consistent radii + shadows */
    --nx-radius-sm: 8px;
    --nx-radius:    12px;
    --nx-radius-lg: 16px;
    --nx-shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);
    --nx-shadow:    0 2px 10px rgba(15, 23, 42, .07);
    --nx-shadow-lg: 0 12px 32px rgba(15, 23, 42, .12);

    /* Semantic colour set — replaces the ad-hoc hex values scattered
       across admin pages so every green/red/amber means the same thing. */
    --nx-ink:        #0f172a;
    --nx-ink-soft:   #475569;
    --nx-ink-mute:   #64748b;
    --nx-line:       #e5e7eb;
    --nx-surface:    #ffffff;
    --nx-surface-2:  #f8fafc;
    --nx-brand:      #e11d48;
    --nx-brand-dark: #be123c;
    --nx-brand-tint: #fff1f2;
    --nx-ok:         #059669;
    --nx-ok-tint:    #ecfdf5;
    --nx-warn:       #d97706;
    --nx-warn-tint:  #fffbeb;
    --nx-bad:        #dc2626;
    --nx-bad-tint:   #fef2f2;
}

body {
    font-family: var(--nx-font-stack);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: 'kern' 1, 'liga' 1;
}

/* Bangla text renders with the Bengali face automatically — the browser
   picks the first family in the stack that has the glyph. Keeping the
   Bengali faces at the FRONT of the body stack means a Bangla page never
   falls back to a Latin-only font with broken conjuncts. */
body,
input, select, textarea, button {
    font-family: var(--nx-font-bn), var(--nx-font-en);
}

h1, h2, h3, h4, h5, h6,
.page-title, .card-title {
    font-family: var(--nx-font-en), var(--nx-font-bn);
    color: var(--nx-ink);
    letter-spacing: -.011em;
    line-height: 1.25;
    font-weight: 700;
}

.page-title { font-size: var(--nx-fs-xl); margin: 0 0 var(--nx-sp-4); }
h2, .card-title { font-size: var(--nx-fs-lg); margin: 0 0 var(--nx-sp-3); }
h3 { font-size: var(--nx-fs-md); }

/* Money and other figures: tabular numerals so columns align. */
.nx-num, .nx-kpi-value, .nx-daily-amt, .nx-daily-total-value, td.nx-num {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}

p, li, td, th { line-height: 1.65; }
.muted { color: var(--nx-ink-mute); }

/* ---------------------------------------------------------------
   2. CARDS / SURFACES
--------------------------------------------------------------- */
.card {
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: var(--nx-radius);
    padding: var(--nx-sp-5);
    margin-bottom: var(--nx-sp-4);
    box-shadow: var(--nx-shadow-sm);
}

/* ---------------------------------------------------------------
   2b. THE GRID-OVERFLOW FIX  ("mobile responsive kharap")

   This single cause broke the mobile layout of the dashboard, products,
   orders, users and balance-sheet pages.

   A CSS grid item defaults to `min-width: auto`, meaning it refuses to
   shrink below its CONTENT. A wide <table> inside a card therefore
   stretched its `1fr` track to the table's natural width (measured:
   620px of table inside a 390px viewport = the page scrolled sideways
   by 261px).

   `minmax(0, 1fr)` lets the track shrink, and `min-width: 0` on the
   flex/grid children lets the card shrink with it — after which the
   table's own wrapper is the thing that scrolls. This is the standard
   fix and it must be applied to every breakpoint.
--------------------------------------------------------------- */
.grid,
.grid-2,
.grid-3,
.grid-4,
.grid > *,
.grid-2 > *,
.grid-3 > *,
.grid-4 > *,
.row,
.row > *,
.flex,
.flex-between,
.flex-between > *,
.stats-grid,
.stats-grid > * {
    min-width: 0;
}

/* Re-declare the tracks so they may shrink below their content width. */
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1100px) {
    .grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
    .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
    .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
}

/* The admin shell must never be widened by its own content either. */
.admin-shell,
.admin-main,
.admin-content,
.main-content,
.container {
    min-width: 0;
    max-width: 100%;
}

.card-title { margin-bottom: var(--nx-sp-3); }

/* ---------------------------------------------------------------
   3. TABLES — one look everywhere, scrollable on small screens
--------------------------------------------------------------- */
.nx-table-wrap,
.table-wrap {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--nx-radius-sm);
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--nx-fs-sm);
    background: var(--nx-surface);
}

.table thead th {
    background: var(--nx-surface-2);
    color: var(--nx-ink-soft);
    font-size: var(--nx-fs-xs);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 700;
    padding: var(--nx-sp-3) var(--nx-sp-3);
    border-bottom: 1px solid var(--nx-line);
    text-align: left;
    white-space: nowrap;
}

.table tbody td {
    padding: var(--nx-sp-3);
    border-bottom: 1px solid #f1f5f9;
    vertical-align: middle;
}

.table tbody tr:hover { background: #fafbff; }
.table tbody tr:last-child td { border-bottom: none; }
.table td .btn, .table td form { display: inline-block; }

/* ---------------------------------------------------------------
   4. BUTTONS — consistent size, radius, focus ring
--------------------------------------------------------------- */
.btn {
    border-radius: var(--nx-radius-sm);
    font-weight: 600;
    line-height: 1.2;
    transition: background .15s, border-color .15s, box-shadow .15s, transform .12s;
}

.btn:focus-visible,
.form-control:focus-visible,
a:focus-visible {
    outline: 2px solid var(--nx-brand);
    outline-offset: 2px;
}

.btn-sm { padding: var(--nx-sp-2) var(--nx-sp-3); font-size: var(--nx-fs-xs); }

.btn-primary { background: var(--nx-brand); border-color: var(--nx-brand); }
.btn-primary:hover { background: var(--nx-brand-dark); border-color: var(--nx-brand-dark); }

.btn-danger { background: var(--nx-bad); border-color: var(--nx-bad); }

/* ---------------------------------------------------------------
   5. FORMS
--------------------------------------------------------------- */
.form-control {
    width: 100%;
    padding: var(--nx-sp-3) var(--nx-sp-3);
    border: 1px solid var(--nx-line);
    border-radius: var(--nx-radius-sm);
    font-size: var(--nx-fs-sm);
    background: var(--nx-surface);
    color: var(--nx-ink);
    transition: border-color .15s, box-shadow .15s;
}

.form-control:focus {
    border-color: var(--nx-brand);
    box-shadow: 0 0 0 3px rgba(225, 29, 72, .12);
    outline: none;
}

/* Native <select> elements render with the OS widget and visually clash
   next to a styled text input. Normalise them so every dropdown in the
   admin — category parent, attribute type, filters — matches. */
select.form-control {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 12px 12px;
    padding-right: 30px;
    cursor: pointer;
    line-height: 1.4;
}
select.form-control::-ms-expand { display: none; }
select.form-control[multiple] { background-image: none; padding-right: var(--nx-sp-3); }

/* Checkbox rows in the attribute form (`.nx-check`). */
label.nx-check {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--nx-sp-2);
    font-weight: 500;
    font-size: var(--nx-fs-sm);
    padding: var(--nx-sp-2) 0;
    cursor: pointer;
}
label.nx-check input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--nx-brand);
    flex: 0 0 auto;
    margin: 0;
}

.form-group { margin-bottom: var(--nx-sp-4); }
.form-group label { display: block; font-size: var(--nx-fs-sm); font-weight: 600; margin-bottom: var(--nx-sp-2); }

/* The two-column form grid used by the nested-category screens. */
.nx-form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--nx-sp-4);
    align-items: end;
}
.nx-form-grid label { display: flex; flex-direction: column; gap: var(--nx-sp-2); font-size: var(--nx-fs-sm); font-weight: 600; }
.nx-span-2 { grid-column: 1 / -1; }

.nx-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--nx-sp-3);
}
.nx-toolbar .form-control { width: auto; min-width: 0; }

/* ---------------------------------------------------------------
   6. KPI strip + link cards (finance / reports consistency)
--------------------------------------------------------------- */
.nx-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--nx-sp-4);
    margin-bottom: var(--nx-sp-4);
}

.nx-kpi {
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: var(--nx-radius);
    padding: var(--nx-sp-4) var(--nx-sp-5);
    box-shadow: var(--nx-shadow-sm);
    display: flex;
    flex-direction: column;
    gap: var(--nx-sp-1);
}

.nx-kpi-label { font-size: var(--nx-fs-xs); text-transform: uppercase; letter-spacing: .04em; color: var(--nx-ink-mute); font-weight: 700; }
.nx-kpi-value { font-size: var(--nx-fs-lg); font-weight: 800; color: var(--nx-ink); }
.nx-kpi .muted { font-size: var(--nx-fs-xs); }

.nx-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--nx-sp-4);
    margin-bottom: var(--nx-sp-4);
}

.nx-card-link {
    display: flex;
    flex-direction: column;
    gap: var(--nx-sp-1);
    padding: var(--nx-sp-4);
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: var(--nx-radius);
    text-decoration: none;
    color: var(--nx-ink);
    box-shadow: var(--nx-shadow-sm);
    transition: border-color .15s, box-shadow .15s, transform .12s;
}
.nx-card-link:hover { border-color: var(--nx-brand); box-shadow: var(--nx-shadow); transform: translateY(-1px); }
.nx-card-link strong { font-size: var(--nx-fs-sm); }
.nx-card-link span { font-size: var(--nx-fs-xs); color: var(--nx-ink-mute); line-height: 1.55; }

/* ---------------------------------------------------------------
   7. DAILY BOOK  — the plain income | expense page
--------------------------------------------------------------- */
.nx-daily-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--nx-sp-4);
    margin-bottom: var(--nx-sp-4);
}

.nx-daily-col {
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-top: 4px solid var(--nx-line);
    border-radius: var(--nx-radius);
    box-shadow: var(--nx-shadow-sm);
    padding: var(--nx-sp-4) var(--nx-sp-5) var(--nx-sp-5);
    min-height: 180px;
}

.nx-daily-in  { border-top-color: var(--nx-ok); }
.nx-daily-out { border-top-color: var(--nx-bad); }

.nx-daily-head {
    display: flex;
    align-items: center;
    gap: var(--nx-sp-3);
    padding-bottom: var(--nx-sp-3);
    margin-bottom: var(--nx-sp-3);
    border-bottom: 1px solid var(--nx-line);
}
.nx-daily-head h2 { margin: 0; font-size: var(--nx-fs-md); }
.nx-daily-head .muted { font-size: var(--nx-fs-xs); }

.nx-daily-head-ico {
    width: 34px; height: 34px;
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1.05rem; font-weight: 800;
    flex: 0 0 auto;
}
.nx-daily-in  .nx-daily-head-ico { background: var(--nx-ok-tint);  color: var(--nx-ok); }
.nx-daily-out .nx-daily-head-ico { background: var(--nx-bad-tint); color: var(--nx-bad); }

.nx-daily-list { list-style: none; margin: 0; padding: 0; }
.nx-daily-list li { border-bottom: 1px dashed #f1f5f9; }
.nx-daily-list li:last-child { border-bottom: none; }

.nx-daily-line {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--nx-sp-3);
    padding: var(--nx-sp-3) 0;
}

.nx-daily-desc { display: flex; flex-direction: column; gap: 2px; font-size: var(--nx-fs-sm); min-width: 0; }
.nx-daily-meta { font-size: var(--nx-fs-xs); color: var(--nx-ink-mute); }
.nx-daily-amt { font-weight: 700; white-space: nowrap; font-size: var(--nx-fs-sm); }
.nx-daily-in  .nx-daily-amt { color: var(--nx-ok); }
.nx-daily-out .nx-daily-amt { color: var(--nx-bad); }

.nx-daily-empty { color: var(--nx-ink-mute); font-size: var(--nx-fs-sm); padding: var(--nx-sp-4) 0; margin: 0; }

.nx-daily-note {
    margin: var(--nx-sp-4) 0 0;
    padding-top: var(--nx-sp-3);
    border-top: 1px solid var(--nx-line);
    font-size: var(--nx-fs-xs);
    color: var(--nx-ink-mute);
}

/* ---- the three totals, stacked as requested ---- */
.nx-daily-totals {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: var(--nx-sp-4);
    margin-bottom: var(--nx-sp-4);
}

.nx-daily-total {
    border-radius: var(--nx-radius);
    padding: var(--nx-sp-5);
    display: flex;
    flex-direction: column;
    gap: var(--nx-sp-1);
    border: 1px solid var(--nx-line);
    background: var(--nx-surface);
    box-shadow: var(--nx-shadow-sm);
}

.nx-daily-total-label { font-size: var(--nx-fs-xs); text-transform: uppercase; letter-spacing: .05em; font-weight: 800; color: var(--nx-ink-mute); }
.nx-daily-total-value { font-size: var(--nx-fs-2xl); font-weight: 800; line-height: 1.15; }
.nx-daily-total-hint { font-size: var(--nx-fs-xs); color: var(--nx-ink-mute); }

.nx-daily-total-in  { border-left: 5px solid var(--nx-ok); }
.nx-daily-total-in  .nx-daily-total-value { color: var(--nx-ok); }

.nx-daily-total-out { border-left: 5px solid var(--nx-bad); }
.nx-daily-total-out .nx-daily-total-value { color: var(--nx-bad); }

.nx-daily-total-net.is-profit { border-left: 5px solid var(--nx-brand); background: var(--nx-brand-tint); }
.nx-daily-total-net.is-profit .nx-daily-total-value { color: var(--nx-brand-dark); }
.nx-daily-total-net.is-loss { border-left: 5px solid var(--nx-bad); background: var(--nx-bad-tint); }
.nx-daily-total-net.is-loss .nx-daily-total-value { color: var(--nx-bad); }

/* ---------------------------------------------------------------
   8. PRODUCT SHARE ROW
--------------------------------------------------------------- */
.pdp-share {
    margin: var(--nx-sp-4) 0;
    padding: var(--nx-sp-4) 0;
    border-top: 1px solid var(--nx-line);
    border-bottom: 1px solid var(--nx-line);
}
.pdp-share-label {
    display: block;
    font-size: var(--nx-fs-xs);
    text-transform: uppercase;
    letter-spacing: .05em;
    font-weight: 700;
    color: var(--nx-ink-mute);
    margin-bottom: var(--nx-sp-3);
}
.pdp-share-btns { display: flex; flex-wrap: wrap; gap: var(--nx-sp-2); }

.pdp-share-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--nx-sp-2);
    padding: var(--nx-sp-2) var(--nx-sp-3);
    border-radius: 999px;
    border: 1px solid var(--nx-line);
    background: var(--nx-surface);
    color: var(--nx-ink);
    font-size: var(--nx-fs-xs);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
.pdp-share-btn svg { width: 16px; height: 16px; fill: currentColor; flex: 0 0 auto; }
.pdp-share-btn:hover { transform: translateY(-1px); }

.pdp-share-btn.is-fb  { color: #1877F2; border-color: #cfe0f9; }
.pdp-share-btn.is-fb:hover  { background: #1877F2; color: #fff; border-color: #1877F2; }
.pdp-share-btn.is-wa  { color: #128C7E; border-color: #c9ece7; }
.pdp-share-btn.is-wa:hover  { background: #25D366; color: #fff; border-color: #25D366; }
.pdp-share-btn.is-msg { color: #0084FF; border-color: #cfe4fb; }
.pdp-share-btn.is-msg:hover { background: #0084FF; color: #fff; border-color: #0084FF; }
.pdp-share-btn.is-copy { color: var(--nx-ink-soft); }
.pdp-share-btn.is-copy:hover { background: var(--nx-ink); color: #fff; border-color: var(--nx-ink); }

/* ---------------------------------------------------------------
   9b. HOME SIDEBAR AD RAIL
   The storefront catalogue becomes two columns ONLY when a sidebar
   ad exists (.has-rail). Without one, everything stays full width
   exactly as before.
--------------------------------------------------------------- */
.nx-home-split { display: block; }

@media (min-width: 1024px) {
    .nx-home-split.has-rail {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 300px;
        gap: var(--nx-sp-5);
        align-items: start;
        max-width: 1200px;
        margin: 0 auto;
        padding: 0 20px;
    }
    /* The rail sticks while the catalogue scrolls past it. */
    .nx-ads-rail { position: sticky; top: 84px; }
}

.nx-ads-rail {
    display: flex;
    flex-direction: column;
    gap: var(--nx-sp-4);
}

.nx-ads-rail-title {
    font-size: var(--nx-fs-xs);
    text-transform: uppercase;
    letter-spacing: .08em;
    font-weight: 800;
    color: var(--nx-ink-mute);
}

.nx-ads-rail-card {
    display: block;
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: var(--nx-radius);
    overflow: hidden;
    box-shadow: var(--nx-shadow-sm);
    text-decoration: none;
    color: var(--nx-ink);
    transition: box-shadow .16s ease, transform .16s ease;
}
.nx-ads-rail-card:hover { box-shadow: var(--nx-shadow-lg); transform: translateY(-2px); }
.nx-ads-rail-card img { display: block; width: 100%; height: auto; }

.nx-ads-rail-text {
    display: block;
    padding: var(--nx-sp-4);
    font-size: var(--nx-fs-sm);
    font-weight: 600;
}

/* Staff-only placeholder — dashed, so it is clearly not a real ad and
   obviously a place to drop artwork. */
.nx-ads-rail-empty {
    border: 2px dashed var(--nx-line);
    border-radius: var(--nx-radius);
    padding: var(--nx-sp-4);
    background: var(--nx-surface-2);
}
.nx-ads-rail-empty .muted { font-size: var(--nx-fs-xs); line-height: 1.6; }

/* Stack the rail under the catalogue on phones and tablets. */
@media (max-width: 1023px) {
    .nx-home-split.has-rail { display: flex; flex-direction: column; gap: var(--nx-sp-4); }
    .nx-ads-rail { order: 2; padding: 0 14px var(--nx-sp-4); }
    .nx-home-main { order: 1; }
}

/* ---------------------------------------------------------------
   9. FLOATING CONTACT BUTTONS (WhatsApp + Messenger)
   ---------------------------------------------------------------
   Three fixed elements share the bottom-right corner and used to
   collide:

       .cookie-banner   bottom 0,   z-index 1000   (full width strip)
       .nx-chat-fab     bottom 22px, z-index 9999  (58px circle)
       .nx-fab          this block                 (52px circles)

   The stack therefore sits ABOVE the chat bubble, and both are lifted
   clear of the cookie strip while it is on screen — `--nx-fab-lift`
   is set from JS when the banner is showing, so nothing overlaps on
   any viewport.

   The storefront elements are only rendered with the site layout
   (`$showAdminShell` false), so the admin back-office is unaffected.
--------------------------------------------------------------- */
:root {
    /* Distance from the bottom edge. Raised while the cookie banner is up. */
    --nx-fab-lift: 0px;
    --nx-fab-size: 52px;
    --nx-chat-size: 58px;
}

.nx-fab {
    position: fixed;
    right: 18px;
    /* 22px baseline + chat bubble height + a gap = clear of the chat FAB. */
    bottom: calc(22px + var(--nx-chat-size) + 12px + var(--nx-fab-lift));
    z-index: 9998;          /* just under the chat FAB (9999) */
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.nx-fab-btn {
    width: var(--nx-fab-size);
    height: var(--nx-fab-size);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    box-shadow: var(--nx-shadow-lg);
    text-decoration: none;
    transition: transform .16s ease, box-shadow .16s ease;
}
.nx-fab-btn svg { width: 27px; height: 27px; fill: currentColor; }
.nx-fab-btn:hover { transform: translateY(-3px) scale(1.05); color: #fff; }

.nx-fab-btn.is-wa  { background: #25D366; }
.nx-fab-btn.is-msg { background: linear-gradient(180deg, #00B2FF 0%, #006AFF 100%); }

/* Lift the existing chat bubble out of the cookie strip as well.
   NOTE: style.css declares `.nx-chat-fab { bottom: ... !important }` inside
   its own media queries, so a plain rule here would lose. The authoritative
   positioning is therefore applied from JS with priority (see the
   nxPositionFloats() function in footer.php) — the rules below are only the
   no-JS fallback for a clean, banner-free page. */

/* Gentle attention pulse on the first button, respecting users who
   have asked the OS to reduce motion. */
@keyframes nxFabPulse {
    0%   { box-shadow: 0 0 0 0 rgba(37, 211, 102, .45); }
    70%  { box-shadow: 0 0 0 14px rgba(37, 211, 102, 0); }
    100% { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0); }
}
.nx-fab-btn.is-wa { animation: nxFabPulse 2.6s ease-out 3; }

@media (prefers-reduced-motion: reduce) {
    .nx-fab-btn { animation: none !important; transition: none !important; }
    .nx-fab-btn:hover { transform: none; }
}

/* The admin back-office does not need sales CTAs. */
body.is-admin-shell .nx-fab { display: none; }

/* v28 — on a phone the contact stack is kept small and tight so it never
   dominates the corner or covers a primary action. The stack also collapses
   behind a single toggle button (see .nx-fab-toggle below). */
@media (max-width: 640px) {
    :root { --nx-fab-size: 44px; --nx-chat-size: 50px; }
    .nx-fab { right: 12px; gap: 8px; }
    .nx-fab-btn svg { width: 22px; height: 22px; }
}

/* v28 — collapsible contact stack.
   Desktop: the toggle is hidden and the buttons are always visible.
   Phone:   only the toggle shows; tapping it reveals the buttons. This is
            what stops the stack from covering the cart summary / checkout
            button on a small screen. */
.nx-fab-toggle { display: none; }
.nx-fab-items { display: flex; flex-direction: column; gap: 10px; }

@media (max-width: 640px) {
    .nx-fab-toggle {
        display: inline-flex; align-items: center; justify-content: center;
        width: var(--nx-fab-size); height: var(--nx-fab-size);
        border-radius: 50%; border: 0; cursor: pointer;
        background: var(--nx-slate-900, #0f172a); color: #fff;
        box-shadow: var(--nx-shadow-lg);
        transition: transform .16s ease;
    }
    .nx-fab-toggle svg { width: 22px; height: 22px; fill: currentColor; }
    .nx-fab-toggle:hover { transform: translateY(-2px); }
    .nx-fab-items {
        display: none;
        flex-direction: column; gap: 8px;
    }
    .nx-fab.is-open .nx-fab-items { display: flex; }
    .nx-fab.is-open .nx-fab-toggle { background: var(--nx-slate-700, #334155); }
}

/* v28 — one contact bubble on a phone.
   The standalone live-chat bubble is hidden on small screens and the same
   action is offered INSIDE the expandable stack (.nx-fab-btn.is-chat), so
   the bottom-right corner shows a single small button. On desktop the
   original chat bubble is restored and the extra stack entry is hidden. */
.nx-fab-btn.is-chat { background: var(--nx-slate-900, #0f172a); }
@media (min-width: 641px) {
    .nx-fab-btn.is-chat { display: none; }
}
@media (max-width: 640px) {
    .nx-chat-fab { display: none !important; }
}

/* ---------------------------------------------------------------
   10. PRINT — reports and the wholesale memo
--------------------------------------------------------------- */
@media print {
    /* Chrome and ink are wasted on navigation and buttons. */
    .no-print,
    .nx-fab,
    .site-header,
    .site-footer,
    .admin-sidebar,
    .admin-topbar,
    .admin-sidebar-backdrop,
    .nx-tabstrip,
    .pdp-share,
    .btn { display: none !important; }

    body { background: #fff; color: #000; font-size: 11.5pt; }

    .admin-main, .admin-content, .container, .main-content {
        margin: 0 !important;
        padding: 0 !important;
        max-width: none !important;
    }

    .card {
        border: 1px solid #cbd5e1 !important;
        box-shadow: none !important;
        break-inside: avoid;
        page-break-inside: avoid;
    }

    .table { font-size: 10.5pt; }
    .table thead th { background: #f1f5f9 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .table th, .table td { border-bottom: 1px solid #e2e8f0 !important; }

    /* Keep the Daily Book columns side by side on paper too. */
    .nx-daily-grid, .nx-daily-totals { display: grid !important; grid-template-columns: 1fr 1fr !important; }
    .nx-daily-totals { grid-template-columns: 1fr 1fr 1fr !important; }

    /* A clean document title instead of the app chrome. */
    .page-title { font-size: 17pt; margin-bottom: 10pt; }

    @page { margin: 14mm; }
}

/* ---------------------------------------------------------------
   11. RESPONSIVE PASS  (mobile: ≤ 900px and ≤ 600px)
--------------------------------------------------------------- */

/* --- tablet / small laptop --- */
@media (max-width: 980px) {
    .nx-daily-grid { grid-template-columns: 1fr; }
    .nx-daily-totals { grid-template-columns: 1fr 1fr; }
    .nx-daily-total-net { grid-column: 1 / -1; }
}

/* --- phone --- */
@media (max-width: 640px) {
    :root {
        --nx-fs-xl: 1.45rem;
        --nx-fs-2xl: 1.75rem;
    }

    .container { padding: 0 14px; }
    .main-content { padding: 18px 14px; }

    .card { padding: var(--nx-sp-4); border-radius: var(--nx-radius-sm); }

    .page-title { font-size: var(--nx-fs-xl); }

    /* Forms stack instead of squeezing two columns into 360px. */
    .nx-form-grid { grid-template-columns: 1fr; }
    .nx-span-2 { grid-column: auto; }

    .nx-toolbar { gap: var(--nx-sp-2); }
    .nx-toolbar .form-control,
    .nx-toolbar input[type="date"],
    .nx-toolbar select { width: 100%; }

    .nx-kpis { grid-template-columns: 1fr; gap: var(--nx-sp-3); }
    .nx-card-grid { grid-template-columns: 1fr; }

    .nx-daily-totals { grid-template-columns: 1fr; }
    .nx-daily-total-value { font-size: var(--nx-fs-xl); }
    .nx-daily-col { padding: var(--nx-sp-4); }

    .pdp-share-btns { gap: var(--nx-sp-2); }
    .pdp-share-btn { flex: 1 1 calc(50% - var(--nx-sp-2)); justify-content: center; }

    /* Floating buttons: keep them clear of the thumb zone and the cookie
       banner. `right`/size only — `bottom` is owned by nxPositionFloats()
       in JS, because style.css sets the chat FAB's bottom with !important
       from its own media queries. */
    .nx-fab { right: 12px; gap: 8px; }
    .nx-fab-btn { width: 46px; height: 46px; }
    .nx-fab-btn svg { width: 24px; height: 24px; }

    /* Every wide table scrolls horizontally rather than breaking layout.
       ---------------------------------------------------------------
       Only some admin views wrap their table in .nx-table-wrap; most use a
       bare <table class="table"> (42 of them). Rather than edit each view,
       the table's PARENT container is made the scroll box via JS on small
       screens (see nxMakeTablesScrollable() in footer.php).

       A pure-CSS `display:block; overflow:auto` on the <table> does NOT
       work here: a table's width is driven by its content, so it grows to
       its natural size and escapes the block box — the page then scrolls
       sideways. Wrapping the table in a real block element is the correct
       fix, so the page-level guard below is the belt to that braces. */
    body { overflow-x: hidden; }

    /* Tables that ARE wrapped keep working as before. */
    .nx-table-wrap, .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

    /* Buttons and links inside a table cell stay comfortably tappable. */
    .table td .btn { padding: var(--nx-sp-2) var(--nx-sp-3); font-size: var(--nx-fs-xs); }

    /* The nested-category action cluster wraps instead of overflowing. */
    .table td[style*="nowrap"] { white-space: normal !important; }

    /* Dialogs that were wider than the screen. */
    .nx-modal-box { width: calc(100vw - 28px); max-width: 520px; margin: 14px auto; }
}

/* --- very small phones --- */
@media (max-width: 380px) {
    .nx-daily-line { flex-direction: column; align-items: flex-start; gap: 2px; }
    .nx-daily-amt { align-self: flex-end; }
    .pdp-share-btn { flex: 1 1 100%; }
}
