/* =====================================================================
   The sale: the red banner, the badges, the sticky buy bar.

   Every rule here is driven by assets/promo.js, which draws nothing at
   all unless catalog.json carries a `promo` block that has not expired.
   Red appears nowhere else on this site - not on one product page, not
   on the store - which is the whole point of using it here.
   ===================================================================== */

:root{
  --sale-red:#E11D2E;
  --sale-red-dark:#A70E1C;
  --sale-ink:#FFFFFF;
}

/* ---------- the strip across the top of a product page ---------- */
.sale-strip{
  background:linear-gradient(90deg,var(--sale-red-dark),var(--sale-red) 42%,var(--sale-red) 58%,var(--sale-red-dark));
  color:var(--sale-ink); position:relative; z-index:60;
  display:flex; align-items:center; justify-content:center; gap:10px 16px; flex-wrap:wrap;
  padding:9px 16px; text-align:center;
  font:600 13.5px/1.45 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  letter-spacing:.01em;
}
.sale-strip .pc{font-weight:800; letter-spacing:.1em; text-transform:uppercase; font-size:12px;
  background:rgba(0,0,0,.24); padding:3px 9px; border-radius:999px}
.sale-strip s{opacity:.75}
.sale-strip .clock{font-variant-numeric:tabular-nums; opacity:.95}
.sale-strip a{color:inherit; text-decoration:underline; text-underline-offset:3px}
@media (max-width:600px){ .sale-strip{font-size:12.5px; padding:8px 12px; gap:6px 10px} }

/* ---------- the line that sits over the shelf ---------- */
/* It used to be a slab across the top of the page. The red now lives
   where the buying happens - on the price of each card - and this is
   one line above them saying why they are low. */
.sale-banner{
  display:flex; align-items:center; gap:12px 16px; flex-wrap:wrap;
  margin:0 0 6px; padding:12px 18px; border-radius:12px;
  background:linear-gradient(90deg,#B3111F,var(--sale-red) 58%,#FF3D4A);
  color:var(--sale-ink); box-shadow:0 12px 34px -22px rgba(225,29,46,.95);
  font:500 14px/1.45 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
}
.sale-banner .tag{flex:none; background:rgba(0,0,0,.26); border-radius:999px;
  padding:4px 11px; font-weight:800; font-size:11.5px; letter-spacing:.1em;
  text-transform:uppercase}
.sale-banner .sub{margin:0; flex:1 1 260px}
.sale-banner .ends{margin:0 0 0 auto; flex:none; display:flex; align-items:baseline; gap:8px}
.sale-banner .ends .lab{font-size:11px; letter-spacing:.12em; text-transform:uppercase; opacity:.78}
.sale-banner .ends .clock{font-weight:700; font-variant-numeric:tabular-nums; letter-spacing:.01em}
@media (max-width:640px){
  .sale-banner{padding:12px 14px; font-size:13.5px}
  .sale-banner .ends{margin-left:0; width:100%}
}

/* ---------- the line under a buy button ---------- */
.promo-line{margin:12px 0 0; font-size:14px; line-height:1.65}
.promo-line[hidden]{display:none}
.promo-tag{display:inline-block; margin-right:10px; padding:3px 10px; vertical-align:1px;
  background:var(--sale-red); color:#fff; border-radius:999px;
  font:800 11px/1.35 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  letter-spacing:.1em; text-transform:uppercase;
  box-shadow:0 2px 10px -2px rgba(225,29,46,.8)}
.promo-line s{opacity:.68; text-decoration-thickness:1px}
.promo-line .save{color:var(--sale-red); font-weight:700}
.promo-line .clock{display:inline-block; margin-left:7px; font-variant-numeric:tabular-nums;
  white-space:nowrap; opacity:.85}
.promo-line .clock[hidden]{display:none}

/* The store's own price row is styled in apps.html, next to the rest of
   the shelf. The red pill on it is the only red the store needs - there
   was a flag over the picture as well, and two of them was one too many. */

/* ---------- what you actually get, under the buy button ---------- */
.assure{list-style:none; display:grid; gap:9px 26px; grid-template-columns:repeat(auto-fit,minmax(272px,1fr));
  margin:18px 0 0; padding:0; max-width:78ch;
  font:500 13px/1.5 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif; opacity:.82}
.assure li{display:flex; align-items:flex-start; gap:7px}
.assure svg{flex:none; width:15px; height:15px; margin-top:1px}
.assure a{color:inherit; text-underline-offset:2px}

/* ---------- the bar that follows you down the page ---------- */
.sale-dock{
  position:fixed; left:0; right:0; bottom:0; z-index:80;
  display:flex; align-items:center; gap:14px; flex-wrap:nowrap;
  padding:11px max(14px,env(safe-area-inset-left)) calc(11px + env(safe-area-inset-bottom)) max(14px,env(safe-area-inset-right));
  background:rgba(9,10,14,.86); backdrop-filter:blur(14px) saturate(1.3);
  border-top:1px solid rgba(255,255,255,.14); color:#F4F4F6;
  font:500 14px/1.3 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  transform:translateY(110%); transition:transform .26s cubic-bezier(.22,.8,.3,1);
}
.sale-dock.up{transform:none}
.sale-dock .who{font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.sale-dock .cost{margin-left:auto; display:flex; align-items:baseline; gap:8px; white-space:nowrap}
.sale-dock .cost b{font-size:17px}
.sale-dock .cost .pwyw{font-weight:700}
.sale-dock .cost s{opacity:.55}
.sale-dock .flag{background:var(--sale-red); color:#fff; border-radius:6px; padding:3px 7px;
  font:800 10.5px/1 system-ui,sans-serif; letter-spacing:.06em}
.sale-dock button{
  flex:none; border:0; border-radius:10px; padding:11px 20px; cursor:pointer;
  background:#fff; color:#0B0C10;
  font:700 14.5px/1 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
}
.sale-dock button:disabled{opacity:.5; cursor:default}
@media (max-width:560px){
  .sale-dock{gap:10px; padding-left:12px; padding-right:12px; font-size:13px}
  .sale-dock .who{display:none}
  .sale-dock .cost{margin-left:0}
  .sale-dock button{padding:11px 16px}
}
@media (prefers-reduced-motion:reduce){ .sale-dock{transition:none} }

/* ---------------------------------------------------------------------
   The other way to pay.

   Under the buy button, and only ever the one the main button is not:
   somebody in Accra is offered the card, somebody in London is offered
   mobile money. Quiet on purpose - it is an alternative, not a second
   call to action competing with the first.
   --------------------------------------------------------------------- */
.pay-alt-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin:14px 0 0}
.pay-alt{appearance:none;cursor:pointer;font:inherit;font-size:14px;font-weight:600;
  color:var(--ink,#EDEAF6);background:transparent;border:1px solid currentColor;
  border-radius:999px;padding:9px 18px;opacity:.72;
  transition:opacity .18s ease,transform .18s ease}
.pay-alt:hover{opacity:1;transform:translateY(-1px)}
.pay-alt:focus-visible{outline:2px solid currentColor;outline-offset:3px;opacity:1}
.pay-alt-note{font-size:13px;color:var(--muted,#A9A2C8)}
@media (max-width:520px){
  .pay-alt-row{flex-direction:column;align-items:flex-start;gap:6px}
  .pay-alt{width:100%;text-align:center}
}

/* Naming your price on Paystack, which needs the figure before the
   redirect rather than on the checkout page. */
.pwyw{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.pwyw label{font-size:14px}
.pwyw-in{display:inline-flex;align-items:center;gap:6px;border:1px solid currentColor;
  border-radius:999px;padding:6px 14px;opacity:.8}
.pwyw-in i{font-style:normal;font-size:13px;opacity:.75}
.pwyw-in input{width:6.5ch;font:inherit;font-size:15px;font-weight:600;color:inherit;
  background:transparent;border:0;padding:0}
.pwyw-in input:focus{outline:none}
.pwyw-in:focus-within{opacity:1}
.pwyw small{flex-basis:100%;font-size:12.5px;opacity:.7}
.pay-alt-fx{flex-basis:100%;font-size:13px;color:var(--muted,#A9A2C8)}

/* ---------------------------------------------------------------------
   What it runs on, next to the price.

   Drawn by assets/platforms.js from the app's own installers, so it can
   never disagree with what the download actually hands over.
   --------------------------------------------------------------------- */
.plat-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:14px 0 0}
.plat-lead{font-family:var(--mono,ui-monospace,monospace);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted,#A9A2C8);margin-right:2px}
/* color:inherit, not var(--ink). These pills go on twelve pages that do
   not agree about what --ink means: most leave it undefined, and aether
   sets it to #1B2733 - a DARK ink, for a light element on that page -
   which rendered near-black pills on a near-black background. The
   colour of the text they sit beside is the one thing every page
   already has right, so take that. */
.plat{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:500;
  color:inherit;background:color-mix(in srgb,currentColor 9%,transparent);
  border:1px solid color-mix(in srgb,currentColor 22%,transparent);
  border-radius:999px;padding:5px 12px 5px 10px;white-space:nowrap}
.plat svg{width:15px;height:15px;flex:none;opacity:.75}
@media (max-width:520px){
  .plat-row{gap:6px}
  .plat{font-size:12.5px;padding:4px 10px 4px 8px}
  .plat svg{width:14px;height:14px}
}

/* The same fact on a store tile, small enough to sit under the price. */
.app-plats{display:flex;flex-wrap:wrap;justify-content:center;gap:5px;margin:8px 0 0}
.app-plat{font-family:var(--mono,ui-monospace,monospace);font-size:9.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted,#8C85AC);border:1px solid currentColor;
  border-radius:999px;padding:2px 7px;opacity:.8;white-space:nowrap}

/* ---------------------------------------------------------------------
   A discount code, under the buy button.

   Closed by default: most people do not have one, and a box asking for
   a code you do not have is a small accusation that you are paying too
   much. It opens when somebody says they have one.
   --------------------------------------------------------------------- */
.code-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin:12px 0 0;font-size:13.5px}
.code-open{appearance:none;cursor:pointer;font:inherit;font-size:13.5px;color:inherit;
  background:transparent;border:0;padding:0;opacity:.72;text-decoration:underline;
  text-underline-offset:3px}
.code-open:hover{opacity:1}
.code-form{display:inline-flex;align-items:center;gap:8px}
.code-in{font-family:var(--mono,ui-monospace,monospace);font-size:13.5px;letter-spacing:.08em;
  text-transform:uppercase;color:inherit;background:color-mix(in srgb,currentColor 7%,transparent);
  border:1px solid color-mix(in srgb,currentColor 26%,transparent);
  border-radius:999px;padding:8px 14px;width:21ch;max-width:100%}
.code-in:focus{outline:none;border-color:currentColor}
.code-go{appearance:none;cursor:pointer;font:inherit;font-size:13.5px;font-weight:600;color:inherit;
  background:transparent;border:1px solid currentColor;border-radius:999px;padding:8px 16px;opacity:.8}
.code-go:hover{opacity:1}
.code-say{font-size:13px;opacity:.8}
.code-say.bad{color:var(--alert,#FF7A8A);opacity:1}
.code-say.on b{font-family:var(--mono,ui-monospace,monospace);font-size:12.5px;letter-spacing:.06em}
@media (max-width:520px){
  .code-row{gap:8px}
  .code-form{width:100%}
  .code-in{flex:1 1 auto;width:auto}
}

/* ---------------------------------------------------------------
   Mobile money over WhatsApp.

   A link, deliberately shaped like one. The buttons beside it start a
   checkout; this one opens a chat, and dressing it up as a third
   payment button would promise a card form that never arrives.

   currentColor throughout, for the same reason the platform pills use
   it: these pages do not agree on what --ink is, and AETHER's is dark
   enough to render a hardcoded colour near-invisible.
   --------------------------------------------------------------- */
.pay-wa{
  display:inline-flex; align-items:center; gap:7px;
  margin-top:6px; padding:7px 13px;
  border:1px solid currentColor; border-radius:999px;
  font:inherit; font-size:14px; font-weight:600; line-height:1;
  color:inherit; text-decoration:none; opacity:.82;
  transition:opacity .15s ease, transform .15s ease;
}
.pay-wa:hover,
.pay-wa:focus-visible{ opacity:1; transform:translateY(-1px); }
.pay-wa svg{ flex:0 0 auto; }

/* The Stripe session reference, shown only when a purchase could not be
   confirmed any other way. Selectable and monospaced because its whole
   job is to be copied into an email. */
.ref{display:inline-block;margin-top:6px;font-family:var(--mono,ui-monospace,Menlo,Consolas,monospace);
  font-size:12px;word-break:break-all;-webkit-user-select:all;user-select:all;opacity:.85}
