/* 21³ DS — Dream. Design. Deliver.  Brand: navy #0B2A4A, orange #F7941D, cream #FFF8EE
 * NOTE: the bottom-nav rules ALSO exist as critical inline CSS in views/layout.js
 * (CRITICAL_NAV_CSS) so the nav/icon size can never depend on this file loading. Keep in sync. */
:root{
  --navy:#0B2A4A; --navy-2:#123C66; --orange:#F7941D; --orange-d:#D97B06;
  --cream:#FFF8EE; --ink:#12213A; --muted:#5C6B84; --line:rgba(11,42,74,.14);
  --ok:#1E8E4E; --warn:#C77700; --bad:#C8202A; --info:#1F5FBF;
  --r:16px; --r-sm:10px; --shadow:0 10px 30px rgba(11,42,74,.10);
  --safe-b: env(safe-area-inset-bottom, 0px);
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Inter,system-ui,sans-serif;
  color:var(--ink);background:var(--cream);-webkit-text-size-adjust:100%;
  padding-bottom:calc(72px + var(--safe-b));
}
/* NOTE: the admin drawer's open state is defined in the admin block below — it must toggle the
 * CONTAINER (`.sidebar`), not a child of it. `body.nav-open .sidenav{display:block}` used to live here
 * and did nothing, because `.sidebar` is `display:none` on mobile: the Menu button was dead. */
@media(min-width:900px){body{padding-bottom:0}}
a{color:var(--navy);text-decoration:none}
a:hover{text-decoration:underline}
img{max-width:100%}
h1,h2,h3,h4{line-height:1.25;margin:0 0 10px}
h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.05rem}
.wrap{max-width:1080px;margin:0 auto;padding:16px}
.wrap.narrow{max-width:620px}
.muted{color:var(--muted)}
.small,.hint{font-size:.83rem}
.req{color:var(--bad)}
.mt{margin-top:16px}.mt-s{margin-top:8px}.mb{margin-bottom:16px}
.grid{display:grid;gap:20px}
@media(min-width:640px){.grid.c2{grid-template-columns:repeat(2,1fr)}.grid.c3{grid-template-columns:repeat(3,1fr)}}
@media(min-width:960px){.grid.c4{grid-template-columns:repeat(4,1fr)}}
@media(min-width:640px) and (max-width:959px){.grid.c4{grid-template-columns:repeat(2,1fr)}}
.row{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.row.between{justify-content:space-between}
.inline{display:inline}
.stack{display:grid;gap:16px}

/* backgrounds */
.blob{position:fixed;border-radius:50%;filter:blur(70px);opacity:.5;z-index:-1;pointer-events:none}
.blob.a{width:340px;height:340px;background:#F7941D;top:-120px;right:-120px}
.blob.b{width:360px;height:360px;background:#4F7FE5;bottom:-140px;left:-140px;opacity:.25}

/* topbar */
.topbar{position:sticky;top:0;z-index:40;background:rgba(255,248,238,.92);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
.topbar-in{max-width:1080px;margin:0 auto;padding:10px 16px;display:flex;gap:14px;align-items:center;justify-content:space-between}
.brand{display:flex;align-items:center;gap:10px;font-weight:800;color:var(--navy)}
.brand:hover{text-decoration:none}
.brand-mark{background:var(--navy);color:#fff;border-radius:10px;padding:5px 9px;font-size:15px;letter-spacing:.5px}
.brand-mark sup{color:var(--orange);font-size:.7em}
.brand-mark i{font-style:normal;color:var(--orange);margin-left:2px}
.brand-txt{display:none;flex-direction:column;line-height:1.05}
.brand-txt b{font-size:.95rem}
.brand-txt small{font-weight:500;color:var(--muted);font-size:.7rem}
@media(min-width:520px){.brand-txt{display:flex}}
.topnav{display:none;gap:14px;font-size:.86rem;font-weight:600}
@media(min-width:1000px){.topnav{display:flex}}
.topnav a.on{color:var(--orange-d)}
.topbar-act{display:flex;gap:8px;align-items:center}
.cartlink{position:relative;font-size:1.25rem;line-height:1;padding:6px}
.cartlink b{position:absolute;top:-2px;right:-4px;background:var(--orange);color:#fff;border-radius:999px;font-size:.65rem;padding:1px 5px}

/* footer + bottom nav */
.foot{border-top:1px solid var(--line);margin-top:32px;padding:22px 0;background:rgba(255,255,255,.5)}
.foot-in{display:grid;gap:14px;font-size:.86rem}
.foot-links{display:flex;flex-wrap:wrap;gap:10px 16px}
.botnav{position:fixed;bottom:0;left:0;right:0;z-index:45;display:flex;background:#fff;border-top:1px solid var(--line);padding-bottom:var(--safe-b)}
.botnav a{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;padding:9px 4px;font-size:.68rem;font-weight:600;color:var(--muted);min-height:56px}
.botnav a span{display:block;white-space:nowrap}
.botnav a.on{color:var(--navy)}
.botnav svg{display:block;width:22px;height:22px;flex:0 0 22px;min-width:22px;min-height:22px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.botnav a.on svg{stroke:var(--orange-d)}
@media(min-width:900px){.botnav{display:none}}

/* buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:11px 18px;
  border-radius:999px;border:1px solid transparent;font-weight:700;font-size:.94rem;cursor:pointer;background:#fff;color:var(--navy)}
.btn.primary{background:linear-gradient(135deg,var(--navy),var(--navy-2));color:#fff}
.btn.accent{background:linear-gradient(135deg,var(--orange),var(--orange-d));color:#fff}
.btn.ghost{border-color:var(--line);background:rgba(255,255,255,.7)}
.btn.danger{background:#fff;color:var(--bad);border-color:rgba(200,32,42,.4)}
.btn.sm{min-height:40px;padding:8px 14px;font-size:.84rem}
/* every tap target ≥44px on touch devices */
@media (pointer:coarse){.btn{min-height:46px}.btn.sm{min-height:44px}.pager a{min-height:44px;display:inline-flex;align-items:center}}
.btn.block{width:100%}
.btn[disabled],.btn.disabled{opacity:.5;cursor:not-allowed;filter:grayscale(.4)}
.btn:hover{text-decoration:none;filter:brightness(1.03)}

/* cards */
.card{background:rgba(255,255,255,.82);backdrop-filter:blur(14px) saturate(160%);border:1px solid rgba(255,255,255,.7);
  border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
.card-h{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:14px 18px;border-bottom:1px solid var(--line)}
.card-h h2,.card-h h3{margin:0}
.card-b{padding:18px}
.notice{border-radius:var(--r-sm);padding:12px 14px;font-size:.87rem;border:1px solid;margin-bottom:14px}
.notice.warn{background:#FFF6E5;border-color:#F2CE8A;color:#7A5200}
.notice.info{background:#EEF4FF;border-color:#BCD2F5;color:#1B3E76}
.notice.ok{background:#EDF8F0;border-color:#B7E2C4;color:#175E35}
.notice.bad{background:#FDEDEE;border-color:#F3BFC3;color:#8A1620}
.flash{margin:14px 0;padding:12px 14px;border-radius:var(--r-sm);font-size:.9rem;font-weight:600}
.flash.info{background:#EEF4FF;color:#1B3E76}.flash.ok{background:#EDF8F0;color:#175E35}
.flash.warn{background:#FFF6E5;color:#7A5200}.flash.bad{background:#FDEDEE;color:#8A1620}
.empty{padding:22px;text-align:center;color:var(--muted);font-size:.9rem}
.pill{display:inline-block;padding:3px 9px;border-radius:999px;font-size:.7rem;font-weight:800;letter-spacing:.3px;white-space:nowrap;
  background:#EEF1F6;color:#33455F}
.pill.ok{background:#E6F6EC;color:#15633A}.pill.warn{background:#FFF3DC;color:#8A5B00}
.pill.bad{background:#FDE9EA;color:#8E1B24}.pill.info{background:#E9F0FF;color:#1B4C9E}
.integ{font-size:.7rem;font-weight:700;padding:2px 8px;border-radius:999px}
.integ.ok{background:#E6F6EC;color:#15633A}.integ.warn{background:#FFF3DC;color:#8A5B00}
.money{font-weight:700;white-space:nowrap}

/* forms */
.fld{margin-bottom:14px;display:flex;flex-direction:column;gap:6px}
.fld label{font-weight:700;font-size:.86rem}
input,select,textarea{font:inherit;padding:11px 12px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:#fff;color:var(--ink);min-height:44px;width:100%}
textarea{min-height:88px}
input:focus,select:focus,textarea:focus{outline:2px solid rgba(247,148,29,.5);border-color:var(--orange)}
.chk{display:flex;gap:10px;align-items:flex-start;font-size:.88rem;min-height:44px}
.chk input{width:20px;height:20px;min-height:20px;margin-top:3px;flex:0 0 auto}
.chk-fld{padding:2px 0}
fieldset{border:1px solid var(--line);border-radius:var(--r-sm);padding:12px;margin:0 0 14px}
legend{font-weight:800;font-size:.84rem;padding:0 6px;color:var(--navy)}
.opt-btns{display:flex;flex-wrap:wrap;gap:8px}
.opt-btns label{border:1px solid var(--line);border-radius:999px;padding:9px 14px;font-size:.86rem;background:#fff;cursor:pointer;min-height:42px;display:inline-flex;align-items:center;gap:7px}
.opt-btns input{width:18px;height:18px;min-height:18px}
.opt-btns label.sel{border-color:var(--orange);background:#FFF6E7}
/* A variant/colour whose own stock is gone: still visible (so the customer knows the option exists),
   clearly marked and not selectable. */
.opt-btns label.off{cursor:not-allowed;opacity:.6;background:#F6F5FA;text-decoration:none;position:relative}
.opt-btns label.off .swatch{filter:grayscale(1)}
.opt-btns label.off .pill{margin-left:2px}
.swatch{width:20px;height:20px;border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 1px var(--line)}

/* masked PIN entry */
.pin-row{display:flex;gap:8px;align-items:center}
.pin-input{letter-spacing:8px;text-align:center;font-size:1.3rem;font-family:ui-monospace,monospace}
.pin-input[type=password]{letter-spacing:6px;font-size:1.5rem}
.pin-eye{flex:0 0 auto;min-width:48px;font-size:1.1rem;padding:8px 10px}
.pin-eye.on{border-color:var(--orange);background:#FFF6E7}

/* login vs register choice */
.choice-grid{display:grid;gap:16px;margin:18px 0}
@media(min-width:640px){.choice-grid{grid-template-columns:1fr 1fr}}
.choice-card{display:flex;flex-direction:column;gap:6px;border:1px solid var(--line);border-radius:16px;padding:18px;
  background:rgba(255,255,255,.85);color:var(--ink);min-height:120px}
.choice-card:hover{text-decoration:none;border-color:var(--orange);background:#FFF9F0;box-shadow:var(--shadow)}
.choice-card b{font-size:1.08rem;color:var(--navy)}
.choice-card small{color:var(--muted);line-height:1.4}
.choice-ico{font-size:1.6rem}
.choice-cta{margin-top:auto;font-weight:800;color:var(--orange-d);font-size:.9rem}

/* numbered how-to steps (donation linking) */
ol.steps{margin:0 0 4px 18px;padding:0;display:grid;gap:6px;font-size:.9rem}
ol.steps li{padding-left:2px}
ol.steps li b{color:var(--navy)}
.mb-s{margin-bottom:8px}
details summary{cursor:pointer;font-weight:700;font-size:.88rem;color:var(--navy)}

/* packaging item picker (touch friendly: big rows, real 44px tap targets) */
.pkg-list{display:grid;gap:10px;margin:6px 0 4px}
.pkg-row{display:grid;gap:10px;grid-template-columns:1fr;align-items:center;
  border:1px solid var(--line);border-radius:12px;padding:10px 12px;background:#fff}
@media(min-width:640px){.pkg-row{grid-template-columns:1fr 130px}}
.pkg-pick{display:flex;gap:12px;align-items:flex-start;min-height:44px;cursor:pointer}
.pkg-pick input{width:22px;height:22px;min-height:22px;margin-top:2px;flex:0 0 auto}
.pkg-name{display:flex;flex-direction:column;gap:2px;font-size:.9rem;line-height:1.35}
.pkg-qty{margin:0}
.pkg-qty input{max-width:none;width:100%;text-align:center;font-weight:700;min-height:44px}
@media(min-width:640px){.pkg-qty input{min-height:44px}}

/* tables */
.tw{overflow-x:auto}
.tbl{width:100%;border-collapse:collapse;font-size:.86rem}
.tbl th,.tbl td{padding:10px 12px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
.tbl th{background:rgba(11,42,74,.05);font-size:.76rem;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
.tbl tr:hover td{background:rgba(247,148,29,.05)}

/* contact / social channels (footer + Contact Us share this block) */
.channels{list-style:none;margin:0 0 6px;padding:0;display:grid;gap:10px}
.channels.compact{gap:8px;margin-bottom:0}
.ch{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:12px;
  background:rgba(255,255,255,.72);color:var(--navy);min-height:44px}
.ch:hover{text-decoration:none;border-color:var(--orange);background:#FFF9F0}
.ch svg{flex:0 0 auto;color:var(--navy)}
.ch-txt{display:flex;flex-direction:column;min-width:0}
.ch-txt b{font-size:.88rem}
.ch-txt small{color:var(--muted);font-size:.78rem;word-break:break-word}
.ch-badge{margin-left:auto;font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.4px;
  background:#FFF3DC;color:#8A5B00;border-radius:999px;padding:3px 9px;white-space:nowrap}
.ch.off{opacity:.85;background:rgba(255,255,255,.5);color:var(--muted)}
.ch.off svg{color:var(--muted)}
.foot-h{display:block;margin-bottom:10px;font-size:.9rem}

/* product cards */
.pcard{background:#fff;border-radius:var(--r);border:1px solid var(--line);overflow:hidden;display:flex;flex-direction:column}
.pcard-img{display:block;aspect-ratio:1/1;background:#F1F0F5}
.pcard-img img{width:100%;height:100%;display:block}
.img-ph{display:flex;align-items:center;justify-content:center;height:100%;color:var(--muted);font-size:.8rem;background:repeating-linear-gradient(45deg,#F4F3F8,#F4F3F8 10px,#EFEEF6 10px,#EFEEF6 20px)}
.media-missing{background:repeating-linear-gradient(45deg,#F4F3F8,#F4F3F8 10px,#EFEEF6 10px,#EFEEF6 20px);color:var(--muted);
  display:flex;align-items:center;justify-content:center;min-height:120px;font-size:.8rem;border-radius:var(--r-sm);text-align:center;padding:8px}
/* sold-out overlay + optional second picture (catalog card) */
.pcard-img{position:relative;display:block}
.pc-flag{position:absolute;top:10px;left:10px;font-size:.7rem;font-weight:800;letter-spacing:.4px;
  padding:4px 10px;border-radius:999px;color:#fff;box-shadow:0 2px 8px rgba(0,0,0,.18)}
.pc-flag.bad{background:#C8202A}
.pc-flag.warn{background:#C77700}
.pcard.is-out .pcard-img img{filter:saturate(.72) brightness(.97)}
.pcard-body{padding:14px;display:flex;flex-direction:column;gap:8px;flex:1}
.pcard-body h3{margin:0;font-size:1rem}
.pc-meta{display:flex;gap:8px;align-items:center;flex-wrap:wrap;font-size:.78rem}
.pc-price{font-weight:800;color:var(--navy);font-size:1.02rem}
.pcard .btn{margin-top:auto}

/* promo admin list */
.promo-admin{display:grid;gap:12px}
.promo-admin-row{display:grid;gap:12px;grid-template-columns:1fr;align-items:center;
  border:1px solid var(--line);border-radius:12px;padding:12px;background:#fff}
@media(min-width:760px){.promo-admin-row{grid-template-columns:200px 1fr auto}}
.promo-thumb{width:100%;aspect-ratio:2/1;border-radius:8px;overflow:hidden;background:#F1F0F5}
.promo-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.promo-meta{display:flex;flex-direction:column;gap:3px;min-width:0}
.promo-actions{display:flex;gap:6px;flex-wrap:wrap;align-items:center}

/* homepage promo carousel (2:1 banners, one visible at a time) */
.promo-carousel{position:relative;overflow:hidden;border-radius:var(--r);box-shadow:var(--shadow);background:#0B2A4A;margin-bottom:20px}
.pc-track{display:flex;transition:transform .5s ease}
.pc-slide{flex:0 0 100%;position:relative;display:block;min-width:0}
.pc-slide img{width:100%;height:auto;display:block;aspect-ratio:2/1;object-fit:cover}
.pc-cap{position:absolute;left:16px;right:16px;bottom:14px;color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.45);
  display:flex;flex-direction:column;gap:2px;pointer-events:none}
.pc-cap b{font-size:1.05rem}
.pc-cap small{font-size:.82rem;opacity:.95}
@media(max-width:520px){.pc-cap b{font-size:.92rem}.pc-cap small{font-size:.75rem}}
.pc-nav{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:50%;
  border:0;background:rgba(11,42,74,.55);color:#fff;font-size:1.5rem;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px)}
.pc-nav:hover{background:rgba(11,42,74,.8)}
.pc-nav.prev{left:10px}
.pc-nav.next{right:10px}
.pc-dots{position:absolute;left:0;right:0;bottom:8px;display:flex;gap:7px;justify-content:center}
.pc-dot{width:9px;height:9px;border-radius:50%;border:0;padding:0;cursor:pointer;background:rgba(255,255,255,.5)}
.pc-dot.on{background:#F7941D;width:24px;border-radius:999px}
/* Without JS the slides stay visible as a vertical stack of promo images (and the controls, which
 * could not do anything, are hidden). `body.js` is added by an inline script in <head>… see head(). */
html.no-js .pc-track,body:not(.js) .pc-track{flex-direction:column}
body:not(.js) .pc-nav,body:not(.js) .pc-dots{display:none}

/* hero — LIGHT on purpose. It used to be a dark navy block, which hid the owner's dark logo in the
 * header area; the hero itself carries only the brand name + tagline + CTAs (the logo lives in the
 * header, so repeating it here was a duplicate — owner asked to remove "logo below carousel"). */
.hero{background:linear-gradient(135deg,#FFFFFF 0%,#F4F1FF 60%,#FFF7EA 100%);color:var(--ink);
  border:1px solid var(--line);border-radius:20px;padding:24px 20px;box-shadow:var(--shadow)}
.hero-in{display:block}
.hero-copy{min-width:0}
.hero h1{font-size:1.6rem;margin-bottom:8px;color:var(--ink)}
.hero p{margin:0 0 16px;color:var(--muted);font-size:.94rem;max-width:62ch}
.hero .row{gap:10px;flex-wrap:wrap}
.hero .btn.ghost{background:#fff;color:var(--navy);border-color:var(--line)}
.hero .btn.accent{color:#3A2400}

/* timeline */
.tl{list-style:none;padding:0;margin:0;display:grid;gap:14px}
.tl li{display:flex;gap:12px;position:relative}
.tl-dot{width:12px;height:12px;border-radius:50%;margin-top:6px;flex:0 0 auto;background:var(--muted)}
.tl-dot.ok{background:var(--ok)}.tl-dot.warn{background:var(--warn)}.tl-dot.bad{background:var(--bad)}.tl-dot.info{background:var(--info)}
.tl-body{display:flex;flex-direction:column;gap:2px;font-size:.9rem}
.tl-note{color:var(--muted);font-size:.84rem}
.stepper{display:flex;gap:6px;overflow-x:auto;padding-bottom:4px}
.stepper .st{flex:0 0 auto;font-size:.72rem;padding:5px 10px;border-radius:999px;background:#EEF1F6;color:var(--muted);font-weight:700}
.stepper .st.done{background:#E6F6EC;color:#15633A}
.stepper .st.now{background:var(--navy);color:#fff}

/* admin */
.admin-shell{display:grid;grid-template-columns:1fr;min-height:100vh}
@media(min-width:900px){.admin-shell{grid-template-columns:246px 1fr}}
.sidebar{background:var(--navy);color:#fff;padding:14px;display:none}
@media(min-width:900px){.sidebar{display:block;position:sticky;top:0;height:100vh;overflow-y:auto}}
.side-brand .brand-txt b,.side-brand .brand-txt small{color:#fff}
.side-user{display:flex;justify-content:space-between;align-items:center;gap:8px;margin:14px 0;padding:10px;border-radius:12px;background:rgba(255,255,255,.1);font-size:.85rem}
.sidenav{display:grid;gap:2px}
.sidenav a{color:#D6E1F0;padding:9px 10px;border-radius:9px;font-size:.87rem;font-weight:600}
.sidenav a:hover{background:rgba(255,255,255,.12);text-decoration:none}
.sidenav a.on{background:var(--orange);color:#231400}
.side-foot{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap}
.admin-main{padding:16px;min-width:0}
.admin-top{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:6px}
.admin-top h1{font-size:1.3rem;margin:0;min-width:0;overflow-wrap:anywhere}
/* Drawer furniture: the backdrop, the close button and the drawer header only exist on mobile. */
.nav-backdrop{display:none}
.nav-close{display:none}
.side-nav-head{display:none}
.only-mobile{display:none}
/* The MOBILE ADMIN DRAWER.  KEEP IN SYNC with ADMIN_DRAWER_CSS in views/layout.js, which inlines the
 * same rules so the drawer still works when this file is cached/stale or fails to load.
 * Two real bugs lived here (owner: "when i'm using the mobile phone, i can not see all the menu bar,
 * and the menu button not working", then again on iPhone Chrome):
 *  1. `.sidebar` was `display:none` and the open state was applied to `.sidenav` (a CHILD), so the
 *     Menu button toggled a class that could not show anything — the whole 24-item admin menu was
 *     unreachable on a phone (the bottom nav belongs to the customer layout only).
 *  2. There was no backdrop / close button / body scroll lock, so an opened drawer was a trap.
 * The container is now the thing that is shown, it scrolls its own content (so every item is
 * reachable), and it can be closed by the button, the backdrop, Esc, or picking an item.
 * The media query also matches a COARSE-pointer device up to 1024px so a phone held in landscape
 * (an iPhone Pro Max is 932 CSS px wide) still gets the drawer instead of a cramped desktop column;
 * a touch laptop with a fine primary pointer keeps the normal sidebar. */
@media(max-width:899px),(max-width:1024px) and (pointer:coarse){
  .sidebar{display:none;position:fixed;top:0;right:30%;bottom:0;left:0;z-index:60;overflow-y:auto;
    -webkit-overflow-scrolling:touch;padding-bottom:calc(24px + var(--safe-b));box-shadow:var(--shadow)}
  body.nav-open .sidebar{display:block}
  body.nav-open{overflow:hidden}
  /* the admin back office has no bottom navigation (that is the customer layout), so it must not
   * reserve 72px of empty space at the bottom of every phone screen */
  body.admin{padding-bottom:calc(16px + var(--safe-b))}
  body.nav-open .nav-backdrop{display:block;position:fixed;top:0;right:0;bottom:0;left:0;z-index:55;background:rgba(11,42,74,.5)}
  .side-nav-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px}
  .side-nav-head b{color:#fff;font-size:.95rem}
  .nav-close{display:inline-flex}
  .sidebar .btn.ghost{border-color:rgba(255,255,255,.4);background:rgba(255,255,255,.12);color:#fff}
  /* 44 px touch targets and a visible rhythm for the long menu list */
  .sidenav{gap:4px}
  .sidenav a{display:flex;align-items:center;min-height:44px}
  .side-foot{margin-top:18px}
  .side-foot .btn{min-height:44px}
  .only-mobile{display:inline-flex}
  /* iOS: make a tap a tap, not the first half of a double-tap zoom */
  .sidenav a,.side-foot .btn,.nav-close,#adminNavBtn{touch-action:manipulation}
}
.kpi{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.kpi .k{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:14px}
.kpi .k b{display:block;font-size:1.5rem;color:var(--navy)}
.kpi .k span{font-size:.76rem;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.3px}
.tabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.tabs a{padding:8px 13px;border-radius:999px;background:#fff;border:1px solid var(--line);font-size:.84rem;font-weight:700}
.tabs a.on{background:var(--navy);color:#fff;border-color:var(--navy)}
.filters{display:grid;gap:10px;grid-template-columns:1fr;margin-bottom:14px}
@media(min-width:700px){.filters{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));align-items:end}}
.pager{display:flex;gap:6px;flex-wrap:wrap;margin-top:14px}
.pager a{padding:7px 12px;border:1px solid var(--line);border-radius:8px;background:#fff;font-size:.84rem}
.pager a.active{background:var(--navy);color:#fff}
.qr-box{background:#fff;padding:14px;border-radius:var(--r);border:1px solid var(--line);text-align:center}
.qr-box img{width:min(320px,100%);height:auto;object-fit:contain}
.copy-row{display:flex;gap:8px;align-items:center}
.copy-row input{font-family:ui-monospace,monospace}

/* product page */
.gallery{display:grid;gap:10px;grid-template-columns:1fr}
.gallery .main{aspect-ratio:1/1;border-radius:var(--r);overflow:hidden;background:#F1F0F5;border:1px solid var(--line)}
.gallery .main img{width:100%;height:100%;object-fit:cover}
.thumbs{display:flex;gap:8px;overflow-x:auto}
.thumbs button{width:64px;height:64px;padding:0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#fff}
.thumbs img{width:100%;height:100%;object-fit:cover}
.count{font-variant-numeric:tabular-nums;font-weight:700}
.sticky-buy{position:sticky;bottom:calc(66px + var(--safe-b));background:rgba(255,255,255,.96);border:1px solid var(--line);
  border-radius:var(--r);padding:12px;margin-top:14px;backdrop-filter:blur(10px)}
@media(min-width:900px){.sticky-buy{bottom:12px}}
.summary{display:grid;gap:6px;font-size:.92rem}
.summary div{display:flex;justify-content:space-between;gap:10px}
.summary .tot{border-top:1px solid var(--line);padding-top:8px;font-weight:800;font-size:1.05rem}
.line-item{display:grid;gap:10px;grid-template-columns:64px 1fr;padding:12px 0;border-bottom:1px solid var(--line)}
.line-item .th{width:64px;height:64px;border-radius:10px;overflow:hidden;background:#F1F0F5}
.line-item .th img{width:100%;height:100%;object-fit:cover}
/* payment method picker */
.pay-pick h2,.pay-section h2{font-size:1.05rem;margin:18px 0 10px}
.pay-options{display:grid;gap:12px}
@media(min-width:640px){.pay-options{grid-template-columns:1fr 1fr}}
.pay-opt{display:flex;gap:12px;align-items:flex-start;border:1px solid var(--line);border-radius:14px;
  padding:14px;background:#fff;cursor:pointer;min-height:64px}
.pay-opt:hover{border-color:var(--orange);background:#FFF9F0}
.pay-opt input{width:22px;height:22px;min-height:22px;margin-top:2px;flex:0 0 auto}
.pay-opt.sel{border-color:var(--orange);background:#FFF9F0;box-shadow:0 0 0 1px var(--orange) inset}
.pay-opt.off{opacity:.62;cursor:not-allowed;background:#FAFAFB}
.pay-opt.off:hover{border-color:var(--line);background:#FAFAFB}
.pay-opt.off input{cursor:not-allowed}
.pay-opt-body b{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pay-opt-body{display:flex;flex-direction:column;gap:3px}
.pay-opt-body small{color:var(--muted);font-size:.8rem;line-height:1.35}
.quote-state{color:var(--ok);font-weight:700}
.quote-state:empty{display:none}
/* Donation options: three EQUAL preset tiles + a full-width "Nominal lain" tile. Every tile is the same
 * height and the same width as its neighbours (the owner reported "some bigger button"), the radio uses the
 * brand colour, and the selected tile is clearly marked. */
.don-opt{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.don-opt label{position:relative;border:1.5px solid var(--line);background:#fff;border-radius:14px;
  padding:12px 10px;cursor:pointer;min-height:64px;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:3px;text-align:center;transition:border-color .15s,background .15s,box-shadow .15s}
.don-opt label b{font-size:1rem;font-weight:800;color:var(--ink);line-height:1.15}
.don-opt label small{font-size:.72rem;color:var(--muted);font-weight:500}
.don-opt label input[type=radio]{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.don-opt label::after{content:'';position:absolute;top:7px;right:7px;width:15px;height:15px;border-radius:50%;
  border:2px solid var(--line);background:#fff;transition:border-color .15s,background .15s}
.don-opt label:hover{border-color:#F7B25C}
.don-opt label.sel{border-color:var(--orange);background:#FFF6E7;box-shadow:0 2px 10px rgba(247,148,29,.16)}
.don-opt label.sel b{color:#8A4B00}
.don-opt label.sel::after{border-color:var(--orange);background:var(--orange);
  box-shadow:inset 0 0 0 2.5px #fff}
/* keyboard/accessibility: the radio itself is visually hidden inside the tile, so show focus on the tile */
.don-opt label:has(input:focus-visible){outline:2px solid var(--orange);outline-offset:2px}
.don-opt label[data-don="other"]{grid-column:1 / -1;flex-direction:row;justify-content:center;gap:10px;min-height:56px}
.don-opt label[data-don="other"] b{font-size:.95rem}
@media(max-width:360px){.don-opt{grid-template-columns:repeat(3,1fr);gap:8px}.don-opt label{padding:10px 6px}.don-opt label b{font-size:.92rem}}

/* Outbox: the full text body of one delivery attempt */
.outbox-body{white-space:pre-wrap;word-break:break-word;background:#FBFBFE;border:1px solid var(--line);
  border-radius:12px;padding:14px;font:13px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;max-height:60vh;overflow:auto}

/* Settings: every card that holds settings gets its own save bar, so configuring SMTP / WhatsApp does
 * not require scrolling to the bottom of a very long page to find the only "Simpan" button. */
.save-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px dashed var(--line)}
.save-bar .hint{margin:0;flex:1 1 240px;min-width:0}
.save-bar .btn{min-height:44px}

/* Profil: read-only account summary + one obvious Edit button */
.profile-head{display:flex;align-items:center;gap:14px}
.profile-avatar{width:56px;height:56px;flex:0 0 56px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,var(--orange-2,#F7941D),#D97B06);color:#231400;font-size:24px;font-weight:800}
.profile-name{font-size:1.1rem}
.profile-head>div{min-width:0}
.profile-head .muted{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* My Donations: older supported events (expandable list) */
.don-more>summary{cursor:pointer;padding:12px 14px;border:1px dashed var(--line);border-radius:12px;background:#FFFDF7;list-style:none;min-height:44px;display:flex;align-items:center}
.don-more>summary::-webkit-details-marker{display:none}
.don-more>summary::before{content:'▸';margin-right:8px;color:var(--orange);font-weight:700}
.don-more[open]>summary::before{content:'▾'}
.don-ev-list{display:grid;gap:10px}
.don-ev-row{display:grid;grid-template-columns:64px 1fr 18px;gap:12px;align-items:center;
  border:1px solid var(--line);border-radius:12px;background:#fff;padding:10px;text-decoration:none;color:inherit;min-height:64px}
.don-ev-row:hover,.don-ev-row:focus{border-color:var(--orange)}
.don-ev-thumb{width:64px;height:40px;border-radius:8px;object-fit:cover;background:#F2EEFF;display:block}
.don-ev-empty{display:flex;align-items:center;justify-content:center;font-size:18px}
.don-ev-main{display:flex;flex-direction:column;gap:2px;min-width:0}
.don-ev-main b{font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.don-ev-go{color:var(--muted);font-size:22px;line-height:1;text-align:right}

/* print (A4 monochrome, toner-saving) */
@media print{
  body{background:#fff;padding:0}
  .topbar,.botnav,.foot,.sidebar,.admin-top,.noprint,.blob{display:none !important}
  .wrap,.admin-main{padding:0;max-width:none}
  .card{box-shadow:none;border:1px solid #000;border-radius:0}
  @page{size:A4 portrait;margin:10mm}
}
.print-sheet{background:#fff;color:#000;font:11px/1.35 Arial,Helvetica,sans-serif;max-width:210mm;margin:0 auto;padding:8mm}
.print-sheet h1{font-size:15px;margin:0}
.print-sheet h2{font-size:12px;margin:0 0 6px}
.print-sheet .phead{display:flex;justify-content:space-between;gap:10px;border-bottom:1.5px solid #000;padding-bottom:6px;margin-bottom:8px}
.print-sheet .gridline{display:grid;grid-template-columns:repeat(4,1fr);gap:4px 10px;font-size:10px;margin-bottom:8px}
.print-sheet table{width:100%;border-collapse:collapse;font-size:9.3px}
.print-sheet th,.print-sheet td{border:1px solid #000;padding:3px 4px;vertical-align:top}
.print-sheet th{background:#fff;font-weight:700;text-align:left}
.print-sheet .cut{border-top:1px dashed #000;margin:8px 0;text-align:center;font-size:9px}
.print-sheet .half{min-height:138mm}
/* PACKING SLIP + DELIVERY LABEL: must fit ONE A4 sheet (owner: "compact packing slip only 1 page tall").
 * The old sheet was 311.9mm tall against 277mm of usable A4 (297mm − 2×10mm @page margin) because each
 * half reserved `min-height:138mm` AND the slip printed 20 numbered rows (19 of them empty) — so it always
 * spilled onto a second page. Here the halves are content-sized, the slip lists only the items actually in
 * the box, and `break-inside:avoid` keeps each block whole if a very large package ever does need a
 * second sheet. */
.print-sheet.pack .half{min-height:0}
.print-sheet.pack section{break-inside:avoid;page-break-inside:avoid}
.print-sheet.pack .phead{padding-bottom:4px;margin-bottom:6px}
.print-sheet.pack table{font-size:8.8px}
.print-sheet.pack table th,.print-sheet.pack table td{padding:2px 3px}
.print-sheet.pack .box{padding:4px 5px;font-size:9.5px}
.print-sheet.pack .gridline{font-size:9.5px;margin-bottom:6px}
/* delivery label: the address is read at arm's length, and `block` keeps the CAPITAL address lines
   from being joined into one long run by the inline layout */
.print-sheet .label .lbl-addr{font-size:11px;line-height:1.42}
.print-sheet .label .lbl-addr>div{display:block}
.print-sheet .label .lbl-to{font:700 13.5px Arial;margin-bottom:3px}
.print-sheet .label .lbl-content{margin-top:6px;border-width:2px;text-align:center;font-size:12px;letter-spacing:.4px}
.print-sheet .label .lbl-courier{margin-top:6px;font-size:11px}
.print-sheet .label .blank{display:inline-block;min-width:46mm;border-bottom:0}
/* street line + the courier note side by side: the instruction is read together with the address it
   applies to, and is vertically centred against that line.
   NOTE the selector depth: `.print-sheet .label .lbl-addr>div{display:block}` above has the same number of
   classes PLUS an element, so a 3-class selector loses to it and the row silently became plain inline
   text (the two spans happened to sit next to each other by accident, which would break as soon as the
   street line wrapped). Naming `.lbl-addr` in the selector wins the cascade on class count (4 > 3). */
.print-sheet .label .lbl-addr .lbl-l1{display:flex;align-items:center;gap:8px}
.print-sheet .label .lbl-l1-addr{flex:1 1 auto;min-width:0}
.print-sheet .label .lbl-l1-note{flex:0 0 auto;max-width:46%;text-align:center;font:700 10px Arial;
  border:1.5px solid #000;padding:2px 5px;letter-spacing:.2px;white-space:normal;line-height:1.25}
.print-sheet .label .lbl-rev{margin-top:3px;font-size:8.5px}
.print-sheet .label .lbl-foot{margin-top:6px;font-size:8.5px}
.print-sheet .footnote{font-size:9px;margin-top:6px}
.bc{display:block;height:auto}
.print-logo{height:34px;width:auto;object-fit:contain}
.print-sheet .box{border:1px solid #000;padding:5px;font-size:10px}
/* Work order line details: one label:value line per parameter, and the customer's remark made
 * unmistakable (bold, rule on the left, line breaks preserved). The density is deliberately tight so a
 * normal order keeps the one-A4-sheet promise; an order where many of the 20 lines carry a multi-line
 * remark is a physical-limit case (A4 cannot hold it) and is allowed to flow to a second sheet — rows
 * never split across pages, and the footnote says so. */
.print-sheet .wo-table table,table.wo-table{border-collapse:collapse}
.print-sheet table.wo-table{font-size:8.9px}
.print-sheet table.wo-table th,.print-sheet table.wo-table td{padding:2px 3px}
.print-sheet table.wo-table tr{page-break-inside:avoid;break-inside:avoid}
.print-sheet .p-ln{line-height:1.2;font-size:8.7px}
.print-sheet .p-ln b{font-weight:700}
.print-sheet .remark{font-weight:700;border-left:2px solid #000;padding-left:4px;white-space:pre-wrap;word-break:break-word;font-size:8.9px}
.print-sheet .prod-note{font-size:8.7px}
.print-sheet .muted{color:#000}
.print-sheet td.qty{text-align:center;font-weight:700}
.print-sheet td.chkbox{width:6%}
/* the WhatsApp message preview on the work order page (plain text, wrapped, monospace-ish) */
.wo-msg{white-space:pre-wrap;word-break:break-word;background:#F6F5FA;border:1px solid var(--line);
  border-radius:10px;padding:12px;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;margin:8px 0 0;max-height:280px;overflow:auto}
.btn.busy{opacity:.6;pointer-events:none}
.writing{height:26mm;border:1px solid #000}
@media screen{.print-sheet{border:1px solid var(--line);box-shadow:var(--shadow);border-radius:8px;margin:14px auto}}
/* work order actions in the production table (print / PDF / WhatsApp) */
.wo-actions{display:inline-flex;gap:6px;flex-wrap:wrap;align-items:center}
.wa-more{position:relative;display:inline-block}
.wa-more summary{cursor:pointer;padding:6px 8px;border:1px dashed var(--line);border-radius:999px;list-style:none}
.wa-more summary::-webkit-details-marker{display:none}
.wa-more[open] summary{border-style:solid}
.wa-more a{display:block;padding:6px 8px;white-space:nowrap}
/* Screen preview of an A4 sheet: the document keeps its true A4 width, but the PAGE must not scroll
 * sideways on a phone — the sheet scrolls inside this wrapper instead. Print output is untouched. */
.sheet-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}
@media print{.sheet-scroll{overflow:visible}}
/* banner shown while the back office acts as a customer (create an order on their behalf) */
.impersona{position:sticky;top:0;z-index:50;background:linear-gradient(135deg,#FFF6E7,#FFE9C7);
  border-bottom:1px solid rgba(217,123,6,.45)}
.impersona-in{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap;padding:9px 16px}
.impersona-txt{font-size:.84rem;color:var(--ink);max-width:70ch}
@media print{.impersona{display:none}}
