/* Small, responsive polish; original palette and layout retained. */
*,*::before,*::after{box-sizing:border-box}
html{scroll-padding-top:90px}
body{overflow-wrap:anywhere}
button,a,input,textarea,select{touch-action:manipulation}
button:disabled{cursor:not-allowed;opacity:.55}
button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid #68baff;outline-offset:3px}
.quality-banner{position:relative;z-index:120;display:flex;gap:12px;align-items:center;justify-content:center;padding:12px 16px;background:#132d48;color:#fff;border-bottom:1px solid #4774a0;font-size:15px;line-height:1.6}
.quality-banner[hidden]{display:none}
.quality-banner button,.quality-state button{min-height:44px;border:1px solid #64a9e7;border-radius:10px;background:#123b63;color:#fff;padding:8px 14px;flex-shrink:0}
.quality-state{grid-column:1/-1;min-height:130px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;text-align:center;padding:24px;border:1px solid #274863;border-radius:16px;background:#0c1725;color:#dce9f4;line-height:1.7}
.modal-card,.product-form,.coupon-form,.cart-drawer{max-height:calc(100dvh - 24px);overflow-y:auto;overscroll-behavior:contain}
.modal-card,.product-form,.coupon-form{scroll-padding-bottom:100px}
.table-wrap{max-width:100%;overflow-x:auto;overscroll-behavior-x:contain}
.product-media{object-fit:contain}
.cart-item b,.history-card b,.product-card h3{overflow-wrap:anywhere}
.form-error{line-height:1.6;min-height:1.6em}
[aria-busy=true]{cursor:progress}
.status-chip{line-height:1.5}
@media(max-width:768px){
 input:not([type=checkbox]):not([type=radio]),select,textarea{font-size:16px!important;min-height:44px}
 #topupModal #bankPayPanel .topup-fields input,#topupModal .topup-fields input{font-size:16px!important}
 button,.btn,.nav-item,.pay-method-tab{min-height:44px}
 #authBtn,#registerBtn,#openCart,#mobileMenu,.modal-close,.close-circle{min-width:44px;min-height:44px}
 .modal{padding:12px!important;align-items:center}
 .modal-card,.product-form,.coupon-form{width:min(100%,680px)!important;max-width:100%!important;padding:20px 16px!important}
 .cart-drawer{width:min(100%,430px)!important;padding-bottom:calc(20px + env(safe-area-inset-bottom))}
 .cart-summary,.form-actions{padding-bottom:env(safe-area-inset-bottom)}
 .form-grid,.product-modal-layout{grid-template-columns:1fr!important}
 .toolbar{flex-wrap:wrap;gap:10px}.toolbar input,.toolbar select{max-width:100%;min-width:0}
 .quality-banner{flex-wrap:wrap;font-size:14px}
 .admin-main{min-width:0;max-width:100%}
 .detail-grid{grid-template-columns:1fr!important}
 #adminNav{max-width:100%;overflow-x:auto}
 #artPlayers a{display:inline-flex;align-items:center;min-height:44px}
}
@media(max-width:375px){.header-actions{gap:4px}.header-actions .btn{padding-inline:9px}.container{padding-inline:12px}.cart-head h2{font-size:21px}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
 
@media(max-width:768px){#topupModal input[type=file]{font-size:16px!important}}
@media(max-width:768px){#topupModal #topupBankFields.topup-fields input[type=file]{font-size:16px!important}}

/* 2026-10-11 contrast: admin avatar initial was 4.43:1 on #126fea, now 5.29:1 (WCAG AA) */
.avatar{background:#1166dd}
/* 2026-10-11 contrast: cart count badge was 4.1:1 at 10px */
#cartCount{background-color:#1166dd;color:#fff}

/* ===== 2026-10-12 design normalisation (01 Design) ===== */
/* D-01: status chips had no colour for cancelled/superseded/expired/needs_admin_review,
   so inside history buttons they rendered black on navy (1.1:1). One default + full set. */
.status-chip{color:#c7d3e0;border-color:#3a4f68}
.status-chip.cancelled,.status-chip.superseded,.status-chip.expired,.status-chip.sold{color:#b9c6d4;border-color:#3d4c5e}
.status-chip.needs_admin_review,.status-chip.queued{color:#ffd36a;border-color:#66542c}
.status-chip.available{color:#57e3a6;border-color:#24624a}
/* D-05: one placeholder colour on every storefront field (browser default #757575 was 4.1:1 on navy) */
input::placeholder,textarea::placeholder{color:#8a9db3;opacity:1}
/* D-05: coupon field text was 11px; align with the other cart text */
.coupon-field input{font-size:14px}
/* D-09: the shared modal max-height (100dvh - 24px) also capped the full-height cart drawer,
   leaving a 24px strip of the page visible under it. The drawer is edge-to-edge by design. */
.cart-drawer{max-height:100dvh}


/* ===== 2026-10-12 02 Mobile (website-completion) ===== */
/* M-01 product modal: the close button sat under the product image (both positioned, image later in DOM) */
.modal-close{z-index:5}
/* M-02/M-03 background page must not scroll behind the cart drawer or admin modals (customer modals already lock via JS) */
body:has(.cart-drawer.open),body:has(.modal.open){overflow:hidden}
/* M-04 admin toast is invisible (opacity 0) but still caught taps at the bottom of the screen */
.toast:not(.show){pointer-events:none}
/* M-05 admin tablet 721-1050px: icon rail rendered empty (::first-letter does not apply to flex items) and the brand text stacked letter by letter; use the phone top-nav layout instead */
@media(min-width:721px) and (max-width:1050px){
 .admin-shell{display:block}
 .sidebar{position:relative;width:100%;height:auto}
 .sidebar nav{display:flex;overflow-x:auto;overscroll-behavior-x:contain}
 .sidebar .nav-item,.nav-item{min-width:max-content;justify-content:flex-start;font-size:12px!important}
 .admin-brand div{display:grid;font-size:inherit}
 .admin-user div{display:grid}
 .side-bottom{display:flex;justify-content:space-between;align-items:center}
 .logout{width:auto}
}
/* M-06 touch targets: phones (<=768px) and any coarse-pointer device such as iPad (820/1024px) */
@media(max-width:768px),(pointer:coarse){
 button,.btn,.nav-item,.mini-btn,.pay-method-tab,#topupModal .pay-method-tab{min-height:44px}
 .modal-close,.close-circle,.x,.connect-card .modal-close,#authBtn,#registerBtn,#openCart,#mobileMenu,.wallet-pill,.user-pill,.connect-pending-pill,.icon-btn{min-width:44px;min-height:44px}
 .cart-item button{min-width:44px;min-height:44px}
 .connect-copy-btn,.connect-order-row.muted .connect-copy-btn{width:44px;height:44px}
 #productGrid .mini-btn,#productGrid[data-kind="single"] .mini-btn{min-height:44px}
 #productGrid .mini-btn:not(.buy){min-width:44px}
 .nav-links a{min-height:44px;display:flex;align-items:center}
 .footer-grid>div:not(:first-child){gap:0}
 .footer-grid>div:not(:first-child) a{display:inline-flex;align-items:center;min-height:44px}
 .shop-breadcrumb button,.shop-breadcrumb a{min-height:44px}
 .footer-bottom a{display:inline-flex;align-items:center;min-height:44px}
 .row-actions button,.mini-action,.secret-line button,.logout{min-height:44px}
 input:not([type=checkbox]):not([type=radio]):not([type=hidden]),select{min-height:44px}
}
/* M-07 top-up: account/phone number must never break mid-number ("123-4-56789-" / "0") on small phones */
#topupModal .bank-copy-block>strong{white-space:nowrap;overflow-wrap:normal;word-break:normal;font-size:clamp(19px,6.6vw,30px)}
/* M-08 top-up: "scan QR" label touched the QR panel edge at 320-430px */
@media(max-width:768px){#topupModal #bankPayPanel .bank-qr-wrap{padding:10px 12px}}
/* M-09 logged-in header at 320-400px: wallet + pending-connect + cart + user overflowed the page (baseline 324px at 320) and the amount wrapped ("฿5,0/00") */
@media(max-width:400px){
 .site-header .nav-wrap{padding-inline:2px;gap:6px}
 .nav-actions{gap:3px}
 .wallet-pill{padding:0 7px;white-space:nowrap;flex-shrink:0}
 .wallet-pill b{white-space:nowrap}
 .user-pill,.connect-pending-pill{padding:0 6px;justify-content:center}
 .nav-actions .icon-btn{position:relative;padding:0 6px;justify-content:center}
 .nav-actions .icon-btn>b{position:absolute;top:1px;right:0;min-width:18px;height:18px;padding:0 4px;font-size:11px}
}
/* M-10 long customer modals (product, top-up, connect, account, guide): the close button scrolled away with the content and phones have no Escape key; keep it pinned while scrolling */
@media(max-width:768px),(pointer:coarse){
 .modal-card>.modal-close{position:sticky;top:-4px;right:auto;float:right;justify-self:end;align-self:flex-end;margin:-16px 0 -28px auto;z-index:5}
}

/* 2026-10-12 launch L-08: fallbacks for browsers without dvh (Safari < 15.4, Chrome/Android WebView < 108,
   e.g. older Facebook/LINE in-app browsers) or the inset shorthand (Safari < 14.1). Modern browsers skip both blocks.
   Integration: the cart drawer stays full height (Design D-09), so it gets 100vh rather than 100vh-24px. */
@supports not (height:100dvh){.cart-drawer{height:100vh;max-height:100vh}.modal-card,.product-form,.coupon-form{max-height:calc(100vh - 24px)}.stock-modal-card{max-height:calc(100vh - 34px)}}
@supports not (inset:0){.modal-backdrop,.drawer-backdrop{top:0;right:0;bottom:0;left:0}}


/* ===== 2026-10-12 M-11 product modal close (GPT PC3 finding, merged by main agent) =====
   Baseline/live: IMG.product-media painted over the x at 320/390/430 (elementFromPoint = IMG; tap timed out).
   Close button now sits outside the scrolling area; details scroll inside #productModalBody. */
/* Product modal close-button fix: keep close control outside scrollable content.
   Mobile-only; merge into source CSS, rebuild hashed assets and test with CSP enabled. */
@media (max-width: 680px) {
  #productModal { padding: 8px 10px; }
  #productModal .product-modal-card {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 10px 12px 12px;
    max-height: calc(100dvh - 16px);
  }
  #productModal .product-modal-card > .modal-close {
    position: relative;
    top: auto;
    right: auto;
    flex: 0 0 44px;
    align-self: flex-end;
    width: 44px;
    height: 44px;
    min-height: 44px;
    margin: 0 0 8px;
    z-index: 20;
    display: grid;
    place-items: center;
    transform: none;
  }
  #productModalBody {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
