/* ═══════════════════════════════════════════════════════════════════════════
   FTK FOODS — DESIGN SYSTEM
   Defined once, here, and used by every customer page: storefront, cart,
   checkout, account, receipt and the auth pages.

   THE OPS-CONSOLE RULE
   admin/ops-console-3dacfcbd19.html links this stylesheet and has no <style>
   block of its own — every pixel of it comes from here, across 155 shared class
   names. So the tokens below are inert declarations (nothing is styled by
   declaring a custom property), and EVERY rule that applies them is scoped to
   `body:not(.admin-body)`. The console's body carries .admin-body, so it keeps
   the styling it had. That scoping is load-bearing, not decoration: without it,
   changing `body { font-family }` alone would restyle the whole console.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Lato, self-hosted. No Google Fonts, no CDN, no external request: the files
      sit in client/fonts/ and are served from our own origin.
      Both the `latin` and `latin-ext` subsets are shipped for each weight. Neither
      has the naira sign: these Lato subsets contain no ₦ (U+20A6) glyph, so ₦ is
      drawn by the next font in --ftk-font that has one (the system font) — as it
      always has been. U+20A6 is therefore NOT in the latin-ext unicode-range below:
      listed there, every price made the browser download a latin-ext file for a
      glyph it does not contain.

      font-display: OPTIONAL (was `swap`). `swap` paints the fallback first and then
      re-draws every glyph in Lato the instant the web font lands — a visible reflow of
      the header (the account name, the "Cart: N" text and the badge number all change
      width) AFTER the first frame, whenever the font is not already in memory. On a phone
      that lands mid-load; on a page whose main thread is busy (the cart, mid account-cart
      sync) it lands ~1s in — exactly the "header changes for about a second" the owner saw.
      `optional` gives the font a ~100ms block window and NO swap window: if it is ready in
      time (400, 700 and 900 — the wordmark and the prices — are preloaded on every page;
      same-origin, ~14KB each) the page is drawn in Lato; if
      not, that one page keeps the fallback for its whole life and does not switch. The
      cost is that a first-ever visit on a slow link may render one page in the fallback
      before the next navigation shows Lato.

      What `optional` does NOT stop, measured (Safari / WebKit): Safari may paint a page's
      first frame DURING that block window — as soon as its images cover a small area, and
      the 52px logo is enough — with the text laid out (invisibly) in the FALLBACK's
      metrics, and lay it out again when Lato lands inside the window. With the system
      font as the fallback, lines re-wrapped on that second layout (a long email on
      Login & security moved everything below it 22.5px). So the fallback right after
      Lato in --ftk-font is 'Lato Fallback' (below): system faces sized to take the same
      space as Lato, so that second layout breaks the lines where Lato does (what it
      cannot always catch is said there). ── */
@font-face { font-family: 'Lato'; font-style: normal; font-weight: 400; font-display: optional;
  src: url('fonts/lato-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20A5, U+20A7-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Lato'; font-style: normal; font-weight: 400; font-display: optional;
  src: url('fonts/lato-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Lato'; font-style: normal; font-weight: 700; font-display: optional;
  src: url('fonts/lato-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20A5, U+20A7-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Lato'; font-style: normal; font-weight: 700; font-display: optional;
  src: url('fonts/lato-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Lato'; font-style: normal; font-weight: 900; font-display: optional;
  src: url('fonts/lato-900-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20A5, U+20A7-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Lato'; font-style: normal; font-weight: 900; font-display: optional;
  src: url('fonts/lato-900-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* ── 'Lato Fallback' — the face text is laid out in BEFORE Lato arrives (see above), sized to take Lato's space.
      Built for Safari, the browser that lays a page out before Lato lands: Optima (400, 700) and Gill Sans SemiBold
      (900) are on every Mac and iPhone, and of the fonts on both they match Lato best — the same line height (their
      ascent + descent at this size is within 1.4% of Lato's 1.2em, where Arial and Helvetica are 8–11% short) and
      the closest widths. The sizes are measured on the site's own text: 400 at 99.2% — every value from 98.9% to
      99.4% gave the policy, help and account pages the same line breaks as Lato at 390px and 1280px, so 99.2% sits in
      the middle; 700 at 101.4%, the width-weighted average over the site's bold text, names and headings; 900 at
      99.6%, which makes the wordmark the same width. A different typeface can only match on average: a name that
      ends within ~2% of a line's end can still wrap differently until Lato lands.
      Safari honours size-adjust only; ascent-override / descent-override / line-gap-override are for the browsers
      that read them (Chrome, Firefox: Lato's own 0.987 / 0.213 / 0, divided by size-adjust) and Safari drops them.
      unicode-range = exactly the characters these Lato files HAVE, so a character Lato lacks (₦, ↑, emoji…) still
      goes straight on to the system font, as it always has. No local font of these names (Windows, Android) → the
      face is skipped and the stack carries on to the system fonts exactly as before. ── */
@font-face { font-family: 'Lato Fallback'; font-style: normal; font-weight: 400;
  src: local('Optima-Regular'), local('Optima Regular');
  size-adjust: 99.2%; ascent-override: 99.5%; descent-override: 21.47%; line-gap-override: 0%;
  unicode-range: U+0020-007E, U+00A0-00FF, U+0104-0107, U+0118-0119, U+0131, U+0141-0144, U+0152-0153, U+015A-015B, U+0160-0161, U+0178-017E, U+0192, U+02C6-02C7, U+02C9, U+02DA, U+02DC-02DD, U+2013-2014, U+2018-201A, U+201C-201E, U+2020, U+2022, U+2026, U+2039-203A, U+2044, U+20AC, U+2122, U+2212; }
@font-face { font-family: 'Lato Fallback'; font-style: normal; font-weight: 700;
  src: local('Optima-Bold'), local('Optima Bold');
  size-adjust: 101.4%; ascent-override: 97.34%; descent-override: 21.01%; line-gap-override: 0%;
  unicode-range: U+0020-007E, U+00A0-00FF, U+0104-0107, U+0118-0119, U+0131, U+0141-0144, U+0152-0153, U+015A-015B, U+0160-0161, U+0178-017E, U+0192, U+02C6-02C7, U+02C9, U+02DA, U+02DC-02DD, U+2013-2014, U+2018-201A, U+201C-201E, U+2020, U+2022, U+2026, U+2039-203A, U+2044, U+20AC, U+2122, U+2212; }
@font-face { font-family: 'Lato Fallback'; font-style: normal; font-weight: 900;
  src: local('GillSans-SemiBold'), local('Gill Sans SemiBold');
  size-adjust: 99.6%; ascent-override: 99.1%; descent-override: 21.39%; line-gap-override: 0%;
  unicode-range: U+0020-007E, U+00A0-00FF, U+0104-0107, U+0118-0119, U+0131, U+0141-0144, U+0152-0153, U+015A-015B, U+0160-0161, U+0178-017E, U+0192, U+02C6-02C7, U+02C9, U+02DA, U+02DC-02DD, U+2013-2014, U+2018-201A, U+201C-201E, U+2020, U+2022, U+2026, U+2039-203A, U+2044, U+20AC, U+2122, U+2212; }

:root {
    /* Type — the ONLY sizes on any customer page */
    --ftk-font: 'Lato', 'Lato Fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --fs-title: 24px;   /* page title,      700 */
    --fs-head:  18px;   /* section heading, 700 */
    --fs-body:  15px;   /* body,            400 */
    --fs-meta:  13px;   /* meta,            400 */
    --fs-micro: 11px;   /* micro-label,     700 uppercase 0.04em */
    --lh-body: 1.5;
    --lh-head: 1.25;

    /* Colour. The gold is NOT invented: it is the dominant gold in
       client/img/ftk-logo.png (#F2CC5F, 42,000 px of the mark). */
    --gold:        #F2CC5F;   /* the brand band, and nothing else. Never a button. */
    --gold-ink:    #3A2E10;   /* dark ink that sits on the gold band */
    --orange:      #E07B1F;   /* every primary action's FILL, everywhere — its text and icons are --ink (5.82:1) */
    --orange-dark: #C0670F;   /* every orange button's HOVER and PRESSED fill, with #000 text and icons (5.19:1 — follow-up 4); also two icons on the light orange tint and one hover border */
    --orange-ink:  #A85C16;   /* orange as TEXT, a link or a control's edge on white or a light surface (4.99:1 on white —
                                 the base orange is only 2.99:1); batch 3A follow-up 3 — and every state indicator (the saved heart,
                                 progress dots and bar, the switch when on, tick boxes and radios: 3:1 or more — follow-up 4) */
    --star-gold:   #BC8413;   /* rating stars, filled and outlined, and the rating bars — a graphical object (WCAG 1.4.11): 3.26:1 on
                                 white, 3.04:1 on --surface. Not text: stars are drawn, the number beside them is the text. */
    --amber-ink:   #9C640C;   /* amber STATUS text and its icon — pending, low stock, unpaid, archive, warnings (4.95:1 on white,
                                 4.54:1 on the #FFF4E0 pill tint, 4.53:1 on the console's #FFF4DB tint) — the one amber; batch 3A
                                 follow-up 4; the console's pills, banners and notices since the gallery batch's push 2 */
    --danger:      #B3261E;   /* deleting only */
    --ink:         #1A1A1A;
    --ink-2:       #6B6B66;
    --surface:     #F7F7F5;
    --divider:     #E5E4E0;   /* lines that divide content — never a control's edge */
    --control-edge: #8A8A84;  /* a control's edge (buttons, fields, pills, the switch's off track): 3.47:1 on white, 3.24:1 on
                                 --surface — rule C, final colour round */
    --page:        #FFFFFF;
    --paid-green:  #1F7A3F;   /* RULE A — the SUCCESS / GOOD-STATUS colour: success confirmations (added to cart, saved, created,
                                 "we'll email you", "no email problems", settings saved …); good-status pills and marks (Paid, Delivered,
                                 Verified, Protected, staff Active, in stock, the "done" marks); money the customer SAVES (the cart's
                                 delivery-discount box, the checkout discount line). Text 5.37:1 on white, 4.78:1 on --paid-green-bg.
                                 Never an action, never a selected/active/editing state, never the console's general money figures,
                                 never decoration. */
    --paid-green-bg: #E8F5EC;
    /* Customer notifications (Job A): the light gold tint behind an ACCOUNT notice's icon — the brand gold
       (--gold) at 16% on the page white, and its ring at 45%. Worked out by hand, not color-mix(), so an older
       phone browser draws it too. */
    --gold-tint:      #FDF7E5;
    --gold-tint-line: #F9E8B7;
    /* Marketplace batch 4B fix round 3 (item 2): the orange STATUS pill's tint — "To ship", "Processing", the Owner role.
       --orange at 8% on white; --orange-ink on it measures 4.60:1 (the approved prototype's #FCE7D3 is 4.16:1, under AA). */
    --orange-tint:    #FDF4ED;

    /* Spacing — 4/8/12/16/24/32/48 and nothing else */
    --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;

    /* The shell. ONE content column for every row on every page: the header, the
       grey strip under it, the product grid, the cart, the account
       centre and the footer all resolve to the same box. Full-bleed backgrounds still
       span the window — only their CONTENTS sit here. Used as padding-inline it makes
       a full-width band and a plain block land on the identical left edge, which a
       max-width alone cannot do.

       FULL-WIDTH PASS: this used to be
         --shell: 1400px;
         --shell-pad: max(var(--s5), calc((100% - var(--shell)) / 2 + var(--s5)));
       which centred every row inside 1400px and gave the rest of the window back as
       empty margin. That single expression was the entire cap — every shell row pulls
       its side padding from here, so removing it here removes it everywhere, on all
       three pages at once. There is now no maximum: the rows are 100% wide with a
       flat gutter, and the product grid absorbs the extra width by adding COLUMNS
       rather than by fattening cards.

       20px is deliberately not one of the --s tokens. The spacing scale is
       4/8/12/16/24/32/48 and none of them is 20; the gutter was specified as 20px, so
       it is written as 20px rather than rounded to --s5 and quietly changed. */
    --shell-pad: 20px;

    /* Radius + border */
    --r-card: 8px; --r-btn: 6px; --r-pill: 999px; --bw: 1px;

    /* The single permitted shadow — drawer and modals only */
    --shadow: 0 8px 30px rgba(16, 24, 20, .18);
}

/* Always-visible (Windows-style) scrollbars: the storefront keeps the scrollbar's room at all times, so a page that
   grows past the window's height or shrinks back — while it loads (the room held under a busy page, "A PAGE THAT
   FILLS IN AFTER IT LOADS") or as its content arrives — never moves sideways. Overlay scrollbars (Macs, phones) take
   no room, so nothing changes there. The console (body.admin-body) keeps its own behaviour. */
:root:has(> body:not(.admin-body)) { scrollbar-gutter: stable; }

* { box-sizing: border-box; }

/* UNCHANGED from before this batch, deliberately. The ops console's whole cascade
   hangs off this rule — `.admin-body { background:#f6f7f9 }` later in the file
   overrides it at (0,1,0). Re-expressing it as `body.admin-body` raised the
   specificity to (0,1,1), out-ranked that rule and turned the console cream. So the
   base rule stays exactly as it was and the customer styling is layered ON TOP. */
body {
    margin: 0;
    font-family: 'Segoe UI', Arial, sans-serif;
    background-color: #fffaf0;
    color: #2f2f2f;
    line-height: 1.55;
}
/* Customer pages only. */
body:not(.admin-body) {
    font-family: var(--ftk-font);
    background-color: var(--page);   /* the cream/beige field is removed */
    color: var(--ink);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
}

button { cursor: pointer; font-family: inherit; }

/* ═══════════════════════════════════════════════
   NAVBAR
═══════════════════════════════════════════════ */
.navbar {
    /* Storefront mobile batch 1: IN NORMAL FLOW. Previously position:sticky with a
       scroll-direction auto-hide on phones; it now scrolls away with the page and
       returns only because the customer scrolled back to the top. */
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 40px;
    background: rgba(255,255,255,0.92);
    backdrop-filter: saturate(180%) blur(10px);
    box-shadow: 0 1px 0 rgba(0,0,0,0.06);
    /* This lift was ADDED to float the old search-results dropdown over the page (the
       backdrop-filter above makes a stacking context that had trapped it). That dropdown
       is GONE — search now filters the grid in place — so the lift no longer has anything
       to float. It is KEPT, not reverted: it still orders the header above all storefront
       content and the cart bar (900) and below the quick-view/image modals (1001/1002),
       the nav drawer (1400), the dialog overlay (5001) and the toast (99999). Reverting it
       is a general navbar-stacking decision, separate from the search change, so it is left
       as-is. position:relative carries NO offsets, so the header still scrolls away with the
       page (it is deliberately NOT sticky). */
    position: relative;
    z-index: 1000;
}

.nav-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    font-size: 20px;
    font-weight: 800;
    color: var(--orange-ink);
    letter-spacing: 0.3px;
    white-space: nowrap; /* WS7B: never wrap the brand to "To Kitchen" */
}


.nav-actions {
    display: flex;
    align-items: center;
    gap: 24px;
}

.nav-link {
    text-decoration: none;
    color: #444;
    font-size: 15px;
    font-weight: 600;
    transition: color 0.2s;
}

.nav-link:hover { color: var(--orange-ink); }

.nav-cart-link {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* WS7 mobile: compact cart-count badge. Hidden on desktop (the text label shows). */
.cart-badge {
    display: none;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: #E07B1F;
    color: var(--ink);
    font-size: 11px;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    align-items: center;
    justify-content: center;
}


/* ═══════════════════════════════════════════════
   TRUST STRIP
═══════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════
   PRODUCTS
═══════════════════════════════════════════════ */
.section-title {
    text-align: center;
    margin-bottom: 44px;
}

.section-title h2 {
    font-size: 36px;
    margin: 0 0 8px;
    color: #1a1a1a;
}

.section-title p {
    color: var(--ink-2);
    font-size: 16px;
    margin: 0;
}

.products {
    padding: 72px 20px;
    max-width: 1180px;
    margin: 0 auto;
}

.product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); /* smaller cards → more per row */
    gap: 18px;
}


/* storefront rework Batch 3 (section 7): the image LIGHTBOX (.img-modal*) and the quick-view
   PRODUCT DETAILS modal (.pd-modal / .pd-dialog / .pd-* / .pd-close) were DELETED — products have
   their own page (/product/<slug>) now. The two non-popup rules from this region are kept below. */
.btn-add:disabled { opacity: .5; cursor: not-allowed; }

/* Infinite-scroll sentinel — a 1px probe the IntersectionObserver watches to auto-load
   the next page. Height lives here (not an inline style attribute) so the enforcing
   production CSP's style-src does not block it. */
.store-sentinel { height: 1px; }

.btn-add {
    background: linear-gradient(135deg, #E07B1F, #E07B1F);
    color: var(--ink);
    border: none;
    padding: 13px;
    font-size: 15px;
    font-weight: 700;
    border-radius: 10px;
    transition: opacity 0.2s, transform 0.1s;
}

.btn-add:hover, .btn-add:active { background: var(--orange-dark); color: #000; }
.btn-add:active { transform: scale(0.98); }

/* ═══════════════════════════════════════════════
   CART
═══════════════════════════════════════════════ */
#cart {
    max-width: 1180px;
    margin: 0 auto;
    padding: 20px 20px 80px;
}

/* BATCH 7 / JOB 4: this is the page title rule. It is scoped to a DIRECT child so
   it can no longer style every h2 that happens to live inside the cart column —
   ".cart-main h2" (ID specificity 1,0,1) was beating ".cart-suggest-head" (0,1,0)
   and setting the "Add more to your order" heading to 30px, which wrapped it onto
   two lines and stranded the word "order". */
#cart > h2,
.cart-main > h2 {
    font-size: 30px;
    color: #1a1a1a;
    margin: 0 0 24px;
}


.cart-main {
    background: white;
    border-radius: 16px;
    padding: 28px 32px;
    box-shadow: 0 4px 20px rgba(0,0,0,0.07);
}

/* Cart header: title + "X Products • Y Total Items" subline */
.cart-subline {
    margin: 5px 0 0;
    font-size: 14px;
    font-weight: 600;
    color: #6b7178;
}

/* ═══════════════ PRODUCT-GROUPED CART (compact nested tables) ═══════════════ */
#cart-items { display: flex; flex-direction: column; gap: 10px; }

/* One card per PRODUCT (all weight variants grouped inside) */
.cart-product {
    background: #fff;
    border: 1px solid #E5E4E0;
    border-radius: 12px;
    box-shadow: 0 1px 6px rgba(0,0,0,0.04);
    overflow: hidden;
    transition: box-shadow 0.18s, border-color 0.18s;
}
.cart-product:hover { box-shadow: 0 4px 14px rgba(0,0,0,0.07); border-color: #e2e8e3; }

/* Product header: image + name (compact) */
.cp-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 13px 4px;   /* tighter; less gap to first weight row */
    border-bottom: 1px solid #F7F7F5;
}
.cart-thumb {
    flex: 0 0 34px;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    overflow: hidden;
    background: #f3f6f3;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 17px;
}
.cart-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cp-name {
    margin: 0;
    font-size: 14.5px;
    font-weight: 800;
    color: #1f2429;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}


/* Single column-header strip at the top of the cart (shown once) */
.cart-colhead th {
    padding-top: 2px;
    padding-bottom: 8px;
    border-bottom: 2px solid #E5E4E0;
}

/* Column widths + alignment */

.cv-weight {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--orange-ink);
    background: #F7F7F5;
    padding: 2px 9px;
    border-radius: 16px;
    white-space: nowrap;
}

/* Bordered quantity pill — [-] 4 [+] (compact, touch-friendly) */
.cart-qty {
    display: inline-flex;
    align-items: stretch;
    border: 1.5px solid #d8e0da;
    border-radius: 18px;
    overflow: hidden;
    background: #fff;
    height: 30px;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.cart-qty:hover { border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }   /* the orange rule: --orange-ink edge, the focused inputs' glow (follow-up 5) */
.cart-qty .qbtn {
    width: 30px;
    border: none;
    background: transparent;
    color: var(--orange-ink);
    font-size: 17px;
    font-weight: 700;
    cursor: pointer;
    line-height: 1;
    transition: background 0.15s, color 0.15s;
}
.cart-qty .qbtn:hover { background: #F7F7F5; }
.cart-qty .qbtn:active { background: rgba(224, 123, 31, .06); }   /* pressed: the site's selected tint (follow-up 5) */
.cart-qty .qval {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    padding: 0 4px;
    font-size: 13.5px;
    font-weight: 800;
    color: #1f2429;
    border-left: 1.5px solid #E5E4E0;
    border-right: 1.5px solid #E5E4E0;
}

/* Remove (per variant) — clean trash icon, red on hover */
.cart-trash svg { display: block; width: 15px; height: 15px; }


/* ── Empty state ── */
/* Storefront empty state (no active products) */
.store-empty {
    grid-column: 1 / -1; text-align: center; padding: 60px 24px;
    background: #f6fbf7; border: 1px dashed #cfe6d6; border-radius: 16px; color: #4a5a50;
}
.store-empty-ico { font-size: 54px; margin-bottom: 10px; }
.store-empty h3 { margin: 6px 0; font-size: 21px; color: var(--orange-ink); }
.store-empty p { margin: 0; font-size: 14.5px; color: var(--ink-2); }

.cart-empty { text-align: center; padding: 46px 20px; }
.cart-empty-ico { font-size: 52px; margin-bottom: 8px; }
.cart-empty h3 { margin: 6px 0; font-size: 20px; color: #1f2429; }
.cart-empty p { margin: 0 0 20px; color: var(--ink-2); font-size: 14.5px; }
.btn-continue {
    display: inline-block;
    background: linear-gradient(135deg, #E07B1F, #E07B1F);
    color: var(--ink);
    text-decoration: none;
    font-weight: 700;
    font-size: 14.5px;
    padding: 12px 26px;
    border-radius: 10px;
    transition: opacity 0.2s;
}
.btn-continue:hover, .btn-continue:active { background: var(--orange-dark); color: #000; }

/* ═══════════════ MOBILE: stack table cells into rows ═══════════════ */
@media (max-width: 420px) {
    .cart-thumb { flex-basis: 44px; width: 44px; height: 44px; }
    .cp-name { font-size: 15px; }
}


.cart-summary h3 {
    margin: 0 0 20px;
    font-size: 19px;
    color: #1a1a1a;
}

.summary-row {
    display: flex;
    justify-content: space-between;
    font-size: 15px;
    color: #555;
    padding: 10px 0;
    border-bottom: 1px solid #f2f2f2;
}

.summary-grand {
    border-bottom: none;
    align-items: baseline;
    font-weight: 800;
    font-size: 15px;
    color: #1a1a1a;
    margin-top: 8px;
    padding-top: 14px;
    border-top: 2px solid #E5E4E0;
}
.summary-grand #grand-total {
    font-size: 26px;            /* ~8% larger */
    font-weight: 900;
    color: var(--orange-ink);
    letter-spacing: -0.3px;
}

.btn-checkout {
    width: 100%;
    background: linear-gradient(135deg, #E07B1F, #E07B1F);
    color: var(--ink);
    border: none;
    padding: 15px;
    font-size: 15px;
    font-weight: 700;
    border-radius: 10px;
    margin-top: 20px;
    box-shadow: none;   /* the green glow is gone — an action is never green (follow-up 6); the site's buttons are flat */
    transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
}

.btn-checkout:hover {
    transform: translateY(-2px);
    background: var(--orange-dark); color: #000;
}
.btn-checkout:active { transform: translateY(0); background: var(--orange-dark); color: #000; }

/* WS10 — checkout is disabled while a cart line exceeds available stock. */
.btn-checkout:disabled,
.btn-checkout[disabled] {
    opacity: .5;
    cursor: not-allowed;
    filter: grayscale(.25);
    box-shadow: none;
    transform: none;
}
.btn-checkout:disabled:hover,
.btn-checkout[disabled]:hover { transform: none; box-shadow: none; filter: grayscale(.25); }

/* WS10 — the cart shortfall notice. DANGER RED on purpose (the same red family as
   .stock-badge.stk-out / .cp-act-danger), so it is never confused with the amber
   "Only N left" nudge (#A33A12, .pp-stock-low): same number, opposite meaning — this one blocks. */
.cart-shortfall {
    background: #fdeaea;
    border: 1px solid #f0c4c4;
    border-radius: 10px;
    padding: 12px 14px;
    margin: 0 0 14px;
    color: #8a2b22;
}
.cart-shortfall-head { margin: 0 0 6px; font-size: 14px; font-weight: 700; color: #b3261e; }
.cart-shortfall-list { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.5; }
.cart-shortfall-list li { margin: 2px 0; }

/* The CALM price-change note — its OWN class, deliberately NOT .cart-shortfall (which
   stays red for stock problems only). Subtle surface, a divider hairline, a small
   price-tag icon in the secondary text colour. No red, no button. Sits at the top of
   the cart on mobile and desktop. Uses the design tokens, never raw colours. */
.cart-price-note {
    display: flex; gap: 12px; align-items: flex-start;
    background: var(--surface);
    border: 1px solid var(--divider);
    border-radius: 8px;
    padding: 16px;
    margin: 0 0 14px;
    color: var(--ink);
}
.cart-price-note .cpn-ico { flex: 0 0 auto; width: 20px; height: 20px; color: var(--ink-2); margin-top: 1px; }
.cart-price-note .cpn-body { min-width: 0; }
.cart-price-note .cpn-head { margin: 0 0 4px; font-size: 15px; font-weight: 700; color: var(--ink); }
.cart-price-note .cpn-line { margin: 2px 0; font-size: 13px; font-weight: 400; color: var(--ink); }
.cart-price-note .cpn-foot { margin: 6px 0 0; font-size: 13px; color: var(--ink-2); }

/* WS10 item-1 follow-up — the per-variant cap message ("Maximum available: N"), under a
   capped cart row or a capped Add button. Shortfall RED (#b3261e), deliberately NOT the
   amber "Only N left" nudge (#A33A12, .pp-stock-low): same number, opposite job. */
.cv-cap {
    margin: 4px 0 0;
    font-size: 12.5px;
    font-weight: 700;
    color: #b3261e;
}
/* On the cart's desktop display:contents grid, the message spans the full product row. */
body:not(.admin-body) #cart-items .cv-cap { grid-column: 1 / -1; }

/* Capped buttons: the SAME greyed treatment as .btn-checkout:disabled. */
.btn-add:disabled,
.btn-add[disabled] {
    opacity: .5;
    cursor: not-allowed;
    filter: grayscale(.25);
    box-shadow: none;
    transform: none;
}
.btn-add:disabled:hover,
.btn-add[disabled]:hover { transform: none; box-shadow: none; filter: grayscale(.25); }
.cart-qty .qbtn:disabled,
.cart-qty .qbtn[disabled] {
    opacity: .4;
    cursor: not-allowed;
    background: transparent;
}
.cart-qty .qbtn:disabled:hover { background: transparent; }

/* The modals' Cancel / Done button (the console's product, stock and staff modals, the receipt, the seller site's dialogs).
   Fix round 7 (item 2): red is for destructive actions only — Cancel is the plain neutral outline, the same look as "Close". */
.btn-clear {
    width: 100%;
    background: #fff;
    color: var(--ink);
    border: 1.5px solid var(--control-edge);
    padding: 13px;
    font-size: 14px;
    font-weight: 600;
    border-radius: 10px;
    margin-top: 10px;
    transition: background 0.2s;
}

.btn-clear:hover { background: var(--surface); }

/* ═══════════════════════════════════════════════
   FOOTER
═══════════════════════════════════════════════ */
.site-footer {
    background: #F7F7F5;
    color: var(--ink-2);
    padding: 56px 40px 24px;
}

.footer-grid {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    gap: 40px;
    max-width: 1100px;
    margin: 0 auto 36px;
}

.footer-grid h4 { margin: 0 0 12px; font-size: 19px; color: white; }
.footer-grid h5 { margin: 0 0 14px; font-size: 14px; color: white; text-transform: uppercase; letter-spacing: 0.6px; }
.footer-grid p { margin: 0; font-size: 14px; opacity: 0.8; max-width: 320px; }
.footer-grid a { display: block; color: var(--ink-2); text-decoration: none; font-size: 14px; margin-bottom: 8px; opacity: 0.85; transition: opacity 0.2s; }

.footer-bottom {
    text-align: center;
    font-size: 13px;
    opacity: 0.6;
    border-top: 1px solid rgba(255,255,255,0.1);
    padding-top: 20px;
    margin: 0;
}

/* ═══════════════════════════════════════════════
   CHECKOUT (preserved)
═══════════════════════════════════════════════ */
#checkout {
    margin-top: 50px;
    padding: 20px;
}

#checkout label {
    display: block;
    margin-top: 15px;
    font-weight: bold;
}

#checkout input {
    width: 100%;
    padding: 10px;
    margin-top: 5px;
    border: 1px solid var(--control-edge);
    border-radius: 5px;
}

/* ═══════════════════════════════════════════════
   ACCOUNT DROPDOWN MENU
═══════════════════════════════════════════════ */
#account-menu {
    position: relative;
    z-index: 9999;
}

#account-icon {
    width: 44px;
    height: 44px;
    border: none;
    border-radius: 50%;
    background: #f4f4f4;
    cursor: pointer;
    font-size: 20px;
    transition: background 0.2s, box-shadow 0.2s;
    /* WS8B: clean vertical/horizontal centering of the icon glyph */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

#account-icon:hover { background: #eaeaea; box-shadow: 0 2px 8px rgba(0,0,0,0.12); }

/* ═══════════════════════════════════════════════
   HOMEPAGE RESPONSIVE
═══════════════════════════════════════════════ */
@media (max-width: 960px) {
    .product-grid { grid-template-columns: repeat(2, 1fr); }
    .footer-grid  { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 600px) {
    /* ── Compact mobile navbar — ONE row, in normal flow (storefront batch 1).
       The sticky + auto-hide behaviour and the wordmark-hiding hacks are gone; the
       logo is now a real image and the wordmark stays readable. ── */
    .navbar       { padding: 10px 14px; gap: 10px; }
    .nav-actions  { gap: 12px; }
    .nav-link:not(.nav-cart-link) { display: none; }
    .nav-cart-link .cart-badge     { display: inline-flex; } /* show compact number badge */


    /* ── WS7B: Amazon-style compact 2-column product feed ── */
    .products     { padding: 24px 10px 90px; }           /* full width + FAB bottom clearance */
    .product-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .btn-add       { padding: 10px; font-size: 13px; border-radius: 9px; } /* usable, not oversized */

    .footer-grid  { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════
   ACCOUNT DASHBOARD — PREMIUM LAYOUT
═══════════════════════════════════════════════ */

/* Account page header */

.account-header #account-menu {
    position: absolute;
    top: 50%;
    right: 24px;
    transform: translateY(-50%);
}

/* Main account wrapper */
#account {
    max-width: 960px;
    margin: 40px auto;
    padding: 0 20px 60px;
}

/* ── Profile Header ─────────────────────────── */

.avatar {
    width: 76px;
    height: 76px;
    border-radius: 50%;
    background: linear-gradient(135deg, #d88b36, #f4a261);
    color: var(--ink);
    font-size: 32px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-shadow: 0 4px 12px rgba(216,139,54,0.35);
}


.profile-details h2 {
    margin: 0 0 4px;
    font-size: 22px;
    color: #1a1a1a;
    text-align: left;
}


.profile-meta p {
    margin: 4px 0;
    font-size: 14px;
    color: #555;
}

.profile-meta strong {
    color: #1a1a1a;
}

/* ── Section Divider ────────────────────────── */

#order-history-panel { margin-top: 36px; }

.section-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 24px;
}

.section-header h2 {
    margin: 0;
    font-size: 20px;
    color: #1a1a1a;
    text-align: left;
}

.order-badge {
    background: #E07B1F;
    color: var(--ink);
    font-size: 12px;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 20px;
    letter-spacing: 0.3px;
}

#order-history {
    display: block;   /* compact rows stack full-width; the header + rows align as one table */
}

/* (Removed dead legacy order-card / order-date / order-status / order-totals rules —
   the My Orders styling now lives in ONE block further down.) */

/* Empty orders */
.empty-orders {
    text-align: center;
    padding: 48px 20px;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
}

.empty-icon {
    font-size: 48px;
    display: block;
    margin-bottom: 12px;
}

.empty-orders p {
    color: var(--ink-2);
    font-size: 16px;
    margin: 0 0 16px;
}

/* WS8B: two-line professional empty-orders copy */
.empty-orders .empty-title { color: #444; font-size: 16px; font-weight: 700; margin: 0 0 4px; }
.empty-orders .empty-sub { color: var(--ink-2); font-size: 14px; margin: 0 0 18px; }

.shop-link {
    display: inline-block;
    background: linear-gradient(135deg, #E07B1F, #E07B1F);
    color: var(--ink);
    text-decoration: none;
    padding: 12px 28px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.3px;
    transition: opacity 0.2s;
}

.shop-link:hover, .shop-link:active { background: var(--orange-dark); color: #000; }

/* ── Auth Section ───────────────────────────── */
/* WS7E: single centered account-entry card (one form shown at a time) */
.auth-grid {
    display: block;
    max-width: 420px;
    margin: 24px auto 0;
}

.auth-card {
    background: white;
    border-radius: 16px;
    padding: 32px;
    box-shadow: 0 4px 20px rgba(0,0,0,0.07);
}


/* WS7F premium: subtle trust builders below the card */
.auth-trust {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px 22px;
    max-width: 420px;
    margin: 18px auto 0;
    padding: 0;
}
.auth-trust li { font-size: 12.5px; color: var(--ink-2); }

/* WS7E: create/sign-in switch link */
.auth-switch {
    margin: 16px 0 0;
    text-align: center;
    font-size: 14px;
    color: var(--ink-2);
}
.auth-switch a {
    color: var(--orange-ink);
    font-weight: 600;
    text-decoration: none;
}
.auth-switch a:hover { text-decoration: underline; }

.auth-card h3 {
    margin: 0 0 6px;
    font-size: 20px;
    color: #1a1a1a;
}

.auth-subtitle {
    color: var(--ink-2);
    font-size: 14px;
    margin: 0 0 24px;
}

.form-group {
    margin-bottom: 18px;
}

.form-group label {
    display: block;
    font-size: 13px;
    font-weight: 700;
    color: #444;
    margin-bottom: 6px;
    letter-spacing: 0.3px;
}

/* Stage 3C: `.state-select` is added to these two selectors rather than given a
   rule of its own, so the state control inherits the SAME height, border,
   radius, font size, background and focus ring as the text inputs beside it —
   by definition, not by a second set of numbers that could drift apart. It is
   both a <select> and (in the fallback) an <input>, hence the bare class.
   The console's dropdowns join for the same reason (resting #fafafa, white when focused, the same text colour);
   :where() keeps them console-only and at the weight of `.form-group input`, so the console's own text-box
   rule (.admin-body .admin-input: padding, radius, border colour) still wins for both alike. */
.form-group input,
.form-group .state-select,
:where(.admin-body) .form-group select:where(.admin-input) {
    width: 100%;
    padding: 12px 14px;
    border: 1.5px solid var(--control-edge);
    border-radius: 8px;
    font-size: 16px; /* 16px min: iOS zooms below this */
    color: #1a1a1a;
    background: #fafafa;
    transition: border-color 0.2s, box-shadow 0.2s;
    box-sizing: border-box;
}

.form-group input:focus,
.form-group .state-select:focus,
:where(.admin-body) .form-group select:where(.admin-input):focus {
    outline: none;
    border-color: var(--orange-ink);
    background: white;
    box-shadow: 0 0 0 3px rgba(224, 123, 31, .18);
}

/* The ONLY properties a <select> needs that a text input does not: the native
   control paints its own chrome, so it is reset and given a chevron drawn to
   match the border colour. min-height is the 44px touch target; the padding
   above yields ~46px, and min-height makes that a floor rather than a
   coincidence of line-height. */
select.state-select {
    -webkit-appearance: none;
    appearance: none;
    min-height: 44px;
    padding-right: 40px;                 /* room for the chevron */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23667' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat;
    background-position: right 14px center;
    cursor: pointer;
    max-width: 100%;                     /* never overflow a narrow container */
    text-overflow: ellipsis;
}
select.state-select:disabled { color: #8a9097; cursor: default; }
input.state-select { min-height: 44px; }
.state-fallback-note { margin: 6px 0 0; }

/* Stage 3C1b — the add/edit form's action row. Reuses .auth-btn for both
   buttons so Cancel matches Save in height and radius; only the colours differ,
   because a secondary action that looks primary gets pressed by mistake. */
.addr-form-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.addr-form-actions .auth-btn { flex: 1 1 auto; min-width: 140px; }
.addr-cancel-btn {
    background: #fff;
    color: #46564c;
    border: 1.5px solid var(--control-edge);
}
.addr-cancel-btn:hover { background: #f6f8f7; }

.auth-btn {
    width: 100%;
    padding: 14px;
    font-size: 15px;
    font-weight: 700;
    border: none;
    border-radius: 10px;
    cursor: pointer;
    letter-spacing: 0.4px;
    transition: opacity 0.2s, transform 0.1s;
    margin-top: 6px;
}

.auth-btn:active { transform: scale(0.99); }

/* ── Toast — ONE pill for the storefront (the admin console has none: its messages sit next to what they are about).
   Self-created by toast.js (#ftk-toast); this file is its only appearance source.
   CSP-safe: everything visual is here, visibility is the .is-visible class.
   Each variant carries a leading icon (::before) and a colour that change
   together: success the long-standing dark ink, error #c0392b. Carried over from
   the old pill: error #c0392b, text #fff, radius 10px, z-index 99999. ── */
.ftk-toast {
    position: fixed;
    bottom: 16px;
    left: 16px;
    right: 16px;
    max-width: 420px;
    margin: 0 auto;                       /* centred once wider than 420px */
    z-index: 99999;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 13px 18px;
    border-radius: 10px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.35;
    color: #fff;
    box-shadow: 0 6px 24px rgba(0,0,0,0.18);
    overflow-wrap: anywhere;             /* long / multi-line messages wrap, never clip */
    cursor: pointer;                     /* click or tap anywhere dismisses */
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity .18s ease, transform .18s ease;
    pointer-events: none;
}
.ftk-toast.is-visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    pointer-events: auto;
}
.ftk-toast::before {
    flex: 0 0 auto;
    font-weight: 800;
    line-height: 1.35;
}
.ftk-toast--success { background: var(--paid-green); }   /* rule A: a success confirmation is green — white text 5.37:1 */
.ftk-toast--success::before { content: "\2713"; }   /* ✓ */
.ftk-toast--error   { background: #c0392b; }
.ftk-toast--error::before   { content: "\2715"; }   /* ✕ */

/* ── Batch 6 (J): "This order was cancelled before your payment arrived." — client/pay.js
   showClosedOrderCard. Phone first: the card fills the width (less the 20px gutter) and its two 48px
   buttons stack full width; from 601px they sit side by side. The site's own tokens throughout; above
   the shared dialog (5001) and below the toast (99999). ── */
.ftk-paycard-overlay {
    position: fixed;
    inset: 0;
    z-index: 5002;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(0,0,0,0.45);
}
.ftk-paycard {
    width: 100%;
    max-width: 440px;
    box-sizing: border-box;
    padding: var(--s5);
    background: var(--page);
    color: var(--ink);
    border: var(--bw) solid var(--divider);
    border-radius: var(--r-card);
    box-shadow: var(--shadow);
    font-family: var(--ftk-font);
}
/* Scoped under .ftk-paycard: the storefront's `body:not(.admin-body) p` rule would otherwise out-rank a single class. */
.ftk-paycard .ftk-paycard__title { margin: 0 0 var(--s3); font-size: var(--fs-head); font-weight: 700; line-height: var(--lh-head); color: var(--ink); }
.ftk-paycard .ftk-paycard__text { margin: 0 0 var(--s2); font-size: var(--fs-body); line-height: var(--lh-body); color: var(--ink); }
.ftk-paycard .ftk-paycard__fee { margin: 0 0 var(--s4); font-size: var(--fs-meta); line-height: var(--lh-body); color: var(--ink-2); }
.ftk-paycard .ftk-paycard__rows { margin: 0 0 var(--s5); padding: var(--s3) var(--s4); background: var(--surface); border-radius: var(--r-btn); }
.ftk-paycard .ftk-paycard__row { display: flex; justify-content: space-between; gap: var(--s4); padding: var(--s1) 0; font-size: var(--fs-body); }
.ftk-paycard .ftk-paycard__row dt { margin: 0; color: var(--ink-2); }
.ftk-paycard .ftk-paycard__row dd { margin: 0; font-weight: 700; white-space: nowrap; }
.ftk-paycard .ftk-paycard__row--total { margin-top: var(--s1); padding-top: var(--s2); border-top: var(--bw) solid var(--divider); }
.ftk-paycard__actions { display: flex; flex-direction: column; gap: var(--s3); }
.ftk-paycard__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 48px;
    box-sizing: border-box;
    padding: 0 var(--s5);
    border-radius: var(--r-btn);
    font-family: var(--ftk-font);
    font-size: var(--fs-body);
    font-weight: 700;
    text-decoration: none;
}
.ftk-paycard__btn--primary { background: var(--orange); border: var(--bw) solid var(--orange); color: var(--ink); }
.ftk-paycard__btn--primary:hover, .ftk-paycard__btn--primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
.ftk-paycard__btn--secondary { background: var(--page); border: var(--bw) solid var(--control-edge); color: var(--ink); }
.ftk-paycard__btn--secondary:hover { border-color: var(--ink-2); }
/* Focus (the card focuses its primary button when it opens) is an outline, never the hover colour. */
.ftk-paycard__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (min-width: 601px) {
    .ftk-paycard__actions { flex-direction: row; }
    .ftk-paycard__btn { width: auto; flex: 1 1 0; }
}

/* ── Shared dialog (ftkConfirm / ftkPrompt / ftkCopy) — self-created by dialog.js.
   CSP-safe: appearance here, behaviour (class toggles + element.style scroll-lock)
   in dialog.js. Overlay z-index 5001 sits ABOVE .modal-overlay (5000) so it covers
   an open admin product modal, and BELOW .ftk-toast (99999). Tokens resolve on the
   admin too — they live on bare :root, not a body:not(.admin-body) scope. ── */
.ftk-dialog-overlay {
    position: fixed;
    inset: 0;
    z-index: 5001;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(0,0,0,0.45);
    opacity: 0;
    visibility: hidden;
    transition: opacity .15s ease;
}
.ftk-dialog-overlay.is-open { opacity: 1; visibility: visible; }
.ftk-dialog {
    width: 100%;
    max-width: 320px;
    box-sizing: border-box;
    padding: 20px;
    background: var(--page);
    color: var(--ink);
    border: 0.5px solid var(--divider);
    border-radius: 12px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3);
    transform: translateY(8px);
    transition: transform .15s ease;
}
.ftk-dialog-overlay.is-open .ftk-dialog { transform: translateY(0); }
.ftk-dialog__title { margin: 0 0 8px; font-size: 16px; font-weight: 500; color: var(--ink); }
.ftk-dialog__msg   { margin: 0 0 16px; font-size: 14px; color: var(--ink-2); line-height: 1.5; white-space: pre-line; }
.ftk-dialog__input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin: 0 0 16px;
    padding: 10px 12px;
    font-family: inherit;
    font-size: 16px;                 /* HARD MINIMUM — below 16px iOS Safari zooms the focused field */
    color: var(--ink);
    background: var(--page);
    border: 1px solid var(--control-edge);
    border-radius: 8px;
}
/* Honour the hidden attribute. dialog.js sets inputEl.hidden = true for confirm/copy
   modes, but the author `display: block` above beats the UA `[hidden]{display:none}`
   rule (same specificity, author origin wins), so ftkConfirm/ftkCopy showed a stray
   empty box. This restores hidden without disturbing the prompt field's styling. */
.ftk-dialog__input[hidden] { display: none; }
.ftk-dialog__actions { display: flex; justify-content: flex-end; gap: 8px; }
.ftk-dialog__btn {
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    padding: 10px 16px;
    border: 1px solid transparent;
    border-radius: 8px;
    cursor: pointer;
}
.ftk-dialog__btn--cancel  { background: var(--page); color: var(--ink); border-color: var(--control-edge); }
.ftk-dialog__btn--cancel:hover  { background: var(--surface); }
.ftk-dialog__btn--confirm { background: var(--orange); color: var(--ink); }
.ftk-dialog__btn--confirm:hover, .ftk-dialog__btn--confirm:active { background: var(--orange-dark); color: #000; }
.ftk-dialog__btn--danger  { background: var(--danger); color: #fff; }
.ftk-dialog__btn--danger:hover  { filter: brightness(0.94); }

/* ── Responsive ─────────────────────────────── */
@media (max-width: 700px) {
    .auth-grid       { grid-template-columns: 1fr; }
    #order-history   { grid-template-columns: 1fr; grid-auto-rows: auto; }
    #account         { margin: 16px auto; }
    .auth-card       { padding: 24px 20px; }
}

/* ===============================================
   PAYMENT - PREMIUM CHECKOUT
=============================================== */


.checkout-steps {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 590px;
    margin: 28px auto 0;
    padding: 0 20px;
}

.step {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--ink-2);
    font-size: 13px;
    font-weight: 700;
    white-space: nowrap;
}

.step-num {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border: 1.5px solid #d7dcd8;
    border-radius: 50%;
    background: white;
    font-size: 12px;
}


.step-line {
    width: 80px;
    height: 1px;
    margin: 0 12px;
    background: var(--control-edge);
}

.step-line.done { background: var(--orange-ink); }












.summary-top h2 { margin-top: 3px; font-size: 20px; }
.summary-top a { color: var(--orange-ink); font-size: 12px; font-weight: 800; text-decoration: none; }


/* ── Delivery Information (right summary footer) ── */


/* Button reads "Complete Order — ₦X" as one centred phrase */

@keyframes success-in { from { opacity: 0; transform: translateY(12px) scale(.97); } }


@media (max-width: 620px) {
    .checkout-steps { margin-top: 20px; }
    .step { font-size: 0; gap: 0; }
    .step.active { font-size: 12px; gap: 7px; }
    .step-line { width: 45px; margin: 0 7px; }
}
/* ═══════════════════════════════════════════════
   CHECKOUT PAGE — PREMIUM
═══════════════════════════════════════════════ */

/* Step indicator */
.checkout-steps {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 32px 20px 8px;
    max-width: 560px;
    margin: 0 auto;
}

.step {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink-2);
}

.step-num {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: #eee;
    color: var(--ink-2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 700;
}

.step.active { color: var(--orange-ink); }
.step.active .step-num { background: var(--orange-ink); color: #fff; border-color: var(--orange-ink); box-shadow: none; }

.step.done { color: var(--orange-ink); }
.step.done .step-num { background: var(--orange-ink); color: #fff; border-color: var(--orange-ink); }

.step-line {
    flex: 1;
    height: 2px;
    background: var(--control-edge);
    max-width: 60px;
}

/* Layout */
#checkout-page {
    max-width: 1020px;
    margin: 24px auto 80px;
    padding: 0 20px;
}

.checkout-grid {
    display: grid;
    grid-template-columns: 1fr 380px;
    gap: 28px;
    align-items: start;
}


.checkout-form-card h2 {
    margin: 0 0 4px;
    font-size: 24px;
    color: #1a1a1a;
}



/* ── Delivery Information (checkout summary) ── */

/* Summary card */
.checkout-summary-card {
    background: white;
    border-radius: 16px;
    padding: 28px;
    box-shadow: 0 4px 20px rgba(0,0,0,0.07);
    /* Was position: sticky; top: 24px — nothing on the storefront may be sticky,
       fixed or floating, and this card was the last violation. */
    position: static;
}

.checkout-summary-card h3 {
    margin: 0 0 18px;
    font-size: 19px;
    color: #1a1a1a;
}


.summary-totals {
    border-top: 1px solid #f0f0f0;
    padding-top: 14px;
}

.summary-empty {
    text-align: center;
    padding: 24px 10px;
    color: var(--ink-2);
}

.summary-empty span { font-size: 36px; display: block; margin-bottom: 8px; }
.summary-empty p { margin: 0 0 10px; font-size: 14px; }
.summary-empty a, #ck-placed-note a { color: var(--orange-ink); font-weight: 600; text-decoration: none; }   /* round 3 (T1): its My orders link, as the summary's */
.summary-empty a:hover, #ck-placed-note a:hover { text-decoration: underline; }

.back-cart-link {
    display: block;
    text-align: center;
    margin-top: 14px;
    font-size: 14px;
    /* WAS #888. Its hover was already #E07B1F, so the intent was always the brand
       colour — only the resting state was grey. Now orange at rest and underlined,
       like every other text link a customer is meant to notice. */
    color: var(--orange-ink);
    text-decoration: underline;
    transition: color 0.2s;
    position: relative;                    /* anchors the hit area below */
}

.back-cart-link:hover { color: var(--orange-ink); }

/* A 44px TAP TARGET THAT MOVES NOTHING.
   The link's own box measures 72x23, under the 44px minimum. Growing it with
   padding would push the card and everything under it down — so the target is a
   pseudo-element centred on the link instead. It is not in the layout, not in the
   accessibility tree, and not an element, so page geometry is byte-identical
   before and after; only the region that answers a tap changes. */
.back-cart-link::after {
    content: "";
    position: absolute;
    left: 0; right: 0; top: 50%;
    transform: translateY(-50%);
    height: 44px;
}

/* ONE FOCUS TREATMENT FOR BOTH CHECKOUT TEXT LINKS.
   :focus-visible, so a mouse click does not draw a ring but a Tab key does.
   `outline` is used rather than a border or shadow because it is drawn outside
   the box and therefore cannot shift a single pixel of layout. */
.back-cart-link:focus-visible,
#checkout-page .ck-btn-outline:focus-visible,
#checkout-page .ck-btn-primary:focus-visible,
#checkout-page .ck-back:focus-visible,
#checkout-page .ck-addr-add:focus-visible {
    outline: 3px solid var(--orange-ink);
    outline-offset: 3px;
    border-radius: 4px;
}

@media (max-width: 800px) {
    .checkout-grid { grid-template-columns: 1fr; }
    .checkout-summary-card { position: static; }
}




/* ═══════════════════════════════════════════════
   ADMIN DASHBOARD
═══════════════════════════════════════════════ */

#admin-page {
    max-width: 1180px;
    margin: 32px auto 80px;
    padding: 0 20px;
}

.admin-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 28px;
}

.admin-head h1 {
    margin: 0 0 4px;
    font-size: 30px;
    color: #1a1a1a;
}

.admin-head p {
    margin: 0;
    color: var(--ink-2);
    font-size: 15px;
}

.admin-updated {
    font-size: 13px;
    color: var(--ink-2);
}

/* Stat cards */

.admin-stat-card {
    background: white;
    border-radius: 16px;
    box-shadow: 0 4px 18px rgba(0,0,0,0.06);
    padding: 24px;
    display: flex;
    align-items: center;
    gap: 16px;
    transition: transform 0.18s, box-shadow 0.2s;
}

/* Only cards that actually navigate lift on hover. The admin console marks a
   clickable card with data-nav="on" (and "off" when it is momentarily inert, e.g.
   orders still loading); the three non-navigating cards — Avg Order Value, Top
   Selling Product, Inventory Value — carry no data-nav at all. Same lift as before,
   only the selector is narrowed. */
.admin-stat-card[data-nav="on"]:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 26px rgba(0,0,0,0.1);
}

.admin-stat-icon {
    width: 56px;
    height: 56px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 28px;
    flex-shrink: 0;
}


.admin-stat-label {
    margin: 0 0 4px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--ink-2);
    font-weight: 700;
}

.admin-stat-value {
    margin: 0;
    font-size: 21px;
    font-weight: 700;
    letter-spacing: -0.4px;
    color: #1a1a1a;
    white-space: nowrap;
}

/* Rework tail (Item 1d): the muted line under a stat card's figure — "Not on sale: N drafts · N archived · N not shown"
   under Products on sale (marketplace batch 4A) and what each of In / Low / Out of stock and the inventory value counts
   (batch 4A fix round, F6). Always shown, even at 0. Admin muted colour, 13px. It WRAPS inside its card — kept on one
   line it ran past the card on a desktop and pushed a 320–360px page sideways — and the card's text column may shrink
   for it. */
.admin-stat-sub {
    margin: 3px 0 0;
    font-size: 13px;
    color: var(--ink-2);
    white-space: normal;
}
.admin-body .admin-stat-card:has(.admin-stat-sub) > div { min-width: 0; }

/* Activity grid */
.admin-grid {
    display: grid;
    grid-template-columns: 1.6fr 1fr;
    gap: 24px;
    align-items: start;
}

.admin-panel {
    background: white;
    border-radius: 16px;
    box-shadow: 0 4px 18px rgba(0,0,0,0.06);
    padding: 24px 26px;
}

.admin-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 18px;
}

.admin-panel-head h2 {
    margin: 0;
    font-size: 19px;
    color: #1a1a1a;
}

.admin-count {
    font-size: 13px;
    color: var(--ink-2);
    font-weight: 600;
}

/* Orders table */
.admin-table-wrap { overflow-x: auto; }

.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.admin-table th {
    text-align: left;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--ink-2);
    font-weight: 700;
    padding: 0 12px 12px;
    border-bottom: 1px solid #f0f0f0;
}

.admin-table td {
    padding: 14px 12px;
    border-bottom: 1px solid #f6f6f6;
    color: #444;
    vertical-align: middle;
}

.admin-table tr:last-child td { border-bottom: none; }

.cust-name { display: block; font-weight: 600; color: #1a1a1a; }
.cust-sub  { display: block; font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.muted     { color: var(--ink-2); font-size: 13px; }
/* Admin product-list count line (ops-console renderProductsCount). Colour/size come from .muted;
   this only sets its spacing above the list. */
.products-count { margin: 2px 0 12px; }

.status-badge {
    font-size: 12px;
    font-weight: 700;
    padding: 4px 12px;
    border-radius: 20px;
    white-space: nowrap;
}


/* Customer list */
.customer-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.customer-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px;
    border-radius: 12px;
    transition: background 0.15s;
}

.customer-row:hover { background: #fafafa; }

.customer-avatar {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: linear-gradient(135deg, #d88b36, #f4a261);
    color: var(--ink);
    font-weight: 700;
    font-size: 17px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.customer-info { flex: 1; min-width: 0; }
.customer-info .cust-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.customer-meta {
    text-align: right;
    flex-shrink: 0;
}

.cust-orders { display: block; font-size: 12px; color: var(--ink-2); }
.cust-spent  { display: block; font-weight: 700; color: var(--ink); font-size: 14px; }

.admin-empty {
    text-align: center;
    color: var(--ink-2);
    padding: 28px 10px;
    font-size: 14px;
}

@media (max-width: 900px) {
    .admin-grid  { grid-template-columns: 1fr; }
}


/* ── Admin login gate ───────────────────────── */
.admin-gate {
    min-height: calc(100vh - 72px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
}

.admin-gate-card {
    background: white;
    border-radius: 18px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.12);
    padding: 44px 40px;
    width: 100%;
    max-width: 400px;
    text-align: center;
}

.admin-gate-icon { font-size: 46px; display: block; margin-bottom: 14px; }

.admin-gate-card h1 { margin: 0 0 6px; font-size: 26px; color: #1a1a1a; }
.admin-gate-card p  { margin: 0 0 24px; color: var(--ink-2); font-size: 14px; }
.admin-gate-card .form-group { text-align: left; }

.admin-gate-error {
    color: #c0392b;
    font-size: 13px;
    margin: 0 0 14px;
    font-weight: 600;
}

.admin-gate-back {
    display: block;
    margin-top: 18px;
    font-size: 14px;
    color: var(--ink-2);
    text-decoration: none;
    transition: color 0.2s;
}


.admin-logout-btn {
    background: transparent;
    border: 1.5px solid var(--gold-ink);
    color: #666;
    padding: 8px 18px;
    font-size: 14px;
    font-weight: 600;
    border-radius: 8px;
    transition: all 0.2s;
}

.admin-logout-btn:hover { border-color: #c0392b; color: #c0392b; background: #fff5f5; }

/* ═══════════════════════════════════════════════
   ADMIN PANEL V2 — full multi-section dashboard
═══════════════════════════════════════════════ */
.admin-body { background: #f6f7f9; }

/* ── Section 1: Navigation ── */
.admin-nav {
    position: sticky;
    top: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 12px 28px;
    background: white;
    box-shadow: 0 1px 0 rgba(0,0,0,0.06);
    flex-wrap: wrap;
}

.admin-tabs {
    display: flex;
    gap: 4px;
    flex: 1;
    overflow-x: auto;
}

.admin-tab {
    background: transparent;
    border: none;
    padding: 9px 16px;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink-2);
    border-radius: 8px;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}

.admin-tab:hover { background: #f3f5f3; color: #1a1a1a; }

.admin-nav-right {
    display: flex;
    align-items: center;
    gap: 14px;
}

/* ── Section 8: Global search ── */
.global-search-wrap { position: relative; }

.global-search {
    width: 280px;
    max-width: 40vw;
    padding: 10px 14px;
    border: 1.5px solid var(--ink-2);
    border-radius: 10px;
    font-size: 14px;
    background: #fafafa;
}


.global-results {
    position: absolute;
    top: 48px;
    right: 0;
    width: 340px;
    max-width: 80vw;
    background: white;
    border-radius: 12px;
    box-shadow: 0 12px 34px rgba(0,0,0,0.16);
    border: 1px solid #f0f0f0;
    padding: 8px;
    max-height: 70vh;
    overflow-y: auto;
}

.gr-group { padding: 6px 4px; }
.gr-title { margin: 0 0 4px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--ink-2); font-weight: 700; }
.gr-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: 8px;
    cursor: pointer;
    font-size: 14px;
    color: #333;
}
.gr-item:hover { background: #f6faf7; }
.gr-meta { font-size: 12px; color: var(--ink-2); }
.gr-empty { padding: 18px; text-align: center; color: var(--ink-2); font-size: 14px; }

/* ── Main + sections ── */
.admin-main { max-width: 1200px; margin: 0 auto; padding: 28px 24px 80px; }
.admin-section { display: none; }
.admin-section.active { display: block; animation: fadeIn 0.25s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ── Section 3: Analytics cards ── */
.analytics-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
    gap: 16px;
    margin-bottom: 30px;
}
.admin-stat-value.sm { font-size: 18px; }

/* ── Toolbars / inputs / filters ── */
.admin-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

.admin-input {
    width: 100%;
    padding: 11px 14px;
    border: 1.5px solid var(--control-edge);
    border-radius: 10px;
    font-size: 16px; /* 16px min: iOS zooms below this */
    background: white;
    box-sizing: border-box;
}
.admin-toolbar > .admin-input { flex: 1; min-width: 220px; }

.filter-pills { display: flex; gap: 8px; flex-wrap: wrap; }
.filter-pill {
    background: white;
    border: 1.5px solid var(--control-edge);
    padding: 8px 16px;
    border-radius: 20px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink-2);
    transition: all 0.15s;
}

/* Product-table server-side pager (admin). Shared file → reaches the console via the build
   copy. Classes only; no inline styles (the enforcing CSP forbids them). */
.admin-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin: 16px 0 4px;
}
.admin-pager-btn {
    background: white;
    border: 1.5px solid var(--control-edge);
    padding: 8px 16px;
    border-radius: 20px;
    font-size: 13px;
    font-weight: 600;
    color: var(--orange-ink);
    cursor: pointer;
    transition: all 0.15s;
}
.admin-pager-btn:hover:not([disabled]) { border-color: var(--orange-ink); color: var(--orange-ink); }   /* = .admin-body .filter-pill:hover (follow-up 5) */
.admin-pager-btn[disabled] { color: #bbb; border-color: #eee; cursor: default; }
.admin-pager-status { font-size: 13px; font-weight: 600; color: var(--ink-2); }

/* ── Section 2: Order status colours ── */
.status-badge.status-cancelled  { background: #fdeaea; color: #c0392b; }

/* customer table cell */
.cust-cell { display: flex; align-items: center; gap: 10px; }
.customer-avatar.sm { width: 32px; height: 32px; font-size: 13px; }

/* ── Section 7: Products grid ── */
.btn-add-product {
    background: var(--orange);
    color: var(--ink);
    border: none;
    padding: 12px 22px;
    font-size: 14px;
    font-weight: 700;
    border-radius: 10px;
    transition: opacity 0.2s;
}
.btn-add-product:hover { opacity: 0.92; }

.admin-products-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 20px;
}
.admin-product-card {
    background: white;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 4px 18px rgba(0,0,0,0.06);
    transition: transform 0.18s, box-shadow 0.2s;
}
.admin-product-card:hover { transform: translateY(-4px); box-shadow: 0 12px 28px rgba(0,0,0,0.1); }
.apc-image { position: relative; height: 150px; background: #f3f3f3; }
.apc-image img { width: 100%; height: 100%; object-fit: cover; }
.apc-body { padding: 16px 18px; }
.apc-body h3 { margin: 0 0 4px; font-size: 17px; color: #1a1a1a; }
.apc-meta { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.apc-price { font-size: 18px; font-weight: 800; color: var(--ink); }
.apc-stock { font-size: 13px; color: var(--ink-2); }
.apc-actions { display: flex; gap: 8px; }
.btn-edit, .btn-del {
    flex: 1; padding: 9px; font-size: 13px; font-weight: 700; border-radius: 8px; border: 1.5px solid;
    background: white; transition: all 0.15s;
}
.btn-del { border-color: var(--danger); color: var(--danger); }
.btn-del:hover { background: #fff5f5; }

/* ── Section 4: Charts ── */
.charts-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 22px;
}
.chart-card { padding: 22px 24px; }
.chart-card canvas { height: 280px !important; width: 100% !important; }
.chart-wide { grid-column: 1 / -1; }

/* ── Settings ── */
.settings-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 22px;
    align-items: start;
}
.settings-saved { color: var(--paid-green); font-weight: 700; font-size: 14px; margin: 12px 0 0; }

/* ── Section 7: Product modal ── */
.modal-overlay {
    position: fixed; inset: 0;
    background: rgba(20,30,22,0.55);
    display: flex; align-items: center; justify-content: center;
    z-index: 5000; padding: 20px;
    backdrop-filter: blur(3px);
}
/* Make the hidden attribute win over display:flex above */
.modal-overlay[hidden] { display: none; }
.modal-card {
    background: white; border-radius: 18px; width: 100%; max-width: 480px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3); overflow: hidden;
    animation: fadeIn 0.2s ease;
}
.modal-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 20px 24px; border-bottom: 1px solid #f0f0f0;
}
.modal-head h2 { margin: 0; font-size: 19px; color: #1a1a1a; }
.modal-close { background: transparent; border: none; font-size: 18px; color: var(--ink-2); }
.modal-close:hover { color: #1a1a1a; }
.modal-body { padding: 22px 24px; }
.modal-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.modal-foot {
    display: flex; justify-content: flex-end; gap: 12px;
    padding: 18px 24px; border-top: 1px solid #f0f0f0;
}
.modal-foot .auth-btn, .modal-foot .btn-clear { width: auto; padding: 12px 24px; margin: 0; }
/* ── Compact admin product modal (scoped so other modals/forms are unaffected) ── */
#product-modal .modal-card {
    max-width: 900px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}
#product-modal .modal-head, #product-modal .modal-foot { flex: 0 0 auto; }
#product-modal .modal-body { overflow-y: auto; padding: 16px 24px; }
#product-modal .form-group { margin-bottom: 12px; }
#product-modal .modal-foot { position: sticky; bottom: 0; background: #fff; }

/* ── Admin fix batch §4: generalise the product modal's scrollable card to EVERY admin overlay ──
   The generic .modal-card has no max-height and overflow:hidden, so a tall panel (the Category photos panel of the time,
   since folded into the Categories screen — categories batch A)
   overflowed the viewport with its head (✕) and foot (Close) clipped off-screen and no way to
   scroll. Applying the product modal's pattern — card capped at 90vh, flex column, head/foot pinned,
   body scrolls — to the whole admin panel fixes Category photos and the same latent defect in the
   order and stock modals. Admin-scoped (.admin-body); the storefront uses none of these classes.
   #product-modal keeps its own (more specific, identical) rules. */
.admin-body .modal-card { max-height: 90vh; display: flex; flex-direction: column; }
.admin-body .modal-head, .admin-body .modal-foot { flex: 0 0 auto; }
.admin-body .modal-body { overflow-y: auto; }
.admin-body .modal-foot { position: sticky; bottom: 0; background: #fff; }
/* Close control is a real 44px target with its existing aria-label. */
.admin-body .modal-close { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }

.pm-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }


.pm-variants-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.pm-variants-top label { margin: 0; }
.pm-total-stock { font-size: 12px; color: #555; }

/* compact variant rows */
.pm-variant-row { margin-bottom: 6px; }
.pm-variant-row .admin-input { padding: 8px 10px; }
.pm-variant-del { height: 34px; }

/* collapsible image: 64px thumbnail by default, expand on click */
.pm-image-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pm-file { display: none; }

/* Shipping-weight suffix ("kg") on the legacy base fields. */
.pm-suffix-field { display: flex; align-items: center; gap: 8px; }
.pm-suffix-field input { flex: 1; }
.pm-suffix { color: var(--ink-2); font-size: 13px; font-weight: 600; }

@media (max-width: 640px) {
    .pm-grid2 { grid-template-columns: 1fr; }
    #product-modal .modal-card { max-height: 94vh; }
}

/* ── Product variants editor (admin product modal) ── */
.pm-variants-hint em { font-style: normal; font-weight: 700; color: var(--orange-ink); }
.pm-variants-head,
.pm-variant-row { display: grid; grid-template-columns: 1fr 100px 80px 92px 34px; gap: 8px; align-items: center; }
/* Stage 4 added a Weight column. On a narrow screen five columns cannot sit on
   one line legibly, so the row becomes two: label full width, then the three
   numbers and the delete button beneath it. */
@media (max-width: 560px) {
    .pm-variants-head { display: none; }
    .pm-variant-row {
        grid-template-columns: repeat(3, 1fr) 34px;
        grid-template-areas: "lab lab lab lab" "pri sto wgt del";
        row-gap: 6px;
    }
    .pm-variant-row .pm-v-label  { grid-area: lab; }
    .pm-variant-row .pm-v-price  { grid-area: pri; }
    .pm-variant-row .pm-v-stock  { grid-area: sto; }
    .pm-variant-row .pm-v-weight { grid-area: wgt; }
    .pm-variant-row .pm-variant-del { grid-area: del; }
    /* Fix round 3 (item 5): the weight box sits inside its kg suffix field now, so the field takes the weight's cell;
       a row's own error line runs the full width beneath the stacked row. */
    .pm-variant-row .pm-suffix-field { grid-area: wgt; }
    .pm-variant-row .pm-variant-err { grid-column: 1 / -1; }
}
.pm-variants-head { margin-bottom: 6px; }
.pm-variants-head span { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ink-2); }
.pm-variant-row { margin-bottom: 8px; }
.pm-variant-row .admin-input { margin: 0; }
.pm-variant-del {
    width: 34px; height: 38px; border: 1px solid var(--danger); background: #fff5f5; color: var(--danger);
    border-radius: 8px; cursor: pointer; font-size: 16px; line-height: 1; display: flex; align-items: center; justify-content: center;
}
.pm-variant-del:hover { background: #fde8e8; }
/* Fix round 3 (item 5): the shared Units & Variants widget (client/product-units.js) — a row's own error line and the
   list's, the red edge on the box at fault, the × greyed at the minimum row count, and the kg suffix field inside a
   row's 92px cell (a text box's own minimum width would otherwise push it out of the grid). */
.pm-variant-row .pm-variant-err, .pm-units-err { grid-column: 1 / -1; margin: 0 0 4px; font-size: 13px; font-weight: 700; color: var(--danger); }
.pm-variant-row .pm-variant-err[hidden], .pm-units-err[hidden] { display: none; }
.pm-units-err { margin-top: 6px; }
.pm-variant-row.is-invalid .admin-input[aria-invalid="true"] { border-color: var(--danger); }
.pm-variant-del[disabled] { opacity: .45; cursor: default; }
.pm-variant-del[disabled]:hover { background: #fff5f5; }
.pm-variant-row .pm-suffix-field { min-width: 0; gap: 4px; }
.pm-variant-row .pm-suffix-field .pm-v-weight { min-width: 0; width: 100%; padding-left: 8px; padding-right: 6px; }
.pm-variant-add {
    margin-top: 4px; padding: 9px 16px; border: 1px dashed var(--control-edge); background: #fff; color: var(--orange-ink);
    border-radius: 8px; cursor: pointer; font-weight: 700; font-size: 13px;
}
/* The no-variants trio — Base Price · Stock · Shipping Weight — is three fields,
   not the generic two-column .modal-row it only borrows `display:grid` from. Give it
   its own three columns by id so all three sit on one aligned row; .modal-row itself
   is left untouched (its sole user is this block) so nothing else can move. */
#pm-legacy-pricing { grid-template-columns: 1fr 1fr 1fr; }
/* Phone: stack the three fields. This override MUST stay AFTER the base rule above —
   both are a bare #id (equal specificity), so source order alone decides the winner.
   Placed before the base rule it loses and the trio never stacks (the 627e88d bug).
   Do NOT reorder above the base rule, and do NOT use !important or a specificity bump. */
@media (max-width: 560px) {
    #pm-legacy-pricing { grid-template-columns: 1fr; }
}
/* The header hides when there are no rows (toggled by syncVariantUI). It needs an
   explicit display:none because an author `display:grid` beats the UA [hidden] rule. */
#pm-legacy-pricing.pm-hidden,
.pm-variants-head.pm-hidden { display: none; }
.pm-units-line { font-size: 11px; color: var(--ink-2); margin-top: 3px; }

/* ── Archive / restore (admin product list) ──
   Marketplace batch 4A fix round (F2): the product's visibility pill (admin-core visibilityPill — Draft, Archived, No
   status) replaced the old grey Archived badge. It wears the console's own pill colours (.ftk-pill-awaiting,
   .mn-pill-grey); .vis-pill only lets it shrink to its words and places it — on a card, where the badge was. An archived
   row or card is still dimmed, but never its pill, so the pill's text keeps at least 4.5:1. */
.admin-body .ftk-pill.vis-pill { min-width: 0; padding: 0 10px; flex-shrink: 0; vertical-align: middle; }
.admin-body .apc-image .vis-pill { position: absolute; top: 10px; left: 10px; z-index: 2; }
.admin-body td .cust-name + .vis-pill { margin-top: 4px; }
.admin-product-card.is-archived .apc-image > :not(.vis-pill), .admin-product-card.is-archived .apc-body,
tr.is-archived > td:not(.cell-product), tr.is-archived > td.cell-product .cell-product-main > :not(.vis-pill) { opacity: .62; }
.btn-archive, .btn-restore {
    border: none; border-radius: 8px; cursor: pointer; font-weight: 700; font-size: 12px; padding: 7px 12px;
}
.btn-archive { background: #fff; border: 1px solid var(--control-edge); color: var(--amber-ink); }
.btn-archive:hover { background: var(--surface); }

/* ── Responsive ── */
@media (max-width: 900px) {
    .charts-grid { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
    .admin-nav { gap: 12px; padding: 10px 16px; }
    .admin-tabs { order: 3; width: 100%; }
    .global-search { width: 200px; }
    .admin-main { padding: 20px 14px 60px; }
}

/* ═══════════════════════════════════════════════
   ORDER MANAGEMENT V2 — shipped status, activity, details
═══════════════════════════════════════════════ */

/* (fix round 3: the old blue Processing / purple Shipped badge rules were dead — body:not(.admin-body) .status-badge wins — and are gone) */

/* Orders table: clickable order id + view button */
.order-link { color: var(--orange-ink); font-weight: 700; cursor: pointer; text-decoration: none; }
.order-link:hover { text-decoration: underline; }
.order-items-cell { max-width: 260px; }

.btn-view {
    background: white;
    border: 1.5px solid var(--control-edge);
    color: var(--ink);
    padding: 7px 14px;
    font-size: 13px;
    font-weight: 700;
    border-radius: 8px;
    transition: background 0.15s;
}

/* Section 11: Recent Activity feed */
.activity-list { display: flex; flex-direction: column; }
.activity-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 6px;
    border-bottom: 1px solid #f4f4f4;
}
.activity-item:last-child { border-bottom: none; }
.activity-icon {
    width: 38px; height: 38px;
    border-radius: 50%;
    background: #f3f5f3;
    display: flex; align-items: center; justify-content: center;
    font-size: 17px; flex-shrink: 0;
}
.activity-msg { flex: 1; font-size: 14px; color: #333; }
.activity-time { font-size: 12px; color: var(--ink-2); white-space: nowrap; }

/* Section 7: Order Details modal */
.od-status { margin-bottom: 18px; }
.od-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    margin-bottom: 18px;
}
.od-cell { display: flex; flex-direction: column; gap: 2px; }
.od-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--ink-2); font-weight: 700; }
.od-value { font-size: 14px; color: #1a1a1a; font-weight: 600; word-break: break-word; }
.od-items {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    border: 1px solid #f0f0f0;
    border-radius: 10px;
    overflow: hidden;
}
.od-items li {
    padding: 10px 14px;
    font-size: 14px;
    color: #444;
    border-bottom: 1px solid #f4f4f4;
}
.od-items li:last-child { border-bottom: none; }
.od-totals { border-top: 1px solid #f0f0f0; padding-top: 14px; }
.od-total-row {
    display: flex;
    justify-content: space-between;
    font-size: 14px;
    color: #555;
    padding: 6px 0;
}
.od-total-row.grand { font-weight: 800; font-size: 16px; color: #1a1a1a; border-top: 1px solid #f0f0f0; margin-top: 6px; padding-top: 12px; }

@media (max-width: 480px) {
    .od-grid { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════
   INVENTORY CENTER
═══════════════════════════════════════════════ */
.inv-head-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

.btn-export {
    background: white;
    border: 1.5px solid var(--control-edge);
    color: var(--ink);
    padding: 11px 16px;
    font-size: 13px;
    font-weight: 700;
    border-radius: 10px;
    transition: background 0.15s;
}

.inv-summary { margin-bottom: 24px; }
.inv-toolbar { gap: 14px; }
/* Cap the products search so the five filter pills (All/In/Low/Out/Archived) fit on one line at
   desktop width. The search is `flex:1` in the toolbar row, so max-width bounds how far it grows;
   the pills then have room. On narrow viewports .inv-toolbar becomes a column (below) and the pill
   row wraps on its own line, unaffected by this cap. */
#products-search { max-width: 520px; }

/* View toggle */
.view-toggle {
    display: inline-flex;
    background: #f0f1f0;
    border-radius: 10px;
    padding: 4px;
}
.view-btn {
    background: transparent;
    border: 1px solid transparent;
    padding: 7px 15px;
    font-size: 13px;
    font-weight: 700;
    color: var(--ink-2);
    border-radius: 8px;
    transition: all 0.15s;
}
.view-btn.active { background: white; box-shadow: 0 1px 4px rgba(0,0,0,0.1); }

/* Stock status badges (admin + storefront) */
.stock-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    font-size: 11px;
    font-weight: 700;
    padding: 4px 10px;
    border-radius: 20px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    z-index: 2;
}
.stock-badge.stk-low { background: #fff4e0; color: var(--amber-ink); }
.stock-badge.stk-out { background: #fdeaea; color: #c0392b; }
/* Marketplace batch 4A round 2 (R2): in the console's Products TABLE the badge sits in its Status cell, in line with the
   row. The corner placement above is the card view's (on the photo); in a table cell it had no positioned box to sit
   in, so it was drawn outside the table and the Status column stood empty. */
.admin-body .inv-table td .stock-badge { position: static; display: inline-block; white-space: nowrap; vertical-align: middle; }

/* Product card SKU line + stock controls */
.apc-sku { font-size: 12px; color: var(--ink-2); margin: 0 0 12px; letter-spacing: 0.3px; }
.stock-controls { display: flex; gap: 8px; margin-bottom: 10px; }
.stk-btn {
    flex: 1;
    background: #f6faf7;
    border: 1.5px solid var(--control-edge);
    color: var(--ink);
    padding: 8px;
    font-size: 13px;
    font-weight: 700;
    border-radius: 8px;
    transition: background 0.15s;
}
.stk-btn.minus { color: #c0392b; border-color: var(--danger); background: #fdf6f5; }
.stk-btn.minus:hover { background: #fbeae8; }

/* Inventory table */
.inv-table-panel { margin-bottom: 24px; }
.inv-thumb { width: 46px; height: 46px; border-radius: 8px; object-fit: cover; }
.inv-row-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.inv-row-actions .stk-btn { flex: 0 0 auto; min-width: 34px; padding: 6px 10px; }
.inv-row-actions .btn-edit,
.inv-row-actions .btn-del { flex: 0 0 auto; padding: 6px 12px; font-size: 12px; }

.inv-charts { margin-top: 24px; }

@media (max-width: 720px) {
    .inv-toolbar { flex-direction: column; align-items: stretch; }
    .view-toggle { align-self: flex-start; }
}

/* ═══════════════════════════════════════════════
   STOREFRONT PRODUCT SEARCH
═══════════════════════════════════════════════ */
.product-search-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

.product-search {
    width: 200px;
    max-width: 38vw;
    padding: 9px 38px 9px 14px;
    border: 1.5px solid var(--ink-2);
    border-radius: 22px;
    font-size: 14px;
    background: #fafafa;
    transition: border-color 0.2s, width 0.2s, background 0.2s;
}
.product-search:focus { outline: none; border-color: var(--orange-ink); background: white; width: 240px; }

.product-search-btn {
    position: absolute;
    right: 4px;
    background: transparent;
    border: none;
    font-size: 15px;
    padding: 6px 8px;
    border-radius: 50%;
    line-height: 1;
}
.product-search-btn:hover { background: #eef3ef; }

/* Search now filters the grid in place. The floating results dropdown
   (#product-search-results and its .ps-* rows) and the jump-to-product
   .product-highlight pulse it drove were removed with that feature; what stays is
   the count line the grid search shows above the grid. #888 is the existing muted
   grey from .section-title p — no new colour, no new type size. */

@media (max-width: 600px) {
    .product-search { width: 140px; }
    .product-search:focus { width: 160px; }
}

/* ═══════════════════════════════════════════════
   PAYSTACK PAYMENT SYSTEM
═══════════════════════════════════════════════ */

/* New order-status colours (badges) */


/* ── Checkout payment buttons ── */
.btn-paystack {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--orange);   /* fix round 3: the Paystack-blue gradient was dead (overridden below); the shop's one orange, dark ink on it (option "A") */
    color: var(--ink);
    border: none;
    padding: 16px 20px;
    font-size: 16px;
    font-weight: 700;
    border-radius: 12px;
    margin-top: 18px;
    box-shadow: none;
    transition: transform 0.15s, box-shadow 0.2s;
}
.btn-paystack:hover { transform: translateY(-2px); }


/* ── Receipt modal ── */
.receipt { padding: 28px 30px 8px; }
.receipt-head h2 { margin: 6px 0 4px; font-size: 22px; color: var(--orange-ink); }
.receipt-table { width: 100%; border-collapse: collapse; margin-bottom: 16px; }
.receipt-table th {
    text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;
    color: var(--ink-2); font-weight: 700; padding: 0 8px 8px; border-bottom: 1px solid #eee;
}
.receipt-table td { padding: 8px; font-size: 13px; color: #444; border-bottom: 1px solid #f5f5f5; }
.receipt-totals { border-top: 1px solid #eee; padding-top: 12px; }
.receipt-totals > div { display: flex; justify-content: space-between; font-size: 14px; color: #555; padding: 5px 0; }
.receipt-totals .rt-grand { font-weight: 800; font-size: 16px; color: #1a1a1a; border-top: 1px solid #eee; margin-top: 6px; padding-top: 10px; }
.receipt-foot { text-align: center; color: var(--ink-2); font-size: 13px; margin: 16px 0 0; }

/* ═══════════════ MY ORDERS — compact row (desktop) / stacked (mobile) ═══════════════ */
/* Overflow fixes kept: list is width:100%/max-width:100%; the row uses flex-wrap so it
   can never force a horizontal page scroll. Mobile (<768px) stacks. */
.orders-rows { width: 100%; max-width: 100%; }


/* ── Mobile (<768px): stack ── */


/* ── Receipt modal (Order History → View Receipt) ── */
.rcpt-overlay {
    position: fixed; inset: 0; z-index: 4000; display: flex; align-items: center; justify-content: center;
    padding: 20px; background: rgba(15,35,21,0.55); backdrop-filter: blur(4px);
}
.rcpt-overlay[hidden] { display: none; }
.rcpt-card {
    position: relative; width: 100%; max-width: 480px; max-height: 90vh; overflow-y: auto;
    background: #fff; border-radius: 18px; box-shadow: 0 24px 60px rgba(0,0,0,0.3);
}
.rcpt-close {
    position: absolute; top: 14px; right: 14px; z-index: 2; width: 32px; height: 32px; border: 1px solid var(--control-edge);
    border-radius: 50%; background: #fff; color: #555; font-size: 15px; cursor: pointer; line-height: 1;
    transition: background 0.15s;
}
.rcpt-close:hover { background: #e4e8e4; }
.rcpt-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 14px 24px 22px; }
.rcpt-foot .btn-clear, .rcpt-foot .auth-btn { width: auto; padding: 11px 22px; margin: 0; }


/* ── Account page payment meta row ── */
.profile-edit-card h3 { margin: 0 0 4px; font-size: 19px; color: #1a1a1a; }

/* Settings modal */
.settings-section h3 { margin: 0 0 8px; font-size: 15px; color: #1a1a1a; }

/* ═══════════════════════════════════════════════
   CUSTOMER ACCOUNT — sidebar layout (Profile & Settings)
═══════════════════════════════════════════════ */
#account-shell {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 24px;
    max-width: 1120px;
    margin: 0 auto;
    align-items: start;
}


.settings-card-panel h3 { margin: 0 0 12px; font-size: 16px; color: #1a1a1a; }


/* Tablet: narrower sidebar (Req 3) */
@media (max-width: 1024px) {
    #account-shell { grid-template-columns: 220px 1fr; }
}
/* Mobile: collapsible slide-in drawer — still a VERTICAL list, never a button row */
@media (max-width: 760px) {
    #account-shell { grid-template-columns: 1fr; }
    .account-sidebar.open { transform: translateX(0); box-shadow: 4px 0 30px rgba(0,0,0,0.25); }
}

/* ── Dark mode (account area; preference remembered per device) ── */
/* ── Profile & Settings: overview landing + new bits ── */


/* Keep the sidebar a vertical list on every screen size (never a button row) */
@media (max-width: 760px) {
    #account-shell { grid-template-columns: 1fr; }
}

/* Dark mode */
/* ── Account mobile drawer bar (hidden on desktop) ── */
#overview-recent { display: flex; flex-direction: column; gap: 10px; }


/* ═══════════════════════════════════════════════════════════════════════
   WS11 — OPS CONSOLE RESPONSIVE (mobile + narrow-laptop)
   ───────────────────────────────────────────────────────────────────────
   EVERY rule below is scoped under `.admin-body`, which exists ONLY on
   admin/ops-console-*.html. The storefront cannot be reached by any of
   this. (`.admin-input` and `.muted` are console classes; no storefront
   page uses either.)
   Layout/styling only — no behaviour, no JS, no data flow.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. TAB STRIP — Settings must be reachable at EVERY width ──────────
   Was: .admin-tabs { flex: 1; overflow-x: auto } on one row with the brand,
   a 280px search box and Logout. The 6th tab (Settings) was pushed past the
   right edge and macOS hides the scrollbar, so it looked like it did not
   exist. Wrapping removes the overflow entirely — nothing can be hidden.
   At wide widths the tabs still fit on one line, so desktop is unchanged. */
.admin-body .admin-tabs {
    flex-wrap: wrap;
    overflow-x: visible;   /* no hidden scroll region => no hidden tabs */
    row-gap: 4px;
}

/* ── 2. TABLES — scroll container with a VISIBLE affordance ────────────
   Chosen over a stacked-card layout because every <tbody> in this console
   is rendered by JavaScript WITHOUT data-label attributes, and a CSS-only
   stacked layout cannot recover the column headings — it would require
   editing the JS renderers, which is out of scope for this batch.
   So: keep the table, make the scroll obvious and the columns uncrushed. */
.admin-body .admin-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;   /* momentum scroll on iOS */
    scrollbar-width: thin;               /* Firefox: keep the bar visible */
}
/* macOS/iOS hide overlay scrollbars until you scroll — force a visible one
   so the table does not look like it simply ends at the screen edge. */
.admin-body .admin-table-wrap::-webkit-scrollbar { height: 10px; }
.admin-body .admin-table-wrap::-webkit-scrollbar-track { background: #f1f3f2; border-radius: 8px; }
.admin-body .admin-table-wrap::-webkit-scrollbar-thumb { background: #c3d2c7; border-radius: 8px; }
.admin-body .admin-table-wrap::-webkit-scrollbar-thumb:hover { background: #a8bfae; }

/* ── WS11 BATCH 2 / JOB 1 — stop the min-width escaping the wrapper ────────
   The min-width below did NOT stay inside .admin-table-wrap. The dashboard's
   Recent Orders table sits at:
     main.admin-main > section.admin-section > div.admin-grid
       > section.admin-panel > div.admin-table-wrap > table.admin-table
   `.admin-grid` is `display: grid`, so `.admin-panel` is a GRID ITEM, and grid
   items default to `min-width: auto` — they refuse to shrink below their
   min-content. A 720px min-content table therefore forced the grid track to
   720px, which widened .admin-main and gave the whole PAGE a sideways scroll.
   (The Orders / Customers / Products tables sit in block context and were
   already contained — verified by ancestry analysis.)
   Fix: give the scroll ancestors an explicit `min-width: 0` so they may shrink,
   and cap the wrapper at the available width. The min-width still applies to the
   TABLE inside the wrapper, so columns are not crushed. */
.admin-body .admin-grid > *,
.admin-body .charts-grid > *,
.admin-body .admin-stats > *,
.admin-body .admin-panel,
.admin-body .admin-section { min-width: 0; }

.admin-body .admin-table-wrap { max-width: 100%; }

@media (min-width: 701px) and (max-width: 900px) {
    /* Only in the band where tables are STILL tables. Below 701px they become
       stacked cards, where any min-width would re-introduce the page scroll. */
    .admin-body .admin-table { min-width: 720px; }
    .admin-body .inv-table   { min-width: 820px; }   /* 8 columns */
}

@media (max-width: 900px) {

    /* Edge fade = the affordance. Tells you there is more to the right even
       before the scrollbar appears. */
    .admin-body .admin-table-wrap {
        background:
            linear-gradient(to right, #fff 30%, rgba(255,255,255,0)) left center,
            linear-gradient(to left,  #fff 30%, rgba(255,255,255,0)) right center,
            radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.13), transparent) left center,
            radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.13), transparent) right center;
        background-repeat: no-repeat;
        background-size: 34px 100%, 34px 100%, 14px 100%, 14px 100%;
        background-attachment: local, local, scroll, scroll;
    }
}

/* ── 5. TOUCH + TYPE (applies at touch widths) ────────────────────────── */
@media (max-width: 900px) {
    /* 44x44 minimum hit area (Apple HIG / WCAG 2.5.5). */
    .admin-body .admin-tab,
    .admin-body .admin-logout-btn,
    .admin-body .filter-pill,
    .admin-body .btn-archive,
    .admin-body .btn-restore {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
    .admin-body .admin-tab { padding: 10px 14px; font-size: 15px; }

    /* 16px floor on anything typed into: below 16px iOS auto-zooms the page
       on focus and the layout jumps. .admin-input is already 16px in its own
       rule, so it is not re-declared here. */
    .admin-body input,
    .admin-body select,
    .admin-body textarea,
    .admin-body .global-search { font-size: 16px; }

    /* No body text below 14px. Scoped to the console like every rule here. */
    .admin-body .muted,
    .admin-body .cust-sub,
    .admin-body .cust-orders,
    .admin-body .gr-meta,
    .admin-body .apc-stock,
    .admin-body .apc-desc,
    .admin-body .admin-count,
    .admin-body .admin-updated,
    .admin-body .pm-suffix,
    .admin-body .pm-variants-hint,
    .admin-body .admin-table { font-size: 14px; }
    /* Column headings stay uppercase-small by design but not tiny. */
    .admin-body .admin-table th { font-size: 12px; }
}

/* ── Narrow phones: let the nav breathe ───────────────────────────────── */
@media (max-width: 620px) {
    .admin-body .admin-nav { gap: 10px; padding: 10px 14px; }
    /* Search + Logout share a row and stretch, instead of squeezing the brand. */
    .admin-body .admin-nav-right { width: 100%; gap: 10px; }
    .admin-body .global-search-wrap { flex: 1; }
    .admin-body .global-search { width: 100%; max-width: none; }
    .admin-body .admin-logout-btn { flex: 0 0 auto; }
    .admin-body .admin-main { padding: 18px 12px 96px; } /* 96px: clears the launcher */
    .admin-body .admin-toolbar > .admin-input { min-width: 0; width: 100%; }
    .admin-body .admin-tab { flex: 1 1 auto; }           /* tabs share the row evenly */
}

/* ═══════════════════════════════════════════════════════════════════════
   WS11 BATCH 2 — stacked cards + auto-hiding header
   Still entirely scoped under .admin-body / #od-* , so the storefront
   cannot shift.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── JOB 2 — tables become readable cards at ≤700px ────────────────────
   The renderers now emit data-label on every <td>, so each cell can print
   its own column heading. Above 700px nothing here applies and the tables
   render exactly as they do today. */
@media (max-width: 700px) {
    /* The header row has no meaning once cells are stacked. Kept in the DOM
       (not display:none) so screen readers still associate the headings. */
    .admin-body .admin-table thead {
        position: absolute;
        width: 1px; height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }

    .admin-body .admin-table,
    .admin-body .admin-table tbody,
    .admin-body .admin-table tr,
    .admin-body .admin-table td {
        display: block;
        width: auto;
        min-width: 0;      /* nothing may push the page wider than the viewport */
    }

    /* One card per row. */
    .admin-body .admin-table tr {
        border: 1px solid #e9edea;
        border-radius: 12px;
        padding: 10px 12px;
        margin: 0 0 12px;
        background: #fff;
        box-shadow: 0 1px 3px rgba(0,0,0,.04);
    }
    .admin-body .admin-table tr:last-child { margin-bottom: 0; }

    /* Label on the left, value on the right. */
    .admin-body .admin-table td {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 14px;
        padding: 7px 0;
        border: none;
        border-bottom: 1px solid #f4f7f5;
        text-align: right;
        overflow-wrap: anywhere;   /* long emails must wrap, not widen the page */
    }
    .admin-body .admin-table td:last-child { border-bottom: none; }

    .admin-body .admin-table td::before {
        content: attr(data-label);
        flex: 0 0 40%;
        text-align: left;
        font-size: 12px;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: .04em;
        color: var(--ink-2);
    }
    /* batch 3B fix round: a date cell kept on one line on the desktop table (Staff "Last sign-in", the Activity log's
       "When") wraps in a phone card — at 320px "17 Oct 2026, 10:12 PM WAT" ran past the screen's edge. */
    .admin-body .admin-table td.staff-when { white-space: normal; }
    .admin-body .dc-table .ftk-pill { min-width: 0; }   /* the Discount codes card: the status pill fits beside its label */
    /* Cells with data-label="" (actions, thumbnail) get no label and the full width. */
    .admin-body .admin-table td[data-label=""]::before { content: none; }
    .admin-body .admin-table td[data-label=""] {
        justify-content: flex-start;
        text-align: left;
    }
    /* Marketplace batch 4A round 3 (T7): …and so does a cell with NO data-label at all — the homepage editor's tables and
       the Categories tab's carry none, and each of their cells used to keep an empty 40% column on its left. */
    .admin-body .admin-table td:not([data-label])::before { content: none; }
    .admin-body .admin-table td:not([data-label]) {
        justify-content: flex-start;
        text-align: left;
    }
    /* Row actions stay reachable: full width, wrapping, 44px targets. */
    .admin-body .admin-table td.cell-actions { padding-top: 10px; }
    .admin-body .admin-table td.cell-actions .inv-row-actions,
    .admin-body .admin-table td.cell-actions {
        display: flex; flex-wrap: wrap; gap: 8px; width: 100%;
    }
    .admin-body .admin-table td.cell-actions button,
    .admin-body .admin-table td.cell-actions .btn-view {
        min-height: 44px; padding: 0 14px;
    }
    .admin-body .admin-table td.cell-thumb { padding-bottom: 2px; }
    .admin-body .admin-table td.cell-thumb .inv-thumb { width: 56px; height: 56px; border-radius: 10px; object-fit: cover; }

    /* Empty-state cell spans the card. */
    .admin-body .admin-table td.admin-empty { justify-content: center; text-align: center; }
    .admin-body .admin-table td.admin-empty::before { content: none; }

    /* Cards supply their own separation; the scroll affordance is now pointless. */
    .admin-body .admin-table-wrap {
        overflow-x: visible;
        background: none;
    }
}

/* ── JOB 3 — header hides on scroll down, returns on scroll up ─────────
   The class is toggled by the small IIFE at the foot of the console. Phone
   widths only: the media query means desktop can never receive it. */
@media (max-width: 700px) {
    .admin-body .admin-nav {
        transition: transform .22s ease;
        will-change: transform;
    }
    .admin-body.nav-hidden .admin-nav {
        transform: translateY(-110%);   /* 110% clears the box-shadow too */
    }
}


/* ═══════════════════════════════════════════════════════════════════════
   STOREFRONT MOBILE — BATCH 1
   Scoped to storefront hooks only. The ops console uses <nav class="admin-nav">
   and has ZERO "navbar" occurrences, so nothing here can reach it. .nav-brand
   and .nav-logo ARE shared with the console, so they are only ever touched
   under a `.navbar` ancestor — never bare.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. HEADER: real logo + wordmark ──────────────────────────────────── */
.navbar .nav-logo-img {
    width: 40px;
    height: 40px;
    border-radius: 50%;        /* circular badge */
    object-fit: contain;       /* never stretched or cropped */
    display: block;
    flex: 0 0 auto;
}
.navbar .nav-wordmark {
    font-family: inherit;      /* the site's own type, not a special face */
    font-weight: 800;
    letter-spacing: 0.2px;
}

/* Inline SVG line icons — one colour, one stroke weight, inherit text colour. */
.navbar .nav-ico {
    width: 24px;
    height: 24px;
    display: block;
    flex: 0 0 auto;
}
.navbar .nav-cart-link { display: inline-flex; align-items: center; gap: 8px; }
.navbar #account-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    padding: 0;
    color: inherit;
}

/* ── 2. Idle-logout notice: in flow, dismissible (see idle-logout.js) ─── */
#ftk-idle-notice { position: static; }

@media (max-width: 600px) {
    /* ── HEADER: one row, generous spacing, nothing decorative ────────── */
    .navbar { flex-wrap: nowrap; }
    .navbar .nav-brand { font-size: 17px; gap: 9px; min-width: 0; }
    .navbar .nav-logo-img { width: 34px; height: 34px; }
    /* The wordmark stays — it may ellipsis rather than disappear or clip a word. */
    .navbar .nav-wordmark { overflow: hidden; text-overflow: ellipsis; }
    .navbar .nav-actions { flex: 0 0 auto; gap: 14px; }

    /* BATCH 2: the search is now a real second ROW in the markup (.nav-row-search),
       not a flex child of .nav-actions. The old `flex: 1 0 100%` resolved against
       .nav-actions and pushed the form's right edge to 400px on a 390px viewport —
       measured, and the cause of the page-wide horizontal scroll. */

    /* Touch targets. */
    .navbar .nav-cart-link,
    .navbar #account-icon { min-width: 44px; min-height: 44px; }

    /* ── 4. PRODUCTS: stop the sideways scroll ────────────────────────── */
    /* The cards are grid items, so they default to min-width:auto and refuse to
       shrink below min-content. A variant <select> renders options such as
       "75cl bottle — ₦12,000 (Out of stock)" and a <select> cannot wrap, so its
       min-content (~300px) forced each ~145px track wide enough to overflow the
       page. min-width:0 lets the track shrink; the select then fits its column. */
    .product-grid { min-width: 0; }
    .btn-add { width: 100%; box-sizing: border-box; }
}

/* ═══════════════════════════════════════════════════════════════════════
   STOREFRONT BATCH 2 — header rows, sub-bar, category strip, footer
   Scoped to storefront hooks. The ops console uses <nav class="admin-nav">
   and has ZERO "navbar" occurrences, so none of this can reach it.
   Nothing here is sticky, fixed or floating.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── JOB 2: two-row header, in normal flow ────────────────────────────── */
.navbar { flex-direction: column; align-items: stretch; gap: 10px; }
.navbar .nav-row { display: flex; align-items: center; width: 100%; min-width: 0; }
.navbar .nav-row-main { justify-content: space-between; gap: 12px; }
.navbar .nav-brand { min-width: 0; }
.navbar .nav-actions { display: flex; align-items: center; gap: 18px; flex: 0 0 auto; }

/* "Sign in ›" as words beside the person icon */
.navbar #account-icon { flex-direction: row; gap: 7px; white-space: nowrap; }
.navbar .nav-signin-label { font-size: 14px; font-weight: 700; color: inherit; }

/* Search row: full width, magnifier INSIDE the field's right edge */
.navbar .nav-row-search { width: 100%; }
/* display:block, NOT flex: an earlier rule makes .product-search-wrap a flex
   container, which made the input shrink-wrap to 148px inside a 362px row
   (measured). As a block, the input's width:100% fills the row properly. */
.navbar .product-search-wrap { position: relative; display: block; width: 100%; min-width: 0; margin: 0; }
.navbar .product-search {
    width: 100%;
    /* The base rule caps this at `max-width: 38vw` (= 148px on a 390px phone —
       measured via CSS.getMatchedStylesForNode). Without this override the field
       stays a third of the row and clips the placeholder mid-word. */
    max-width: 100%;
    box-sizing: border-box;
    padding: 11px 46px 11px 14px;      /* right padding clears the button */
    font-size: 16px;                    /* 16px: iOS will not zoom on focus */
    border: 1.5px solid var(--ink-2);
    border-radius: 10px;
    background: #fff;
}
.navbar .product-search:focus { width: 100%; outline: none; border-color: var(--orange-ink); }
.navbar .product-search-btn {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 34px; height: 34px;
    display: inline-flex; align-items: center; justify-content: center;
    background: none; border: none; color: #6b7a70; padding: 0;
}
.navbar .product-search-btn svg { width: 19px; height: 19px; display: block; }

/* ── JOB 4: delivery line + category strip ──────────────────────────────
   Categories batch B: the separate delivery bar (.store-subbar / .delivery-line) was removed — "Delivery across
   Nigeria" now lives in the light grey strip under the gold band (.nav-strip, section C at the end of this file).
   storefront rework Batch 3 (section 7): the text pill category STRIP (.category-strip / .category-chip) was
   DELETED. */

/* ── JOB 7: footer, two background tones ──────────────────────────────── */
.site-footer { padding: 0; }
.footer-top-link {
    display: block;
    text-align: center;
    padding: 14px 16px;
    background: #1A1A1A;
    color: #d8e8dd;
    text-decoration: none;
    font-size: 13.5px;
    font-weight: 600;
}
.footer-top-link:hover { background: #EFEFEC; }

/* Tone 1 — link columns */
.footer-links { padding: 26px 20px; }
.footer-links .footer-grid { max-width: 1180px; margin: 0 auto; }
.footer-col h5 { color: #fff; margin: 0 0 10px; font-size: 14px; }
.footer-col a,
.footer-col .footer-plain {
    display: block;
    padding: 7px 0;
    font-size: 13.5px;
    line-height: 1.4;
    text-decoration: none;
}
.footer-col a { color: #6B6B66; }
.footer-col a:hover { color: #fff; text-decoration: underline; }

/* Tone 2 — legal / statement block, visibly separated */
.footer-legal {
    background: #102618;
    padding: 20px 20px 26px;
    text-align: center;
    color: #9fb6a7;
    font-size: 13px;
}
.footer-locale { margin: 0 0 10px; color: var(--ink-2); }   /* a statement, not a switcher */
.footer-signin { margin: 0 0 12px; }
.footer-signin a { color: var(--ink-2); font-weight: 700; }
.footer-terms { margin: 0 0 10px; display: flex; gap: 18px; justify-content: center; flex-wrap: wrap; }
/* PLAIN TEXT: those pages do not exist, so nothing may look like a link. */
.footer-terms span { color: var(--ink-2); cursor: default; }
.footer-bottom { margin: 0; color: var(--ink-2); }

@media (max-width: 600px) {
    .navbar { padding: 10px 14px; }
    .navbar .nav-actions { gap: 14px; }
    .navbar .nav-signin-label { font-size: 13.5px; }
    .footer-links { padding: 22px 16px; }
    .footer-links .footer-grid { grid-template-columns: 1fr 1fr; gap: 18px; }
    .footer-legal { padding: 18px 16px 24px; }
}

/* Desktop: keep the new two-row header, but don't let the search stretch the full
   1200px content width — measured at 1280px it spanned the whole row, which is a
   visible regression from the previous ~200px field. Phones keep 100%. */
@media (min-width: 601px) {
    .navbar .nav-row-search { justify-content: flex-start; }
    .navbar .product-search-wrap { max-width: 520px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   STOREFRONT BATCH 3 — cart page, badge-on-glyph, toast, spacing, footer
   Scoped to storefront hooks (.navbar / .site-footer / cart classes).
   The ops console uses .admin-nav and has zero "navbar" occurrences.
   Nothing here is sticky, fixed or floating.
   ═══════════════════════════════════════════════════════════════════════ */

.visually-hidden {
    position: absolute !important; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

/* ── JOB 4: count ON the cart glyph, and Sign in separated from the cart ── */
.navbar .nav-cart-ico { position: relative; display: inline-flex; }
.navbar .nav-cart-link { gap: 0; }
.navbar .cart-badge {
    display: inline-flex !important;
    align-items: center; justify-content: center;
    position: absolute;
    top: -6px; right: -9px;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: #f4a261;
    color: #1a2a1e;
    font-size: 11px;
    font-weight: 800;
    line-height: 1;
    border: 2px solid #fff;      /* lifts the number off the glyph */
    box-sizing: content-box;
}
/* A clear divider so "Sign in ›" and the cart no longer read as one control. */
.navbar .nav-actions { gap: 0; }
.navbar #account-menu { padding-right: 14px; margin-right: 14px; border-right: 1px solid #e4eae6; }

/* ── JOB 6: close the gap between the category strip and "Our Products" ── */
.products { padding: 22px 20px 72px; }          /* was 72px top */
.section-title { margin-bottom: 18px; }

/* ── JOB 3: per-product cart controls ── */
.cp-actions { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 0 2px; position: relative; }
.cp-act {
    background: #fff; border: 1px solid var(--control-edge); color: var(--orange-ink);
    border-radius: 8px; padding: 0 14px; min-height: 40px;
    font-size: 13px; font-weight: 700;
}
.cp-act:hover { background: #f2f8f4; }
.cp-act-danger { color: var(--danger); border-color: var(--danger); }
.cp-share-menu {
    display: flex; flex-direction: column; gap: 2px;
    background: #fff; border: 1px solid #dfe7e2; border-radius: 10px;
    padding: 6px; box-shadow: 0 6px 20px rgba(0,0,0,.10);
    width: 190px;
}
.cp-share-opt {
    background: none; border: none; text-align: left;
    padding: 0 10px; min-height: 40px; border-radius: 7px;
    font-size: 13.5px; color: #2c3b32; font-weight: 600;
}
.cp-share-opt:hover { background: #f2f8f4; }

.saved-section { margin-top: 30px; border-top: 1px solid #e9efeb; padding-top: 22px; }
.saved-meta { margin: 0 0 8px; font-size: 13px; color: var(--ink-2); }
.cart-page { padding-top: 22px; }
.btn-continue-shopping {
    display: block; text-align: center; margin-top: 12px;
    color: var(--orange-ink); font-size: 13.5px; font-weight: 700; text-decoration: none;
}

/* ── JOB 7: footer — tight aligned columns, less wasted height ── */
.site-footer .footer-grid {
    grid-template-columns: repeat(3, 1fr);   /* was 2fr 1fr 1fr — first col was double */
    gap: 24px;
    max-width: 1100px;
    margin: 0 auto;                          /* was 0 auto 36px */
}
.footer-links { padding: 20px 20px 22px; }
.footer-col h5 { margin: 0 0 8px; }
.footer-col a, .footer-col .footer-plain { padding: 5px 0; margin: 0; }
.footer-legal { padding: 14px 20px 18px; }
.footer-legal p { margin: 0 0 7px; }
.footer-legal .footer-bottom { margin: 0; }
.footer-top-link { padding: 11px 16px; }

@media (max-width: 600px) {
    /* Two tight columns; the third sits under them, left-aligned to the same edge. */
    .site-footer .footer-grid { grid-template-columns: 1fr 1fr; gap: 14px 18px; }
    .footer-links { padding: 18px 16px; }
    .products { padding: 16px 10px 90px; }
}

.cp-actions { display: flex; gap: 8px; padding: 10px 0 2px; position: relative; flex-wrap: nowrap; }
.cp-act {
    flex: 1 1 0;                 /* equal width, Amazon style */
    min-width: 0;
    padding: 0 8px;
    min-height: 42px;
    font-size: 12.5px;
    white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
}

/* ── JOB 2: share menu COLLAPSED until tapped.
   Cause: `.cp-share-menu { display:flex }` beat the [hidden] attribute, so the
   options rendered permanently. Display is now tied to the open state. ── */
.cp-share-menu { display: none; }
.cp-share-menu:not([hidden]) {
    display: flex;
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 5;
}

/* ── JOB 3: cart page structure ── */
.cart-page { padding: 16px 0 0; }
.cart-page .cart-main { max-width: 900px; margin: 0 auto; padding: 0 16px; }
.cart-topline { padding: 4px 0 12px; border-bottom: 1px solid #F7F7F5; margin-bottom: 12px; }
.cart-subtotal-line strong { font-size: 20px; }
.cart-topline .cart-subline { margin: 4px 0 0; font-size: 13px; color: var(--ink-2); }
.cart-delivery-note { margin: 6px 0 0; font-size: 13px; color: #6b7a70; }
.saved-heading { margin: 0; font-size: 16px; font-weight: 800; color: #1A1A1A; }
.cart-secondary { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 16px 0 4px; }
.cart-secondary .btn-continue-shopping { margin: 0; }
/* spec v6 (A1): hidden while the cart is empty (the empty panel carries the one big button).
   `.cart-secondary` sets display:flex, which beats the [hidden] attribute's UA rule. */
.cart-secondary[hidden] { display: none; }

/* Pinned checkout bar — DELIBERATE exception (a cart action bar, not furniture). */
.cart-actionbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
    background: #fff; border-top: 1px solid #e4ebe6;
    box-shadow: 0 -4px 18px rgba(0,0,0,.08);
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
}
.cab-inner {
    max-width: 900px; margin: 0 auto;
    display: flex; align-items: center; gap: 14px;
}
.cab-total strong { font-size: 17px; color: #1A1A1A; }
.cart-actionbar .btn-checkout { margin: 0 0 0 auto; min-height: 48px; padding: 0 22px; width: auto; }
/* Matching bottom padding so the bar can never cover the last item. */
body:has(.cart-actionbar:not([hidden])) .cart-page { padding-bottom: 96px; }
.cart-page { padding-bottom: 96px; }   /* fallback for browsers without :has() */

/* ── JOB 5: words BEFORE the glyph ── */
.navbar #account-icon { flex-direction: row; gap: 7px; }
.navbar .nav-signin-label { order: 0; }
.navbar #account-icon .nav-ico { order: 1; }

@media (max-width: 600px) {
    .cp-act { font-size: 12px; min-height: 44px; }
    .cart-actionbar .btn-checkout { padding: 0 16px; font-size: 14px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   STOREFRONT BATCH 4b — badge inside the glyph, cart suggestions, no subtotal
   ═══════════════════════════════════════════════════════════════════════ */

/* ── JOB 4: the count sits INSIDE the cart glyph, small (Amazon-style).
   It was an oversized pill floating above the icon and competing with it. ── */
.navbar .nav-cart-ico { position: relative; display: inline-flex; }
.navbar .cart-badge {
    position: absolute;
    /* Inside the basket bowl, not above the icon */
    top: 44%;
    left: 50%;
    transform: translate(-50%, -50%);
    min-width: 0;
    height: auto;
    padding: 0;
    border: none;                 /* the white ring made it read as a separate pill */
    background: none;
    box-shadow: none;
    color: var(--orange-ink);
    font-size: 10.5px;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.2px;
    pointer-events: none;
}

/* ── JOB 2: bar carries the action only ── */
.cart-actionbar .btn-checkout { margin: 0; width: 100%; }
.cab-inner { justify-content: stretch; }

/* ── JOB 3: catalogue picks on the cart page ── */
.cart-suggest { margin: 26px 0 8px; border-top: 1px solid #F7F7F5; padding-top: 18px; }
.cart-suggest-head { margin: 0 0 12px; font-size: 16px; font-weight: 800; color: #1A1A1A; }
/* 25 Sep: "Add more to your order" is now the SAME .prod-row swipe row + .row-card doorway the
   product page "You might also like" and a department's "Best sellers" use (styled at .prod-row /
   .row-card). The old .cart-suggest-grid grid + its media rules were removed. */

/* Footer entry to the assistant — styled exactly like the sibling links. */
.footer-col .footer-linkbtn {
    display: block; width: 100%; text-align: left;
    background: none; border: none; padding: 5px 0;
    font-size: 13.5px; line-height: 1.4; color: #6B6B66; font-family: inherit;
}
.footer-col .footer-linkbtn:hover { color: #fff; text-decoration: underline; }


/* ═══════════════════════════════════════════════════════════════════════
   STOREFRONT BATCH 6 — cart item rebuilt: boxed variant rows, one pill row
   per PRODUCT, bin-minus stepper, shared product card, cart glyph.
   Scoped to storefront hooks (#cart-items, .navbar, .cart-suggest). The ops
   console uses .admin-nav and has zero "cart-" / "navbar" occurrences.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── STEP 2: ONE CARD PER PRODUCT. Thumbnail + name at the top. ── */
#cart-items .cart-product { padding: 0; }
#cart-items .cp-head {
    display: flex; align-items: center; gap: 11px;
    padding: 12px 12px 10px;
    border-bottom: 1px solid #f1f4f2;
}
#cart-items .cart-thumb {
    flex: 0 0 52px; width: 52px; height: 52px;
    border-radius: 9px; overflow: hidden; background: #f3f6f4;
}
#cart-items .cart-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
#cart-items .cp-name {
    margin: 0; min-width: 0;
    font-size: 15px; font-weight: 800; color: #16281c; line-height: 1.3;
    /* Two lines then ellipsis — a long name must not push the card taller than
       its neighbours, but it must not be cut to a single word either. */
    white-space: normal;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; overflow-wrap: anywhere;
}

/* ── STEP 2: ONE BOXED ROW PER VARIANT. A real container with its own visible
   surface and border — never text floating on plain white. A second variant is
   a second box below it; a third is a third box. Same treatment always. ── */
#cart-items .cp-lines {
    display: flex; flex-direction: column; gap: 8px;
    padding: 10px 12px;
}
#cart-items .cv-row {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px;
    background: #f8faf9;                 /* the visible surface */
    border: 1px solid #E5E4E0;
    border-radius: 10px;
    min-width: 0;
}
#cart-items .cv-weight {
    flex: 0 0 auto; min-width: 0;
    font-size: 13.5px; font-weight: 700; color: #46564c;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#cart-items .cv-row .cart-qty { flex: 0 0 auto; background: #fff; }
#cart-items .cv-price {
    margin-left: auto;                   /* price to the right edge of the box */
    flex: 0 0 auto;
    font-size: 15px; font-weight: 800; color: #1A1A1A; white-space: nowrap;
}

/* The minus button IS the remove control at quantity 1 — no separate trash icon. */
#cart-items .qbtn-bin { color: #b03636; display: inline-flex; align-items: center; justify-content: center; }
#cart-items .qbtn-bin:hover { background: #fdeeee; }
#cart-items .qbtn-bin:active { background: #f9dede; }
.qbin { width: 16px; height: 16px; display: block; }

/* ── STEP 2: ONE full-width row of three EQUAL pills, PER PRODUCT.
   They truncated in batch 5 only because they shared a row with the stepper.
   On their own row there is room for the full labels. ── */
#cart-items .cp-actions {
    display: flex; gap: 8px; flex-wrap: nowrap;
    padding: 0 12px 12px;
    position: relative;
}
#cart-items .cp-act {
    flex: 1 1 0; min-width: 0;
    padding: 0 6px; min-height: 44px;
    font-size: 12.5px; font-weight: 700;
    border: 1px solid var(--control-edge); border-radius: 9px; background: #fff;
    color: #24402e;
    white-space: nowrap;                 /* one line; sizing below guarantees a fit */
}
#cart-items .cp-act-danger { color: var(--danger); border-color: var(--danger); }
#cart-items .cp-share-menu { top: calc(100% - 8px); right: 12px; }

/* ── The cart glyph and its count, matched to Amazon's.

   The basket is OPEN at the top — one stroke, no rim line — so the numeral sits in
   the opening itself, the way Amazon's does — in the gold band's ink (body:not(.admin-body) .navbar .cart-badge;
   the old #f08804 here never applied and was removed in batch 3A follow-up 4).

   Path geometry (viewBox 0 0 32 32): handle bar y 3.8 from x 0.9 to 10.2, the left
   wall down to (14.1, 23.0), the floor to (25.6, 23.0), then the right wall up to
   (31.3, 3.3). Because the handle extends to the left, the OPENING's centre is not
   the glyph's centre: at the numeral's height the walls sit at x 11.7 and 29.0, so
   the opening centres on x ~20.4 = 63% across. Centring the numeral on the glyph
   instead pushed "99" through the left wall (measured ink x 10.23 against a wall at
   11.73). ── */
.navbar .nav-cart-icon { width: 32px; height: 32px; display: block; flex: 0 0 auto; }
.navbar .nav-cart-ico { position: relative; display: inline-flex; }
.navbar .cart-badge {
    position: absolute;
    left: 63%;
    top: 20%;
    transform: translate(-50%, -50%);
    /* max-content, not auto: an auto width on an absolutely positioned box does not
       shrink-wrap here (measured 22px for a single digit), which is what previously
       made the count read as a pill hanging off the icon. */
    width: max-content;
    min-width: 0; height: auto; padding: 0;
    border: none; background: none; box-shadow: none;
    text-align: center;
    justify-content: center;
    font-size: 15px; font-weight: 700; line-height: 1;
    letter-spacing: -0.2px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    pointer-events: none;
}
/* spec v6 (B1): an EMPTY cart shows no count at all — not a "0", not an empty bubble. Every
   writer sets `hidden` at 0; the rules above set display with !important (and the ≤600px rule
   sets inline-flex), so this must win over all of them. */
.navbar .cart-badge[hidden],
.nav-cart-link .cart-badge[hidden] { display: none !important; }
/* spec v6 (B2): over 99 the count reads "99+". Three glyphs at 15px (~25px) would overrun the
   opening (~17px between the walls at this height), so "99+" is set smaller to stay inside the
   basket. Every writer adds this class exactly when it writes "99+". */
.navbar .cart-badge.is-99plus { font-size: 10px; letter-spacing: -0.4px; }

/* 25 Sep: the old .cart-suggest-grid (fixed 4/2-column grid of buyable cards) was removed —
   "Add more to your order" is the .prod-row swipe row now (see .prod-row / .row-card). */

@media (max-width: 600px) {
    #cart-items .cp-head { padding: 11px 11px 9px; gap: 10px; }
    #cart-items .cart-thumb { flex-basis: 48px; width: 48px; height: 48px; }
    #cart-items .cp-name { font-size: 14px; }
    #cart-items .cp-lines { padding: 9px 11px; gap: 7px; }
    #cart-items .cv-row { padding: 7px 9px; gap: 8px; }
    /* Measured: the row is 316px at 390px wide. Trimming the padding and gap lifts
       each pill's inner width from 79px to ~88px, against 79px of label — so
       "Save for later" clears with real headroom instead of sitting exactly on the
       limit, where a font fallback would have truncated it. */
    #cart-items .cp-actions { padding: 0 11px 11px; gap: 5px; }
    #cart-items .cp-act { padding: 0 3px; }
}

@media (max-width: 360px) {
    /* Narrowest supported width. The pills stay on ONE row carrying their FULL
       labels — the font drops rather than the text truncating. Measured at 320px:
       inner width 70px against 67px of "Save for later" at 10.5px. The 44px touch
       height is unchanged. */
    #cart-items .cp-act { font-size: 10.5px; padding: 0 1px; }
    #cart-items .cp-actions { padding: 0 8px 10px; gap: 4px; }
    #cart-items .cv-row { gap: 6px; padding: 7px 8px; }
    #cart-items .cv-weight { font-size: 12.5px; }
    #cart-items .cv-price { font-size: 14px; }
}


@media (max-width: 600px) {
    /* Shared with the ops console; keep the badge compact on a phone (the storefront
       card that also carried this rule was removed). */
    .stock-badge { font-size: 10px; padding: 3px 7px; top: 7px; }
}

/* JOB 4: match the ID specificity that styles the cart's page title so this
   section heading keeps a normal size and stays on one line. */
#cart .cart-suggest-head,
.cart-main .cart-suggest-head {
    font-size: 16px;
    font-weight: 800;
    line-height: 1.35;
    margin: 0 0 12px;
    color: #1A1A1A;
}

/* ═══════════════════════════════════════════════════════════════════════
   CHECKOUT REBUILD — delivering-to box, secure line, order button.
   Scoped to checkout hooks (.ck-*, #checkout-page). The ops console uses
   .admin-nav and has no "ck-" or "checkout-" occurrences.
   ═══════════════════════════════════════════════════════════════════════ */

/* One column: the customer-information card is gone, so a 1fr/380px split would
   strand the summary in a narrow rail beside empty space. */
#checkout-page .checkout-grid {
    grid-template-columns: minmax(0, 1fr);
    max-width: 640px;
    margin: 0 auto;
    gap: 16px;
}

/* ── Delivering to ── */
.ck-deliver {
    background: #fff;
    border: 1px solid #E5E4E0;
    border-radius: 14px;
    padding: 16px 18px;
}
.ck-deliver-name { margin: 0 0 6px; font-size: 15px; font-weight: 800; color: #16281c; line-height: 1.35; }
.ck-deliver-addr { margin: 0 0 8px; font-size: 14px; color: #46564c; line-height: 1.5; overflow-wrap: anywhere; }
.ck-deliver-eta  { margin: 0 0 10px; font-size: 13.5px; font-weight: 700; color: var(--orange-ink); }
/* ONE LINE, ALWAYS (spec v3, 27 Sep — nothing that appears late may move the Pay button).
   The line holds the date, its shimmer, or a short note when there is no date; every note is
   one line from 360px up, and this keeps a narrower screen from wrapping one onto a second
   line (which would push the button down) — it is cut short with an ellipsis instead. */
.ck-deliver-eta  { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* spec v6 (F1): the no-address note is the one delivery-date note allowed to wrap — it is drawn
   in the first frame and changes only when the customer adds an address (see setEtaLine). */
.ck-deliver-eta.is-wrap { white-space: normal; overflow: visible; text-overflow: clip; }

/* ── spec v6 (F1): "Delivering to" — the chosen address, with "Change" on the right ── */
.ck-deliver-row { display: flex; align-items: flex-start; gap: var(--s3); }
.ck-deliver-row[hidden], .ck-deliver-none[hidden] { display: none; }
.ck-deliver-body { flex: 1 1 auto; min-width: 0; }
/* ONE LINE, whatever the font: the "Change" button narrows this column, so a name near the wrap
   point was two lines in the fallback font (the first frame, before Lato is ready) and one line in
   Lato — a 22.5px jump of the Pay button, measured in WebKit. A long name ends in "…" here; the
   full name is on the "Select a delivery address" screen. */
#checkout-page .ck-deliver-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#checkout-page .ck-deliver-phone { margin: 0 0 8px; font-size: 14px; color: #46564c; line-height: 1.5; }
#checkout-page .ck-deliver-note { margin: 0 0 8px; font-size: 14px; font-style: italic; color: var(--ink-2); line-height: 1.5; overflow-wrap: anywhere; }
#checkout-page .ck-deliver-note[hidden], #checkout-page .ck-deliver-phone[hidden] { display: none; }
#checkout-page .ck-deliver-none-text { margin: 0 0 var(--s3); font-size: 15px; color: var(--ink); line-height: 1.5; }
#checkout-page .ck-deliver-none .ck-btn-tall { width: 100%; margin-bottom: var(--s3); }

/* ── spec v6: the checkout's buttons (outlined 40px / tall 48px, orange primary 48px) ── */
#checkout-page .ck-btn-outline {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 40px; padding: 0 var(--s4);
    background: var(--page); color: var(--orange-ink);
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-btn);
    font-family: inherit; font-size: 15px; font-weight: 700; line-height: 1.2; cursor: pointer;
}
#checkout-page .ck-btn-outline:hover { color: var(--orange-ink); border-color: var(--orange-ink); }
#checkout-page .ck-btn-tall { min-height: 48px; }
#checkout-page .ck-change { flex: 0 0 auto; }
#checkout-page .ck-btn-primary {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 48px; padding: 0 var(--s4);
    background: var(--orange); color: var(--ink);
    border: var(--bw) solid var(--orange); border-radius: var(--r-btn);
    font-family: inherit; font-size: 16px; font-weight: 700; line-height: 1.2; cursor: pointer;
}
#checkout-page .ck-btn-primary:hover, #checkout-page .ck-btn-primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
#checkout-page .ck-btn-primary[disabled] { opacity: .6; cursor: progress; }
#checkout-page .ck-btn-block { width: 100%; }

/* ── spec v6 (F2/F4): the address screens, inside checkout ── */
#checkout-page .ck-screen { max-width: 640px; margin: 0 auto; padding: 0 16px 32px; box-sizing: border-box; }
#checkout-page .ck-screen[hidden], #ck-main[hidden] { display: none; }
#checkout-page .ck-back {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0;
    background: none; border: 0; color: var(--orange-ink);
    font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
#checkout-page .ck-screen-h { margin: var(--s2) 0 var(--s4); font-size: 24px; font-weight: 700; line-height: var(--lh-head); color: var(--ink); }
#checkout-page .ck-screen-h:focus { outline: none; }
#checkout-page .ck-addr-list { display: flex; flex-direction: column; gap: 12px; }
#checkout-page .ck-addr-card {
    display: flex; align-items: flex-start; gap: 12px; padding: 14px;
    border: var(--bw) solid var(--divider); border-radius: var(--r-card); background: var(--page); cursor: pointer;
}
/* SELECTED: a 2px orange border (padding 13px keeps the card the same size) and a light tint of
   the same brand orange — no new colour. */
#checkout-page .ck-addr-card[aria-checked="true"] { border: 2px solid var(--orange-ink); padding: 13px; background: rgba(224, 123, 31, .06); }
#checkout-page .ck-addr-card:focus-visible { outline: 3px solid var(--orange-ink); outline-offset: 2px; }
#checkout-page .ck-radio {
    flex: 0 0 20px; width: 20px; height: 20px; margin-top: 1px; box-sizing: border-box;
    border: 2px solid var(--ink-2); border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
}
#checkout-page .ck-addr-card[aria-checked="true"] .ck-radio { border-color: var(--orange-ink); }
#checkout-page .ck-addr-card[aria-checked="true"] .ck-radio::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--orange-ink); }
#checkout-page .ck-addr-main { flex: 1 1 auto; min-width: 0; }
#checkout-page .ck-addr-title { margin: 0 0 4px; font-size: 15px; line-height: 1.4; color: var(--ink); }
#checkout-page .ck-pill {
    display: inline-block; margin-left: 6px; padding: 2px 8px; vertical-align: 1px;
    border-radius: var(--r-pill); background: var(--surface); border: var(--bw) solid var(--divider);
    color: var(--ink-2); font-size: 11px; font-weight: 900; letter-spacing: .04em; text-transform: uppercase; line-height: 1.4;
}
#checkout-page .ck-addr-line { margin: 0 0 2px; font-size: 14px; line-height: 1.5; color: #46564c; overflow-wrap: anywhere; }
#checkout-page .ck-addr-ins { font-style: italic; color: var(--ink-2); }
#checkout-page .ck-addr-edit { margin-top: var(--s2); }
#checkout-page .ck-addr-add {
    display: flex; align-items: center; justify-content: center; width: 100%; min-height: 52px; margin-top: 12px;
    border: var(--bw) dashed var(--orange-ink); border-radius: var(--r-card); background: var(--page);
    color: var(--orange-ink); font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
#checkout-page .ck-addr-add[hidden], #checkout-page .ck-addr-limit[hidden] { display: none; }
#checkout-page .ck-addr-limit { margin: 12px 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
#checkout-page #ck-deliver-here { margin-top: var(--s4); }
#checkout-page .ck-field { margin-bottom: var(--s4); }
#checkout-page .ck-field > label { display: block; margin: 0 0 6px; font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.4; text-transform: none; letter-spacing: 0; }
#checkout-page .ck-field input[type="text"],
#checkout-page .ck-field input[type="tel"],
#checkout-page .ck-field select,
#checkout-page .ck-field textarea {
    width: 100%; height: 48px; min-height: 48px; margin: 0; padding: 0 12px; box-sizing: border-box;
    font-family: inherit; font-size: 16px; color: var(--ink); background: var(--page);   /* 16px: no iOS zoom */
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-card);
}
#checkout-page .ck-field textarea { height: auto; min-height: 88px; padding: 12px; line-height: 1.5; resize: vertical; }
#checkout-page .ck-field input:focus, #checkout-page .ck-field select:focus, #checkout-page .ck-field textarea:focus {
    outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18);
}
#checkout-page .ck-field [aria-invalid="true"] { border-color: var(--danger); }
#checkout-page .ck-f-help { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
#checkout-page .ck-f-helprow { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
#checkout-page .ck-f-count { flex: 0 0 auto; margin-top: 6px; font-size: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
#checkout-page .ck-f-err { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: var(--danger); }
#checkout-page .ck-f-err[hidden], #checkout-page .ck-f-default[hidden] { display: none; }
#checkout-page .ck-field > label.ck-check { display: flex; align-items: center; gap: var(--s2); min-height: 44px; margin: 0; font-size: 15px; font-weight: 400; cursor: pointer; }
#checkout-page .ck-check input { width: 20px; height: 20px; margin: 0; accent-color: var(--orange-ink); }
#checkout-page .ck-f-actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); margin-top: var(--s2); }
#checkout-page .ck-f-actions button { width: 100%; min-height: 48px; }

/* ── spec v6 (D1): the Order Summary's rows — photo · name + "size · Qty N" · line price. The
   thumb box is the cart page's (48px, the same radius and placeholder background). ── */
/* No border of its own: .summary-totals below already draws the rule between the rows and the money. */
#checkout-page .ck-lines { list-style: none; margin: 0 0 var(--s3); padding: 0; display: flex; flex-direction: column; gap: var(--s3); }
#checkout-page .ck-lines[hidden] { display: none; }
#checkout-page .ck-line { display: flex; align-items: center; gap: 12px; }
#checkout-page .ck-line-thumb { flex: 0 0 48px; width: 48px; height: 48px; border-radius: 9px; overflow: hidden; background: #f3f6f4; }
#checkout-page .ck-line-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
#checkout-page .ck-line-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
#checkout-page .ck-line-name { font-size: 15px; font-weight: 700; color: var(--ink); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#checkout-page .ck-line-meta { font-size: 13px; color: var(--ink-2); line-height: 1.4; }
#checkout-page .ck-line-price { flex: 0 0 auto; font-size: 15px; font-weight: 700; color: var(--ink); text-align: right; }

/* ── spec v6 (D2): ONE static line above the button — centred, 13px, secondary text, with a
   14px lock before it. ── */
#checkout-page .ck-secure {
    max-width: 640px;
    margin: 22px auto 0;
    padding: 0 16px;
    box-sizing: border-box;
    font-size: 13px; line-height: 1.5; color: var(--ink-2); text-align: center;
}
#checkout-page .ck-secure-ico { display: inline-block; width: 14px; height: 14px; margin-right: 6px; vertical-align: -2px; }

/* ── The order button: alone, centred, at the very bottom, outside every box ── */
.ck-place {
    max-width: 640px;
    margin: 12px auto 0;
    padding: 0 16px 40px;
    display: flex; flex-direction: column; align-items: center;
}
.ck-place .btn-paystack {
    width: 100%; max-width: 340px;
    margin: 0;
    display: flex; align-items: center; justify-content: center;
    min-height: 48px;
}
.ck-place .checkout-status { margin-top: 10px; }

/* Summary: three rows, nothing else. */
#checkout-page .summary-row { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; }

/* ═══════════════════════════════════════════════════════════════════════════
   STAGE 4 BATCH 3b — the checkout summary tells the truth about delivery.

   The shipping and total cells used to be a hardcoded figure in the markup. They
   are now one of three things and never anything else: a shimmer while the
   server is being asked, a muted phrase when there is no figure to give, or a
   real amount the server quoted. Each has a visual weight that matches how much
   it should be trusted.
   ═══════════════════════════════════════════════════════════════════════════ */

/* IN FLIGHT (state 5). A placeholder the size of the number it stands in for, so
   the row does not jump when the figure lands. */
.ck-shimmer {
    display: inline-block;
    width: 74px; height: 15px;
    border-radius: 4px;
    background: linear-gradient(90deg, #E6E6E6, #F2F2F2 50%, #E6E6E6);
    background-size: 200% 100%;
    animation: ck-shimmer 1.1s linear infinite;
}
@keyframes ck-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
/* A moving gradient beside a price is exactly the kind of motion that triggers
   discomfort. Under the reduced-motion preference it becomes a still block —
   still a placeholder, still the right size, simply not animated. */
@media (prefers-reduced-motion: reduce) { .ck-shimmer { animation: none; } }

/* NOT A NUMBER (states 4 and 6). Deliberately quieter than a real figure —
   normal weight even on the grand-total row, which is otherwise 800. */
#checkout-page .ck-muted { color: #5C5C5C; font-weight: 400; }

/* DISCOUNT (state 3). Green and bold on BOTH halves: the customer earned this and it should read as a gain, not as an
   accounting adjustment — money the customer SAVES is rule A's green (5.37:1 on white). */
#checkout-page .ck-discount-row,
#checkout-page .ck-discount-row span { color: var(--paid-green); font-weight: 700; }

/* CLOSING THE TRAP THAT PRODUCED THE EMPTY DISCOUNT ROW.
   `hidden` is honoured by the UA rule [hidden] { display: none }, which sits in
   the weakest cascade origin: the .summary-row rule above sets display:flex and
   overrides it, so a summary row marked `hidden` was painted anyway — label
   showing, amount blank, on every ordinary cart.

   The discount row no longer relies on this — it is added to and removed from
   the DOM (see setDiscountRow in checkout.html). This rule exists so the NEXT
   summary row someone marks `hidden` behaves the way its author will expect.
   Specificity (1,2,0) beats the display:flex rule at (1,1,0) without needing
   !important, and it reaches nothing outside a summary row. */
#checkout-page .summary-row[hidden] { display: none; }

/* OVER THE PRICED CEILING (state 6). A notice, not a warning — nothing has gone
   wrong and the customer has done nothing incorrectly. */
/* SELECTED BY ID, NOT BY CLASS, AND FOR A MEASURED REASON. The customer-page type
   scale below sets `body:not(.admin-body) p` to var(--fs-body) — specificity (0,2,1)
   — which outranks any class selector here and appears LATER in this file, so a
   class rule loses twice over. This was not theoretical: the hint measured 15px on
   the rendered page when it was written as a class. An id is (1,0,0) and settles it
   in both directions. The sizes below are the approved design, not the type scale. */
.ck-heavy-note {
    margin-top: 12px;
    background: #FFF7E8;
    border: 1px solid #E9D6A6;
    border-radius: 10px;
    padding: 12px 13px;
    line-height: 1.55;
    color: #4A3F2C;
}
#ck-heavy-note, #ck-heavy-note p { font-size: 14px; }
#ck-heavy-note p { margin: 0 0 8px; line-height: 1.55; }
#ck-heavy-note p:last-child { margin-bottom: 0; }
#ck-heavy-note .ck-heavy-lead { font-weight: 700; }
/* It sits UNDER the Pay button now, inside .ck-place (spec v4 — nothing that appears late may
   move the Pay button). .ck-place centres its children at their own width; the note keeps the
   full width of the column instead, as it had in the summary card, so it still reads as a panel. */
.ck-place .ck-heavy-note { align-self: stretch; }

/* WHY THE BUTTON IS OFF. Sits under it, quieter than the button and quieter than
   the error line — because this is not an error. */
#ck-pay-hint, #ck-placed-note { margin: 10px 0 0; text-align: center; font-size: 13px; line-height: 1.5; color: #5C5C5C; }   /* round 3 (T1): the placed order's line, the same grey hint */

/* A button disabled because we cannot price the order is not "in progress".
   The inline rule sets cursor: progress for the payment spinner; this wins for
   the blocked case, which is a different thing and should not look busy. */
#checkout-page #pay-btn[disabled].is-blocked { cursor: not-allowed; }
#checkout-page .back-cart-link { display: inline-block; margin-top: 14px; }

/* ── Batch 3B: THE DISCOUNT CODE (checkout.js, "A DISCOUNT CODE") ──
   The link is orange TEXT (--orange-ink, 4.99:1 on white) with a 44px target; the field is the checkout's own 48px field
   and Apply its secondary (outlined) button, --orange-ink text (4.99:1); the reason a code is refused is --danger (#B3261E, 6.54:1 on
   white); the applied line and the row's −₦X are rule A's green (--paid-green, 5.37:1). Every part is added or shown
   by the script — [hidden] is restated for each one that sets `display`. */
#checkout-page .ck-code { margin-top: var(--s3); }
#checkout-page .ck-code-link {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0;
    background: none; border: 0; color: var(--orange-ink); text-decoration: underline; text-underline-offset: 3px;
    font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
#checkout-page .ck-code-link:hover { text-decoration-thickness: 2px; }
#checkout-page .ck-code-link:focus-visible, #checkout-page .ck-code-remove:focus-visible { outline: 3px solid var(--orange-ink); outline-offset: 2px; border-radius: 2px; }
#checkout-page .ck-code-link[hidden], #checkout-page .ck-code-form[hidden], #checkout-page .ck-code-err[hidden], #checkout-page .ck-code-ok[hidden] { display: none; }
#checkout-page .ck-code-label { display: block; margin: 0 0 6px; font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.4; text-transform: none; letter-spacing: 0; }
#checkout-page .ck-code-fieldrow { display: flex; gap: var(--s2); }
#checkout-page .ck-code-input {
    flex: 1 1 auto; min-width: 0; height: 48px; margin: 0; padding: 0 12px; box-sizing: border-box;
    font-family: inherit; font-size: 16px; color: var(--ink); background: var(--page); text-transform: uppercase;   /* 16px: no iOS zoom */
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-card);
}
#checkout-page .ck-code-input::placeholder { text-transform: none; }
#checkout-page .ck-code-input:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
#checkout-page .ck-code-input[aria-invalid="true"] { border-color: var(--danger); }
#checkout-page .ck-code-apply {   /* secondary: the checkout's outlined button, 48px */
    flex: 0 0 auto; min-height: 48px; padding: 0 var(--s4);
    background: var(--page); color: var(--orange-ink); border: var(--bw) solid var(--control-edge); border-radius: var(--r-btn);
    font-family: inherit; font-size: 15px; font-weight: 700; line-height: 1.2; cursor: pointer;
}
#checkout-page .ck-code-apply:hover { border-color: var(--orange-ink); }
#checkout-page .ck-code-apply[disabled] { opacity: .6; cursor: progress; }
#checkout-page .ck-code-err { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: var(--danger); }
#checkout-page .ck-code-ok { margin: 0; font-size: 14px; line-height: 1.5; color: var(--paid-green); font-weight: 700; }
/* The row: "Discount · CODE  Remove" on the left (ink), −₦X on the right (green, bold). A long code wraps rather than
   pushing the amount off a 320px screen. */
#checkout-page .ck-code-line { align-items: center; }
#checkout-page .ck-code-name { display: inline-flex; flex-wrap: wrap; align-items: center; column-gap: var(--s2); min-width: 0; overflow-wrap: anywhere; }
#checkout-page .ck-code-remove {
    display: inline-flex; align-items: center; min-height: 36px; padding: 0 2px;
    background: none; border: 0; color: var(--orange-ink); text-decoration: underline; text-underline-offset: 3px;
    font-family: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
}
#checkout-page .ck-code-off { color: var(--paid-green); font-weight: 700; white-space: nowrap; }
/* 4A follow-up (B1): a placed order's code row has no Remove — the author display:inline-flex above beats the UA [hidden]. */
#checkout-page .ck-code-remove[hidden] { display: none; }

@media (max-width: 600px) {
    #checkout-page .checkout-grid { padding: 0 14px; gap: 14px; }
    .checkout-summary-card { padding: 18px 16px; }
    .ck-deliver { padding: 14px 16px; }
    .ck-place { padding: 0 14px 32px; }
    .ck-place .btn-paystack { max-width: 100%; }
}

/* ═══════════════════════════════════════════════════════════════════════
   CHECKOUT COSMETICS — button colour, secure-line wrapping, page end.
   Presentation only. Scoped to checkout hooks; the ops console has no
   "ck-" / "checkout-" / "btn-paystack" occurrences.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 2. The order button: flat brand ORANGE #E07B1F (the --orange token — "every primary
   action, everywhere"), no shadow. On hover it turns dark GREEN #195e34 with a soft green
   shadow; while pressed (:active) it is that same green. ── */
.ck-place .btn-paystack {
    background: #E07B1F;
    box-shadow: none;
}
.ck-place .btn-paystack:hover { transform: none; }   /* no lift; its hover and pressed colours are every orange button's (follow-up 4) */

/* ── 4. The empty band under the button. Measured at 390px AND 320px: the button
   ended at y=773 while the document ran to 900 — a 127px dead band, from
   `#checkout-page { margin: 24px auto 80px }` (an 80px bottom margin that collapsed
   through <body>) plus 32px of .ck-place bottom padding. Nothing was rendered in it.
   The page now ends shortly after the button. ── */
#checkout-page { margin-bottom: 0; }
.ck-place { padding-bottom: 20px; }
@media (max-width: 600px) {
    .ck-place { padding-bottom: 18px; }
}

/* ── Step indicator: the tick is an inline SVG, not an emoji (emoji render
   differently on every device). Sized to sit in the 28px circle exactly as the
   numerals 2 and 3 do — the circle's own dimensions are untouched, and 14px at
   stroke-width 2.8 in a 24 viewBox gives a ~1.6px stem, matching the 12px/700
   numerals beside it. ── */
.step-num .step-tick { width: 14px; height: 14px; display: block; }

/* ═══════════════════════════════════════════════════════════════════════
   THE RECEIPT — one appearance, one renderer (receipt.js).
   Scoped to `.receipt`, the container the receipt renders into
   (#account-receipt-body on account). Checkout's post-payment receipt popup
   was removed, so this now dresses the Account Center receipt alone; keeping
   the rules on the shared class means any future entry point inherits this
   exact appearance. The ops console has no "receipt"/"rcpt" occurrences.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Head: wordmark + status. No logo badge on screen (it repeated the
   wordmark directly beneath it); the PDF keeps it. ── */
.receipt .rcpt-top { text-align: center; margin-bottom: 14px; }
.receipt .rcpt-brand { margin: 0 0 4px; font-size: 19px; font-weight: 800; color: var(--orange-ink); }
.receipt .rcpt-status {
    display: inline-flex; align-items: center; gap: 6px;
    margin: 0; font-size: 13.5px; font-weight: 700;
}
.receipt .rcpt-status.is-paid { color: #1f7a3f; }
.receipt .rcpt-status.is-pending { color: var(--amber-ink); }
.receipt .rcpt-ico { width: 15px; height: 15px; flex: 0 0 auto; }   /* inline SVG, never emoji */
/* The brief screen drops the whole Order box, so the one identifier worth quoting
   to support sits under the status instead. Monospaced digits so it reads as a
   reference rather than prose. */
.receipt .rcpt-orderid {
    margin: 6px 0 0; font-size: 12.5px; font-weight: 700; color: #6b7a70;
    font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.receipt .rcpt-date { margin: 2px 0 0; font-size: 12px; color: var(--ink-2); }
/* Delivery leads with the recipient; the address is the supporting line. */
.receipt .rcpt-to { font-weight: 700; color: #16281c; }
/* No box title on Items — the table's own header row announces it — so the table
   must not inherit the gap a title would have left. */
.receipt .rcpt-box-items > .receipt-table:first-child { margin-top: 0; }

/* ── The Account Center receipt container ────────────────────────────────────
   Checkout's receipt popup is gone, so this dresses the account receipt alone.
   The body keeps 18px/20px padding — the content width at which the address stays
   on one line and "Download PDF" does not wrap onto a second (the card measures
   ~350px at a 390px viewport, ~280px at 320px). The container and the footer-button
   rules sit together here. ── */
#account-receipt-modal .receipt { padding: 18px 20px 8px; }
#account-receipt-modal .rcpt-foot .btn-clear,
#account-receipt-modal .rcpt-foot .auth-btn {
    width: auto; margin: 0; padding: 12px 20px; white-space: nowrap;
}

/* ── PART 3: every section is a real box with its own surface, spaced apart —
   the same treatment the cart already uses. Nothing floats on plain white. ── */
.receipt .rcpt-box {
    background: #f8faf9;
    border: 1px solid #E5E4E0;
    border-radius: 12px;
    padding: 12px 14px;
    margin-bottom: 10px;
}
.receipt .rcpt-box:last-of-type { margin-bottom: 0; }
.receipt .rcpt-box-title {
    margin: 0 0 8px; font-size: 11px; font-weight: 800;
    letter-spacing: 0.5px; text-transform: uppercase; color: var(--ink-2);
}
.receipt .rcpt-line { margin: 0 0 3px; font-size: 13px; color: #2b3530; overflow-wrap: anywhere; }
.receipt .rcpt-dim { color: var(--ink-2); }
.receipt .rcpt-eta {
    display: flex; align-items: center; gap: 6px;
    margin: 8px 0 0; font-size: 13px; font-weight: 700; color: var(--orange-ink);
}
/* Gallery batch, part C: late → the warning icon and its sentence in --amber-ink (4.72:1 on the box's #f8faf9); new
   dates → dark ink */
.receipt .rcpt-eta.is-late { color: var(--amber-ink); }
.receipt .rcpt-eta.is-new-date { color: var(--ink); }
.receipt .rcpt-eta .late-ic { flex: 0 0 18px; display: block; }

/* Order block: two columns, with the payment ref full width in mono so it
   cannot run to four lines the way it used to. */
.receipt .rcpt-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.receipt .rcpt-field { display: flex; flex-direction: column; min-width: 0; }
.receipt .rcpt-wide { grid-column: 1 / -1; }
.receipt .rcpt-k { font-size: 11px; font-weight: 700; letter-spacing: 0.4px; text-transform: uppercase; color: var(--ink-2); }
.receipt .rcpt-v { font-size: 12px; font-weight: 700; color: #16281c; line-height: 1.35; overflow-wrap: anywhere; }
.receipt .rcpt-ref {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11.5px; font-weight: 600; letter-spacing: -0.2px;
    user-select: all;                       /* one drag selects the whole ref */
}

/* Items table + totals sit inside the last box. */
.receipt .rcpt-box .receipt-table { margin-bottom: 10px; }
.receipt .receipt-table th,
.receipt .receipt-table td { padding: 7px 4px; }
.receipt .receipt-table th:first-child,
.receipt .receipt-table td:first-child { padding-left: 0; }
.receipt .receipt-table .rt-qty,
.receipt .receipt-table .rt-amt { text-align: right; }
.receipt .receipt-table td:first-child { overflow-wrap: anywhere; }
.receipt .receipt-table td.rt-size { color: var(--ink-2); white-space: nowrap; }
.receipt .receipt-table td.rt-qty,
.receipt .receipt-table td.rt-amt { font-variant-numeric: tabular-nums; white-space: nowrap; }
.receipt .rcpt-box .receipt-totals { border-top: 1px solid #E5E4E0; padding-top: 10px; }

/* ── The account modal gets the same guarantees the checkout one has: the body
   scrolls and the footer is always reachable, so Done / Download PDF can never
   be cut off at 320px. A scroll container, not sticky/fixed positioning. ── */
#account-receipt-modal .rcpt-card {
    max-height: calc(100vh - 40px);
    display: flex; flex-direction: column; overflow: hidden;
}
#account-receipt-modal .receipt { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
#account-receipt-modal .rcpt-foot { flex: 0 0 auto; border-top: 1px solid #f0f0f0; padding: 12px 16px; }
#account-receipt-modal .rcpt-close { width: 30px; height: 30px; display: grid; place-items: center; }
#account-receipt-modal .rcpt-close svg { width: 15px; height: 15px; }
.rcpt-foot .auth-btn { display: inline-flex; align-items: center; gap: 7px; }

@media (max-width: 360px) {
    .receipt .rcpt-grid { grid-template-columns: 1fr; }
    .receipt .rcpt-box { padding: 11px 12px; }
    /* The account receipt's narrow-screen overrides, placed AFTER the shared
       container rules above so they actually win — at equal specificity the later
       rule takes effect; getting that ordering wrong once left the account receipt
       on desktop padding at 320px. */
    #account-receipt-modal .receipt { padding: 16px 14px 8px; }
    #account-receipt-modal .rcpt-foot .btn-clear,
    #account-receipt-modal .rcpt-foot .auth-btn { padding: 11px 12px; font-size: 13px; }
}

/* ═══ THE account drawer — one component, every page (account-nav.js) ═══
   The overlay wrapper. Everything INSIDE it is the same markup account.html paints
   into its sidebar (.sb-profile / .sb-item / .sb-footer), so the two surfaces cannot
   drift: there is one builder and one set of item styles. This replaces .ftk-drawer
   /.dw-* (the old eleven-entry emoji drawer) and #account-dropdown /.dd-* (a third,
   permanently hidden menu), both deleted. */

/* The shared item styles live here (not only in account.html's inline <style>) so the
   drawer looks right on index, cart and checkout, which never load that page. */
.nav-drawer-body nav { display: flex; flex-direction: column; gap: 2px; }
body:not(.admin-body) .sb-item {
    display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
    background: transparent; border: none; border-left: 3px solid transparent;
    padding: 12px 14px; font-size: 14.5px; font-weight: 600; color: #4b5158;
    border-radius: 9px; cursor: pointer; text-decoration: none;
    font-family: inherit; transition: background .15s, color .15s, border-color .15s;
}
body:not(.admin-body) .sb-item:hover { background: #f4f6f4; color: #1a1a1a; }
body:not(.admin-body) .sb-item.active { background: #F7F7F5; color: var(--orange-ink); border-left-color: var(--orange-ink); font-weight: 700; }
body:not(.admin-body) .sb-ico { flex: 0 0 18px; width: 18px; height: 18px; }
body:not(.admin-body) .sb-footer { margin-top: auto; padding-top: 14px; border-top: 1px solid #E5E4E0; flex: 0 0 auto; }
body:not(.admin-body) .sb-item.sb-logout { color: #c0392b; font-weight: 700; }
body:not(.admin-body) .sb-item.sb-logout:hover { background: #fdecea; color: #a93226; }

/* ═══════════════════════════════════════════════════════════════════════════
   COMPONENT LAYER — every selector scoped to body:not(.admin-body).
   Appended last so it wins on source order at equal specificity; the
   `body:not(...)` prefix also raises specificity above the page rules above.
   ═══════════════════════════════════════════════════════════════════════════ */
body:not(.admin-body) * { font-family: inherit; }

/* ── TYPE SCALE — the only sizes on a customer page ── */
body:not(.admin-body) h1,
body:not(.admin-body) .s-heading { font-size: var(--fs-title); font-weight: 700; line-height: var(--lh-head); color: var(--ink); margin: 0 0 var(--s4); letter-spacing: 0; }
body:not(.admin-body) h2,
body:not(.admin-body) h3,
body:not(.admin-body) .s-card h3,
body:not(.admin-body) .section-header h2 { font-size: var(--fs-head); font-weight: 700; line-height: var(--lh-head); color: var(--ink); margin: 0 0 var(--s3); }
body:not(.admin-body) p,
body:not(.admin-body) li,
body:not(.admin-body) label,
body:not(.admin-body) input,
body:not(.admin-body) select,
body:not(.admin-body) textarea,
body:not(.admin-body) button,
body:not(.admin-body) a { font-size: var(--fs-body); line-height: var(--lh-body); }
/* iOS Safari ZOOMS the layout when a focused control is under 16px, and the page then
   pans sideways until reload — confirmed on a real iPhone. 16px is the threshold, so it
   is written as a literal here: it is a device constraint, not a typographic choice, and
   must not follow --fs-body if that is ever retuned. Split out of the rule above rather
   than raising its value, because that selector list also carries p/li/label/button/a
   and raising it would resize the whole customer site. */
body:not(.admin-body) input,
body:not(.admin-body) select,
body:not(.admin-body) textarea { font-size: 16px; }
body:not(.admin-body) .s-note,
body:not(.admin-body) .acc-sub,
body:not(.admin-body) .acc-msg,
body:not(.admin-body) .sb-since,
body:not(.admin-body) .empty-sub { font-size: var(--fs-meta); line-height: var(--lh-body); color: var(--ink-2); }
body:not(.admin-body) .micro,
body:not(.admin-body) .form-group label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); line-height: var(--lh-body); }

/* ── HEADER BAND: solid brand gold, full width, dark ink, on every page ── */
body:not(.admin-body) .navbar {
    background: var(--gold); border-bottom: none; box-shadow: none;
    padding: var(--s3) var(--s4); color: var(--gold-ink);
}
body:not(.admin-body) .navbar .nav-wordmark,
body:not(.admin-body) .navbar .nav-signin-label,
body:not(.admin-body) .navbar a,
body:not(.admin-body) .navbar button,
body:not(.admin-body) .navbar .nav-ico,
body:not(.admin-body) .navbar .nav-cart-icon { color: var(--gold-ink); }
body:not(.admin-body) .navbar #account-icon,
body:not(.admin-body) .navbar .nav-cart-link { background: none; border: none; }
body:not(.admin-body) .navbar .cart-badge { color: var(--gold-ink); }
body:not(.admin-body) .nav-row { max-width: 720px; margin: 0 auto; width: 100%; }

/* ── PAGE SHELL ── */
body:not(.admin-body) main,
body:not(.admin-body) .settings-layout,
body:not(.admin-body) #checkout-page,
body:not(.admin-body) .cart-page { max-width: 720px; margin-left: auto; margin-right: auto; padding-left: var(--s4); padding-right: var(--s4); }
@media (min-width: 721px) {
    body:not(.admin-body) main,
    body:not(.admin-body) .settings-layout,
    body:not(.admin-body) #checkout-page,
    body:not(.admin-body) .cart-page { padding-left: var(--s5); padding-right: var(--s5); }
}

/* ── FOOTER: grey with a 1px top divider. The homepage green block is gone. ── */
body:not(.admin-body) .site-footer,
body:not(.admin-body) footer { background: var(--surface); color: var(--ink); border-top: var(--bw) solid var(--divider); box-shadow: none; }
body:not(.admin-body) .site-footer h4,
body:not(.admin-body) .site-footer h5,
body:not(.admin-body) .footer-grid h4,
body:not(.admin-body) .footer-grid h5 { color: var(--ink); }
body:not(.admin-body) .footer-grid p,
body:not(.admin-body) .footer-grid a,
body:not(.admin-body) .footer-bottom,
body:not(.admin-body) .footer-locale { color: var(--ink-2); opacity: 1; }
body:not(.admin-body) .footer-grid a:hover { color: var(--orange-ink); }

/* ── BUTTONS: 48px, 15/700, radius 6, full width on mobile ── */
body:not(.admin-body) .auth-btn,
body:not(.admin-body) .acc-btn,
body:not(.admin-body) .btn-paystack,
body:not(.admin-body) .shop-link,
body:not(.admin-body) .receipt-btn,
body:not(.admin-body) .rcpt-foot button {
    min-height: var(--s7); padding: 0 var(--s4);
    font-size: var(--fs-body); font-weight: 700; line-height: var(--lh-body);
    border-radius: var(--r-btn); border: var(--bw) solid transparent;
    display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
    cursor: pointer; box-shadow: none; text-decoration: none; transition: background .15s, border-color .15s;
}
/* PRIMARY — orange, every primary action on every page. Gold is never a button. */
body:not(.admin-body) .auth-btn.primary,
body:not(.admin-body) .acc-btn:not(.ghost),
body:not(.admin-body) .btn-paystack,
body:not(.admin-body) .shop-link,
body:not(.admin-body) .rcpt-foot .auth-btn { background: var(--orange); color: var(--ink); border-color: var(--orange); }
body:not(.admin-body) .auth-btn.primary:hover, body:not(.admin-body) .acc-btn:not(.ghost):hover, body:not(.admin-body) .btn-paystack:hover, body:not(.admin-body) .shop-link:hover, body:not(.admin-body) .auth-btn.primary:active, body:not(.admin-body) .acc-btn:not(.ghost):active, body:not(.admin-body) .btn-paystack:active, body:not(.admin-body) .shop-link:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
/* SECONDARY — white fill, warm border, orange-ink text */
body:not(.admin-body) .auth-btn.secondary,
body:not(.admin-body) .acc-btn.ghost,
body:not(.admin-body) .receipt-btn,
body:not(.admin-body) .btn-secondary,
body:not(.admin-body) .rcpt-foot .btn-clear { background: #fff; color: var(--orange-ink); border-color: var(--control-edge); }
body:not(.admin-body) .auth-btn.secondary:hover,
body:not(.admin-body) .acc-btn.ghost:hover,
body:not(.admin-body) .receipt-btn:hover { background: var(--surface); border-color: var(--orange-ink); }
/* DESTRUCTIVE — text only, red, for deleting */
body:not(.admin-body) .btn-destructive,
body:not(.admin-body) .s-link.danger,
body:not(.admin-body) .sb-item.sb-logout { color: var(--danger); }
@media (max-width: 720px) {
    body:not(.admin-body) .auth-btn,
    body:not(.admin-body) .acc-btn,
    body:not(.admin-body) .btn-paystack { width: 100%; }
}

/* ── INPUTS ── */
body:not(.admin-body) .form-group input,
body:not(.admin-body) .form-group select,
body:not(.admin-body) .acc-input,
body:not(.admin-body) input[type="text"],
body:not(.admin-body) input[type="email"],
body:not(.admin-body) input[type="tel"],
body:not(.admin-body) input[type="password"],
body:not(.admin-body) input[type="search"] {
    min-height: var(--s7); width: 100%; padding: 0 var(--s3);
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-card);
    /* 16px literal — see the iOS focus-zoom note above. This rule outranks it. */
    font-size: 16px; color: var(--ink); background: #fff; box-shadow: none;
}
body:not(.admin-body) .form-group input:focus,
body:not(.admin-body) .acc-input:focus,
body:not(.admin-body) input:focus {
    outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18);
}
body:not(.admin-body) .form-group { margin-bottom: var(--s4); }
body:not(.admin-body) .form-group label { display: block; margin-bottom: var(--s2); }
/* spec v6 (F5): the Account Center's delivery-instructions box — the same tokens as the inputs
   above, 88px tall, with checkout's live "N/200" counter on the right of its help line. */
body:not(.admin-body) .form-group textarea.addr-ins {
    display: block; width: 100%; min-height: 88px; padding: var(--s3); box-sizing: border-box;
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-card);
    font-family: inherit; font-size: 16px; line-height: 1.5; color: var(--ink); background: #fff; resize: vertical;
}
body:not(.admin-body) .form-group textarea.addr-ins:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
.addr-ins-helprow { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.addr-ins-count { flex: 0 0 auto; font-size: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.addr-ins-line { font-style: italic; }

/* ── CARDS VS ROWS ──
   A card means "this is tappable". Settings and detail content are PLAIN ROWS
   separated by 1px dividers. Applies to Security, Addresses, My Account, Support. */
body:not(.admin-body) .s-card,
body:not(.admin-body) .acc-card {
    background: transparent; border: none; border-radius: 0;
    box-shadow: none; padding: 0; margin: 0 0 var(--s5); max-width: none;
}
body:not(.admin-body) .acc-card + .acc-card { border-top: var(--bw) solid var(--divider); padding-top: var(--s4); }
body:not(.admin-body) .acc-head { padding: var(--s4) 0; gap: var(--s3); }
/* the grey filled icon squares on Security are removed */
body:not(.admin-body) .acc-ic { display: none; }
body:not(.admin-body) .acc-body-inner { padding: 0 0 var(--s4) 0; }
body:not(.admin-body) .s-row { padding: var(--s4) 0; border-bottom: var(--bw) solid var(--divider); }
body:not(.admin-body) .s-card > h3 { padding-bottom: var(--s2); }

/* ── ICONS: inline SVG, 20px, 1.5px stroke, currentColor ── */
body:not(.admin-body) .sb-ico,
body:not(.admin-body) .trust-ico,
body:not(.admin-body) .acc-head svg { width: 20px; height: 20px; flex: 0 0 20px; stroke-width: 1.5; }

/* ── PILLS ── */
body:not(.admin-body) .status-badge,
body:not(.admin-body) .s-badge,
body:not(.admin-body) .order-badge {
    border-radius: var(--r-pill); font-size: var(--fs-micro); font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.04em; padding: var(--s1) var(--s3);
    border: var(--bw) solid var(--divider); background: var(--surface); color: var(--ink-2);
}
/* Green is for STATUS only (rule A, final colour round) — this is the Paid pill. */
body:not(.admin-body) .status-badge.status-paid {
    background: var(--paid-green-bg); color: var(--paid-green); border-color: var(--paid-green-bg);
}

/* ── SHADOWS: none, except the drawer and modals ── */
body:not(.admin-body) .checkout-summary-card,
body:not(.admin-body) .ck-deliver,
body:not(.admin-body) .settings-sidebar { box-shadow: none; border-radius: var(--r-card); }
body:not(.admin-body) .nav-drawer-panel,
body:not(.admin-body) .rcpt-card,
body:not(.admin-body) .modal-card { box-shadow: var(--shadow); }


/* ── Row-level actions (address rows): secondary and destructive, not bare text ── */
body:not(.admin-body) .btn-row {
    min-height: var(--s6); padding: 0 var(--s3);
    font-size: var(--fs-meta); font-weight: 700; line-height: var(--lh-body);
    border-radius: var(--r-btn); border: var(--bw) solid var(--control-edge);
    background: #fff; cursor: pointer; font-family: inherit;
}
body:not(.admin-body) .btn-row-secondary { color: var(--orange-ink); }
body:not(.admin-body) .btn-row-secondary:hover { background: var(--surface); border-color: var(--orange-ink); }
body:not(.admin-body) .btn-row-danger { color: var(--danger); }
body:not(.admin-body) .btn-row-danger:hover { background: #FDF2F1; border-color: var(--danger); }
body:not(.admin-body) .s-row-actions { gap: var(--s2); }
body:not(.admin-body) .dev-meta { font-size: var(--fs-meta); color: var(--ink-2); line-height: var(--lh-body); }

/* Empty states are invitations, not null reports — give them room and a clear action. */
body:not(.admin-body) .empty-orders { padding: var(--s6) var(--s4); text-align: center; }
body:not(.admin-body) .empty-orders .empty-icon { color: var(--ink-2); display: inline-block; margin-bottom: var(--s3); }
body:not(.admin-body) .empty-title { font-size: var(--fs-head); font-weight: 700; color: var(--ink); margin: 0 0 var(--s2); }
body:not(.admin-body) .empty-orders .shop-link { margin-top: var(--s4); }

/* ── FOOTER: the homepage green block becomes grey. The dark greens live on the
      footer's CHILDREN (#1a2b1f / #14301f / #1a3c27), not only on .site-footer, so
      each one is repainted rather than relying on the parent. ── */
body:not(.admin-body) .site-footer,
body:not(.admin-body) .footer-top-link,
body:not(.admin-body) .footer-links,
body:not(.admin-body) .footer-grid,
body:not(.admin-body) .footer-legal,
body:not(.admin-body) .footer-bottom,
body:not(.admin-body) .footer-col {
    background: var(--surface); color: var(--ink); border-color: var(--divider);
}
body:not(.admin-body) .site-footer { border-top: var(--bw) solid var(--divider); }
body:not(.admin-body) .footer-top-link {
    color: var(--orange-ink); border-bottom: var(--bw) solid var(--divider);
    font-size: var(--fs-meta); font-weight: 700;
}
body:not(.admin-body) .footer-top-link:hover { background: var(--page); }   /* --orange-ink on white 4.99:1 (on #EFEFEC it was 4.33:1) — final colour round */
body:not(.admin-body) .navbar .product-search { border-color: var(--ink-2); }   /* on the gold band: 3.5:1 (the shared field edge is 2.3:1 there) */
body:not(.admin-body) .navbar .product-search:focus { border-color: var(--orange-ink); }
body:not(.admin-body) .footer-legal,
body:not(.admin-body) .footer-legal a,
body:not(.admin-body) .footer-plain,
body:not(.admin-body) .footer-locale { color: var(--ink-2); }
body:not(.admin-body) .footer-linkbtn,
body:not(.admin-body) .footer-grid a { color: var(--ink-2); background: none; }
body:not(.admin-body) .footer-grid a:hover,
body:not(.admin-body) .footer-linkbtn:hover { color: var(--orange-ink); }
body:not(.admin-body) .footer-legal { border-top: var(--bw) solid var(--divider); }

body:not(.admin-body) .cv-price,
body:not(.admin-body) .cart-suggest-head,
body:not(.admin-body) .cart-total-value,
body:not(.admin-body) .cp-name { color: var(--ink); border-color: var(--divider); }
body:not(.admin-body) .cp-act { color: var(--orange-ink); border-color: var(--control-edge); }

/* ═══ LOGIN & SECURITY rows — label · value · action ═══ */
body:not(.admin-body) .ls-rows { border-top: var(--bw) solid var(--divider); margin-bottom: var(--s5); }
body:not(.admin-body) .ls-row {
    display: flex; align-items: flex-start; gap: var(--s4);
    padding: var(--s4) 0; border-bottom: var(--bw) solid var(--divider);
}
body:not(.admin-body) .ls-main { flex: 1 1 auto; min-width: 0; }
body:not(.admin-body) .ls-label {
    margin: 0; font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.04em; color: var(--ink-2); display: flex; align-items: center; gap: var(--s1);
}
body:not(.admin-body) .ls-value { margin: var(--s1) 0 0; font-size: var(--fs-body); color: var(--ink); word-break: break-word; }
body:not(.admin-body) .ls-empty { color: var(--ink-2); }
/* Says WHY, not what — only present when there is a real reason to act. */
body:not(.admin-body) .ls-why { margin: var(--s1) 0 0; font-size: var(--fs-meta); color: var(--ink-2); }
/* A quiet amber marker, not an alarm. */
body:not(.admin-body) .ls-warn { color: var(--amber-ink); flex: 0 0 16px; }
body:not(.admin-body) .ls-act {
    flex: 0 0 auto; min-height: var(--s7); padding: 0 var(--s4);
    font-size: var(--fs-body); font-weight: 700; font-family: inherit;
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-btn);
    background: #fff; color: var(--orange-ink); cursor: pointer;
}
body:not(.admin-body) .ls-act:hover { background: var(--surface); border-color: var(--orange-ink); }
body:not(.admin-body) .ls-editor {
    border: var(--bw) solid var(--divider); border-radius: var(--r-card);
    padding: var(--s4); margin-bottom: var(--s5); background: var(--surface);
}
body:not(.admin-body) .ls-editor .auth-btn { width: auto; margin-right: var(--s2); }
@media (max-width: 380px) {
    body:not(.admin-body) .ls-act { padding: 0 var(--s3); }
}

/* ══ Rework Batch 1 · Part A — EDIT IN PLACE (Login & security + Addresses). Append-only,
   higher-specificity overrides. Each editor opens inside its own row/card; the page does not jump
   (the scroll rule lives in account.js). One row/card is open at a time. ══ */
/* the row becomes a column: [top: label/value/button][slot for the editor] */
body:not(.admin-body) .ls-rows .ls-row { display: block; }
body:not(.admin-body) .ls-row-top { display: flex; align-items: flex-start; gap: var(--s4); }
/* the open row: soft grey, edge-to-edge inside the page gutter (16px phone, 20px laptop) */
body:not(.admin-body) .ls-row.is-open {
    background: #F7F7F5; border-radius: var(--r-card);
    margin-inline: -16px; padding-inline: 16px;
}
body:not(.admin-body) .ls-row.is-open .ls-value,
body:not(.admin-body) .ls-row.is-open .ls-why,
body:not(.admin-body) .ls-row.is-open > .ls-row-top > .ls-act { display: none; }   /* A2 */
body:not(.admin-body) .ls-slot:empty { display: none; }
body:not(.admin-body) .ls-row.is-open .ls-slot { display: flex; flex-direction: column; align-items: stretch; padding: var(--s3) 0 var(--s2); }
/* moved editors sit cleanly on the grey — strip their own card chrome */
body:not(.admin-body) .ls-slot .ls-editor { background: transparent; border: 0; padding: 0; margin: 0; }
body:not(.admin-body) .ls-slot .acc-card,
body:not(.admin-body) .ls-slot .s-card { background: transparent; border: 0; box-shadow: none; margin: 0; padding: 0; max-width: none; }
body:not(.admin-body) .ls-slot .acc-card:hover { box-shadow: none; }
body:not(.admin-body) .ls-slot .acc-head { display: none; }              /* the row label is the title */
body:not(.admin-body) .ls-slot .acc-body { max-height: none; opacity: 1; overflow: visible; }
body:not(.admin-body) .ls-slot .acc-body-inner { padding: 0; }
body:not(.admin-body) .ls-slot #ls-data > h3 { display: none; }
/* A6 — button rows: right-aligned, wrap on narrow screens, 8px gap */
body:not(.admin-body) .ls-form-actions,
body:not(.admin-body) .addr-form-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; margin-top: var(--s4); }
/* A6 — every control 44px tall, 14px bold, 8px radius */
body:not(.admin-body) .ls-slot .auth-btn,
body:not(.admin-body) .ls-slot .acc-btn,
body:not(.admin-body) .ls-done,
body:not(.admin-body) .addr-form-actions .auth-btn {
    height: 44px; min-height: 44px; padding: 0 16px; font-size: 14px; font-weight: 700;
    border-radius: 8px; width: auto; margin: 0; display: inline-flex; align-items: center; justify-content: center;
}
body:not(.admin-body) .ls-slot .auth-btn.secondary,
body:not(.admin-body) .ls-done { background: #fff; color: var(--ink); border: 1px solid var(--control-edge); }
body:not(.admin-body) .ls-slot .auth-btn.primary,
body:not(.admin-body) .ls-slot .acc-btn:not(.ghost),
body:not(.admin-body) .addr-form-actions .auth-btn.primary { background: var(--orange); color: var(--ink); border: 1px solid var(--orange); }
body:not(.admin-body) .ls-slot .auth-btn.primary:hover, body:not(.admin-body) .addr-form-actions .auth-btn.primary:hover, body:not(.admin-body) .ls-slot .auth-btn.primary:active, body:not(.admin-body) .addr-form-actions .auth-btn.primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
body:not(.admin-body) .ls-slot .ls-done { align-self: flex-end; margin-top: var(--s3); }
/* A6 — the row/summary buttons themselves: 44px, padding 0 18px, 14px */
body:not(.admin-body) .ls-act { min-height: 44px; height: 44px; padding: 0 18px; font-size: 14px; }
/* A7 — Delete pushed LEFT (danger outline); Cancel white/border; the form inside the card is grey */
body:not(.admin-body) .addr-form-actions .addr-delete-btn { margin-right: auto; background: #fff; color: var(--danger); border: 1px solid var(--danger); }
body:not(.admin-body) .addr-form-actions .addr-cancel-btn { background: #fff; color: var(--ink); border: 1px solid var(--control-edge); }
body:not(.admin-body) .s-row.is-editing { background: rgba(224, 123, 31, .06); border-radius: var(--r-card); padding: var(--s4); }
body:not(.admin-body) .s-row.is-editing #addr-form-card { background: transparent; border: 0; box-shadow: none; margin: 0; padding: 0; max-width: none; }
/* Part K3/K4 — the editing/adding card is now form-ONLY (the address text is not shown above it),
   so the form's title is shown: "Add an address" / "Edit address". */
body:not(.admin-body) .s-row.is-editing #addr-form-card > h3 { display: block; margin: 0 0 var(--s3); font-size: 16px; font-weight: 700; color: var(--ink); }

/* The grid stretches its items so cards in a row share a height. */
body:not(.admin-body) .product-grid,
body:not(.admin-body) #product-grid,
body:not(.admin-body) #best-grid { align-items: stretch; }
/* 3 · Out of stock is NOT a primary colour and must not look pressable. */
body:not(.admin-body) .btn-add:disabled {
    background: var(--surface); color: var(--ink-2); border: var(--bw) solid var(--divider);
    cursor: not-allowed; opacity: 1;
}

/* ═══ THE ACCOUNT CENTER FRONT PAGE — "All options" ═══
   The gold .acct-band that used to sit here (hamburger · title · Shop) is deleted,
   markup and rules together. Its whole purpose was to let the sections reach each
   other through a hamburger; this page does that in the open, naming and describing
   every destination, so the band had nothing left to do.

   Everything below is `body:not(.admin-body)`-scoped as usual — but note that these
   are all NEW class names (.ao-*), so unlike the greens and the form rules, none of
   them can reach the ops console even by accident. */
/* Signed in, #account is a bare container. Its 40px top margin and 20px gutter would
   have pushed the back arrow away from the top-left corner, which is the one place it
   has to be on a phone. The three things inside it each carry their own width and
   rhythm already (.ao-shell here, .settings-layout below), so the wrapper has nothing
   left to contribute. Signed out it keeps every bit of its padding — the sign-in card
   still needs it, and that is why this is a class and not an edit to #account. */
body:not(.admin-body) #account.acct-shell { max-width: 960px; margin: 0 auto; padding: 0 0 var(--s6); }

body:not(.admin-body) .ao-shell { max-width: 720px; margin: 0 auto; background: var(--page); }
body:not(.admin-body) .ao-page { padding-bottom: var(--s6); }

/* The back control. 48x48 tap target, chevron only, --orange-ink (4.99:1), hard left, with a
   1px rule under the row it sits in. Identical on the front page and all four
   sections — one builder in account-nav.js paints it. */
body:not(.admin-body) .ao-backrow {
    display: flex; align-items: center;
    padding-left: var(--s2);
    border-bottom: var(--bw) solid var(--divider);
}
body:not(.admin-body) .ao-back {
    display: grid; place-items: center;
    width: 48px; height: 48px; min-height: 48px; padding: 0; margin: 0;
    color: var(--orange-ink); background: none; border: none; border-radius: var(--r-btn);
    cursor: pointer; text-decoration: none;
}
body:not(.admin-body) .ao-back:hover { background: var(--surface); }
body:not(.admin-body) .ao-back-ico { width: 22px; height: 22px; flex: 0 0 22px; }

/* Greeting. Larger than the drawer's, because here it is the page's title rather
   than a label above a menu. */
body:not(.admin-body) .ao-page .sb-hello { padding: var(--s5) var(--s4) var(--s4); }
body:not(.admin-body) .ao-page .sb-greet { font-size: var(--fs-title); font-weight: 700; line-height: var(--lh-head); }
body:not(.admin-body) .ao-page .sb-since { font-size: var(--fs-meta); color: var(--ink-2); }

/* The rows. Two lines of text between a 22px icon and a chevron, 16px of air above
   and below, a rule under each — including a rule above the first, so the list reads
   as a list and not as four things after a heading. */
body:not(.admin-body) .ao-rows { display: block; border-top: var(--bw) solid var(--divider); }
body:not(.admin-body) .ao-row {
    display: flex; align-items: center; gap: 14px;
    width: 100%; box-sizing: border-box; margin: 0;
    padding: var(--s4); min-height: 0;
    background: none; border: none; border-radius: 0;
    border-bottom: var(--bw) solid var(--divider);
    text-align: left; text-decoration: none; cursor: pointer;
    font-family: inherit; color: var(--ink);
}
body:not(.admin-body) .ao-row:hover { background: var(--surface); }
body:not(.admin-body) .ao-row .sb-ico { flex: 0 0 22px; width: 22px; height: 22px; color: var(--ink-2); }
body:not(.admin-body) .ao-text { flex: 1 1 auto; min-width: 0; display: block; }
body:not(.admin-body) .ao-title {
    display: block; font-size: 16px; font-weight: 700; line-height: var(--lh-head); color: var(--ink);
}
body:not(.admin-body) .ao-sub {
    display: block; margin-top: 2px;
    font-size: var(--fs-meta); font-weight: 400; line-height: 1.35; color: var(--ink-2);
}
body:not(.admin-body) .ao-sub:empty { display: none; }
body:not(.admin-body) .ao-chev { flex: 0 0 18px; width: 18px; height: 18px; color: var(--ink-2); }
/* Logout is the one row that does not open anything, so it has no chevron and no
   subtitle — and it is red, because it ends the session. */
body:not(.admin-body) .ao-row.ao-logout { color: var(--danger); }
body:not(.admin-body) .ao-row.ao-logout .sb-ico { color: var(--danger); }
body:not(.admin-body) .ao-row.ao-logout .ao-title { color: var(--danger); }
body:not(.admin-body) .ao-row.ao-logout:hover { background: #FDF2F1; }
body:not(.admin-body) .ao-back:focus-visible,
body:not(.admin-body) .ao-row:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: -2px; }

/* The shell sits under the back row now, not under a band. */
body:not(.admin-body) .settings-layout { margin-top: var(--s5); }


/* ── POLICY PAGES — Delivery, Returns, Terms, Privacy, Contact ──────────────
   Long-form prose, which the site had no styling for: every other page is a grid
   of cards, a form or a list. These are the ONLY rules here, and every value is
   an existing token — no new colour is introduced, and nothing outside
   .policy-page is touched, so no existing page can shift.

   The measure is capped at 68 characters rather than a pixel width: prose is read by
   the line, and a policy paragraph stretched across a 1440px screen is unreadable
   however wide the shell is. It is written as 39.44em, which is exactly 68ch IN LATO
   (Lato's "0" is 0.58em in every weight): a `ch` is measured in whichever font is
   drawing, so while Safari lays a page out in the fallback before Lato lands the
   column was 23px narrower (568.8px, not 591.6px) and every paragraph re-wrapped
   when Lato arrived. An em cap is the same width in both. */
/* ONE measure for the whole page, not two. The container was 760px while the prose
   inside it was capped at 68ch (~592px), so at 1440px the "Also worth reading" rule
   ran ~168px past the end of every paragraph above it — measured, not guessed. The
   cap lives on the container now, so the rule and the text share an edge. */
body:not(.admin-body) .policy-page {
    max-width: 39.44em;   /* = 68ch in Lato — see above */
    margin: 0 auto;
    padding: var(--s6) var(--shell-pad) var(--s7);
}
body:not(.admin-body) .policy h1 {
    font-size: var(--fs-title); line-height: var(--lh-head); font-weight: 700;
    color: var(--ink); margin: 0 0 var(--s2);
}
body:not(.admin-body) .policy h2 {
    font-size: var(--fs-head); line-height: var(--lh-head); font-weight: 700;
    color: var(--ink); margin: var(--s6) 0 var(--s2);
}
body:not(.admin-body) .policy p,
body:not(.admin-body) .policy li {
    font-size: var(--fs-body); line-height: var(--lh-body); color: var(--ink); margin: 0 0 var(--s3);
}
body:not(.admin-body) .policy ul { margin: 0 0 var(--s4); padding-left: var(--s5); }
body:not(.admin-body) .policy li { margin-bottom: var(--s2); }
body:not(.admin-body) .policy strong { font-weight: 700; }
/* The "Last updated" line: present, dated, and not competing with the copy. */
body:not(.admin-body) .policy .updated {
    font-size: var(--fs-meta); color: var(--ink-2); margin: 0 0 var(--s5);
}
/* Pulled-out note. --surface and --divider, the same pair every card on the site
   uses; the left rule is --orange because it is the one accent colour. */
body:not(.admin-body) .policy .callout {
    background: var(--surface);
    border: var(--bw) solid var(--divider);
    border-left: 3px solid var(--orange);
    border-radius: var(--r-card);
    padding: var(--s4);
    margin: var(--s5) 0;
    font-size: var(--fs-body); line-height: var(--lh-body); color: var(--ink);
}
/* Contact rows. A definition list in spirit; the label is the site's micro-label. */
body:not(.admin-body) .policy .contact {
    border: var(--bw) solid var(--divider); border-radius: var(--r-card);
    padding: var(--s4); margin: var(--s5) 0;
}
body:not(.admin-body) .policy .contact > div { margin-bottom: var(--s4); }
body:not(.admin-body) .policy .contact > div:last-child { margin-bottom: 0; }
body:not(.admin-body) .policy .contact span {
    display: block; font-size: var(--fs-micro); font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); margin-bottom: var(--s1);
}
body:not(.admin-body) .policy .contact a {
    font-size: var(--fs-body); font-weight: 700; color: var(--orange-ink); text-decoration: none;
    /* 44px tap target — these are the two controls on the page that matter. */
    display: inline-block; min-height: 44px; line-height: 44px;
}
body:not(.admin-body) .policy .contact a:hover { color: var(--orange-ink); text-decoration: underline; }
body:not(.admin-body) .policy a { color: var(--orange-ink); }
body:not(.admin-body) .policy a:hover { color: var(--orange-ink); }

/* The cross-links at the foot of each policy page: the other four, always. */
body:not(.admin-body) .policy-more {
    margin-top: var(--s7); padding-top: var(--s5); border-top: var(--bw) solid var(--divider);
}
body:not(.admin-body) .policy-more h2 {
    font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.04em; color: var(--ink-2); margin: 0 0 var(--s3);
}
body:not(.admin-body) .policy-more-links { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); }
body:not(.admin-body) .policy-more-links a {
    font-size: var(--fs-body); color: var(--orange-ink); text-decoration: none;
    min-height: 44px; line-height: 44px;
}
body:not(.admin-body) .policy-more-links a:hover { color: var(--orange-ink); text-decoration: underline; }

/* The contact route on the too-heavy notice. Inherits .ck-heavy-note's box. */
body:not(.admin-body) .ck-heavy-contact {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2);
    margin: var(--s3) 0 0; font-size: var(--fs-body);
}
body:not(.admin-body) .ck-heavy-contact a {
    color: var(--orange-ink); font-weight: 700; text-decoration: none;
    min-height: 44px; line-height: 44px;
}
body:not(.admin-body) .ck-heavy-contact a:hover { color: var(--orange-ink); text-decoration: underline; }
body:not(.admin-body) .ck-heavy-contact span { color: var(--ink-2); }

/* ── CHECKOUT'S ONE LEGAL LINE ──────────────────────────────────────────────
   Checkout deliberately does NOT get the site footer: a row of exits at the
   moment we want the customer paying is a row of ways to leave. This is the
   whole concession — three links, meta size, muted, below the fold of the form. */
body:not(.admin-body) .ck-legal {
    display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3);
    justify-content: center;
    margin: var(--s6) 0 var(--s5);
    font-size: var(--fs-meta); color: var(--ink-2);
}
body:not(.admin-body) .ck-legal a { color: var(--ink-2); text-decoration: none; }
body:not(.admin-body) .ck-legal a:hover { color: var(--ink); text-decoration: underline; }

/* ── RETRY PAYMENT — only on an "Awaiting Payment" order (marketplace batch 3A: inside the order's card) ── */
body:not(.admin-body) .ov-order-actions {
    display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
    padding: 0;
}
/* 44px min-height is the tap target, not decoration — this sits directly under the
   card's head, itself a button, so a near-miss must not open the receipt instead. */
body:not(.admin-body) .ov-retry {
    flex: 0 0 auto; min-height: 44px; padding: 0 var(--s4);
    font-family: inherit; font-size: var(--fs-meta); font-weight: 700;
    /* --orange, because line 55 says it is "every primary action, everywhere".
       Green is spoken for: --paid-green is the Paid status pill and nothing else,
       and a green Retry button beside a status pill would read as a state. */
    color: var(--ink); background: var(--orange);
    border: none; border-radius: var(--r-btn); cursor: pointer;
    transition: background 0.15s;
}
body:not(.admin-body) .ov-retry:hover, body:not(.admin-body) .ov-retry:active { background: var(--orange-dark); color: #000; }
body:not(.admin-body) .ov-retry:disabled { opacity: 0.55; cursor: progress; }
body:not(.admin-body) .ov-retry-msg {
    flex: 1 1 auto; min-width: 0;
    font-size: var(--fs-meta); line-height: var(--lh-body); color: var(--ink-2);
}
body:not(.admin-body) .ov-retry-msg.is-error { color: #c0392b; }
/* Batch 6 fix 4: the refund line on a refunded order's card — the same secondary text as the Retry message (meta
   size, --ink-2). */
body:not(.admin-body) .ov-refund-note {
    margin: 0; padding: 0;
    font-size: var(--fs-meta); line-height: var(--lh-body); color: var(--ink-2);
}
body:not(.admin-body) .ov-retry-msg:empty { display: none; }

/* Address row heading: the label when the customer gave one, otherwise the address. */
body:not(.admin-body) .addr-head { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
body:not(.admin-body) .addr-title { font-size: var(--fs-body); font-weight: 700; color: var(--ink); }
body:not(.admin-body) .addr-head .s-badge { flex: 0 0 auto; }

/* ═══ PART 3 — a tighter drawer. Rows keep a 44px tap target and the type scale. ═══ */

body:not(.admin-body) .nav-drawer-body nav { gap: 0; }
body:not(.admin-body) .sb-footer { margin-top: var(--s3); padding-top: var(--s2); }

/* Tighter still: the identity block gives its room back to the menu. */

body:not(.admin-body) .sb-footer { margin-top: var(--s2); padding-top: var(--s2); }

/* (the previous 200px content-height panel block was removed — the approved
   full-height side panel is defined at the end of this file) */

/* ═══ Doorway skeletons — shown while the catalogue / popular is in flight (Part B6) ═══
   The grid renders .cat-card and the swipe rows render .row-card (photo + name), so the skeletons
   take those shapes: a square photo box (.cat-card-img / .row-card-img size it) + one name line.
   Categories batch B: the category tiles on the department and "All categories" pages (department.js,
   categories.js) use the SAME grey boxes in the tile shape (.cat-tile-img sizes the square box). The homepage
   has no category tiles; its headline panels have their own grey boxes (.hero-panel.is-skeleton, below). */
body:not(.admin-body) .cat-card.is-skeleton,
body:not(.admin-body) .row-card.is-skeleton,
body:not(.admin-body) .cat-tile.is-skeleton { pointer-events: none; }
body:not(.admin-body) .cat-card.is-skeleton .sk-box,
body:not(.admin-body) .row-card.is-skeleton .sk-box,
body:not(.admin-body) .cat-tile.is-skeleton .sk-box { background: var(--surface); }
body:not(.admin-body) .cat-card.is-skeleton .sk-line {
    display: block; height: 14px; width: 80%; margin-top: 8px; background: var(--surface); border-radius: 4px;
}
/* Category tiles (department / "All categories" pages) + the swipe rows (best sellers, cart "Add more"): the grey box must be
   EXACTLY the size of the card it stands in for, so nothing below moves at the swap. The grey name line
   therefore keeps the real name's own box — the span carries .cat-tile-name / .row-card-name, so the same
   font-size, line-height and margin apply, and a no-break space gives it exactly one line — and the 14px
   grey bar is drawn inside that line, vertically centred. (Real names in these cards are always one line:
   tiles are short category names, row names are one line with an ellipsis.) */
body:not(.admin-body) .row-card.is-skeleton .sk-line,
body:not(.admin-body) .cat-tile.is-skeleton .sk-line { position: relative; }
body:not(.admin-body) .row-card.is-skeleton .sk-line::after,
body:not(.admin-body) .cat-tile.is-skeleton .sk-line::after { content: "\00a0"; }
body:not(.admin-body) .row-card.is-skeleton .sk-line::before,
body:not(.admin-body) .cat-tile.is-skeleton .sk-line::before {
    content: ""; position: absolute; left: 0; top: 50%; width: 80%; height: 14px; margin-top: -7px;
    background: var(--surface); border-radius: 4px;
}
@media (prefers-reduced-motion: no-preference) {
    body:not(.admin-body) .cat-card.is-skeleton .sk-box,
    body:not(.admin-body) .cat-card.is-skeleton .sk-line,
    body:not(.admin-body) .row-card.is-skeleton .sk-box,
    body:not(.admin-body) .row-card.is-skeleton .sk-line,
    body:not(.admin-body) .cat-tile.is-skeleton .sk-box,
    body:not(.admin-body) .cat-tile.is-skeleton .sk-line { animation: sk-pulse 1.4s ease-in-out infinite; }
    @keyframes sk-pulse { 0%,100% { opacity: 1; } 50% { opacity: .55; } }
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE ACCOUNT MENU — a full-height side panel. One component; only the row list
   differs between the storefront header and the Account Center hamburger.
   ═══════════════════════════════════════════════════════════════════════════ */
.nav-drawer { position: fixed; inset: 0; z-index: 1400; }
.nav-drawer[hidden] { display: none; }
/* the dimmed 110px strip of page that stays visible — tapping it closes */
.nav-drawer-scrim { position: absolute; inset: 0; background: rgba(16, 24, 20, .45); }
/* The X lives in the STRIP, not the panel: 44x44, white, near the top. */
body:not(.admin-body) .nav-drawer-close,
.nav-drawer-close {
    position: absolute; top: 16px; left: 22px; z-index: 2;
    display: grid;
    width: 44px; height: 44px; padding: 0; margin: 0;
    display: grid; place-items: center;
    background: none; border: none; color: #fff; cursor: pointer;
}
.nav-drawer-close:hover { opacity: .8; }
body:not(.admin-body) .nav-drawer-panel,
.nav-drawer-panel {
    /* FULL HEIGHT, anchored right. The width is exactly the viewport less the
       110px strip — 280px at 390, 210px at 320 — so the strip is always 110px. */
    position: fixed; top: 0; right: 0; bottom: 0;
    width: calc(100vw - 110px);
    background: #fff; box-shadow: -10px 0 34px rgba(16, 24, 20, .22);
    padding: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
    display: flex; flex-direction: column;
}
.nav-drawer-body { display: block; flex: 0 0 auto; padding: 20px 0 8px; }
body.nav-drawer-open { overflow: hidden; }

/* Header: two lines, no email, no avatar, no card. */
body:not(.admin-body) .sb-hello { padding: 0 16px 14px; text-align: left; background: none; border: none; }
body:not(.admin-body) .sb-greet {
    margin: 0; font-size: 20px; font-weight: 700; line-height: 1.25; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body:not(.admin-body) .sb-since {
    margin: 3px 0 0; font-size: 13px; font-weight: 400; line-height: 1.3; color: var(--ink-2);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body:not(.admin-body) .nav-drawer-body nav {
    display: block; border-top: 1px solid var(--divider); padding: 4px 0 0; margin: 0;
}
/* Rows: 48px tall, 15px text, 20px icon, 12px gap. */
body:not(.admin-body) .nav-drawer-body .sb-item {
    display: flex; align-items: center; gap: 12px;
    height: 48px; min-height: 48px; max-height: 48px;
    padding: 0 16px; margin: 0; width: 100%; box-sizing: border-box;
    font-size: 15px; font-weight: 600; line-height: 1.25; color: var(--ink);
    background: none; border: none; border-radius: 0;
    text-decoration: none; cursor: pointer; font-family: inherit;
}
body:not(.admin-body) .nav-drawer-body .sb-item:hover { background: var(--surface); }
body:not(.admin-body) .nav-drawer-body .sb-item.active { background: var(--surface); border-left: 3px solid var(--orange-ink); padding-left: 13px; color: var(--orange-ink); font-weight: 700; }
body:not(.admin-body) .nav-drawer-body .sb-ico { flex: 0 0 20px; width: 20px; height: 20px; }
body:not(.admin-body) .nav-drawer-body .sb-footer { margin: 0; padding: 4px 0 0; border-top: 1px solid var(--divider); }
body:not(.admin-body) .nav-drawer-body .sb-item.sb-logout { color: var(--danger); }
body:not(.admin-body) .nav-drawer-body .sb-item.sb-logout:hover { background: #FDF2F1; }

/* ═══════════════════════════════════════════════════════════════════════
   DESKTOP LAYOUT PASS
   The whole site was designed and signed off on a phone. Every container was
   therefore capped at 720px, which is correct at 390px and wrong at 1440px: the
   header sat in a 720px column inside a full-width gold band, the product grid
   started at x=150 while the header started at x=360 and the footer at x=170, and
   nothing lined up with anything.

   TWO RULES GOVERN EVERYTHING BELOW.

   1. Nothing here fires below 900px, except the grid column counts and the card
      baseline fix, which start at 640px. The 390px design is untouched by
      construction — every rule is inside a min-width query above it.
   2. Everything is scoped `body:not(.admin-body)`. The ops console has no <style>
      block of its own; 100% of its appearance comes from this file, so an unscoped
      rule would repaint it. It carries .admin-body, so none of this can reach it.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1 · THE SHELL ──────────────────────────────────────────────────────
   One content column, full window width, 20px gutter each side. The bands that
   must stay full-bleed (the gold header, the grey strip under it, the footer tones, the
   pinned cart bar) keep their background edge-to-edge and get the shell as
   PADDING; the plain blocks get it as padding too, so both resolve to the same
   content box and therefore the same left edge. Mixing max-width for one and
   padding for the other is what put the footer 20px inside the product grid.
   `max-width: none` below is what makes width:100% real — several of these rows
   carry a narrower cap of their own further up the file. */
@media (min-width: 900px) {
    body:not(.admin-body) .navbar,
    body:not(.admin-body) .products,
    body:not(.admin-body) .cart-page,
    body:not(.admin-body) #checkout-page,
    body:not(.admin-body) .footer-top-link,
    body:not(.admin-body) .footer-links,
    body:not(.admin-body) .footer-legal {
        max-width: none;
        margin-left: 0;
        margin-right: 0;
        padding-left: var(--shell-pad);
        padding-right: var(--shell-pad);
    }
    /* Two containers carry an id, so a class-only selector loses to them however
       many classes it has. `#cart { max-width: 1180px }` is why the cart page sat
       20px inside the product grid, and `#account.acct-shell { max-width: 960px }`
       is why the account centre did. Named here at id strength. */
    body:not(.admin-body) #cart.cart-page,
    body:not(.admin-body) main#account,
    body:not(.admin-body) main#account.acct-shell {
        max-width: none;
        margin-left: 0;
        margin-right: 0;
        padding-left: var(--shell-pad);
        padding-right: var(--shell-pad);
    }
    /* Inner caps that used to fight the shell. Each of these was a second, narrower
       container inside a row that is now already the right width. */
    body:not(.admin-body) .nav-row,
    body:not(.admin-body) .footer-links .footer-grid,
    body:not(.admin-body) .cab-inner,
    body:not(.admin-body) .ao-shell {
        max-width: none;
        margin-left: 0;
        margin-right: 0;
    }
    body:not(.admin-body) .cart-page .cart-main {
        max-width: none;
        margin-left: 0;
        margin-right: 0;
        padding-left: 0;
        padding-right: 0;
    }
    /* Checkout keeps its reading-width form column — a 1400px-wide address form is
       not an improvement — and the column is CENTRED in the window.

       It used to be pinned to the shell's left edge. That was right when the shell
       was capped at 1400px and every row shared that left edge, but once the cap
       came off the column stopped being one row among many and became a 640px form
       stranded in the corner of a 2300px window with 1,640px of nothing beside it.

       Only the margins change. Every one of these boxes keeps its own max-width, so
       the column is exactly as wide as it was — 640px, measured before and after —
       and the text inside is untouched: the Order Summary figures stay right-aligned
       against the column's right edge, its labels stay left, .ck-secure keeps its
       centred text.

       Every column box on checkout is listed, including the address screens
       (.ck-screen, spec v6) — left out, they would snap back to the left edge the
       moment a customer opened one. */
    body:not(.admin-body) #checkout-page .checkout-grid,
    body:not(.admin-body) #checkout-page .ck-secure,
    body:not(.admin-body) #checkout-page .ck-screen,
    body:not(.admin-body) #checkout-page .ck-place { margin-left: auto; margin-right: auto; }
    /* The step indicator is a sibling of <main>, not a child of it, so it does not
       inherit the shell padding and has to be centred in the viewport directly. Its
       own 20px side padding is dropped, or its contents sit 20px off the axis
       everything else is centred on. It is 560px against the column's 640px, so
       centring puts the two on one axis — closer than they were, since its steps are
       already justify-content:center inside their own box. */
    body:not(.admin-body) .checkout-steps {
        margin-left: auto; margin-right: auto;
        padding-left: 0; padding-right: 0;
    }
}

/* ── 2 · DESKTOP HEADER: one row ────────────────────────────────────────
   Logo + wordmark left, search filling the middle, "Sign in ›" + person + cart
   right. The markup keeps its two .nav-row divs — display:contents dissolves the
   first one so its two children become flex items of .navbar itself, and `order`
   drops the search between them. No HTML change, so below 900px the header is
   byte-for-byte the two-row control it is today. */
@media (min-width: 900px) {
    body:not(.admin-body) .navbar {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;   /* checkout.html has no search row */
        gap: var(--s5);
        padding-top: var(--s3);
        padding-bottom: var(--s3);
    }
    body:not(.admin-body) .navbar .nav-row-main { display: contents; }
    body:not(.admin-body) .navbar .nav-brand { order: 1; flex: 0 0 auto; }
    body:not(.admin-body) .navbar .nav-row-search {
        order: 2;
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
    }
    body:not(.admin-body) .navbar .nav-actions { order: 3; flex: 0 0 auto; }
    /* The 520px cap was a phone-era guard against the field spanning the row. In a
       three-part row the field IS the middle part, so it fills what is left. */
    body:not(.admin-body) .navbar .product-search-wrap { max-width: none; }
}

/* ── 3 · GRID COLUMNS ───────────────────────────────────────────────────
   6 / 5 / 4 / 3 / 2, exactly. The base grid is repeat(auto-fill, minmax(210px,1fr)),
   which produced 5 at 1440px and — because a max-width:960px rule forced two —
   only 2 between 640px and 960px, so a laptop showed fewer products than a tablet.
   These are explicit counts, not a track guess.

   The 24px gap starts at 640px, NOT below it. The <640px grid keeps its 10px gap
   because the 390px layout has to stay pixel-identical, and a gap change there
   would move every card.

   25 Sep: these column rules now belong to #product-grid ALONE (category / search) — and, since categories batch B,
   the Best Sellers page's #best-grid, which draws the same cards from the best-sellers list. The cart's
   "Add more to your order" is no longer a grid — it is the .prod-row swipe row (see .prod-row /
   .row-card), so it was removed from these selectors. */

/* FULL-WIDTH PASS: with no 1400px cap the window's extra width has to go somewhere,
   and it must not go into the cards — a 400px-wide product card on a 2300px monitor
   is worse than six 215px ones. The ladder therefore keeps climbing past 1440, so
   every extra ~300px of window buys another column and the card stays roughly the
   same size. Measured card widths: 215px at 1440, 218px at 1700, 226px at 2000,
   232px at 2300 — all inside the 200-280px band.

   Gap is 22px, which like the 20px gutter is not one of the --s tokens (4/8/12/16/
   24/32/48). It was specified as 22px and is written as 22px. */
@media (min-width: 640px) {
    body:not(.admin-body) #product-grid,
    body:not(.admin-body) #best-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 22px;
    }
}
@media (min-width: 900px) {
    body:not(.admin-body) #product-grid, body:not(.admin-body) #best-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
    body:not(.admin-body) #product-grid, body:not(.admin-body) #best-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
@media (min-width: 1440px) {
    body:not(.admin-body) #product-grid, body:not(.admin-body) #best-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (min-width: 1700px) {
    body:not(.admin-body) #product-grid, body:not(.admin-body) #best-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
}
@media (min-width: 2000px) {
    body:not(.admin-body) #product-grid, body:not(.admin-body) #best-grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}
@media (min-width: 2300px) {
    body:not(.admin-body) #product-grid, body:not(.admin-body) #best-grid { grid-template-columns: repeat(9, minmax(0, 1fr)); }
}

/* ── 5 · CART ───────────────────────────────────────────────────────────
   Delete / Save for later / Share were `flex: 1 1 0`, so on a wide page three
   pills stretched to 275px each and spanned the whole row like primary actions.
   They are secondary, so they sit at their own width, grouped at the left.

   The price was pushed to the far right by `margin-left:auto`, which at 900px+
   left it marooned across an empty gutter from the item it belongs to. It now
   follows the stepper. */
@media (min-width: 900px) {
    /* CATEGORIES BATCH B · THE CART ITEM ON A LAPTOP: a 120px photo with everything else beside it — the name, then
       one line per size (size · quantity · price), then Delete / Save for later / Share — in rows capped at 1100px,
       so no gap opens in the middle of a wide screen (the approved desktop-width prototype). It replaced R3's
       six-track row (64px photo, name, size, stepper, price and the three pills spread across the whole window).
       The markup is unchanged: .cp-head and .cp-lines are dissolved with display:contents and their children
       placed in this two-column grid. Below 900px none of this applies. */
    body:not(.admin-body) #cart-items { max-width: 1100px; }
    body:not(.admin-body) #cart-items .cart-product {
        display: grid;
        grid-template-columns: 120px minmax(0, 1fr);
        column-gap: 18px;
        row-gap: var(--s2);
        align-items: start;
        padding: var(--s4);
    }
    body:not(.admin-body) #cart-items .cp-head,
    body:not(.admin-body) #cart-items .cp-lines { display: contents; }
    body:not(.admin-body) #cart-items .cart-thumb {
        grid-column: 1; grid-row: 1 / span 3;   /* name, the first size line, the pills — every item has at least these */
        flex-basis: auto; width: 120px; height: 120px;
    }
    body:not(.admin-body) #cart-items .cp-name,
    body:not(.admin-body) #cart-items .cv-row,
    body:not(.admin-body) #cart-items .cv-cap,
    body:not(.admin-body) #cart-items .cp-actions { grid-column: 2; }
    /* The full stored name stays, slash and all, and may wrap. */
    body:not(.admin-body) #cart-items .cp-name {
        font-size: 17px; -webkit-line-clamp: 2; white-space: normal; overflow-wrap: anywhere;
    }
    body:not(.admin-body) #cart-items .cv-row {
        display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start;
        gap: 10px 18px; padding: 0; background: none; border: 0;
    }
    body:not(.admin-body) #cart-items .cv-weight { white-space: nowrap; overflow: visible; }
    body:not(.admin-body) #cart-items .cv-price { margin-left: 0; text-align: left; }
    /* The three pills at their own width, grouped at the left (they are secondary actions). */
    body:not(.admin-body) #cart-items .cp-actions {
        display: flex; flex-wrap: wrap; gap: var(--s2); padding: 0; justify-content: flex-start;
    }
    body:not(.admin-body) #cart-items .cp-act { flex: 0 0 auto; min-width: 132px; padding: 0 var(--s4); }
    /* The rule under the name divided a stacked card; beside a photo it would cut through the item. */
    body:not(.admin-body) #cart-items .cp-head { border-bottom: none; }

    /* R2 · PROCEED TO CHECKOUT.
       Round 1 pinned it and pushed it to the end of the bar, which put it in the
       bottom-right corner of the window, the one place on the page that lines up
       with nothing. A fixed bar also cannot be stopped from passing over the
       suggestion strip — that is what fixed means — so at desktop it stops being
       fixed. It sits in the flow at the shell's left edge, after the cart and
       before the suggestions, and can no longer cover anything.
       Below 900px it is untouched: still pinned, still full width. */
    body:not(.admin-body) .cart-actionbar {
        position: static;
        border-top: none;
        box-shadow: none;
        padding-top: var(--s5);
        padding-bottom: 0;
        /* The pinned bar carried its own 16px side padding because it spanned the
           window. In flow it is already inside the shell, so that padding would
           inset it 16px from every other row on the page. */
        padding-left: 0;
        padding-right: 0;
    }
    body:not(.admin-body) .cab-inner { justify-content: flex-start; }
    body:not(.admin-body) .cart-actionbar .btn-checkout {
        width: auto; min-width: 280px; margin: 0;
    }
    /* Both of these reserved space for a bar that is no longer floating. */
    body:not(.admin-body):has(.cart-actionbar:not([hidden])) .cart-page { padding-bottom: 0; }
    body:not(.admin-body) .cart-page { padding-bottom: 0; }

    /* R2 · THE EMPTY-CART ICON, found while screenshotting the empty state.
       It renders 1312x1312 at 1440px — a cart glyph taller than the window, with
       the "Your cart is empty" heading pushed 1531px down the page. .cart-empty-ico
       sets font-size:52px, which sized an emoji; the emoji was later replaced by an
       inline <svg> with a viewBox and no width or height, and an SVG with an
       intrinsic ratio and no size resolves to 100% of its container. Nothing capped
       it, so it grew with the container — 812px at 900px wide, 278px at 390px.

       NOT a regression from this pass: measured identical on the round-1 snapshot
       and before it. Fixed here at desktop widths only. It is just as wrong at
       390px, but correcting it there would change the mobile rendering this round
       is required to leave pixel-identical, so that one is reported, not touched. */
    body:not(.admin-body) .cart-empty-ico .cart-empty-svg,
    body:not(.admin-body) .cart-empty-ico > svg {
        width: calc(var(--s7) + var(--s4));      /* 64px */
        height: calc(var(--s7) + var(--s4));
        display: block;
        margin: 0 auto;
    }
}

/* ── 6 · FOOTER ─────────────────────────────────────────────────────────
   Measured before changing anything: SHOP / ACCOUNT / SUPPORT already share one
   top baseline at every width from 640px to 1440px (headingTops identical at
   1440/1280/1200/1024/960/900/768/640). They stagger only at <=600px, where the
   grid is deliberately 2-up and SUPPORT wraps to a second row — that is the
   mobile design and it stays. So there is no baseline rule here on purpose.
   What WAS wrong is the left edge: the grid started at 170px while the product
   grid started at 150px. The shell above fixes that, and this keeps the three
   columns equal rather than the 2fr/1fr/1fr that made SHOP twice as wide. */
@media (min-width: 640px) {
    body:not(.admin-body) .footer-links .footer-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: var(--s5);
        align-items: start;
    }
}

/* ── 7 · ACCOUNT CENTRE, DESKTOP ────────────────────────────────────────
   The two-column shape is kept: nav list left with the active item highlighted,
   section content right. What changes is the arrow. On a phone the arrow steps
   up to the All options menu, because that menu is the only way to reach the
   other sections. On a desktop that menu is already on screen as the left-hand
   nav, so an arrow pointing at it is a detour to a page the customer can already
   see — and it meant two different arrows across two screens. Desktop gets ONE
   arrow and it leaves the Account Centre for the shop. account.html sets the
   href; this sizes the layout it sits in.
   CATEGORIES BATCH B: the 260px menu and the 780px panel are ONE block, centred in the window
   (260 + 24 + 780 = 1064px — the approved desktop-width prototype), with the back arrow's row
   on the same edges, under the shop's gold header (.nav-acct, the end of this file). */
@media (min-width: 900px) {
    body:not(.admin-body) .settings-layout {
        max-width: 1064px;
        margin-left: auto;
        margin-right: auto;
        padding-left: 0;
        padding-right: 0;
        grid-template-columns: 260px minmax(0, 780px);
        gap: var(--s5);
    }
    body:not(.admin-body) #account-back.ao-shell { max-width: 1064px; margin-left: auto; margin-right: auto; }
}

/* ── The receipt download is a network request now ──────────────────────────
   The PDF is rendered by the server and fetched, so the button can be in flight.
   These two rules give it the SAME treatment the pay button already has on
   checkout (checkout.html:20-26) rather than inventing a second loading language:
   the identical 15px ring, the identical 0.7s spin, the identical 0.65 opacity.

   Scoped body:not(.admin-body) like every other rule added to this file — the ops
   console has no <style> block of its own and takes 100% of its appearance from
   here, so an unscoped selector can reach it. */
body:not(.admin-body) .rcpt-spinner {
    display: inline-block; width: 15px; height: 15px; margin-right: 8px; vertical-align: -2px;
    border: 2px solid rgba(255, 255, 255, 0.5); border-top-color: #fff; border-radius: 50%;
    animation: rcpt-spin 0.7s linear infinite;
}
body:not(.admin-body) [data-rcpt-pdf][disabled] { opacity: 0.65; cursor: progress; }
@keyframes rcpt-spin { to { transform: rotate(360deg); } }
/* A page that fills in after it loads: its footer (and the cart, until drawn) shows after 8 s should the page's script
   never run — the fallback for the rule "A PAGE THAT FILLS IN AFTER IT LOADS" further down. */
@keyframes ftk-show-late { to { visibility: visible; } }


/* ═══════════════════════════════════════════════════════════════════════════
   ADMIN HEADER — the ops console adopts the storefront's header look.
   EVERY selector here is scoped to `.admin-body`, so the storefront
   (body:not(.admin-body)) is untouched. Mirrors the storefront navbar's gold
   band, Lato type, responsive search row, and a tab strip below the band.
   Nothing here edits .nav-brand, the base body rule, or .auth-btn.
   ═══════════════════════════════════════════════════════════════════════════ */

/* STEP 5 — Lato across the whole panel (was Segoe UI; the search box was Arial).
   Normal elements inherit the family from .admin-body; form controls do not
   inherit by default, so they are named explicitly — this is what fixes Arial. */
.admin-body { font-family: var(--ftk-font); font-size: 15px; }
.admin-body input,
.admin-body select,
.admin-body textarea,
.admin-body button { font-family: inherit; }

/* STEP 4 — the gold brand band, full viewport width. Two stacked rows on a phone
   (brand, then a full-width search), collapsing to one row on desktop. */
.admin-body .admin-nav {
    background: var(--gold);
    color: var(--gold-ink);
    box-shadow: none;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: var(--s3) var(--s4);
}
.admin-body .admin-nav-row { display: flex; align-items: center; width: 100%; min-width: 0; }
.admin-body .admin-nav-row-main { justify-content: space-between; gap: 12px; }
.admin-body .admin-nav-row-search { width: 100%; }
.admin-body .admin-nav .nav-brand { color: var(--gold-ink); text-decoration: none; }
/* width:auto overrides a pre-existing @media(max-width:620px) rule that set this to
   100% back when the search shared this container; the search now has its own row. */
.admin-body .admin-nav-right { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; width: auto; }
.admin-body .admin-logout-btn {
    color: var(--gold-ink);
    border: 1px solid var(--gold-ink);
    background: transparent;
}
.admin-body .admin-logout-btn:hover { background: rgba(58, 46, 16, 0.08); color: var(--gold-ink); border-color: var(--gold-ink); }

/* STEP 2 — the logo image, same treatment as the storefront's. */
.admin-body .nav-logo-img {
    width: 40px; height: 40px;
    border-radius: 50%;
    object-fit: contain;
    display: block;
    flex: 0 0 auto;
}

/* STEP 3 — the wordmark: Lato 15 / 800 / gold-ink, achieved here (never on .nav-brand). */
.admin-body .nav-wordmark {
    font-family: var(--ftk-font);
    font-size: 15px;
    font-weight: 800;
    letter-spacing: 0.2px;
    color: var(--gold-ink);
}

/* STEP 7 — the Admin badge: dark ink on gold. Green is reserved for the Paid pill. */
.admin-body .admin-pill {
    background: var(--gold-ink);
    color: var(--gold);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 5px 10px;
    border-radius: 999px;
    margin-left: 4px;
}

/* STEP 6 — the search field, matching the storefront header search. */
.admin-body .global-search-wrap { position: relative; display: block; width: 100%; min-width: 0; margin: 0; }
.admin-body .global-search {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    padding: 11px 14px;
    font-size: 16px;
    border: 1.5px solid var(--ink-2);
    border-radius: 10px;
    background: #fff;
    color: var(--ink);
}
.admin-body .global-search:focus { outline: none; border-color: var(--orange-ink); background: #fff; }

/* STEP 8 — the tabs: a white strip below the band, orange active underline,
   horizontally scrollable and never wrapping. */
.admin-body .admin-tabstrip {
    background: #fff;
    border-bottom: 1px solid var(--divider);
    width: 100%;
    /* The row owns everything it draws: its own stacking context under the header, and nothing it paints —
       the active tab's orange underline included — can show outside its own box, so once the row has
       scrolled under the header no part of it stays visible. Scrolling and stickiness are unchanged. */
    position: relative;
    z-index: 0;
    contain: paint;
}
.admin-body .admin-tabstrip .admin-tabs {
    display: flex;
    flex: 0 1 auto;
    gap: 4px;
    flex-wrap: nowrap;
    overflow-x: auto;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 24px;
    -webkit-overflow-scrolling: touch;
}
.admin-body .admin-tabstrip .admin-tab {
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: 12px 14px;
    font-size: 14px;
    line-height: 20px;   /* fix round 5 (item 9): a whole-pixel strip (46 px) — with line-height: normal it was 46.3–46.4 px, and the sub-pixel remainder of the orange underline could paint as one device row just under the header while scrolling */
    font-weight: 700;
    color: var(--ink-2);
    white-space: nowrap;
}
.admin-body .admin-tabstrip .admin-tab:hover { background: transparent; color: var(--ink); }
.admin-body .admin-tabstrip .admin-tab.active {
    background: transparent;
    color: var(--ink);
    border-bottom-color: var(--orange-ink);
}

/* Desktop (≥800px — it was the storefront's 900px until marketplace batch 2's header fix): the band collapses to one
   row — brand, search filling the middle, who is signed in and the buttons on the right — and it NEVER wraps: always
   72px. The search box gives up its room first (flex-basis 0: it only ever takes what is left), down to 200px; then the
   name truncates (the batch 2 block below). Further steps, only when needed: ops-console-3dacfcbd19.js fitHeader. */
@media (min-width: 800px) {
    .admin-body .admin-nav {
        flex-direction: row;
        /* The old .admin-nav rule wraps; with the fixed height, a row that ran out of room dropped its right-hand group
           onto the tab row (the owner's three-role fault). This band never wraps. */
        flex-wrap: nowrap;
        align-items: center;
        gap: var(--s5);
        height: 72px;
        box-sizing: border-box;
    }
    .admin-body .admin-nav-row-main { display: contents; }
    .admin-body .admin-nav .nav-brand { order: 1; flex: 0 0 auto; }
    .admin-body .admin-nav-row-search { order: 2; flex: 1 1 0; width: auto; min-width: 200px; }
    .admin-body .admin-nav-right { order: 3; flex: 0 1 auto; min-width: 0; }   /* shrinks only once the search is at 200px */
}

/* ═══════════════════════════════════════════════════════════════════════════
   ADMIN CONTENT GOES FULL WIDTH — the 1200px cap is removed and the content sits
   in a 20px gutter, the same left edge as the (already full-bleed) nav and the
   tab strip, at every width. Scoped to .admin-body; the storefront is untouched.
   Horizontal padding only, so the existing vertical rhythm (incl. the mobile
   96px bottom that clears the floating launcher) is preserved.
   ═══════════════════════════════════════════════════════════════════════════ */
.admin-body .admin-main { max-width: none; padding-left: 20px; padding-right: 20px; }
.admin-body .admin-nav { padding-left: 20px; padding-right: 20px; }
/* THE TOP-BAR RESULTS PANEL ON PHONES (hygiene batch v6, Fix 4). Below 640px the panel spans the
   screen with a --s4 (16px) margin each side. It is positioned inside .global-search-wrap, which sits
   inside the nav's 20px gutter just above, so each side reaches out by (20px - --s4); if that gutter
   changes, change it here too. At 640px and up the desktop rule (340px, right-aligned) is untouched. */
@media (max-width: 639.98px) {
    .admin-body .global-results { left: calc(var(--s4) - 20px); right: calc(var(--s4) - 20px); width: auto; max-width: none; }
}
.admin-body .admin-tabstrip .admin-tabs { max-width: none; padding-left: 20px; padding-right: 20px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ADMIN ADOPTS THE STOREFRONT'S SIZES — the panel read "zoomed". Every value here
   is the storefront's own token or a STEP-2 measurement (no invented numbers).
   Scoped to .admin-body; storefront untouched. .nav-brand / base body / .auth-btn
   are not edited.
     • body line-height  1.5   (store body = 22.5px)
     • page title (h1)   24/700 line-height 1.25   (store --fs-title)
     • section head (h2)  18/700 line-height 1.25   (store --fs-head / measured 18)
     • micro label       11 + 0.04em                (store --fs-micro / measured .ls-label)
     • card radius       8px                          (store --r-card)
     • grid gaps         22px                         (store .product-grid gap)
     • form input        min-height 48, pad 0 12, radius 8, 1px divider (store input)
   ═══════════════════════════════════════════════════════════════════════════ */
.admin-body { line-height: var(--lh-body); }
.admin-body .admin-head h1 { font-size: var(--fs-title); font-weight: 700; line-height: var(--lh-head); }
.admin-body .admin-panel-head h2 { font-size: var(--fs-head); font-weight: 700; line-height: var(--lh-head); }
.admin-body .admin-stat-label { font-size: var(--fs-micro); letter-spacing: 0.04em; }
.admin-body .admin-stat-card,
.admin-body .admin-panel { border-radius: var(--r-card); }
.admin-body .analytics-grid,
.admin-body .admin-grid { gap: 22px; }
.admin-body .admin-input { min-height: var(--s7); padding: 0 var(--s3); border-radius: var(--r-card); border-color: var(--control-edge); }
/* Every console dropdown is a text box with an arrow: it takes the SAME height, border, radius, font size,
   padding and background as the single-line text box from the rules above (it carries .admin-input too), by
   definition rather than by a second set of numbers. Only the native look is reset — Safari otherwise draws
   its own 24px menu with a 5px radius and no padding, whatever the box says — and the arrow drawn here is the
   storefront address form's chevron (select.state-select). */
.admin-body select.admin-input {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 40px;                 /* room for the chevron */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23667' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat;
    background-position: right 14px center;
    cursor: pointer;
    text-overflow: ellipsis;
}
/* primary button font-size matches the storefront's primary button (.btn-add = 15px).
   Height is NOT forced to the storefront's 49px: .btn-add is a full-width card CTA
   while this is a compact toolbar button — a different role — so only the "reads
   larger" attribute (font-size) is matched. See report. */
.admin-body .btn-add-product { font-size: var(--fs-body); }

/* ── ADMIN SEARCH CONTROL matches the storefront's ──
   Field: 48 tall, 8 radius, 1px divider border — the storefront search values —
   with room on the right for the magnifier. The magnifier moves to the RIGHT and
   is built with the SAME box, icon size and colour as the storefront's
   .navbar .product-search-btn. It is DECORATIVE (aria-hidden, pointer-events:none,
   a <span> not a button) because the admin search has no submit path: it filters
   as you type and its input is not inside a form. */
.admin-body .global-search {
    min-height: var(--s7);
    padding: 0 40px 0 var(--s3);
    border: 1px solid var(--ink-2);
    border-radius: var(--r-card);
}
/* Focus: the --orange-ink edge and the inputs' orange glow, as every console field (final colour round). */
.admin-body .global-search:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
.admin-body .global-search-ico {
    position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
    width: 34px; height: 34px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--gold-ink);
    pointer-events: none;
}
.admin-body .global-search-ico svg { width: 19px; height: 19px; display: block; }

/* ═══════════════════════════════════════════════════════════════════════════
   ORDER DETAIL — async actions + payment/stock history, moved in from the
   deleted floating panel. EVERY selector is scoped to `.admin-body #order-modal`
   so the SHARED modal and auth-btn rules (used by checkout.html & account.html)
   are never touched. Reuses the design tokens; matches ftk-order-detail-approved.html.
   ═══════════════════════════════════════════════════════════════════════════ */
/* STEP 3 — the order modal gets a capped height and an internally scrolling body;
   head and foot stay fixed. Scoped to #order-modal only. */
.admin-body #order-modal .modal-card {
    max-width: 560px; max-height: 85vh; border-radius: var(--r-card);
    display: flex; flex-direction: column;
}
.admin-body #order-modal .modal-head,
.admin-body #order-modal .modal-foot { flex: 0 0 auto; }
.admin-body #order-modal .modal-body { flex: 1 1 auto; overflow-y: auto; min-height: 0; }

/* section headings (mock h3): first has no top rule */
.admin-body #order-modal .od-h3 {
    font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    color: var(--ink-2); margin: 0 0 10px; padding-top: 20px; border-top: 1px solid var(--divider);
}
.admin-body #order-modal .od-h3:first-of-type { padding-top: 0; border-top: 0; }
.admin-body #order-modal .od-cell-wide { grid-column: 1 / -1; }

/* STEP 4 — the two history lists: capped, internally scrolling */
.admin-body #order-modal .od-hist {
    max-height: 180px; overflow-y: auto;
    border: 1px solid var(--divider); border-radius: var(--r-card); margin-bottom: 20px;
}
.admin-body #order-modal .od-hrow {
    display: flex; gap: 12px; align-items: baseline;
    padding: 10px 12px; border-bottom: 1px solid #F1F0EC;
}
.admin-body #order-modal .od-hrow:last-child { border-bottom: 0; }
.admin-body #order-modal .od-htype {
    font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; min-width: 84px;
}
.admin-body #order-modal .od-hmain { font-size: 15px; }
.admin-body #order-modal .od-hmeta {
    font-size: 13px; color: var(--ink-2); margin-left: auto; text-align: right; white-space: nowrap;
}
/* The refund fix round, fix 4: on a phone (the window is narrower than its 560px) a history row — Payment history, Order
   history, Stock movements — wraps onto a second line rather than pushing its date out of sight; the date itself
   (.od-hwhen) never breaks. Wider screens are unchanged. */
.admin-body #order-modal .od-hwhen { white-space: nowrap; }
@media (max-width: 600px) {
    .admin-body #order-modal .od-hist { max-height: 260px; }   /* the refund fix round 3, fix 5: a taller list on a phone (rows wrap); 180px from 600px up */
    .admin-body #order-modal .od-hrow { flex-wrap: wrap; row-gap: 2px; }
    .admin-body #order-modal .od-hmain { min-width: 0; overflow-wrap: anywhere; }
    .admin-body #order-modal .od-hmeta { white-space: normal; max-width: 100%; }
}
.admin-body #order-modal .od-empty,
.admin-body #order-modal .od-loading { padding: 14px 12px; font-size: 15px; color: var(--ink-2); }
.admin-body #order-modal .od-note { font-size: 13px; color: var(--ink-2); margin: 10px 0 0; }

/* STEP 5/6 — action buttons (danger for Refund/Cancel, ghost for Release; never orange) */
.admin-body #order-modal .od-controls { display: flex; gap: 10px; flex-wrap: wrap; padding-top: 4px; }
.admin-body #order-modal .od-btn {
    font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
    height: 44px; padding: 0 18px; border-radius: var(--r-btn); border: 1px solid transparent;
}
.admin-body #order-modal .od-btn.primary { background: var(--orange); color: var(--ink); }
.admin-body #order-modal .od-btn.ghost { background: #fff; color: var(--ink); border-color: var(--control-edge); }
.admin-body #order-modal .od-btn.danger { background: #fff; color: var(--danger); border-color: var(--danger); }
.admin-body #order-modal .od-btn:disabled { opacity: .55; cursor: not-allowed; }

/* STEP 6 — the inline reason block (replaces the browser prompt) */
.admin-body #order-modal .od-reason {
    border: 1px solid var(--divider); border-radius: var(--r-card);
    padding: 16px; margin-top: 14px; background: var(--surface);
}
.admin-body #order-modal .od-reason p { margin: 0 0 10px; font-size: 15px; font-weight: 700; }
.admin-body #order-modal .od-reason input {
    font-family: inherit; font-size: 15px; width: 100%; height: 48px; padding: 0 12px;
    border-radius: var(--r-card); border: 1px solid var(--control-edge); background: #fff; margin-bottom: 12px;
}
.admin-body #order-modal .od-reason input:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224,123,31,.18); }
.admin-body #order-modal .od-reason-row { display: flex; gap: 10px; }

/* ═══════════════════════════════════════════════════════════════════════════
   NO EMOJI, NO GREEN — the admin adopts the approved stat-card / button mock
   (ftk-stat-cards-approved.html). Every rule is scoped to .admin-body so the
   storefront is untouched. Green is rule A's success / good-status colour (see
   --paid-green): Paid, Delivered, Active, In Stock, Saved, "No email problems".
     - Tiles:   44x44, radius 8, ONE neutral surface, gold-ink 22px line icons.
     - Buttons: primary = flat --orange; secondary/export/view/edit = white +
                --control-edge + ink; destructive = white + --danger + a --danger edge.
                No gradient on any admin button.
     - Accents: focus rings, active pills, links -> orange/ink, never green.
   Tile surface uses var(--surface) (#F7F7F5); the mock's literal is #F4F4F1 —
   a 3-4 unit difference — reused as a token per the brief. Tile/login icons are
   22px/26px per the MOCK (the brief said 20px; the mock wins, as instructed).
   ═══════════════════════════════════════════════════════════════════════════ */

/* -- STAT / INVENTORY TILES: one neutral tile, gold-ink drawn icon -- */
.admin-body .admin-stat-icon {
    width: 44px; height: 44px; border-radius: 8px;
    background: var(--surface); color: var(--gold-ink);
    display: grid; place-items: center;
    font-size: 0; flex-shrink: 0;
}
.admin-body .admin-stat-icon svg { width: 22px; height: 22px; display: block; }
.admin-body .admin-stat-label { color: var(--ink-2); letter-spacing: 0.05em; font-weight: 700; }

/* -- SIGN-IN MARK: the neutral 52x52 mark from the mock, drawn padlock -- */
.admin-body .admin-gate-icon {
    width: 52px; height: 52px; border-radius: 10px;
    background: var(--surface); color: var(--gold-ink);
    display: grid; place-items: center;
    margin: 0 auto 14px; font-size: 0;
}
/* The lock is drawn exactly as a 26×26 icon (the same scale and origin — viewBox 0 0 24 24, xMinYMin slice), but its
   BOX is 26×18 (+ 8px margin; the bottom of the lock draws into it). Why: WebKit paints a page's first frame as soon as
   its laid-out images and SVGs cover more than 32×32 px; this lock (26×26) and the passkey button's icon (20×20) together
   did, so WebKit painted before Lato was ready, the intro line wrapped in the fallback font, and the card shrank 21px a
   frame later (390px). Under that size, the first frame waits for Lato (preloaded, font-display: optional). */
.admin-body .admin-gate-icon svg { width: 26px; height: 18px; margin-bottom: 8px; overflow: visible; display: block; }

/* -- PRIMARY BUTTONS: flat orange, no gradient -- */
.admin-body .auth-btn.primary,
.admin-body .btn-add-product {
    background: var(--orange); color: var(--ink); border: 1px solid transparent;
}
.admin-body .auth-btn.primary:hover, .admin-body .btn-add-product:hover, .admin-body .auth-btn.primary:active, .admin-body .btn-add-product:active { background: var(--orange-dark); opacity: 1; color: #000; }

/* -- SECONDARY / GHOST BUTTONS: white, the control edge (--control-edge, 3.47:1), ink text -- */
.admin-body .auth-btn.secondary,
.admin-body .btn-export,
.admin-body .btn-view,
.admin-body .btn-edit {
    background: #fff; color: var(--ink); border: 1.5px solid var(--control-edge);
}
.admin-body .auth-btn.secondary:hover,
.admin-body .btn-export:hover,
.admin-body .btn-view:hover,
.admin-body .btn-edit:hover { background: var(--surface); opacity: 1; }

/* -- DESTRUCTIVE: white fill, danger text, light-red border (mock .btn.danger) -- */
.admin-body .btn-del { background: #fff; color: var(--danger); border: 1.5px solid var(--danger); }
/* Marketplace batch 4B, fix round 5 (item 7): a LINK styled as the export button is the button's twin — no underline, the
   button's line height and cursor, never wrapping (the seller site's "Orders CSV" / "Products CSV" are links; the console's
   "Preview homepage" is one too). And every CSV / download control, link or button, on both sites takes Refresh's box:
   32 px tall, a 1 px edge, the 6 px radius — the same row, the same height. */
.admin-body a.btn-export { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; line-height: normal; cursor: pointer; white-space: nowrap; box-sizing: border-box; }
.admin-body a.btn-export:hover, .admin-body a.btn-export:focus { text-decoration: none; }
.admin-body .btn-export[data-sc-csv], .admin-body .btn-export[data-act="exportProductsCSV"], .admin-body .btn-export[data-act="exportInventoryCSV"] { height: 32px; padding: 0 14px; border: 1px solid var(--control-edge); border-radius: 6px; font-size: 13px; font-weight: 600; }
.admin-body .btn-export[data-sc-csv]:hover, .admin-body .btn-export[data-act="exportProductsCSV"]:hover, .admin-body .btn-export[data-act="exportInventoryCSV"]:hover { border-color: var(--orange-ink); background: #fff; }

/* ── Marketplace batch 4B, fix round 5 (item 5): iPhone Safari zooms into any box whose text is under 16 px. At phone width every
   input, select and textarea on the console and the storefront is 16 px — these are the rules that undercut the general
   .admin-body 16 px rule (each outranks it by specificity): the review and email-problem note boxes, the modal fields, the
   order modal's reason and new-date boxes, the storefront's account box. The viewport tag is untouched (zoom stays allowed). */
@media (max-width: 640px) {
  .admin-body .rv-textarea, .admin-body .ep-note textarea, .admin-body .mn-field input, .admin-body .mn-textarea, .admin-body .sl-textarea,
  .admin-body #order-modal .od-reason input, .admin-body #order-modal .od-newdate input[type="date"], body:not(.admin-body) .acc-input,
  .admin-body input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), .admin-body select, .admin-body textarea,
  body:not(.admin-body) input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), body:not(.admin-body) select, body:not(.admin-body) textarea { font-size: 16px; }
}
/* ── fix round 6 (item 2), the sweep's finding: six of the selectors above are ALSO the selectors of base rules written FURTHER
   DOWN this file (.rv-textarea 14 px, .sl-textarea 15 px, .mn-field input / .mn-textarea 15 px, .ep-note textarea 14 px,
   #order-modal .od-newdate input[type="date"] 15 px). Equal specificity, later in the file: the base rules won, and at 390 px
   the review reply box measured 14 px, the sellers' decline reason and the problem report's reason 15 px (the other three
   were not reachable on the throwaway but lose the same way). The same six, one `body` heavier, so the 16 px floor holds.
   (.od-reason input's base rule is written BEFORE round 5's block, so round 5 already wins there.) Phones only. */
@media (max-width: 640px) {
  body.admin-body .rv-textarea, body.admin-body .ep-note textarea, body.admin-body .mn-field input, body.admin-body .mn-textarea, body.admin-body .sl-textarea,
  body.admin-body #order-modal .od-newdate input[type="date"] { font-size: 16px; }
}
/* ── fix round 6 (the sweep at 320): a pill inside a settings-row note — the seller Account's "New account <bank> ····1234 waiting
   for FTK" — wraps instead of pushing the page sideways on a 320 px phone (the pill's own rule is one line, nowrap). Both sites' rows. */
.admin-body .set-row-note .ftk-pill { white-space: normal; height: auto; min-height: 22px; padding: 3px 10px; line-height: 1.3; max-width: 100%; text-align: left; }
/* ── fix round 7 (item 4): the console Dashboard scrolled sideways on a 320 px phone (documentElement 340 > 320). The walk found
   ONE uncontained box: the Recent Activity row's time, span.activity-time (one line, nowrap) — pushed past the screen because the
   row is a flex line of icon (38 px) + message (flex: 1, so never narrower than its longest word) + time, and a message that holds
   an email address or an order number cannot break, so the time is what spills (right 340 at 320; at 360 it already ran 26 px
   into the card's padding, at 390 it fit with 0 px to spare). The Recent Orders table was NOT the cause: its header cells read
   past the viewport (th "Status" right 412) only inside the visually hidden thead (clip, overflow hidden), which adds nothing to
   the scroll width; the stacked cards stay inside .admin-table-wrap. Phones only (620 is the console's own phone band, the one
   that drops .admin-main's padding to 12 px: a longer staff name in "Name · 2h ago" tips a 412 / 430 px phone the same way, and
   the rules change nothing where the row already fits): the message may break anywhere and shrink, the time may wrap within
   two fifths of the row, its lines flush right. Nothing above 620 px; the storefront has neither class.
   The same walk, inside the Recent Orders panel: a stacked card's STATUS pill (.ftk-pill, min-width 124 px, nowrap) crossed the
   card's edge by 4 px at 320 (right 277.8, card 274) — the card's label column is a fixed two fifths (flex: 0 0 40%) and the value
   column it leaves is 107 px there. In a pill's row only (td:has(.ftk-pill) — :has() is already relied on above for the stat
   cards), the label column may give way (flex-shrink: 1) and its one word stays whole (overflow-wrap: normal — the card's own
   "anywhere" would otherwise let STATUS break into letters): it moves only when the row would otherwise overflow, so the pill
   stays inside the card; above 320 the row already fits and nothing moves. A text row's label is untouched. */
@media (max-width: 620px) {
  .admin-body .activity-msg { min-width: 0; overflow-wrap: anywhere; }
  .admin-body .activity-time { white-space: normal; max-width: 40%; text-align: right; }
  .admin-body .admin-table td:has(.ftk-pill)::before { flex-shrink: 1; overflow-wrap: normal; }
}
/* ── end fix round 7 (item 4) ── */
/* ── Marketplace batch 4B, fix round 6 (item 5): the one-line note directly under the header band on both sites (the console's
   #nav-notify-note, the seller site's #sc-notify-note) — why Notifications cannot turn on: this browser has blocked the site, or
   the address is a plain http://. The console's amber (mn-amber: #FFF4DB / --amber-ink), 14 px, full width, 8 px above and
   below, the band's 20 px gutter each side; hidden until the switch's click writes it, cleared when it turns on. */
.admin-body .admin-nav-note { margin: 0; padding: 8px 20px; width: 100%; box-sizing: border-box; background: #FFF4DB; color: var(--amber-ink); font-size: 14px; font-weight: 700; line-height: 1.45; }
.admin-body .admin-nav-note[hidden] { display: none; }
.admin-body .btn-del:hover { background: #fff5f4; }

/* -- STOCK +/- controls: neutral (the minus keeps its red) -- */
.admin-body .stk-btn { background: var(--surface); border: 1.5px solid var(--control-edge); color: var(--ink); }
.admin-body .stk-btn:hover { background: #eeeeec; }
.admin-body .stk-btn.minus { background: #fdf6f5; border-color: var(--danger); color: var(--danger); }
.admin-body .stk-btn.minus:hover { background: #fbeae8; }

/* -- FILTER PILLS: active/hover orange, never green -- */
.admin-body .filter-pill:hover { border-color: var(--orange-ink); color: var(--orange-ink); }
.admin-body .filter-pill.active { background: var(--orange); border-color: var(--orange); color: var(--ink); }
.admin-body .filter-pill.active:hover, .admin-body .filter-pill.active:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }   /* follow-up 4 */

/* -- VIEW TOGGLE: active is neutral (white chip, ink text) -- */
.admin-body .view-btn.active { color: var(--orange-ink); background: #fff; border-color: var(--orange-ink); }   /* the selected view: the orange system's edge (final colour round) */

/* -- FOCUS RINGS: orange, matching the mock inputs -- */
.admin-body .admin-input:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224,123,31,.18); }
.admin-body ::placeholder { color: var(--ink-2); opacity: 1; }   /* placeholder text: 5.33:1 (the browsers' own grey is 2.35:1) — final colour round */

/* -- LINKS (orange) and the console's general figures (neutral) -- */
.admin-body .order-link { color: var(--orange-ink); }
.admin-body .pm-total-stock strong { color: var(--ink); }
.admin-body .admin-gate-back:hover { color: var(--orange-ink); }

/* -- the In Stock badge: a good status, rule A's green -- */
.admin-body .stock-badge.stk-in { background: var(--paid-green-bg); color: var(--paid-green); }

/* -- ACTIVITY FEED icons + row layout --
   SVG icons draw at 20px in the neutral disc. Legacy entries whose stored icon
   is a text glyph (an emoji, or the "•" fallback) have no <svg>: hide that glyph
   WITHOUT zero-sizing it (the old font-size:0 zeroed any text icon to 0x0).
   visibility hides the glyph reliably — colour emoji included, which
   color:transparent does not — and a ::before repaints the disc that visibility
   would otherwise blank. SVG tiles are left untouched, so no stacking games. -- */
.admin-body .activity-icon { color: var(--gold-ink); }
.admin-body .activity-icon svg { width: 20px; height: 20px; display: block; }
.admin-body .activity-icon:not(:has(svg)) { position: relative; visibility: hidden; }
.admin-body .activity-icon:not(:has(svg))::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: #f3f5f3; visibility: visible; }
/* The timestamp sat ~1000px from the message because .activity-msg{flex:1} ate
   all the row's slack and .activity-time is pinned after it. Let the message keep
   its content width so the time sits right after it; no panel/row max-width
   (admin runs full width). */
.admin-body .activity-msg { flex: 0 1 auto; }

/* -- ADMIN PRODUCT CARDS adopt the storefront's sizing (display only) --
   The audit found admin cards larger than the shop's: .admin-products-grid used a
   240px column minimum (vs the shop's 210px, style.css:356) and .admin-product-card
   a 16px radius (vs the shop's computed 8px = var(--r-card), set at :5342). Two
   scoped overrides bring them into line; the shop's <=600px two-column rule is NOT
   copied — the admin card carries five row controls and stays one-up on the phone
   by design (owner decision). Gap is left at the admin's own 20px. */
.admin-body .admin-products-grid { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.admin-body .admin-product-card { border-radius: var(--r-card); }

/* -- DASHBOARD "Top selling product" containment (this ONE stat value only) --
   The name is already shortened at the first "/" (via API.gridName), but a long
   no-slash name must still never spill past the card. Scoped to #stat-top-product
   so the shared .admin-stat-value rule (numbers on the other tiles) is untouched:
   override its nowrap, clamp to at most 2 lines with an ellipsis, and let the
   value shrink inside its flex column. font-size stays 18px (from .sm). The
   parent stat-card column also needs min-width:0 (flex items default to
   min-width:auto and would refuse to shrink), scoped via :has() to only this card. */
.admin-body #stat-top-product {
    min-width: 0;
    white-space: normal;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}
.admin-body .admin-stat-card:has(#stat-top-product) > div { min-width: 0; }

/* -- PRODUCT-MODAL / CARD buttons: neutral, never green -- */
.admin-body .pm-variant-add { border: 1px dashed var(--control-edge); background: #fff; color: var(--orange-ink); }
.admin-body .pm-variant-add:hover { background: var(--surface); }
.admin-body .btn-restore { background: #fff; border: 1px solid var(--control-edge); color: var(--ink); }
.admin-body .btn-restore:hover { background: var(--surface); }

/* -- Admin modal backdrop: neutral scrim (was a faint green-black); .modal-overlay
      is shared with the checkout receipt modal, so this is scoped to .admin-body. -- */
.admin-body .modal-overlay { background: rgba(26,26,26,0.55); }

/* ============================================================================
   CSP STYLE PASS — BATCH 1: auth-page inline styles moved out of
   forgot-password.html, reset-password.html and verify-email.html.
   forgot and reset both defined .abox / .abox p / .abox input / .abtn with
   DIFFERENT values, so each page's rules are keyed to a page-specific body class
   (ftk-auth-forgot / ftk-auth-reset / ftk-auth-verify). The key is wrapped in
   :where() so it adds ZERO specificity — every selector therefore keeps the exact
   specificity it had inline, and the cascade result is byte-for-byte the same as
   before (notably: h1/p font-size still defer to body:not(.admin-body), which is
   what these cards actually rendered with). Declarations are byte-identical to the
   former inline <style> blocks. Nothing above this line changed.
   ============================================================================ */

/* shared auth-page background (was body style="background:#f6fbf7" on all three) */
body.ftk-auth-forgot, body.ftk-auth-reset, body.ftk-auth-verify { background: #f6fbf7; }

/* --- forgot-password.html (former inline <style>) --- */
:where(body.ftk-auth-forgot) .abox { max-width: 420px; margin: 9vh auto; background: #fff; border-radius: 16px; box-shadow: 0 12px 40px rgba(0,0,0,.1); padding: 32px 28px; font-family: var(--ftk-font); }
:where(body.ftk-auth-forgot) .abox h1 { font-size: 21px; margin: 0 0 6px; color: #1a1a1a; }
:where(body.ftk-auth-forgot) .abox p { color: #6a6a6a; font-size: 14px; margin: 0 0 16px; }
:where(body.ftk-auth-forgot) .abox input { width: 100%; box-sizing: border-box; padding: 11px 12px; border: 1.5px solid var(--control-edge); border-radius: 8px; font-size: 16px; margin-bottom: 12px; }
:where(body.ftk-auth-forgot) .abtn { width: 100%; background: linear-gradient(135deg,#E07B1F,#E07B1F); color: var(--ink); border: none; padding: 12px; border-radius: 9px; font-weight: 700; font-size: 15px; cursor: pointer; }
:where(body.ftk-auth-forgot) .amuted { font-size: 13px; color: var(--ink-2); margin-top: 12px; }
:where(body.ftk-auth-forgot) .alink { color: var(--orange-ink); font-weight: 700; text-decoration: none; }

/* --- reset-password.html (former inline <style>) --- */
:where(body.ftk-auth-reset) .abox { max-width: 440px; margin: 8vh auto; background: #fff; border-radius: 16px; box-shadow: 0 12px 40px rgba(0,0,0,.1); padding: 32px 28px; font-family: var(--ftk-font); }
:where(body.ftk-auth-reset) .abox h1 { font-size: 21px; margin: 0 0 6px; color: #1a1a1a; }
:where(body.ftk-auth-reset) .abox p { color: #6a6a6a; font-size: 14px; margin: 0 0 14px; }
:where(body.ftk-auth-reset) .abox label { display: block; font-size: 12px; font-weight: 700; color: #666; margin: 8px 0 4px; }
/* Batch 2 fix 3: the reset-page labels carry .authf-label to match the Sign in labels.
   This scoped rule (0,2,1) beats the .abox label rule above (0,1,1) for the three
   .authf-label VALUES (13px / 0.3px / muted); the block display + 8/0/4 margin above are
   kept for spacing. Customer-only scope (body.ftk-auth-reset); not used by admin. */
body.ftk-auth-reset .authf-label { font-size: 13px; letter-spacing: 0.3px; color: var(--ink-2); }
:where(body.ftk-auth-reset) .abox input { width: 100%; box-sizing: border-box; padding: 11px 12px; border: 1.5px solid var(--control-edge); border-radius: 8px; font-size: 16px; }
:where(body.ftk-auth-reset) .abtn { width: 100%; background: linear-gradient(135deg,#E07B1F,#E07B1F); color: var(--ink); border: none; padding: 12px; border-radius: 9px; font-weight: 700; font-size: 15px; cursor: pointer; margin-top: 14px; }
:where(body.ftk-auth-reset) .amuted { font-size: 13px; color: var(--ink-2); margin-top: 12px; }
:where(body.ftk-auth-reset) .alink { color: var(--orange-ink); font-weight: 700; text-decoration: none; }
/* reset code-fields initial hidden state (was style="display:none"); reset-password.js
   reveals it with el.style.display="block", which overrides this stylesheet rule. */
:where(body.ftk-auth-reset) #rp-code-fields { display: none; }

/* --- verify-email.html (former inline <style>) --- */
:where(body.ftk-auth-verify) .vbox { position: relative; max-width: 460px; margin: 8vh auto; background: #fff; border-radius: 16px; box-shadow: 0 12px 40px rgba(0,0,0,.1); padding: 36px 30px; text-align: center; font-family: var(--ftk-font); }
/* Small corner back affordance — replaces the old full-width mid-card button. */
:where(body.ftk-auth-verify) .vback { position: absolute; top: 12px; left: 14px; width: 34px; height: 34px; line-height: 32px; border-radius: 50%; color: var(--orange-ink); font-size: 19px; text-decoration: none; }
:where(body.ftk-auth-verify) .vback:hover { background: #F7F7F5; }
:where(body.ftk-auth-verify) .vbox .vico { font-size: 52px; margin-bottom: 8px; }
:where(body.ftk-auth-verify) .vbox h1 { font-size: 22px; margin: 6px 0 10px; color: #1a1a1a; }
:where(body.ftk-auth-verify) .vbox p { color: #6a6a6a; font-size: 14.5px; line-height: 1.55; margin: 0 0 18px; }
:where(body.ftk-auth-verify) .vbox .ok { color: var(--orange-ink); } :where(body.ftk-auth-verify) .vbox .warn { color: var(--amber-ink); } :where(body.ftk-auth-verify) .vbox .bad { color: #c0392b; }
:where(body.ftk-auth-verify) .vbox .neutral { color: #1a1a1a; }
:where(body.ftk-auth-verify) .vbtn { display: inline-block; background: linear-gradient(135deg,#E07B1F,#E07B1F); color: var(--ink); border: none; padding: 12px 24px; border-radius: 9px; font-weight: 700; font-size: 14px; cursor: pointer; text-decoration: none; }
:where(body.ftk-auth-verify) .vbtn.secondary { background: #F7F7F5; color: var(--orange-ink); border: 1px solid #C0670F; }
:where(body.ftk-auth-verify) .vcode { margin-top: 22px; border-top: 1px solid #eee; padding-top: 18px; }
:where(body.ftk-auth-verify) .vcode input { width: 100%; box-sizing: border-box; padding: 11px 12px; border: 1.5px solid var(--control-edge); border-radius: 8px; font-size: 16px; margin-bottom: 10px; }
:where(body.ftk-auth-verify) .vlink { background: none; border: none; padding: 0; color: var(--orange-ink); font-weight: 700; font-size: 13px; cursor: pointer; text-decoration: underline; }
:where(body.ftk-auth-verify) .vlink:disabled { color: #9aa1aa; cursor: default; text-decoration: none; }
:where(body.ftk-auth-verify) .vresend { margin: 12px 0 0; }
:where(body.ftk-auth-verify) .vhide { display: none; }
/* "Verify your email" (verify-email.html): "Do this later" under the button — back to the page they came from. */
:where(body.ftk-auth-verify) .vlater { display: inline-block; margin: 14px 0 0; }
/* "PROTECT YOUR ACCOUNT" (protect-account.html) — shown once, right after the email is verified. The code page's
   own card (.vbox); sizes, colours and fonts are the site's tokens. Rules that must beat the site-wide card and
   button rules (body:not(.admin-body) …) are written with body.ftk-protect. */
:where(body.ftk-protect) .pa-screen[hidden], :where(body.ftk-protect) .pa-tfa-view[hidden],
:where(body.ftk-protect) .pa-ticks[hidden], :where(body.ftk-protect) .pa-nodevice[hidden],
:where(body.ftk-protect) .pa-pw[hidden] { display: none; }
/* Drawn in the first frame: protect-account.js (in <head>) marks <html> — "pa-on" when the hand-off is there (without
   it nothing is drawn and the page goes on), "pa-nodev" for the "No passkey device" journey: no passkey button and no
   ticked lines, the line about two-step, and two-step as the orange button without its "instead" (.pk-btn-primary). */
html:not(.pa-on) body.ftk-protect .pa-screen,
html:not(.pa-nodev) body.ftk-protect .pa-nodevice,
html.pa-nodev body.ftk-protect .pa-ticks,
html.pa-nodev body.ftk-protect #pa-passkey,
html.pa-nodev body.ftk-protect .pa-instead { display: none; }
:where(body.ftk-protect) .pa-shield { width: 64px; height: 64px; margin: 0 auto var(--s3); border-radius: 50%; display: grid; place-items: center; background: #FBEFE4; color: var(--orange-dark); }
:where(body.ftk-protect) .vbox .pa-lead { margin: 0 0 var(--s4); }
/* the no-passkey device: one small, muted line about two-step above its orange button */
:where(body.ftk-protect) .vbox .pa-nodevice { margin: 0 0 var(--s4); font-size: var(--fs-meta); color: var(--ink-2); }
:where(body.ftk-protect) .pa-ticks { list-style: none; margin: 0 0 var(--s5); padding: 0; text-align: left; display: grid; gap: var(--s3); }
:where(body.ftk-protect) .pa-ticks li { display: flex; align-items: flex-start; gap: var(--s2); font-size: var(--fs-body); line-height: var(--lh-body); color: var(--ink); }
:where(body.ftk-protect) .pa-ticks svg { flex: none; margin-top: 1px; color: var(--paid-green); }
:where(body.ftk-protect) .pa-actions { display: grid; gap: var(--s2); }
body.ftk-protect .pa-box .pa-btn { width: 100%; min-height: 48px; display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); }
body.ftk-protect .pa-box .pa-btn[hidden] { display: none; }
:where(body.ftk-protect) .pa-btn-ic { display: inline-flex; }
:where(body.ftk-protect) .pa-pw { display: grid; gap: var(--s2); margin: 0 0 var(--s3); text-align: left; }
:where(body.ftk-protect) .vbox .pa-msg { margin: var(--s2) 0 0; font-size: var(--fs-meta); color: #c0392b; }   /* as .pk-offer-msg */
:where(body.ftk-protect) .vbox .pa-msg:empty { margin: 0; }
:where(body.ftk-protect) .pa-skip { display: inline-block; margin: var(--s4) 0 0; color: var(--orange-ink); font-weight: 700; font-size: 14px; text-decoration: underline; }
:where(body.ftk-protect) .vbox .pa-foot { margin: var(--s3) 0 0; font-size: var(--fs-meta); color: var(--ink-2); }
/* the two-step card inside the screen — no card chrome and no header, like the account page's in-row look */
:where(body.ftk-protect) .pa-tfa-view { text-align: left; }
body.ftk-protect .pa-tfa .acc-card { background: transparent; border: 0; box-shadow: none; margin: 0; padding: 0; max-width: none; }
body.ftk-protect .pa-tfa .acc-card:hover { box-shadow: none; }
body.ftk-protect .pa-tfa .acc-head { display: none; }
body.ftk-protect .pa-tfa .acc-body { max-height: none; opacity: 1; overflow: visible; }
body.ftk-protect .pa-tfa .acc-body-inner { padding: 0; }

/* ============================================================================
   CSP STYLE PASS — BATCH 2: checkout.html's inline <style> block moved here
   verbatim. Selectors are unique to checkout (.checkout-status, #pay-btn,
   .ck-spinner) and are NOT renamed or scoped, so each keeps the exact specificity
   it had inline; appended at the end, they stay last among equal-specificity
   rules, so the cascade outcome is unchanged (no :where() needed here — the
   duplicate-name problem that forced :where() in batch 1 does not exist here).
   .ck-spinner and its @keyframes ck-spin move together in this same section.
   Nothing above this line changed.
   ============================================================================ */

        .checkout-status { margin: 10px 0 0; font-size: 13.5px; line-height: 1.5; color: #5b6b60; text-align: center; }
        .checkout-status.error { color: #c0392b; font-weight: 600; }
        #pay-btn[disabled] { opacity: 0.65; cursor: progress; }
        .ck-spinner {
            display: inline-block; width: 15px; height: 15px; margin-right: 8px; vertical-align: -2px;
            border: 2px solid rgba(255,255,255,0.5); border-top-color: #fff; border-radius: 50%;
            animation: ck-spin 0.7s linear infinite;
        }
        @keyframes ck-spin { to { transform: rotate(360deg); } }

/* ============================================================================
   CSP STYLE PASS — BATCH 3a: blocked style="" attributes written by JS moved to
   classes/ids here (idle-logout, account-sessions, index banner, account email
   banner, change-password, account addresses error, phone-verify, out-of-stock).
   The assistant (its injected <style> + 3 .ftk-status badges) is deferred to a
   separate batch 3b. CSSOM (element.style.x=...) writes are untouched.
   Specificity, per rule:
   - id'd elements keyed by #id (1,0,0) to beat body:not(.admin-body) element rules
     that set font-size/line-height (style.css ~5161).
   - elements whose font-size/color would otherwise be overridden and that have NO
     id use a body:not(.admin-body) .class compound (0,1,2) appended last (wins the
     tie by source order): .ftk-sess-rev, .ftk-cp-forgot, .ftk-addr-error.
   - out-of-stock uses body:not(.admin-body) .btn-add.ftk-oos (0,3,1) to beat the
     body:not(.admin-body) .btn-add:disabled{opacity:1} rule (~5513) that the original
     inline opacity:.5 used to win against.
   - everything else is a plain class (no competing rule).
   ============================================================================ */
/* idle-logout.js idle modal */
.ftk-idle-card { background:#fff;border-radius:16px;max-width:400px;width:100%;padding:26px 22px;box-shadow:0 18px 50px rgba(0,0,0,.28);text-align:center; }
.ftk-idle-ico { line-height:0;margin-bottom:10px;color:#E07B1F; }
#ftk-idle-title { margin:0 0 18px;font-size:19px;line-height:1.35;color:#1a1a1a; }
#ftk-idle-stay { width:100%;background:linear-gradient(135deg,#E07B1F,#E07B1F);color:var(--ink);border:none;padding:15px 20px;border-radius:11px;font-weight:700;font-size:16px;cursor:pointer;min-height:48px; }
#ftk-idle-now { width:100%;background:none;border:none;margin-top:10px;color:var(--ink-2);font-size:14px;cursor:pointer;min-height:44px;text-decoration:underline; }
/* account-sessions.js — the OLD Devices markup (#sess-list font, #sess-all, .ftk-sess-badge/rev/row)
   was replaced by the Part G device-card design; those rules are gone. The new .sess-* rules live in
   the "LOGIN & SECURITY FINISH" block at the end of this file. */
/* verify-banner.js — the "verify your email" banner (index.html + account.html; var(--orange)==#E07B1F) */
.ftk-verify-link { color:var(--orange-ink);font-weight:700; }
/* account-change-password.js */
body:not(.admin-body) .ftk-cp-forgot { margin:10px 0 0;font-size:12.5px; }
.ftk-cp-forgot-link { color:var(--orange-ink);font-weight:700; }
/* account.js addresses-load error */
body:not(.admin-body) .ftk-addr-error { color:#c0392b; }
/* account-phone-verify.js */
#pv-send { margin-bottom:10px; }
/* script.js out-of-stock / unavailable product buttons */
body:not(.admin-body) .btn-add.ftk-oos { opacity:.5;cursor:not-allowed; }

/* ============================================================================
   CSP STYLE PASS — BATCH 3b: the assistant panel stylesheet, formerly injected as
   a runtime <style id="ftk-assistant-style"> element by assistant.js, moved here
   verbatim (the injection is removed). The 3 .ftk-status badges that set colours
   with inline style="" become a status-class family (below). Rules are unchanged
   and NOT scoped: no .ftk-* selector exists elsewhere in style.css, and the rules
   sit last so they keep the same cascade position the injected <style> had (which
   loaded after style.css). @keyframes ftkb travels with .ftk-typing that uses it.
   ============================================================================ */
.ftk-panel{position:fixed;right:20px;bottom:20px;z-index:99999;width:370px;max-width:calc(100vw - 32px);height:560px;max-height:calc(100vh - 40px);background:#fff;border-radius:18px;overflow:hidden;box-shadow:0 24px 60px rgba(0,0,0,.26);display:none;flex-direction:column;transform:translateY(18px) scale(.98);opacity:0;transition:transform .2s ease,opacity .2s ease;font-family:inherit;}
.ftk-panel.open{display:flex;transform:none;opacity:1;}
.ftk-head{background:linear-gradient(135deg,#E07B1F,#E07B1F);color:var(--ink);padding:16px 18px;display:flex;align-items:center;gap:11px;}
.ftk-head .ftk-h-ava{width:38px;height:38px;border-radius:50%;background:rgba(255,255,255,.18);display:flex;align-items:center;justify-content:center;font-size:19px;}
.ftk-head .ftk-h-tt{font-size:15.5px;font-weight:800;line-height:1.2;}
.ftk-head .ftk-h-sub{font-size:12px;opacity:.9;display:flex;align-items:center;gap:5px;}
.ftk-head .ftk-close{margin-left:auto;background:rgba(255,255,255,.16);border:1px solid var(--ink);color:var(--ink);width:30px;height:30px;border-radius:50%;cursor:pointer;font-size:16px;line-height:1;}
.ftk-head .ftk-close:hover{background:rgba(255,255,255,.3);}
.ftk-body{flex:1;overflow-y:auto;padding:16px;background:#f6f8f6;}
.ftk-row{display:flex;margin-bottom:12px;}
.ftk-row.user{justify-content:flex-end;}
.ftk-bub{max-width:84%;padding:11px 14px;border-radius:14px;font-size:13.7px;line-height:1.5;box-shadow:0 1px 2px rgba(0,0,0,.05);white-space:pre-wrap;word-wrap:break-word;}
.ftk-row.bot .ftk-bub{background:#fff;color:#2b2f33;border-bottom-left-radius:5px;}
.ftk-row.user .ftk-bub{background:#E07B1F;color:var(--ink);border-bottom-right-radius:5px;}
.ftk-bub strong{font-weight:700;}
.ftk-bub .ftk-note{display:inline-block;margin-top:4px;font-size:12.5px;line-height:1.45;color:var(--ink-2);}   /* batch 6 fix 4: the refund line — the site's secondary ink */
.ftk-bub a{color:var(--orange-ink);font-weight:600;}
.ftk-row.user .ftk-bub a{color:var(--ink);}
.ftk-status{display:inline-block;margin-top:3px;padding:2px 9px;border-radius:20px;font-size:11.5px;font-weight:700;}
.ftk-qa{padding:12px 14px 16px;border-top:1px solid #eef0ee;background:#fff;}
.ftk-qa-tt{font-size:11px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;color:var(--ink-2);margin:0 2px 9px;}
.ftk-qa-grid{display:flex;flex-wrap:wrap;gap:8px;}
.ftk-chip{flex:1 1 auto;display:inline-flex;align-items:center;gap:6px;padding:9px 13px;border:1px solid var(--control-edge);background:#F7F7F5;color:var(--orange-ink);border-radius:22px;font-size:12.8px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,transform .12s;font-family:inherit;white-space:nowrap;}
.ftk-chip:hover{background:#F7F7F5;border-color:var(--orange-ink);transform:translateY(-1px);}
.ftk-typing{display:inline-flex;gap:4px;padding:13px 15px;}
.ftk-typing span{width:7px;height:7px;border-radius:50%;background:#bcc3c9;animation:ftkb 1s infinite;}
.ftk-typing span:nth-child(2){animation-delay:.15s;}.ftk-typing span:nth-child(3){animation-delay:.3s;}
@keyframes ftkb{0%,60%,100%{opacity:.3;transform:translateY(0);}30%{opacity:1;transform:translateY(-3px);}}
/* .ftk-status badge colours (were inline style="background;color") — one class per
   order status (assistant.js statusChip map), plus in-stock / out-of-stock. */
.ftk-status--pending{background:#fff4e0;color:var(--amber-ink);}
.ftk-status--processing{background:var(--orange-tint);color:var(--orange-ink);}   /* fix round 3: orange, not blue */
.ftk-status--paid{background:#e8f5ec;color:#1f7a3f;}
.ftk-status--shipped{background:#FFF4DB;color:var(--amber-ink);}   /* fix round 3: amber, not blue */
.ftk-status--delivered{background:#e8f5ec;color:#1f7a3f;}
.ftk-status--cancelled{background:#fdecea;color:#c0392b;}
.ftk-status--default{background:#eef0ee;color:#555;}
.ftk-status--instock{background:#F7F7F5;color:var(--orange-ink);}
.ftk-status--oos{background:#fdecea;color:#c0392b;}

/* ============================================================================
   CSP STYLE PASS — BATCH 4: account.html's inline <style> block (moved verbatim
   below) and its 23 static style="" attributes (converted to #id rules / classes).
   The cache-inlining rationale is obsolete (style.css is max-age=0, must-revalidate).
   Verbatim block, unscoped: it sits last, keeping the same cascade position the
   inline <style> had (which loaded after style.css). #auth-create{display:none} is
   its initial hidden state; showCreate now sets display:'block' explicitly.
   ============================================================================ */

/* ---- account.html former inline <style> block (verbatim) ---- */
        .settings-layout {
            display: grid;
            grid-template-columns: 260px 1fr;   /* permanent left sidebar + wide content panel */
            gap: 28px;
            max-width: 1320px;
            margin: 28px auto;
            padding: 0 24px;
            align-items: start;
        }
        .settings-sidebar {
            width: 260px;
            background: #fff;
            border-radius: 18px;
            box-shadow: 0 6px 26px rgba(0,0,0,0.06);
            padding: 22px;
            position: sticky;
            top: 22px;
            display: flex;
            flex-direction: column;
        }
        /* Profile card above the navigation */
        /* .sb-profile / .sb-avatar are NOT styled here.
           They were, and that is why the same drawer rendered orange over the
           storefront and GREEN over this page: account.html's inline <style> loads
           AFTER style.css, and `.sb-profile .sb-avatar` matched at the identical
           specificity (0,2,0) as `.nav-drawer-body .sb-avatar`, so on this page the
           later copy won. One component, one stylesheet — style.css owns it. */
        /* Member since — a line of text under the name and email, not a card. */

        .settings-sidebar nav { display: flex; flex-direction: column; gap: 2px; }   /* VERTICAL only */
        /* Icons are inline SVG at currentColor, so they follow hover/active states
           without a second colour rule — and client/ keeps zero dependencies. */
        /* Logout pinned to the very bottom, divided, as a danger action */

        .settings-content { min-width: 0; width: 100%; }
        .settings-panel { display: none; }
        .settings-panel.active { display: block; }

        /* ===== Account Center premium design system ===== */
        .acc-card { max-width: 640px; margin: 0 auto 16px; background: #fff; border: 1px solid var(--divider);
            border-radius: 12px; box-shadow: 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06);
            overflow: hidden; transition: box-shadow .18s ease, border-color .18s ease; }
        .acc-card:hover { box-shadow: 0 2px 6px rgba(16,24,20,.05), 0 14px 32px rgba(16,24,20,.09); border-color: #dde7e0; }
        .acc-head { display: flex; align-items: center; gap: 14px; width: 100%; padding: 17px 20px;
            background: none; border: 0; cursor: pointer; text-align: left; font: inherit; color: inherit; }
        .acc-head:hover { background: #fff; }
        .acc-head:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: -2px; border-radius: 12px; }
        .acc-ic { flex: 0 0 38px; width: 38px; height: 38px; border-radius: 10px; display: grid;
            place-items: center; background: var(--surface); color: var(--orange); }
        .acc-ic svg { width: 19px; height: 19px; }
        .acc-titles { flex: 1 1 auto; min-width: 0; }
        .acc-title { display: block; margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); letter-spacing: -.1px; line-height: 1.25; }
        .acc-sub { display: block; margin: 2px 0 0; font-size: 13px; color: var(--ink-2); line-height: 1.45; }
        .acc-chev { flex: 0 0 auto; color: var(--ink-2); font-size: 14px; transition: transform .22s ease; }
        .acc-head[aria-expanded="true"] .acc-chev { transform: rotate(90deg); }
        .acc-body { max-height: 0; opacity: 0; overflow: hidden; transition: max-height .3s ease, opacity .22s ease; }
        .acc-body.acc-open { max-height: 760px; opacity: 1; }
        .acc-body-inner { padding: 4px 20px 20px 72px; }

        .acc-input { width: 100%; box-sizing: border-box; padding: 11px 12px; border: 1.5px solid var(--control-edge);
            border-radius: 10px; font-size: 14px; color: var(--ink); background: #fff; margin-bottom: 10px;
            transition: border-color .15s ease, box-shadow .15s ease; font-family: inherit; }
        .acc-input:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224,123,31,.14); }
        .acc-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; background: var(--orange);
            color: var(--ink); border: none; padding: 10px 16px; border-radius: 10px; font-weight: 700; font-size: 14px;
            cursor: pointer; transition: background .15s ease, transform .05s ease; font-family: inherit; }
        .acc-btn:hover, .acc-btn:active { background: var(--orange-dark); color: #000; } .acc-btn:active { transform: translateY(1px); }
        .acc-btn:disabled { opacity: .6; cursor: default; }
        .acc-btn.ghost { background: var(--surface); color: var(--orange-ink); border: 1px solid var(--control-edge); }
        .acc-btn:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }

        /* (the old phone card's badge, row and slide-open panel lived here — removed with the card by the phone
           confirmation job: account-phone-verify.js now draws "Change mobile number", styled under .pv-* / .pc-*) */
        .acc-msg { margin: 8px 0 0; font-size: 13px; color: var(--ink-2); }

        @media (max-width: 640px) {
            .acc-body-inner { padding-left: 20px; }
            .acc-head { padding: 15px 16px; gap: 12px; }
        }
        .s-heading { font-size: 28px; font-weight: 800; color: #1a1a1a; margin: 0 0 22px; letter-spacing: -0.3px; }

        .s-card {
            background: #fff; border-radius: 16px; box-shadow: 0 4px 22px rgba(0,0,0,0.05);
            padding: 26px 28px; margin-bottom: 20px; max-width: 760px;
        }
        .s-card h3 { margin: 0 0 14px; font-size: 17px; font-weight: 700; color: #1a1a1a; }
        .s-note { font-size: 14px; color: var(--ink-2); line-height: 1.6; margin: 0 0 4px; }

        .s-badge { font-size: 11px; font-weight: 700; color: var(--orange-ink); background: var(--surface); padding: 2px 8px; border-radius: 10px; }
        /* Trust row on the signed-out cards — inline SVG, inherits the list colour. */
        .auth-trust li { display: inline-flex; align-items: center; gap: 6px; }
        .trust-ico { width: 15px; height: 15px; flex: 0 0 15px; }
        .s-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 12px 0; border-bottom: 1px solid #f2f2f2; }
        .s-row:last-child { border-bottom: none; }
        .s-row-actions { display: flex; gap: 12px; flex-shrink: 0; flex-wrap: wrap; }
        /* Below ~560px the three actions (Set default · Edit · Delete) take enough of
           the row that the address itself is squeezed to one word per line. Stack
           instead: the address gets the full width, the actions sit under it. */
        @media (max-width: 560px) {
            /* `align-items: flex-start` shrink-wraps each child once the row is a
               column, so the address kept its narrow measure. Stretch instead. */
            .s-row { flex-direction: column; align-items: stretch; gap: 10px; }
            .s-row > div { min-width: 0; }
            .s-row-actions { width: 100%; }
        }
        .s-link { background: none; border: none; color: var(--orange-ink); font-weight: 600; font-size: 14px; cursor: pointer; padding: 0; }
        .s-link.danger { color: #c0392b; }


        /* Neutral, not orange: opening a menu is navigation, not a primary action,
           and orange is reserved for actions that do something. */

        @media (max-width: 1024px) {
            .settings-layout { grid-template-columns: 260px 1fr; gap: 22px; }
            .settings-sidebar { width: 260px; }
        }
        @media (max-width: 760px) {
            .settings-layout { grid-template-columns: 1fr; }
            .settings-sidebar {
                position: fixed; top: 0; left: 0; bottom: 0; z-index: 1200;
                width: 268px; max-width: 84vw; border-radius: 0;
                transform: translateX(-100%); transition: transform 0.25s ease; overflow-y: auto;
            }
            .settings-sidebar.open { transform: translateX(0); box-shadow: 4px 0 30px rgba(0,0,0,0.25); }
        }

/* ---- account.html former static style="" attributes ---- */
#account-back { display: none; }
#all-options-page { display: none; }
#settings-shell { display: none; }
#auth-create { display: none; }
/* account.html#create: Create account from the first paint (script.js syncAuthCard sets the class in <head>). */
html.ftk-auth-create #auth-login { display: none; }
html.ftk-auth-create #auth-create { display: flex; }
#email-pending { background:#fff4e5;border:1px solid #f0c98a;border-radius:9px;padding:12px 14px; }
#email-pending-exp { color:#9a7a3a; }
#email-pending-code { width:130px;padding:9px 11px;border:1.5px solid #e8c98a;border-radius:8px;font-size:16px;letter-spacing:2px; }
#email-pending-confirm { padding:9px 16px;font-size:13.5px; }
#email-pending-resend { background:none;border:none;padding:0;color:var(--orange-ink);font-weight:700;font-size:13px;cursor:pointer;text-decoration:underline; }
#email-pending-msg { margin:8px 0 0;font-size:12.5px;color:#9a7a3a; }
#email-pending .ftk-ep-resend { margin:8px 0 0;font-size:13px;color:#7a5200; }   /* "Didn’t get it? Check spam, or send a new code" */
#email-pending-cancel { margin-top:9px;background:#fff;border:1px solid #c0392b;color:#c0392b;padding:6px 12px;border-radius:7px;font-weight:700;font-size:12.5px;cursor:pointer; }
#email-change-form { border:1px solid #e8e8e8;border-radius:9px;padding:14px; }
#email-change-submit { padding:9px 16px;font-size:13.5px; }
#email-change-cancelbtn { background:#f4f5f6;border:1px solid var(--control-edge);color:#5a6068;padding:9px 16px;border-radius:8px;font-weight:700;font-size:13.5px;cursor:pointer; }
#email-change-msg { margin:9px 0 0;font-size:12.5px;color:var(--ink-2); }
#addr-msg { margin-top:10px; }
#create-error { color:#c0392b;font-size:13px;margin:-4px 0 8px;line-height:1.4; }
/* no-id children of the email cards — id-scoped so they beat body:not(.admin-body) .form-group label (0,2,2) and any descendant rule, matching the old inline win */
#email-pending .ftk-ep-text { font-size:13.5px;color:#7a5200;line-height:1.5; }
#email-pending .ftk-ep-row { display:flex;gap:8px;margin-top:10px;flex-wrap:wrap;align-items:center; }
#email-change-form .ftk-ec-row { display:flex;gap:8px;margin-top:10px;flex-wrap:wrap; }
#email-change-form .ftk-ecl-new { font-size:13px; }
#email-change-form .ftk-ecl-pw { font-size:13px;margin-top:8px;display:block; }
/* My Orders heading: beat body:not(.admin-body) .section-header h2 (0,2,2) with (0,3,1) */
body:not(.admin-body) .section-header .ftk-heading-flush { margin:0; }

/* ============================================================================
   ACCOUNT DELETION (self-service) — the delete card's text inputs. The 16px is a
   LITERAL, never a variable: below 16px iOS Safari zooms the focused field and
   pans the page sideways (a device fault, not a style choice). Everything else
   on the card reuses existing account classes (.acc-card/.acc-head/.acc-body/
   .acc-input/.acc-msg/.s-link.danger).
   ============================================================================ */
#del-pw, #del-confirm { font-size: 16px; }

/* ============================================================================
   TWO-STEP SIGN-IN (customer TOTP) — the enrolment/disable card in panel-security
   (account-2fa.js) and the sign-in challenge (account.html #auth-mfa). Colours,
   radii and fonts are the existing tokens; the card reuses .acc-card/.acc-head/
   .acc-body/.acc-input/.acc-btn/.s-link.danger. Only the pieces the mock adds
   (step label, manual key, warning, recovery-code grid, checkbox, pill) are new.

   16px is a LITERAL on every text input, never a variable: below 16px iOS Safari
   zooms the focused field and pans the page sideways (a device fault).
   ============================================================================ */
#tfa-pw, #tfa-code, #tfa-disable-pw, #login-mfa-code, #login-mfa-recovery { font-size: 16px; }

.tfa-step[hidden] { display: none; }
.tfa-steps { font-size: var(--fs-meta); color: var(--ink-2); margin: 0 0 12px; font-weight: 700; }
.tfa-otpauth { display: inline-block; color: var(--orange-ink); font-weight: 700; font-size: var(--fs-body); margin: 0 0 16px; text-decoration: none; }
.tfa-otpauth:hover { text-decoration: underline; }
.tfa-key { background: var(--surface); border: var(--bw) solid var(--divider); border-radius: var(--r-card);
  padding: 12px; font-size: var(--fs-body); letter-spacing: .08em; text-align: center; word-break: break-all; margin: 0 0 16px; }
.tfa-warn { background: var(--surface); border: var(--bw) solid var(--divider); border-left: 4px solid var(--danger);
  border-radius: var(--r-card); padding: 12px; font-size: 14px; line-height: 1.5; margin: 0 0 16px; color: var(--ink); }
.tfa-warn strong { color: var(--danger); }
.tfa-codes { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0 0 16px; }
.tfa-codes span { background: var(--surface); border: var(--bw) solid var(--divider); border-radius: var(--r-btn);
  padding: 10px; font-size: var(--fs-body); letter-spacing: .06em; text-align: center; font-variant-numeric: tabular-nums; }
.tfa-check { display: flex; gap: 10px; align-items: flex-start; margin: 0 0 16px; font-size: 14px; line-height: 1.5; color: var(--ink); }
.tfa-check input { width: 20px; height: 20px; flex: none; margin: 0; accent-color: var(--orange-ink); }
.tfa-pill { display: inline-block; font-size: var(--fs-micro); font-weight: 700; letter-spacing: .04em;
  padding: 3px 9px; border-radius: var(--r-pill); background: var(--paid-green-bg); border: var(--bw) solid var(--paid-green-bg); color: var(--paid-green); }
.ftk-2fa-back { background: none; border: 0; font-family: inherit; font-size: var(--fs-body); color: var(--ink-2); padding: 8px 0 0; cursor: pointer; display: block; }

/* ══════════════════════════════════════════════════════════════════════════
   ADMIN OPS CONSOLE — CSP style pass (batch E). Relocated inline styles from
   admin/ops-console-3dacfcbd19.html + .js so style-src 'self' can be enforced.
   EVERY rule is scoped under `.admin-body` AND prefixed `acsp-` (a token that
   appears NOWHERE else): the storefront never carries `.admin-body`, so none of
   these can match a storefront element — this file is SHARED with the store.
   Declarations are copied verbatim from the inline styles they replace; this is
   a relocation, not a restyle. `.admin-body` gives specificity (0,2,0) to win
   over the console's existing (0,1,0)/(0,2,0) rules by source order; the
   od-note rule also carries an #order-modal variant to beat that (1,1,1) rule.
   ══════════════════════════════════════════════════════════════════════════ */
.admin-body .acsp-hidden { display: none; }
.admin-body .acsp-topclip { position: sticky; top: 0; height: 6px; background: #f6f7f9; z-index: 1001; }
.admin-body .acsp-secret { word-break: break-all; font-size: 13px; background: #f6f8f7; padding: 8px; border-radius: 6px; display: block; }
.admin-body .acsp-otpauth-note { font-size: 12px; }
.admin-body .acsp-codes { background: #f6f8f7; padding: 10px; border-radius: 8px; font-size: 13px; white-space: pre-wrap; }
.admin-body .acsp-nav-top { top: 6px; }
.admin-body .acsp-mt24 { margin-top: 24px; }
.admin-body .acsp-flexcol-18 { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.admin-body .acsp-statlabel-c { align-self: center; margin: 0; }
.admin-body .acsp-errorbox { margin: 0 0 16px; padding: 12px; border: 1px solid #B3261E; border-radius: 8px; background: #FDECEA; color: #B3261E; font-size: 14px; line-height: 1.4; }
.admin-body .acsp-sm-product { margin: 0 0 4px; font-weight: 700; color: #1a1a1a; }
.admin-body .acsp-sm-hint { margin: 0 0 16px; color: #667; font-size: 13px; }
.admin-body .acsp-retry-btn { margin-top: 8px; background: var(--orange); color: var(--ink); border: none; padding: 8px 16px; border-radius: 6px; font-weight: 700; cursor: pointer; font-family: inherit; font-size: 13px; }
.admin-body .acsp-retry-btn:hover, .admin-body .acsp-retry-btn:active { background: var(--orange-dark); color: #000; }   /* = the console primary button's hover and pressed (follow-up 6) */
.admin-body .acsp-empty-err { color: #a11722; }
.admin-body .acsp-m0 { margin: 0; }
/* od-note is rendered inside #order-modal, where `.admin-body #order-modal .od-note`
   (1,1,1) would otherwise win — this variant (1,2,0) beats it; the bare form covers
   any other placement. */
.admin-body #order-modal .acsp-od-done, .admin-body .acsp-od-done { color: var(--paid-green); font-weight: 700; }
.admin-body .acsp-sm-label { font-weight: 700; color: #1a1a1a; }
.admin-body .acsp-sm-stock { color: #667; font-size: 13px; }
.admin-body .acsp-sm-hold { color: #B3261E; }
/* sm-unit (stock-adjust unit selector) — was a computed inline style (border/background
   depended on the selected state). Two-class state family: base carries the static +
   UNSELECTED look; `-sel` overrides only the two things that differ when selected.
   The selected one is the console's selected-card style (--orange-ink edge, the orange selected tint — the same as the
   checked staff-role card; batch 3A follow-up 5: no action or selected state is green); #cfe0d4 is the unselected
   border literal (not a token). */
.admin-body .acsp-sm-unit { display: flex; align-items: center; justify-content: flex-start; gap: 6px; width: 100%;   /* fix round 3 (item 4): "5kg · 40 in stock" reads as one phrase — the dot no longer sits at the far edge */ text-align: left; padding: 12px 14px; border-radius: 8px; cursor: pointer; font-size: 14px; border: 1px solid var(--control-edge); background: #fff; }
.admin-body .acsp-sm-unit-sel { border-color: var(--orange-ink); background: rgba(224, 123, 31, .06); }   /* = the selected staff-role card (follow-up 5) */

/* ── Checkout "Order placed" success panel (Batch 1) ───────────────────────────
   Replaces the on-screen receipt after a settled payment (see checkout.js
   showOrderPlaced). Namespaced .order-success-* so it adds only new selectors and
   changes no existing rule — style.css is copied verbatim into the admin console at
   build (admin/package.json). Colours are the shared brand tokens; spacing/type use
   the house --s* and --fs*/--lh* scales, which already equal the approved values
   (32/16 padding, 24 gap to the buttons, 8 heading→line, 12 between buttons;
   heading 24/700/1.25, line 15/1.5). Muted text is --ink-2 (#6B6B66), the site's
   secondary-text token — the prototype's #55554F was sampled by eye. */
.order-success {
    max-width: 480px;                 /* wide screens: capped, centred in the column */
    margin: 0 auto;
    padding: var(--s6) var(--s4);      /* 32px top/bottom, 16px left/right */
    box-sizing: border-box;            /* full width at 390px with no horizontal scroll */
}
.order-success-head {
    margin: 0;
    font-size: var(--fs-title);        /* 24px */
    font-weight: 700;
    line-height: var(--lh-head);       /* 1.25 */
    color: var(--ink);
}
.order-success-head:focus { outline: none; }                     /* no ring on the scroll-to focus */
.order-success-head:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 3px; border-radius: 4px; }
.order-success-line {
    margin: var(--s2) 0 0;             /* 8px below the heading */
    font-size: var(--fs-body);         /* 15px */
    line-height: var(--lh-body);       /* 1.5 */
    color: var(--ink-2);
}
.order-success-actions {
    margin-top: var(--s5);             /* 24px gap between the text and the buttons */
    display: flex;
    flex-direction: column;
    gap: var(--s3);                    /* 12px between the two buttons */
}
.order-success-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;                       /* full width of the panel */
    height: 48px;
    border-radius: 6px;
    font-size: var(--fs-body);         /* 15px */
    font-weight: 700;
    text-align: center;
    text-decoration: none;
    box-sizing: border-box;
    cursor: pointer;
}
.order-success-btn--primary {
    background: var(--orange);
    color: var(--ink);
    border: 1px solid var(--orange);
}
.order-success-btn--primary:hover, .order-success-btn--primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
.order-success-btn--outline {
    background: var(--page);           /* white */
    color: var(--orange-ink);
    border: 1px solid var(--orange-ink);
}
.order-success-btn--outline:hover { background: var(--surface); }
.order-success-btn:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }

/* ── Create account / Sign in forms (Batch 2, Part E) ─────────────────────────
   Namespaced .authf-* so nothing here touches a shared selector (the .auth-* auth
   cards, and .auth-btn which the account receipt reuses, are untouched). style.css
   is copied verbatim into the admin console at build. Tokens: --orange / --orange-dark
   (button), --ink / --ink-2 (text), --divider (rule). The 1px input border #C9C8C2 has
   no existing token, so the approved prototype value is used literally here. */
.authf-card {
    max-width: 420px;              /* live .auth-grid max-width */
    margin: 0 auto;
    padding: 24px 32px 32px;       /* side padding = live .auth-card (32px desktop; 20px at ≤700 below) */
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: 24px;                     /* 24px between sections (kept from the redesign) */
}
@media (max-width: 700px) {
    .authf-card { padding-left: 20px; padding-right: 20px; }   /* matches live .auth-card @≤700 */
}
.authf-top { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.authf-logo { width: 52px; height: 52px; display: block; }   /* live .auth-hero-logo */
.authf-title {
    margin: 0;
    font-size: 20px;                   /* live .auth-card h3 ("Welcome Back") */
    font-weight: 700;
    line-height: 1.25;
    text-align: center;
    color: var(--ink);
}
.authf-fields { display: flex; flex-direction: column; gap: 16px; }
.authf-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.authf-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.authf-label {                         /* live .form-group label: 13/700/0.3px/none */
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.3px;
    color: var(--ink-2);
}
/* Batch 2 fix 2: match the LIVE input sizes exactly — min-height 48px, 16px text,
   0 12px padding, 8px radius (= --r-card, live's value; the earlier fix's 6px was wrong).
   The ONE deliberate difference from live is the #8A8A85 border (--divider #E5E4E0 is far
   lighter, --ink-2 #6B6B66 darker — no token matches). Selector (0,2,2) + later source beats
   the broad `body:not(.admin-body) input[type=…]` rule for the border colour; every other
   property equals what that rule already sets, so the inputs render the same size as live.
   The Account Center #prof-first-name/#prof-last-name inputs are intentionally NOT here —
   they use the shared .form-group/broad rules and so look identical to the other profile
   inputs (16px, no iOS zoom). */
body:not(.admin-body) .authf-input {
    min-height: 48px;
    padding: 0 12px;
    font-size: 16px;
    border: 1px solid var(--control-edge);
    border-radius: 8px;
    width: 100%;
    box-sizing: border-box;
    background: #ffffff;
    color: var(--ink);
}
/* Existing focus, re-affirmed above the broad rule's border-color: outline off, orange
   border. The orange focus ring (box-shadow) still comes from the broad input:focus rule. */
body:not(.admin-body) .authf-input:focus { outline: none; border-color: var(--orange-ink); }
/* Phone confirmation job: a sign-up box whose own message shows under it (the Mobile number — account.js phoneFieldErr) is
   outlined in the page's inline-error red, focused or not (after the :focus rule, same specificity). */
body:not(.admin-body) .authf-input[aria-invalid="true"] { border-color: #c0392b; }
.authf-help { margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.authf-forgot { margin: 0; text-align: right; }
.authf-forgot a { font-size: 13px; color: var(--ink-2); text-decoration: none; }
.authf-forgot a:hover { text-decoration: underline; }
.authf-error { margin: 0; font-size: 14px; line-height: 1.5; color: #c0392b; }  /* the page's existing inline-error red */
.authf-btn {
    height: 48px;
    width: 100%;
    border: none;
    border-radius: 6px;
    background: var(--orange);
    color: var(--ink);
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
}
.authf-btn:hover, .authf-btn:active { background: var(--orange-dark); color: #000; }
.authf-btn-create { margin-top: 8px; }   /* 8px extra above the Create button */
.authf-terms { margin: 0; font-size: 13px; line-height: 1.5; text-align: center; color: var(--ink-2); }
.authf-terms a { color: var(--ink-2); }
.authf-divider { border: none; border-top: 1px solid var(--divider); margin: 0; }
.authf-switch { margin: 0; font-size: 14px; text-align: center; color: var(--ink-2); }   /* live .auth-switch: 14px */
.authf-switch a { font-weight: 700; color: var(--orange-ink); text-decoration: none; }
.authf-switch a:hover { text-decoration: underline; }

/* ── Bulk product upload (admin ops console) ──────────────────────────────────
   Namespaced .bulk-* so it can only style the bulk-upload screen (the storefront has
   no .bulk-* elements). style.css is copied into the admin console at build. No inline
   styles: the progress bar width is set from JS via el.style (CSSOM), not a style= attr.
   Colours reuse the shared tokens (--orange, --ink, --surface); the greys/reds below are
   the approved mock's own values where no token exists. */

/* step pills */
.bulk-pills { display: flex; align-items: center; gap: 0; margin: 4px 0 20px; flex-wrap: wrap; }
.bulk-pill { padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 700; background: #F1EFEA; color: #6B6B66; white-space: nowrap; }
.bulk-pill--current { background: var(--orange-ink); color: #FFFFFF; }
.bulk-pill-line { width: 24px; height: 1px; margin: 0 8px; background: var(--control-edge); flex: 0 0 auto; align-self: center; }

/* step 1 — one bordered container, rows split by dividers */
.bulk-card { max-width: 880px; border: 1px solid #E5E4E0; border-radius: 8px; background: #FFFFFF; }
.bulk-row { position: relative; display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; padding: 24px; border-bottom: 1px solid #E5E4E0; }
.bulk-row:last-child { border-bottom: 0; }
.bulk-row-main { flex: 1 1 auto; min-width: 0; }
.bulk-row-side { flex: 0 0 auto; }
.bulk-row-title { margin: 0 0 6px; font-size: 18px; font-weight: 700; color: var(--ink); }
.bulk-help { margin: 0; font-size: 15px; color: #6B6B66; line-height: 1.4; word-break: break-word; }
.bulk-links { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 18px; }
.bulk-row--action { align-items: center; }
.bulk-row--action .bulk-actions { margin-top: 0; }

/* plain text links (downloads / exports) — never bordered pills */
.bulk-link { background: none; border: 0; padding: 0; font: inherit; font-size: 13px; font-weight: 700; color: var(--orange-ink); cursor: pointer; text-decoration: none; }
.bulk-link:hover { color: var(--orange-ink); text-decoration: underline; }

/* update checkbox */
.bulk-check { display: flex; align-items: center; gap: 10px; margin: 0; cursor: pointer; }
.bulk-check input { width: 20px; height: 20px; flex: 0 0 auto; }
.bulk-check-label { font-size: 15px; font-weight: 700; color: var(--ink); }
.bulk-check-help { margin: 8px 0 0; font-size: 13px; color: #6B6B66; line-height: 1.45; }

/* action rows: below their content, right-aligned, never overlapping */
.bulk-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 16px; margin-top: 16px; }
.bulk-actions--split { justify-content: space-between; }
.bulk-note { margin: 0; font-size: 13px; color: #6B6B66; }

/* buttons — never full width; width set by their text */
.bulk-btn { height: 48px; padding: 0 28px; border-radius: 6px; border: 1px solid var(--orange); background: var(--orange); color: var(--ink); font-size: 15px; font-weight: 700; line-height: 46px; cursor: pointer; white-space: nowrap; display: inline-block; }
.bulk-btn:hover, .bulk-btn:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
.bulk-btn--secondary { background: #FFFFFF; border-color: var(--orange-ink); color: var(--orange-ink); }
.bulk-btn--secondary:hover { background: var(--surface); color: var(--orange-ink); border-color: var(--orange-dark); }
.bulk-btn:disabled, .bulk-btn[disabled] { background: #E5E4E0; border-color: #E5E4E0; color: #6B6B66; cursor: not-allowed; }

/* Stop is the only red text on the screen (destructive) */
.bulk-stop { background: none; border: 0; padding: 6px 0; font: inherit; font-size: 15px; font-weight: 700; color: #B3261E; cursor: pointer; }
.bulk-stop:hover { color: #8C1D17; text-decoration: underline; }

/* the real file inputs stay hidden; the buttons trigger them (keyboard reaches the button) */
.bulk-sr-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* check / finish panels */
.bulk-panel { max-width: 1040px; }

/* four count cards in a 4-column grid */
.bulk-counts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin-bottom: 20px; }
.bulk-counts--five { grid-template-columns: repeat(5, minmax(0, 1fr)); }   /* stopped import: five cards in one row */
.bulk-count { background: #F7F7F5; border: 1px solid #E5E4E0; border-radius: 10px; padding: 16px; text-align: center; min-width: 0; }
.bulk-count-n { display: block; font-size: 26px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.bulk-count-l { display: block; font-size: 12px; color: #6B6B66; margin-top: 4px; }
.bulk-count--problem { background: #FCF3F2; border-color: #E8C3BF; }
.bulk-count--problem .bulk-count-n { color: #B3261E; }
.bulk-count--problem .bulk-count-l { color: #8C1D17; }

/* review block (problems table + downloads) */
.bulk-review { margin: 0 0 20px; }
.bulk-review-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 10px; }
.bulk-review-title { margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); }
.bulk-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.bulk-table th, .bulk-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid #EEE; vertical-align: top; }
.bulk-table th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--ink-2); }
.bulk-table td:first-child { font-variant-numeric: tabular-nums; white-space: nowrap; color: #6B6B66; }

/* finish heading + download line */
.bulk-result-title { margin: 0 0 6px; font-size: 20px; font-weight: 800; color: var(--ink); }
.bulk-result-sub { margin: 0 0 20px; font-size: 14px; color: #6B6B66; }
.bulk-dl-line { margin: 0 0 12px; }

/* progress */
.bulk-progress { height: 12px; background: #ECEAE6; border-radius: 999px; overflow: hidden; margin-bottom: 10px; max-width: 1040px; }
.bulk-progress-bar { height: 100%; width: 0; background: var(--orange-ink); transition: width 0.2s ease; }
.bulk-progress-text { margin: 0 0 6px; font-size: 14px; font-weight: 700; color: var(--ink); }
.bulk-progress-current { color: #6B6B66; font-weight: 400; }
.bulk-keepopen { margin: 0 0 12px; font-size: 13px; color: #6B6B66; }

/* messages */
.bulk-msg { margin: 12px 0 0; font-size: 13px; color: #6B6B66; }
.bulk-msg-err { color: #B3261E; }

/* narrow admin content: stack the step-1 rows so the button never crowds the text */
@media (max-width: 560px) {
  .bulk-row { flex-direction: column; }
  .bulk-counts { grid-template-columns: repeat(2, 1fr); }
}

/* ═══ storefront rework Batch 1 §5 — ADMIN product-modal photos/about/details + category screen.
   Scoped to .admin-body ONLY (style.css is shared with the storefront). CSP-safe: no inline
   styles in the markup — these classes carry it. Tokens match the approved canvas. ═══ */
.admin-body .pm-section { padding: 20px 0; border-top: 1px solid #E5E4E0; display: flex; flex-direction: column; gap: 14px; }
.admin-body .pm-section:first-child { border-top: 0; padding-top: 0; }
.admin-body .pm-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.admin-body .pm-section-head-col { display: flex; flex-direction: column; gap: 4px; }
.admin-body .pm-section-title { margin: 0; font-size: 18px; font-weight: 700; color: #1A1A1A; }
.admin-body .pm-help { margin: 0; font-size: 13px; color: #6B6B66; line-height: 1.5; }
.admin-body .pm-photo-count { font-size: 13px; font-weight: 700; color: #6B6B66; }
.admin-body .pm-hidden-file { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }

/* Marketplace batch 4B (Parts E.1 / K): TEN square slots in ONE row that scrolls sideways — 176 px slots and a 16 px gap
   from 640 px up, 140 px and 12 px on a phone (client/product-photos.js draws them for the console AND the seller site). */
.admin-body .pm-photos { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x proximity; padding-bottom: 10px; scrollbar-width: thin; }
.admin-body .pm-photo-cell { flex: 0 0 176px; scroll-snap-align: start; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.admin-body .pm-photo-nav { display: flex; align-items: center; gap: 8px; }
.admin-body .pm-photo-nav button { width: 36px; height: 36px; border-radius: 50%; border: 1.5px solid var(--control-edge); background: #fff; font-size: 18px; line-height: 1; cursor: pointer; color: var(--ink); }
.admin-body .pm-photo-nav button:hover { border-color: var(--ink); }
.admin-body .pm-photo-rm { position: absolute; top: 8px; right: 8px; width: 32px; height: 32px; border-radius: 50%; border: 0; background: #1A1A1A; color: #fff; font-size: 14px; font-weight: 700; cursor: pointer; z-index: 2; padding: 0; }
.admin-body .pm-photo-plus { font-size: 34px; line-height: 1; color: var(--orange-ink); }
.admin-body .pm-photo-cap { display: flex; flex-direction: column; gap: 2px; min-height: 18px; }
.admin-body .pm-photo-dim { font-size: 13px; color: #6B6B66; font-variant-numeric: tabular-nums; }
.admin-body .pm-photo-warn { font-size: 13px; font-weight: 700; color: var(--amber-ink); }
@media (max-width: 640px) {
    .admin-body .pm-photos { gap: 12px; }
    .admin-body .pm-photo-cell { flex-basis: 140px; }
    .admin-body .pm-photo-nav button { display: none; }
}
.admin-body .pm-photo-frame { position: relative; width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden; border: 1px solid #E5E4E0; }
.admin-body .pm-photo-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.admin-body .pm-photo-mainpill { position: absolute; left: 8px; bottom: 8px; padding: 2px 10px; border-radius: 999px; background: #FFFFFF; color: #1A1A1A; font-size: 12px; font-weight: 900; z-index: 2; }
.admin-body .pm-photo-actions { display: flex; gap: 8px; }
.admin-body .pm-photo-actions-spacer { height: 44px; }
.admin-body .pm-photo-btn { flex-grow: 1; height: 36px; border-radius: 6px; background: #FFFFFF; font-size: 13px; font-weight: 700; cursor: pointer; }
.admin-body .pm-photo-makemain { border: 1px solid var(--orange-ink); color: var(--orange-ink); }
.admin-body .pm-photo-remove { border: 1px solid var(--control-edge); color: #B3261E; }
.admin-body .pm-photo-add { width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; border: 1.5px dashed var(--control-edge); background: #F7F7F5; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; cursor: pointer; }
.admin-body .pm-photo-addlabel { font-size: 15px; font-weight: 700; color: var(--orange-ink); }
.admin-body .pm-photo-addnum { font-size: 13px; color: #6B6B66; }
/* Gallery batch, part B — a photo on its way: its preview under a white band with "Preparing…" / "Uploading 45%" and a
   bar (--orange-ink on --divider), or its error in --danger with Try again and Remove. Text #1A1A1A / #B3261E on white. */
.admin-body .pm-photo-uploading { background: var(--surface); }
.admin-body .pm-photo-progress { position: absolute; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; background: rgba(255, 255, 255, .94); }
.admin-body .pm-photo-uploading.is-error .pm-photo-progress { top: 0; justify-content: center; background: #FFFFFF; }
.admin-body .pm-photo-progress-text { font-size: 13px; font-weight: 700; line-height: 1.35; color: var(--ink); }
.admin-body .pm-photo-uploading.is-error .pm-photo-progress-text { color: var(--danger); font-weight: 600; }
/* The photo note (not square / under 1,600px) under a photo here and beside it at the bulk upload's Check step: the error
   line's style in the one amber, --amber-ink #9C640C — 4.95:1 on the white modal and panel. A warning: nothing waits on it. */
.admin-body .ftk-photo-notes { display: flex; flex-direction: column; gap: 4px; }
.admin-body .ftk-photo-note { margin: 0; font-size: 13px; font-weight: 600; line-height: 1.35; color: var(--amber-ink); }
.admin-body .pm-photo-bar { display: block; height: 4px; border-radius: 999px; background: var(--divider); overflow: hidden; }
.admin-body .pm-photo-bar-fill { display: block; height: 100%; width: 0; border-radius: 999px; background: var(--orange-ink); transition: width .2s ease; }

.admin-body .pm-about { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.admin-body .pm-desc-textarea { height: 220px; resize: vertical; }
.admin-body .pm-preview-cust { height: 220px; box-sizing: border-box; padding: 14px 16px; border: 1px solid #E5E4E0; border-radius: 8px; background: #F7F7F5; overflow: auto; display: flex; flex-direction: column; gap: 10px; }
.admin-body .pm-preview-title { font-size: 17px; font-weight: 700; }
.admin-body .pm-preview-para { margin: 0; font-size: 15px; line-height: 1.5; }
.admin-body .pm-preview-list { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 4px; }
.admin-body .pm-preview-list li { font-size: 15px; line-height: 1.5; }
.admin-body .pm-preview-empty { margin: 0; font-size: 15px; color: #6B6B66; }

/* ══════════ categories batch A: the Categories screen, the product form's category dropdown and the
   Homepage editor (admin/catalogue-admin.js). Admin-scoped; the storefront uses none of these classes.
   Colours, type and buttons are the console's own (btn-add-product, btn-export, btn-edit, btn-del, ftk-pill).
   The console had no on/off switch before; .ftk-switch is the one switch — on, it is --orange-ink, as the shop's (follow-up 6). Off, the track is --control-edge #8A8A84 (3.47:1; white knob 3.47:1) — final colour round. ══════════ */
.admin-body .ftk-switch { position: relative; display: inline-block; width: 40px; height: 22px; padding: 0; border: 0; border-radius: 999px; background: var(--control-edge); cursor: pointer; vertical-align: middle; }
.admin-body .ftk-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 999px; background: #fff; transition: left .15s; }
.admin-body .ftk-switch[aria-checked="true"] { background: var(--orange-ink); }   /* = the shop's switch when on (follow-up 6) */
.admin-body .ftk-switch[aria-checked="true"]::after { left: 21px; }
.admin-body .ftk-switch[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) { .admin-body .ftk-switch::after { transition: none; } }
.admin-body .ftk-switch:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
/* An on/off setting saved WITH a form ("Show it on the homepage", "Update products that already exist"): the
   same switch, then its clickable label (catalogue-admin.js, [data-form-switch]). A tick box is only for
   choosing items from a list (bulk upload's "Create …" names), and every tick box takes the brand orange,
   never the browser's blue. */
.admin-body .ftk-switch-row { display: flex; align-items: center; gap: 10px; margin: 0; }
.admin-body .ftk-switch-row label { cursor: pointer; }
.admin-body input[type="checkbox"],
.admin-body input[type="radio"] { accent-color: var(--orange-ink); }
.admin-body .cat-table td { vertical-align: middle; }
.admin-body .cat-table tr.cat-dept-row td { background: var(--surface); font-weight: 700; }
.admin-body .cat-indent { padding-left: 28px; }
.admin-body .cat-thumb { width: 44px; height: 44px; border-radius: 6px; overflow: hidden; background: var(--surface); display: flex; align-items: center; justify-content: center; }
.admin-body .cat-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.admin-body .cat-thumb-empty span { font-size: 10px; color: var(--ink-2); text-align: center; line-height: 1.2; }
.admin-body .cat-photo-btn { padding: 0; border: 0; background: none; cursor: pointer; border-radius: 6px; }
.admin-body .cat-name-wrap { margin-right: 8px; }
.admin-body .cat-sub { font-size: 12px; font-weight: 400; color: var(--ink-2); }
.admin-body .cat-mini { min-height: 30px; padding: 0 10px; font-size: 13px; margin-right: 4px; }
.admin-body .cat-mini:disabled { opacity: .45; cursor: not-allowed; }
.admin-body .cat-order { white-space: nowrap; }
.admin-body .cat-rename-input { display: inline-block; width: min(240px, 100%); margin-right: 6px; }
.admin-body .cat-msg-box { margin: 0 0 12px; padding: 10px 12px; border-radius: 8px; font-size: 14px; }
.admin-body .cat-msg-ok { background: var(--paid-green-bg); color: var(--paid-green); }
.admin-body .cat-msg-err { background: #FCEBEA; color: #8C1D18; }
.admin-body .cat-msg-warn { background: #FFF4DB; color: var(--amber-ink); }   /* the one amber, #9C640C — 4.53:1 on this #FFF4DB */
.admin-body .cat-box { display: flex; flex-direction: column; gap: 12px; margin: 0 0 16px; padding: 16px; border: 1px solid var(--divider); border-radius: 10px; background: #fff; }
.admin-body .cat-box-danger { border-color: #E7C6C3; }
.admin-body .cat-box-title { margin: 0; font-size: 18px; font-weight: 700; }
.admin-body .cat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.admin-body .cat-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.admin-body .cat-photo-pick { display: flex; align-items: center; gap: 10px; }
.admin-body .cat-note { margin: 12px 0 0; font-size: 13px; color: var(--ink-2); }
.admin-body .cat-p { margin: 0; }
.admin-body .cat-move { max-width: 360px; }
.admin-body .cat-count { display: block; font-size: 12px; color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; }
.admin-body .pm-hint { display: block; margin-top: 4px; font-size: 12px; color: var(--ink-2); }
.admin-body .pm-newcat { display: flex; flex-direction: column; gap: 10px; margin: 0 0 12px; padding: 12px; border: 1px solid #E8C66A; border-radius: 8px; background: #FFF6E0; }
.admin-body .pm-newcat-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.admin-body .pm-newcat-ok { margin: 0 0 12px; padding: 10px 12px; border-radius: 8px; background: var(--paid-green-bg); color: var(--paid-green); font-size: 14px; }
.admin-body .hp-head-actions { flex-wrap: wrap; align-items: center; }
/* Product Edit always current: while the product (read fresh) and the category list load, the Edit form shows only
   "Loading…" (and any error) — no field, so nothing older can be seen or saved. */
.admin-body #product-modal.is-loading .modal-body > :not(#pm-loading):not(#pm-error) { display: none; }
.admin-body .pm-loading { margin: 24px 0; text-align: center; color: var(--ink-2); font-size: 15px; }
.admin-body .hp-small { font-size: 13px; font-weight: 400; }
.admin-body .hp-box { margin-bottom: 16px; }
.admin-body .hp-section-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px; }
.admin-body .hp-section-head h2 { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.admin-body .hp-section-acts, .admin-body .hp-row-acts { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.admin-body .hp-pill { min-width: 0; height: auto; min-height: 26px; white-space: normal; text-align: left; }
/* Marketplace batch 4A round 2 (R3): a section's or product row's heading WRAPS — its title and its status pill — so the
   page is never wider than the screen. Two rules held them on one line: every console button is nowrap (a product
   row's title is a button), and the .hp-pill rule above loses to the later .admin-body .ftk-pill (nowrap, 26px high).
   On one line nothing changes: the pill keeps its 26px height and 124px minimum, its text where it was. */
.admin-body .hp-section-head .hp-row-toggle { white-space: normal; }
.admin-body .hp-section-head .ftk-pill.hp-pill { white-space: normal; height: auto; min-height: 26px; max-width: 100%; padding: 4px 12px; line-height: 1.25; }
@media (max-width: 700px) {
    /* …and a status pill in a homepage table once the table is a stack of cards (a card's "… is hidden", a long
       product name in it) — the same rule, the same cause. Wider, those tables are tables, and stay as they are. */
    .admin-body .admin-table .ftk-pill.hp-pill { white-space: normal; height: auto; min-height: 26px; max-width: 100%; padding: 4px 12px; line-height: 1.25; }
}
.admin-body .hp-picker { display: flex; flex-direction: column; gap: 6px; }
.admin-body .hp-search { display: flex; flex-direction: column; gap: 6px; }
.admin-body .hp-search-results { display: flex; flex-direction: column; gap: 4px; max-height: 220px; overflow-y: auto; }
.admin-body .hp-result { text-align: left; padding: 8px 10px; border: 1px solid var(--divider); border-radius: 6px; background: #fff; cursor: pointer; }
.admin-body .hp-result:hover { background: var(--surface); }
.admin-body .hp-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.admin-body .hp-tile { display: flex; flex-direction: column; gap: 8px; padding: 10px; border: 1px solid var(--divider); border-radius: 8px; }
.admin-body .hp-tile .cat-thumb { width: 96px; height: 96px; }
.admin-body .hp-editor { border-color: var(--orange); }
.admin-body .hp-add-section { margin: 0 0 16px; }
.admin-body .hp-add-btns { display: flex; flex-wrap: wrap; gap: 8px; }
/* A form drawn in a table row's place (the Homepage editor's and the Categories screen's placement fix): one cell
   across the row; the form keeps its own box, padding and colours. */
.admin-body .admin-table td.hp-form-cell { padding: 12px 0; color: inherit; }
.admin-body #hp-sec-form { margin-bottom: 12px; }
/* A product row opens and closes: its title is a button that looks like the heading, ▸ closed / ▾ open (drawn here,
   so a screen reader hears only "Product row: …" and whether it is expanded). */
.admin-body .hp-row-toggle {
    display: inline-flex; align-items: baseline; gap: 6px; padding: 0; margin: 0;
    background: none; border: 0; font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.admin-body .hp-row-toggle::before { content: "▸"; content: "▸" / ""; display: inline-block; width: 1em; color: var(--ink-2); }
.admin-body .hp-row-toggle[aria-expanded="true"]::before { content: "▾"; content: "▾" / ""; }
.admin-body .hp-row-toggle:focus-visible { outline: 3px solid var(--orange-ink); outline-offset: 2px; border-radius: 4px; }
/* "+ Add product": the box under a product row's header; a message next to its item */
.admin-body .hp-qa { margin: 0 0 12px; }
.admin-body .hp-note .cat-msg-box { margin: 8px 0 12px; }
/* A row's own message on the Reviews, Products, Orders and Email problems lists (admin-core rowNote): directly under the
   row it is about — across a whole grid line, or a whole table row — or where the row was once it has gone. */
.admin-body .row-note { grid-column: 1 / -1; }
.admin-body .row-note .cat-msg-box { margin: 8px 0; }
.admin-body .rv-box-err { margin: 8px 0 0; }
/* the product row editor (homepage spec v3): its products in order, each with ↑ ↓ Remove; the search's Add lines */
.admin-body .hp-prow-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.admin-body .hp-prow-item, .admin-body .hp-prow-result { display: flex; align-items: center; gap: 12px; }
.admin-body .hp-prow-item { padding: 6px 8px; border: 1px solid var(--divider); border-radius: 8px; }
.admin-body .hp-prow-result { padding: 6px 10px; border: 1px solid var(--divider); border-radius: 6px; background: #fff; }
.admin-body .hp-prow-name { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.admin-body .hp-prow-arrow { margin: 0 0 8px; }

/* ══════════ Admin badge-fix batch: make the `hidden` attribute actually hide ══════════
   ROOT CAUSE of "the Reported badge stays at 1 when the list is empty": an author `display:`
   rule (e.g. `.admin-body .rv-badge{display:inline-flex}`) is MORE SPECIFIC than the UA
   `[hidden]{display:none}`, so setting `el.hidden = true` sets the attribute but the element
   stays displayed with its stale text. This is the same trap the storefront already patched
   per-element (see `.modal-overlay[hidden]`, `.ftk-dialog__input[hidden]`, `.rcpt-overlay[hidden]`).
   One admin-scoped rule restores it for the WHOLE admin panel, covering every element toggled via
   the hidden attribute that also carries a `display:` rule — TODAY that is `.rv-badge` (the visible
   symptom), `.rv-list` and `.admin-pager` (latent, previously masked only because their content is
   also cleared). `!important` because these author rules out-specify the plain attribute selector. */
.admin-body [hidden] { display: none !important; }

/* ══════════ Admin fix batch §7: self-refresh header widget ══════════
   Admin-scoped only. The header widget sits at the right of each .admin-head (which is
   display:flex, space-between). (The "N new — show" banner is gone: the timed refresh now
   redraws the rows and flashes the changed ones — .row-flash below.) */
.admin-body .admin-updated { margin-left: auto; display: flex; align-items: center; gap: 12px; font-size: 12.5px; color: #6B6B66; }
.admin-body .admin-updated-time { white-space: nowrap; }
.admin-body .admin-updated-time.is-stale { color: #B3261E; font-weight: 600; }
/* The refund fix round, fix 5: the clock reads "Updated 18 Oct 2026, 3:58 AM WAT" now — on a narrow phone (320px) Refresh
   moves under it rather than past the header's edge; wherever both fit, nothing changes. */
.admin-body .admin-updated { flex-wrap: wrap; row-gap: 6px; }
.admin-body .admin-updated-refresh { height: 32px; padding: 0 14px; border: 1px solid var(--control-edge); background: #FFFFFF; color: #1A1A1A; border-radius: 6px; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
.admin-body .admin-updated-refresh:hover { border-color: var(--orange-ink); }   /* = .admin-body .admin-nav-btn:hover (follow-up 5) */

/* ══════════ storefront rework Batch 2: Admin Reviews tab (canvas screen 3) ══════════
   Admin-scoped only (.admin-body). Panel colours: the site's orange system (--orange fill with --ink text, --orange-ink
   text and edges), dividers #E5E4E0, control edges #8A8A84, grey #6B6B66, ink #1A1A1A, red #B3261E (final colour round). No inline styles or on* handlers — all behaviour is in the JS. */
.admin-body .rv-tabs { display: flex; gap: 8px; margin: 4px 0 18px; border-bottom: 1px solid #E5E4E0; }
.admin-body .rv-tab { appearance: none; border: none; background: transparent; padding: 10px 4px; margin-right: 18px; font: inherit; font-size: 14px; font-weight: 600; color: #6B6B66; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.admin-body .rv-tab.active { color: var(--orange-ink); border-bottom-color: var(--orange-ink); }
.admin-body .rv-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; margin-left: 7px; border-radius: 9px; background: #B3261E; color: #FFFFFF; font-size: 11px; font-weight: 700; vertical-align: middle; }


.admin-body .rv-list { display: flex; flex-direction: column; gap: 14px; }
.admin-body .rv-row { display: flex; gap: 16px; padding: 16px 18px; background: #FFFFFF; border: 1px solid #E5E4E0; border-radius: 10px; }
.admin-body .rv-photo { width: 72px; height: 72px; flex: 0 0 72px; object-fit: cover; border-radius: 8px; background: #F2F1EE; border: 1px solid #E5E4E0; }
.admin-body .rv-main { flex: 1 1 auto; min-width: 0; }
.admin-body .rv-row-top { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.admin-body .rv-pname { font-size: 15px; font-weight: 700; color: #1A1A1A; }
.admin-body .rv-stars { display: inline-flex; gap: 1px; font-size: 15px; line-height: 1; letter-spacing: 1px; }
.admin-body .rv-star { color: transparent; -webkit-text-stroke: 1px var(--star-gold); }
.admin-body .rv-star--on { color: var(--star-gold); -webkit-text-stroke: 0; }
.admin-body .rv-meta { display: flex; align-items: center; gap: 7px; margin: 4px 0 8px; font-size: 12.5px; color: #6B6B66; }
.admin-body .rv-dot { color: var(--ink-2); }
.admin-body .rv-text { margin: 0 0 8px; font-size: 14px; line-height: 1.5; color: #1A1A1A; white-space: pre-wrap; overflow-wrap: anywhere; }
.admin-body .rv-reported { margin: 6px 0 10px; font-size: 12.5px; font-weight: 600; color: #B3261E; }

.admin-body .rv-reply-holder { margin-top: 8px; }
.admin-body .rv-reply { background: #F4F3F0; border-radius: 8px; padding: 12px 14px; }
.admin-body .rv-reply-head { font-size: 12px; font-weight: 700; color: #6B6B66; margin-bottom: 5px; }
.admin-body .rv-reply-body { font-size: 14px; line-height: 1.5; color: #1A1A1A; white-space: pre-wrap; overflow-wrap: anywhere; }
.admin-body .rv-reply-acts { display: flex; gap: 14px; margin-top: 10px; }

.admin-body .rv-actions { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.admin-body .rv-btn { appearance: none; height: 36px; padding: 0 16px; border-radius: 8px; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; border: 1px solid transparent; }
.admin-body .rv-btn--primary { background: var(--orange); color: var(--ink); border-color: var(--orange); }
.admin-body .rv-btn--primary:hover, .admin-body .rv-btn--primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }   /* the console's primary hover and pressed (final colour round) */
.admin-body .rv-btn--ghost { background: #FFFFFF; color: #1A1A1A; border-color: var(--control-edge); }
.admin-body .rv-btn--danger-solid { background: #B3261E; color: #FFFFFF; border-color: #B3261E; }
.admin-body .rv-btn--link { height: auto; padding: 0; background: transparent; border: none; color: var(--orange-ink); font-weight: 600; }
.admin-body .rv-btn--link.rv-btn--danger { color: #B3261E; }

.admin-body .rv-composer { margin-top: 8px; }
.admin-body .rv-textarea { width: 100%; min-height: 84px; padding: 10px 12px; border: 1px solid var(--control-edge); border-radius: 8px; font: inherit; font-size: 14px; color: #1A1A1A; resize: vertical; box-sizing: border-box; }
.admin-body .rv-textarea:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224,123,31,.18); }
.admin-body .rv-composer-info { margin: 7px 0 10px; font-size: 12.5px; color: #6B6B66; }
.admin-body .rv-composer-acts { display: flex; gap: 10px; }

.admin-body .rv-empty { padding: 48px 20px; text-align: center; background: #FFFFFF; border: 1px dashed #E5E4E0; border-radius: 10px; }
.admin-body .rv-empty-title { font-size: 15px; font-weight: 700; color: #1A1A1A; margin-bottom: 6px; }
.admin-body .rv-empty-sub { font-size: 13px; color: #6B6B66; }

@media (max-width: 560px) {
  .admin-body .rv-row { flex-direction: column; }
  .admin-body .rv-photo { width: 64px; height: 64px; flex-basis: 64px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MARKETPLACE BATCH 4B — THE CONSOLE'S SELLER SCREENS (admin/sellers-admin.js): Sellers, Listing reviews, the Seller
   Agreement. On the money screens' pieces above (.pr-*, .mn-*): the sign-up switch card, the flags, the side-by-side
   "Approved now / Proposed" table with its changed rows in amber, each photo's size and note, the publish box.
   ═══════════════════════════════════════════════════════════════════════════ */
.admin-body .sl-signup-card { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; margin: 0 0 14px; padding: 14px 16px; border: 1px solid var(--divider); border-radius: var(--r-card); background: #fff; }
.admin-body .sl-signup-card:empty { display: none; }
.admin-body .sl-signup-t { display: grid; gap: 2px; min-width: 0; }
.admin-body .sl-signup-t strong { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 15px; color: var(--ink); }
.admin-body .sl-signup-t span:not(.ftk-pill) { font-size: 14px; color: var(--ink-2); }
.admin-body .sl-signup-confirm { align-items: center; font-size: 14px; }
.admin-body .sl-signup-card .mn-err { flex-basis: 100%; }
.admin-body .sl-flag { display: inline-flex; margin-top: 6px; min-width: 0; height: auto; min-height: 22px; padding: 2px 10px; white-space: normal; text-align: left; }
.admin-body .sl-sub { margin: -6px 0 12px; font-size: 14px; }
.admin-body .sl-note-red { margin: 0 0 12px; padding: 10px 12px; border-radius: var(--r-card); background: #FCEBEA; color: #8C1D18; font-size: 14px; line-height: 1.45; }
.admin-body .sl-hist { margin: 0; padding-left: 18px; font-size: 14px; line-height: 1.5; color: var(--ink); display: grid; gap: 4px; }
.admin-body .sl-textarea { display: block; width: 100%; max-width: 520px; min-height: 96px; margin: 0 0 6px; padding: 10px 12px; box-sizing: border-box; border: 1px solid var(--control-edge); border-radius: var(--r-card); font: inherit; font-size: 15px; color: var(--ink); background: #fff; resize: vertical; }
.admin-body .sl-textarea[aria-invalid="true"] { border-color: #B3261E; }
.admin-body .sl-cmp td { vertical-align: top; }
.admin-body .sl-cmp tr.is-changed td { background: #FFF4DB; }
.admin-body .sl-cmp tr.is-changed td:first-child { box-shadow: inset 3px 0 0 var(--amber-ink); }
.admin-body .sl-photos { display: flex; flex-wrap: wrap; gap: 6px; }
.admin-body .sl-mini-ph { width: 68px; display: grid; gap: 2px; }
.admin-body .sl-mini-ph img { display: block; width: 68px; height: 68px; object-fit: cover; border-radius: 6px; border: 1px solid var(--divider); background: var(--surface); }
.admin-body .sl-ph-dim { font-size: 10px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.admin-body .sl-ph-warn { font-size: 11px; font-weight: 700; color: var(--amber-ink); }
.admin-body .sl-publish { padding: 16px 18px; margin: 0 0 16px; border: 1px solid var(--ink); }
.admin-body .sl-pub-h { margin: 0 0 12px; font-size: 17px; font-weight: 700; color: var(--ink); }
.admin-body .sl-pub-row { align-items: center; margin: 0 0 12px; }
.admin-body .sl-pub-file { font-size: 14px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.admin-body .sl-publish .mn-confirm { margin-top: 0; }
/* 4B fix round 6 (item 1): the seller detail's "Edit business details" button sits with the title and the status pill; the
   amber "Business name needs fixing" pill on the head and the list row; the two boxes of the correction panel (16 px at
   phone width through .mn-field's rule above) with their inline field errors */
.admin-body .sl-biz-edit { margin-left: auto; }
.admin-body .pr-head .sl-flag { margin-top: 0; }
/* the sellers list's row: a long name (an email, before it is corrected) and the pill wrap instead of overlapping (scoped to this list) */
.admin-body #sl-list .pr-item-top { flex-wrap: wrap; }
.admin-body #sl-list .pr-item-num { min-width: 0; overflow-wrap: anywhere; }
.admin-body #sl-list .pr-item-top .sl-flag { margin-top: 0; }
.admin-body .sl-bizpanel .mn-fields { margin-bottom: 10px; }
.admin-body .sl-bizpanel .mn-field input[aria-invalid="true"] { border-color: #B3261E; }
.admin-body .sl-bizpanel .mn-err { margin: 0 0 6px; font-weight: 400; }
.admin-body .ag-table td { vertical-align: top; }
.admin-body .ag-table .mn-link { white-space: normal; overflow-wrap: anywhere; text-align: left; }   /* fix round 6 (the sweep at 390/320): a long PDF name wraps inside the stacked row instead of scrolling the page sideways */

/* ═══════════════════════════════════════════════════════════════════════════════════════
   STOREFRONT REWORK BATCH 3 — category tiles, swipe rows, category page, product page, search,
   not-found. Mobile-first (390×844); the laptop layout (full window width, the column ladder)
   is the "CATEGORIES BATCH B + DESKTOP WIDTH" block at the end of this file.
   No inline styles anywhere — every dynamic value (bar width) is set via CSSOM.
   Tokens reused: --orange #E07B1F, --ink #1A1A1A, --ink-2 #6B6B66, --surface, --divider.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* ── CATEGORY TILE (the department and "All categories" pages; storefront-render.js tileHtml) ── */
.cat-tile { display: block; text-decoration: none; color: var(--ink); }
.cat-tile-img {
    display: block;
    aspect-ratio: 1 / 1;
    border-radius: 8px;
    overflow: hidden;
    background: var(--surface);
}
.cat-tile-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cat-tile-name { display: block; margin-top: 8px; font-size: 15px; font-weight: 700; line-height: 1.25; color: var(--ink); }
.cat-tile-count { display: block; margin-top: 2px; font-size: 13px; line-height: 1.3; color: var(--ink-2); }

/* ── THE SWIPE ROW (product page "You might also like", the cart's "Add more", a department's "Best sellers").
   Horizontal, snap-scrolling, NEVER wraps. From 900px it is whole cards with arrows (the block at the end). */
.prod-row {
    display: flex; flex-wrap: nowrap; gap: 12px;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
    padding: 2px 16px 6px;
}
.prod-row::-webkit-scrollbar { display: none; }
.row-card { flex: 0 0 auto; width: 134px; scroll-snap-align: start; text-decoration: none; color: var(--ink); }
.row-card-img { display: block; width: 134px; height: 134px; border-radius: 8px; overflow: hidden; background: var(--surface); }
.row-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.row-card-name {
    display: block; margin-top: 6px; font-size: 14px; font-weight: 700; line-height: 1.3; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;   /* one line, ellipsis */
}

/* ── 3 CATEGORY PAGE ───────────────────────────────────────────────────────── */
.cat-head { padding: 16px 16px 4px; }
.cat-back {
    display: inline-block; margin-bottom: 10px; font-size: 14px; font-weight: 600;
    color: var(--orange-ink); text-decoration: none;
}
.cat-back:hover { text-decoration: underline; }
.cat-name { margin: 0; font-size: 24px; font-weight: 700; color: var(--ink); }
.cat-count { margin: 4px 0 0; font-size: 14px; color: #5A5A55; }
/* The category / search grid card: PHOTO + FULL NAME, the whole card a link. It sits inside the
   existing .product-grid (which supplies the 2-col-phone → desktop column ladder). */
.cat-card { display: block; text-decoration: none; color: var(--ink); }
.cat-card-img { display: block; aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden; background: var(--surface); }
.cat-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .18s ease; }
.cat-card:hover .cat-card-img img { transform: scale(1.04); }
.cat-card-name { display: block; margin-top: 8px; font-size: 14px; font-weight: 700; line-height: 1.3; color: var(--ink); }   /* size fix Item 2: 14.5 → 14 (site's standard size) */

/* ── 4 PRODUCT PAGE ────────────────────────────────────────────────────────── */
.pp-root { padding: 16px; }

/* 4b gallery — gallery batch, part A: section "THE PRODUCT PHOTO GALLERY" below (after E) */

/* 4c name + rating */
.pp-head { margin-top: 16px; }
.pp-name { margin: 0 0 8px; font-size: 22px; font-weight: 700; line-height: 1.25; color: var(--ink); }
.pp-rating { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pp-stars { display: inline-flex; letter-spacing: 1px; }
.pp-stars .star { color: transparent; -webkit-text-stroke: 1px var(--star-gold); font-size: 17px; line-height: 1; }
.pp-stars .star.is-on { color: var(--star-gold); -webkit-text-stroke: 0; }
.pp-stars-sm .star { font-size: 14px; }
.pp-rating-num { font-weight: 700; color: var(--ink); font-size: 14px; }
.pp-rating-count { font-size: 14px; color: var(--orange-ink); text-decoration: none; }
.pp-rating-count:hover { text-decoration: underline; }
.pp-noreviews { margin: 0; font-size: 14px; color: var(--ink-2); }
.pp-noreviews a { color: var(--orange-ink); }

/* 4d size boxes — Batch 3 SIZE FIX Item 1: 4 per row, compact. Grid of 4 equal columns capped at
   400px (so they don't grow on desktop); a 5th+ size wraps to a second row of 4. Look (selected /
   sold-out) unchanged; radius snapped to the --r-card token (8). */
.pp-sizes {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px;
    max-width: 400px;
    margin: 16px 0 8px;
}
.pp-size {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    min-height: 52px; padding: 8px 6px; background: #fff;
    border: 1px solid var(--control-edge); border-radius: 8px; cursor: pointer; color: var(--ink);
    font: inherit; text-align: center;
}
/* label: 14/700, wraps to at most 2 lines */
.pp-size-label {
    font-size: 14px; font-weight: 700; line-height: 1.2;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* price: 13/400, secondary, NEVER wraps or clips (drops to 12 below 360 so it still fits 4-up) */
.pp-size-price { font-size: 13px; font-weight: 400; color: var(--ink-2); white-space: nowrap; }
.pp-size.is-sel { border: 2px solid #1A1A1A; background: #FFF8E7; }
.pp-size.is-out { border: 1px dashed var(--control-edge); color: var(--ink-2); cursor: not-allowed; background: #fff; }
.pp-size.is-out .pp-size-price { color: var(--ink-2); }
@media (max-width: 360px) { .pp-size-price { font-size: 12px; } }

/* 4e stock line */
.pp-stock { margin: 0 0 16px; font-size: 14px; font-weight: 600; }
.pp-stock-low { color: #A33A12; }
.pp-stock-in  { color: #1E6B35; }
.pp-stock-out { color: var(--danger); }

/* 4f stepper + Add To Cart */
.pp-buy { display: flex; align-items: stretch; gap: 12px; margin-bottom: 8px; }   /* size fix Item 2: 6 → 8 */
.pp-stepper { display: inline-flex; align-items: center; border: 1px solid var(--control-edge); border-radius: var(--r-card); overflow: hidden; }   /* size fix Item 2: radius 10 → --r-card (8), matches inputs */
.pp-step { width: 44px; min-height: 44px; border: none; background: #fff; font-size: 20px; line-height: 1; color: var(--ink); cursor: pointer; }   /* size fix Item 2: 46 → 44 (site control height; brief's 48 does not match the site — reported) */
.pp-step:disabled { color: #C9C7C0; cursor: not-allowed; }
.pp-qty { min-width: 40px; text-align: center; font-size: 16px; font-weight: 700; }
.pp-add { flex: 1 1 auto; }

/* 4g about / 4h details */
.pp-sec-h { margin: 24px 0 8px; font-size: 17px; font-weight: 700; color: var(--ink); }   /* size fix Item 2: 26/10 → 24/8 (product section gap = 24) */
.pp-about-body, #pp-about-body { color: #3f3f3a; }
.pp-para { margin: 0 0 10px; font-size: 15px; line-height: 1.6; color: #3f3f3a; }
.pp-list { margin: 0 0 10px; padding-left: 20px; }
.pp-list li { margin: 4px 0; font-size: 15px; line-height: 1.55; color: #3f3f3a; }
.pp-dl { margin: 0; }
.pp-dl-row { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--surface); }
.pp-dl-row dt { flex: 0 0 110px; font-weight: 700; color: var(--ink); font-size: 14px; }
.pp-dl-row dd { margin: 0; color: #4a4a45; font-size: 14px; }

/* 4i reviews */
.pp-reviews { margin-top: 0; }   /* size fix Item 2: 6 → 0 (uniform 24 section gap comes from .pp-sec-h) */
.pp-rv-summary { margin-bottom: 16px; }
.pp-rv-avg { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }   /* 10 → 8 */
.pp-rv-avg-num { font-size: 24px; font-weight: 700; color: var(--ink); line-height: 1.25; }   /* size fix Item 2: 30/800 → 24/700 (page-title standard; was larger than any site text) */
.pp-rv-count { font-size: 14px; color: var(--ink-2); }
.pp-rv-bars { display: flex; flex-direction: column; gap: 6px; }
.pp-bar { display: flex; align-items: center; gap: 10px; width: 100%; background: none; border: none; padding: 3px 0; cursor: pointer; font: inherit; }
.pp-bar-star { flex: 0 0 34px; text-align: right; font-size: 13px; color: var(--ink-2); }
.pp-bar-track { flex: 1 1 auto; height: 9px; background: var(--surface); border-radius: 999px; overflow: hidden; }
.pp-bar-fill { display: block; height: 100%; background: var(--star-gold); border-radius: 999px; }
.pp-bar-n { flex: 0 0 28px; text-align: left; font-size: 13px; color: var(--ink-2); }
.pp-bar.is-active .pp-bar-star, .pp-bar.is-active .pp-bar-n { color: var(--ink); font-weight: 700; }
.pp-bar:hover .pp-bar-track { outline: 1px solid var(--divider); }
.pp-rv-clear { margin-top: 8px; background: none; border: none; color: var(--orange-ink); font-size: 13px; font-weight: 600; cursor: pointer; padding: 0; }   /* size fix Item 2: 13.5 → 13 (meta) */
.pp-rv-clear:hover { text-decoration: underline; }

/* write a review */
.pp-write { margin: 16px 0; padding: 16px; background: var(--surface); border-radius: var(--r-card); }   /* size fix Item 2: margin 18 → 16, radius 12 → --r-card (8) */
.pp-write-h { margin: 0 0 10px; font-size: 15px; font-weight: 700; color: var(--ink); }
.pp-write-note { margin: 0; font-size: 14px; color: var(--ink-2); }
.pp-write-signin { display: inline-block; text-decoration: none; }
.pp-pick-row { display: inline-flex; gap: 4px; margin-bottom: 10px; }
.pp-pick { background: none; border: none; font-size: 22px; line-height: 1; color: transparent; -webkit-text-stroke: 1px var(--ink-2); cursor: pointer; padding: 2px 3px; }   /* size fix Item 2: 26 → 22 (star input was larger than the page title) */
.pp-pick.is-on { color: var(--orange-ink); -webkit-text-stroke: 0; }
.pp-write-text { display: block; width: 100%; box-sizing: border-box; border: 1px solid var(--divider); border-radius: 8px; padding: 10px 12px; font: inherit; font-size: 14px; resize: vertical; margin-bottom: 10px; }
.pp-write-submit { display: inline-block; }

/* review list */
.pp-rv-list { display: flex; flex-direction: column; gap: 16px; }
.pp-rv { border-top: 1px solid var(--surface); padding-top: 14px; }
.pp-rv-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pp-rv-name { font-weight: 700; color: var(--ink); font-size: 14px; }
.pp-rv-date { font-size: 12.5px; color: var(--ink-2); }
.pp-rv-text { margin: 8px 0 0; font-size: 14px; line-height: 1.55; color: #3f3f3a; overflow-wrap: anywhere; }   /* size fix Item 2: 14.5 → 14 (site's standard size) */
.pp-rv-reply { margin: 10px 0 0; padding: 10px 12px; background: #FFF8E7; border-radius: 8px; }
.pp-rv-reply-h { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--orange-ink); margin-bottom: 4px; }
.pp-rv-reply p { margin: 0; font-size: 14px; color: #4a4a45; overflow-wrap: anywhere; }
.pp-rv-actions { display: flex; align-items: center; gap: 16px; margin-top: 10px; }
.pp-rv-helpful, .pp-rv-report { background: none; border: none; padding: 0; font: inherit; font-size: 13px; color: var(--ink-2); cursor: pointer; }
.pp-rv-helpful.is-on { color: var(--orange-ink); font-weight: 700; }
.pp-rv-helpful:hover, .pp-rv-report:hover { color: var(--ink); }
.pp-rv-report.is-done { color: var(--ink-2); cursor: default; }
.pp-rv-you { font-size: 12.5px; color: var(--ink-2); font-style: italic; }
.pp-rv-empty { font-size: 14px; color: var(--ink-2); }
.pp-rv-more { margin-top: 16px; }

/* Rework tail (Item 5) — the customer's own-review Edit control + the edit form's Delete/Cancel/Save
   row. All controls 44px tall, 14px bold, 8px radius, to the site standard. */
.pp-rv-edit {
    margin-left: auto;                 /* right-align on the own-review action row */
    height: 44px;
    padding: 0 18px;
    font-size: 14px;
    font-weight: 700;
    background: #fff;
    border: 1px solid var(--control-edge);
    border-radius: 8px;
    color: var(--ink);
    cursor: pointer;
}
.pp-rv-edit:hover { border-color: var(--ink-2); }

.pp-write-actions {
    display: flex;
    flex-wrap: wrap;                    /* a very narrow screen wraps instead of overflowing */
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--divider);
}
.pp-write-actions .pp-write-delete { margin-right: auto; }   /* Delete pushed left; Cancel+Save right */
.pp-write-delete,
.pp-write-cancel,
.pp-write-save {
    height: 44px;
    padding: 0 14px;
    font-size: 14px;
    font-weight: 700;
    border-radius: 8px;
    border: 1px solid transparent;
    cursor: pointer;
}
.pp-write-delete { background: #fff; border-color: var(--danger); color: var(--danger); }
.pp-write-delete:hover { background: #fdf3f2; }
.pp-write-cancel { background: #fff; border-color: var(--divider); color: var(--ink); }
.pp-write-cancel:hover { border-color: var(--ink-2); }
.pp-write-save { background: var(--orange); border-color: var(--orange); color: var(--ink); }
.pp-write-save:hover, .pp-write-save:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
.pp-write-save:disabled { opacity: .5; cursor: not-allowed; }

/* 4j you might also like — reuses .prod-row / .row-card above */
.pp-more { margin-top: 0; }   /* size fix Item 2: 8 → 0 (uniform 24 section gap comes from .pp-sec-h) */
.pp-more .prod-row { padding-left: 0; padding-right: 0; }

/* ── Not found (bad /product/<slug> or /category/<slug>) ─────────────────────── */
.ftk-notfound { text-align: center; padding: 48px 16px; max-width: 520px; margin: 0 auto; }   /* size fix Item 2: 48 20 60 → 48 16 48 (on-scale) */
.ftk-notfound h1 { font-size: 24px; color: var(--ink); margin: 8px 0 8px; line-height: 1.25; }
.ftk-notfound p { font-size: 15px; color: var(--ink-2); margin: 0 0 16px; }   /* 18 → 16 */
.ftk-notfound .btn-continue { display: inline-block; text-decoration: none; }

/* The product page's laptop layout (gallery · details · buy box) is in the "CATEGORIES BATCH B + DESKTOP WIDTH"
   block at the end of this file. */

/* ══════════════════════════════════════════════════════════════════════════
   LOGIN & SECURITY FINISH (Parts G / H / I / J5). Append-only. Storefront rules are
   scoped to body:not(.admin-body); the admin QR is scoped to .admin-body. Colours, radii
   and 44px/14px sizing use the existing tokens. Every panel opens in place inside its row.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Part I — two-step screens ─────────────────────────────────────────────── */
body:not(.admin-body) .tfa-h { margin: 0 0 var(--s2); font-size: 16px; font-weight: 700; color: var(--ink); }

/* Step 1: QR + key. Desktop = QR left (200px) then the side column; mobile = the "add to app"
   button FIRST, above the QR (you can't scan your own screen). display:contents on mobile lets
   the side column's children reorder around the QR without a second copy of the markup. */
body:not(.admin-body) .tfa-scan { display: flex; flex-direction: column; gap: var(--s3); margin: 0 0 var(--s4); }
body:not(.admin-body) .tfa-qr-box { width: 200px; height: 200px; padding: 8px; background: #fff; border: 1px solid var(--divider); border-radius: 10px; box-sizing: content-box; flex: none; }
body:not(.admin-body) .tfa-qr { width: 200px; height: 200px; display: block; }
body:not(.admin-body) .tfa-scan-side { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
body:not(.admin-body) .tfa-scan-hint { margin: 0; }
body:not(.admin-body) .tfa-appbtn { display: inline-flex; align-items: center; justify-content: center; text-align: center;
  min-height: 44px; padding: 10px 16px; border: 1px solid var(--control-edge); border-radius: 8px; background: #fff;
  color: var(--ink); font-size: 14px; font-weight: 700; text-decoration: none; line-height: 1.3; }
body:not(.admin-body) .tfa-appbtn:hover { background: var(--surface); border-color: var(--orange-ink); }
body:not(.admin-body) .tfa-details { margin: 0; }
body:not(.admin-body) .tfa-details > summary { cursor: pointer; font-size: 14px; font-weight: 700; color: var(--orange-ink); padding: var(--s2) 0; list-style: none; }
body:not(.admin-body) .tfa-details > summary::-webkit-details-marker { display: none; }
body:not(.admin-body) .tfa-copy { margin: 0 0 var(--s2); }
body:not(.admin-body) .tfa-key-hint { margin: 0; }
@media (max-width: 699px) {
  body:not(.admin-body) .tfa-scan-side { display: contents; }
  body:not(.admin-body) .tfa-appbtn { order: -1; }
  body:not(.admin-body) .tfa-qr-box { order: 0; align-self: center; }
  body:not(.admin-body) .tfa-scan-hint { order: 1; }
  body:not(.admin-body) .tfa-details { order: 2; }
}
@media (min-width: 700px) {
  body:not(.admin-body) .tfa-scan { flex-direction: row; align-items: flex-start; gap: var(--s4); }
  body:not(.admin-body) .tfa-scan-side { flex: 1 1 240px; }
}

/* Step 2: the code input — letter-spaced, capped at 180px. */
body:not(.admin-body) .tfa-code-input { max-width: 180px; letter-spacing: .3em; text-align: center; font-variant-numeric: tabular-nums; }

/* Button rows across the steps: back/cancel on the left, the primary on the right. */
body:not(.admin-body) .tfa-actions { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-top: var(--s4); }
body:not(.admin-body) .tfa-actions .ftk-2fa-back { padding: 0; }

/* On state + the danger buttons. */
body:not(.admin-body) .tfa-on-status { display: flex; align-items: center; gap: var(--s2); margin: 0 0 var(--s2); font-size: var(--fs-body); }
body:not(.admin-body) .tfa-on-status .value { font-weight: 700; color: var(--ink); }
body:not(.admin-body) .tfa-pill { text-transform: uppercase; }
body:not(.admin-body) .tfa-btn { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 16px;
  border-radius: 8px; font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer; border: 1px solid transparent; }
body:not(.admin-body) .tfa-btn-white { background: #fff; color: var(--ink); border-color: var(--control-edge); }
body:not(.admin-body) .tfa-btn-white:hover { background: var(--surface); }
body:not(.admin-body) .tfa-btn-danger { background: #fff; color: var(--danger); border-color: var(--danger); }        /* Turn off (On row) */
body:not(.admin-body) .tfa-btn-danger-solid { background: var(--danger); color: #fff; border-color: var(--danger); }  /* Turn it off */

/* ── Part G — the Devices panel ────────────────────────────────────────────── */
body:not(.admin-body) .sess-list { display: flex; flex-direction: column; gap: 8px; margin: 0 0 var(--s4); }
body:not(.admin-body) .sess-card { display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  border: 1px solid var(--divider); border-radius: 8px; padding: 12px 14px; }
body:not(.admin-body) .sess-card-main { min-width: 0; }
body:not(.admin-body) .sess-card-line1 { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
body:not(.admin-body) .sess-devlabel { font-size: 15px; font-weight: 700; color: var(--ink); }
body:not(.admin-body) .sess-tag { font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .04em;
  padding: 2px 8px; border-radius: 999px; background: var(--paid-green-bg); color: var(--paid-green); }
body:not(.admin-body) .sess-card-line2 { margin-top: 2px; font-size: 13px; color: var(--ink-2); }
body:not(.admin-body) .sess-signout { flex: none; min-height: 44px; padding: 0 14px; border: 1px solid var(--divider);
  border-radius: 8px; background: #fff; color: var(--ink); font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer; }
body:not(.admin-body) .sess-signout:hover { background: var(--surface); border-color: var(--danger); color: var(--danger); }
body:not(.admin-body) .sess-foot { display: flex; align-items: center; justify-content: flex-end; gap: var(--s2); flex-wrap: wrap; }
body:not(.admin-body) .sess-btn { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 16px;
  border-radius: 8px; font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer; border: 1px solid var(--control-edge); background: #fff; color: var(--ink); }
body:not(.admin-body) .sess-btn-white { background: #fff; color: var(--ink); border-color: var(--control-edge); }
body:not(.admin-body) .sess-btn-white:hover { background: var(--surface); }
body:not(.admin-body) .sess-btn-danger { background: #fff; color: var(--danger); border-color: var(--danger); }         /* Sign out all others */
body:not(.admin-body) .sess-btn-danger-solid { background: var(--danger); color: #fff; border-color: var(--danger); }   /* Confirm sign-out */
body:not(.admin-body) .sess-btn[hidden] { display: none; }   /* the display above would otherwise beat the UA [hidden] rule */
body:not(.admin-body) .sess-confirm-actions { display: flex; gap: var(--s2); margin-top: var(--s3); }
body:not(.admin-body) #sess-confirm { margin: 0 0 var(--s3); }
body:not(.admin-body) #sess-msg:empty { display: none; margin: 0; }   /* G8 — no leftover message / empty space */

/* ── Part G9 — one divider, not two, between "Your data" and "Delete account".
   The ls-rows list already ends in a divider under "Your data"; the delete card's own
   top border (from .acc-card + .acc-card, triggered by the hidden cards before it) made a
   second line with an empty band between. Drop the delete card's top border/padding. ── */
body:not(.admin-body) #delete-account-card { border-top: 0; padding-top: 0; }

/* ── Part K5 — address form action row: Delete · Cancel · Save on ONE row at EVERY width
   (supersedes Part H's narrow-only rule). Delete pushed left (margin-right:auto, set at ~4491),
   right-aligned, gap 8, buttons padding 0 16 (0 14 under 480). ── */
body:not(.admin-body) .addr-form-actions { flex-wrap: nowrap; gap: 8px; }
body:not(.admin-body) .addr-form-actions .auth-btn { min-width: 0; flex: 0 1 auto; padding: 0 16px; white-space: nowrap; }
/* The display:inline-flex on .addr-form-actions .auth-btn (~4478) beats the UA [hidden] rule, so the
   Delete button stayed visible on the ADD form ("nothing to delete yet" — the owner's complaint #2).
   Honour the hidden attribute so Delete only shows when editing. */
body:not(.admin-body) .addr-form-actions .auth-btn[hidden] { display: none; }
@media (max-width: 480px) {
  body:not(.admin-body) .addr-form-actions .auth-btn { padding: 0 14px; }
}

/* ── Part J5 — admin two-step QR (admin console only). Same 200×200 server-drawn SVG. ── */
.admin-body .acsp-qr { display: block; width: 200px; height: 200px; padding: 8px; background: #fff;
  border: 1px solid #e0e0e0; border-radius: 10px; box-sizing: content-box; margin: 0 0 12px; }

/* ══════════════════════════════════════════════════════════════════════════
   PART K — ADDRESSES PAGE (match the approved prototype). Append-only, scoped to the
   storefront account page (body:not(.admin-body)). No form is open on load; the header
   button opens it in place at the top; saved addresses are bordered cards with ONE Edit.
   ══════════════════════════════════════════════════════════════════════════ */
/* K1 — header row: "Your addresses" + a light "+ Add an address" button (NOT a big orange block). */
body:not(.admin-body) .addr-header { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; margin: 0 0 var(--s4); }
body:not(.admin-body) .addr-your { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); }
body:not(.admin-body) .addr-add-toggle { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 16px;
  background: #fff; border: 1px solid var(--control-edge); border-radius: 8px; color: var(--orange-ink); font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer; }
body:not(.admin-body) .addr-add-toggle:hover { background: var(--surface); border-color: var(--orange-ink); }
body:not(.admin-body) .addr-add-plus { font-size: 18px; line-height: 1; font-weight: 700; }
/* the display:inline-flex above beats the UA [hidden] rule; restore hiding while a form is open. */
body:not(.admin-body) .addr-add-toggle[hidden] { display: none; }

/* K2 — saved cards: 1px line-grey border, radius 10, padding 16, 12px apart; ONE Edit on the right. */
body:not(.admin-body) #addresses-list .s-row {
  display: flex; flex-direction: row; align-items: flex-start; justify-content: space-between; gap: var(--s3);
  border: 1px solid var(--divider); border-radius: 10px; padding: 16px; margin: 0 0 12px;
}
body:not(.admin-body) #addresses-list .s-row:last-child { margin-bottom: 0; }
/* flex sizing overrides the @media(max-width:560px) block that stacked .s-row and set the actions to
   full width (built for THREE buttons; there is now only one Edit, so the card stays a row at 390). */
body:not(.admin-body) #addresses-list .addr-card-main { flex: 1 1 auto; min-width: 0; }
body:not(.admin-body) #addresses-list .addr-title { font-size: 16px; font-weight: 700; color: var(--ink); }
body:not(.admin-body) #addresses-list .addr-card-main .s-note { font-size: 15px; color: var(--ink-2); margin: 2px 0 0; }
body:not(.admin-body) #addresses-list .s-row-actions { flex: 0 0 auto; width: auto; display: flex; }
body:not(.admin-body) #addresses-list .addr-edit-btn {
  min-height: 44px; height: 44px; padding: 0 18px; border: 1px solid var(--control-edge); border-radius: 8px;
  background: #fff; color: var(--orange-ink); font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer;
}
body:not(.admin-body) #addresses-list .addr-edit-btn:hover { background: var(--surface); border-color: var(--orange-ink); }

/* K3/K4 — the adding/editing card, form-only (block), so the form fills it. The row currently open in the form, so a
   customer scrolled away from it can still tell which address they are changing: EXACTLY the selected checkout address
   card (#checkout-page .ck-addr-card[aria-checked="true"]) — a 2px --orange-ink edge and the light orange tint; 15px
   padding keeps the card the same size as the 1px + 16px it replaces (final colour round). */
body:not(.admin-body) #addresses-list .s-row.is-editing {
  display: block; background: rgba(224, 123, 31, .06); border: 2px solid var(--orange-ink); border-radius: var(--r-card); padding: 15px;
}

/* K3/K4 — "Make this my default address" checkbox row. */
body:not(.admin-body) .addr-default-group { margin: 0 0 var(--s3); }
body:not(.admin-body) .addr-default-check { display: flex; align-items: center; gap: var(--s2); font-size: 14px; color: var(--ink); cursor: pointer; }
body:not(.admin-body) .addr-default-check input { width: 18px; height: 18px; accent-color: var(--orange-ink); flex: none; margin: 0; }

/* ══ Part A — the FTK logo links to the homepage on every sign-in screen ══
   No visual change (an <img> inside an <a>); a keyboard focus ring only on focus-visible.
   Centred on the standalone auth pages (.abox / .vbox); in account.html the logo sits in
   .authf-top, which already centres it. Append-only. */
.authf-logo-link { display: inline-block; text-decoration: none; line-height: 0; }
.authf-logo-link:focus-visible { outline: 3px solid var(--orange-ink); outline-offset: 2px; border-radius: 8px; }
.abox .authf-logo-link, .vbox .authf-logo-link { display: block; width: 52px; margin: 0 auto 14px; }

/* ── Part C — cart Share fallback menu (shown when there is no OS share sheet: desktop browsers, or
   ANY non-https page such as the local LAN test). Pinned FIXED to the viewport by positionShareMenu
   (script.js) so the cart card's overflow cannot clip it, above the swipe row and the sticky
   "Proceed to Checkout" bar (z-index 900). Its top/left are set on the element inline; look and
   wording are unchanged. Appended last so it wins over the earlier absolute-position rule. ── */
.cp-share-menu.cp-share-fixed {
    position: fixed; right: auto; z-index: 1000;
    max-height: 70vh; overflow-y: auto;
}

/* ══════════ Email outbox fix + admin fixes (Part C) ══════════
   Admin-scoped only (.admin-body — the storefront never carries that class). Tokens from the
   spec: page #F6F7F9, text #2F2F2F, primary #E07B1F, panels white / 8px / 0 4px 18px
   rgba(0,0,0,.06), table headers 11px 700 uppercase #AAAAAA. No inline styles (the admin CSP). */
/* left/top 0 (batch 3B fix round): without them the hidden text sat where it would have flowed — at the far end of the
   Orders list's columns — outside the list's own scroller, and the whole page could scroll sideways on a phone. It
   paints nothing either way. */
.admin-body .acsp-sr-only { position: absolute; left: 0; top: 0; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* C2 + batch 6 — pills: 26px high, at least 124px wide (longer labels such as "Refund in progress" grow),
   padding 0 12px, radius 999, 13px bold, centred, never wrapping; the same everywhere. */
.admin-body .ftk-pill { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; min-width: 124px; height: 26px; padding: 0 12px; border-radius: 999px; font-size: 13px; font-weight: 700; line-height: 1; white-space: nowrap; }
.admin-body .ftk-pill-paid, .admin-body .ftk-pill-delivered { background: #E8F5E9; color: #1F7A3F; }
.admin-body .ftk-pill-unpaid, .admin-body .ftk-pill-awaiting { background: #FFF4DB; color: var(--amber-ink); }
/* Fix round 3 (item 2): no blue or purple in the console or the seller site — Processing is the orange "in hand" pill,
   Shipped the amber "on its way" pill (the seller site's To ship / Shipped read the same); C2's blue/purple pair is retired. */
.admin-body .ftk-pill-processing { background: var(--orange-tint); color: var(--orange-ink); }
.admin-body .ftk-pill-shipped { background: #FFF4DB; color: var(--amber-ink); }
.admin-body .ftk-pill-toship { background: var(--orange-tint); color: var(--orange-ink); }   /* the seller site's "To ship" and Owner pills */
.admin-body .ftk-pill-cancelled { background: #FCEBEA; color: #8C1D18; }
.admin-body .ftk-pill-refunded { background: #FFFFFF; color: #3F3F3B; border: 1px solid #C9C8C2; }
/* Payment safety batch (item 2): an order paid after it was cancelled — "Refund needed" in place of its
   payment pill, and the banner at the top of its pop-up, until an admin refunds it. */
.admin-body .ftk-pill-refundneeded { background: #FCEBEA; color: #8C1D18; }
/* Batch 6: a Paystack refund — started, failed, or waiting for the customer's bank details. The refund status batch: both
   problems red ("Needs bank details" the light red of Refund needed, 7.4:1), "Partly refunded" neutral like Refunded. */
.admin-body .ftk-pill-refundprogress { background: #FDF0D5; color: #7A4B00; }
.admin-body .ftk-pill-refundfailed { background: #8C1D18; color: #FFFFFF; }
.admin-body .ftk-pill-refundbank { background: #FCEBEA; color: #8C1D18; }
.admin-body .ftk-pill-partlyrefunded { background: #FFFFFF; color: #3F3F3B; border: 1px solid #C9C8C2; }
/* Gallery batch, part C — LATE ORDERS in the console: the list's second pill under the status, and the order window's
   "Set a new delivery date" form. "Late by N days" #9C640C on #FFF4DE (4.54:1); "New date …" dark on --surface with a
   --control-edge edge (3.47:1 on the white row). */
.admin-body .ord-status { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.admin-body .ftk-pill-late { background: #FFF4DE; color: #9C640C; }
.admin-body .ftk-pill-newdate { background: #F7F7F5; color: #1A1A1A; border: 1px solid #8A8A84; }
.admin-body #order-modal .od-status .ftk-pill + .ftk-pill { margin-left: 8px; }
.admin-body #order-modal .od-newdate { margin: 0 0 14px; padding: 16px; border: 1px solid var(--divider); border-radius: var(--r-card); background: var(--surface); }
.admin-body #order-modal .od-newdate-title { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); }
.admin-body #order-modal .od-newdate .od-note { margin: 6px 0 12px; }
.admin-body #order-modal .od-newdate-row { display: flex; flex-wrap: wrap; gap: 12px; }
.admin-body #order-modal .od-newdate input[type="date"] { display: block; font-family: inherit; font-size: 15px; height: 44px; padding: 0 10px; border-radius: var(--r-card); border: 1px solid var(--control-edge); background: #fff; color: var(--ink); }
.admin-body #order-modal .od-newdate input[type="date"]:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
.admin-body #order-modal .od-newdate .od-newdate-msg { margin: 10px 0 0; }
.admin-body #order-modal .od-newdate .od-newdate-msg:empty { display: none; }
.admin-body #order-modal .od-newdate .od-newdate-msg.od-msg-error { color: #B3261E; }
.admin-body #order-modal .od-newdate .od-controls { margin-top: 12px; }
/* The pop-up's refund banner — the first thing in it. The payment safety batch's "Refund needed" shape,
   one colour set per state (batch 6); a failed / needs-bank-details banner also holds "Open Paystack refunds". */
.admin-body #order-modal .od-refund-banner { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; margin: 0 0 14px; padding: 10px 14px; border: 1px solid transparent; border-radius: 8px; background: #FCEBEA; color: #8C1D18; font-size: 14px; font-weight: 700; line-height: 1.4; }
.admin-body #order-modal .od-refund-banner.od-banner-progress { background: #FDF0D5; border-color: #F2D49A; color: #5C3900; }
.admin-body #order-modal .od-refund-banner.od-banner-failed { background: #FCEBEA; border-color: #F3C5C1; color: #8C1D18; }
.admin-body #order-modal .od-refund-banner.od-banner-bank { background: #FCEBEA; border-color: #F3C5C1; color: #8C1D18; }   /* the refund status batch: red, as failed */
.admin-body #order-modal .od-refund-banner.od-banner-over { background: #FCEBEA; border-color: #F3C5C1; color: #8C1D18; }   /* fix round 3, fix 2: refunded more than the order total */
.admin-body #order-modal .od-refund-banner .od-banner-link { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
/* The refund status batch — the money rows (Part 8.24): label left, amount right; the parts indented under their row. */
.admin-body #order-modal .od-money { margin: 12px 0 18px; padding: 10px 14px; border: 1px solid var(--divider); border-radius: var(--r-card); }
.admin-body #order-modal .od-money-row { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; font-size: 14px; color: var(--ink); }
.admin-body #order-modal .od-money-row > span:last-child { white-space: nowrap; font-variant-numeric: tabular-nums; }
.admin-body #order-modal .od-money-strong { font-weight: 700; }
.admin-body #order-modal .od-money-sub { padding: 2px 0 2px 16px; font-size: 13px; color: var(--ink-2); }
.admin-body #order-modal .od-money-over { color: #B3261E; font-weight: 700; }   /* fix round 3, fix 2: "Refunded ₦X more than the order total" */
/* fix round 4, fix 3: …once marked as reviewed, the neutral grey text colour, followed by "Reviewed by <name> on <date>: <note>";
   "Mark as reviewed" and its in-page form under a red one */
.admin-body #order-modal .od-money-over-reviewed { color: var(--ink-2); font-weight: 700; }
.admin-body #order-modal .od-over-reviewed { margin: 0 0 4px; font-size: 13px; line-height: 1.45; color: var(--ink-2); overflow-wrap: anywhere; }
.admin-body #order-modal .od-over-act { margin: 4px 0 6px; }
.admin-body #order-modal .od-over-form { margin: 6px 0 8px; }
.admin-body #order-modal .od-over-form .mn-textarea { margin: 0; }
.admin-body #order-modal .od-over-form .mn-err { margin: 6px 0 0; }
.admin-body #order-modal .od-over-form .mn-confirm-acts { margin-top: 12px; }
.admin-body #order-modal .od-over-done { margin: 6px 0 4px; }
/* Refund order's parts and "The problem was our fault" (Parts 4.16, 5.18) */
.admin-body #order-modal .od-parts { margin: 0 0 12px; padding: 10px 12px; border: 1px solid var(--divider); border-radius: var(--r-card); background: #fff; }
.admin-body #order-modal .od-part { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 14px; color: var(--ink); }
.admin-body #order-modal .od-part > span:first-child { overflow-wrap: anywhere; }
.admin-body #order-modal .od-part > span:last-child { white-space: nowrap; font-variant-numeric: tabular-nums; }
.admin-body #order-modal .od-part-total { margin-top: 4px; padding-top: 8px; border-top: 1px solid var(--divider); font-weight: 700; }
.admin-body #order-modal .od-fault, .admin-body .ir-delivery { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 12px; cursor: pointer; }
.admin-body #order-modal .od-fault input, .admin-body .ir-delivery input { flex: 0 0 auto; width: 22px; height: 22px; margin: 1px 0 0; accent-color: var(--orange-ink); cursor: pointer; }
.admin-body #order-modal .od-fault-text, .admin-body .ir-delivery-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.admin-body #order-modal .od-fault-label, .admin-body .ir-delivery-label { font-size: 15px; font-weight: 700; color: var(--ink); }
.admin-body #order-modal .od-fault-line, .admin-body .ir-delivery-line { font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.admin-body #order-modal .od-refund-all { font-weight: 700; color: var(--ink); }
.admin-body #order-modal .od-note.od-refund-line { margin: 0 0 10px; }
/* red — and as specific as the grey `.od-reason p.od-note` rule it has to beat */
.admin-body #order-modal .od-reason p.od-note.od-msg-error { color: #B3261E; }
/* Batch 6: the Orders tab's "Refund needed" chip count — dark red, white figure, only when above 0. */
.admin-body .filter-pill .chip-count { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; margin-left: 6px; border-radius: 9px; background: #8C1D18; color: #FFFFFF; font-size: 11px; font-weight: 700; line-height: 1; }

/* C2 — the Orders list: fixed columns; below 1232px (batch 6; 1180px before) it scrolls sideways inside its card. */
.admin-body .ord-panel { padding: 8px 0; border-radius: 8px; overflow: hidden; }
.admin-body .ord-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Batch 6: the two pill columns are 150px — the widest pill, "Needs bank details", is 134px in Lato and 148px
   in the fallback font a first visit can get (Lato is font-display: optional) — so the grid is 52px wider:
   the card's width at a 1232px window (1232 − 2×20): below 1232 it scrolls. */
.admin-body .ord-grid { min-width: 1192px; }
.admin-body .ord-row { display: grid; grid-template-columns: 170px 230px 190px minmax(0,1fr) 100px 150px 150px 56px; column-gap: 12px; align-items: center; padding: 14px 24px; border-bottom: 1px solid #F6F6F6; color: #2F2F2F; font-size: 14px; transition: background-color .6s ease; }
.admin-body #orders-table .ord-row:last-child { border-bottom: none; }
.admin-body .ord-head { padding-top: 10px; padding-bottom: 12px; border-bottom: 1px solid #F0F0F0; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: var(--ink-2); }
.admin-body .ord-cell { min-width: 0; }
.admin-body .ord-id, .admin-body .ord-date, .admin-body .ord-total { white-space: nowrap; }
.admin-body .ord-id .order-link { cursor: pointer; font-weight: 700; color: #2F2F2F; white-space: nowrap; }
.admin-body .ord-id .order-link:hover { color: var(--orange-ink); }
.admin-body .ord-name, .admin-body .ord-email { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.admin-body .ord-name { font-weight: 700; color: #2F2F2F; }
.admin-body .ord-email { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.admin-body .ord-items { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #444; }
.admin-body .ord-act { text-align: right; }
.admin-body .ord-act .btn-view { padding: 6px 0; width: 56px; }
/* Batch 7, round 4: EVERY admin action button keeps its label on one line. A row with a longer action than "View" (a payment
   with no matching order: "Mark handled") gives it the Status column too, so the grid's columns — and its no-scroll width
   at 1280px — stay exactly as they are. Existing button styles; nothing new but the layout. */
.admin-body button, .admin-body .btn-view, .admin-body a.od-btn { white-space: nowrap; }
.admin-body .ord-act-wide { grid-column: span 2; }
.admin-body .ord-act-wide .btn-view { width: auto; padding: 6px 12px; }
.admin-body .ord-msg { padding: 18px 24px; color: #6B6B66; font-size: 14px; }

/* C1 — a row the timed refresh changed: #FFF6EE for 4 s (the class is removed after 4 s). */
.admin-body .row-flash, .admin-body tr.row-flash > td { background-color: #FFF6EE !important; }

/* C4/C5 — tab badges. Orange; red when an order confirmation failed. */
.admin-body .admin-tab-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; margin-left: 7px; border-radius: 9px; background: #E07B1F; color: var(--ink); font-size: 11px; font-weight: 700; line-height: 1; vertical-align: middle; }
.admin-body .admin-tab-badge.is-critical { background: #B3261E; color: #FFFFFF; }   /* white on the red (the orange badge's own text is --ink) */

/* C5 — the sound / notification buttons in the top bar (the Logout button's shape). */
.admin-body .admin-nav-btn { background: #FFFFFF; border: 1.5px solid var(--ink-2); color: #2F2F2F; padding: 8px 14px; font: inherit; font-size: 13px; font-weight: 600; border-radius: 8px; cursor: pointer; white-space: nowrap; }
.admin-body .admin-nav-btn:hover { border-color: var(--orange-ink); }
.admin-body .admin-nav-btn[aria-pressed="false"] { color: #6B6B66; }

/* C3 — the pop-up additions. */
.admin-body #order-modal .od-mail-row { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; padding: 10px 12px; border-bottom: 1px solid #F1F0EC; font-size: 14px; }
.admin-body #order-modal .od-mail-act { flex-basis: 100%; text-align: right; }
.admin-body #order-modal .od-mail-why { font-size: 12px; color: #6B6B66; }
.admin-body #order-modal .od-mini-btn { height: 30px; padding: 0 12px; border-radius: 6px; border: 1.5px solid #E07B1F; background: #E07B1F; color: var(--ink); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.admin-body #order-modal .od-mini-btn:disabled { opacity: .6; cursor: not-allowed; }
.admin-body #order-modal .od-btn.primary:hover, .admin-body #order-modal .od-btn.primary:active,
.admin-body #order-modal .od-mini-btn:hover, .admin-body #order-modal .od-mini-btn:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }   /* hover and pressed: --orange-dark, #000 (5.19:1 — follow-up 4) */
.admin-body #order-modal .od-mail-row:last-child { border-bottom: 0; }
.admin-body #order-modal .od-mail-type { font-weight: 700; color: #2F2F2F; }
.admin-body #order-modal .od-mail-state { margin-left: auto; text-align: right; color: #6B6B66; }
.admin-body #order-modal .od-mail-state.is-failed { color: #B3261E; font-weight: 600; }
.admin-body #order-modal .od-reason p.od-note { font-size: 13px; font-weight: 400; color: var(--ink-2); }
.admin-body #order-modal .od-field { display: block; font-size: 13px; font-weight: 700; color: #2F2F2F; }
.admin-body #order-modal .od-field input { margin-top: 6px; }

/* C4 — Email problems. */
.admin-body .ep-banner { margin: 0 0 18px; padding: 12px 16px; border-radius: 8px; font-size: 14px; font-weight: 600; line-height: 1.45; }
.admin-body .ep-banner-critical { background: #FCEBEA; color: #8C1D18; }
.admin-body .ep-banner-attention { background: #FFF4DB; color: var(--amber-ink); }
.admin-body .ep-banner-clear { background: var(--paid-green-bg); color: var(--paid-green); }
/* 130+220+220+160+300 fixed + 5×12 gaps + 48 padding = 1138, plus at least 100px for "What went wrong"
   (fix batch 3: the 160px "When" must not squeeze it to nothing) — narrower, the table scrolls sideways. */
.admin-body .ep-grid { min-width: 1238px; }
.admin-body .ep-row { display: grid; grid-template-columns: 130px 220px 220px minmax(100px,1fr) 160px 300px; column-gap: 12px; align-items: center; padding: 14px 24px; border-bottom: 1px solid #F6F6F6; color: #2F2F2F; font-size: 14px; }
.admin-body .ep-row:last-child { border-bottom: none; }
.admin-body .ep-head { padding-top: 10px; padding-bottom: 12px; border-bottom: 1px solid #F0F0F0; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: var(--ink-2); }
.admin-body .ep-row > div { min-width: 0; }
/* Fix batch 3, item 3: "When" is 160px and never wraps — "29 Sep, 11:35 PM" sits on one line. */
.admin-body .ep-when { white-space: nowrap; }
.admin-body .ep-trunc { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.admin-body .ep-tries { display: block; font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.admin-body .ep-sev { display: inline-flex; align-items: center; justify-content: center; height: 24px; padding: 0 10px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.admin-body .ep-sev-critical { background: #FCEBEA; color: #8C1D18; }
.admin-body .ep-sev-normal { background: #FFF4DB; color: var(--amber-ink); }
.admin-body .ep-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Item 8: the one reason line when Resend is not offered, under the Mark handled button. */
.admin-body .ep-why { flex-basis: 100%; font-size: 12px; line-height: 1.4; color: #6B6B66; }
.admin-body .ep-btn { height: 34px; padding: 0 12px; border-radius: 6px; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; white-space: nowrap; border: 1.5px solid var(--control-edge); background: #FFFFFF; color: #2F2F2F; }
.admin-body .ep-btn.primary { background: #E07B1F; border-color: #E07B1F; color: var(--ink); }
.admin-body .ep-btn.primary:hover, .admin-body .ep-btn.primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }   /* follow-up 4 */
.admin-body .ep-btn:disabled { opacity: .55; cursor: not-allowed; }
.admin-body .ep-note { grid-column: 1 / -1; margin-top: 12px; padding: 14px; border: 1px solid #E5E4E0; border-radius: 8px; background: #FAFAF8; }
.admin-body .ep-note label { display: block; font-size: 13px; font-weight: 700; margin-bottom: 6px; }
.admin-body .ep-note textarea { box-sizing: border-box; width: 100%; min-height: 72px; padding: 10px 12px; border: 1px solid var(--control-edge); border-radius: 8px; font: inherit; font-size: 14px; resize: vertical; }
.admin-body .ep-note textarea:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224,123,31,.18); }
.admin-body .ep-note-row { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.admin-body .ep-note-msg { font-size: 13px; color: #B3261E; }
.admin-body .ep-h2 { margin: 28px 0 4px; font-size: 19px; color: #2F2F2F; }
.admin-body .ep-sub { margin: 0 0 12px; font-size: 13px; color: #6B6B66; }
.admin-body .ep-empty { padding: 18px 24px; color: #6B6B66; font-size: 14px; }

/* C6 — the idle warning: white, 1px --orange-ink border, 8px corners, centred near the top, 560px wide (final colour round). */
.admin-body .idle-banner { position: fixed; top: 24px; left: 50%; transform: translateX(-50%); z-index: 5000; box-sizing: border-box; width: 560px; max-width: calc(100vw - 32px); padding: 18px 22px; background: #FFFFFF; border: 1px solid var(--orange-ink); border-radius: 8px; box-shadow: 0 4px 18px rgba(0,0,0,.06); color: #2F2F2F; }
.admin-body .idle-title { margin: 0 0 14px; font-size: 17px; font-weight: 700; }

/* C7 — the line the sign-in form shows after a sign-out. */
.admin-body .admin-gate-notice { margin: 0 0 14px; padding: 10px 14px; border-radius: 8px; background: #FFF4DB; color: var(--amber-ink); font-size: 14px; font-weight: 600; text-align: left; }

/* ══════════ Marketplace batch 2: staff roles in the console (admin-scoped only — no customer page changes) ══════════
   Who is signed in (the header), role chips (Owner in the brand gold), the Staff tab and its dialog, the Activity log
   and Settings' rows. Every colour is a token above, or the console's own pill values (.ftk-pill). */
/* The header: the name (truncated with "…", never wider than 160px — its title carries it in full) and ONE chip
   (admin-core headerChip). It is the only part of the band's right side that shrinks; the chip and the Sound,
   Notifications and Logout buttons never do. */
.admin-body .admin-who { display: inline-flex; align-items: center; gap: var(--s2); min-width: 0; flex: 0 1 auto; }
.admin-body .admin-who-name { font-size: var(--fs-meta); font-weight: 700; color: var(--gold-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 160px; flex: 0 1 auto; }
.admin-body .admin-who-chip { flex: none; }
.admin-body .admin-nav-right > .admin-nav-btn,
.admin-body .admin-nav-right > .admin-logout-btn { flex: none; white-space: nowrap; }
/* fitHeader's steps, each only when the one before was not enough (in this order). */
.admin-body .admin-nav.hdr-tight { gap: var(--s3); }
.admin-body .admin-nav.hdr-tight .admin-nav-right { gap: var(--s2); }
.admin-body .admin-nav.hdr-no-wordmark .nav-wordmark { display: none; }
.admin-body .admin-nav.hdr-no-pill .admin-pill { display: none; }
.admin-body .admin-nav.hdr-no-name .admin-who-name { display: none; }
.admin-body .admin-nav.hdr-squeeze .admin-nav-row-search { min-width: 0; }
.admin-body .staff-roles { display: inline-flex; flex-wrap: wrap; gap: var(--s1); }
.admin-body .role-chip { display: inline-flex; align-items: center; height: 22px; padding: 0 var(--s2); border-radius: var(--r-pill); border: var(--bw) solid var(--divider); background: var(--surface); color: var(--ink); font-size: 12px; font-weight: 700; line-height: 1; white-space: nowrap; }
.admin-body .role-chip.role-owner { background: var(--gold); border-color: var(--gold-ink); color: var(--gold-ink); }
.admin-body .admin-who .role-chip { background: var(--page); }
.admin-body .admin-who .role-chip.role-owner { background: var(--gold); }
/* ── THE PHONE HEADER (batch 3B fix round) — below 800px, rows that never run past the screen:
     1. the brand, and Logout on the right (a target of at least 44 × 44);
     2. who is signed in — the name, cut short with "…" inside the row, and the role chip;
     3. Sound and Notifications (44px tall);
     4. the search (its own row, as before).
   The right-hand group is "display: contents" here, so its four children take their places in the main row, which wraps.
   From 800px the one-row band above is unchanged. */
@media (max-width: 799.98px) {
    .admin-body .admin-nav-row-main { flex-wrap: wrap; justify-content: flex-start; column-gap: var(--s2); row-gap: var(--s2); }
    .admin-body .admin-nav-row-main > .nav-brand { order: 1; flex: 0 1 auto; min-width: 0; }
    .admin-body .admin-nav-right { display: contents; }
    .admin-body .admin-nav-right > .admin-logout-btn { order: 2; margin-left: auto; min-width: 44px; min-height: 44px; }
    .admin-body .admin-who { display: flex; order: 3; flex: 1 0 100%; min-width: 0; }
    .admin-body .admin-who[hidden] { display: none; }
    .admin-body .admin-who-name { max-width: none; }
    .admin-body .admin-nav-right > .admin-nav-btn { order: 4; min-height: 44px; }
}
/* Below 360px the brand and Logout only share the first row without the "FTK Foods" wordmark — the logo stays (the
   desktop band's own first step, fitHeader's hdr-no-wordmark). */
@media (max-width: 359.98px) { .admin-body .admin-nav .nav-wordmark { display: none; } }

/* Staff status and the Activity log's refused pill — the console's own pill (.ftk-pill) colours. */
.admin-body .ftk-pill-active { background: var(--paid-green-bg); color: var(--paid-green); }
.admin-body .ftk-pill-invited { background: #FFF4DB; color: var(--amber-ink); }
.admin-body .ftk-pill-suspended { background: #FCEBEA; color: #8C1D18; }
.admin-body .ftk-pill-refused { background: #FCEBEA; color: #8C1D18; min-width: 0; height: 22px; padding: 0 var(--s2); font-size: 12px; vertical-align: middle; }

/* The Staff tab */
.admin-body .staff-name { display: block; font-weight: 700; color: var(--ink); }
.admin-body .staff-sub { display: block; margin-top: 2px; font-size: var(--fs-meta); color: var(--ink-2); font-weight: 400; }
.admin-body .staff-when { white-space: nowrap; }
.admin-body .staff-actions { display: flex; flex-wrap: wrap; gap: var(--s2); }
.admin-body .staff-actions .btn-edit,
.admin-body .staff-actions .btn-del { flex: 0 0 auto; padding: 6px var(--s3); font-size: var(--fs-meta); cursor: pointer; }

/* The staff dialog (the console's own modal) */
.admin-body .staff-modal-card { max-width: 560px; max-height: calc(100vh - 40px); display: flex; flex-direction: column; }
.admin-body .staff-modal-card .modal-body { overflow-y: auto; }
.admin-body .stm-label { margin: 0 0 var(--s2); font-size: 14px; font-weight: 700; color: var(--ink); }
.admin-body .stm-label .muted { font-weight: 400; margin-left: var(--s1); }
.admin-body .stm-roles { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
.admin-body .stm-role { display: flex; align-items: flex-start; gap: var(--s2); padding: var(--s3); border: var(--bw) solid var(--divider); border-radius: var(--r-card); cursor: pointer; background: var(--page); }
.admin-body .stm-role:has(input:checked) { border-color: var(--orange-ink); background: rgba(224, 123, 31, .06); }
.admin-body .stm-role input { flex: none; width: 18px; height: 18px; margin: 1px 0 0; }
.admin-body .stm-role-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.admin-body .stm-role-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.admin-body .stm-role-hint { font-size: var(--fs-meta); color: var(--ink-2); line-height: 1.4; }
.admin-body .stm-what-line { margin: 0 0 var(--s2); font-size: 14px; color: var(--ink); line-height: var(--lh-body); }
.admin-body .stm-list { margin: 0 0 var(--s2); padding-left: 20px; font-size: 14px; color: var(--ink); line-height: var(--lh-body); }
.admin-body .stm-list li { margin: 0 0 var(--s1); }
.admin-body .modal-foot .auth-btn.stm-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.admin-body .modal-foot .auth-btn.stm-danger:hover { background: var(--danger); filter: brightness(0.94); }
@media (max-width: 560px) { .admin-body .stm-roles { grid-template-columns: 1fr; } }

/* The Activity log */
.admin-body .al-filters { justify-content: flex-start; align-items: flex-end; }
.admin-body .al-filters .form-group { margin: 0; min-width: 180px; }
.admin-body .al-table tr.al-refused td { background: #FDF3F2; }
.admin-body .al-change { display: block; font-size: var(--fs-meta); }
.admin-body .al-key { color: var(--ink-2); }
.admin-body .al-arrow { color: var(--ink-2); }
.admin-body .al-ip { font-size: var(--fs-meta); color: var(--ink-2); white-space: nowrap; }

/* Settings — one row per part of this person's own sign-in */
.admin-body .set-rows { margin: 0 0 22px; }
.admin-body .set-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); padding: var(--s3) 0; border-top: var(--bw) solid var(--divider); }
.admin-body .set-row-main { min-width: 0; }
.admin-body .set-row-name { margin: 0; font-size: var(--fs-body); font-weight: 700; color: var(--ink); }
.admin-body .set-row-note { margin: 2px 0 0; font-size: var(--fs-meta); color: var(--ink-2); }
.admin-body .set-row .btn-export { flex: 0 0 auto; }
.admin-body .set-row-form { padding: var(--s3) 0; border-top: var(--bw) solid var(--divider); }
.admin-body .set-row-form h3 { margin: 0 0 var(--s2); font-size: 16px; }

/* The set-password page (the gate card) */
.admin-body .ag-link-head { margin: 0 0 var(--s2); font-weight: 700; color: var(--ink); }

/* ═══════════════════════════════════════════════════════════════════════════
   BATCH 3B — THE CONSOLE'S MONEY SCREENS (admin/money-admin.js): Discount codes, Problem reports, the order window's
   Refund items. FTK tokens: orange buttons (--ink on --orange 5.82:1; hover #000 on --orange-dark 5.19:1), secondary
   buttons --ink on white with a --control-edge edge, links --orange-ink (4.99:1), amber notes --amber-ink on #FFF4DB
   (4.53:1), errors #B3261E (6.54:1), grey pills #545450 on #EDEDEA (6.48:1), success --paid-green (5.37:1).
   Buttons 48px (small 36px), radius 6; cards and fields 8; pills 999. Phones: the report list stacks over the report.
   ═══════════════════════════════════════════════════════════════════════════ */
.admin-body .mn-btn {
    display: inline-flex; align-items: center; justify-content: center; min-height: 48px; padding: 0 18px; box-sizing: border-box;
    border-radius: var(--r-btn); border: 1px solid transparent; font-family: inherit; font-size: 15px; font-weight: 700; line-height: 1.2; cursor: pointer;
}
.admin-body .mn-btn-small { min-height: 36px; padding: 0 12px; font-size: 14px; }
.admin-body .mn-btn-primary { background: var(--orange); border-color: var(--orange); color: var(--ink); }
.admin-body .mn-btn-primary:hover, .admin-body .mn-btn-primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
.admin-body .mn-btn-secondary { background: #fff; border-color: var(--control-edge); color: var(--ink); }
.admin-body .mn-btn-secondary:hover { border-color: var(--orange-ink); color: var(--orange-ink); }
.admin-body .mn-btn:disabled { opacity: .55; cursor: not-allowed; }
.admin-body .mn-btn:focus-visible, .admin-body .mn-link:focus-visible, .admin-body .pr-item:focus-visible, .admin-body .ir-step:focus-visible { outline: 3px solid var(--orange-ink); outline-offset: 2px; }
.admin-body .mn-link { padding: 0; border: 0; background: none; color: var(--orange-ink); font: inherit; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; min-height: 24px; }
.admin-body .mn-row-acts { display: flex; flex-wrap: wrap; gap: 8px; }
.admin-body .mn-pill-grey { background: #EDEDEA; color: #545450; }
.admin-body .ftk-pill.mn-pill-small { min-width: 0; height: 22px; padding: 0 10px; font-size: 12px; }
.admin-body .mn-err { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: #B3261E; }
.admin-body .mn-err[hidden], .admin-body .mn-amber[hidden], .admin-body .mn-form-panel[hidden], .admin-body .od-items-refund[hidden] { display: none; }
.admin-body .mn-amber { margin: 0 0 12px; padding: 10px 12px; border-radius: var(--r-card); background: #FFF4DB; color: var(--amber-ink); font-size: 14px; font-weight: 700; line-height: 1.45; }
.admin-body .mn-note { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.admin-body .mn-empty { margin: 0; padding: 16px; }
.admin-body .mn-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.admin-body .mn-count { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; margin-left: 6px; padding: 0 6px; border-radius: 999px; background: rgba(26, 26, 26, .08); font-size: 12px; font-weight: 700; }
.admin-body .mn-confirm { margin: 12px 0 0; padding: 14px; border: 1px solid var(--divider); border-radius: var(--r-card); background: var(--surface); }
.admin-body .mn-confirm-q { margin: 0 0 12px; font-size: 15px; font-weight: 700; line-height: 1.45; color: var(--ink); }
.admin-body .mn-confirm-acts { display: flex; flex-wrap: wrap; gap: 10px; }
.admin-body .mn-confirm-row td { background: var(--surface); }
.admin-body .mn-confirm-row .mn-confirm { margin: 0; border: 0; padding: 4px 0; background: none; }
.admin-body .mn-fields { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 0 4px; }
.admin-body .mn-field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 700; color: var(--ink); flex: 1 1 200px; min-width: 0; }
.admin-body .mn-field input, .admin-body .mn-textarea {
    font-family: inherit; font-size: 15px; min-height: 48px; padding: 0 12px; box-sizing: border-box; width: 100%;
    border: 1px solid var(--control-edge); border-radius: var(--r-card); background: #fff; color: var(--ink);
}
.admin-body .mn-textarea { display: block; padding: 10px 12px; line-height: 1.5; resize: vertical; margin-top: 6px; }
.admin-body .mn-field input:focus, .admin-body .mn-textarea:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
.admin-body .mn-count-line, .admin-body .mn-confirm .mn-count { display: block; margin: 4px 0 10px; text-align: right; background: none; font-weight: 400; color: var(--ink-2); }

/* Discount codes */
.admin-body .mn-form-panel { padding: 18px; margin-bottom: 16px; }
.admin-body .mn-form-title { margin: 0 0 12px; font-size: 18px; font-weight: 700; color: var(--ink); }
.admin-body .mn-form-grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
@media (min-width: 720px) { .admin-body .mn-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .admin-body .mn-form-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.admin-body .mn-field-box { display: flex; flex-direction: column; min-width: 0; }
.admin-body .mn-label { margin: 0 0 6px; font-size: 13px; font-weight: 700; color: var(--ink); }
.admin-body .mn-field-box .admin-input { width: 100%; box-sizing: border-box; }
.admin-body .mn-field-box .admin-input[aria-invalid="true"] { border-color: #B3261E; }
.admin-body .mn-field-box .admin-input:disabled { background: var(--surface); color: var(--ink-2); }
.admin-body .mn-code-input { text-transform: uppercase; }
.admin-body .mn-sentence { margin: 16px 0 12px; padding: 12px; border-radius: var(--r-card); background: var(--surface); font-size: 15px; line-height: 1.5; color: var(--ink); }
.admin-body .dc-code { font-weight: 700; letter-spacing: .02em; }

/* Problem reports */
.admin-body .pr-filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.admin-body .pr-layout { display: grid; grid-template-columns: 1fr; gap: 14px; align-items: start; }
@media (min-width: 960px) { .admin-body .pr-layout { grid-template-columns: minmax(260px, 340px) minmax(0, 1fr); } }
.admin-body .pr-list { padding: 6px; }
.admin-body .pr-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.admin-body .pr-item {
    display: flex; flex-direction: column; gap: 4px; width: 100%; padding: 10px 12px; box-sizing: border-box; text-align: left;
    border: 1px solid transparent; border-radius: var(--r-card); background: #fff; font: inherit; color: var(--ink); cursor: pointer; min-height: 48px;
}
.admin-body .pr-item:hover { border-color: var(--divider); background: var(--surface); }
.admin-body .pr-item.is-current { border: 2px solid var(--orange-ink); padding: 9px 11px; background: rgba(224, 123, 31, .06); }
.admin-body .pr-item-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.admin-body .pr-item-num { font-weight: 700; font-size: 15px; }
.admin-body .pr-item-who { font-size: 14px; overflow-wrap: anywhere; }
.admin-body .pr-item-meta { font-size: 13px; color: var(--ink-2); }
.admin-body .pr-detail { padding: 18px; min-width: 0; }
.admin-body .pr-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 0 0 12px; }
.admin-body .pr-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); }
.admin-body .pr-title:focus { outline: none; }
.admin-body .pr-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px 16px; margin: 0 0 16px; }
.admin-body .pr-facts dt { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); }
.admin-body .pr-facts dd { margin: 2px 0 0; font-size: 15px; color: var(--ink); overflow-wrap: anywhere; }
.admin-body .pr-sub { display: block; font-size: 13px; color: var(--ink-2); }
/* Its own plain table (not .admin-table, whose phone rules stack every row into a card): three short columns fit at 320px. */
.admin-body .pr-table { width: 100%; border-collapse: collapse; font-size: 14px; color: var(--ink); }
.admin-body .pr-table th { padding: 8px; text-align: left; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); border-bottom: 1px solid var(--divider); }
.admin-body .pr-table td { padding: 10px 8px; border-bottom: 1px solid var(--divider); vertical-align: top; overflow-wrap: anywhere; }
.admin-body .pr-table th.mn-num, .admin-body .pr-table td.mn-num { text-align: right; }
.admin-body .pr-table tfoot td { font-weight: 700; border-bottom: 0; }
.admin-body .pr-h3 { margin: 18px 0 8px; font-size: 15px; font-weight: 700; color: var(--ink); }
.admin-body .pr-photos { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.admin-body .pr-photo { display: block; width: 160px; height: 160px; object-fit: cover; border-radius: var(--r-card); border: 1px solid var(--divider); background: var(--surface); }
.admin-body .pr-photo.is-broken { font-size: 12px; color: var(--ink-2); }
.admin-body .pr-note { margin: 0; font-size: 15px; line-height: 1.5; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.admin-body .pr-outcome { margin: 16px 0 0; font-size: 14px; font-weight: 700; color: var(--ink); }
.admin-body .pr-acts { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0 0; }

/* Refund items (the order window) */
.admin-body #order-modal .od-items-refund { margin-top: 4px; }
.admin-body #order-modal .ir-lines { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.admin-body #order-modal .ir-line { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; border: 1px solid var(--divider); border-radius: var(--r-card); }
.admin-body #order-modal .ir-line-text { display: flex; flex-direction: column; min-width: 0; }
.admin-body #order-modal .ir-line-name { font-size: 15px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.admin-body #order-modal .ir-line-sub { font-size: 13px; color: var(--ink-2); }
.admin-body #order-modal .ir-stepper { flex: 0 0 auto; display: inline-flex; align-items: center; border: 1px solid var(--control-edge); border-radius: var(--r-btn); overflow: hidden; }
.admin-body #order-modal .ir-step { width: 36px; height: 36px; padding: 0; border: 0; background: #fff; color: var(--orange-ink); font-family: inherit; font-size: 18px; font-weight: 700; cursor: pointer; }
.admin-body #order-modal .ir-step:disabled { color: #8A8A84; cursor: not-allowed; }
.admin-body #order-modal .ir-step-val { min-width: 32px; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.admin-body #order-modal .ir-reason { max-width: 320px; margin: 0 0 12px; }
/* The refund status batch: the summary under the pick (Part 5.20) — Items · Delivery fee · Paystack fee the customer paid ·
   Customer gets back — in the order window and a problem report's refund. */
.admin-body .ir-summary { margin: 0 0 6px; padding: 10px 12px; border: 1px solid var(--divider); border-radius: var(--r-card); background: #fff; }
.admin-body .ir-sum-row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 14px; color: var(--ink); }
.admin-body .ir-sum-row > span:last-child { white-space: nowrap; font-variant-numeric: tabular-nums; text-align: right; }
.admin-body .ir-sum-total { margin-top: 4px; padding-top: 8px; border-top: 1px solid var(--divider); font-size: 16px; font-weight: 800; }
.admin-body .ir-fee-line { margin: 4px 0 12px; }
.admin-body .mn-confirm .ir-summary { margin-bottom: 6px; }
.admin-body .mn-confirm .ir-fee-line + .mn-confirm-q { margin-top: 12px; }
.admin-body #order-modal .ir-success { margin: 0 0 12px; padding: 10px 12px; border-radius: var(--r-card); background: var(--paid-green-bg); color: var(--paid-green); font-size: 14px; font-weight: 700; }
/* The refund status batch — "Refunds on this order" (Part 8.25): every refund, newest first; its pill wraps on a phone. */
.admin-body #order-modal .od-refund-list { margin: 0 0 18px; }
.admin-body #order-modal .rl-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.admin-body #order-modal .rl-row { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; border-top: 1px solid var(--divider); }
.admin-body #order-modal .rl-main { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; font-weight: 700; color: var(--ink); }
.admin-body #order-modal .rl-what { overflow-wrap: anywhere; min-width: 0; }
.admin-body #order-modal .rl-amt { white-space: nowrap; font-variant-numeric: tabular-nums; }
.admin-body #order-modal .rl-meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; font-size: 13px; color: var(--ink-2); }
.admin-body #order-modal .rl-pill { min-width: 0; height: auto; min-height: 26px; padding: 4px 12px; white-space: normal; text-align: center; }
.admin-body #order-modal .rl-act .mn-note { margin-top: 6px; }
.admin-body #order-modal .rl-bank { margin: 0; color: var(--ink); }
/* The refund fix round, fix 2: a refund made in Paystack's dashboard that matches a failed one says so, in red (a warning
   only); fix 3: a refused email re-send stays under the emails. */
.admin-body #order-modal .rl-warn { margin: 0; color: #B3261E; font-size: 13px; font-weight: 700; line-height: 1.4; overflow-wrap: anywhere; }
.admin-body #order-modal .od-mail-err { margin: 0; padding: 8px 12px 10px; color: #B3261E; }
/* The refund fix round 3, fix 2: "This was a retry of the failed ₦X refund", its in-page confirmation, and the linked line */
.admin-body #order-modal .rl-link-confirm { margin: 4px 0 0; }
.admin-body #order-modal .rl-linked { margin: 0; color: var(--ink-2); }
/* fix round 4, fix 4: "Made in Paystack" — a neutral grey pill beside the refund's status pill */
.admin-body .ftk-pill-madeinpaystack { background: #EEEDE9; color: #3F3F3B; }
.admin-body #order-modal .rl-pills { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; min-width: 0; }

/* ══ PASSKEYS (passkeys spec Part B) ══════════════════════════════════════════════════════════════
   The storefront's sign-in button, the "Sign in faster next time" card, the Login & security Passkeys
   card and the "Use a passkey instead" links (scoped body:not(.admin-body) — this file is copied into
   the console), then the console's own sign-in button and Settings section (.admin-body, the console's
   look). Tokens wherever one exists: --orange / --orange-dark, --ink / --ink-2, --divider, --surface,
   --danger, and --paid-green / --paid-green-bg for the "Passkey created" tick. Append-only. */
.pk-ico { flex: none; display: block; }

/* Sign in (account.html): the fields are a <form> that keeps the card's 24px rhythm; then "or" and the
   full-width outline button. Its 1px #8A8A85 border is the sign-in inputs' own (.authf-input). */
body:not(.admin-body) .authf-form { display: flex; flex-direction: column; gap: 24px; margin: 0; }
body:not(.admin-body) .authf-passkey { display: flex; flex-direction: column; gap: 16px; }
body:not(.admin-body) .authf-passkey[hidden] { display: none; }
/* Drawn from the first frame on a browser that can use passkeys (passkeys.js marks <html> in <head>), never on one that cannot. */
html:not(.pk-supported) body:not(.admin-body) .authf-passkey { display: none; }
body:not(.admin-body) .authf-or { display: flex; align-items: center; gap: 12px; margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
body:not(.admin-body) .authf-or::before,
body:not(.admin-body) .authf-or::after { content: ""; flex: 1; border-top: 1px solid var(--divider); }
body:not(.admin-body) .authf-btn-outline {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    height: 48px; width: 100%; border: 1px solid #8A8A85; border-radius: 6px; background: #fff;
    color: var(--ink); font-size: 15px; font-weight: 700; font-family: inherit; cursor: pointer;
}
body:not(.admin-body) .authf-btn-outline:hover { background: var(--surface); }
body:not(.admin-body) .authf-btn-outline:disabled { opacity: .6; cursor: default; }
body:not(.admin-body) .authf-btn-outline:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }

/* "Sign in faster next time" — once, at the top of the page a password sign-in lands on (never checkout).
   The icon's soft circle is the orange at 12% on white (#FBEFE4; no token holds a tint of it). */
body:not(.admin-body) .pk-offer {
    box-sizing: border-box; width: calc(100% - 32px); max-width: 720px; margin: 16px auto 0;
    display: flex; flex-direction: column; gap: 16px; padding: 16px;
    border: 1px solid var(--divider); border-radius: var(--r-card); background: #fff;
}
body:not(.admin-body) #account > .pk-offer { width: 100%; }
body:not(.admin-body) .pk-offer-body { display: flex; align-items: flex-start; gap: 12px; }
body:not(.admin-body) .pk-offer-ic { flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: #FBEFE4; color: var(--orange-dark); }
body:not(.admin-body) .pk-offer-ic-done { background: var(--paid-green-bg); color: var(--paid-green); }
body:not(.admin-body) .pk-offer-text { min-width: 0; }
body:not(.admin-body) .pk-offer-title { margin: 0; font-size: var(--fs-head); font-weight: 700; line-height: var(--lh-head); color: var(--ink); }
body:not(.admin-body) .pk-offer-sub { margin: 4px 0 0; color: var(--ink-2); }
body:not(.admin-body) .pk-offer-msg { margin: 8px 0 0; font-size: var(--fs-meta); color: #c0392b; }
body:not(.admin-body) .pk-offer-msg[hidden] { display: none; }
body:not(.admin-body) .pk-offer-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
body:not(.admin-body) .pk-btn {
    min-height: 44px; padding: 0 16px; border-radius: 8px; border: 1px solid transparent;
    font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer;
}
body:not(.admin-body) .pk-btn-primary,
html.pa-nodev body:not(.admin-body) #pa-twostep { background: var(--orange); border-color: var(--orange); color: var(--ink); }
body:not(.admin-body) .pk-btn-primary:hover, html.pa-nodev body:not(.admin-body) #pa-twostep:hover, body:not(.admin-body) .pk-btn-primary:active, html.pa-nodev body:not(.admin-body) #pa-twostep:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
body:not(.admin-body) .pk-btn-outline { background: #fff; border-color: var(--control-edge); color: var(--ink); }
body:not(.admin-body) .pk-btn-outline:hover { background: var(--surface); }
body:not(.admin-body) .pk-btn:disabled { opacity: .6; cursor: default; }

/* Login & security → Passkeys: one bordered card per passkey (like the Devices cards), a red-text Remove
   with its confirm inside the card, the "+ Add a passkey" button (like "+ Add an address"). */
body:not(.admin-body) .pk-list { display: flex; flex-direction: column; gap: 8px; margin: 0 0 var(--s4); }
/* "Checking…" in exactly the room of the "You have no passkeys" line: an invisible copy of that line in the same grid
   cell (account-passkeys.js WAIT), so a list that arrives with none moves nothing. */
body:not(.admin-body) .pk-wait { display: grid; }
body:not(.admin-body) .pk-wait > * { grid-area: 1 / 1; }
body:not(.admin-body) .pk-wait-room { visibility: hidden; }
body:not(.admin-body) .pk-item { border: 1px solid var(--divider); border-radius: 8px; padding: 12px 14px; background: #fff; }
body:not(.admin-body) .pk-item-row { display: flex; align-items: center; gap: var(--s3); }
body:not(.admin-body) .pk-item-ic { flex: none; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; background: var(--surface); color: var(--ink); }
body:not(.admin-body) .pk-item-main { flex: 1 1 auto; min-width: 0; }
body:not(.admin-body) .pk-item-name { font-size: 15px; font-weight: 700; color: var(--ink); word-break: break-word; }
body:not(.admin-body) .pk-item-meta { margin-top: 2px; font-size: 13px; color: var(--ink-2); }
body:not(.admin-body) .pk-remove { flex: none; min-height: 44px; padding: 0 8px; border: 0; background: transparent; color: var(--danger); font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer; }
body:not(.admin-body) .pk-remove:hover { text-decoration: underline; }
body:not(.admin-body) .pk-remove[hidden] { display: none; }
body:not(.admin-body) .pk-item-confirm { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--divider); }
body:not(.admin-body) .pk-item-q { margin: 0; font-size: 14px; color: var(--ink); }
body:not(.admin-body) .pk-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s2); margin-top: var(--s3); }
body:not(.admin-body) .pk-empty { margin: 0; font-size: 14px; color: var(--ink-2); }
body:not(.admin-body) .pk-add-wrap[hidden] { display: none; }
body:not(.admin-body) .pk-add {
    display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 16px;
    background: #fff; border: 1px solid var(--divider); border-radius: 8px; color: var(--orange-ink);
    font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer;
}
body:not(.admin-body) .pk-add:hover { background: var(--surface); border-color: var(--orange-ink); }
body:not(.admin-body) .pk-add[hidden] { display: none; }
body:not(.admin-body) .pk-add-plus { font-size: 18px; line-height: 1; }
body:not(.admin-body) .pk-limit { margin: 0; font-size: 14px; color: var(--ink-2); }
body:not(.admin-body) .pk-confirm-title { margin: 0 0 4px; font-size: var(--fs-head); font-weight: 700; line-height: var(--lh-head); color: var(--ink); }
body:not(.admin-body) .pk-confirm .authf-field { margin-top: var(--s3); }
body:not(.admin-body) .pk-note { margin: var(--s4) 0 0; font-size: 13px; color: var(--ink-2); }
body:not(.admin-body) .pk-foot { display: flex; justify-content: flex-end; }
body:not(.admin-body) #pk-msg:empty { display: none; margin: 0; }
/* "Use a passkey instead" — under every password re-check, only when the account has a passkey. */
body:not(.admin-body) .pk-instead { margin: 6px 0 0; }
body:not(.admin-body) .pk-instead[hidden] { display: none; }
body:not(.admin-body) .pk-link { padding: 0; border: 0; background: none; color: var(--orange-ink); font-size: 14px; font-weight: 700; font-family: inherit; text-decoration: underline; cursor: pointer; }

/* The console (rules 17–18): "or" and "Sign in with a passkey" under Sign In (the console's own
   secondary button); Settings → Passkeys, each with Remove (the console's destructive button). */
.admin-body .ag-passkey { margin-top: 18px; }
/* Drawn from the first frame on a browser that can use passkeys (admin/passkey-support.js marks <html> in <head>), never on one that cannot. */
html:not(.pk-supported) .admin-body .ag-passkey { display: none; }
.admin-body .ag-or { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; color: var(--ink-2); font-size: 13px; }
.admin-body .ag-or::before,
.admin-body .ag-or::after { content: ""; flex: 1; border-top: 1px solid var(--divider); }
.admin-body .ag-passkey-btn { display: flex; align-items: center; justify-content: center; gap: 8px; }
.admin-body .apk-list { display: flex; flex-direction: column; gap: 10px; margin: 0 0 14px; }
/* Settings → Passkeys: "Checking…" in exactly the room of the "No passkeys yet" line — an invisible copy of that line
   in the same grid cell (ops-console-3dacfcbd19.js APK_WAIT), so a list that arrives with none moves nothing. */
.admin-body .apk-wait { display: grid; }
.admin-body .apk-wait > * { grid-area: 1 / 1; }
.admin-body .apk-wait-room { visibility: hidden; }
.admin-body .apk-item { border: 1px solid var(--divider); border-radius: 10px; padding: 12px 14px; }
.admin-body .apk-row { display: flex; align-items: center; gap: 12px; }
.admin-body .apk-ic { flex: none; color: var(--ink); }
.admin-body .apk-main { flex: 1 1 auto; min-width: 0; }
.admin-body .apk-name { font-size: 15px; font-weight: 700; color: #1a1a1a; word-break: break-word; }
.admin-body .apk-meta { margin-top: 2px; font-size: 13px; color: #6B6B66; }
.admin-body .apk-row .btn-del { flex: none; padding: 8px 14px; border-radius: 8px; font-weight: 700; cursor: pointer; }
.admin-body .apk-confirm { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--divider); }
.admin-body .apk-confirm p { margin: 0 0 10px; font-size: 14px; color: #1a1a1a; }
.admin-body .apk-actions { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
.admin-body .apk-actions .auth-btn { width: auto; margin: 0; padding: 10px 16px; }
.admin-body .apk-actions .btn-del { padding: 10px 16px; border-radius: 10px; font-weight: 700; cursor: pointer; }
.admin-body .apk-empty { margin: 0 0 14px; color: #6B6B66; font-size: 14px; }
.admin-body .apk-add-confirm h3 { margin: 0 0 10px; font-size: 16px; }
.admin-body .apk-msg { margin: 10px 0 0; font-size: 13px; color: #B3261E; }
.admin-body .apk-msg:empty { display: none; }
/* Settings → Change Admin Password: the line a wrong current password leaves (passkeys follow-up, Fix 5). */
.admin-body .set-msg { margin: 10px 0 0; font-size: 13px; color: #B3261E; }
.admin-body .set-msg:empty { display: none; }


/* ═══════════════════════════════════════════════════════════════════════════════════════════════════════
   CATEGORIES BATCH B + DESKTOP WIDTH — the storefront's departments and categories (the "All" menu, the
   homepage's headline panels and sections, the department / category / "All categories" pages) and the
   laptop layout at the full window width (the approved prototypes ftk-categories-approved.html and
   ftk-desktop-width-approved.html). "Laptop" is 900px and up. Every rule is scoped to the storefront
   (body:not(.admin-body)) — the ops console takes its whole look from this file. Existing tokens only.
   Below 900px only the new parts apply (the "All" button and panel, the homepage, the new pages, the
   category breadcrumb, and at 360px and below the header's wordmark giving the button its room); every other
   page draws on a phone exactly as before.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── THE COLUMN LADDER as a number, for the rows (the grid's own ladder is section 3 above) ── */
@media (min-width: 900px)  { body:not(.admin-body) { --cols: 4; } }
@media (min-width: 1200px) { body:not(.admin-body) { --cols: 5; } }
@media (min-width: 1440px) { body:not(.admin-body) { --cols: 6; } }
@media (min-width: 1700px) { body:not(.admin-body) { --cols: 7; } }
@media (min-width: 2000px) { body:not(.admin-body) { --cols: 8; } }
@media (min-width: 2300px) { body:not(.admin-body) { --cols: 9; } }

/* ── A · PAGE WIDTH. The homepage, department, category, "All categories", search and product pages fill
   the window with the shell's 20px gutter: the 720px cap on <main> (the PAGE SHELL rule) stops applying to
   them from 900px. Their inner boxes drop their own side padding, so every heading, row and grid on the page
   starts at the same left edge. The product page alone stops growing at 1500px and centres (#pp-root). ── */
@media (min-width: 900px) {
    body:not(.admin-body) main.home,
    body:not(.admin-body) main.cat-page,
    body:not(.admin-body) main.dept-page,
    body:not(.admin-body) main.pp {
        max-width: none;
        margin-left: 0;
        margin-right: 0;
        padding-left: var(--shell-pad);
        padding-right: var(--shell-pad);
    }
    body:not(.admin-body) main.cat-page .cat-head,
    body:not(.admin-body) main.dept-page .cat-head { padding-left: 0; padding-right: 0; }
    body:not(.admin-body) main.cat-page .products { padding-left: 0; padding-right: 0; }
}

/* ── C · THE HEADER: the menu buttons, the grey strip under the gold band, and the side panel ──
   THE GOLD BAND is the live header, unchanged (the HEAD rules above: the same height, padding, logo, wordmark,
   search, "Sign in ›" and cart). The only thing categories batch B adds inside it is the phone's ☰ (#nav-all — 26px,
   no word, "Open menu"), in front of the logo; on a laptop it is not shown.
   THE GREY STRIP (.nav-strip) sits directly under the gold band — no gap, no line — in the footer's "Top of page"
   grey (--surface), the second and last colour band of the header. It replaced the old separate delivery bar.
   Phone: 36px, the map pin and "Delivery across Nigeria" alone, centred. Laptop: 40px, the full window width with
   20px each side — "☰ All", "Best Sellers", "Customer Service" on the left, the delivery line on the right. Both ☰
   buttons open the same panel (shop-nav.js). Checkout has neither the ☰ nor the strip. */
body:not(.admin-body) .navbar .nav-all {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    min-width: 44px; min-height: 44px; padding: 0; margin: 0;
    background: none; border: 0; cursor: pointer; color: var(--gold-ink);
}
body:not(.admin-body) .navbar .nav-all-ico { width: 26px; height: 26px; display: block; }
@media (max-width: 899px) {
    /* the brand keeps its place next to the button; the account and cart stay at the right */
    body:not(.admin-body) .navbar .nav-row-main .nav-brand { margin-right: auto; }
}
@media (max-width: 360px) {
    /* The narrowest phones have no room for the button, the logo, the wordmark, "Sign in" and the cart on one row
       (at 320px the wordmark was cut to "FTK Fo…" against "Sign in"): the logo stands alone there, as the categories
       prototype draws every phone header. 361px and up keep the wordmark. */
    body:not(.admin-body) .navbar .nav-row-main .nav-wordmark { display: none; }
}
@media (min-width: 900px) {
    body:not(.admin-body) .navbar .nav-row-main .nav-all { display: none; }
}
body:not(.admin-body) .nav-strip {
    display: flex; align-items: center; justify-content: center;
    height: 36px; padding: 0 var(--s4); margin: 0; box-sizing: border-box;
    background: var(--surface); border: 0;
}
body:not(.admin-body) .nav-strip-links { display: none; }
body:not(.admin-body) .nav-strip-deliv {
    display: inline-flex; align-items: center; gap: 6px; margin: 0;
    font-size: 14px; line-height: 1.2; color: var(--ink-2); white-space: nowrap;
}
body:not(.admin-body) .nav-strip-pin { width: 16px; height: 16px; flex: none; display: block; }
@media (min-width: 900px) {
    body:not(.admin-body) .nav-strip { height: 40px; padding: 0 var(--shell-pad); justify-content: space-between; }
    body:not(.admin-body) .nav-strip-links { display: flex; align-items: center; gap: var(--s1); }
    body:not(.admin-body) .nav-strip-item {
        display: inline-flex; align-items: center; gap: 6px; margin: 0;
        padding: 7px 10px; border: 1px solid transparent; border-radius: 6px;
        background: none; cursor: pointer; text-decoration: none;
        font: inherit; font-size: 14px; font-weight: 700; line-height: 1.2; color: var(--ink);
    }
    body:not(.admin-body) .nav-strip-item:hover { border-color: var(--ink); }
    body:not(.admin-body) .nav-strip-ico { width: 18px; height: 18px; display: block; }
}
/* the Account Center's strip follows its header: a laptop with the Account Center open (signed in) only */
body:not(.admin-body) .nav-strip.nav-strip-acct { display: none; }
@media (min-width: 900px) { body:not(.admin-body):has(main#account.acct-shell) .nav-strip.nav-strip-acct { display: flex; } }

/* the page behind the open menu does not scroll (body's overflow reaches the window: no rule sets html's) */
body:not(.admin-body).all-open { overflow: hidden; }
body:not(.admin-body) .all-scrim {
    position: fixed; inset: 0; z-index: 1400;
    display: flex; align-items: stretch;
    background: rgba(16, 24, 20, .45);   /* the account menu's scrim */
}
body:not(.admin-body) .all-scrim[hidden] { display: none; }
body:not(.admin-body) .all-panel {
    width: min(360px, calc(100vw - 56px)); height: 100%;
    display: flex; flex-direction: column; overflow-y: auto; overscroll-behavior: contain;
    background: #fff; outline: none;
    padding-bottom: env(safe-area-inset-bottom, 0px);
}
body:not(.admin-body) .all-top {
    padding: calc(18px + env(safe-area-inset-top, 0px)) 18px 18px;
    background: var(--ink); color: #fff; font-size: 18px; font-weight: 700;
}
body:not(.admin-body) .all-hello { color: #fff; text-decoration: none; }
body:not(.admin-body) a.all-hello:hover { text-decoration: underline; }
body:not(.admin-body) .all-body { display: flex; flex-direction: column; padding-bottom: var(--s4); }
body:not(.admin-body) .all-h { margin: 0; padding: 16px 18px 6px; font-size: 17px; font-weight: 700; color: var(--ink); outline: none; }
body:not(.admin-body) .all-row {
    display: flex; justify-content: space-between; align-items: center; gap: 12px;
    width: 100%; min-height: 44px; padding: 12px 18px; margin: 0;
    background: #fff; border: 0; border-radius: 0; cursor: pointer; text-align: left; text-decoration: none;
    font: inherit; font-size: 15px; color: var(--ink);
}
body:not(.admin-body) .all-row:hover { background: var(--surface); }
body:not(.admin-body) .all-chev { width: 18px; height: 18px; flex: none; color: var(--ink-2); }
body:not(.admin-body) .all-back { font-weight: 700; border-bottom: 1px solid var(--divider); }
body:not(.admin-body) .all-row-all { margin-top: var(--s2); border-top: 1px solid var(--divider); font-weight: 700; }
body:not(.admin-body) .all-note { margin: 0; padding: 16px 18px 8px; color: var(--ink-2); font-size: 15px; }
body:not(.admin-body) .all-x {
    align-self: flex-start; flex: none; margin: calc(10px + env(safe-area-inset-top, 0px)) 10px 10px;
    width: 44px; height: 44px; padding: 0; border: 0; border-radius: 999px;
    background: #fff; color: var(--ink); font-size: 20px; line-height: 1; cursor: pointer;
}

/* ── B · THE HOMEPAGE: the headline panels row, then the admin's sections ── */
/* ── A PAGE THAT FILLS IN AFTER IT LOADS — the homepage, a department, "All categories", a category, search, Best
   Sellers, a product and the cart (page-load layout shift, the "footer jump"). Its own content area is aria-busy="true" in the page itself
   until its script has drawn what arrived (or the error, or not-found) and sets it to "false" (ftkPageFilled). While it
   is busy:
     • a full screen of room is held under that area, so the footer starts below the screen, and the footer waits
       unseen: the arriving content pushes nothing anyone can see, and the footer appears once, in its final place.
       The room goes with the wait, so a page with little content has no gap. It is room UNDER the area, not a
       min-height on it: several of these areas are grids, whose rows would stretch into a min-height and then move
       back when it went;
     • a heading line that is still empty — the breadcrumb, the name, the product count, search's "N products
       matching …" — keeps the one line it is about to hold, so what is under it does not move when its words arrive;
     • the cart shows nothing until its list is first drawn (a frame or two after the page appears).
   Nothing is drawn in that room or in those lines — no placeholder, no spinner. Should a page's script never run, the
   footer and the cart show after 8 seconds. ── */
body:not(.admin-body) main[aria-busy="true"],
body:not(.admin-body) #cart[aria-busy="true"] { margin-bottom: 100vh; }
body:not(.admin-body) main[aria-busy="true"] ~ .site-footer,
body:not(.admin-body) #cart[aria-busy="true"] ~ .site-footer,
body:not(.admin-body) #cart[aria-busy="true"]:has(#cart-items:empty) .cart-main { visibility: hidden; animation: ftk-show-late 0s linear 8s forwards; }
body:not(.admin-body) main[aria-busy="true"] .cat-crumb:empty,
body:not(.admin-body) main[aria-busy="true"] .cat-name:empty,
body:not(.admin-body) main[aria-busy="true"] .cat-count:empty,
body:not(.admin-body) main[aria-busy="true"] .grid-count:empty { display: block; min-height: 1lh; }
body:not(.admin-body) main.home { display: flex; flex-direction: column; gap: var(--s6); padding-top: var(--s4); padding-bottom: var(--s6); }
body:not(.admin-body) .home-secs { display: flex; flex-direction: column; gap: var(--s6); }
body:not(.admin-body) .home-secs:empty { display: none; }   /* no sections: no empty gap under the panels */
body:not(.admin-body) .home-hero[hidden] { display: none; }
body:not(.admin-body) .hero-track {
    display: flex; gap: 12px;
    overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
body:not(.admin-body) .hero-track::-webkit-scrollbar { display: none; }
/* A panel has a FIXED size — it never stretches to fill the row. Laptop: 3 a screen at 900–1199px, 4 at 1200–1439px,
   5 from 1440px; width = (row width − the 12px gaps) ÷ that number, height from 5:8 (width:height). Fewer panels than
   fit keep that width and start at the left; more than fit scroll with the arrows. Phone: 70% of the width, 4:5,
   swiped, the next one peeking in. Inside: the photo fills the bottom 76% (cover); the top 24% is the light surface
   tint, and a gradient from that tint to transparent runs from the 24% line across 14% of the panel's height. The
   headline (real text, ink, 900) sits 18px from the top and each side. "Shop now" sits on the photo, bottom-left — a
   span inside the panel's one link, not a second link. */
body:not(.admin-body) .hero-panel {
    position: relative; display: block; flex: 0 0 70%; max-width: 100%; aspect-ratio: 4 / 5;
    border-radius: 10px; overflow: hidden; scroll-snap-align: start;
    background: var(--surface); color: var(--ink); text-decoration: none;
}
@media (min-width: 900px)  { body:not(.admin-body) .hero-panel { flex-basis: calc((100% - 2 * 12px) / 3); aspect-ratio: 5 / 8; } }
@media (min-width: 1200px) { body:not(.admin-body) .hero-panel { flex-basis: calc((100% - 3 * 12px) / 4); } }
@media (min-width: 1440px) { body:not(.admin-body) .hero-panel { flex-basis: calc((100% - 4 * 12px) / 5); } }
body:not(.admin-body) .hero-panel-h {
    position: absolute; z-index: 2; left: 18px; right: 18px; top: 18px;
    font-size: 22px; line-height: 1.1; font-weight: 900; color: var(--ink);
    text-wrap: balance; overflow-wrap: anywhere;
}
@media (min-width: 900px)  { body:not(.admin-body) .hero-panel-h { font-size: 26px; } }
@media (min-width: 1440px) { body:not(.admin-body) .hero-panel-h { font-size: 28px; } }
body:not(.admin-body) .hero-panel-img { position: absolute; left: 0; right: 0; bottom: 0; height: 76%; display: block; }
body:not(.admin-body) .hero-panel-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
body:not(.admin-body) .hero-panel::after {
    content: ""; position: absolute; z-index: 1; left: 0; right: 0; top: 24%; height: 14%;
    background: linear-gradient(var(--surface), transparent); pointer-events: none;
}
body:not(.admin-body) .hero-panel-cta {
    position: absolute; z-index: 2; left: 16px; bottom: 16px;
    padding: 7px 16px; border-radius: 999px; background: #fff; color: var(--ink);
    font-size: 14px; font-weight: 700; line-height: 1.2;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .25);
}
body:not(.admin-body) .hero-panel.is-skeleton .sk-box { position: absolute; inset: 0; background: var(--surface); }
body:not(.admin-body) .home-sec { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
body:not(.admin-body) .home-sec-h { margin: 0; font-size: 22px; font-weight: 700; line-height: 1.25; color: var(--ink); }
/* a phone: the cards scroll sideways, one card wide with the next peeking in */
body:not(.admin-body) .home-cards {
    display: flex; gap: 12px;
    overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
body:not(.admin-body) .home-cards::-webkit-scrollbar { display: none; }
body:not(.admin-body) .home-cards > .hcard { flex: 0 0 86%; scroll-snap-align: start; }
/* a laptop: every card in a FIXED SLOT — 3 slots a row at 900–1199px, each (row − 40px) ÷ 3; 4 from 1200px, each
   (row − 60px) ÷ 4 (four is the most at any width). A section with fewer cards keeps them one slot wide on the left —
   the rest of the row stays empty, nothing stretches; more cards wrap onto the next row, the same size. 20px apart. */
@media (min-width: 900px) {
    body:not(.admin-body) .home-cards { display: grid; grid-template-columns: repeat(3, calc((100% - 40px) / 3)); justify-content: start; gap: 20px; overflow: visible; }
}
@media (min-width: 1200px) {
    body:not(.admin-body) .home-cards { grid-template-columns: repeat(4, calc((100% - 60px) / 4)); }
}
body:not(.admin-body) .hcard {
    display: flex; flex-direction: column; gap: 12px; min-width: 0;
    padding: 16px; background: #fff; border: 1px solid var(--divider); border-radius: 10px;
}
body:not(.admin-body) .hcard-h {
    display: flex; justify-content: space-between; align-items: flex-start; gap: 10px;
    font-size: 20px; font-weight: 700; line-height: 1.2; color: var(--ink); text-decoration: none;
}
body:not(.admin-body) .hcard-h:hover span { text-decoration: underline; }
body:not(.admin-body) .hcard-chev { width: 22px; height: 22px; flex: none; margin-top: 1px; }
body:not(.admin-body) .hcard-quad { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 12px; }
body:not(.admin-body) .hcard-tile { display: flex; flex-direction: column; gap: 6px; min-width: 0; color: var(--ink); text-decoration: none; }
body:not(.admin-body) .hcard-tile-img { display: block; aspect-ratio: 1 / 1; border-radius: 6px; overflow: hidden; background: var(--surface); }
body:not(.admin-body) .hcard-tile-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
body:not(.admin-body) .hcard-tile-lb { font-size: 15px; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body:not(.admin-body) .hcard-tile:hover .hcard-tile-lb { text-decoration: underline; }
/* A PRODUCT ROW (homepage spec v3): the admin's title — a link with a › when it opens something — then single products
   in one row that scrolls sideways and never moves by itself. Each product is EXACTLY 150px wide on a phone (swiped, no
   arrows) and 200px from 900px, 12px apart: a square photo on the light surface, the name on at most 2 lines then …,
   and its price ("From ₦X" only when its sizes differ in price, else "₦X"). Fewer than fill the row sit on the left. The laptop arrows are the headline panels' own (.row-arrow,
   shop-nav.js ftkScrollRow), centred on the 200px photo. */
body:not(.admin-body) .home-sec-link { display: inline-flex; align-items: center; gap: 6px; color: inherit; text-decoration: none; }
body:not(.admin-body) .home-sec-link:hover span { text-decoration: underline; }
body:not(.admin-body) .home-sec-chev { width: 20px; height: 20px; flex: none; }
body:not(.admin-body) .hprow {
    display: flex; gap: 12px;
    overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
body:not(.admin-body) .hprow::-webkit-scrollbar { display: none; }
body:not(.admin-body) .hprod { flex: 0 0 150px; width: 150px; min-width: 0; display: flex; flex-direction: column; scroll-snap-align: start; color: var(--ink); text-decoration: none; }
body:not(.admin-body) .hprod-img { display: block; aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden; background: var(--surface); }
body:not(.admin-body) .hprod-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
body:not(.admin-body) .hprod-name {
    margin-top: 8px; font-size: 14px; line-height: 1.35; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
body:not(.admin-body) .hprod:hover .hprod-name { text-decoration: underline; }
body:not(.admin-body) .hprod-price { margin-top: 2px; font-size: 15px; font-weight: 900; font-variant-numeric: tabular-nums; }
body:not(.admin-body) .hprod-price small { font-size: 13px; font-weight: 400; color: var(--ink-2); }
@media (min-width: 900px) {
    body:not(.admin-body) .hprod { flex-basis: 200px; width: 200px; }
    body:not(.admin-body) .home-prow .row-arrow { top: 100px; }
}
@media (prefers-reduced-motion: reduce) { body:not(.admin-body) .hprow { scroll-behavior: auto; } }

/* ── D · DEPARTMENT and "ALL CATEGORIES" pages, and the CATEGORY page's breadcrumb + side column ── */
body:not(.admin-body) main.dept-page { display: flex; flex-direction: column; gap: var(--s5); padding-top: var(--s4); padding-bottom: var(--s6); }
body:not(.admin-body) main.dept-page .cat-head { padding: 0; }
body:not(.admin-body) .dept-sec { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
body:not(.admin-body) .dept-sec[hidden] { display: none; }
body:not(.admin-body) .dept-sec-h { margin: 0; font-size: 20px; font-weight: 700; line-height: 1.25; color: var(--ink); }
body:not(.admin-body) .dept-sec-h a { color: inherit; text-decoration: none; }
body:not(.admin-body) .dept-sec-h a:hover { text-decoration: underline; }
/* a phone: two tiles a row, like a card's 2×2 (the prototype's 200px minimum gave one 358px tile a row);
   a laptop: the prototype's grid, as many 200px-and-up tiles as fit */
body:not(.admin-body) .dept-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 12px; }
@media (min-width: 900px) { body:not(.admin-body) .dept-tiles { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 22px; } }
body:not(.admin-body) .dept-page .prod-row { padding-left: 0; padding-right: 0; }
body:not(.admin-body) #all-cats { display: flex; flex-direction: column; gap: var(--s6); }
/* The breadcrumb takes the old "‹ All categories" back link's place and look. */
body:not(.admin-body) .cat-crumb { margin: 0 0 10px; font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--ink-2); }
body:not(.admin-body) .cat-crumb a { color: var(--orange-ink); font-weight: 700; text-decoration: none; font-size: inherit; line-height: inherit; }   /* the breadcrumb's own 14px line, not every link's 15px / 1.5 */
body:not(.admin-body) .cat-crumb a:hover { text-decoration: underline; }
body:not(.admin-body) .cat-crumb:empty { min-height: 1.4em; }
body:not(.admin-body) .cat-side { display: none; }
@media (min-width: 900px) {
    /* the category page (the only one with a side column — not search, not Best Sellers): crumb across the top; the
       department's other categories in a 220px column; name, count and grid beside it */
    body:not(.admin-body) main.cat-page:has(> #cat-side) {
        display: grid;
        grid-template-columns: 220px minmax(0, 1fr);
        grid-template-areas: "crumb crumb" "side name" "side count" "side grid";
        grid-template-rows: auto auto auto 1fr;
        column-gap: var(--s5);
        align-items: start;
        padding-top: var(--s4);
    }
    body:not(.admin-body) main.cat-page:has(> #cat-side) .cat-head { display: contents; }
    body:not(.admin-body) main.cat-page:has(> #cat-side) .cat-crumb { grid-area: crumb; }
    body:not(.admin-body) main.cat-page:has(> #cat-side) .cat-name { grid-area: name; }
    body:not(.admin-body) main.cat-page:has(> #cat-side) .cat-count { grid-area: count; }
    body:not(.admin-body) main.cat-page:has(> #cat-side) .products { grid-area: grid; padding-top: var(--s4); }
    body:not(.admin-body) .cat-side { grid-area: side; display: flex; flex-direction: column; gap: 2px; padding-top: 4px; font-size: 14px; }
    body:not(.admin-body) .cat-side-h { margin: 0 0 6px; font-size: 15px; font-weight: 700; color: var(--ink); }
    body:not(.admin-body) .cat-side a { padding: 5px 0; color: var(--ink); text-decoration: none; }
    body:not(.admin-body) .cat-side a:hover { text-decoration: underline; }
    body:not(.admin-body) .cat-side a[aria-current="page"] { font-weight: 700; color: var(--orange-ink); }
    /* (the not-found state replaces the page's content, side column included, so the grid above no longer applies) */
}

/* ── E · THE PRODUCT PAGE (every width; the fix round of categories batch B).
   The breadcrumb "<Department> › <Category>" leads (the category page's .cat-crumb). The main photo box is square
   (1:1), its left edge on the breadcrumb's, at most 560px — the gallery itself is "THE PRODUCT PHOTO GALLERY" below
   (gallery batch, part A). The details: name (26px) · rating · the price block between two lines (28px / 900 price and the
   delivery line) · "Size: <chosen>" and the size boxes · a line, then About (left off with no description) · the
   facts · Product details. The bordered buy box: its own price and delivery line (from 1200px only — below 1200px
   the details' price block shows them, so the price is never on screen twice), the stock line, the stepper and Add
   To Cart, then Sold by / Payment / Returns. Customer reviews run the full width under a line, 32px below.
   Phone: photo, details, buy box, stacked. 900–1199: gallery and details side by side, the buy box under the
   details. From 1200: gallery (the 64px rail + 8px + a box of at most 560px; 44% of the page until it reaches that) ·
   details · the 300px buy box, 24px apart, in the page's 1500px. ── */
body:not(.admin-body) .pp-crumb { margin: 0 0 12px; }
body:not(.admin-body) .pp-det { min-width: 0; }
body:not(.admin-body) .pp-det .pp-name { font-size: 26px; font-weight: 700; line-height: 1.2; }
body:not(.admin-body) .pp-priceblock { margin: 12px 0 0; padding: 12px 0; border-top: 1px solid var(--divider); border-bottom: 1px solid var(--divider); }
body:not(.admin-body) .pp-price { margin: 0; font-size: 28px; font-weight: 900; line-height: 1.2; color: var(--ink); font-variant-numeric: tabular-nums; }
body:not(.admin-body) .pp-price:empty { display: none; }
body:not(.admin-body) .pp-deliv { margin: 4px 0 0; font-size: 14px; color: var(--ink-2); }
body:not(.admin-body) .pp-size-now { margin: 12px 0 0; font-size: 14px; color: var(--ink); }
body:not(.admin-body) .pp-size-now:empty { display: none; }
body:not(.admin-body) .pp-det .pp-sizes { margin-top: 8px; }
body:not(.admin-body) .pp-about { margin-top: 16px; border-top: 1px solid var(--divider); }
body:not(.admin-body) .pp-about .pp-sec-h { margin-top: 16px; }
body:not(.admin-body) .pp-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 18px; margin: 16px 0 0; font-size: 14px; }
body:not(.admin-body) .pp-facts > div { display: contents; }
body:not(.admin-body) .pp-facts dt { color: var(--ink-2); }
body:not(.admin-body) .pp-facts dd { margin: 0; color: var(--ink); }
body:not(.admin-body) .pp-buybox {
    display: flex; flex-direction: column; gap: 12px; min-width: 0;
    margin-top: var(--s5); padding: 18px; border: 1px solid var(--divider); border-radius: 10px;
}
body:not(.admin-body) .pp-buybox .pp-price-box,
body:not(.admin-body) .pp-buybox .pp-deliv-box { display: none; }
body:not(.admin-body) .pp-buybox .pp-stock,
body:not(.admin-body) .pp-buybox .pp-buy { margin: 0; }
body:not(.admin-body) .pp-trust { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 14px; margin: 0; padding-top: 12px; border-top: 1px solid var(--divider); font-size: 13px; }
body:not(.admin-body) .pp-trust > div { display: contents; }
body:not(.admin-body) .pp-trust dt { color: var(--ink-2); }
body:not(.admin-body) .pp-trust dd { margin: 0; color: var(--ink); }
body:not(.admin-body) .pp-trust a { color: var(--orange-ink); }
body:not(.admin-body) .pp-reviews { margin-top: 32px; border-top: 1px solid var(--divider); min-width: 0; }
@media (min-width: 900px) {
    body:not(.admin-body) .pp-root {
        max-width: 1500px; margin-left: auto; margin-right: auto;
        padding: var(--s4) 0 var(--s6);
        display: grid; column-gap: 24px; align-items: start;
        grid-template-columns: minmax(0, 45%) minmax(0, 1fr);
        grid-template-areas: "crumb crumb" "gal det" "gal box" "rev rev" "more more";
        grid-template-rows: auto auto 1fr auto auto;
    }
    body:not(.admin-body) .pp-root > .ftk-notfound { grid-column: 1 / -1; }
    body:not(.admin-body) .pp-crumb { grid-area: crumb; }
    body:not(.admin-body) .pp-gallery { grid-area: gal; margin: 0; }
    body:not(.admin-body) .pp-det { grid-area: det; }
    body:not(.admin-body) .pp-det .pp-head { margin-top: 0; }
    body:not(.admin-body) .pp-buybox { grid-area: box; width: 100%; max-width: 300px; }
    body:not(.admin-body) .pp-buybox .pp-buy { flex-direction: column; align-items: stretch; }
    body:not(.admin-body) .pp-buybox .pp-stepper { align-self: flex-start; }
    body:not(.admin-body) .pp-buybox .pp-add { flex: 0 0 auto; }
    body:not(.admin-body) .pp-reviews { grid-area: rev; }
    body:not(.admin-body) .pp-more { grid-area: more; min-width: 0; }
}
@media (min-width: 1200px) {
    body:not(.admin-body) .pp-root {
        grid-template-columns: minmax(0, min(632px, 44%)) minmax(0, 1fr) 300px;   /* gallery batch: the rail + a box of ≤560px */
        grid-template-areas: "crumb crumb crumb" "gal det box" "rev rev rev" "more more more";
        grid-template-rows: auto auto auto auto;
    }
    body:not(.admin-body) .pp-buybox { margin-top: 0; }
    /* the price moves into the buy box: the details' price block goes, the box's own price and delivery line show */
    body:not(.admin-body) .pp-det .pp-priceblock { display: none; }
    body:not(.admin-body) .pp-buybox .pp-price-box { display: block; }
    body:not(.admin-body) .pp-buybox .pp-price-box:empty { display: none; }
    body:not(.admin-body) .pp-buybox .pp-deliv-box { display: block; margin: 0; }
}

/* ── THE PRODUCT PHOTO GALLERY (gallery batch, part A) — markup storefront-render.js galleryHtml, behaviour
   client/product-gallery.js. TWO MODES from ONE media query (the same words as FTKGalleryRules.MAC_QUERY — never the
   device): MAC = (min-width: 900px), or (hover: hover) and (pointer: fine) and (min-width: 560px); PHONE = the rest.
   Every photo box is square, #F7F7F5 — the grey is what shows the box, never white on white — with 8px corners and the
   photo contained, never cropped. Heart, share, the viewer's × and arrows: 40px (48px) white circles with the
   --control-edge edge (3.47:1). Every control has the 2px --orange-ink focus ring. Marketplace batch 4B (Part K): up to
   10 photos — the rail shows all of them up to 7, else 6 and a "+N" tile; the phone dots shrink from 7 photos; NO lens
   on the photo (the 2× pane alone). ── */
body:not(.admin-body) .pp-gallery { position: relative; max-width: 560px; margin: 0 0 8px; }
body:not(.admin-body) .pp-rail { display: none; }
body:not(.admin-body) .pp-stage { position: relative; min-width: 0; }
body:not(.admin-body) .pp-main { position: relative; }
/* PHONE: the strip, edge to edge in the page gutter — 2+ photos are (100% − 32px) wide so the next one peeks in */
body:not(.admin-body) .pp-track {
    display: flex; gap: 8px; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
body:not(.admin-body) .pp-track::-webkit-scrollbar { display: none; }
body:not(.admin-body) .pp-slide { flex: 0 0 100%; min-width: 0; aspect-ratio: 1 / 1; scroll-snap-align: start; background: #F7F7F5; border-radius: 8px; overflow: hidden; }
body:not(.admin-body) .pp-gallery.is-multi .pp-slide { flex-basis: calc(100% - 32px); }
body:not(.admin-body) .pp-open { display: block; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer; }
body:not(.admin-body) .pp-open img { display: block; width: 100%; height: 100%; object-fit: contain; }
/* …one row under it: the dots centred, heart and share on the right (nothing on the photo) */
body:not(.admin-body) .pp-photobar { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; min-height: 40px; margin-top: 10px; }
body:not(.admin-body) .pp-dots { grid-column: 2; display: flex; align-items: center; justify-content: center; }
body:not(.admin-body) .pp-dot { display: inline-grid; place-items: center; width: 24px; height: 24px; margin: 0; padding: 0; border: 0; border-radius: 999px; background: transparent; cursor: pointer; }
body:not(.admin-body) .pp-dot::before { content: ""; display: block; width: 10px; height: 10px; border-radius: 999px; background: var(--control-edge); transition: width .18s ease, background-color .18s ease; }   /* #8A8A84 */
body:not(.admin-body) .pp-dot.is-current::before { width: 22px; background: var(--orange-ink); }   /* #A85C16 */
/* marketplace batch 4B (Part K): from 7 photos the dots are 8px (18px when current), 6px apart — ten fit a 320px screen */
body:not(.admin-body) .pp-dots.many .pp-dot { width: 14px; height: 24px; }
body:not(.admin-body) .pp-dots.many .pp-dot.is-current { width: 24px; }
body:not(.admin-body) .pp-dots.many .pp-dot::before { width: 8px; height: 8px; }
body:not(.admin-body) .pp-dots.many .pp-dot.is-current::before { width: 18px; }
body:not(.admin-body) .pp-actions { grid-column: 3; justify-self: end; display: flex; gap: 8px; }
body:not(.admin-body) .pp-actions .ftk-heart,
body:not(.admin-body) .pp-actions .pp-share { position: static; flex: 0 0 40px; width: 40px; height: 40px; }
body:not(.admin-body) .pp-share {
    display: flex; align-items: center; justify-content: center; padding: 0; border-radius: 999px; cursor: pointer;
    background: #fff; color: var(--ink); border: 1px solid var(--control-edge);
}
body:not(.admin-body) .pp-share:hover { border-color: var(--ink-2); }
body:not(.admin-body) .pp-hint { margin: 8px 0 0; font-size: 13px; line-height: 1.4; color: #6B6B66; }
body:not(.admin-body) .pp-hint:empty { display: none; }
body:not(.admin-body) .pp-zoom { display: none; }
body:not(.admin-body) .pp-open:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: -4px; }
body:not(.admin-body) .pp-thumb:focus-visible,
body:not(.admin-body) .pp-dot:focus-visible,
body:not(.admin-body) .pp-share:focus-visible,
body:not(.admin-body) .ppv button:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
/* MAC: the rail on the left, 8px from a square box of at most 560px that never moves or shrinks (the rail's column is
   kept for one photo); heart and share inside the box's top-right corner, 12px in; the hover zoom; nothing scrolls */
@media (min-width: 900px), (hover: hover) and (pointer: fine) and (min-width: 560px) {
    body:not(.admin-body) .pp-gallery { display: grid; grid-template-columns: 64px minmax(0, 560px); column-gap: 8px; align-items: start; max-width: 632px; }
    body:not(.admin-body) .pp-rail { display: flex; flex-direction: column; gap: 8px; grid-column: 1; grid-row: 1; }
    body:not(.admin-body) .pp-stage { grid-column: 2; grid-row: 1; }
    body:not(.admin-body) .pp-main { aspect-ratio: 1 / 1; overflow: hidden; background: #F7F7F5; border-radius: 8px; }
    body:not(.admin-body) .pp-track { position: absolute; inset: 0; display: block; overflow: hidden; scroll-snap-type: none; }
    body:not(.admin-body) .pp-slide { position: absolute; inset: 0; display: none; aspect-ratio: auto; border-radius: 0; background: transparent; }
    body:not(.admin-body) .pp-slide.is-current { display: block; }
    body:not(.admin-body) .pp-open { border-radius: 0; }
    body:not(.admin-body) .pp-slide[data-zoom] .pp-open { cursor: zoom-in; }
    body:not(.admin-body) .pp-photobar { position: absolute; z-index: 2; top: 12px; right: 12px; display: block; min-height: 0; margin: 0; }
    body:not(.admin-body) .pp-dots { display: none; }
    body:not(.admin-body) .pp-actions { flex-direction: column; gap: 8px; }
    body:not(.admin-body) .pp-thumb { display: block; width: 64px; height: 64px; margin: 0; padding: 0; overflow: hidden; cursor: pointer; background: var(--surface); border: 1px solid var(--control-edge); border-radius: 6px; }
    body:not(.admin-body) .pp-thumb[aria-current="true"] { border: 2px solid var(--orange-ink); }
    body:not(.admin-body) .pp-thumb img { display: block; width: 100%; height: 100%; object-fit: contain; }
    /* marketplace batch 4B (Part K): with 8+ photos the 7th tile is "+N" — photo 7 darkened, the count in white over it */
    body:not(.admin-body) .pp-thumb.pp-more { position: relative; }
    body:not(.admin-body) .pp-thumb.pp-more img { filter: brightness(.45); }
    body:not(.admin-body) .pp-more-n { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; font-size: 16px; font-weight: 700; letter-spacing: .02em; pointer-events: none; }
    body:not(.admin-body) .pp-zoom { display: block; position: absolute; z-index: 20; overflow: hidden; pointer-events: none; background: #F7F7F5; border: 1px solid #E5E4E0; border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); }
    body:not(.admin-body) .pp-zoom[hidden] { display: none; }
    body:not(.admin-body) .pp-zoom-clip { position: absolute; overflow: hidden; }
    body:not(.admin-body) .pp-zoom-img { position: absolute; left: 0; top: 0; max-width: none; transform-origin: 0 0; }
}
/* THE FULL-SCREEN VIEWER (both modes): white, inside the safe-area insets; the name (15px, bold, … when long) and a 40px ×
   on top, the dots under the photo; the page cannot scroll behind it. Mac adds 48px arrow buttons, 16px from the edges. */
body:not(.admin-body).ppv-lock { overflow: hidden; }   /* the page under the viewer cannot scroll (the body's overflow reaches the viewport) */
body:not(.admin-body) .ppv {
    position: fixed; inset: 0; z-index: 1000; display: flex; flex-direction: column; background: #FFFFFF; color: var(--ink);
    padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
    overscroll-behavior: contain; touch-action: none;   /* no finger on the viewer pans or zooms the page under it (iOS) */
}
body:not(.admin-body) .ppv[hidden] { display: none; }
body:not(.admin-body) .ppv-top { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 8px 12px 8px 16px; border-bottom: 1px solid #E5E4E0; }
body:not(.admin-body) .ppv-title { flex: 1 1 auto; min-width: 0; margin: 0; font-size: 15px; font-weight: 700; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body:not(.admin-body) .ppv-close { flex: 0 0 40px; display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border-radius: 999px; cursor: pointer; background: #fff; color: var(--ink); border: 1px solid var(--control-edge); }
body:not(.admin-body) .ppv-stage { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; touch-action: none; -webkit-user-select: none; user-select: none; }
body:not(.admin-body) .ppv-track { display: flex; height: 100%; }
body:not(.admin-body) .ppv-track.is-moving { transition: transform .25s ease; }
body:not(.admin-body) .ppv-slide { position: relative; flex: 0 0 100%; height: 100%; overflow: hidden; }
body:not(.admin-body) .ppv-img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: contain; transform-origin: 0 0; -webkit-user-drag: none; }
body:not(.admin-body) .ppv.can-zoom .ppv-stage { cursor: zoom-in; }
body:not(.admin-body) .ppv.is-zoomed .ppv-stage { cursor: grab; }
body:not(.admin-body) .ppv-arrow { display: none; }
body:not(.admin-body) .ppv-foot { padding: 10px 16px 14px; text-align: center; }
body:not(.admin-body) .ppv-dots { display: flex; justify-content: center; }
body:not(.admin-body) .ppv-hint { margin: 6px 0 0; font-size: 13px; line-height: 1.4; color: #6B6B66; }
body:not(.admin-body) .ppv-hint[hidden] { display: none; }
@media (min-width: 900px), (hover: hover) and (pointer: fine) and (min-width: 560px) {
    body:not(.admin-body) .ppv-arrow {
        position: absolute; z-index: 2; top: 50%; display: flex; align-items: center; justify-content: center; width: 48px; height: 48px;
        margin-top: -24px; padding: 0; border-radius: 999px; cursor: pointer;
        background: #fff; color: var(--ink); border: 1px solid var(--control-edge); box-shadow: 0 2px 12px rgba(0, 0, 0, .16);
    }
    body:not(.admin-body) .ppv-prev { left: 16px; }
    body:not(.admin-body) .ppv-next { right: 16px; }
    body:not(.admin-body) .ppv-arrow:disabled { opacity: .35; cursor: default; box-shadow: none; }
}

/* ── F · SCROLLING ROWS on a laptop: whole cards only (a column of the ladder each), with a 44px round arrow
   inside each end that moves one screenful and hides when there is nothing more that way (shop-nav.js). On a
   phone the arrows are not shown and the row is swiped as before. ── */
body:not(.admin-body) .row-arrow { display: none; }
@media (min-width: 900px) {
    body:not(.admin-body) .row-wrap { position: relative; }
    body:not(.admin-body) .prod-row { gap: 22px; padding-left: 0; padding-right: 0; scroll-behavior: smooth; }
    body:not(.admin-body) .prod-row > .row-card { width: calc((100% - (var(--cols) - 1) * 22px) / var(--cols)); }
    body:not(.admin-body) .prod-row .row-card-img { width: 100%; height: auto; aspect-ratio: 1 / 1; }
    body:not(.admin-body) .row-arrow {
        position: absolute; z-index: 2; top: calc(var(--row-imgh, 100%) / 2); transform: translateY(-50%);
        display: flex; align-items: center; justify-content: center;
        width: 44px; height: 44px; padding: 0; cursor: pointer;
        background: #fff; color: var(--ink); border: 1px solid var(--control-edge); border-radius: 999px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, .16);
    }
    body:not(.admin-body) .row-arrow svg { width: 18px; height: 18px; }
    body:not(.admin-body) .row-prev { left: 8px; }
    body:not(.admin-body) .row-next { right: 8px; }
    body:not(.admin-body) .row-arrow[hidden] { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    body:not(.admin-body) .hero-track,
    body:not(.admin-body) .prod-row { scroll-behavior: auto; }
}

/* ── G · OTHER PAGES ── */
/* The cart's search row: on a laptop only — a phone's cart header stays as it was. */
body:not(.admin-body) .navbar .nav-row-search-laptop { display: none; }
@media (min-width: 900px) { body:not(.admin-body) .navbar .nav-row-search-laptop { display: flex; } }
/* The Account Center's gold header: a laptop with the Account Center open (signed in) only. */
body:not(.admin-body) .navbar.nav-acct { display: none; }
@media (min-width: 900px) { body:not(.admin-body):has(main#account.acct-shell) .navbar.nav-acct { display: flex; } }
/* Protect your account: the same 460px centred card as Verify your email. Its card is a <main>, so the
   PAGE SHELL's 720px cap and side padding reached it (it drew 720px wide, flush under the top). */
@media (min-width: 900px) {
    body.ftk-protect main.vbox.pa-box { max-width: 460px; margin: 8vh auto; padding: 36px 30px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   CUSTOMER NOTIFICATIONS (Job A) — the menus' pill and the Notifications page. The header's person icon shows no count
   (the owner's ruling): the count is seen only once the menu or the Account Center is open.
   ═══════════════════════════════════════════════════════════════════════ */
/* The pill on the Notifications row — the storefront menu, the Account Center's sidebar and drawer, and the All
   options page (before the chevron). 24px round-ended, 13px bold white on the primary orange; the row keeps its
   height (48px in the menu). */
body:not(.admin-body) .nt-pill {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    min-width: 24px; height: 24px; padding: 0 7px; box-sizing: border-box; margin-left: auto;
    border-radius: var(--r-pill); background: var(--orange); color: var(--ink);
    font-size: 13px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
}
body:not(.admin-body) .nt-pill[hidden] { display: none; }

/* The page: the subline, then one row per notice — a 40px round icon (an order: the grey surface; an account
   change: the light gold tint), the line (bold while unread) with its time under it, and the orange unread dot. */
body:not(.admin-body) .nt-sub { margin: 0 0 var(--s4); font-size: var(--fs-meta); line-height: var(--lh-body); color: var(--ink-2); }
body:not(.admin-body) .nt-list { list-style: none; margin: 0; padding: 0; border-top: var(--bw) solid var(--divider); }
body:not(.admin-body) .nt-list:empty { display: none; }
body:not(.admin-body) .nt-row {
    display: grid; grid-template-columns: 40px minmax(0, 1fr) 10px; gap: var(--s3); align-items: start;
    width: 100%; box-sizing: border-box; margin: 0; padding: 14px var(--s2);
    background: none; border: none; border-bottom: var(--bw) solid var(--divider); border-radius: 0;
    text-align: left; font-family: inherit; color: var(--ink); cursor: pointer;
}
body:not(.admin-body) .nt-row:hover { background: var(--surface); }
body:not(.admin-body) .nt-row:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: -2px; }
body:not(.admin-body) .nt-ic {
    width: 40px; height: 40px; box-sizing: border-box; border-radius: 50%;
    display: grid; place-items: center;
    background: var(--surface); border: var(--bw) solid var(--divider); color: var(--ink);
}
body:not(.admin-body) .nt-ic svg { display: block; width: 20px; height: 20px; }
body:not(.admin-body) .nt-ic--account { background: var(--gold-tint); border-color: var(--gold-tint-line); color: var(--gold-ink); }
body:not(.admin-body) .nt-text { display: block; min-width: 0; }
body:not(.admin-body) .nt-line { display: block; font-size: var(--fs-body); font-weight: 400; line-height: 1.4; overflow-wrap: anywhere; }
body:not(.admin-body) .nt-row.is-unread .nt-line { font-weight: 700; }
body:not(.admin-body) .nt-time { display: block; margin-top: 2px; font-size: var(--fs-meta); line-height: 1.35; color: var(--ink-2); }
body:not(.admin-body) .nt-dot { width: 10px; height: 10px; margin-top: 15px; border-radius: 50%; background: var(--orange-ink); visibility: hidden; }
body:not(.admin-body) .nt-row.is-unread .nt-dot { visibility: visible; }
body:not(.admin-body) .nt-more {
    display: block; margin: var(--s5) auto 0; min-height: 44px; padding: 0 var(--s5);
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-btn); background: var(--page); color: var(--ink);
    font-family: inherit; font-size: var(--fs-body); font-weight: 700; line-height: 1; cursor: pointer;
}
body:not(.admin-body) .nt-more:hover { border-color: var(--ink-2); }
body:not(.admin-body) .nt-more:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
body:not(.admin-body) .nt-more[hidden],
body:not(.admin-body) .nt-state[hidden] { display: none; }
body:not(.admin-body) .nt-empty { margin: 0; padding: var(--s7) 0 0; text-align: center; font-size: var(--fs-body); color: var(--ink-2); }

/* "Top of page" moves keyboard focus to the top of the page (script.js gives <body id="top"> tabindex -1 and focuses
   it): no ring around the whole page — the next Tab goes to the first control as usual. */
body:not(.admin-body)[tabindex="-1"]:focus { outline: none; }

/* ═══ PHONE CONFIRMATION (phone confirmation job, Parts E1–E7) ═══════════════════════════════════════════════════
   Checkout's "Verify your mobile number" section and its screens (checkout.html, checkout.js), the code / lock /
   limit screens both places share (phone-confirm.js: .pc-*), Login & security's "Verified" pill and its "Verify /
   Change mobile number" screens (account-phone-verify.js: .pv-*). Storefront only — every rule is scoped to
   body:not(.admin-body), and the console has none of these classes. The site's own tokens throughout: the orange
   primary and white outline buttons, 48px tall, the one green (--paid-green, a "done" mark), the amber the old
   "Not verified" badge used. No style attributes anywhere (CSP). */

/* The pill: green "Verified" (checkout's verified number; Login & security's verified email and mobile number) — a good
   status, rule A's green (4.78:1 on its tint) */
body:not(.admin-body) .pc-pill {
    display: inline-block; margin-left: 6px; padding: 2px 8px; vertical-align: 1px;
    border-radius: var(--r-pill); border: var(--bw) solid transparent;
    font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; line-height: 1.4; white-space: nowrap;
}
body:not(.admin-body) .pc-pill-ok { background: var(--paid-green-bg); color: var(--paid-green); border-color: var(--paid-green-bg); }

/* E1 — checkout's section, the same card as "Delivering to" */
body:not(.admin-body) #checkout-page .ck-phone {
    background: #fff; border: 1px solid #E5E4E0; border-radius: 14px; padding: 16px 18px;
}
body:not(.admin-body) #checkout-page .ck-phone[hidden],
body:not(.admin-body) #checkout-page #ck-phone-todo[hidden],
body:not(.admin-body) #checkout-page #ck-phone-done[hidden],
body:not(.admin-body) #checkout-page .ck-phone-num[hidden],
body:not(.admin-body) #checkout-page #ck-phone-send[hidden],
body:not(.admin-body) #checkout-page #ck-phone-hint[hidden] { display: none; }
body:not(.admin-body) #checkout-page .ck-phone-h { margin: 0 0 6px; font-size: 16px; font-weight: 800; line-height: 1.35; color: #16281c; }
body:not(.admin-body) #checkout-page .ck-phone-text { margin: 0 0 var(--s3); font-size: 14px; line-height: 1.5; color: #46564c; }
body:not(.admin-body) #checkout-page .ck-phone-label { margin: 0 0 6px; font-size: 15px; font-weight: 800; line-height: 1.35; color: #16281c; }
body:not(.admin-body) #checkout-page .ck-phone-num {
    margin: 0 0 var(--s3); font-size: 22px; font-weight: 700; line-height: 1.3; color: var(--ink);
    font-variant-numeric: tabular-nums; letter-spacing: .01em; overflow-wrap: anywhere;
}
body:not(.admin-body) #checkout-page #ck-phone-done .ck-phone-num { margin-bottom: 0; }
body:not(.admin-body) #checkout-page #ck-phone-err { margin: 0 0 var(--s3); }
body:not(.admin-body) #checkout-page .ck-phone-actions { display: grid; grid-template-columns: 1fr; gap: var(--s3); }
body:not(.admin-body) #checkout-page .ck-phone-actions button { width: 100%; min-height: 48px; }
@media (min-width: 480px) {
    body:not(.admin-body) #checkout-page .ck-phone-actions { grid-template-columns: 1fr 1fr; }
}
/* The line under the pay button while the number is not confirmed — #ck-pay-hint's look */
body:not(.admin-body) #checkout-page #ck-phone-hint { margin: 10px 0 0; text-align: center; font-size: 13px; line-height: 1.5; color: #5C5C5C; }

/* E3–E5 — the code, "Too many wrong codes", "Code limit reached" (phone-confirm.js), in either place */
body:not(.admin-body) .pc-screen { display: flex; flex-direction: column; align-items: stretch; }
body:not(.admin-body) .pc-text { margin: 0 0 var(--s4); font-size: 15px; line-height: 1.5; color: var(--ink); }
body:not(.admin-body) .pc-num { font-weight: 700; white-space: nowrap; }
body:not(.admin-body) .pc-alert {
    margin: 0 0 var(--s4); padding: var(--s3) var(--s4); border-radius: var(--r-card);
    background: #FDECEA; border: var(--bw) solid #F5C2BD; color: var(--danger); font-size: 14px; line-height: 1.5;
}
body:not(.admin-body) .pc-alert[hidden], body:not(.admin-body) .pc-last[hidden], body:not(.admin-body) .pc-wait[hidden],
body:not(.admin-body) .pc-again[hidden] { display: none; }
/* visually hidden, still read out: the code box's label */
body:not(.admin-body) .pc-sr {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* ONE box, large centred digits */
body:not(.admin-body) .pc-screen input.pc-code {
    width: 100%; height: 60px; min-height: 60px; margin: 0 0 var(--s4); padding: 0 var(--s3); box-sizing: border-box;
    font-family: inherit; font-size: 28px; font-weight: 700; letter-spacing: .3em; text-align: center; font-variant-numeric: tabular-nums;
    color: var(--ink); background: #fff; border: var(--bw) solid var(--control-edge); border-radius: var(--r-card);
}
body:not(.admin-body) .pc-screen input.pc-code:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
body:not(.admin-body) .pc-screen .pc-confirm,
body:not(.admin-body) .pc-screen .pc-back { width: 100%; min-height: 48px; }
body:not(.admin-body) .pc-resend, body:not(.admin-body) .pc-last { margin: var(--s4) 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); text-align: center; }
body:not(.admin-body) .pc-wait { font-variant-numeric: tabular-nums; }
body:not(.admin-body) .pc-link {
    display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 var(--s2);
    background: none; border: 0; color: var(--orange-ink); font-family: inherit; font-size: 15px; font-weight: 700;
    text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
body:not(.admin-body) .pc-link:hover { color: var(--orange-ink); }
body:not(.admin-body) .pc-change { align-self: center; margin-top: var(--s2); }
body:not(.admin-body) .pc-mark {
    align-self: flex-start; display: inline-flex; align-items: center; justify-content: center;
    width: 56px; height: 56px; margin: 0 0 var(--s3); border-radius: 50%; background: var(--surface); color: var(--ink);
}
body:not(.admin-body) .pc-ico { width: 28px; height: 28px; }
body:not(.admin-body) .pc-link:focus-visible, body:not(.admin-body) .pv-bar-back:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }

/* E6/E7 — Login & security's "Change mobile number" (account-phone-verify.js) */
body:not(.admin-body) .pv-screen[hidden], body:not(.admin-body) .pv-start[hidden], body:not(.admin-body) .pv-flow[hidden],
body:not(.admin-body) #ls-heading[hidden], body:not(.admin-body) #ls-rows[hidden] { display: none; }
body:not(.admin-body) .pv-screen { max-width: 560px; }
/* while "Change mobile number" is open, the rest of the panel steps aside (account-phone-verify.js rowsShown) */
body:not(.admin-body) #panel-security > [data-pv-was-hidden] { display: none; }
body:not(.admin-body) .pv-bar {
    display: flex; align-items: center; gap: var(--s2); min-height: 48px; margin: 0 0 var(--s3);
    border-bottom: var(--bw) solid var(--divider);
}
body:not(.admin-body) .pv-bar-back {
    display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin-left: -10px;
    background: none; border: 0; border-radius: var(--r-btn); color: var(--ink); cursor: pointer;
}
body:not(.admin-body) .pv-bar-back:hover { background: var(--surface); }
body:not(.admin-body) .pv-bar-ico { width: 22px; height: 22px; }
body:not(.admin-body) .pv-bar-title { font-size: 15px; font-weight: 700; color: var(--ink); }
body:not(.admin-body) .pv-title:focus { outline: none; }
body:not(.admin-body) .pv-current {
    margin: 0 0 var(--s5); padding: var(--s4); border-radius: var(--r-card);
    background: var(--surface); border: var(--bw) solid var(--divider);
}
body:not(.admin-body) .pv-current-label {
    margin: 0; font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2);
}
body:not(.admin-body) .pv-current-num { margin: var(--s1) 0 var(--s2); font-size: 20px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
body:not(.admin-body) .pv-current-note { margin: 0; font-size: var(--fs-meta); line-height: 1.5; color: var(--ink-2); }
body:not(.admin-body) .pv-status { margin: 0 0 var(--s4); font-size: 15px; line-height: 1.5; color: var(--ink); }   /* "Verify mobile number": sending, or why it could not */
body:not(.admin-body) #pv-status-back[hidden] { display: none; }
body:not(.admin-body) .pv-screen .pv-send,
body:not(.admin-body) .pv-screen .pv-wide { width: 100%; }

/* The country picker beside every ACCOUNT-number box (sign-up, Login & security, checkout's "Use a different number",
   "Change mobile number"): a native <select> to the left, the same 48px height, border and radius as the box beside it,
   and the delivery-state picker's chevron (select.state-select). Never on a recipient's phone. */
body:not(.admin-body) .ftk-phone-row { display: flex; gap: var(--s2); align-items: stretch; }
body:not(.admin-body) .ftk-phone-row > input { flex: 1 1 auto; min-width: 0; width: auto; }
body:not(.admin-body) select.ftk-phone-cc {
    flex: 0 0 auto; width: auto; min-width: 108px; height: 48px; min-height: 48px; margin: 0; box-sizing: border-box;
    padding: 0 34px 0 12px; font-family: inherit; font-size: 16px; color: var(--ink); background-color: #fff;
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-card); cursor: pointer;
    -webkit-appearance: none; appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23667' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat; background-position: right 12px center;
}
body:not(.admin-body) select.ftk-phone-cc:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
/* …and checkout's field rule, which would make it full width and — with its `background` shorthand — take the chevron
   away; the picker keeps the box's own background there. (Sign-up's boxes show the same divider border as the rest: the
   broad input rule outranks .authf-input's #8A8A85, so the picker matches what is drawn.) */
body:not(.admin-body) #checkout-page .ck-field select.ftk-phone-cc {
    width: auto; padding: 0 34px 0 12px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23667' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat; background-position: right 12px center;
}
body:not(.admin-body) #checkout-page .ck-field .ftk-phone-row > input { width: auto; }

/* A4 — a phone field's message: under the field, only while it fails (the page's inline-error red) */
body:not(.admin-body) .ftk-field-err { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: #c0392b; }
body:not(.admin-body) .ftk-field-err[hidden] { display: none; }
body:not(.admin-body) [aria-invalid="true"]#prof-phone,
body:not(.admin-body) [aria-invalid="true"]#addr-phone,
body:not(.admin-body) [aria-invalid="true"]#pv-new { border-color: var(--danger); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════
   MARKETPLACE BATCH 3A — THE SHOPPING FEATURES. The site's own tokens throughout (orange actions, Lato, 44px controls,
   the gold tint, the "done" green, the light grey surface). No inline styles: every rule here is for markup the scripts
   draw with these classes.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── A PRODUCT CARD is a box holding the link (photo + name …) and the heart beside it (a button may not sit in a link):
   the grid card (.cat-card), the swipe-row card (.row-card) and the homepage's product row (.hprod). ── */
body:not(.admin-body) .cat-card,
body:not(.admin-body) .row-card,
body:not(.admin-body) .hprod { position: relative; }
body:not(.admin-body) .cat-card-link,
body:not(.admin-body) .row-card-link { display: block; color: inherit; text-decoration: none; }
body:not(.admin-body) .hprod-link { display: flex; flex-direction: column; min-width: 0; color: inherit; text-decoration: none; }
body:not(.admin-body) .cat-card-img,
body:not(.admin-body) .row-card-img,
body:not(.admin-body) .hprod-img { position: relative; }

/* THE HEART — outline when not saved, filled orange when saved (client/saved-items.js sets .is-saved / aria-pressed). */
body:not(.admin-body) .ftk-heart {
    position: absolute; z-index: 2;
    display: flex; align-items: center; justify-content: center;
    padding: 0; border-radius: 999px; cursor: pointer;
    background: #fff; color: var(--ink); border: 1px solid var(--control-edge);
}
body:not(.admin-body) .ftk-heart:hover { border-color: var(--ink-2); }
body:not(.admin-body) .ftk-heart:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
body:not(.admin-body) .ftk-heart .heart-ic { display: block; }
body:not(.admin-body) .ftk-heart.is-saved { color: var(--orange-ink); }
body:not(.admin-body) .ftk-heart.is-saved .heart-ic { fill: var(--orange-ink); }
body:not(.admin-body) .card-heart { top: 8px; right: 8px; width: 36px; height: 36px; }          /* a card: 36px, inset 8px, 18px icon */
/* the product page's heart: a 40px circle beside Share (gallery batch, part A — "THE PRODUCT PHOTO GALLERY") */

/* SOLD OUT — every size sold out: the photo dimmed, a dark tag in its bottom-left corner. */
body:not(.admin-body) .is-soldout .cat-card-img img,
body:not(.admin-body) .is-soldout .row-card-img img,
body:not(.admin-body) .is-soldout .hprod-img img { opacity: .45; }
body:not(.admin-body) .card-soldout {
    position: absolute; left: 8px; bottom: 8px; z-index: 1;
    padding: 3px 6px; border-radius: 4px; background: rgba(26, 26, 26, .9); color: #fff;
    font-size: 11px; font-weight: 900; line-height: 1.25; letter-spacing: .04em; text-transform: uppercase;
}

/* The grid card's price ("From ₦X", 14px bold) and rating ("★ 4.6 (31)" / "No reviews yet"). */
body:not(.admin-body) .card-price { display: block; margin-top: 4px; font-size: 14px; font-weight: 700; line-height: 1.3; color: var(--ink); font-variant-numeric: tabular-nums; }
body:not(.admin-body) .card-rating { display: block; margin-top: 2px; font-size: 13px; line-height: 1.3; color: var(--ink); }
body:not(.admin-body) .card-rating .card-star { color: var(--star-gold); }
body:not(.admin-body) .card-rating.is-none { color: var(--ink-2); }

/* ── THE TOOLBAR (category, search, department): "<N> products", then Sort and Filter as 40px pills; the active
   filters as removable gold-tint chips with "Clear all". ── */
body:not(.admin-body) .grid-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 12px; }
body:not(.admin-body) .grid-count { margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
body:not(.admin-body) .grid-tools-btns { display: flex; gap: 8px; margin-left: auto; }
body:not(.admin-body) .tool-pill {
    display: inline-flex; align-items: center; gap: 4px; height: 40px; padding: 0 14px;
    border-radius: 999px; border: 1px solid var(--control-edge); background: #fff; color: var(--ink);
    font: inherit; font-size: 14px; font-weight: 700; white-space: nowrap; cursor: pointer;
}
body:not(.admin-body) .tool-pill:hover,
body:not(.admin-body) .tool-pill.is-on { border-color: var(--ink); }
body:not(.admin-body) .tool-caret { font-size: 11px; color: var(--ink-2); }
body:not(.admin-body) .grid-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 14px; }
body:not(.admin-body) .grid-chips[hidden] { display: none; }
body:not(.admin-body) .grid-chip {
    display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 0 12px;
    border-radius: 999px; background: var(--gold-tint); border: 1px solid var(--gold-tint-line); color: var(--ink);
    font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
}
body:not(.admin-body) .grid-chip-x { font-size: 11px; color: var(--ink-2); }
body:not(.admin-body) .grid-chip-clear {
    min-height: 32px; padding: 0 4px; background: none; border: none; cursor: pointer;
    color: var(--orange-ink); font: inherit; font-size: 13px; font-weight: 700; text-decoration: underline;
}
body:not(.admin-body) .dept-all { margin-top: var(--s5); }

/* ── THE BOTTOM SHEET (client/sheet.js): white, top corners 14px, at most 480px wide and centred, over a scrim ── */
body:not(.admin-body).ftk-sheet-open { overflow: hidden; }
body:not(.admin-body) .ftk-sheet-scrim { position: fixed; inset: 0; z-index: 9000; background: rgba(0, 0, 0, .45); }
body:not(.admin-body) .ftk-sheet {
    position: fixed; z-index: 9001; left: 0; right: 0; bottom: 0; margin: 0 auto;
    width: 100%; max-width: 480px; max-height: 88vh; overflow-y: auto; box-sizing: border-box;
    padding: 8px 16px calc(16px + env(safe-area-inset-bottom, 0px));
    background: #fff; color: var(--ink); border-radius: 14px 14px 0 0; box-shadow: var(--shadow);
    font-family: var(--ftk-font);
}
body:not(.admin-body) .ftk-sheet-grab { width: 40px; height: 4px; margin: 0 auto 10px; border-radius: 2px; background: var(--divider); }
body:not(.admin-body) .ftk-sheet-h { margin: 0 0 8px; font-size: 18px; font-weight: 700; line-height: 1.3; }
body:not(.admin-body) .ftk-sheet-text { margin: 0; font-size: 15px; line-height: 1.5; color: var(--ink); }
body:not(.admin-body) .ftk-sheet-foot { display: flex; gap: 12px; margin-top: 16px; }
body:not(.admin-body) .sheet-btn { flex: 1 1 0; min-height: 44px; padding: 0 12px; border-radius: var(--r-btn); font: inherit; font-size: 15px; font-weight: 700; cursor: pointer; }
body:not(.admin-body) .sheet-btn-ghost { background: #fff; color: var(--ink); border: 1px solid var(--control-edge); }
body:not(.admin-body) .sheet-btn-primary { background: var(--orange); color: var(--ink); border: 1px solid var(--orange); }
body:not(.admin-body) .sheet-btn-primary:hover, body:not(.admin-body) .sheet-btn-primary:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
body:not(.admin-body) .sheet-radio { display: flex; align-items: center; gap: 12px; min-height: 48px; border-bottom: 1px solid var(--divider); font-size: 15px; cursor: pointer; }
body:not(.admin-body) .sheet-radio:last-child { border-bottom: none; }
body:not(.admin-body) .sheet-radio input { width: 20px; height: 20px; margin: 0; accent-color: var(--orange-ink); }
/* Filter */
body:not(.admin-body) .flt-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 48px; border-bottom: 1px solid var(--divider); font-size: 15px; }
body:not(.admin-body) .ftk-switch { position: relative; flex: 0 0 auto; width: 48px; height: 28px; padding: 0; border: none; border-radius: 999px; background: var(--control-edge); cursor: pointer; }
body:not(.admin-body) .ftk-switch-knob { position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .2); transition: transform .15s; }
body:not(.admin-body) .ftk-switch[aria-checked="true"] { background: var(--orange-ink); }
body:not(.admin-body) .ftk-switch[aria-checked="true"] .ftk-switch-knob { transform: translateX(20px); }
body:not(.admin-body) .ftk-switch:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
body:not(.admin-body) .flt-price, body:not(.admin-body) .flt-sellers { margin: 0; padding: 12px 0; border: none; border-bottom: 1px solid var(--divider); }
body:not(.admin-body) .flt-legend { padding: 0; margin: 0 0 8px; font-size: 15px; font-weight: 700; }
body:not(.admin-body) .flt-num { display: inline-flex; flex-direction: column; gap: 4px; width: calc(50% - 6px); font-size: 13px; color: var(--ink-2); }
body:not(.admin-body) .flt-num + .flt-num { margin-left: 12px; }
body:not(.admin-body) .flt-num input { height: 44px; padding: 0 12px; border: 1px solid var(--control-edge); border-radius: var(--r-btn); font: inherit; font-size: 15px; color: var(--ink); box-sizing: border-box; width: 100%; }
body:not(.admin-body) .flt-check { display: flex; align-items: center; gap: 10px; min-height: 44px; font-size: 15px; cursor: pointer; }
body:not(.admin-body) .flt-check input { width: 20px; height: 20px; margin: 0; accent-color: var(--orange-ink); }

/* ── THE PRODUCT PAGE ── a sold-out size can be chosen; with it chosen (.pp-oos) the price, the stepper, Add To Cart and
   the delivery box give way to the Notify box (the light grey surface). */
body:not(.admin-body) .pp-size.is-out { cursor: pointer; }
body:not(.admin-body) .pp-size.is-out.is-sel { border: 2px dashed var(--ink); background: #fff; color: var(--ink-2); }
body:not(.admin-body) .pp-root.pp-oos .pp-priceblock,
body:not(.admin-body) .pp-root.pp-oos .pp-price-box,
body:not(.admin-body) .pp-root.pp-oos .pp-stock,
body:not(.admin-body) .pp-root.pp-oos .pp-buy,
body:not(.admin-body) .pp-root.pp-oos .pp-delivery { display: none !important; }
body:not(.admin-body) .pp-notify { display: none; flex-direction: column; gap: 8px; padding: 14px; border-radius: 8px; background: var(--surface); }
body:not(.admin-body) .pp-root.pp-oos .pp-notify { display: flex; }
body:not(.admin-body) .pp-notify-h { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.4; color: var(--ink); }
body:not(.admin-body) .pp-notify-sub { margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
body:not(.admin-body) .pp-notify-btn { width: 100%; min-height: 44px; }
body:not(.admin-body) .pp-notify [hidden] { display: none !important; }
body:not(.admin-body) .pp-notify-on {
    display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px;
    border-radius: 6px; background: #F5F9F6; color: var(--paid-green); font-size: 14px; font-weight: 700; line-height: 1.4;   /* #F5F9F6 = the paid green at 6% on WHITE, opaque: it sits in the grey Notify panel, where a see-through tint gave its orange Cancel only 4.30:1 — now green 5.05:1, Cancel 4.70:1 */
}
body:not(.admin-body) .pp-notify-cancel {
    flex: 0 0 auto; min-height: 32px; padding: 0 4px; background: none; border: none; cursor: pointer;
    color: var(--orange-ink); font: inherit; font-size: 14px; font-weight: 700; text-decoration: underline;
}
body:not(.admin-body) .pp-notify-note { margin: 0; font-size: 12px; line-height: 1.4; color: var(--ink-2); }
/* The delivery box (an in-stock size): a truck, then "Delivery to <State>" + "Arrives …" or Lagos / Other states. */
body:not(.admin-body) .pp-delivery { display: flex; align-items: flex-start; gap: 10px; padding-top: 12px; border-top: 1px solid var(--divider); }
body:not(.admin-body) .pp-delivery:empty { display: none; }
body:not(.admin-body) .pp-delivery.is-waiting { min-height: 74px; }
body:not(.admin-body) .pp-delivery-ic { flex: 0 0 auto; margin-top: 1px; color: var(--ink); }
body:not(.admin-body) .pp-delivery-body { min-width: 0; }
body:not(.admin-body) .pp-delivery-row { display: flex; flex-wrap: wrap; gap: 0 8px; margin: 0 0 2px; font-size: 14px; line-height: 1.4; color: var(--ink); }
body:not(.admin-body) .pp-delivery-place { min-width: 96px; font-weight: 700; }
body:not(.admin-body) .pp-delivery-to { font-weight: 700; }
body:not(.admin-body) .pp-delivery-note { margin: 6px 0 0; font-size: 12px; line-height: 1.4; color: var(--ink-2); }
/* "Similar items in stock" — under the box on a phone; the full width under the three columns on a laptop. */
body:not(.admin-body) .pp-similar { margin-top: var(--s5); min-width: 0; }
body:not(.admin-body) .pp-similar .prod-row { padding-left: 0; padding-right: 0; }
@media (min-width: 900px) {
    body:not(.admin-body) .pp-root {
        grid-template-areas: "crumb crumb" "gal det" "gal box" "sim sim" "rev rev" "more more";
        grid-template-rows: auto auto 1fr auto auto auto;
    }
    body:not(.admin-body) .pp-similar { grid-area: sim; }
}
@media (min-width: 1200px) {
    body:not(.admin-body) .pp-root {
        grid-template-areas: "crumb crumb crumb" "gal det box" "sim sim sim" "rev rev rev" "more more more";
        grid-template-rows: auto auto auto auto auto;
    }
}

/* ── THE CART: the delivery discount line, under the cart's top line ── */
body:not(.admin-body) .cart-deal { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 14px; padding: 12px 14px; border-radius: 8px; border: 1px solid transparent; }
body:not(.admin-body) .cart-deal[hidden] { display: none; }
body:not(.admin-body) .cart-deal.is-gap { background: var(--gold-tint); border-color: var(--gold-tint-line); }
body:not(.admin-body) .cart-deal.is-met { background: var(--paid-green-bg); border-color: var(--paid-green-bg); }
body:not(.admin-body) .cart-deal-ic { flex: 0 0 auto; width: 20px; height: 20px; margin-top: 1px; color: var(--gold-ink); }
body:not(.admin-body) .cart-deal.is-met .cart-deal-ic { color: var(--paid-green); }
body:not(.admin-body) .cart-deal-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
body:not(.admin-body) .cart-deal-main { font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--ink); }
body:not(.admin-body) .cart-deal-sub { font-size: 12px; line-height: 1.4; color: var(--ink-2); }

/* ── MY ORDERS — server pages of 20, each order a card ── */
body:not(.admin-body) .orders-showing { margin: 0 0 10px; font-size: 13px; color: var(--ink-2); }
body:not(.admin-body) .orders-rows { display: flex; flex-direction: column; gap: 12px; }
body:not(.admin-body) .oc { display: flex; flex-direction: column; gap: 10px; padding: 14px; border: 1px solid var(--divider); border-radius: 10px; background: #fff; }
body:not(.admin-body) .oc-head {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; width: 100%; min-height: 32px; padding: 0;
    background: none; border: none; font: inherit; text-align: left; color: var(--ink); cursor: pointer;
}
body:not(.admin-body) .oc-head:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
body:not(.admin-body) .oc-id { font-size: 15px; font-weight: 700; white-space: nowrap; }
body:not(.admin-body) .oc-head .status-badge { flex: 0 0 auto; width: auto; padding: 2px 8px; font-size: var(--fs-micro); white-space: nowrap; }
body:not(.admin-body) .oc-end { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }   /* the total and the chevron move together */
body:not(.admin-body) .oc-total { font-size: 15px; font-weight: 700; white-space: nowrap; }
body:not(.admin-body) .oc-chev { flex: 0 0 auto; width: 18px; height: 18px; color: var(--ink-2); }
body:not(.admin-body) .oc-when { margin: 0; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--ink); }
body:not(.admin-body) .oc-when.is-delivered { color: var(--paid-green); }
body:not(.admin-body) .oc-when-date { font-weight: 400; color: var(--ink-2); }
/* Gallery batch, part C: a LATE order's line — an 18px warning icon and "Running late. We expected it by …" in
   --amber-ink (4.95:1 on the white card); a new date reads in the line's normal dark bold. */
body:not(.admin-body) .oc-when.is-late { display: flex; align-items: center; gap: 6px; color: var(--amber-ink); }
body:not(.admin-body) .oc-when .late-ic { flex: 0 0 18px; display: block; }
/* The four-step progress line: 20px dots joined by a 2px line, orange up to the current step. */
body:not(.admin-body) .oc-steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 2px 0 0; padding: 0; list-style: none; }
body:not(.admin-body) .oc-step { position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; font-size: 12px; line-height: 1.3; color: var(--ink-2); }
body:not(.admin-body) .oc-step::before { content: ""; position: absolute; top: 9px; left: -50%; width: 100%; height: 2px; background: var(--control-edge); }
body:not(.admin-body) .oc-step:first-child::before { display: none; }
body:not(.admin-body) .oc-step.is-done::before { background: var(--orange-ink); }
body:not(.admin-body) .oc-dot { position: relative; z-index: 1; box-sizing: border-box; width: 20px; height: 20px; border-radius: 50%; background: #fff; border: 2px solid var(--control-edge); }
body:not(.admin-body) .oc-step.is-done .oc-dot { background: var(--orange-ink); border-color: var(--orange-ink); }
body:not(.admin-body) .oc-step-name { font-weight: 700; color: var(--ink); }
body:not(.admin-body) .oc-step:not(.is-done) .oc-step-name { font-weight: 400; color: var(--ink-2); }
body:not(.admin-body) .oc-step-date { min-height: 1.3em; }
body:not(.admin-body) .oc-items { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
body:not(.admin-body) .oc-item { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: 14px; color: var(--ink); }
body:not(.admin-body) .oc-thumb { flex: 0 0 auto; width: 40px; height: 40px; border-radius: 6px; overflow: hidden; background: var(--surface); }
body:not(.admin-body) .oc-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
body:not(.admin-body) .oc-item-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body:not(.admin-body) .oc-item-more { padding-left: 50px; font-size: 13px; color: var(--ink-2); }
/* Buy again: white, 1px border, the full width, 44px; its result under it. */
body:not(.admin-body) .oc-again,
body:not(.admin-body) .rcpt-again { display: flex; flex-direction: column; gap: 8px; }
body:not(.admin-body) .btn-buyagain {
    width: 100%; min-height: 44px; padding: 0 16px; border-radius: var(--r-btn); border: 1px solid var(--control-edge);
    background: #fff; color: var(--ink); font: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
body:not(.admin-body) .btn-buyagain:hover { border-color: var(--ink-2); }
body:not(.admin-body) .btn-buyagain:disabled { opacity: .6; cursor: progress; }
body:not(.admin-body) .ba-result { display: flex; flex-direction: column; gap: 6px; }
body:not(.admin-body) .ba-result[hidden] { display: none; }
body:not(.admin-body) .ba-ok { margin: 0; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--paid-green); }
body:not(.admin-body) .ba-skip { margin: 0; font-size: 13px; line-height: 1.4; color: var(--ink-2); }
body:not(.admin-body) .btn-gotocart {
    align-self: flex-start; display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px;
    border-radius: var(--r-btn); background: var(--orange); color: var(--ink); font-size: 15px; font-weight: 700; text-decoration: none;
}
body:not(.admin-body) .btn-gotocart:hover, body:not(.admin-body) .btn-gotocart:active { background: var(--orange-dark); color: #000; }
body:not(.admin-body) .orders-pager { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 16px; }
body:not(.admin-body) .orders-pg { min-height: 44px; padding: 0 16px; border-radius: var(--r-btn); border: 1px solid var(--control-edge); background: #fff; color: var(--ink); font: inherit; font-size: 15px; font-weight: 700; cursor: pointer; }
body:not(.admin-body) .orders-pg:disabled { opacity: .45; cursor: default; }
body:not(.admin-body) .orders-pg-now { font-size: 13px; color: var(--ink-2); }

/* ── SAVED ITEMS (the Account Center) ── */
body:not(.admin-body) .sv-list { display: flex; flex-direction: column; }
body:not(.admin-body) .sv-row { display: flex; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--divider); }
body:not(.admin-body) .sv-photo { display: block; flex: 0 0 84px; width: 84px; height: 84px; border-radius: 8px; overflow: hidden; background: var(--surface); }
body:not(.admin-body) .sv-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
body:not(.admin-body) .sv-main { display: flex; flex-direction: column; gap: 3px; flex: 1 1 auto; min-width: 0; }
body:not(.admin-body) .sv-name { font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--ink); text-decoration: none; }
body:not(.admin-body) .sv-name:hover { text-decoration: underline; }
body:not(.admin-body) .sv-price { font-size: 14px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
body:not(.admin-body) .sv-stock { font-size: 13px; font-weight: 700; }
body:not(.admin-body) .sv-stock.is-in { color: var(--paid-green); }
body:not(.admin-body) .sv-stock.is-out { color: var(--danger); }
body:not(.admin-body) .sv-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 6px; }
body:not(.admin-body) .sv-act {
    display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 16px;
    border-radius: var(--r-btn); background: var(--orange); border: 1px solid var(--orange); color: var(--ink);
    font: inherit; font-size: 14px; font-weight: 700; text-decoration: none; cursor: pointer;
}
body:not(.admin-body) .sv-act:hover, body:not(.admin-body) .sv-act:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
body:not(.admin-body) .sv-act-ghost { background: #fff; color: var(--ink); border-color: var(--control-edge); }
body:not(.admin-body) .sv-act-ghost:hover { background: var(--surface); border-color: var(--ink-2); }
body:not(.admin-body) .sv-remove { min-height: 44px; padding: 0 4px; background: none; border: none; color: var(--ink-2); font: inherit; font-size: 14px; text-decoration: underline; cursor: pointer; }
body:not(.admin-body) .sv-loading { margin: 12px 0; font-size: 14px; color: var(--ink-2); }

/* ── ORANGE BUTTONS WITHOUT A HOVER OF THEIR OWN (batch 3A follow-up 4, the owner's decision): the same hover and pressed
   state as every orange button — --orange-dark with #000 text and icons (5.19:1). The sign-in slot's button needs its own
   line: its fill rule out-ranks the shared hover. (The console's own buttons have theirs beside their rules.) ── */
body:not(.admin-body) #ftk-idle-stay:hover, body:not(.admin-body) #ftk-idle-stay:active,
body:not(.admin-body).ftk-auth-forgot .abtn:hover, body:not(.admin-body).ftk-auth-forgot .abtn:active,
body:not(.admin-body).ftk-auth-reset .abtn:hover, body:not(.admin-body).ftk-auth-reset .abtn:active,
body:not(.admin-body).ftk-auth-verify .vbtn:not(.secondary):hover, body:not(.admin-body).ftk-auth-verify .vbtn:not(.secondary):active,
body:not(.admin-body) .ls-slot .acc-btn:not(.ghost):hover, body:not(.admin-body) .ls-slot .acc-btn:not(.ghost):active {
    background: var(--orange-dark); border-color: var(--orange-dark); color: #000;
}

/* ══ Final colour round — placeholder text. The browsers draw it #A9A9A9 / #757575 by default (2.35:1 / 4.41:1 on the
   fields' #FAFAFA); it is text, so it takes the secondary text colour (5.33:1 on white). opacity 1: one browser fades
   placeholders on its own. The console's twin is with the console's field rules. ══ */
body:not(.admin-body) ::placeholder { color: var(--ink-2); opacity: 1; }

/* ═══════════════════════════════════════════════════════════════════════════
   BATCH 3B — REPORT A PROBLEM (report.html, report.js) and the My orders blocks
   FTK tokens only. Text: --ink on white (17.4:1), --ink-2 secondary (5.36:1), links and controls --orange-ink
   (4.99:1), errors --danger (#B3261E, 6.54:1), the send button --ink on --orange (5.82:1; hover #000 on
   --orange-dark, 5.19:1). Controls 48px (the stepper and chips 36px — "small"), radius 6; cards and fields 8;
   pills 999. Mobile first; nothing is wider than the column at 320px. Selectors carry body:not(.admin-body)
   where they style a <p>, so the page type scale (which sets p at (0,2,1)) cannot override them.
   ═══════════════════════════════════════════════════════════════════════════ */
body:not(.admin-body) .rp-page { max-width: 640px; margin: 0 auto; padding: var(--s5) var(--shell-pad) var(--s7); box-sizing: border-box; }
body:not(.admin-body) .rp-back { display: inline-flex; align-items: center; min-height: 44px; color: var(--orange-ink); font-size: 15px; font-weight: 700; text-decoration: none; }
body:not(.admin-body) .rp-back:hover { text-decoration: underline; }
body:not(.admin-body) .rp-title { margin: var(--s2) 0 var(--s1); font-size: var(--fs-title); line-height: var(--lh-head); font-weight: 700; color: var(--ink); }
body:not(.admin-body) .rp-title:focus { outline: none; }
body:not(.admin-body) .rp-meta { margin: 0 0 var(--s4); font-size: var(--fs-meta); line-height: 1.5; color: var(--ink-2); }
body:not(.admin-body) .rp-state { margin: 0 0 var(--s4); }
body:not(.admin-body) .rp-state[hidden], body:not(.admin-body) .rp-form[hidden], body:not(.admin-body) .rp-err[hidden],
body:not(.admin-body) .rp-photos[hidden], body:not(.admin-body) .rp-add-photo[hidden] { display: none; }
body:not(.admin-body) .rp-state-line { margin: 0 0 var(--s2); font-size: var(--fs-body); line-height: var(--lh-body); color: var(--ink); }
body:not(.admin-body) .rp-state-link { display: inline-flex; align-items: center; min-height: 44px; color: var(--orange-ink); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
body:not(.admin-body) .rp-state.is-sent { padding: var(--s4); border: var(--bw) solid var(--divider); border-radius: var(--r-card); background: var(--paid-green-bg); }
body:not(.admin-body) .rp-sent-h { margin: 0 0 var(--s2); font-size: var(--fs-head); font-weight: 700; color: var(--paid-green); }   /* 4.78:1 on --paid-green-bg */
body:not(.admin-body) .rp-sent-h:focus { outline: none; }
body:not(.admin-body) .rp-sec { margin: 0 0 var(--s5); }
body:not(.admin-body) .rp-h { display: block; margin: 0 0 var(--s2); font-size: var(--fs-head); line-height: var(--lh-head); font-weight: 700; color: var(--ink); }
body:not(.admin-body) .rp-help { margin: 0 0 var(--s2); font-size: var(--fs-meta); line-height: 1.5; color: var(--ink-2); }
body:not(.admin-body) .rp-err { margin: var(--s2) 0 0; font-size: var(--fs-meta); line-height: 1.5; color: var(--danger); }
body:not(.admin-body) .rp-err-form { margin: 0 0 var(--s3); }

body:not(.admin-body) .rp-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
body:not(.admin-body) .rp-line { border: var(--bw) solid var(--divider); border-radius: var(--r-card); background: var(--page); }
body:not(.admin-body) .rp-line-pick { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s3); cursor: pointer; min-height: 48px; box-sizing: border-box; }
body:not(.admin-body) .rp-check { flex: 0 0 20px; width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--orange-ink); }
body:not(.admin-body) .rp-line-text { display: flex; flex-direction: column; min-width: 0; }
body:not(.admin-body) .rp-line-name { font-size: 15px; font-weight: 700; color: var(--ink); line-height: 1.4; overflow-wrap: anywhere; }
body:not(.admin-body) .rp-line-sub { font-size: var(--fs-meta); color: var(--ink-2); line-height: 1.5; }
body:not(.admin-body) .rp-line-more { padding: 0 var(--s3) var(--s3) calc(var(--s3) + 20px + var(--s3)); }
body:not(.admin-body) .rp-qty-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin: 0 0 var(--s2); }
body:not(.admin-body) .rp-sub { margin: 0 0 var(--s2); font-size: var(--fs-meta); font-weight: 700; color: var(--ink); line-height: 1.4; }
body:not(.admin-body) .rp-qty-row .rp-sub { margin: 0; }
body:not(.admin-body) .rp-stepper { display: inline-flex; align-items: center; border: var(--bw) solid var(--control-edge); border-radius: var(--r-btn); overflow: hidden; }
body:not(.admin-body) .rp-step { width: 36px; height: 36px; padding: 0; border: 0; background: var(--page); color: var(--orange-ink); font-family: inherit; font-size: 18px; font-weight: 700; cursor: pointer; }
body:not(.admin-body) .rp-step:disabled { color: #8A8A84; cursor: not-allowed; }   /* a disabled control: exempt from 1.4.3, still 3.47:1 */
body:not(.admin-body) .rp-step-val { min-width: 36px; text-align: center; font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
body:not(.admin-body) .rp-chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
body:not(.admin-body) .rp-chip { position: relative; display: inline-flex; }
body:not(.admin-body) .rp-chip-input { position: absolute; opacity: 0; width: 1px; height: 1px; }
body:not(.admin-body) .rp-chip-text {
    display: inline-flex; align-items: center; min-height: 36px; padding: 0 var(--s3); box-sizing: border-box;
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-pill); background: var(--page);
    color: var(--ink); font-size: 14px; font-weight: 700; cursor: pointer;
}
body:not(.admin-body) .rp-chip-input:checked + .rp-chip-text { border: 2px solid var(--orange-ink); padding: 0 11px; background: rgba(224, 123, 31, .06); color: var(--ink); }
body:not(.admin-body) .rp-chip-input:focus-visible + .rp-chip-text { outline: 3px solid var(--orange-ink); outline-offset: 2px; }

body:not(.admin-body) .rp-photos { list-style: none; margin: 0 0 var(--s2); padding: 0; display: flex; flex-wrap: wrap; gap: var(--s3); }
body:not(.admin-body) .rp-photo { display: flex; flex-direction: column; align-items: center; gap: var(--s1); }
body:not(.admin-body) .rp-photo-img { width: 72px; height: 72px; object-fit: cover; border-radius: var(--r-card); border: var(--bw) solid var(--divider); background: var(--surface); }
body:not(.admin-body) .rp-photo-wait { width: 72px; height: 72px; justify-content: center; border: var(--bw) dashed var(--control-edge); border-radius: var(--r-card); }
body:not(.admin-body) .rp-photo-spin { font-size: 12px; color: var(--ink-2); }
body:not(.admin-body) .rp-photo-rm { min-height: 36px; padding: 0 var(--s1); border: 0; background: none; color: var(--orange-ink); font-family: inherit; font-size: 13px; font-weight: 700; text-decoration: underline; cursor: pointer; }
body:not(.admin-body) .rp-add-photo {
    position: relative; display: inline-flex; align-items: center; gap: var(--s2); min-height: 48px; padding: 0 var(--s4); box-sizing: border-box;
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-btn); background: var(--page);
    color: var(--orange-ink); font-size: 15px; font-weight: 700; cursor: pointer;
}
body:not(.admin-body) .rp-add-photo:hover { border-color: var(--orange-ink); }
body:not(.admin-body) .rp-add-photo:focus-within { outline: 3px solid var(--orange-ink); outline-offset: 2px; }
body:not(.admin-body) .rp-file { position: absolute; opacity: 0; width: 1px; height: 1px; }

body:not(.admin-body) .rp-options { display: grid; grid-template-columns: 1fr; gap: var(--s2); margin: 0 0 var(--s2); }
@media (min-width: 560px) { body:not(.admin-body) .rp-options { grid-template-columns: 1fr 1fr; } }
body:not(.admin-body) .rp-option { position: relative; display: flex; cursor: pointer; }
body:not(.admin-body) .rp-option-input { position: absolute; opacity: 0; width: 1px; height: 1px; }
body:not(.admin-body) .rp-option-body {
    flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--s1); padding: var(--s3) var(--s4); min-height: 48px; box-sizing: border-box;
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-card); background: var(--page);
}
body:not(.admin-body) .rp-option-input:checked + .rp-option-body { border: 2px solid var(--orange-ink); padding: 11px 15px; background: rgba(224, 123, 31, .06); }
body:not(.admin-body) .rp-option-input:focus-visible + .rp-option-body { outline: 3px solid var(--orange-ink); outline-offset: 2px; }
body:not(.admin-body) .rp-option-title { font-size: 15px; font-weight: 700; color: var(--ink); }
body:not(.admin-body) .rp-option-sub { font-size: var(--fs-meta); color: var(--ink-2); line-height: 1.5; }
body:not(.admin-body) .rp-note {
    display: block; width: 100%; min-height: 96px; padding: var(--s3); box-sizing: border-box; resize: vertical;
    font-family: inherit; font-size: 16px; line-height: 1.5; color: var(--ink); background: var(--page);
    border: var(--bw) solid var(--control-edge); border-radius: var(--r-card);
}
body:not(.admin-body) .rp-note:focus { outline: none; border-color: var(--orange-ink); box-shadow: 0 0 0 3px rgba(224, 123, 31, .18); }
body:not(.admin-body) .rp-count { margin: var(--s1) 0 0; text-align: right; font-size: var(--fs-meta); color: var(--ink-2); font-variant-numeric: tabular-nums; }
body:not(.admin-body) .rp-send {
    display: flex; align-items: center; justify-content: center; width: 100%; min-height: 48px; padding: 0 var(--s4);
    background: var(--orange); color: var(--ink); border: var(--bw) solid var(--orange); border-radius: var(--r-btn);
    font-family: inherit; font-size: 16px; font-weight: 700; cursor: pointer;
}
body:not(.admin-body) .rp-send:hover, body:not(.admin-body) .rp-send:active { background: var(--orange-dark); border-color: var(--orange-dark); color: #000; }
body:not(.admin-body) .rp-send[disabled] { opacity: .6; cursor: progress; }
@media (min-width: 560px) { body:not(.admin-body) .rp-send { width: auto; min-width: 220px; } }
/* My orders (account.js — batch 3B): the "Refunded" and "Problem report" blocks and "Report a problem". */
body:not(.admin-body) .oc-block { display: flex; flex-direction: column; gap: 6px; padding: 12px; border: 1px solid var(--divider); border-radius: var(--r-card); background: var(--surface); }
body:not(.admin-body) .oc-block-h { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--ink); }
body:not(.admin-body) .oc-block-row { display: flex; flex-direction: column; gap: 2px; }
body:not(.admin-body) .oc-block-row + .oc-block-row { padding-top: 6px; border-top: 1px solid var(--divider); }
body:not(.admin-body) .oc-block-items { display: flex; justify-content: space-between; gap: 12px; margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink); overflow-wrap: anywhere; }
body:not(.admin-body) .oc-block-amt { flex: 0 0 auto; font-weight: 700; white-space: nowrap; }
body:not(.admin-body) .oc-block-line { margin: 0; font-size: var(--fs-meta); line-height: 1.5; color: var(--ink-2); }   /* 4.98:1 on --surface */
body:not(.admin-body) .oc-block-list { margin: 0; padding-left: 18px; font-size: var(--fs-meta); line-height: 1.5; color: var(--ink); }
body:not(.admin-body) .oc-pill { display: inline-flex; align-items: center; min-height: 22px; padding: 0 10px; border-radius: var(--r-pill); font-size: 12px; font-weight: 700; line-height: 1; white-space: nowrap; }
body:not(.admin-body) .oc-pill-amber { background: #FFF4DB; color: var(--amber-ink); }      /* 4.53:1 */
body:not(.admin-body) .oc-pill-green { background: var(--paid-green-bg); color: var(--paid-green); }   /* 4.78:1 */
body:not(.admin-body) .oc-pill-grey { background: #EDEDEA; color: #545450; }              /* 6.48:1 */
body:not(.admin-body) .oc-report { display: flex; flex-direction: column; gap: 6px; }
body:not(.admin-body) .btn-report {
    display: inline-flex; align-items: center; justify-content: center; width: 100%; min-height: 48px; padding: 0 16px; box-sizing: border-box;
    border-radius: var(--r-btn); border: 1px solid var(--control-edge); background: #fff; color: var(--orange-ink);
    font-size: 15px; font-weight: 700; text-decoration: none;
}
body:not(.admin-body) .btn-report:hover { border-color: var(--orange-ink); }
body:not(.admin-body) .oc-report-line { margin: 0; font-size: var(--fs-meta); line-height: 1.5; color: var(--ink-2); }
body:not(.admin-body) .oc-report-line a { color: var(--orange-ink); font-weight: 700; }
