/* ============================================================
   Affhaat 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; }
}

/* v32 — on a phone the fixed contact stack sits over the bottom of the page.
   On most pages that is harmless, but the checkout's LAST line is the order
   Total, so the bubble covered the amount the customer is about to pay.
   Reserve the stack's height at the end of the summary (and of any future
   card that ends with a primary figure) instead of letting the bubble float
   on top of it. */
@media (max-width: 640px) {
    .order-summary {
        padding-bottom: calc(56px + var(--nx-chat-size) + 20px);
    }
}

/* 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. */
    /* v38 — `clip` (not `hidden`): no page-level sideways scroll, and no
       scroll container that would interfere with the product rows' own
       `overflow-x: auto` scrolling. */
    body { overflow-x: clip; }

    /* 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%; }
}

/* ============================================================
   FIX (audit) — MOBILE ADMIN TABLES WERE CLIPPED, NOT SCROLLABLE
   ------------------------------------------------------------
   `.table { width: 100% }` (nx-v16.css:206) makes the table shrink to
   the width of its scroll container. On a 390px phone the container is
   ~340px, so a 7-column product table was compressed into 340px: the
   "Price" column was cut off mid-number and the action buttons were
   pushed out of view. `overflow-x: auto` on the wrapper never engaged
   because the table never became wider than the wrapper.

   Giving the table a min-width on small screens makes it keep its
   natural column widths; the wrapper then actually scrolls, which is
   what the existing `overflow-x: auto` was always meant to do.
   ============================================================ */
@media (max-width: 900px) {
  .nx-table-wrap > table,
  .table-wrap > table,
  .nx-table-wrap > .table,
  .table-wrap > .table {
    min-width: 720px;
  }
  /* Keep the first column (usually the product/order name) readable
     while the rest scrolls. */
  .nx-table-wrap > table th:first-child,
  .nx-table-wrap > table td:first-child,
  .table-wrap > table th:first-child,
  .table-wrap > table td:first-child {
    position: sticky;
    left: 0;
    background: #fff;
    z-index: 1;
  }
}
