/* ============================================================================
   CamperBay.nl — MOBILE / PWA app design for the SHARED INNER-PAGE chrome
   (system/header.php `.cp-*` + system/footer.php `.mp-tabbar` + `.cp-foot`).
   --------------------------------------------------------------------------
   SEPARATE mobile design. EVERY rule is inside @media(max-width:768px) (or a base
   display:none on a new mobile-only element), so the DESKTOP render stays
   byte-identical — the desktop design is FROZEN (camperplaats/app.md §0).
   Loaded on every inner page (header.php), AFTER header.css so ≤768px wins.
   Mirrors assets/css/home-mobile.css so homepage + inner pages share ONE mobile
   app-shell. Layout ref: MOBILE-PWA-HANDBOOK.md. Functions = the real portal's.
   Built section by section; grows as inner surfaces convert.
   Dark mode for inner pages is added in a later pass (this file first does the
   light app-bar; the .mp-tabbar bottom nav already exists in mp.css).
   ============================================================================ */

@media(max-width:768px){

  /* ===== APP BAR — compact. `.cp-header` is already sticky (header.css); the dark
         `.cp-topbar` (location + language) scrolls away above it. Search shown full
         width (header.css hides it ≤820); Saved/Account/Sell nav moves to the bottom
         `.mp-tabbar`. Every chrome FUNCTION stays reachable. ===== */
  .cp-header .cp-wrap{gap:12px}
  .cp-header .headsearch{display:flex;flex:1;min-width:0;max-width:none;margin:0}
  .cp-header .headsearch input{min-width:0}
  .cp-header .headnav{display:none}

  /* topbar — IDENTICAL layout to the homepage (.topbar in home-mobile.css:48-54): location
     pill sits at the LEFT (the ship note .left is hidden, so space-between drops it to flex-start)
     and the langs follow to the right. ⚠ was justify-content:flex-end here → it crammed the whole
     .cp-topright to the RIGHT with an empty gap on the left = the "topbar squeezes" the user saw. */
  .cp-topbar .cp-wrap{height:auto;min-height:34px;padding-top:5px;padding-bottom:5px;gap:8px;justify-content:space-between}
  .cp-topbar .left{display:none}                 /* ship note hidden → drop the empty flex child */
  .cp-topbar .cp-topright{flex-wrap:nowrap;gap:6px 8px;min-width:0}
  .cp-deliver{height:28px;min-width:0;max-width:100%}
  .cp-deliver .dt-l{display:none}                /* drop "Locatie:" label; keep pin + value */
  .cp-deliver .dt-v{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:120px}

  /* category nav → scrollable chip chooser (the row is already overflow-x:auto) */
  .cp-catnav .cp-wrap{gap:6px;height:auto;padding-top:8px;padding-bottom:8px}
  .cp-catnav a{border:1px solid var(--line);border-radius:20px;padding:7px 13px;font-size:12.5px;background:var(--card);flex:0 0 auto}
}

/* ============================================================================
   APP-SHELL CONSISTENCY — make the inner-page bottom nav (.mp-tabbar, footer.php)
   a subtle FLOATING pill matching the homepage (.m-tabbar) so the whole app shares
   ONE shell (master-prompt §5.3 "subtle floating container"). The mp.css FAB is
   already the correct rounded-square amber; here we just lift the bar off the edges
   + blur it. All ≤768; .mp-tabbar is display:none on desktop → desktop FROZEN.
   ============================================================================ */
@media(max-width:768px){
  /* clear the floating bar (mp.css reserves 60px for the old flush bar) */
  body{padding-bottom:calc(80px + env(safe-area-inset-bottom))!important}
  .mp-tabbar{left:12px;right:12px;bottom:calc(10px + env(safe-area-inset-bottom));
    border:1px solid var(--mp-line);border-radius:22px;
    background:rgba(255,255,255,.9);backdrop-filter:blur(18px) saturate(1.5);-webkit-backdrop-filter:blur(18px) saturate(1.5);
    padding:7px 6px calc(7px + env(safe-area-inset-bottom));
    box-shadow:0 8px 26px -8px rgba(21,33,28,.3)}
  .mp-tab{min-height:48px}

  /* ⚠ .mp-page runs a fade-in (mp.css) whose keyframe animates `transform:translateY`.
     A transformed ancestor makes position:fixed anchor to IT, not the viewport — which
     broke the filter BOTTOM SHEET (it dropped below the page instead of sliding up from
     the viewport bottom). Drop the transform-based fade on mobile so fixed sheets anchor
     to the viewport. Desktop keeps the fade (frozen). */
  .mp-page{animation:none}
}

/* ============================================================================
   APP-BAR + NAV DRAWER consistency — make every inner page's header match the
   homepage: boxed burger + centred brand + boxed saved, and a left off-canvas NAV
   drawer opened by the burger (on non-account pages; account pages keep their own
   account drawer — see footer.php JS). All ≤768 / base display:none on new elements
   → DESKTOP FROZEN. The drawer sits outside .cp-chrome, so its brand tokens are
   defined on .m-drawer itself (dark overrides deferred with the rest of dark).
   ============================================================================ */
.cp-hsaved,.m-drawer,.m-scrim,.lp-handle{display:none}

/* ============================================================================
   LANGUAGE → a compact trigger + bottom sheet on mobile (DAY 27, user-reported).
   ⭐ THE FOUR INLINE LANGUAGE LINKS WERE BREAKING THE WHOLE PAGE, not just crowding
   it. MEASURED at a 320px viewport: `.langs` is a non-shrinking 139px row (42% of the
   topbar's content width) that ran to x=348 — 28px past the screen — so the DOCUMENT
   itself became 349px wide. And because `.m-tabbar`/`.mp-tabbar` are position:fixed
   with left/right insets, they size to that widened initial containing block, which is
   exactly the second bug the user reported: **the bottom nav hanging off the screen.**
   Proof: hiding `.langs` alone took the document 349→320 and the bar's right edge
   337→308. One cause, both symptoms.
   THE FIX follows the master prompt (§11 "bottom sheets for filters, sorting, location,
   LANGUAGE and simple choices" · §21 sheet requirements) and, deliberately, the exact
   pattern of the location pill sitting next to it — same trigger shape, same sheet, same
   scrim and scroll-lock — so the utility strip reads as one system.
   ⚠ DESKTOP FROZEN: the wrappers are display:contents and the trigger/handle/title are
   display:none at ≥769px, so `.langs` renders in precisely its approved place; verified
   byte-identical at 1280.
   ============================================================================ */
.cp-langwrap,.cp-langpop{display:contents}
.cp-langbtn{display:none}
.cp-langpop h4{display:none}
/* the flag and the full language name exist ONLY for the mobile sheet — hidden at every other
   width so the desktop topbar keeps rendering the bare NL/DE/FR/EN codes it always did */
.langs .flag,.langs .lg-name{display:none}

@media(max-width:768px){
  /* app bar — IDENTICAL to the homepage: boxed burger + centred brand + boxed saved on
     row 1, full-width search on row 2. ⚠ header.css fixes .cp-wrap to height:64px, which
     clipped the wrapped search row so it overlapped the catnav — override to auto height. */
  .cp-header{background:rgba(239,241,237,.82);backdrop-filter:blur(14px) saturate(1.3);-webkit-backdrop-filter:blur(14px) saturate(1.3);padding-top:env(safe-area-inset-top)}
  /* ⭐ WIDTH PARITY with the homepage (fixes "inner pages look narrower / content squeezes"):
     header.css:11 fixes .cp-chrome .cp-wrap to 24px side padding, but the homepage overrides
     .wrap to 16px on mobile (home-mobile.css:39) — so the inner header + content were NARROWER
     than the homepage. Match 16px everywhere so the app chrome is identical on every page.
     .container.mp-page is header.php's UNIVERSAL content wrapper (header.php:358) → this one line
     re-insets EVERY inner page (cat/LRP/VIP/parts/seller/account/garage) to 16px. ⚠ .cp-msg (chat)
     sits INSIDE that container (chat/index.php:160→162), and account.css:424 gives it its own 10px →
     that would DOUBLE to ~26px; zero it on mobile so the container's 16px is the only inset (scope
     body.page-chat to beat account.css which loads after this file). Seller/.cp-acc already carry 0
     own-padding so they inherit the 16px correctly. */
  .cp-chrome .cp-wrap{padding-left:16px;padding-right:16px}
  .container.mp-page{padding-left:16px;padding-right:16px}
  body.page-chat .cp-msg{padding-left:0;padding-right:0}
  .cp-header .cp-wrap{height:auto;min-height:56px;flex-wrap:wrap;row-gap:10px;column-gap:12px;align-items:center;padding-top:9px;padding-bottom:11px}
  .cp-header .cp-acc-burger{display:inline-flex;order:0;width:44px;height:44px;border:1px solid var(--line);background:var(--card);border-radius:12px;color:var(--pine);flex-shrink:0;padding:0;margin:0}
  .cp-header .cp-acc-burger svg{width:23px;height:23px}
  .cp-header .brand{order:1;flex:1;justify-content:center;min-width:0}
  .cp-header .brand .name{font-size:18px}
  .cp-hsaved{display:inline-flex;order:2;align-items:center;justify-content:center;width:44px;height:44px;border:1px solid var(--line);background:var(--card);border-radius:12px;color:var(--pine);flex-shrink:0}
  .cp-hsaved svg{width:23px;height:23px;stroke:currentColor;stroke-width:1.8;fill:none}
  .cp-header .cp-acc-burger:active,.cp-hsaved:active{background:var(--mist)}
  .cp-header .headsearch{order:3;display:flex;flex:1 1 100%;min-width:0;max-width:none;margin:0;height:46px;border-radius:13px;background:var(--card)}
  .cp-header .headsearch input{min-width:0}
  /* the homepage has no category-chip row → hide the inner .cp-catnav on mobile so the
     header is identical (categories live in the nav drawer + bottom nav). */
  .cp-catnav{display:none}

  /* scrim + nav drawer (mirrors the homepage .m-drawer). ⚠ the inner .cp-header is
     position:sticky z-index:1030, so the scrim/drawer MUST sit above it (the homepage
     header is only z40). z: scrim 1290 < drawer 1300 < location sheet 1310. */
  .m-scrim{display:block;position:fixed;inset:0;z-index:1290;background:rgba(21,33,28,.5);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);opacity:0;visibility:hidden;transition:opacity .25s cubic-bezier(.22,.61,.36,1),visibility .25s cubic-bezier(.22,.61,.36,1)}
  body.m-drawer-open .m-scrim,body.m-loc-open .m-scrim,body.m-lang-open .m-scrim{opacity:1;visibility:visible}
  body.m-drawer-open,body.m-loc-open,body.m-lang-open{overflow:hidden}
  .m-drawer{--paper:#EFF1ED;--card:#fff;--line:#CBD4CC;--pine:#1F3D30;--ink:#15211C;--muted:#5C6A62;--mist:#E2E7E1;--amber:#E08A2C;
    display:flex;flex-direction:column;position:fixed;top:0;bottom:0;left:0;z-index:1300;width:min(87vw,340px);
    background:var(--paper);box-shadow:0 0 44px -8px rgba(21,33,28,.5);transform:translateX(-100%);visibility:hidden;
    transition:transform .3s cubic-bezier(.22,.61,.36,1),visibility .3s cubic-bezier(.22,.61,.36,1);
    padding-top:env(safe-area-inset-top);overscroll-behavior:contain}
  body.m-drawer-open .m-drawer{transform:none;visibility:visible}
  .m-drawer .dw-head{display:flex;align-items:center;gap:10px;padding:15px 15px 14px;border-bottom:1px solid var(--line)}
  .m-drawer .dw-head .brand{flex:0 0 auto}
  .m-drawer .dw-head .brand .name{font-family:"Archivo",system-ui,sans-serif;font-weight:800;font-size:18px;letter-spacing:-.02em}
  .m-drawer .dw-head .brand .name b{color:var(--pine)}.m-drawer .dw-head .brand .name i{font-style:normal;color:var(--amber)}
  .m-drawer .dw-head .brand .mark{width:30px;height:30px;border-radius:8px;background:var(--pine);display:grid;place-items:center;margin-right:8px}
  .m-drawer .dw-x{margin-left:auto;width:44px;height:44px;border-radius:11px;border:1px solid var(--line);background:var(--card);display:grid;place-items:center;color:var(--muted);cursor:pointer;flex-shrink:0}
  .m-drawer .dw-x svg{width:17px;height:17px;stroke:currentColor;stroke-width:2;fill:none}
  .m-drawer .dw-body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:12px 12px calc(20px + env(safe-area-inset-bottom))}
  .m-drawer .dw-sec{margin-top:12px}
  .m-drawer .dw-lbl{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);padding:0 10px;margin-bottom:5px}
  .m-drawer a.dw-link{display:flex;align-items:center;gap:13px;padding:12px 10px;border-radius:12px;color:var(--ink);font-weight:600;font-size:14.5px;text-decoration:none}
  .m-drawer a.dw-link svg{width:20px;height:20px;stroke:var(--pine);stroke-width:1.8;fill:none;flex-shrink:0}
  .m-drawer a.dw-link:active{background:var(--mist)}
  .m-drawer a.dw-sell{background:var(--amber);color:#3a2408;justify-content:center;font-family:"Archivo",system-ui,sans-serif;font-weight:700;margin:2px 0 6px;height:48px}
  .m-drawer a.dw-sell svg{stroke:#3a2408}
  .m-drawer .dw-langs{display:flex;gap:6px;padding:4px 10px 2px;flex-wrap:wrap}
  .m-drawer .dw-langs a{font-family:"JetBrains Mono",ui-monospace,monospace;font-weight:600;font-size:12px;letter-spacing:.05em;color:var(--pine);border:1px solid var(--line);background:var(--card);border-radius:9px;padding:0 14px;min-height:44px;display:inline-flex;align-items:center;text-decoration:none}
  .m-drawer .dw-langs a.active{background:var(--pine);color:#fff;border-color:var(--pine)}

  /* inner-page location popup → bottom sheet (mirrors the homepage; z ABOVE the sticky
     header). Was rendering as a broken off-screen-left desktop popup on mobile. */
  .cp-locwrap{position:static}
  .cp-locpop{position:fixed;left:0;right:0;bottom:0;top:auto;width:auto;max-width:none;z-index:1310;
    border:0;border-top:1px solid var(--line);border-radius:20px 20px 0 0;max-height:86dvh;overflow-y:auto;-webkit-overflow-scrolling:touch;
    padding:6px 18px calc(18px + env(safe-area-inset-bottom));box-shadow:0 -18px 44px -20px rgba(21,33,28,.5);
    display:block;visibility:hidden;transform:translateY(101%);transition:transform .3s cubic-bezier(.22,.61,.36,1),visibility .3s cubic-bezier(.22,.61,.36,1)}
  .cp-locpop.open{display:block;visibility:visible;transform:none}
  .cp-locpop .lp-handle{display:block;width:42px;height:4px;border-radius:99px;background:var(--line);margin:8px auto 12px}
  .cp-locpop .lp-apply{position:sticky;bottom:0;height:48px;margin-top:14px}

  /* ---- language: one compact pill (matching the location pill's 28px height so the two
     read as siblings) that opens the same kind of bottom sheet ---- */
  /* ⚠ scoped to body.m-lang-ready, which the footer/homepage script adds only after it has
     wired the pill: without JS the sheet could never open, so a no-JS visitor must keep the
     plain inline row rather than lose the language switcher entirely (progressive enhancement,
     the same contract as the footer accordion's `.js` class). */
  body.m-lang-ready .cp-langwrap{display:block;position:static}
  body.m-lang-ready .cp-langbtn{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 8px;flex-shrink:0;
    border:1px solid rgba(255,255,255,.16);border-radius:7px;background:rgba(255,255,255,.06);
    color:#D6DED8;font:600 12px/1 inherit;letter-spacing:.06em;cursor:pointer}
  body.m-lang-ready .cp-langbtn svg{width:13px;height:13px;flex-shrink:0;transition:transform .2s var(--ease,ease)}
  body.m-lang-ready .cp-langbtn[aria-expanded="true"]{background:rgba(255,255,255,.14);color:#fff}
  body.m-lang-ready .cp-langbtn[aria-expanded="true"] svg{transform:rotate(180deg)}
  body.m-lang-ready .cp-langpop{display:block;position:fixed;left:0;right:0;bottom:0;top:auto;z-index:1310;
    background:var(--card);border-top:1px solid var(--line);border-radius:20px 20px 0 0;
    max-height:86dvh;overflow-y:auto;-webkit-overflow-scrolling:touch;
    padding:6px 18px calc(18px + env(safe-area-inset-bottom));box-shadow:0 -18px 44px -20px rgba(21,33,28,.5);
    visibility:hidden;transform:translateY(101%);transition:transform .3s var(--ease,ease),visibility .3s var(--ease,ease)}
  body.m-lang-ready .cp-langpop.open{visibility:visible;transform:none}
  body.m-lang-ready .cp-langpop .lp-handle{display:block;width:42px;height:4px;border-radius:99px;background:var(--line);margin:8px auto 12px}
  body.m-lang-ready .cp-langpop h4{display:block;margin:0 0 10px;font-family:"Archivo",system-ui,sans-serif;font-size:17px;font-weight:800;letter-spacing:-.02em;color:var(--ink)}
  /* the links become full-width rows — 52px, well over the 44px target, with the current
     language marked by more than colour alone (a check) for WCAG 1.4.1 */
  body.m-lang-ready .cp-langpop .langs{display:flex;flex-direction:column;gap:6px}
  /* row: [flag] [Nederlands] [NL] [check when current] — everything vertically centred */
  body.m-lang-ready .cp-langpop .langs a{display:flex;align-items:center;gap:11px;min-height:52px;padding:0 14px;border-radius:12px;
    border:1px solid var(--line);background:var(--paper);color:var(--ink);
    font-family:"Inter",system-ui,sans-serif;font-weight:600;font-size:15px;line-height:1;text-decoration:none}
  /* CSS-only flags, same 20x14 component the location picker already uses (no image assets).
     NL/DE reuse its exact gradients; FR is built the same way (vertical thirds, like .be) and EN
     is the Union Jack layered from the same primitive — blue field, white saltire, red saltire,
     white cross, red cross. At 20x14 it reads as the flag without needing an asset. */
  body.m-lang-ready .cp-langpop .langs .flag{display:block;width:20px;height:14px;border-radius:3px;flex:0 0 20px;box-shadow:0 0 0 1px rgba(0,0,0,.1)}
  body.m-lang-ready .cp-langpop .langs .flag.nl{background:linear-gradient(#AE1C28 0 33.33%,#fff 33.33% 66.66%,#21468B 66.66%)}
  body.m-lang-ready .cp-langpop .langs .flag.de{background:linear-gradient(#000 0 33.33%,#DD0000 33.33% 66.66%,#FFCE00 66.66%)}
  body.m-lang-ready .cp-langpop .langs .flag.fr{background:linear-gradient(90deg,#0055A4 0 33.33%,#fff 33.33% 66.66%,#EF4135 66.66%)}
  body.m-lang-ready .cp-langpop .langs .flag.en{background:
    linear-gradient(to bottom,transparent 43%,#C8102E 43% 57%,transparent 57%),
    linear-gradient(to right,transparent 43%,#C8102E 43% 57%,transparent 57%),
    linear-gradient(to bottom,transparent 36%,#fff 36% 64%,transparent 64%),
    linear-gradient(to right,transparent 36%,#fff 36% 64%,transparent 64%),
    linear-gradient(45deg,transparent 45%,#C8102E 45% 55%,transparent 55%),
    linear-gradient(-45deg,transparent 45%,#C8102E 45% 55%,transparent 55%),
    linear-gradient(45deg,transparent 39%,#fff 39% 61%,transparent 61%),
    linear-gradient(-45deg,transparent 39%,#fff 39% 61%,transparent 61%),
    #012169}
  body.m-lang-ready .cp-langpop .langs .lg-name{display:block;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  body.m-lang-ready .cp-langpop .langs .lg-code{flex:0 0 auto;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:12px;font-weight:600;letter-spacing:.08em;color:var(--muted)}
  body.m-lang-ready .cp-langpop .langs a.active .lg-code{color:inherit;opacity:.72}
  body.m-lang-ready .cp-langpop .langs a:active{background:var(--mist)}
  body.m-lang-ready .cp-langpop .langs a.active{background:var(--pine);border-color:var(--pine);color:#fff}
  body.m-lang-ready .cp-langpop .langs a.active::after{content:"";margin-left:auto;width:15px;height:9px;
    border-left:2.5px solid currentColor;border-bottom:2.5px solid currentColor;transform:rotate(-45deg) translateY(-3px)}
  @media(prefers-reduced-motion:reduce){.m-drawer,.m-scrim,.cp-locpop,.cp-langpop{transition:none}}
}

/* theme toggle button — base HIDDEN (desktop frozen: no dark UI on desktop) */
.cp-theme-toggle{display:none;align-items:center;justify-content:center;width:30px;height:26px;border:1px solid rgba(255,255,255,.16);border-radius:7px;background:rgba(255,255,255,.06);color:#D6DED8;cursor:pointer;padding:0;flex-shrink:0}
.cp-theme-toggle:hover{background:rgba(255,255,255,.12)}
.cp-theme-toggle svg{width:15px;height:15px;stroke:currentColor;stroke-width:1.9;fill:none}

/* VIP sticky bottom action bar + gallery image counter — base HIDDEN (desktop frozen) */
.vip-actionbar{display:none}
.galcount{display:none}

/* ============================================================================
   DARK MODE — INNER PAGES, MOBILE ONLY (≤768px). Desktop frozen: no [data-theme]
   rules exist outside this media query. Remaps the TWO token systems so token-driven
   rules adapt automatically: content `--mp-*` (mp.css/theme.css) + chrome `.cp-chrome`
   (header.css). Chrome hardcoded-hex overridden here. Per-page content hardcoded hex
   (results.css/listing.css/account.css/bootstrap) is completed per-surface as each
   converts. Palette = DARKMODE-BRIEF.md (measured, WCAG).
   ============================================================================ */
@media(max-width:768px){
  .cp-theme-toggle{display:inline-flex}

  /* content design tokens (mp.css :root, re-pointed by theme.css) */
  html[data-theme="dark"]{
    --mp-ink:rgba(255,255,255,.88); --mp-muted:rgba(255,255,255,.62);
    --mp-line:#586760; --mp-bg:#141716; --mp-card:#292E2C;
    --mp-primary:#5FA584; --mp-primary-hover:#7EB99E; --mp-primary-050:#1e2a24;
  }
  /* chrome tokens (header.css .cp-chrome, self-scoped) */
  html[data-theme="dark"] .cp-chrome{
    --paper:#141716; --card:#292E2C; --line:#586760; --mist:#252A28;
    --ink:rgba(255,255,255,.88); --muted:rgba(255,255,255,.62);
    --pine:#5FA584; --pine-2:#4E8163; --fern:#7EB99E;
  }
  html[data-theme="dark"] body{font-weight:420}

  /* chrome hardcoded / overloaded-token overrides */
  html[data-theme="dark"] .cp-topbar{background:#0F1210}            /* was var(--ink); --ink is now light */
  html[data-theme="dark"] .cp-header{background:rgba(20,23,22,.92)}
  html[data-theme="dark"] .cp-locpop .lp-country:hover{background:var(--paper)}
  html[data-theme="dark"] .cp-locpop .lp-country.on{background:#20302a;border-color:var(--fern)}
  html[data-theme="dark"] .cp-locpop .lp-apply{color:#0F150E}

  /* bottom tab bar (mp.css hardcodes #fff at ≤768) */
  html[data-theme="dark"] .mp-tabbar{background:#292E2C;border-top-color:#586760}

  /* custom dropdowns (cpselect.css hardcoded hex) — shared by every inner-page filter/sort */
  html[data-theme="dark"] .cpsel-btn{background:#141716;border-color:#586760;color:rgba(255,255,255,.62)}
  html[data-theme="dark"] .cpsel-btn.set,
  html[data-theme="dark"] .cpsel.open .cpsel-btn{background:#292E2C;border-color:#7EB99E;color:rgba(255,255,255,.88)}
  html[data-theme="dark"] .cpsel-menu{background:#292E2C;border-color:#586760}
  html[data-theme="dark"] .cpsel-search{background:#141716;border-color:#586760;color:rgba(255,255,255,.62)}
  html[data-theme="dark"] .cpsel-search input{color:rgba(255,255,255,.88)}
  html[data-theme="dark"] .cpsel-opt{color:rgba(255,255,255,.85)}
  html[data-theme="dark"] .cpsel-opt:hover{background:#252A28}
  html[data-theme="dark"] .cpsel-opt.cpsel-sel{background:#183A2A;color:#7EB99E}
  html[data-theme="dark"] .cpsel-opt .cpsel-tick{color:#7EB99E}
  html[data-theme="dark"] .cpsel-empty{color:rgba(255,255,255,.62)}
  /* ⚠ the crowned banner row in the section list carries a hardcoded LIGHT amber pair
     (#FDF4E3/#8a5a12, account.css) — this is the project's dark counterpart for that pair, so it
     reads as a highlight rather than a bright hole in a dark menu. The crown keeps its amber. */
  html[data-theme="dark"] body.act-add .cpsel-opt[data-v="cp-adv"]{background:#3A2D16;color:#E6C294;border-top-color:#586760}
  html[data-theme="dark"] body.act-add .cpsel-opt[data-v="cp-adv"]:hover{background:#46361a}

  /* native <select> (theme.css hardcodes light) */
  html[data-theme="dark"] select{background-color:#141716;border-color:#586760;color:rgba(255,255,255,.88)}
}

/* ============================================================================
   SURFACE: LRP / SEARCH RESULTS (plugins/cat/ads_list.php + results.css).
   The filter BOTTOM SHEET (.mp-filters → mpOpenFilters/mp-sheet-backdrop) + the
   1-col collapse already exist in mp.css. Here: 2-column app card grid + drop the
   redundant "Bekijken" button (the whole .lcard is a link) + dark. Dark remaps
   results.css's own --cp-* tokens (adapts most rules) + hardcoded-hex overrides.
   ============================================================================ */
@media(max-width:768px){
  /* 2-col app grid — higher specificity (.mp-lrp) beats results.css ≤560 1-col */
  .mp-lrp .lr-results.grid{grid-template-columns:1fr 1fr;gap:11px}
  .mp-lrp .lr-results.grid .lthumb{height:132px}
  .mp-lrp .lr-results.grid .lfoot{padding:11px 13px}
  .mp-lrp .lr-results.grid .lfoot .lbtn{display:none}   /* card is a link → button redundant */
  .lcard:active{transform:scale(.985)}

  /* ---- LRP toolbar (§9.7): result count on its own line, then ONE clean control row
     [Filter · Sort · Save · view]. Was wrapping into ~3 rows. The sort <select> is
     enhanced by cpselect into a .cpsel wrapper → target both (and native as fallback). ---- */
  .mp-lrp .lr-toolbar{gap:8px;align-items:center;margin-bottom:12px}
  .mp-lrp .lr-count{order:-1;flex:1 0 100%;font-size:14px;font-weight:700}
  .mp-lrp .lr-count b{color:var(--cp-pine)}
  .mp-lrp .lr-count span{display:none}                 /* drop the "in this category" sub */
  .mp-lrp .lr-spacer{display:none}
  .mp-lrp .lr-filter-toggle{order:1;flex-shrink:0;height:40px;padding:0 13px;font-size:13.5px}
  .mp-lrp .lr-toolbar .lr-sort,
  .mp-lrp .lr-toolbar .cpsel{order:2;flex:1 1 0;min-width:56px}
  .mp-lrp .lr-toolbar .lr-sort{height:40px}
  .mp-lrp .lr-toolbar .cpsel .cpsel-btn{height:40px;width:100%;min-width:0}
  .mp-lrp .lr-savesearch{order:3;flex-shrink:0;width:40px;height:40px;padding:0;justify-content:center;gap:0;font-size:0}
  .mp-lrp .lr-savesearch svg{width:17px;height:17px}
  .mp-lrp .lr-viewtoggle{order:4;flex-shrink:0}
  .mp-lrp .lr-chips{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin:0 -16px 12px;padding:0 16px}
  .mp-lrp .lr-chips::-webkit-scrollbar{display:none}
  .mp-lrp .lr-chip{flex-shrink:0}

  /* ---- PAGINATION on a phone: the numbered nav gives way to "Load more" (pagination spec §5:
     "the user should not be forced to tap page numbers on a small screen"). Both halves are in the
     server HTML, so this is a pure swap — and the Load-more control is a REAL link to ?page=N+1,
     which keeps working when the script does not (§18). Skeletons appear BELOW the existing cards,
     never replacing them (§14). ---- */
  .mp-lrp .cp-pager .pg-nav,.mp-lrp .cp-pager .pg-range{display:none}
  .mp-lrp .cp-pager .pg-more{display:block;text-align:center}
  .mp-lrp .cp-pager .pg-progress{margin:0 0 10px;font-size:13px;color:var(--cp-muted)}
  .mp-lrp .cp-pager .pg-morebtn{display:flex;align-items:center;justify-content:center;width:100%;min-height:48px;
    padding:0 18px;border:1px solid var(--cp-line);border-radius:13px;background:var(--cp-card);
    color:var(--cp-pine);font-family:"Archivo",system-ui,sans-serif;font-weight:700;font-size:15px;
    text-decoration:none;cursor:pointer}
  .mp-lrp .cp-pager .pg-morebtn:active{background:var(--cp-mist)}
  .mp-lrp .cp-pager .pg-morebtn.is-loading{opacity:.6;pointer-events:none}
  .mp-lrp .cp-pager .pg-end{display:block;margin:0;padding:12px 0;font-size:13px;color:var(--cp-muted)}
  .mp-lrp .cp-pager .pg-skel{display:grid;grid-template-columns:1fr 1fr;gap:11px;margin-top:11px}
  .mp-lrp .cp-pager .pg-skel span{display:block;height:340px;border-radius:14px;background:var(--cp-mist)}
  .mp-lrp .cp-pager .pg-err{margin-top:12px}

  /* ---- filter BOTTOM SHEET: drag handle + sticky header/footer + dvh (master-prompt §11) ---- */
  .mp-filters{max-height:86dvh}
  .mp-filters .f-top{position:sticky;top:0;z-index:3;background:var(--cp-card);padding-top:22px}
  .mp-filters .f-top::before{content:"";position:absolute;top:9px;left:50%;transform:translateX(-50%);width:42px;height:4px;border-radius:99px;background:var(--cp-line)}
  .mp-filters .f-foot{position:sticky;bottom:0;z-index:3;padding-bottom:calc(15px + env(safe-area-inset-bottom));box-shadow:0 -10px 22px -14px rgba(21,33,28,.28)}

  /* ---- dual min/max slider, phone sizing --------------------------------
     A 20px thumb is a desktop pointer target. On a touch sheet the grab area
     grows to 28px and the row gets taller, so a thumb can be caught without
     magnifying the whole track. The summary also earns a bigger type size —
     on a phone it is the only place the chosen span is stated in words. */
  /* ⚠ The `body` prefix is required, not decoration: results.css loads AFTER
     app-mobile.css (header.php:102 vs :121), so a selector of equal weight
     here loses to the desktop one and the phone kept the 20px desktop thumb.
     `body .cp-rs` (0,1,1) beats `.cp-rs` (0,1,0) regardless of order. */
  body .cp-rs{height:42px;margin-top:14px}
  body .cp-rs .rs-track,
  body .cp-rs .rs-fill{top:18px;height:7px}
  body .cp-rs input[type=range]{height:42px}
  body .cp-rs input[type=range]::-webkit-slider-thumb{width:28px;height:28px;margin-top:-11px;border-width:3px}
  body .cp-rs input[type=range]::-moz-range-thumb{width:28px;height:28px;border-width:3px}
  body .rs-scale{font-size:11px}
  body .rs-sum{margin-top:10px;padding:9px 12px;font-size:12.5px;border-radius:10px}

  /* ---- VIP sticky bottom action bar (§9.8): Bod doen (secondary) + Stuur bericht (primary).
     The marketplace tab bar is already hidden on body.page-ads (mp.css); this replaces it.
     Hide the inline .b-primary so the primary CTA isn't duplicated on mobile. ---- */
  body.page-ads .vip-actionbar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:1040;gap:10px;
    padding:10px 12px calc(10px + env(safe-area-inset-bottom));
    background:rgba(255,255,255,.94);backdrop-filter:blur(14px) saturate(1.4);-webkit-backdrop-filter:blur(14px) saturate(1.4);
    border-top:1px solid var(--cp-line);box-shadow:0 -4px 18px -10px rgba(21,33,28,.28)}
  .vip-actionbar .va-offer,.vip-actionbar .va-msg{height:50px;border-radius:12px;display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:"Archivo",system-ui,sans-serif;font-weight:700;font-size:14.5px;text-decoration:none;cursor:pointer}
  .vip-actionbar .va-offer{flex:0 0 auto;padding:0 18px;background:var(--cp-card);border:1px solid var(--cp-line);color:var(--cp-pine)}
  .vip-actionbar .va-msg{flex:1;background:var(--cp-pine);color:#fff;border:0}
  .vip-actionbar svg{width:18px;height:18px;stroke:currentColor;stroke-width:1.9;fill:none;flex-shrink:0}
  .vip-actionbar .va-msg svg{stroke:#fff}
  .cp-vip .buy-actions > .b-primary{display:none}   /* primary CTA now lives in the sticky bar */
  /* gallery image counter (§9.8) — overlay badge top-right of the main image */
  .cp-vip .gallery .main{position:relative}
  .galcount{display:block;position:absolute;top:10px;right:10px;z-index:3;
    background:rgba(21,33,28,.72);color:#fff;font-family:"JetBrains Mono",ui-monospace,monospace;
    font-size:12px;font-weight:600;padding:4px 9px;border-radius:20px;
    backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}

  /* ---- Parts-category landing (§9.6): subcategory cards → 2-col compact app cards.
     Mirrors the homepage catsec (home-mobile.css); this file is inner-page only, so the
     homepage stays untouched. The inner landing renders no .shead (its own h1+lead sit above). ---- */
  .catsec .catgrid{grid-template-columns:1fr 1fr;gap:10px}
  .catsec .cat{flex-direction:column;align-items:flex-start;gap:10px;padding:14px 13px;border-radius:14px;min-height:96px}
  .catsec .cat .ic{width:42px;height:42px}
  .catsec .cat .body{width:100%;gap:2px}
  .catsec .cat .nm{white-space:normal;font-size:13.5px;line-height:1.2}
  .catsec .cat .sub{display:none}
  .catsec .cat .ct{position:absolute;top:12px;right:12px}
  .catsec .cat .chev{display:none}
  .catsec .cat:active{transform:scale(.985)}

  /* highlighted-parts / featured strip on a category landing → horizontal snap carousel with a
     peek of the next card (§9.6). The strip reuses .lr-results.grid but sits OUTSIDE .mp-lrp,
     so it needs its own carousel rule here. */
  .promo-strip .lr-results.grid{display:flex;grid-template-columns:none;gap:12px;overflow-x:auto;
    scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none;
    margin:0 -16px;padding:2px 16px 6px;scroll-padding-left:16px}
  .promo-strip .lr-results.grid::-webkit-scrollbar{display:none}
  .promo-strip .lr-results.grid > .lcard{flex:0 0 62%;scroll-snap-align:start}

  /* ---- Seller store (§9.8 "View shop"): compact the tall banner + make the tab row scroll.
     store.css loads AFTER app-mobile.css → use body.page-seller to out-specify it. ---- */
  body.page-seller .cp-store .subnav{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;gap:2px}
  body.page-seller .cp-store .subnav::-webkit-scrollbar{display:none}
  body.page-seller .cp-store .snav{flex:0 0 auto;white-space:nowrap;padding:13px 14px}
  body.page-seller .cp-store .bstats{display:flex;grid-template-columns:none;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;gap:0;margin-top:16px;padding-top:16px}
  body.page-seller .cp-store .bstats::-webkit-scrollbar{display:none}
  body.page-seller .cp-store .bstat{flex:0 0 auto;min-width:82px;padding-right:14px}
  body.page-seller .cp-store .bstat .n{font-size:18px}
  body.page-seller .cp-store .storeav{width:66px;height:66px}
  body.page-seller .cp-store .toolbar{gap:8px}

  /* ---- Garage fitment results → 2-col cards (density, matches the LRP). results.css loads
     after app-mobile, so .gr-main .lr-results.grid out-specifies its 1-col ≤560 rule. ---- */
  .gr-main .lr-results.grid{grid-template-columns:1fr 1fr;gap:11px}
  .gr-main .lr-results.grid .lthumb{height:132px}
  .gr-main .lr-results.grid .lfoot .lbtn{display:none}

  /* ---- Inner-page footer → accordion, matching the homepage footer (app-shell consistency).
     footer.php adds .js + nests a <button> in each <h4> ≤768 (heading semantics preserved). ---- */
  .cp-foot .fgrid{gap:0;padding-bottom:14px}
  .cp-foot .fbrand{margin-bottom:4px}
  .cp-foot.js .fcol:not(.fbrand){border-top:1px solid rgba(255,255,255,.09)}
  .cp-foot.js .fcol:not(.fbrand) h4{margin:0}
  .cp-foot.js .fcol:not(.fbrand) .facc-btn{width:100%;margin:0;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:10px;padding:15px 2px;font-family:"Archivo",system-ui,sans-serif;font-size:14.5px;font-weight:600;color:#fff;background:none;border:0;text-align:left}
  .cp-foot.js .fcol:not(.fbrand) .facc-btn::after{content:"";width:8px;height:8px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);transition:transform .15s ease;opacity:.65;margin-right:4px;flex-shrink:0}
  .cp-foot.js .fcol:not(.fbrand).open .facc-btn::after{transform:rotate(-135deg)}
  .cp-foot.js .fcol:not(.fbrand) a{display:none}
  .cp-foot.js .fcol:not(.fbrand).open a{display:block}
  .cp-foot.js .fcol:not(.fbrand).open a:last-of-type{margin-bottom:12px}
  .cp-foot .fbot{flex-direction:column;align-items:flex-start;gap:9px}

  /* ---- DARK: remap results.css :root --cp-* tokens (content auto-adapts) ---- */
  html[data-theme="dark"]{
    --cp-ink:rgba(255,255,255,.88); --cp-muted:rgba(255,255,255,.62);
    --cp-line:#586760; --cp-paper:#141716; --cp-card:#292E2C; --cp-card-2:#363D3A;
    --cp-mist:#252A28; --cp-pine:#5FA584; --cp-pine2:#7EB99E; --cp-fern:#7EB99E;
    --cp-amber:#E08A2C; --cp-amber-soft:#E6C294; --fit-bg:#183A2A; --fit-fg:#60BE92; --fit-line:#295540;
  }
  /* results.css hardcoded-hex / pine-fill overrides */
  html[data-theme="dark"] .lthumb{background:linear-gradient(135deg,#2E332F,#242926)}
  html[data-theme="dark"] .lthumb img{filter:brightness(.84) contrast(.95)}
  html[data-theme="dark"] .lthumb .fav{background:rgba(30,34,32,.82)}
  html[data-theme="dark"] .lcond.new{color:#0F150E}
  html[data-theme="dark"] .lcond.dmg{background:#7a2a20}
  html[data-theme="dark"] .fitflag.confirmed{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .fitflag.confirmed svg{stroke:#60BE92}
  html[data-theme="dark"] .fitflag.universal{background:#2a302c;color:rgba(255,255,255,.6)}
  html[data-theme="dark"] .fitflag.universal svg{stroke:rgba(255,255,255,.6)}
  html[data-theme="dark"] .fitflag.check{background:#3A2C15;color:#E0A050}
  html[data-theme="dark"] .fitflag.check svg{stroke:#E0A050}
  html[data-theme="dark"] .fitflag.seller{background:#1c2f42;color:#82b1e0}
  html[data-theme="dark"] .fitflag.seller svg{stroke:#82b1e0}
  html[data-theme="dark"] .lbtn,
  html[data-theme="dark"] .lr-vt.active,
  html[data-theme="dark"] .mp-filters .f-show,
  html[data-theme="dark"] .mp-filters .f-top .badge{color:#0F150E}
  html[data-theme="dark"] .lbtn svg{stroke:#0F150E}
  html[data-theme="dark"] .cp-landlinks a{background:#292E2C;border-color:#586760;color:#7EB99E}
  /* filter dropdowns (results.css .dd*, hardcoded #fff/#2c3a33/#eef4f0) */
  html[data-theme="dark"] .mp-filters .dd.open .dd-btn,
  html[data-theme="dark"] .mp-filters .dd-btn.set,
  html[data-theme="dark"] .mp-filters .rng input:focus,
  html[data-theme="dark"] .mp-filters .rng input.set{background:#292E2C}
  /* dual slider — the track and the thumb centre are the only literals that
     cannot ride the --cp-* remap (a white thumb on a dark sheet is a hole) */
  html[data-theme="dark"] .cp-rs .rs-track{background:#3A403D;box-shadow:none}
  html[data-theme="dark"] .cp-rs input[type=range]::-webkit-slider-thumb{
    background:#1B211E;box-shadow:0 2px 8px rgba(0,0,0,.5)}
  html[data-theme="dark"] .cp-rs input[type=range]::-moz-range-thumb{
    background:#1B211E;box-shadow:0 2px 8px rgba(0,0,0,.5)}
  html[data-theme="dark"] .rs-sum{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .mp-filters .dd-opt{color:rgba(255,255,255,.85)}
  html[data-theme="dark"] .mp-filters .dd-opt:hover{background:#141716}
  html[data-theme="dark"] .mp-filters .dd-opt.sel{background:#183A2A;color:#7EB99E}
  /* garage sidebar facets (results.css hardcoded hex) */
  html[data-theme="dark"] .gr-side{background:#292E2C;border-color:#586760}
  html[data-theme="dark"] .gr-fg{border-top-color:#252A28}
  html[data-theme="dark"] .gr-opt{color:rgba(255,255,255,.85)}
  html[data-theme="dark"] .gr-opt:hover{background:#141716}
  html[data-theme="dark"] .gr-opt.is-on{background:#5FA584;color:#0F150E}
  html[data-theme="dark"] .gr-price input{background:#141716;border-color:#586760;color:rgba(255,255,255,.88)}

  /* ===== SURFACE: VIP (plugins/ads + listing.css .cp-vip). Shares --cp-* tokens
     (already remapped above) + already collapses to a single column on mobile. Here:
     listing.css hardcoded light tints (gallery thumbnail placeholders, honest trust
     cards). Gallery .zoom/.gnav stay light — they overlay the photo, not the page. ===== */
  html[data-theme="dark"] .cp-vip .thumb{background:linear-gradient(135deg,#2E332F,#242926)}
  html[data-theme="dark"] .cp-vip .thumb img{filter:brightness(.84) contrast(.95)}
  html[data-theme="dark"] .cp-vip .tn{background:#292E2C;color:rgba(255,255,255,.72)}
  html[data-theme="dark"] .cp-vip .protect-mini{background:#1c2b22;border-color:#295540}
  html[data-theme="dark"] .cp-vip .ti{background:#1c2b22}
}

/* ============================================================================
   SURFACE: ACCOUNT — the shared sidebar (_side.php `.dside`) becomes a TOP-LEFT
   OFF-CANVAS DRAWER (burger), per the user's spec. account.css ≤900 turns .dside
   into a horizontal row; here (higher specificity `body.page-account`) it becomes a
   fixed left drawer that slides in on the burger. Drawer content is exactly the
   requested list: Dashboard · Profiel · My ads · Feature · Saved · Messages ·
   Place a listing · Log out. The bottom tab bar is unrelated and stays.
   ============================================================================ */
/* burger button (in the shared app bar) — base hidden; shown only on account + mobile */
.cp-acc-burger{display:none;align-items:center;justify-content:center;width:40px;height:40px;border-radius:11px;background:var(--card);border:1px solid var(--line);color:var(--ink);cursor:pointer;padding:0;flex-shrink:0}
.cp-acc-burger svg{width:20px;height:20px;stroke:currentColor;stroke-width:2;fill:none}
.acc-drawer-bd{display:none}
@media(max-width:768px){
  body.page-account .cp-acc-burger{display:inline-flex}
  body.page-account .cp-dash .dwrap{grid-template-columns:1fr}
  body.page-account .cp-dash .dside{
    position:fixed;left:0;top:0;bottom:0;width:min(85vw,320px);z-index:1300;
    flex-direction:column;flex-wrap:nowrap;gap:16px;
    background:var(--cp-paper);border-right:1px solid var(--cp-line);
    padding:14px 14px calc(16px + env(safe-area-inset-bottom));
    overflow-y:auto;transform:translateX(-100%);
    transition:transform .28s cubic-bezier(.22,.61,.36,1);box-shadow:0 0 44px rgba(0,0,0,.3)}
  body.page-account.acc-drawer-open .cp-dash .dside{transform:translateX(0)}
  .acc-drawer-bd{display:block;position:fixed;inset:0;background:rgba(10,14,12,.5);z-index:1290;opacity:0;visibility:hidden;transition:opacity .22s}
  body.acc-drawer-open .acc-drawer-bd{opacity:1;visibility:visible}
  body.acc-drawer-open{overflow:hidden}
}

/* ============================================================================
   SURFACE: ACCOUNT + MESSAGES — mobile-app LAYOUT (light). DAY 25 (2026-07-25).
   The 5 login-gated surfaces (My-listings / Dashboard / Promote / Profile /
   Messages) become app cards + sticky action bars, per the master brief §9.1-9.5.
   ⚠ LOAD ORDER: account.css (the per-plugin sheet for page-account AND page-chat)
   loads AFTER this file, so every rule here leads with body.page-account /
   body.page-chat / body.act-* to OUT-SPECIFY account.css (its base rules are
   .cp-dash .x = 0,2,0 or .cp-dash .x .y = 0,3,0). ⚠ .setcard{overflow:hidden} +
   .panel.on{animation:cpFade (animates transform)} would trap position:fixed
   children (the .mp-page gotcha) → the fade is killed on mobile below.
   NOTE: these are login-gated → NOT browser-verified live (I do not type the test
   password). Verified statically: php -l / node --check, specificity, no overflow.
   ============================================================================ */
@media(max-width:768px){

  /* ---- MY-LISTINGS (account/ads.php): table rows → management cards ---- */
  /* toolbar: status pills become a horizontal scroll row; KEEP the search (account.css hides it ≤600) */
  body.page-account .cp-dash .mtoolbar{padding:12px;gap:10px}
  body.page-account .cp-dash .fpills{flex-wrap:nowrap;overflow-x:auto;order:0;flex-basis:100%;margin:0 -2px;padding:2px;scrollbar-width:none;-ms-overflow-style:none}
  body.page-account .cp-dash .fpills::-webkit-scrollbar{display:none}
  body.page-account .cp-dash .fpill{flex-shrink:0}
  body.page-account .cp-dash .tspacer{display:none}
  body.page-account .cp-dash .minisearch{display:flex;order:1;flex:1 1 auto;width:auto;min-width:0}
  body.page-account .cp-dash .sortsel{order:2;flex-shrink:0}
  /* ---- the listing CARD (user-reported: "the Actief tag sits in a badly thought-out place and the
     whole .adrow is not arranged like an app"). The DAY-25 version stacked the columns and pinned
     .aacts (status + kebab) into the top-right corner, which (a) disconnected the status from the
     content it describes and (b) stole a 52px right gutter from the title on EVERY card.
     Rebuilt as a real management card — one reading path down the content column:
         [ 84px photo ]  ● Actief                              ⋮   ← status leads, kebab pinned
                         Hobby De Luxe 460 UFe compacte…           ← title, 2-line clamp
                         € 15.750                                  ← price
                         👁 124   ♥ 8   ✉ 2                        ← performance, icons + numbers
         Geplaatst 21.07.2026 · OEM · pasvorm                      ← meta, full width
     Mechanism: the card is a 2-column grid and `.amain`/`.aacts` become `display:contents`, so their
     children (title/meta, status/kebab/menu) become grid items and can be placed individually —
     no PHP/markup change, so desktop keeps its 6-column table row untouched. ---- */
  body.page-account .cp-dash #adRows{display:flex;flex-direction:column;gap:12px;padding:12px;background:var(--cp-paper)}
  body.page-account .cp-dash .adrow.head{display:none}
  body.page-account .cp-dash #adRows .adrow{
    /* ⚠ account.css sets `gap:14px` on .adrow — that is BOTH axes, so row-gap has to be zeroed
       explicitly or every one of the five rows gains 14px and the card balloons (measured: 246px
       instead of 189px). The vertical rhythm comes from each row's own margin-top instead. */
    display:grid;grid-template-columns:84px minmax(0,1fr);column-gap:12px;row-gap:0;align-items:start;
    position:relative;padding:11px 46px 11px 11px;
    border:1px solid var(--cp-line);border-radius:14px;background:var(--cp-card);
    box-shadow:0 1px 2px rgba(21,33,28,.05)}
  body.page-account .cp-dash #adRows .adrow:hover{background:var(--cp-card)}
  body.page-account .cp-dash .adrow .athumb{grid-column:1;grid-row:1 / span 4;position:static;width:84px;height:84px;border-radius:12px}
  body.page-account .cp-dash .adrow .chk{position:absolute;left:18px;top:18px;z-index:3;box-shadow:0 0 0 2px rgba(255,255,255,.9)}
  body.page-account .cp-dash .adrow .amain,
  body.page-account .cp-dash .adrow .aacts{display:contents}
  /* ⭐ 1. STATUS — the fix the user asked for: it now opens the content column instead of floating
     in the corner. A dot + label reads as a state, not as a stray tag. */
  body.page-account .cp-dash .adrow .status{grid-column:2;grid-row:1;justify-self:start;align-self:start;
    display:inline-flex;align-items:center;gap:5px;padding:3px 9px 3px 7px;font-size:10px;border-radius:7px}
  body.page-account .cp-dash .adrow .status::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.8;flex-shrink:0}
  /* 2. title */
  body.page-account .cp-dash .adrow .at{grid-column:2;grid-row:2;margin-top:3px;
    white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
    font-size:14.5px;line-height:1.28}
  /* 3. price */
  body.page-account .cp-dash .adrow .aprice{grid-column:2;grid-row:3;margin-top:2px;font-size:15.5px}
  /* 4. performance — number + icon instead of number over a word (there is no room for three
     stacked label columns at 320px). The word stays in the DOM, visually hidden, so a screen
     reader still announces "124 weergaven". */
  body.page-account .cp-dash .adrow .astats{grid-column:2;grid-row:4;display:flex;gap:13px;margin-top:5px;flex-wrap:wrap}
  body.page-account .cp-dash .adrow .astats .st{flex-direction:row;align-items:center;gap:5px}
  body.page-account .cp-dash .adrow .astats .st::before{content:"";width:13px;height:13px;flex-shrink:0;
    background-repeat:no-repeat;background-position:center;background-size:13px 13px}
  body.page-account .cp-dash .adrow .astats .st:nth-child(1)::before{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6A62' stroke-width='1.9'><path d='M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z'/><circle cx='12' cy='12' r='3'/></svg>")}
  body.page-account .cp-dash .adrow .astats .st:nth-child(2)::before{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6A62' stroke-width='1.9'><path d='M12 21s-7-4.5-9-9a4.5 4.5 0 0 1 9-2 4.5 4.5 0 0 1 9 2c-2 4.5-9 9-9 9z'/></svg>")}
  body.page-account .cp-dash .adrow .astats .st:nth-child(3)::before{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6A62' stroke-width='1.9'><path d='M4 5h16v11H8l-4 4z'/></svg>")}
  body.page-account .cp-dash .adrow .astats .st .n{font-size:12.5px}
  body.page-account .cp-dash .adrow .astats .st .l{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
  /* 5. meta (part number / fitment / listed date) — full width, so a long date never squeezes the title */
  body.page-account .cp-dash .adrow .ameta{grid-column:1 / -1;grid-row:5;margin-top:8px;gap:8px;font-size:11px}
  body.page-account .cp-dash .adrow .ameta .apn,body.page-account .cp-dash .adrow .ameta .adate{font-size:11px}
  /* row actions stay where a phone expects them: pinned top-right, menu drops under the button */
  body.page-account .cp-dash .adrow .kebab{position:absolute;right:8px;top:8px;width:36px;height:36px;z-index:2}
  body.page-account .cp-dash .adrow .menu{right:8px;top:50px}
  /* bulk bar → floating pill at the bottom; hide the tab bar while a batch is active */
  body.page-account .cp-dash .bulkbar.on{
    position:fixed;left:12px;right:12px;bottom:calc(12px + env(safe-area-inset-bottom));z-index:1305;
    border:1px solid var(--cp-line);border-radius:14px;padding:11px 14px;
    box-shadow:0 12px 30px -10px rgba(21,33,28,.4)}
  body:has(.cp-dash .bulkbar.on) .mp-tabbar{display:none}

  /* ---- KPI TILES (.kpis/.kpi — dashboard 4-up, My-listings/Promote 3-up ".k3") ----
     User-reported: "the kpis are far too big for an app". MEASURED at 390px before this block:
     each dashboard tile was 139px tall and the 2×2 grid took 292px = 35% of the screen before
     anything else appeared; and account.css:752 drops the 3-up variant to ONE column at ≤1000px,
     i.e. three full-width cards (~270px) for three numbers. Master prompt §9.1/§19: metric cards
     become a compact 2×2 grid on a 390px screen — clear number, short label, optional trend,
     tappable where a real destination exists. Nothing is removed, only re-proportioned. */
  body.page-account .cp-dash .kpis{gap:10px;margin-bottom:12px}
  body.page-account .cp-dash .kpi{padding:12px;border-radius:13px}
  body.page-account .cp-dash .kpi .kt{font-size:11.5px;gap:6px;line-height:1.3;align-items:flex-start}
  body.page-account .cp-dash .kpi .kt svg{width:14px;height:14px;margin-top:1px}
  body.page-account .cp-dash .kpi .kv{font-size:21px;line-height:1.1;margin-top:5px}
  body.page-account .cp-dash .kpi .kd{font-size:11px;margin-top:3px;min-height:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* tiles that link somewhere real (account/index.php + ads.php) — grid items are blockified,
     so an <a class="kpi"> lays out exactly like the <div> version */
  body.page-account .cp-dash a.kpi:active{background:var(--cp-paper)}
  /* the 3-up strip: one row instead of three stacked full-width cards. The icon goes (≈94px of
     inner width at 390px, and the label already names the metric); the number is the signal. */
  body.page-account .cp-dash .kpis.k3{grid-template-columns:repeat(3,1fr);gap:8px}
  body.page-account .cp-dash .kpis.k3 .kpi{padding:10px 9px}
  body.page-account .cp-dash .kpis.k3 .kt{font-size:10.5px;line-height:1.28}
  body.page-account .cp-dash .kpis.k3 .kt svg{display:none}
  body.page-account .cp-dash .kpis.k3 .kv{font-size:19px;margin-top:3px}

  /* ---- DASHBOARD (account/index.php): my-ads preview .lrow → 2-line card ---- */
  body.page-account .cp-dash .dcard .lrow.head{display:none}
  body.page-account .cp-dash .dcard .lrow:not(.head){
    display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;
    position:relative;padding:12px 44px 12px 14px}
  body.page-account .cp-dash .dcard .lrow:not(.head) .litem{order:1;flex:1 1 100%}
  body.page-account .cp-dash .dcard .lrow:not(.head) .lacts{order:2;position:absolute;right:12px;top:12px}
  body.page-account .cp-dash .dcard .lrow:not(.head) .lprice{order:3}
  body.page-account .cp-dash .dcard .lrow:not(.head) .c-st{order:4;display:inline-flex}
  body.page-account .cp-dash .dcard .lrow:not(.head) .c-v{order:5;display:inline-flex}
  body.page-account .cp-dash .dcard .lrow:not(.head) .c-s{display:none}

  /* ---- PROMOTE + PROFILE shared: kill the panel fade (animates transform → traps fixed children) ---- */
  body.page-account .cp-dash .setcard .panel.on{animation:none}

  /* ---- PROMOTE (act-promote): sticky bottom CTA; hide global tab bar during the focused flow (VIP-page precedent) ---- */
  body.act-promote .mp-tabbar{display:none}
  /* ⚠ MEASURED IN A LOGGED-IN SESSION (2026-07-25): pinning the whole .setfoot produced a **172px**
     bottom bar — 20% of a 390×844 screen — because the two explanatory lines ("stop or switch any
     time", "max 3 at a time") were pinned together with the button. `display:contents` lets that
     text flow back into the page (nothing is hidden — §4.1) and only the ACTION stays pinned, as a
     normal full-width 56px CTA. */
  body.act-promote .cp-dash .promo-studio .setfoot{display:contents}
  body.act-promote .cp-dash .promo-studio .setfoot .saved,
  body.act-promote .cp-dash .promo-studio .setfoot .pmax-hint{display:flex;gap:7px;align-items:flex-start;margin-top:10px;font-size:12.5px;line-height:1.45}
  body.act-promote .cp-dash .promo-studio .setfoot .save{
    position:fixed;left:0;right:0;bottom:0;width:100%;margin:0;z-index:1305;
    min-height:56px;border-radius:0;justify-content:center;
    padding-bottom:env(safe-area-inset-bottom);
    box-shadow:0 -10px 26px -14px rgba(21,33,28,.4)}
  body.act-promote{padding-bottom:calc(76px + env(safe-area-inset-bottom))!important}

  /* ---- PROFILE (act-profile): smaller panels + sticky save bar (tabs = one .on panel visible) ---- */
  body.act-profile .cp-dash .setcard .panel{padding:16px}
  body.act-profile .mp-tabbar{display:none}
  /* ⚠ MEASURED LOGGED-IN: pinning the whole .setfoot gave a 103px bar (12% of the screen) because the
     "changes are saved to your account" line rode along with the button. Same fix as Promote: the
     line flows back into the panel (nothing hidden), only the action is pinned. */
  body.act-profile .cp-dash .setcard .panel.on .setfoot{display:contents}
  body.act-profile .cp-dash .setcard .panel.on .setfoot .saved{display:flex;gap:7px;align-items:center;margin-top:12px;font-size:12.5px}
  body.act-profile .cp-dash .setcard .panel.on .setfoot .save{
    position:fixed;left:0;right:0;bottom:0;width:100%;margin:0;z-index:1305;
    min-height:56px;border-radius:0;justify-content:center;
    padding-bottom:env(safe-area-inset-bottom);
    box-shadow:0 -10px 26px -14px rgba(21,33,28,.4)}
  body.act-profile{padding-bottom:calc(76px + env(safe-area-inset-bottom))!important}
  /* 16px fields here too — below 16px iOS zooms the page on focus (registration got this already) */
  body.act-profile .cp-dash .setcard .inp,
  body.act-profile .cp-dash .setcard input[type=text],body.act-profile .cp-dash .setcard input[type=email],
  body.act-profile .cp-dash .setcard input[type=tel],body.act-profile .cp-dash .setcard input[type=password],
  body.act-profile .cp-dash .setcard select,body.act-profile .cp-dash .setcard .cpsel-btn{font-size:16px;min-height:50px}

  /* ---- CREATE / EDIT LISTING (act-add / act-edit): the sticky .cp-acc-bar Save/Draft bar
     was HIDDEN behind the floating .mp-tabbar (z1040 > the bar's z50). Hide the tab bar on
     this focused flow (like promote/profile) so Save + Draft are reachable, lift the bar
     above everything, add home-indicator safe-area, and reserve body space so the last
     field isn't covered. ---- */
  body.act-add .mp-tabbar,body.act-edit .mp-tabbar{display:none}
  body.act-add .cp-acc-bar,body.act-edit .cp-acc-bar{z-index:1305;padding-bottom:env(safe-area-inset-bottom)}
  body.act-add,body.act-edit{padding-bottom:calc(92px + env(safe-area-inset-bottom))!important}

  /* ---- MESSAGES (page-chat): full-height chat, contextual thread, keyboard-safe composer ---- */
  /* the rich footer is noise on the full-height SPA */
  body.page-chat .cp-foot{display:none}
  /* an OPEN thread is contextual chat → hide the 5-item tab bar + reclaim its reserved space */
  body:has(.cp-msg .inbox.show-thread) .mp-tabbar{display:none}
  body:has(.cp-msg .inbox.show-thread){padding-bottom:0!important}
  /* ⚠ MEASURED IN A LOGGED-IN SESSION (2026-07-25): the conversation column was 377px inside a
     358px .inbox and every row's right edge was clipped by .inbox{overflow:hidden}. Cause: the
     mobile grid is `1fr`, which is `minmax(auto,1fr)` — the auto MINIMUM is min-content, and the
     min-content grew to 377px when the filter tabs became a nowrap scroller below. `minmax(0,1fr)`
     lets the track shrink to the container; `min-width:0` does the same for the flex/grid children. */
  body.page-chat .cp-msg .inbox{grid-template-columns:minmax(0,1fr)}
  body.page-chat .cp-msg .convcol,body.page-chat .cp-msg .msgcol{min-width:0}
  /* conversation filter tabs scroll horizontally instead of crowding */
  body.page-chat .cp-msg .convtabs{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;min-width:0}
  body.page-chat .cp-msg .convtabs::-webkit-scrollbar{display:none}
  body.page-chat .cp-msg .convtab{flex-shrink:0}
  /* composer: home-indicator safe-area + shrink the inbox by the on-screen-keyboard height (--cp-kb set by chat JS via visualViewport) */
  body.page-chat .cp-msg .composer{padding-bottom:calc(12px + env(safe-area-inset-bottom))}
  body.page-chat .cp-msg .inbox.show-thread{height:calc(100dvh - 200px - var(--cp-kb, 0px))}
}

/* ============================================================================
   BREADCRUMBS + BACK BUTTON — app style (mobile ≤768px). DAY 25 (user reference
   "Back button + breadcrumbs"): EVERY breadcrumb gets a dedicated square BACK
   BUTTON to its left that goes to the PREVIOUS page (history.back), plus a bordered
   scrollable "shell". The portal has TWO breadcrumb components — .breadcrumb (ol:
   cat/search/about/help/rules) and .crumb (div: VIP/seller/account/registration);
   footer.php JS wraps BOTH into `.cp-navctx > .cp-backbtn + .cp-crumbshell > <crumb>`
   on mobile only. ⚠ DESKTOP FROZEN: the wrappers are display:contents + the button
   display:none at ≥769px, so even a mobile→desktop resize renders the crumb byte-
   identically. `!important` needed (per-plugin sheets load after this file). SEO
   safe — the whole trail stays visible + tappable.
   ============================================================================ */
/* base (all widths) — neutralise the JS wrappers on desktop */
.cp-navctx{display:contents}
.cp-crumbshell{display:contents}
.cp-backbtn{display:none}

@media(max-width:768px){
  /* nav-context grid: [back button 42px] [breadcrumb shell 1fr] */
  .cp-navctx{display:grid;grid-template-columns:42px minmax(0,1fr);align-items:center;gap:9px;margin:12px 0 14px}
  .cp-backbtn{display:grid;place-items:center;width:42px;height:42px;padding:0;
    border:1px solid var(--cp-line);border-radius:13px;color:var(--cp-pine);
    background:var(--cp-card);box-shadow:0 5px 16px rgba(21,33,28,.06)}
  .cp-backbtn:active{transform:scale(.96);background:var(--cp-mist)}
  .cp-backbtn svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2}
  .cp-crumbshell{display:block;position:relative;min-width:0;overflow:hidden;
    border:1px solid var(--cp-line);border-radius:13px;background:rgba(255,255,255,.72)}
  .cp-crumbshell::after{content:"";position:absolute;top:0;right:0;bottom:0;width:30px;
    pointer-events:none;background:linear-gradient(90deg,transparent,rgba(255,255,255,.95))}
  /* the breadcrumb INSIDE the shell (post-wrap). ⚠ these carry ONE MORE class than the pre-wrap
     fallback below (.container.mp-page .cp-crumbshell > x = 4 classes vs 3) so they win once the JS
     has moved the crumb into the shell — both sets are !important, so specificity decides. */
  .container.mp-page .cp-crumbshell>.breadcrumb,.container.mp-page .cp-crumbshell>.crumb{
    display:flex!important;flex-wrap:nowrap!important;align-items:center;gap:7px;min-height:42px;
    overflow-x:auto;-webkit-overflow-scrolling:touch;white-space:nowrap;scrollbar-width:none;-ms-overflow-style:none;
    margin:0!important;padding:0 30px 0 14px!important;font-size:11px}
  .cp-crumbshell>.breadcrumb::-webkit-scrollbar,.cp-crumbshell>.crumb::-webkit-scrollbar{display:none}
  .cp-crumbshell>.breadcrumb>li{flex:0 0 auto;white-space:nowrap;margin:0}
  .cp-crumbshell>.breadcrumb>li>a,.cp-crumbshell>.crumb>a{flex:0 0 auto;font-weight:700;color:var(--cp-muted)!important;text-decoration:none}
  .cp-crumbshell>.breadcrumb>.active,.cp-crumbshell>.crumb>.here{flex:0 0 auto;font-weight:900;color:var(--cp-ink)!important}
  /* pre-wrap fallback (the milliseconds before footer.php's JS runs) — single-line already, so no
     multi-line flash. ⚠ FIXED 2026-07-25: this used to be a list of DIRECT-CHILD selectors and so
     skipped /registration/ (.cp-reg > .rwrap > .crumb) and /chat/ (.cp-msg > .mwrap > .crumb) —
     the same nesting blind spot that left those pages without a Back button. Now descendant. */
  .container.mp-page .breadcrumb,.container.mp-page .crumb{
    display:flex!important;flex-wrap:nowrap!important;align-items:center;gap:7px;overflow-x:auto;
    white-space:nowrap;scrollbar-width:none;-ms-overflow-style:none;margin:12px 0 14px!important;padding:2px 0!important;font-size:12px}
  .container.mp-page .breadcrumb::-webkit-scrollbar,.container.mp-page .crumb::-webkit-scrollbar{display:none}
  .container.mp-page .breadcrumb>li{flex:0 0 auto;white-space:nowrap;margin:0}

  /* ---- WIDTH PARITY, round 2 (user: "the content is narrow on the form page") ----
     Rule for the whole app shell: a top-level surface wrapper carries ZERO own side padding on
     mobile — the single `.container.mp-page` inset (16px, header.php) is the entire story.
     `.cp-vip`/`.cp-store`/`.cp-acc`/`.cp-dash` already comply and `.cp-msg` was zeroed on DAY-25,
     but `.cp-reg` (account.css:532) still added `padding:0 24px` → 40px of inset on a phone, i.e.
     24px narrower than every other page. `.cp-auth` centred its card with its own 12px for the
     same reason. Both now defer to the container. */
  body.page-registration .cp-reg{padding:0}
}

/* ============================================================================
   SURFACE: CATEGORY HEADER (plugins/cat/index.php) — compact app title + SEO.
   The title + type badge collapse to one row; the SEO prose is 2-line clamped with
   an inline More/Less toggle (full text ALWAYS stays in the DOM, only CSS-clamped).
   ⚠ DESKTOP FROZEN: the wrappers are display:contents at ≥769px so the <h1>/<p>
   render byte-identically; badge/button are display:none on desktop.
   ============================================================================ */
.cp-cathead{display:contents}
.cp-cat-type{display:none}
.cp-seo{display:contents}
.cp-readmore{display:none}

@media(max-width:768px){
  /* title row: title left, category-type badge right */
  .cp-cathead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:6px}
  .cp-cathead .mp-h2{min-width:0;margin:0;font-size:22px;line-height:1.1;letter-spacing:-.03em;font-weight:800}
  .cp-cat-type{display:inline-flex;flex:0 0 auto;align-items:center;max-width:42vw;padding:5px 9px;border-radius:999px;
    background:var(--cp-amber-soft);color:#8a5a12;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    font:800 9.5px/1 Inter,system-ui,sans-serif;letter-spacing:.07em;text-transform:uppercase}

  /* compact SEO: 2-line clamp + inline More/Less (no card / border / shadow) */
  .cp-seo{display:flex;align-items:flex-end;gap:7px;margin-top:7px;margin-bottom:16px}
  .cp-seo .mp-lead{flex:1 1 auto;min-width:0;margin:0;max-width:none;font-size:13px;line-height:1.48;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .cp-seo.cp-open{display:block}
  .cp-seo.cp-open .mp-lead{display:block;overflow:visible;-webkit-line-clamp:none}
  .cp-readmore{flex:0 0 auto;display:inline-flex;align-items:center;gap:3px;margin:0 0 1px;padding:3px 0;
    border:0;background:transparent;color:var(--cp-pine);cursor:pointer;
    font:800 12px/1 Inter,system-ui,sans-serif;white-space:nowrap}
  .cp-seo.cp-open .cp-readmore{margin-top:7px}
  .cp-readmore svg{width:13px;height:13px;stroke:currentColor;stroke-width:2;fill:none;transition:transform .2s ease}
  .cp-seo.cp-open .cp-readmore svg{transform:rotate(180deg)}
  .cp-readmore:focus-visible{outline:2px solid var(--cp-pine);outline-offset:4px;border-radius:4px}
}
@media(max-width:768px) and (prefers-reduced-motion:reduce){
  .cp-readmore svg{transition:none}
}

/* ============================================================================
   SURFACE: MESSAGES (plugins/chat) — modern app redesign (mobile ≤768px). DAY 25
   (user reference "Modern Messages"): the WhatsApp-style list + thread restyled to
   the app look — big title + subtitle + unread badge, role chips, rounded avatars,
   unread accent + amber dot / chevron, clean bubbles + read ticks, app composer.
   ⚠ REAL DATA ONLY (§0): NO fake offer accept/decline, NO online/presence, NO
   options/attach buttons (portal chat is text-only). Scoped body.page-chat to
   out-specify account.css (its chat rules are @820 and load AFTER this file).
   DESKTOP FROZEN: the new elements (.ch-sub/.crole/.cchev) are display:none ≥769px;
   every restyle rule below is ≤768 only.
   ============================================================================ */
.cp-msg .ch-sub{display:none}
.cp-msg .crole{display:none}
.cp-msg .cchev{display:none}

@media(max-width:768px){
  /* ---- LIST: page header (title + unread badge + subtitle + search) ---- */
  body.page-chat .cp-msg .convhead{padding:16px 16px 12px}
  body.page-chat .cp-msg .convhead h1{font-family:"Archivo",system-ui,sans-serif;font-weight:800;font-size:25px;letter-spacing:-.03em;align-items:center}
  body.page-chat .cp-msg .convhead h1 .uc{margin-left:auto;font-family:"Inter",system-ui,sans-serif;font-size:10px;font-weight:800;background:var(--cp-amber);color:#3a2408;padding:3px 9px;border-radius:999px}
  body.page-chat .cp-msg .ch-sub{display:block;margin-top:3px;color:var(--cp-muted);font-size:11.5px}
  body.page-chat .cp-msg .convsearch{margin-top:14px;height:44px;border-radius:13px;background:var(--cp-paper)}
  /* ---- LIST: filter tabs ---- */
  body.page-chat .cp-msg .convtabs{gap:7px;padding:2px 16px 12px}
  body.page-chat .cp-msg .convtab{height:34px;padding:0 12px;border-radius:10px;font-size:11.5px;font-weight:800}
  /* ---- LIST: conversation rows ---- */
  body.page-chat .cp-msg .conv{gap:12px;padding:13px 16px;align-items:center}
  body.page-chat .cp-msg .conv .cav{width:50px;height:50px;border-radius:15px;font-size:15px;align-self:center}
  body.page-chat .cp-msg .conv .cname{gap:7px;align-items:center}
  body.page-chat .cp-msg .conv .cnm{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:800;font-size:13.5px}
  body.page-chat .cp-msg .conv .crole{display:inline-block;flex:0 0 auto;padding:3px 6px;border-radius:999px;background:#E3ECE6;color:#315441;font-size:8px;font-weight:900;text-transform:uppercase;letter-spacing:.04em;line-height:1}
  body.page-chat .cp-msg .conv .ctime{margin-left:auto;flex:0 0 auto;font-size:9.5px;font-family:inherit}
  body.page-chat .cp-msg .conv .cprev{font-size:11px;margin-top:5px}
  body.page-chat .cp-msg .conv .citem{font-size:9.5px;margin-top:6px}
  body.page-chat .cp-msg .conv.unreadrow{background:#EAF2EC}
  body.page-chat .cp-msg .conv.unreadrow::before{content:"";position:absolute;left:0;top:14px;bottom:14px;width:4px;border-radius:0 999px 999px 0;background:var(--cp-amber)}
  body.page-chat .cp-msg .conv .unread{position:static;transform:none;align-self:center;flex:0 0 auto;min-width:22px;height:22px;font-family:inherit;font-size:9px}
  body.page-chat .cp-msg .conv .cchev{display:block;align-self:center;flex:0 0 auto;width:15px;height:15px;stroke:#8C9890;stroke-width:2;fill:none}
  /* ---- DETAIL: chat header ---- */
  body.page-chat .cp-msg .thead{gap:10px;padding:10px 14px;align-items:center}
  body.page-chat .cp-msg .thead .tav{width:42px;height:42px;border-radius:13px;font-size:12px}
  body.page-chat .cp-msg .thead .tn{font-size:14px}
  body.page-chat .cp-msg .thead .ts{font-size:10.5px}
  /* ---- DETAIL: linked-listing card ---- */
  body.page-chat .cp-msg .ctxbar{margin:0 14px 10px;padding:10px;border:1px solid var(--cp-line);border-radius:14px;background:var(--cp-card)}
  body.page-chat .cp-msg .ctxbar .cx-th{width:48px;height:48px;border-radius:12px;background:#E8EEE9}
  body.page-chat .cp-msg .ctxbar .cx-t{font-size:11.5px;font-weight:800}
  body.page-chat .cp-msg .ctxbar .cx-p{font-size:12px}
  body.page-chat .cp-msg .ctxbar .cx-view{height:36px;padding:0 11px;font-size:10px;font-weight:800;border-radius:10px}
  /* ---- DETAIL: message bubbles ---- */
  body.page-chat .cp-msg .msgs{padding:16px 14px;gap:7px}
  body.page-chat .cp-msg .daysep span{background:#E2E8E3;font-size:9px;font-weight:800;padding:5px 11px}
  body.page-chat .cp-msg .bubble{max-width:80%;padding:10px 12px 8px;font-size:12.5px;border-radius:15px;box-shadow:0 4px 14px rgba(21,33,28,.05)}
  body.page-chat .cp-msg .bubble.them{background:var(--cp-card);color:var(--cp-ink);border-bottom-left-radius:5px}
  body.page-chat .cp-msg .bubble.me{border-bottom-right-radius:5px}
  body.page-chat .cp-msg .bubble .bt{font-family:inherit;font-size:8.5px}
  /* ---- DETAIL: composer (text-only — no attach) ---- */
  body.page-chat .cp-msg .composer{padding:9px 12px calc(10px + env(safe-area-inset-bottom));gap:8px;background:var(--cp-card)}
  body.page-chat .cp-msg .composer .cinput{border-radius:14px;background:var(--cp-paper);font-size:12.5px}
  body.page-chat .cp-msg .composer .send{width:44px;height:44px;border-radius:12px}
}

/* ============================================================================
   SURFACE: ACCOUNT DRAWER (premium mobile menu) — the burger→.dside drawer on
   account pages. DAY 25 (user reference "Premium account menu"): a rich app menu —
   profile card + completeness ring + quick-access grid + manage list + support +
   sticky sell/logout bar. ⚠ REAL data/routes only (§0): the reference's fake
   payments/payouts row, online-presence dot and no-page "Activity" row are OMITTED.
   The desktop sidebar (.dprof/.dnav) is UNTOUCHED — on mobile it is hidden and the
   new .dside-m takes over; .dside-m is display:none ≥769px so desktop stays frozen.
   ============================================================================ */
.dside-m{display:none}

@media(max-width:768px){
  /* drawer shell → a top / scroll / bottom app frame (overrides the DAY-22 drawer padding) */
  body.page-account .cp-dash .dside{padding:0;gap:0;overflow:hidden;width:min(92vw,384px)}
  body.page-account .cp-dash .dside .dprof,
  body.page-account .cp-dash .dside .dnav{display:none}
  body.page-account .cp-dash .dside .dside-m{display:flex;flex-direction:column;flex:1;min-height:0}
  /* top bar */
  .dside-m .dm-top{display:flex;align-items:center;justify-content:space-between;min-height:60px;padding:calc(12px + env(safe-area-inset-top)) 14px 12px;border-bottom:1px solid var(--cp-line);background:var(--cp-card)}
  .dside-m .dm-title{font-family:"Archivo",system-ui,sans-serif;font-size:15px;font-weight:800;letter-spacing:-.02em;color:var(--cp-ink)}
  .dside-m .dm-close{width:40px;height:40px;display:grid;place-items:center;border:1px solid var(--cp-line);border-radius:12px;background:var(--cp-card);color:var(--cp-pine);padding:0;cursor:pointer}
  .dside-m .dm-close svg{width:18px;height:18px;stroke:currentColor;stroke-width:2;fill:none}
  /* scroll area */
  .dside-m .dm-scroll{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:14px;scrollbar-width:none}
  .dside-m .dm-scroll::-webkit-scrollbar{display:none}
  /* profile card */
  .dside-m .dm-prof{padding:14px;border:1px solid var(--cp-line);border-radius:20px;background:var(--cp-card);box-shadow:0 8px 24px rgba(21,33,28,.05)}
  .dside-m .dm-prow{display:grid;grid-template-columns:60px minmax(0,1fr) 40px;align-items:center;gap:12px}
  .dside-m .dm-av{width:60px;height:60px;border-radius:18px;overflow:hidden;background:var(--cp-pine);color:#fff;display:grid;place-items:center;font-family:"Archivo",system-ui,sans-serif;font-weight:800;font-size:20px;border:3px solid #fff;box-shadow:0 6px 16px rgba(21,33,28,.15)}
  .dside-m .dm-av img{width:100%;height:100%;object-fit:cover}
  .dside-m .dm-pcopy{min-width:0}
  .dside-m .dm-nl{display:flex;align-items:center;gap:7px;min-width:0}
  .dside-m .dm-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:16px;font-weight:800;letter-spacing:-.02em;color:var(--cp-ink)}
  .dside-m .dm-badge{flex:0 0 auto;padding:3px 7px;border-radius:999px;background:#E2ECE5;color:#315441;font-size:8px;font-weight:900;text-transform:uppercase;line-height:1}
  .dside-m .dm-email{margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--cp-muted);font-size:10.5px}
  .dside-m .dm-loc{display:flex;align-items:center;gap:5px;margin-top:6px;color:var(--cp-muted);font-size:9.5px}
  .dside-m .dm-loc svg{width:12px;height:12px;stroke:currentColor;stroke-width:1.8;fill:none;flex:0 0 auto}
  .dside-m .dm-edit{width:40px;height:40px;display:grid;place-items:center;border:1px solid var(--cp-line);border-radius:12px;background:var(--cp-paper);color:var(--cp-pine)}
  .dside-m .dm-edit svg{width:17px;height:17px;stroke:currentColor;stroke-width:1.9;fill:none}
  /* completeness ring */
  .dside-m .dm-pbottom{display:flex;align-items:center;gap:12px;margin-top:14px;padding-top:12px;border-top:1px solid var(--cp-mist)}
  .dside-m .dm-ring{--p:0;width:46px;height:46px;flex:0 0 46px;display:grid;place-items:center;border-radius:50%;background:radial-gradient(circle 17px,var(--cp-card) 96%,transparent 100%),conic-gradient(var(--cp-pine) calc(var(--p)*1%),#E6ECE7 0)}
  .dside-m .dm-ring span{font-size:9px;font-weight:900;color:var(--cp-pine)}
  .dside-m .dm-pc{flex:1;min-width:0}
  .dside-m .dm-pc strong{display:block;font-size:11px;color:var(--cp-ink)}
  .dside-m .dm-pc span{display:block;margin-top:3px;color:var(--cp-muted);font-size:9px;line-height:1.35}
  .dside-m .dm-finish{flex:0 0 auto;color:var(--cp-fern);font-size:9px;font-weight:900;text-decoration:none}
  /* section labels */
  .dside-m .dm-label{margin:18px 4px 9px;color:#7A867E;font-size:9px;font-weight:900;letter-spacing:.11em;text-transform:uppercase}
  /* quick-access grid */
  .dside-m .dm-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}
  .dside-m .dm-card{position:relative;min-height:92px;display:flex;flex-direction:column;align-items:flex-start;justify-content:space-between;gap:8px;padding:12px;border:1px solid var(--cp-line);border-radius:17px;background:var(--cp-card);color:var(--cp-ink);text-decoration:none;box-shadow:0 6px 18px rgba(21,33,28,.04)}
  .dside-m .dm-card.primary{color:#fff;border-color:var(--cp-pine);background:linear-gradient(135deg,var(--cp-pine),var(--cp-pine2,#2E5A45))}
  .dside-m .dm-ci{width:35px;height:35px;display:grid;place-items:center;border-radius:11px;background:#EDF2EE;color:var(--cp-pine)}
  .dside-m .dm-card.primary .dm-ci{background:rgba(255,255,255,.14);color:#fff}
  .dside-m .dm-ci svg{width:18px;height:18px;stroke:currentColor;stroke-width:1.8;fill:none}
  .dside-m .dm-ct strong{font-size:11px;font-weight:900}
  .dside-m .dm-ct small{display:block;margin-top:2px;color:var(--cp-muted);font-size:8.5px}
  .dside-m .dm-card.primary .dm-ct small{color:rgba(255,255,255,.7)}
  .dside-m .dm-count{position:absolute;top:11px;right:11px;min-width:22px;height:22px;display:grid;place-items:center;padding:0 6px;border-radius:999px;background:#E2EAE4;color:#315441;font-size:8px;font-weight:900}
  .dside-m .dm-card.primary .dm-count{background:var(--cp-amber);color:#3a2408}
  .dside-m .dm-count.hot{background:var(--cp-amber);color:#3a2408}
  /* manage list + support card */
  .dside-m .dm-list{overflow:hidden;border:1px solid var(--cp-line);border-radius:18px;background:var(--cp-card)}
  .dside-m .dm-row,.dside-m .dm-support{display:grid;grid-template-columns:36px minmax(0,1fr) auto;align-items:center;gap:10px;padding:11px;color:var(--cp-ink);text-decoration:none}
  .dside-m .dm-row{min-height:54px;border-bottom:1px solid var(--cp-mist)}
  .dside-m .dm-list .dm-row:last-child{border-bottom:0}
  .dside-m .dm-support{margin-top:14px;border:1px solid var(--cp-line);border-radius:16px;background:var(--cp-paper)}
  .dside-m .dm-ri{width:36px;height:36px;display:grid;place-items:center;border-radius:11px;background:#EDF2EE;color:var(--cp-pine)}
  .dside-m .dm-ri svg{width:18px;height:18px;stroke:currentColor;stroke-width:1.8;fill:none}
  .dside-m .dm-rc{min-width:0}
  .dside-m .dm-rc strong{display:block;font-size:11.5px;font-weight:800;color:var(--cp-ink)}
  .dside-m .dm-rc small{display:block;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--cp-muted);font-size:8.5px}
  .dside-m .dm-chev{width:15px;height:15px;stroke:#88948C;stroke-width:2;fill:none}
  /* sticky bottom bar */
  .dside-m .dm-bottom{padding:10px 14px calc(12px + env(safe-area-inset-bottom));border-top:1px solid var(--cp-line);background:var(--cp-card)}
  .dside-m .dm-sell{width:100%;height:48px;display:flex;align-items:center;justify-content:center;gap:8px;border-radius:14px;background:var(--cp-amber);color:#3a2408;font-family:"Archivo",system-ui,sans-serif;font-size:12.5px;font-weight:800;text-decoration:none;box-shadow:0 10px 24px rgba(224,138,44,.28)}
  .dside-m .dm-sell svg{width:18px;height:18px;stroke:currentColor;stroke-width:2;fill:none}
  .dside-m .dm-links{display:flex;justify-content:center;margin-top:10px}
  .dside-m .dm-logout{display:inline-flex;align-items:center;gap:6px;color:#B64A39;font-size:10px;font-weight:800;text-decoration:none}
  .dside-m .dm-logout svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none}
}

/* ============================================================================
   DARK MODE — FULL-PORTAL COMPLETION (mobile ≤768px). From the dark-gap audit
   (workflow wf_f4fd9d75) over account/store/listing/catcards/mp/cp-uploader/main.
   Every rule is a [data-theme=dark] override → desktop stays frozen. Closes the
   hardcoded-hex / non-remapped-local-token gaps so dark is 100% across all inner
   surfaces (category browse, VIP, account, create/edit, seller, garage, chat, rules).
   Palette: DARKMODE-BRIEF.md. No red/blue token in the brief → dark analogues below.
   ============================================================================ */
@media(max-width:768px){
  /* the VIP/account green-check local token joins the remap */
  html[data-theme="dark"]{--cp-up:#60BE92}

  /* ---- catcards.css: inner /cat/ category cards (local .catsec tokens) — one remap ---- */
  html[data-theme="dark"] .catsec{
    --cat-card:#292E2C; --cat-line:#363D3A; --ic-bg:#363D3A; --ic-line:#586760;
    --cat-muted:rgba(255,255,255,.62); --cat-pine:#7EB99E;
    --amber-tint:rgba(224,138,44,.15); --amber-line:rgba(224,138,44,.38); --amber-2:#E6C294;
  }

  /* ---- account.css: dashboard/my-ads/promote/saved/profile/create-edit/reg/auth/chat ---- */
  html[data-theme="dark"] .cp-acc-bar{background:rgba(20,23,22,.92)}
  html[data-theme="dark"] .cp-acc .fld input:focus,
  html[data-theme="dark"] .cp-acc .fld select:focus,
  html[data-theme="dark"] .cp-acc .fld textarea:focus,
  html[data-theme="dark"] .cp-acc .form-control:focus,
  html[data-theme="dark"] .cp-acc .pricebox:focus-within,
  html[data-theme="dark"] .cp-dash .inp:focus,
  html[data-theme="dark"] .cp-dash .locpick-wrap select:focus,
  html[data-theme="dark"] .cp-dash .locpick-wrap .lp-pc input:focus,
  html[data-theme="dark"] .cp-msg .composer .cinput:focus,
  html[data-theme="dark"] .cp-reg .inp:focus,
  html[data-theme="dark"] .cp-auth .authform .inp:focus,
  /* ⚠ background-color, NOT the `background` shorthand: several of these controls carry a
     background-IMAGE (the location picker's select chevron is a data-URI SVG), and the shorthand
     resets it to none — the arrow vanished the moment the field was focused. */
  html[data-theme="dark"] .cp-acc .mp-photos .slim:hover{background-color:#363D3A}
  html[data-theme="dark"] .cp-acc .freenote,
  html[data-theme="dark"] .cp-acc .mp-myad__status.is-active,
  html[data-theme="dark"] .cp-dash .status.active,
  html[data-theme="dark"] .cp-dash .dsaved,
  html[data-theme="dark"] .cp-dash .listrow .thistag,
  html[data-theme="dark"] .cp-dash .tk-reco,
  html[data-theme="dark"] .cp-dash .fitflag.confirmed,
  html[data-theme="dark"] .cp-dash .pflash.ok,
  html[data-theme="dark"] .cp-auth.ok .authic,
  html[data-theme="dark"] .cp-acc .fitchip,
  html[data-theme="dark"] .cp-acc .eqchip:has(input:checked),
  html[data-theme="dark"] .cp-dash .fc-trend.up{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .cp-dash .kpi .kd.up{color:#60BE92}
  html[data-theme="dark"] .cp-acc .mp-myad__status.is-exp,
  html[data-theme="dark"] .cp-dash .status.exp,
  html[data-theme="dark"] .cp-dash .dalert,
  html[data-theme="dark"] .cp-dash .paydemo,
  html[data-theme="dark"] .cp-dash .fitflag.check,
  html[data-theme="dark"] .cp-dash .fi.review{background:#3A2D16;color:#E6C294}
  html[data-theme="dark"] .cp-reg .typetab.on,
  html[data-theme="dark"] .cp-dash .padrow.sel,
  html[data-theme="dark"] .cp-dash .tieropt.on,
  html[data-theme="dark"] .cp-msg .conv.active,
  html[data-theme="dark"] .cp-dash .bulkbar,
  html[data-theme="dark"] .cp-acc .fitpick{background:#252A28;border-color:#586760}
  html[data-theme="dark"] .cp-reg .regerr,
  html[data-theme="dark"] .cp-auth.err .authic,
  html[data-theme="dark"] .cp-dash .pflash.err,
  html[data-theme="dark"] .cp-dash .fi.save,
  html[data-theme="dark"] .cp-acc .mp-myad__btn--del:hover,
  html[data-theme="dark"] .cp-dash .lmenu.del:hover,
  html[data-theme="dark"] .cp-dash .ssrow .ssdel:hover,
  html[data-theme="dark"] .cp-dash .savedcard .sc-del:hover{background:#3A1E1A;color:#EEB3A7}
  html[data-theme="dark"] .cp-dash .status.draft,
  html[data-theme="dark"] .cp-dash .fi.follow,
  html[data-theme="dark"] .cp-dash .fi.msg{background:#1E2942;color:#9DB4E8}
  html[data-theme="dark"] .cp-acc .pvcard .pv-img,
  html[data-theme="dark"] .cp-dash .athumb,
  html[data-theme="dark"] .cp-dash .fc-thumb{background:linear-gradient(135deg,#2B322E,#363D3A)}
  html[data-theme="dark"] .cp-acc .mp-myad__img{background:#252A28}
  html[data-theme="dark"] .cp-acc .fitadd,
  html[data-theme="dark"] .cp-dash .pc-stop,
  html[data-theme="dark"] .cp-acc .shiprow .si,
  html[data-theme="dark"] .cp-reg .brow .bi{background:#292E2C}
  html[data-theme="dark"] .cp-acc .fitpick-hd svg{stroke:#5FA584}
  html[data-theme="dark"] .cp-acc .fitadd{border-color:#5FA584;color:#5FA584}
  html[data-theme="dark"] .cp-acc .fitpick-hd b,
  html[data-theme="dark"] .cp-reg .checkrow label{color:rgba(255,255,255,.88)}
  html[data-theme="dark"] .cp-acc .fitpick-hd small,
  html[data-theme="dark"] .cp-acc .fitpick-hd p{color:rgba(255,255,255,.62)}
  html[data-theme="dark"] .cp-dash .promo-cur{background:#292E2C}
  html[data-theme="dark"] .cp-dash .promo-note{background:#3A2D16;color:#E6C294}
  html[data-theme="dark"] .cp-dash .dnav a.out,
  html[data-theme="dark"] .cp-dash .menu a.del,
  html[data-theme="dark"] .cp-dash .avup-info .btns button.rm{color:#EEB3A7}
  html[data-theme="dark"] .cp-dash .avup .edit{border-color:#292E2C}

  /* ---- listing.css (VIP) — the hardcoded rest (most already via the --cp- and --cp-up tokens) ----
     ⚠ this line used to read "--cp-" + "*" + "/" + "--cp-up", which CLOSED the comment early and made
     CSS error recovery swallow the `.buy .fitrow.ok` rule right below it. Fixed 2026-07-25. ---- */
  html[data-theme="dark"] .cp-vip .buy .fitrow.ok{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .cp-vip .buy .fitrow.ok svg{stroke:#60BE92}
  html[data-theme="dark"] .cp-vip .desc .post_text,
  html[data-theme="dark"] .cp-vip .desc p,
  html[data-theme="dark"] .cp-vip .desc li,
  html[data-theme="dark"] .cp-vip .rv-body{color:rgba(255,255,255,.88)}
  html[data-theme="dark"] .cp-vip .eqbox .eq{background:#252A28}
  html[data-theme="dark"] .cp-vip .eqbox .eq:hover{border-color:#586760}
  html[data-theme="dark"] .cp-vip .eqbox .eq .ei{background:#363D3A}
  html[data-theme="dark"] .cp-vip .eqbox .box-h .hi,
  html[data-theme="dark"] .cp-vip .eqbox .box-h .hc{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .cp-vip .buy .fitrow.check{background:#3A2E18;color:#E6C294}
  html[data-theme="dark"] .cp-vip .buy .fitrow.check svg{stroke:#E6C294}
  html[data-theme="dark"] .cp-vip .buy .fitrow.universal,
  html[data-theme="dark"] .cp-vip .buy .fitrow.no{background:#252A28}
  html[data-theme="dark"] .cp-vip .buy-ship{color:rgba(255,255,255,.62)}
  html[data-theme="dark"] .cp-vip .fitcard .tag.ok{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .cp-vip .fitcard .tag.at{background:#3A2E18;color:#E6C294}
  html[data-theme="dark"] .cp-vip .fitcard .tag.sl{background:#1B2A38;color:#7FB2D8}
  html[data-theme="dark"] .cp-vip .mycar-chip{background:#183A2A;color:#60BE92;border-color:#586760}
  html[data-theme="dark"] .cp-vip .fitcard.mine{background:#183A2A}
  html[data-theme="dark"] .cp-vip .carmenu{background:#363D3A}
  html[data-theme="dark"] .cp-vip .offin:focus-within,
  html[data-theme="dark"] .cp-vip .fitsearch:focus-within,
  html[data-theme="dark"] .cp-vip .rvform select:focus,
  html[data-theme="dark"] .cp-vip .rvform textarea:focus{background:#363D3A}
  html[data-theme="dark"] .cp-vip .stars svg.off,
  html[data-theme="dark"] .cp-store .rev .rstars svg.off{fill:#586760}
  html[data-theme="dark"] .cp-vip .simcard .sff{color:#60BE92}
  html[data-theme="dark"] .cp-vip .bttoggle{background:#252A28;border-color:#586760}
  html[data-theme="dark"] .cp-vip .bttoggle .bt{color:rgba(255,255,255,.62)}
  html[data-theme="dark"] .cp-vip .bttoggle .bt:hover{color:#5FA584}
  html[data-theme="dark"] .cp-vip .garage-hero{background:linear-gradient(135deg,#363D3A,#292E2C)}
  html[data-theme="dark"] .cp-vip .gallery .main,
  html[data-theme="dark"] .cp-vip .simcard .sph{background:linear-gradient(135deg,#292E2C,#363D3A)}

  /* ---- store.css (seller) ---- */
  html[data-theme="dark"] .cp-store .acard p,
  html[data-theme="dark"] .cp-store .rev p,
  html[data-theme="dark"] .cp-store .abouttab p{color:rgba(255,255,255,.88)}

  /* ---- mp.css (legacy content bits still emitted on inner pages) ---- */
  html[data-theme="dark"] .mp-ad-actions,
  html[data-theme="dark"] .mp-ad-btn--call,
  html[data-theme="dark"] .panel-heading,
  html[data-theme="dark"] .btn-default,
  html[data-theme="dark"] .mp-field select,
  html[data-theme="dark"] .mp-field input,
  html[data-theme="dark"] .mp-sort,
  html[data-theme="dark"] .mp-filter-toggle,
  html[data-theme="dark"] .mp-accnav a,
  html[data-theme="dark"] .mp-savesearch,
  html[data-theme="dark"] .mp-share__btn,
  html[data-theme="dark"] .mp-myad__btn,
  html[data-theme="dark"] .mp-listing__fav,
  html[data-theme="dark"] .mp-listing__chips span,
  html[data-theme="dark"] .mp-catrow__cnt{background:#363D3A}
  html[data-theme="dark"] .rulestext{background:#292E2C}
  html[data-theme="dark"] .mp-listing__img,
  html[data-theme="dark"] .mp-specs__row:nth-child(even),
  html[data-theme="dark"] .mp-catrow__ic{background:#252A28}
  html[data-theme="dark"] .mp-myad__status.is-active,
  html[data-theme="dark"] .mp-savesearch.is-saved,
  html[data-theme="dark"] .mp-share__btn.is-done,
  html[data-theme="dark"] .mp-success__ic{background:#183A2A;color:#60BE92}

  /* ---- cp-uploader.css (create/edit photo editor) ---- */
  html[data-theme="dark"] .cp-up .cp-ed-box{background:#292E2C}
  html[data-theme="dark"] .cp-up .cp-ed-t,
  html[data-theme="dark"] .cp-up .cp-ed-cancel{background:#363D3A}
  html[data-theme="dark"] .cp-up .cp-ed-t:hover{background:#3F4744}
  html[data-theme="dark"] .cp-up .cp-add:hover{background:#363D3A}
  html[data-theme="dark"] .cp-up.cp-drag{background:#183A2A}
  html[data-theme="dark"] .cp-up .cp-up-err{background:#3A2420;border-color:rgba(178,59,46,.45);color:#E6A99E}

  /* ---- main.css (generic globals on DB-rendered content: rules/about, VIP description HTML) ---- */
  html[data-theme="dark"] .cp-vip .desc a,
  html[data-theme="dark"] .rulestext a{color:#7EB99E}
  html[data-theme="dark"] .rulestext hr,
  html[data-theme="dark"] .cp-vip .desc hr{border-top-color:#586760}

  /* ---- SVG line-art in dark: file category icons (.cisvg, baked pine stroke #1F3D30)
       + no-photo placeholder SVGs (ph-*.svg = light-gradient bg + green icon) render
       DARK/LIGHT-wrong on a dark page. invert(1)+hue-rotate(180) flips light bg → dark
       and the green icon → a lighter green, without touching REAL raster photos
       (only [src$=".svg"] is matched; jpg/png keep the brightness-dim). ---- */
  html[data-theme="dark"] .catsec .cat .ic .cisvg,
  html[data-theme="dark"] .lthumb img[src$=".svg"],
  html[data-theme="dark"] .van .photo img[src$=".svg"],
  html[data-theme="dark"] .cp-vip .gallery .main img[src$=".svg"],
  html[data-theme="dark"] .cp-vip .simcard .sph img[src$=".svg"],
  html[data-theme="dark"] .chatctx .cim img[src$=".svg"]{filter:invert(1) hue-rotate(180deg)}
}

/* ============================================================================
   SURFACE: CREATE / EDIT LISTING — mobile app STEP FLOW + form polish (≤768px).
   DAY 26 (2026-07-25). Covers plugins/account/finadd.php (act-add) + edit.php (act-edit),
   the seller's core flow, which until now had only 3 mobile rules (the DAY-25 tab-bar/z-index fix).
   Per the master prompts: §16 FORMS "long forms should become multi-step flows — progress, Back,
   Continue, Save draft, validation per step, keyboard-safe bottom actions"; §6 "right-side summary →
   review step"; §5.3/§8 "do not stack multiple large fixed bars" (Back/Next live INSIDE the existing
   sticky .cp-acc-bar); §10.2 44px targets; §12 SEO text untouched (no SEO text on this page).
   ⚠ LOAD ORDER: account.css loads AFTER this file → every rule here leads with #sellform (id) or
   body.act-add / body.act-edit so it out-specifies account.css's .cp-acc / .cp-acc-bar rules.
   ⚠ The step machine is assets/js/cp-wizard.js — mobile-only, no DOM moves, all fields stay in the
   one <form> so the POST/validation/cascades/uploader/preview are unchanged. See its header.
   ============================================================================ */
/* base, ALL widths: the JS-injected wizard chrome stays invisible outside mobile, so a
   mobile→desktop resize renders the approved desktop form byte-identically. */
.cp-wz-top,.cp-acc-bar .wz-back,.cp-acc-bar .wz-next,.cp-acc .wz-jump,.cp-acc .wz-msg,.cp-acc .wz-hint{display:none}

@media(max-width:768px){
  /* ---- 1. form shell: app-compact (h1/lead/sections/fields) ---- */
  body.act-add .cp-acc h1,body.act-edit .cp-acc h1{font-size:22px;line-height:1.22;margin:4px 0 2px}
  body.act-add .cp-acc .sub,body.act-edit .cp-acc .sub{font-size:13.5px;line-height:1.45;margin-bottom:14px}
  /* one column + the preview column BELOW the form (account.css @940 lifts it to order:-1, which put a
     still-empty preview card above the fields on a phone); in wizard mode it becomes the review step */
  body.act-add .cp-acc .split,body.act-edit .cp-acc .split{display:block;padding-bottom:6px}
  body.act-add .cp-acc .side,body.act-edit .cp-acc .side{position:static;gap:12px;margin-top:12px}
  body.act-add .cp-acc .sec,body.act-edit .cp-acc .sec{padding:16px;border-radius:14px;margin-bottom:12px}
  body.act-add .cp-acc .sec h2,body.act-edit .cp-acc .sec h2{font-size:16px;gap:9px}
  body.act-add .cp-acc .sec .hint,body.act-edit .cp-acc .sec .hint{margin-left:0}
  body.act-add .cp-acc .grid2,body.act-edit .cp-acc .grid2{grid-template-columns:1fr;gap:12px}
  /* ⭐ 16px controls: below 16px iOS Safari zooms the page on focus, which breaks the app feel */
  #sellform .fld input[type=text],#sellform .fld input[type=number],#sellform .fld select,
  #sellform .fld textarea,#sellform .form-control,#sellform select.form-control{font-size:16px;min-height:50px}
  #sellform .fld textarea,#sellform textarea.form-control{min-height:132px}
  #sellform .cpsel-btn{min-height:50px;font-size:15.5px}
  #sellform .pricebox{height:54px}
  #sellform .pricebox input.amt{font-size:21px}
  #sellform .pricebox .cur{font-size:18px}
  /* condition segments: stacked rows with the hint inline (3 cramped 1/3 columns at 360px) */
  body.act-add .cp-acc .seg,body.act-edit .cp-acc .seg{grid-template-columns:1fr;gap:8px}
  body.act-add .cp-acc .seg button,body.act-edit .cp-acc .seg button{min-height:50px;flex-direction:row;justify-content:flex-start;gap:9px;padding:8px 14px;text-align:left}
  body.act-add .cp-acc .seg button .cd,body.act-edit .cp-acc .seg button .cd{margin-left:auto}
  /* photo tiles: fill the row (3 up at 390px, 2 up at 320px) instead of the desktop 4-col grid */
  #sellform .cp-up-grid{grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:8px}
  /* length-unit note (cp-unit.js): its one-tap button needs a touch target */
  body .cp-acc .cp-unitfix{min-height:44px;padding:0 14px;font-size:13.5px}
  body .cp-acc .cp-unitnote{font-size:13px}

  /* Bouwjaar quick-pick chips (cp-year.js): the desktop 34px is under the 44px touch
     target the master prompt requires, and the note wants the mobile body size */
  body.act-add .cp-acc .cp-ychip,body.act-edit .cp-acc .cp-ychip{min-height:44px;padding:0 15px;font-size:14px}
  body.act-add .cp-acc .cp-ynote,body.act-edit .cp-acc .cp-ynote{font-size:13px}
  /* equipment + fitment chips ≥44px tap height */
  body.act-add .cp-acc .eqchip,body.act-edit .cp-acc .eqchip{min-height:44px;padding:8px 14px}
  body.act-add .cp-acc .fitadd,body.act-edit .cp-acc .fitadd{min-height:46px}
  body.act-add .cp-acc .fitchip,body.act-edit .cp-acc .fitchip{min-height:38px}

  /* ---- 2. THE STEP FLOW (only while cp-wizard.js is active) ---- */
  #sellform.cp-wz .split>.main>.sec,#sellform.cp-wz .split>.side{display:none}
  #sellform.cp-wz .split>.main>.sec.wz-on{display:block}
  #sellform.cp-wz .split>.side.wz-on{display:flex}
  #sellform.cp-wz .sec h2 .n{display:none}   /* the step number lives in the progress counter */
  #sellform.cp-wz .cp-wz-top{display:block;margin:2px 0 12px}
  #sellform.cp-wz .cp-wz-top .wz-count{display:block;font-family:"JetBrains Mono",ui-monospace,monospace;font-weight:600;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--cp-muted);margin-bottom:8px}
  #sellform.cp-wz .cp-wz-top .wz-prog{display:flex;gap:4px}
  #sellform.cp-wz .cp-wz-top .wz-prog i{height:4px;flex:1 1 0;border-radius:99px;background:var(--cp-mist)}
  #sellform.cp-wz .cp-wz-top .wz-prog i.done{background:var(--cp-fern)}
  #sellform.cp-wz .cp-wz-top .wz-prog i.on{background:var(--cp-pine)}

  /* ---- 3. the EXISTING sticky bar becomes the wizard nav (one fixed bar, never two) ---- */
  body.act-add .cp-acc-bar .ab-inner,body.act-edit .cp-acc-bar .ab-inner{height:auto;min-height:66px;padding:9px 16px;gap:8px}
  body.act-add .cp-acc-bar .ab-info,body.act-edit .cp-acc-bar .ab-info{display:none}
  body.act-add .cp-acc-bar .ab-r,body.act-edit .cp-acc-bar .ab-r{margin-left:0;flex:1 1 auto;min-width:0;gap:8px}
  body.act-add .cp-acc-bar .btn-draft,body.act-edit .cp-acc-bar .btn-draft{order:1;flex:0 0 auto;height:48px;padding:0 14px;font-size:13.5px}
  body.act-add .cp-acc-bar .btn-pub,body.act-edit .cp-acc-bar .btn-pub{order:3;flex:1 1 0;min-width:0;height:48px;padding:0 14px;font-size:15px;justify-content:center}
  #sellform.cp-wz .cp-acc-bar .wz-back{display:inline-flex;align-items:center;justify-content:center;flex:0 0 48px;width:48px;height:48px;padding:0;border:1px solid var(--cp-line);border-radius:12px;background:var(--cp-card);color:var(--cp-ink);cursor:pointer}
  #sellform.cp-wz .cp-acc-bar .wz-back svg{width:21px;height:21px}
  #sellform.cp-wz .cp-acc-bar .wz-back:active{background:var(--cp-mist)}
  #sellform.cp-wz.wz-first .cp-acc-bar .wz-back{display:none}
  #sellform.cp-wz .cp-acc-bar .wz-next{display:inline-flex;align-items:center;justify-content:center;gap:8px;order:2;flex:1 1 0;min-width:0;height:48px;padding:0 16px;border:0;border-radius:12px;background:var(--cp-pine);color:#fff;font-family:"Archivo",system-ui,sans-serif;font-weight:800;font-size:15px;cursor:pointer}
  #sellform.cp-wz .cp-acc-bar .wz-next svg{width:19px;height:19px;flex-shrink:0}
  #sellform.cp-wz.wz-last .cp-acc-bar .wz-next{display:none}
  #sellform.cp-wz:not(.wz-last) .cp-acc-bar .btn-pub{display:none}
  #sellform.cp-wz:not(.wz-last) .cp-acc-bar .btn-draft{width:48px;flex:0 0 48px;padding:0;justify-content:center}
  #sellform.cp-wz:not(.wz-last) .cp-acc-bar .btn-draft .ab-dtext{display:none}

  /* ---- 4. inline per-step validation + the honest photo nudge ---- */
  #sellform.cp-wz .wz-msg{display:block;margin-top:7px;font-size:12.5px;font-weight:600;color:#a12d2d}
  /* ⚠ MEASURED GOTCHA: a control's BORDER cannot be recoloured on these pages. mp.css has
     `.form-control{border:1px solid var(--mp-line)!important}` and a var() inside an !important
     SHORTHAND leaves Chrome pending-substitution longhands that even an inline !important
     border-color cannot beat (verified: border-style/width DO change, colour never does — which is
     also why account.css's --cp-line border never shows on these inputs). So the invalid state
     reuses the project's OWN error affordance: `.fld-err`, the same outline the server-side
     validation puts on a failed field (account.css:959) — added by cp-wizard.js next to .wz-invalid,
     so client and server errors look identical. Only the offset is tightened for phones. */
  #sellform.cp-wz .fld-err,body.act-add .cp-acc .fld-err,body.act-edit .cp-acc .fld-err{outline-offset:2px}
  #sellform.cp-wz .wz-hint{display:flex;gap:9px;align-items:flex-start;margin-top:12px;padding:11px 13px;border:1px solid #f0d7a8;border-radius:12px;background:#fbefd9;color:#8a5a12;font-size:13px;font-weight:600;line-height:1.45}
  #sellform.cp-wz .wz-hint svg{width:18px;height:18px;flex-shrink:0;margin-top:1px}

  /* ---- 5. the REVIEW step (the real .lcard preview + a jump-back list) ---- */
  #sellform.cp-wz .split>.side.wz-on .pv-label{font-family:"Archivo",system-ui,sans-serif;font-weight:800;font-size:17px;letter-spacing:-.01em;text-transform:none;color:var(--cp-ink);margin:0 0 2px}
  #sellform.cp-wz .wz-jump{display:block;background:var(--cp-card);border:1px solid var(--cp-line);border-radius:14px;overflow:hidden}
  #sellform.cp-wz .wz-jrow{display:flex;align-items:center;gap:11px;width:100%;min-height:52px;padding:10px 14px;border:0;border-bottom:1px solid var(--cp-mist);background:none;font:inherit;text-align:left;cursor:pointer}
  #sellform.cp-wz .wz-jrow:last-child{border-bottom:0}
  #sellform.cp-wz .wz-jrow:active{background:var(--cp-paper)}
  #sellform.cp-wz .wz-jn{width:22px;height:22px;border-radius:7px;background:var(--cp-paper);color:var(--cp-muted);font-family:"JetBrains Mono",ui-monospace,monospace;font-size:11.5px;font-weight:600;display:grid;place-items:center;flex-shrink:0}
  #sellform.cp-wz .wz-jt{flex:1 1 auto;min-width:0;font-size:14px;font-weight:600;color:var(--cp-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #sellform.cp-wz .wz-je{flex-shrink:0;font-size:12.5px;font-weight:700;color:var(--cp-pine)}
}
/* small phones (320-400px): "Concept opslaan" + "Plaats advertentie" + Back do not fit on one row —
   measured at 320px the publish label clipped (61px available for 78px of text). The primary action
   keeps its label; the draft button becomes icon-only (cp-wizard.js gives it an aria-label/title). */
@media(max-width:400px){
  #sellform.cp-wz .cp-acc-bar .btn-draft{width:48px;flex:0 0 48px;padding:0;justify-content:center}
  #sellform.cp-wz .cp-acc-bar .btn-draft .ab-dtext{display:none}
}
/* very narrow phones (≤360px): the three performance figures need ~113px to stay on one line.
   MEASURED at 320 with the 84px thumb: the row wrapped to three lines and the card grew 155→213px.
   Giving the content column 129px (72px thumb + tighter gutters) puts them back on one line. */
@media(max-width:360px){
  /* the 46px right gutter stays — it is what keeps the 2-line title clear of the kebab button */
  body.page-account .cp-dash #adRows .adrow{grid-template-columns:70px minmax(0,1fr);column-gap:10px}
  body.page-account .cp-dash .adrow .athumb{width:70px;height:70px}
  body.page-account .cp-dash .adrow .astats{gap:10px}
  body.page-account .cp-dash .adrow .astats .st{gap:4px}
  body.page-account .cp-dash .adrow .chk{left:16px;top:16px}
}

/* ============================================================================
   THE REST OF THE CREATE / ACCOUNT DEPTH (≤768px). DAY 26 (2026-07-25) — the
   surfaces the DAY-25 pass did not reach, each one a real route a seller walks:
     · /account/add/      — step 0 of selling: the category picker (act-add, no #sellform)
     · /account/saved/    — Bewaard (act-saved): saved searches + saved ads (was never touched)
     · /account/adsadd/   — the "your ad is online" success screen (act-adsadd)
     · /registration/     — CREATE ACCOUNT (page-registration, .cp-reg) + the shared .cp-auth cards
   ⚠ account.css loads after this file → rules lead with a body.act- / body.page- class to out-specify it.
   ⚠⚠ NEVER write the two characters that close a CSS comment inside one (a glob like "act-" + "*" + "/"
      + "page-" does exactly that): the comment ends early and CSS error recovery then swallows the NEXT
      rule — or, as happened here, the entire following @media block. Same family as the </ script>
      gotcha in inline JS. Line 843 below had the same bug since DAY-22 and killed one dark VIP rule.
   ============================================================================ */
@media(max-width:768px){
  /* ---- step 0: the category picker ---- */
  /* the DAY-25 rule hides the bottom nav on every act-add page so the sticky save bar is reachable,
     but the PICKER has no save bar — it lost its navigation for nothing. Give it back, keyed on the
     bar's real absence. Fails safe: where :has() is unsupported the DAY-25 state simply remains. */
  body.act-add:not(:has(.cp-acc-bar)) .mp-tabbar{display:flex}
  body.act-add .cp-acc .selcatdiv{margin-bottom:12px}
  body.act-add .cp-acc .selcatdiv select,body.act-add .cp-acc .selcatdiv .cpsel-btn{min-height:52px;font-size:16px}
  /* ajax.php gives the Continue link an inline style="margin-top:40px" — only !important reaches it */
  body.act-add .cp-acc .selcatdiv .btn-success{margin-top:18px!important;height:52px;width:100%}

  /* ---- SAVED (act-saved): rows and cards built for thumbs ---- */
  body.act-saved .cp-dash .dhead h1{font-size:22px}
  body.act-saved .cp-dash .ssrow{min-height:56px;padding:10px 14px;gap:10px}
  body.act-saved .cp-dash .ssrow .sstitle{font-size:14.5px;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  body.act-saved .cp-dash .ssrow .ssdel{width:44px;height:44px}   /* was 32px — under the 44px target */
  body.act-saved .cp-dash .ssrow .ssdel svg{width:19px;height:19px}
  /* the desktop grid is minmax(180px,1fr) → exactly ONE column on a phone; 2-up compares better */
  body.act-saved .cp-dash .savedgrid{grid-template-columns:repeat(2,1fr);gap:10px;padding:12px}
  body.act-saved .cp-dash .savedcard .sc-img{height:auto;aspect-ratio:4/3}
  body.act-saved .cp-dash .savedcard .sc-title{padding:10px 10px 0;font-size:13px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  body.act-saved .cp-dash .savedcard .sc-foot{padding:8px 10px 10px}
  body.act-saved .cp-dash .savedcard .sc-del{width:38px;height:38px}

  /* ---- the SUCCESS screen after publishing ---- */
  body.act-adsadd .cp-acc .mp-success{padding:26px 18px;margin:6px auto}
  body.act-adsadd .cp-acc .mp-success h1{font-size:21px;line-height:1.25}
  body.act-adsadd .cp-acc .mp-success p{font-size:14px}
  body.act-adsadd .cp-acc .mp-success__btns{display:flex;flex-direction:column;gap:9px;margin-top:20px}
  body.act-adsadd .cp-acc .mp-success__btns .btn{display:inline-flex;align-items:center;justify-content:center;width:100%;min-height:50px;font-size:15px;border-radius:12px}

  /* ---- CREATE ACCOUNT (/registration/) ---- */
  body.page-registration .cp-reg .rhead{margin-bottom:16px}
  body.page-registration .cp-reg .rhead h1{font-size:22px;line-height:1.22}
  body.page-registration .cp-reg .rhead .sub{font-size:13.5px;line-height:1.45}
  body.page-registration .cp-reg .reg{gap:16px}
  body.page-registration .cp-reg .typetabs{gap:9px;margin-bottom:16px}
  body.page-registration .cp-reg .typetab{padding:13px;gap:11px;border-radius:13px}
  body.page-registration .cp-reg .typetab .ti{width:38px;height:38px}
  body.page-registration .cp-reg .typetab .td{font-size:12px}
  body.page-registration .cp-reg .fc-body{padding:16px}
  body.page-registration .cp-reg .fsec{margin-bottom:20px}
  body.page-registration .cp-reg .fc-foot{padding:14px 16px}
  /* 16px inputs: below 16px iOS zooms the page on focus (the .inp default here is 14.5px) */
  body.page-registration .cp-reg .inp{font-size:16px;height:52px}
  body.page-registration .cp-reg .inp.mono{font-size:15px}
  body.page-registration .cp-reg .createbtn{height:54px;font-size:16px}
  /* the real location picker (Land→Regio→Stad + postcode quick-fill) matches the other fields */
  body.page-registration .cp-reg .locpick-wrap select,
  body.page-registration .cp-reg .locpick-wrap input{font-size:16px;height:52px}
  body.page-registration .cp-reg .locpick-wrap .cpsel-btn{min-height:52px;font-size:16px}
  body.page-registration .cp-reg .locpick-wrap .lp-hint{font-size:12.5px}
  /* the tap target is the <label for="…"> (it toggles the box), so the ROW is what needs to be
     comfortable — measured: enlarging the .cb box itself has no effect on these pages (a width set even
     with inline !important stays at account.css's 20px), so that rule is deliberately not shipped. */
  body.page-registration .cp-reg .checkrow{margin-top:14px;gap:12px;align-items:center}
  body.page-registration .cp-reg .checkrow label{font-size:13.5px;line-height:1.5;padding:6px 0;min-height:34px;display:flex;align-items:center;flex-wrap:wrap}
  body.page-registration .cp-reg .aside{gap:12px}
  body.page-registration .cp-reg .benefit,body.page-registration .cp-reg .bizperk{padding:16px;border-radius:14px}

  /* ---- shared AUTH cards (recovery, registration success/error) ---- */
  .cp-auth{padding:22px 0 40px}   /* own side padding → 0; the .container.mp-page 16px is the inset */
  .cp-auth .authcard{padding:26px 18px;border-radius:16px}
  .cp-auth .autht{font-size:21px}
  .cp-auth .authp{font-size:14px}
  .cp-auth .authform .inp{font-size:16px;height:52px}
  .cp-auth .authbtn{height:54px;font-size:16px}
}

/* ============================================================================
   DARK MODE — THE DAY 23→26 APP ELEMENTS + a MEASURED pine-fill contrast sweep.
   DAY 27 (2026-07-25). Dark had been PAUSED since DAY-23; the user re-enabled it
   for this pass. Mobile only (≤768px) — every rule below is a [data-theme=dark]
   override inside the media query, so the DESKTOP render stays byte-identical and
   desktop never turns dark.
   --------------------------------------------------------------------------
   HOW THIS LIST WAS BUILT (measured, not guessed): each surface was loaded at
   390px with data-theme=dark and every visible element was walked, computing its
   background luminance and its text/background contrast ratio (WCAG 2.2 AA:
   4.5 normal text, 3.0 large). Everything below is a real failure that the walk
   returned. Public pages AND the login-gated ones (dashboard, my-ads, saved,
   promote, profile, chat, create + edit form) were measured in a REAL logged-in
   session, so this also closes the "dark logged-in QA" item.
   ⚠⚠ METHOD GOTCHA worth keeping: in this environment the browser tab reports
   document.visibilityState === "hidden", so CSS TRANSITIONS NEVER TICK. Toggling
   data-theme and reading getComputedStyle then returns the LIGHT start value for
   every transitioned property, forever — half the portal looked "broken in dark"
   until a `transition:none` stylesheet was injected before measuring. Always kill
   transitions before judging a colour here (related to the DAY-26 "wait ~300ms"
   note — here waiting is not enough).
   --------------------------------------------------------------------------
   THE THREE RULES APPLIED (so future elements are handled the same way):
   1. A pine FILL on a small CONTROL (button, chip, badge, avatar) keeps the fill —
      the dark remap turns it into #5FA584 — and its TEXT/SVG flips to the brand
      ink #0F150E. White on #5FA584 measures 2.92:1 and fails.
   2. A pine FILL used as a large SURFACE that was DARK in light mode (store
      banner, VIP fitbar, balance box) must go back to being a DARK surface —
      flipping it to light green inverts the page's whole value structure.
   3. A pale tint chip maps to this file's established dark pair: green
      #183A2A/#60BE92, amber #3A2D16/#E6C294, red #3A1E1A/#EEB3A7, blue
      #1E2942/#9DB4E8, neutral #252A28 / #363D3A.
   No new hues are introduced — every value already exists in the dark layer
   (DARKMODE-BRIEF.md palette).
   ============================================================================ */
@media(max-width:768px){

  /* ---- 1. SHARED APP SHELL ---------------------------------------------- */
  /* ⭐⭐ THE BIGGEST FIND OF THIS PASS: on INNER pages the shared nav drawer was
     still fully LIGHT in dark mode. It sits OUTSIDE .cp-chrome, so DAY-23 gave it
     its own token block (see the .m-drawer rule above, whose comment reads "dark
     overrides deferred with the rest of dark") — and that block hardcodes the LIGHT
     values. Measured with the drawer open: panel #EFF1ED, rows #fff, while the text
     colour correctly followed the dark token to rgba(255,255,255,.88) — white text
     on a white panel. The homepage drawer was never affected because it reads the
     global :root tokens. Same remap as .cp-chrome, so every drawer rule adapts.
     ⚠ It escaped the automated sweep because a closed drawer is visibility:hidden
     and the walker skips hidden elements — overlays must be OPENED to be audited. */
  html[data-theme="dark"] .m-drawer{
    --paper:#141716; --card:#292E2C; --line:#586760; --mist:#252A28;
    --ink:rgba(255,255,255,.88); --muted:rgba(255,255,255,.62);
    --pine:#5FA584; --amber:#E08A2C;
  }
  /* breadcrumb shell (DAY-25): it was a translucent WHITE plate, so the whole
     trail rendered white-on-white (measured contrast 1.00 on every inner page). */
  html[data-theme="dark"] .cp-crumbshell{background:rgba(41,46,44,.72)}
  html[data-theme="dark"] .cp-crumbshell::after{background:linear-gradient(90deg,transparent,rgba(41,46,44,.95))}
  /* the brand mark is a pine square holding a pale-stroked caravan glyph (the
     stroke is an inline SVG attribute, which a CSS stroke still wins over) */
  html[data-theme="dark"] .cp-header .brand .mark svg,
  html[data-theme="dark"] .m-drawer .dw-head .brand .mark svg{stroke:#0F150E}
  /* nav drawer: the active language pill is a pine fill with white text */
  html[data-theme="dark"] .m-drawer .dw-langs a.active{color:#0F150E}
  /* …and the same fill in the new language bottom sheet (rule 1; measured 2.92:1) */
  html[data-theme="dark"] body.m-lang-ready .cp-langpop .langs a.active{color:#0F150E}
  /* the legacy Bootstrap dialogs are still the real contact/report/send-listing
     surfaces (footer Help → Contact opens #send_mess on EVERY page, VIP uses
     #send_message / #finsend). Their shell is plain Bootstrap, so it kept a #fff
     panel while its text followed the token to white — measured white-on-white.
     The AJAX-loaded contents inside read the remapped --mp- tokens already. */
  html[data-theme="dark"] .modal-content{background:#292E2C;border-color:#586760}
  html[data-theme="dark"] .modal-header,
  html[data-theme="dark"] .modal-footer{border-color:#586760}
  html[data-theme="dark"] .modal-content .close{color:rgba(255,255,255,.88);text-shadow:none;opacity:.75}

  /* ---- 2. VIP (plugins/ads) --------------------------------------------- */
  /* the DAY-24 sticky action bar was a translucent WHITE bar pinned over a dark page */
  html[data-theme="dark"] body.page-ads .vip-actionbar{background:rgba(20,23,22,.94)}
  html[data-theme="dark"] .vip-actionbar .va-msg{color:#0F150E}
  html[data-theme="dark"] .vip-actionbar .va-msg svg{stroke:#0F150E}
  /* gallery overlay controls stay LIGHT on purpose (they sit on the photo, not on
     the page) — but their pine text/stroke followed the remap and washed out, so
     they go back to the light-mode pine value */
  html[data-theme="dark"] .cp-vip .gallery .main .zoom{color:#1F3D30}
  html[data-theme="dark"] .cp-vip .gallery .main .zoom svg,
  html[data-theme="dark"] .cp-vip .gallery .main .gnav svg{stroke:#1F3D30}
  /* rule 2 — the fitment context bar is a dark hero in light mode */
  html[data-theme="dark"] .cp-vip .fitbar{background:#1c2b22}
  /* rule 1 — pine-filled controls */
  html[data-theme="dark"] .cp-vip .b-primary,
  html[data-theme="dark"] .cp-vip .offerbox button,
  html[data-theme="dark"] .cp-vip .rv-submit,
  html[data-theme="dark"] .cp-vip .fitcard .mytag,
  html[data-theme="dark"] .cp-vip .sellerbig .av,
  html[data-theme="dark"] .cp-vip .gallery .main .cond.new,
  html[data-theme="dark"] .cp-vip .simcard .scond.new{color:#0F150E}
  /* ⚠ NOT `.bttoggle .bt.is-on` — listing.css:320 fills it with a HARDCODED #1F3D30,
     which the remap never touches, so it is still a DARK plate and keeps white text.
     Re-inking it measured 1.56:1. Check whether a pine fill is a token or a literal
     before applying rule 1. */
  html[data-theme="dark"] .cp-vip .b-primary svg,
  html[data-theme="dark"] .cp-vip .rv-submit svg{stroke:#0F150E}
  /* honest "buy with confidence" body copy was #3b4a43 on the dark tinted card */
  html[data-theme="dark"] .cp-vip .protect-mini .pm-d{color:rgba(255,255,255,.72)}

  /* ---- 3. RESULTS / LRP / GARAGE leftovers ------------------------------ */
  /* the card location line reads var(--muted) with a #5C6A62 FALLBACK, and --muted
     only exists inside .cp-chrome — outside it the fallback wins and stays dark */
  html[data-theme="dark"] .lseller .lloc{color:rgba(255,255,255,.62)}
  /* pagination (results.css .cp-pager): tokens carry it, except the current-page pine fill
     (rule 1) and the error line's light-theme red */
  html[data-theme="dark"] .cp-pager .pg-num.is-cur{color:#0F150E}
  html[data-theme="dark"] .cp-pager .pg-err{color:#EEB3A7}
  html[data-theme="dark"] .lr-empty .lr-empty-cta{color:#0F150E}
  /* the garage price-apply button is another HARDCODED #1F3D30 fill — dark-on-dark
     inside the dark sidebar. Its sibling `.gr-opt.is-on` was already remapped to the
     dark pine on DAY-22, so this one follows it instead of only re-inking. */
  html[data-theme="dark"] .gr-price button{background:#5FA584;color:#0F150E}
  /* the same sidebar's small print is a literal #5C6A62 (facet headings, per-option
     counts, the price-range dash) — 2.43:1 on the dark panel */
  html[data-theme="dark"] .gr-fg h4,
  html[data-theme="dark"] .gr-opt .gr-c,
  html[data-theme="dark"] .gr-price .gr-dash{color:rgba(255,255,255,.62)}
  html[data-theme="dark"] .gr-opt.is-on .gr-c{color:rgba(15,21,14,.7)}

  /* ---- 4. CATEGORY HEADER (DAY-25) -------------------------------------- */
  /* the type badge kept the light amber-soft plate; use the dark amber pair so it
     matches every other "state" pill on a dark page (and reads 7:1 instead of 3.8) */
  html[data-theme="dark"] .cp-cat-type{background:#3A2D16;color:#E6C294}

  /* ---- 5. SELLER STORE --------------------------------------------------- */
  /* rule 2: the banner is the page's dark hero — as a light-green plate its whole
     content set (name, rating, stats, Message button) fell to 1.4–2.9:1 */
  html[data-theme="dark"] .cp-store .banner{background:#0F1210}
  html[data-theme="dark"] .cp-store .storeav{background:#1c2b22;color:#7EB99E;box-shadow:0 0 0 4px rgba(255,255,255,.08)}
  html[data-theme="dark"] .cp-store .chip.on,
  html[data-theme="dark"] .cp-store .vt.active{color:#0F150E}

  /* ---- 6. ACCOUNT (dashboard · my-ads · saved · promote · profile) ------- */
  /* rule 1 — every pine-filled control in the account shell */
  html[data-theme="dark"] .cp-dash .save,
  html[data-theme="dark"] .cp-dash .dprof .av,
  html[data-theme="dark"] .cp-dash .avup .av,
  html[data-theme="dark"] .cp-dash .dnav a.on,
  html[data-theme="dark"] .accnav a.is-on,
  html[data-theme="dark"] .cp-dash .fpill[aria-pressed="true"],
  html[data-theme="dark"] .cp-dash .catchip[aria-pressed="true"],
  html[data-theme="dark"] .cp-dash .fcard.open .fc-exp{color:#0F150E}
  html[data-theme="dark"] .cp-dash .save svg,
  html[data-theme="dark"] .cp-dash .dnav a.on svg,
  html[data-theme="dark"] .cp-dash .fcard.open .fc-exp svg{stroke:#0F150E}
  /* …but NOT while it is disabled (Promote's CTA before a listing+package are
     picked): the base rule paints it --cp-line/--cp-muted, which in dark is a
     2.4:1 grey-on-grey. Give the state its own dark plate so "disabled" still
     reads as disabled, and more legibly than the light theme manages. */
  html[data-theme="dark"] .cp-dash .save.is-disabled,
  html[data-theme="dark"] .cp-dash .save:disabled{background:#363D3A;color:rgba(255,255,255,.45)}
  /* the counters that ride inside those pills inherit a pale grey/white */
  html[data-theme="dark"] .cp-dash .fpill[aria-pressed="true"] .pc,
  html[data-theme="dark"] .cp-dash .catchip[aria-pressed="true"] .cc{color:rgba(15,21,14,.7)}
  /* the avatar-edit pencil is an amber chip → amber ink, like every other amber control */
  html[data-theme="dark"] .cp-dash .avup .edit{color:#3a2408}
  html[data-theme="dark"] .cp-dash .avup .edit svg{stroke:#3a2408}
  /* rule 2 — the payouts preview box is a dark plate in light mode (§0: the panel
     itself stays exactly as the owner approved, this is colour only) */
  html[data-theme="dark"] .cp-dash .balancebox{background:#1c2b22}
  /* the 14-day views chart is a hand-rolled SVG whose colours are INLINE PRESENTATION
     ATTRIBUTES in the PHP (account/index.php:245-248) — app.md §4.5 flagged it as
     needing dualisation and this is that fix. A CSS property still beats a
     presentation attribute, so no PHP change is needed: the trend line was dark pine
     on a dark card (invisible), the grid lines were the light mist, and the last-day
     dot wore a white ring. The amber dot itself is already correct on both themes. */
  html[data-theme="dark"] #dashChart line{stroke:#363D3A}
  html[data-theme="dark"] #cpChartLine{stroke:#7EB99E}
  html[data-theme="dark"] #cpChartDot{stroke:#292E2C}
  html[data-theme="dark"] #cpAreaGrad stop{stop-color:#7EB99E}
  /* pale tints that were still light */
  html[data-theme="dark"] .cp-dash .tk-price{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .cp-dash .settab .soonbadge{background:#3A2D16;color:#E6C294}
  html[data-theme="dark"] .cp-dash .setfoot .pmax-hint{color:#EEB3A7}
  html[data-theme="dark"] .cp-dash .savedcard .sc-del{color:#EEB3A7}
  html[data-theme="dark"] .cp-dash .savedcard .sc-del svg,
  html[data-theme="dark"] .cp-dash .fi.save svg{stroke:#EEB3A7}
  /* MY-ADS management card (DAY-26): the selection checkbox wore a WHITE 2px ring
     to lift it off the photo, and the three performance icons are data-URI SVGs
     whose stroke is the LIGHT muted #5C6A62 — near-invisible on a #292E2C card.
     Both are re-stated with the dark equivalents (card colour / dark muted). */
  html[data-theme="dark"] body.page-account .cp-dash .adrow .chk{box-shadow:0 0 0 2px rgba(41,46,44,.9)}
  html[data-theme="dark"] body.page-account .cp-dash .adrow .astats .st:nth-child(1)::before{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.62)' stroke-width='1.9'><path d='M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z'/><circle cx='12' cy='12' r='3'/></svg>")}
  html[data-theme="dark"] body.page-account .cp-dash .adrow .astats .st:nth-child(2)::before{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.62)' stroke-width='1.9'><path d='M12 21s-7-4.5-9-9a4.5 4.5 0 0 1 9-2 4.5 4.5 0 0 1 9 2c-2 4.5-9 9-9 9z'/></svg>")}
  html[data-theme="dark"] body.page-account .cp-dash .adrow .astats .st:nth-child(3)::before{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.62)' stroke-width='1.9'><path d='M4 5h16v11H8l-4 4z'/></svg>")}

  /* ---- 7. MESSAGES (the DAY-25 redesign) -------------------------------- */
  html[data-theme="dark"] body.page-chat .cp-msg .conv .crole{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] body.page-chat .cp-msg .conv.unreadrow{background:#20302a}
  html[data-theme="dark"] body.page-chat .cp-msg .conv .cchev{stroke:rgba(255,255,255,.45)}
  html[data-theme="dark"] body.page-chat .cp-msg .daysep span{background:#252A28}
  html[data-theme="dark"] body.page-chat .cp-msg .ctxbar .cx-th{background:#252A28}
  /* own bubbles: a pine fill with white text measured 2.92:1. A dark GREEN bubble
     (the file's established green tint) keeps "mine vs theirs" legible and is the
     conventional dark-mode chat treatment; the read ticks keep the green accent. */
  html[data-theme="dark"] .cp-msg .bubble.me{background:#183A2A;color:rgba(255,255,255,.92)}
  html[data-theme="dark"] .cp-msg .bubble.me .bt{color:rgba(255,255,255,.55)}
  html[data-theme="dark"] .cp-msg .bubble.me .bt svg{stroke:rgba(255,255,255,.5)}
  html[data-theme="dark"] .cp-msg .bubble.me .bt svg.rd{stroke:#60BE92}
  /* ⚠ the avatar tint classes are NOT all light: .g1 is the fern, but .g2 (#7a5230
     brown) and .g3 (#3f5c8a blue) are dark plates that keep white text — an
     unscoped ink rule here made the blue avatar unreadable (measured 2.74:1), so
     only the pine/fern-filled ones are re-inked. */
  html[data-theme="dark"] .cp-msg .convtab[aria-pressed="true"],
  html[data-theme="dark"] .cp-msg .conv .cav:not(.g2):not(.g3),
  html[data-theme="dark"] .cp-msg .thead .tav:not(.g2):not(.g3){color:#0F150E}
  html[data-theme="dark"] .cp-msg .composer .send svg{stroke:#0F150E}

  /* ---- 8. ACCOUNT DRAWER (.dside-m, DAY-25) ----------------------------- */
  html[data-theme="dark"] .dside-m .dm-av{border-color:#292E2C;color:#0F150E}
  html[data-theme="dark"] .dside-m .dm-badge,
  html[data-theme="dark"] .dside-m .dm-count{background:#183A2A;color:#60BE92}
  html[data-theme="dark"] .dside-m .dm-ci,
  html[data-theme="dark"] .dside-m .dm-ri{background:#363D3A}
  html[data-theme="dark"] .dside-m .dm-ring{background:radial-gradient(circle 17px,var(--cp-card) 96%,transparent 100%),conic-gradient(var(--cp-pine) calc(var(--p)*1%),#363D3A 0)}
  html[data-theme="dark"] .dside-m .dm-label{color:rgba(255,255,255,.62)}
  html[data-theme="dark"] .dside-m .dm-chev{stroke:rgba(255,255,255,.45)}
  html[data-theme="dark"] .dside-m .dm-logout{color:#EEB3A7}
  /* the "primary" quick-access card keeps its green gradient (it is the drawer's
     one emphasis) and takes brand ink, exactly like every other pine fill */
  html[data-theme="dark"] .dside-m .dm-card.primary{color:#0F150E}
  html[data-theme="dark"] .dside-m .dm-card.primary .dm-ci{background:rgba(15,21,14,.14);color:#0F150E}
  html[data-theme="dark"] .dside-m .dm-card.primary .dm-ct small{color:rgba(15,21,14,.68)}

  /* ---- 9. CREATE / EDIT LISTING — the DAY-26 step flow ------------------ */
  html[data-theme="dark"] #sellform.cp-wz .cp-acc-bar .wz-next{color:#0F150E}
  html[data-theme="dark"] #sellform.cp-wz .cp-acc-bar .wz-next svg{stroke:#0F150E}
  html[data-theme="dark"] .cp-acc-bar .btn-pub,
  html[data-theme="dark"] .cp-acc .sec h2 .n,
  html[data-theme="dark"] .cp-acc .seg button[aria-pressed="true"],
  html[data-theme="dark"] .cp-up .cp-tile .cp-cover{color:#0F150E}
  html[data-theme="dark"] .cp-acc-bar .btn-pub svg{stroke:#0F150E}
  html[data-theme="dark"] .cp-acc .seg button[aria-pressed="true"] .cd{color:rgba(15,21,14,.72)}
  /* per-step validation chrome (the inline message and the one-off photo nudge) */
  html[data-theme="dark"] #sellform.cp-wz .wz-msg{color:#EEB3A7}
  html[data-theme="dark"] #sellform.cp-wz .wz-hint{background:#3A2D16;border-color:#5a4420;color:#E6C294}
  /* the shared invalid-field affordance (client AND server side use .fld-err) */
  html[data-theme="dark"] .cp-acc .fld-err{outline-color:#E6A99E}
  /* the fitment chip's pale border survived the DAY-22 pass (its fill did not) */
  html[data-theme="dark"] .cp-acc .fitchip{border-color:#295540}
  /* Bouwjaar helper (cp-year.js): the chips read tokens already, so only the two
     literals need mapping — rule 1 for the selected chip's pine fill, and the amber
     pair for the "is this year right?" note. */
  html[data-theme="dark"] .cp-acc .cp-ychip.on{color:#0F150E}
  html[data-theme="dark"] .cp-acc .cp-ynote.cp-ywarn{color:#E6C294}
  /* length-unit note (cp-unit.js) — the project's standard dark amber pair */
  html[data-theme="dark"] .cp-acc .cp-unitnote{color:#E6C294}
  html[data-theme="dark"] .cp-acc .cp-unitfix{background:#3A2D16;border-color:#5c4a24;color:#E6C294}

  /* ---- 10. REGISTRATION / AUTH + the real location picker --------------- */
  html[data-theme="dark"] .cp-reg .createbtn,
  html[data-theme="dark"] .cp-auth .authbtn{color:#0F150E}
  html[data-theme="dark"] .cp-reg .createbtn svg,
  html[data-theme="dark"] .cp-auth .authbtn svg{stroke:#0F150E}
  /* EVERY native select's chevron is a data-URI SVG stroked with the LIGHT muted
     #5C6A62 — on a #141716 field it is effectively gone (measured on the location
     picker, but it is the same arrow on filters, sort and the listing form).
     ⚠ theme.css:28 sets that `background-image` with `!important` on `select,
     select.form-control`, so specificity alone cannot win — `!important` is the
     only thing that beats `!important`; the per-page rules (account.css) lose to
     it too, which is why one global override is both correct and sufficient.
     The rgba() literal keeps the exact dark --cp-muted value inside the URL, and
     `.cp-dash .sortsel select` keeps its own `background-image:none!important`. */
  html[data-theme="dark"] select,
  html[data-theme="dark"] select.form-control{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.62)' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>")!important}

/* ---- 11. SELF-SERVICE BANNERS — the app layer (DAY 38) -------------------
   ⚠ The owner's correction: mobile is NOT the desktop layout squeezed. In this portal the
     app design lives HERE, keyed on body.act-*, because app-mobile.css loads BEFORE
     account.css and an unkeyed rule would simply lose. These rules were written into
     account.css by mistake and moved verbatim, then extended with the app patterns the
     two master prompts require (step progress instead of desktop pills, 44px targets,
     16px fields, full-width actions).
   Surfaces: /account/add/ entry card (act-add) · /account/banner/ flow (act-banner) ·
             /account/banners/ list (act-banners). Desktop is untouched. ---- */
  /* ⭐ DAY 41 — the entry card rebuilt to the owner's `preview (7).html`. On a phone it is ONE
     column and deliberately tighter than the desktop card: the message, then the placement
     preview (a picture answers "where?" faster than a sentence), then the chips, then a
     full-width action. The panels are re-ordered individually, so `.cp-advsec__body` becomes
     `display:contents` — the same technique the DAY-40 banner flow uses for `.advside`.
     ⚠ The desktop card is FROZEN: every rule here is inside the 768px query and keyed on
       body.act-add, and the two-column grid is untouched above it. */
  body.act-add .cp-acc .cp-advsec{padding:16px 16px 16px 20px}
  body.act-add .cp-acc .cp-advsec__in{grid-template-columns:minmax(0,1fr);gap:12px}
  body.act-add .cp-acc .cp-advsec__body{display:contents}
  body.act-add .cp-acc .cp-advsec__hd{order:1;grid-template-columns:34px minmax(0,1fr);gap:10px}
  body.act-add .cp-acc .cp-advsec__prev{order:2;padding:8px}
  body.act-add .cp-acc .cp-advsec__chips{order:3;margin-left:0;gap:6px}
  body.act-add .cp-acc .cp-advsec__foot{order:4;margin-left:0;gap:9px}
  body.act-add .cp-acc .cp-advsec__i{width:34px;height:34px;border-radius:10px}
  body.act-add .cp-acc .cp-advsec__i svg{width:18px;height:18px}
  body.act-add .cp-acc .cp-advsec h2{font-size:17px;margin-bottom:4px}
  body.act-add .cp-acc .cp-advsec__p{font-size:12.5px;line-height:1.45}
  body.act-add .cp-acc .cp-advsec__chip{font-size:11px;padding:4px 8px}
  body.act-add .cp-acc .cp-advsec__cta{width:100%;justify-content:center;height:48px;font-size:15px}
  body.act-add .cp-acc .cp-advsec__note{font-size:11.5px}
  body.act-add .cp-acc .cp-advsec__stage{min-height:132px}
  body.act-add .cp-acc .cp-advsec__cap{font-size:10px;padding:4px 170px 4px 9px}
  /* ⚠ TOUCH TARGETS, MEASURED HONESTLY: the dot stays 6px and its HIT AREA becomes 24 x 44 —
     the master prompts' 44px floor is met on the axis a thumb travels, and the width is the
     WCAG 2.2 minimum, because seven targets cannot each be 44px wide in a 315px strip. The
     spacing (18px gap = 24px between centres) is chosen so no two hit areas overlap, which is
     the failure mode that actually loses taps. */
  body.act-add .cp-acc .cp-advsec__dots{right:12px;bottom:5px;gap:18px}
  body.act-add .cp-acc .cp-advsec__dot:after{inset:-19px -9px}
  /* ⚠ the position pill is a hardcoded LIGHT success pair in account.css (#e4efe8/#1c6b3f) —
     the project's dark counterpart is the fit pair, so it is remapped here rather than left as
     a bright chip on a dark card. Everything else on this card is token-driven and follows. */
  html[data-theme="dark"] body.act-add .cp-acc .cp-advsec__pos{background:#183A2A;color:#60BE92}
  /* ⚠ MEASURED AT 320: a 150px dot row inside a 245px strip left 65px for the place name and
     pushed 9px past the frame. The row tightens here; the hit area becomes 18 x 44 with centres
     18px apart — still no overlap, which is the failure that actually loses taps, and the
     vertical 44px floor is kept. Stated rather than silently rounded up. */
  @media(max-width:360px){
    body.act-add .cp-acc .cp-advsec__dots{gap:12px;right:9px}
    body.act-add .cp-acc .cp-advsec__dot:after{inset:-19px -6px}
    body.act-add .cp-acc .cp-advsec__cap{padding-right:136px}
  }
  body.act-banner .cp-advpage .advcard__fmt{font-size:19px}
  body.act-banner .cp-advpage .advtable th{font-size:13px}
  body.act-banner .cp-advpage .advprice{font-size:15px}
  body.act-banner .cp-advpage .advfoot{padding-bottom:90px}
  body.act-banner .cp-advpage .crumb .crumb-mid{display:none}
  body.act-banner .cp-advpage .advmodes{grid-template-columns:1fr}
  body.act-banner .cp-advpage .advgrid{grid-template-columns:1fr}
  body.act-banner .cp-advpage .advactions{flex-direction:column-reverse;align-items:stretch}
  body.act-banner .cp-advpage .advactions .advbtn{width:100%}
  body.act-banner .cp-advpage .advback{justify-content:center}
  body.act-banner .cp-advpage .advrail{font-size:12px;padding:5px 11px 5px 6px}
  body.act-banner .cp-advpage .advform input[type=text],body.act-banner .cp-advpage .advform input[type=url]{font-size:16px}
  body.act-banner .cp-advpage .advhero{display:block}
  body.act-banner .cp-advpage .advhero .advsteps__rail{margin-top:14px}
  body.act-banner .cp-advpage .advfmts{grid-template-columns:1fr}
  body.act-banner .cp-advpage .advfmt__in{grid-template-columns:108px minmax(0,1fr)}
  body.act-banner .cp-advpage .advctx{grid-template-columns:1fr}
  body.act-banner .cp-advpage .advctx__i{border-right:0;border-bottom:1px solid var(--cp-mist)}
  body.act-banner .cp-advpage .advctx__a{padding:10px 14px}
  body.act-banner .cp-advpage .advgrid2{grid-template-columns:1fr}
  /* ⚠ MEASURED: the url field computed 14.5px while every text field was 16px — the desktop rule
  `.cp-advpage .advform .fld input[type=url]` (0,4,1) out-specifies the mobile 16px rule
  (0,3,1), and under 16px iOS zooms the page on focus. Match the specificity, don't guess. */
  body.act-banner .cp-advpage .advform .fld input[type=url]{font-size:16px}
  /* the context action is a real tap target on a phone */
  body.act-banner .cp-advpage .advctx__a .advselbtn{height:44px;width:100%}
  /* ⚠ the panel header is a flex row; at 390px "Creative studio" and its note fought for the
  line and the title broke mid-phrase. Let it stack instead of hyphenating itself. */
  body.act-banner .cp-advpage .advpanel__hd{flex-wrap:wrap;row-gap:2px}
  body.act-banner .cp-advpage .advpanel__hd strong{flex:1 0 100%}

  /* the step rail is a DESKTOP component. On a phone the portal shows a mono step counter
     plus a segmented progress bar — the same pattern cp-wizard uses on the listing form. */
  body.act-banner .advsteps__rail{gap:0;margin:2px 0 14px;display:block}
  body.act-banner .advrail{display:none}
  body.act-banner .advrail.is-on{display:flex;border:0;background:none;padding:0;
    font-family:"JetBrains Mono",ui-monospace,monospace;font-weight:600;font-size:11px;
    letter-spacing:.1em;text-transform:uppercase;color:var(--cp-muted);margin-bottom:8px}
  body.act-banner .advrail.is-on .rn{width:auto;height:auto;background:none;color:var(--cp-muted);
    font-size:11px;letter-spacing:.1em}
  body.act-banner .advrail.is-on .rn:after{content:" /"}
  body.act-banner .advsteps__rail:after{content:"";display:flex;gap:4px}
  body.act-banner .advprog{display:flex;gap:4px;margin-bottom:16px}
  body.act-banner .advprog i{height:4px;flex:1 1 0;border-radius:99px;background:var(--cp-mist)}
  body.act-banner .advprog i.done{background:var(--cp-fern)}
  body.act-banner .advprog i.on{background:var(--cp-pine)}
  /* app cards: full-bleed inside the 16px gutter, no desktop double padding */
  body.act-banner .advpanel__bd,body.act-banner .advgrp__b{padding:12px}
  body.act-banner .advpanel__hd,body.act-banner .advgrp__h{padding:11px 12px}
  /* the primary action is the last thing on the screen and spans it (master prompt §10.2) */
  body.act-banner .advactions{flex-direction:column-reverse;align-items:stretch;gap:10px}
  body.act-banner .advactions .advbtn,body.act-banner .advactions .advbtn--go{width:100%;min-width:0;height:50px}
  body.act-banner .advback{justify-content:center;min-height:44px}

  /* ---- 11b. THE CREATIVE STUDIO, DAY 40 — the app pass over what was rebuilt today ----
     ⚠⚠ THE MEASURED FAULT: on a 390px screen the studio form ran from y=649 to y≈2550 and the
     PREVIEW started at **2550** — the advertiser typed a headline, a sub-line, a button and a
     photo entirely blind, and only met the banner after scrolling past the whole form. The
     desktop puts the preview beside the form; a phone has no beside. It goes ON TOP, which is
     also what the master prompt asks for (§8: the app feeling comes from the thing you are
     building being visible while you build it).
     `.advside` becomes `display:contents` so its four panels are grid items in their own right
     and can be ordered individually. ⚠ Desktop is untouched — this whole block is inside the
     768px query, and the sidebar keeps being a sidebar above it. */
  body.act-banner .advcols .advside{display:contents}
  body.act-banner .advcols > .advpanel{order:0}                    /* the studio form */
  body.act-banner .advside > .advpanel:first-child{order:-2}       /* the page preview */
  body.act-banner .advside > .advstage{order:-1}                   /* actual size */
  body.act-banner .advside > .advqual{order:1}                     /* the checks */
  body.act-banner .advside > .advmod{order:2}                      /* moderation */
  /* with display:contents the aside's own gap is gone; the grid supplies it */
  body.act-banner .advcols{gap:12px}

  /* the stage on a phone: the pills wrap instead of squeezing, and the zoom switch is a real
     target. STAGE_MAX_H already caps the height, so nothing here has to fight the picture. */
  body.act-banner .advstage__hd{padding:11px 12px}
  body.act-banner .advstage__pills{padding:10px 12px 0;row-gap:8px}
  body.act-banner .advzoom{margin-left:0}
  body.act-banner .advzoom__b{min-height:44px;padding:0 16px;display:inline-flex;align-items:center}
  body.act-banner .advstage .advtrue{margin:10px auto 0}
  body.act-banner .advstage .advtrue__m,body.act-banner .advstage .advnarrow{margin-left:12px;margin-right:12px}
  /* a 4px range track is a desktop affordance; a thumb you can hit with a thumb is 44px tall */
  body.act-banner .advpan{width:calc(100% - 24px);margin:10px 12px 0;height:44px}

  /* the aim window keeps its shape (it is the format's crop window) but may use the full
     gutter width on a phone, where 340px is most of the screen */
  body.act-banner .advaim{width:min(100%,calc(200px * var(--r,1.5)));max-width:100%}
  body.act-banner .advaimbar{flex-direction:column;align-items:stretch;gap:8px}
  body.act-banner .advaimbar .advclear{width:100%;min-height:44px}

  /* ---- 11c. /account/banners/ — the analytics + management screen (DAY 40) ----
     The card component is shared with /account/promote/, so only what this screen ADDS is
     answered here. ⚠ Measured at 390px: the action buttons were 40px, under the 44px floor, and
     `.bnfacts` was right-aligned — correct beside a chart on a desktop, wrong in a stacked
     mobile card where it reads as a column that lost its heading. */
  body.act-banners .bnbtn{min-height:44px;flex:1 1 auto;justify-content:center}
  body.act-banners .bnact{gap:8px}
  body.act-banners .bnact__f{flex:1 1 140px;display:flex}
  body.act-banners .bnact__f .bnbtn{width:100%}
  body.act-banners .bnfacts{text-align:left}
  body.act-banners .fc-det-grid{grid-template-columns:1fr;gap:14px}
  body.act-banners .bnpaysoon{flex:1 1 100%}

  /* ⚠ 44px is the floor for anything tappable (master prompt §10.2). Measured before this:
     `.advselbtn` 36px on the format cards, `.advclear` 25px, `.advseg__b` 32px. */
  body.act-banner .advselbtn{min-height:44px}
  body.act-banner .advclear{min-height:44px;padding:10px 14px}
  body.act-banner .advseg__b{min-height:44px;display:flex;align-items:center;justify-content:center}
  body.act-banner .advskin{min-width:44px;min-height:44px}

}

/* ============================================================================
   RESULT CARDS — the app list/grid pass.
   Shared by all four result surfaces (LRP, search, garage, seller store), which
   all render the same `.lcard` inside `.container.mp-page`.

   WHY: results.css was written for a desktop card and, below 900px, simply
   turned BOTH modes into the same vertical card in a different column count —
   which is exactly what master-prompt §13 forbids ("List and grid modes must
   not be the same card in different column counts"). Measured at 375px before
   this block: the list card was 437px tall and column-flowing (≈1.5 rows per
   screen), and in the 2-col grid nothing scaled down, so the 132px of inner
   width clipped the datasheet VALUE ("Touring caravan" needed 97px and had 51)
   and pushed the location 83px outside the card, where `overflow:hidden` ate
   it entirely.

   ⚠ SPECIFICITY: results.css loads AFTER app-mobile.css (header.php per-plugin
   loader), so every rule here is scoped through `.mp-page` to out-specify its
   (0,3,0) selectors. Do not drop that prefix.
   ============================================================================ */
@media(max-width:768px){

  /* ---- 1. GRID = a true compact comparison card (§13.2) ------------------ */
  .mp-page .lr-results.grid .lmain{padding:10px 11px 11px}
  .mp-page .lr-results.grid .ltitle{font-size:13.5px;line-height:1.28}
  .mp-page .lr-results.grid .lpn{font-size:10.5px;margin-top:3px}

  /* The datasheet: let the VALUE size the column and truncate the LABEL.
     results.css does the reverse (auto label + 1fr value) — correct at desktop
     width, wrong at 132px, where the label ("Length (m)") took 67px and left
     the value 51. A clipped value is a clipped FACT; a clipped label still
     reads. */
  .mp-page .lr-results.grid .lkv{margin-top:7px;gap:3px 8px;font-size:11px;
    grid-template-columns:minmax(0,1fr) auto}
  .mp-page .lr-results.grid .lkv dt{overflow:hidden;text-overflow:ellipsis}
  .mp-page .lr-results.grid .lkv dd{overflow:visible;text-overflow:clip}

  /* Seller: avatar + name + type on line 1, location on line 2. Before this,
     the row was `nowrap` at desktop sizes, so the bare text node broke across
     two lines ("Max / F.") while the location started at x=162 in a card that
     ended at 182. `.snm` is the span the two result templates now wrap the
     name in — without an element there, no ellipsis is possible. */
  .mp-page .lr-results.grid .lseller{margin-top:8px;gap:3px 5px;font-size:11px;
    flex-wrap:wrap;white-space:nowrap}
  .mp-page .lr-results.grid .lseller .av{width:17px;height:17px;font-size:8.5px}
  .mp-page .lr-results.grid .lseller .snm{min-width:0;overflow:hidden;text-overflow:ellipsis}
  .mp-page .lr-results.grid .lseller .type{font-size:9.5px;padding:1px 5px}
  .mp-page .lr-results.grid .lseller .lloc{flex:1 0 100%;margin-left:0;font-size:10.5px;
    min-width:0;overflow:hidden}

  .mp-page .lr-results.grid .lfoot{padding:9px 11px}
  .mp-page .lr-results.grid .lprice{font-size:15.5px}

  /* fitment flag is a chip, not a headline, at this size */
  .mp-page .lr-results .fitflag{font-size:10px;padding:3px 6px;gap:4px;margin-bottom:6px}
  .mp-page .lr-results .fitflag svg{width:11px;height:11px}

  /* ---- 2. LIST = a true horizontal app row (§13.1) ----------------------- */
  .mp-page .lr-results.list{gap:10px}
  .mp-page .lr-results.list .lcard{flex-direction:row;align-items:stretch;min-height:112px}
  .mp-page .lr-results.list .lthumb{flex:0 0 116px;width:116px;height:auto;min-height:0;
    align-self:stretch}
  .mp-page .lr-results.list .lthumb .fav{width:28px;height:28px;top:6px;right:6px;border-radius:7px}
  .mp-page .lr-results.list .lthumb .fav svg{width:14px;height:14px}
  .mp-page .lr-results.list .lcond{top:6px;left:6px;font-size:9px;padding:3px 6px;border-radius:5px}
  .mp-page .lr-results.list .lbody{flex-direction:column;min-width:0}
  .mp-page .lr-results.list .lmain{padding:10px 12px 0;min-width:0;display:block}
  .mp-page .lr-results.list .ltitle{font-size:14px;line-height:1.3}
  .mp-page .lr-results.list .lpn{font-size:10.5px;margin-top:3px}

  /* The same datasheet reads better here as ONE flowing metadata line — a
     two-column table inside a 200px column would wrap every value. Clamped to
     2 lines so consecutive rows keep an even rhythm. */
  .mp-page .lr-results.list .lkv{display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;
    -webkit-box-orient:vertical;overflow:hidden;margin-top:5px;font-size:11.5px;
    line-height:1.45;color:var(--cp-muted)}
  .mp-page .lr-results.list .lkv dt{display:inline;white-space:normal}
  .mp-page .lr-results.list .lkv dd{display:inline;margin:0 0 0 3px;text-align:left;
    white-space:normal;overflow:visible;text-overflow:clip}
  .mp-page .lr-results.list .lkv dd:not(:last-of-type)::after{content:" · ";color:var(--cp-line)}

  .mp-page .lr-results.list .lseller{margin-top:6px;gap:5px;font-size:11px;white-space:nowrap}
  .mp-page .lr-results.list .lseller .av{width:17px;height:17px;font-size:8.5px}
  .mp-page .lr-results.list .lseller .snm{min-width:0;overflow:hidden;text-overflow:ellipsis}
  .mp-page .lr-results.list .lseller .type{font-size:9.5px;padding:1px 5px}
  .mp-page .lr-results.list .lseller .lloc{margin-left:4px;font-size:10.5px;min-width:0;overflow:hidden}

  .mp-page .lr-results.list .lfoot{border-top:0;padding:4px 12px 10px;justify-content:flex-start;gap:10px}
  .mp-page .lr-results.list .lprice{font-size:16.5px}
  .mp-page .lr-results.list .lbtn{display:none}   /* the whole card is the link */
  .mp-page .lr-results.list .lspecs{display:none}
}

/* The location belongs OPPOSITE THE PRICE, bottom-right (user request) — in the
   seller line there simply is no room for it. Measured at 375: that line offers
   202px and holds 17 avatar + 34 name + 42 type + 90 location + gaps, so the
   name got 34px for the 35px it needs and rendered "Max…". Moving the location
   out leaves ~108px for a ~104px row, and the price row has 202px of inner
   width for a 79px price plus the location.

   It is positioned rather than re-parented because `.lloc` is emitted INSIDE
   `.lseller` (cat/ads_list.php:530) and moving it in PHP would change the
   desktop card, which is frozen. `bottom:10px;height:24px` are the price box's
   own values, so the two baselines line up exactly. The `:has()` padding
   reserves the strip so a long city can never collide with a long price, and it
   only applies to cards that actually carry a location (search cards do not).

   ⚠ Below 361px the row cannot hold both (148px of inner width vs 169px
   needed), so the block below keeps the location on its own line instead. */
@media(min-width:361px) and (max-width:768px){
  .mp-page .lr-results.list .lbody{position:relative}
  .mp-page .lr-results.list .lseller .lloc{position:absolute;right:12px;bottom:10px;
    height:24px;align-items:center;margin-left:0;max-width:46%}
  /* the reserve must cover the strip AND its 12px right offset — `46% + 8` let a
     "'s-Hertogenbosch, NL" collide with a "€ 249.950" by 4px (measured). */
  .mp-page .lr-results.list .lbody:has(.lloc) .lfoot{padding-right:calc(46% + 14px)}
  .mp-page .lr-results.list .lprice{min-width:0}
  /* ⚠ THE PRICE NEVER TRUNCATES — the city does. `.lcn` is the span the template
     now wraps the city in; an ellipsis is impossible on the bare text node that
     used to sit next to the pin SVG. */
  .mp-page .lr-results.list .lloc .lcn{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}

@media(max-width:768px){

  /* ---- 3. toolbar: the sort control was being squeezed to 95px, which left
     its label 37px for 55px of text ("Ne…"). Buy it ~27px back from the two
     icon controls and the button's own padding — every target stays ≥36px. -- */
  .mp-lrp .lr-viewtoggle .lr-vt{width:36px}
  .mp-lrp .lr-savesearch{width:38px;height:38px}
  .mp-lrp .lr-filter-toggle{padding:0 11px}
  .mp-lrp .lr-toolbar .cpsel .cpsel-btn{padding:0 31px 0 11px;font-size:13.5px}
  .mp-lrp .lr-toolbar .cpsel .cpsel-btn .cpsel-chev{right:10px;width:14px;height:14px}

  /* ---- 4. the Load-more skeletons must match whichever card is on screen -- */
  .mp-lrp .lr-results.list ~ .cp-pager .pg-skel{grid-template-columns:1fr}
  .mp-lrp .lr-results.list ~ .cp-pager .pg-skel span{height:118px}

  /* ---- 5. the seller store was the one result surface still stuck at ONE
     column in grid mode: the 2-col rule was scoped to `.mp-lrp` (LRP/search)
     and `.gr-main` (garage), so `#svResults` fell through to results.css's
     ≤560 single column — a 358px-wide card with a 357px photo per listing.
     Scoped through `.cp-store` on purpose: a bare `.mp-page .lr-results.grid`
     would also hit the featured `.promo-strip` carousel, which deliberately
     replaces the grid with a snap scroller at the same specificity. -------- */
  .mp-page .cp-store .lr-results.grid{grid-template-columns:1fr 1fr;gap:11px}
  .mp-page .cp-store .lr-results.grid .lthumb{height:132px}
  .mp-page .cp-store .lr-results.grid .lfoot .lbtn{display:none}

  /* ---- 6. "Browse by type" (.cp-landlinks) is desktop-only.
     It is an SEO internal-link strip to the per-type landing pages
     (/cat/<vehiclecat>/<type-slug>/, added DAY-20) and it sits right under the
     SEO prose — but its entries are read from filter 304, i.e. EXACTLY the
     options the Type group in the filter sheet already offers. Verified on both
     vehicle LRPs: caravans 2/2 identical (65px eaten), motorhomes 6/6 identical
     (102px). On a phone that is a duplicate control pushing the actual results
     further down the first screen, so the app hides it and the filter sheet is
     the single way to narrow by type.
     ⚠ SEO is NOT lost: `display:none` leaves the anchors in the HTML, so they
     are still crawled and followed, the desktop page carries them normally, and
     the sitemap emits every landing URL through its `land` child. Do NOT
     "clean this up" by removing the markup in cat/index.php. -------------- */
  .mp-page .cp-landlinks{display:none}

  /* ---- 7. GARAGE FITMENT RESULTS ---------------------------------------
     The hand-written sheet CSS that used to live here is GONE. The garage
     sidebar now carries the `mp-filters` class itself, so mp.css:549 turns it
     into the same slide-up sheet as the LRP and every .grp/.chip/.dd/.rng rule
     applies without a second copy. Only the two things mp.css does not know
     about remain: the trigger button, and the panel's own padding (the LRP
     panel gets its padding from .f-top/.f-body, which this one also uses). */
  .mp-page .gr-filter-toggle{display:inline-flex;margin:0 0 12px}
}

/* the close button is a sheet affordance only — desktop keeps the plain sidebar header */
/* (the garage header is now `.mp-filters__head f-top`, so mp.css:441 already
   hides its close button above 768 — no garage-specific rule needed) */

/* Narrow phones: the list row's seller line needs ~163px and only has 148 at
   320px, so the location (last flex item, shrinkable) was being cut without an
   ellipsis — measured. Wrap it onto its own line instead, exactly like the grid
   card does: +17px of row height buys back the whole city name. */
@media(max-width:360px){
  .mp-page .lr-results.list .lseller{flex-wrap:wrap;gap:3px 5px}
  .mp-page .lr-results.list .lseller .lloc{flex:1 0 100%;margin-left:0}
}
