/* Mtepe stylesheet — one hand-written file (PLAN D4, DESIGN_SPEC §3).
   Two skins, one component set: the admin wears Mtepe's teal, the storefront
   wears the seller's accent. The tokens live in tokens.css, which every
   layout loads first; nothing here redefines them.

   Contrast is resolved in Go, on save (internal/settings/colour.go), not
   guessed here: --store-accent-ink is already the readable one of white or
   dark ink by the time it reaches this file. That is what makes "any accent
   colour" safe rather than a hope.

   Size: DESIGN_SPEC §3 asks for under 15 KB and this is about 48 KB, of
   which roughly 42 KB is rules. It misses that target and is flagged rather
   than met by deleting rules the screens need. The budget a buyer actually
   feels is §12's — under 60 KB transferred on a product page — and at about
   11 KB gzipped, served once and then cached, this is well inside it. If the
   15 KB figure is meant literally, the way to reach it is fewer components,
   not tighter ones; that is a design decision, not a formatting one. */

/* Base ------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  color: var(--text);
  background: var(--bg);
  font: var(--fs-md)/var(--lh-body) var(--font);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; }

h1, h2, h3 { line-height: var(--lh-tight); letter-spacing: -0.01em; }
h1 { font-size: var(--fs-3xl); font-weight: 650; margin: 0 0 var(--sp-3); color: var(--ink); }
h2 { font-size: var(--fs-lg); font-weight: 650; margin: 0 0 var(--sp-2); color: var(--ink); }
h3 { font-size: var(--fs-md); font-weight: 650; margin: 0 0 var(--sp-2); }

/* Numbers that change in place must not shift while somebody reads them. */
.money, .receipt, .countdown { font-variant-numeric: tabular-nums; }

/* A masked number must never break across two lines (DESIGN_SPEC §5.13). */
.phone, .phone--masked { white-space: nowrap; font-variant-numeric: tabular-nums; }

.muted { color: var(--text-muted); }
.hint, .field__help {
  margin: var(--sp-1) 0 0; font-size: 13px;
  color: var(--text-muted); line-height: 1.45;
}
/* The only spacing utilities. The content security policy has no
   'unsafe-inline', so a style attribute on an element is silently dropped —
   these exist so a template never reaches for one. */
.gap-top { margin-top: var(--sp-4); }
.gap-top-sm { margin-top: var(--sp-3); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Links and buttons -------------------------------------------------------
   .link is the only rule carrying text-decoration, and a.btn resets it, so
   link styling can never leak into a button (DESIGN_SPEC §5.3). */

a { color: var(--brand); }
a:hover { color: var(--brand-hi); }

.link {
  font: inherit; padding: 0; border: 0; background: none;
  color: var(--brand); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.link:hover { color: var(--brand-hi); }
.link--danger { color: var(--danger); }
.link--quiet { color: var(--text-muted); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  font: inherit; font-size: var(--fs-md); font-weight: 600;
  padding: var(--sp-3) 18px; min-height: var(--tap);
  border: 1px solid transparent; border-radius: var(--r-md);
  cursor: pointer; text-align: center;
}
a.btn { text-decoration: none; }
.btn--primary { color: #fff; background: var(--brand); border-color: var(--brand); }
.btn--primary:hover { background: var(--brand-hi); border-color: var(--brand-hi); color: #fff; }
.btn--primary:active { background: var(--brand-lo); border-color: var(--brand-lo); transform: translateY(1px); }
.btn--secondary { color: var(--brand); background: var(--surface); border-color: var(--line-strong); }
.btn--secondary:hover { background: var(--bg); color: var(--brand-hi); }
.btn--danger { color: var(--danger); background: var(--surface); border-color: var(--danger-line); }
.btn--danger:hover { background: var(--danger-wash); color: var(--danger); }
.btn--block { width: 100%; }
.btn--big { font-size: var(--fs-lg); min-height: 52px; }
.btn[disabled], .btn[aria-disabled="true"] {
  color: #8b9491; background: var(--surface-sunk); border-color: var(--line);
  cursor: not-allowed;
}
.btn--loading, .btn[aria-busy="true"] { cursor: wait; }
.btn--loading::before, .btn[aria-busy="true"]::before {
  content: ""; width: 14px; height: 14px; border-radius: var(--r-pill);
  border: 2px solid rgb(255 255 255 / 40%); border-top-color: currentColor;
}
@media (prefers-reduced-motion: no-preference) {
  .btn--loading::before, .btn[aria-busy="true"]::before { animation: spin .9s linear infinite; }
}
@keyframes spin { to { transform: rotate(360deg); } }

/* The storefront's own button wears the seller's colour; its ink was already
   chosen for contrast in Go. */
.btn--store { color: var(--store-accent-ink); background: var(--store-accent); border-color: var(--store-accent); }
.btn--store:hover { color: var(--store-accent-ink); filter: brightness(1.08); }

:where(a, button, input, select, textarea, summary, label.option, label.agent, label.swatch):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* Fields ------------------------------------------------------------------ */

.field { display: block; margin: 0 0 var(--sp-4); }
.field > label, .field__label {
  display: block; font-size: var(--fs-sm); font-weight: 600;
  color: var(--text-soft); padding-bottom: var(--sp-1);
}

/* 16px is the floor for anything typed into, so iOS never zooms on focus. */
.input, textarea, select,
input[type="text"], input[type="email"], input[type="password"],
input[type="tel"], input[type="search"], input[type="number"] {
  font: inherit; font-size: var(--fs-md); color: var(--text);
  width: 100%; padding: 11px var(--sp-3); min-height: var(--tap);
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
}
textarea { min-height: 8rem; line-height: var(--lh-body); }

/* The money prefix lives inside the bordered group, never outside it
   (DESIGN_SPEC §5.4). */
.input-group {
  display: flex; align-items: stretch; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--r-md); overflow: hidden;
}
.input-group__prefix, .input-group__suffix {
  display: flex; align-items: center; padding: 0 var(--sp-3);
  font-size: 13px; font-weight: 600; color: var(--text-muted);
  background: var(--bg); white-space: nowrap;
}
.input-group__prefix { border-right: 1px solid var(--line); }
.input-group__suffix { font-weight: 400; border-left: 1px solid var(--line); }
.input-group input { border: 0; border-radius: 0; background: transparent; }
.input-group:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px rgb(15 76 70 / 12%); }
.input-group input:focus-visible { outline: none; }

.field--error > label, .field--error .field__label { color: var(--danger); }
.field--error .input, .field--error input, .field--error select, .field--error textarea,
[aria-invalid="true"] { border-color: var(--danger); border-width: 1.5px; }
.field--error .input-group { border-color: var(--danger); border-width: 1.5px; }
.field--error .input-group__prefix { background: var(--danger-wash); }
.field__error { margin: var(--sp-1) 0 0; font-size: 13px; font-weight: 600; color: var(--danger); }

.switch { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--tap); }
.switch > span { font-size: var(--fs-md); }
.check { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--tap); }
.switch input, .check input { width: auto; min-height: 0; margin: 0; }

/* A toggle a thumb can hit, rather than a 13px browser checkbox. Built from
   the checkbox itself, so it stays a real form control: it posts, it takes
   focus, and it works from the keyboard exactly as before. */
.switch input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  flex: none; width: 52px; height: 30px; padding: 3px;
  background: #d9d2c6; border: 0; border-radius: var(--r-pill);
  cursor: pointer;
}
.switch input[type="checkbox"]::after {
  content: ""; display: block; width: 24px; height: 24px;
  background: #fff; border-radius: var(--r-pill);
  box-shadow: 0 1px 2px rgb(14 42 42 / 25%);
}
.switch input[type="checkbox"]:checked { background: var(--brand); }
.switch input[type="checkbox"]:checked::after { margin-left: 22px; }
@media (prefers-reduced-motion: no-preference) {
  .switch input[type="checkbox"]::after { transition: margin-left .12s ease; }
}

.fields-2 { display: grid; gap: var(--sp-4); grid-template-columns: 1fr; }
@media (min-width: 480px) { .fields-2 { grid-template-columns: 1fr 1fr; } }
.fields-2 .field { margin: 0; }

/* Badges — colour is never the only signal; each carries its word.
   Sold out, Draft, Expired and Cancelled share the neutral wash, so a red
   badge in the admin always means "money needs you". */

.badge {
  display: inline-block; font-size: var(--fs-xs); font-weight: 650;
  padding: 5px 9px; border-radius: var(--r-sm); white-space: nowrap;
  border: 1px solid var(--neutral-line); background: var(--neutral-wash); color: var(--neutral);
}
.badge--ok { background: var(--ok-wash); color: var(--ok-ink); border-color: var(--ok-line); }
.badge--warn { background: var(--warn-wash); color: var(--warn-ink); border-color: var(--warn-line); }
.badge--danger { background: var(--danger-wash); color: var(--danger-ink); border-color: var(--danger-line); }
.badge--info { background: var(--info-wash); color: var(--info-ink); border-color: var(--info-line); }
.badge--neutral { background: var(--neutral-wash); color: var(--neutral); border-color: var(--neutral-line); }
.badge--big { font-size: var(--fs-sm); padding: 6px 11px; }

/* The count beside a tab. badge-loud is the red one on Needs attention. */
.count {
  display: inline-block; min-width: 1.5em; padding: 1px 6px; margin-left: var(--sp-1);
  border-radius: var(--r-pill); background: var(--neutral-wash); color: var(--neutral);
  font-size: var(--fs-xs); font-weight: 650; text-align: center;
  font-variant-numeric: tabular-nums;
}
.badge-loud, .count--loud { background: var(--danger-wash); color: var(--danger-ink); }

.tag {
  display: inline-block; margin-left: var(--sp-2); padding: 2px 7px;
  border-radius: var(--r-pill); background: var(--neutral-wash); color: var(--neutral);
  font-size: 11px; font-weight: 650; white-space: nowrap;
}
.tag--set { background: var(--ok-wash); color: var(--ok-ink); font-variant-numeric: tabular-nums; }
.tag--unset { background: var(--warn-wash); color: var(--warn-ink); }

/* Cards, banners, empty states ------------------------------------------- */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--sp-5);
}
.card + .card, form.card { margin-top: var(--sp-4); }
.card--narrow { max-width: var(--measure); margin: var(--sp-7) auto; }
.card--attention { border-color: var(--danger-line); background: var(--danger-wash); }
.card__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-3); margin-bottom: var(--sp-2);
}
.card__head h2 { margin: 0; }

.banner, .alert, .note {
  display: grid; gap: var(--sp-2); margin: 0 0 var(--sp-4);
  padding: var(--sp-4); border-radius: var(--r-md);
  border: 1px solid var(--info-line); background: var(--info-wash); color: var(--info-ink);
  font-size: var(--fs-sm);
}
.banner h2 { font-size: var(--fs-md); margin: 0; color: inherit; }
.banner p, .alert p, .note p { margin: 0; line-height: var(--lh-body); }
.banner--ok, .note { border-color: var(--ok-line); background: var(--ok-wash); color: var(--ok-ink); }
.banner--warn { border-color: var(--warn-line); background: var(--warn-wash); color: var(--warn-ink); }
.banner--attention, .alert { border-color: var(--danger-line); background: var(--danger-wash); color: var(--danger-ink); }
.banner__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-1); }

/* An empty state guides the next action rather than stating a fact. */
.empty {
  display: grid; gap: var(--sp-2); justify-items: start;
  padding: var(--sp-6) var(--sp-5); margin: var(--sp-4) 0;
  background: var(--surface); border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
}
.empty h2 { font-size: var(--fs-lg); margin: 0; }
.empty p { margin: 0; color: var(--text-muted); font-size: var(--fs-sm); max-width: 44ch; }
.empty .btn { margin-top: var(--sp-2); }

/* Admin shell ------------------------------------------------------------- */

.topbar {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--ink); color: #fff;
}
.topbar__brand {
  font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.02em;
  color: #fff; text-decoration: none;
}
.topbar__store { font-size: var(--fs-sm); color: #b9c8c4; margin-left: auto; overflow-wrap: anywhere; }
.topbar__nav { display: none; }
.topbar__nav a {
  color: #d8e6e2; text-decoration: none; font-size: var(--fs-sm); font-weight: 600;
  padding: var(--sp-2) 0; border-bottom: 2px solid transparent;
}
.topbar__nav a:hover { color: #fff; }
.topbar__nav a.is-active { color: #fff; border-bottom-color: var(--accent); }
/* On a phone the bar carries the wordmark and whose shop this is, and
   nothing else. Who is signed in and the way out are one tap away under
   More, and both of them here left "Sign out" wrapping onto two lines. */
.topbar__who, .topbar__out { display: none; }
.topbar__out {
  font: inherit; font-size: 13px; font-weight: 600;
  padding: var(--sp-2) var(--sp-3); min-height: 34px;
  color: #d8e6e2; background: transparent;
  border: 1px solid #35514d; border-radius: var(--r-sm);
  cursor: pointer; white-space: nowrap;
}
.topbar__out:hover { color: #fff; border-color: #6d8582; }

@media (min-width: 768px) {
  .topbar { padding: var(--sp-3) var(--sp-5); gap: var(--sp-5); }
  .topbar__nav { display: flex; align-items: center; gap: var(--sp-5); }
  .topbar__store { display: none; }
  .topbar__who { display: inline; font-size: 13px; color: #9fb2ae; }
  .topbar__out { display: inline-flex; align-items: center; }
}

/* The four things a seller does all day, under her thumb. Phones only. */
.tabbar {
  position: fixed; inset: auto 0 0 0; z-index: 20;
  display: grid; grid-template-columns: repeat(4, 1fr);
  background: var(--surface); box-shadow: var(--shadow-sticky);
  padding-bottom: env(safe-area-inset-bottom);
}
.tabbar a {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-height: var(--tap); padding: var(--sp-2) var(--sp-1);
  font-size: 11px; font-weight: 600; color: var(--text-muted); text-decoration: none;
}
.tabbar a.is-active, .tabbar a.is-active .icon { color: var(--brand); }
.tabbar__count {
  position: absolute; top: 2px; left: 50%; margin-left: 4px;
  min-width: 17px; padding: 0 4px; border-radius: var(--r-pill);
  background: var(--danger); color: #fff;
  font-size: 10px; line-height: 16px; text-align: center;
  font-variant-numeric: tabular-nums;
}
@media (min-width: 768px) { .tabbar { display: none; } }

.icon { display: block; width: 22px; height: 22px; color: currentColor; }

.wrap { max-width: 68rem; margin: 0 auto; padding: var(--sp-5) var(--sp-4) 96px; }
@media (min-width: 768px) { .wrap { padding: var(--sp-6) var(--sp-5) var(--sp-7); } }
.wrap--narrow { max-width: var(--measure); }

.page-head {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  align-items: center; justify-content: space-between;
  margin-bottom: var(--sp-4);
}
.page-head h1 { margin: 0; }
.page-head__links { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center; }
.crumb { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); }
.crumb a { text-decoration: none; font-weight: 600; }
.crumb a:hover { text-decoration: underline; }

.stack { display: grid; gap: var(--sp-4); }
.two-up { display: grid; gap: var(--sp-4); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 768px) { .two-up { grid-template-columns: 1fr 1fr; } }

/* Sticky save, clear of the tab bar. */
.sticky-actions {
  position: sticky; bottom: 0; z-index: 10;
  display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center;
  margin: var(--sp-5) calc(var(--sp-4) * -1) 0;
  padding: var(--sp-3) var(--sp-4);
  padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom));
  background: var(--bg); box-shadow: var(--shadow-sticky);
}
@media (max-width: 767px) { .sticky-actions { bottom: 58px; } }

/* Tabs -------------------------------------------------------------------- */

.tabs {
  display: flex; gap: var(--sp-1); overflow-x: auto;
  margin: 0 0 var(--sp-4); border-bottom: 1px solid var(--line);
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  flex: none; padding: var(--sp-3);
  color: var(--text-muted); text-decoration: none;
  font-size: var(--fs-sm); font-weight: 600;
  white-space: nowrap; border-bottom: 2px solid transparent;
}
.tab:hover { color: var(--text); }
.tab-on, .tab.is-active { color: var(--ink); border-bottom-color: var(--accent); }

.toolbar { margin-bottom: var(--sp-3); }

/* Dashboard --------------------------------------------------------------- */

.greeting { margin: 0 0 var(--sp-5); }
.greeting h1 { margin: 0 0 2px; }
.greeting p { margin: 0; color: var(--text-muted); font-size: var(--fs-sm); }

/* Every tile starts on the same line, however much is inside it
   (DESIGN_SPEC §5.2). */
.tiles { display: grid; gap: var(--sp-3); grid-template-columns: 1fr; margin: 0 0 var(--sp-4); align-items: stretch; }
@media (min-width: 480px) { .tiles { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .tiles { grid-template-columns: repeat(3, 1fr); } }

.tile {
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-4); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  text-decoration: none; color: inherit;
}
.tile__label { font-size: 13px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.tile__figure { font-size: var(--fs-3xl); font-weight: 700; line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.tile__note { margin: 0; font-size: 13px; color: var(--text-soft); }
.tile__action { margin-top: auto; padding-top: var(--sp-2); font-size: var(--fs-sm); font-weight: 650; color: var(--brand); }
.tile--attention { border-color: var(--danger-line); background: var(--danger-wash); }
.tile--attention .tile__figure,
.tile--attention .tile__label,
.tile--attention .tile__action { color: var(--danger-ink); }

.storelink {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4); background: var(--brand-wash);
  border: 1px solid #cfe0db; border-radius: var(--r-lg);
}
.storelink__url {
  flex: 1 1 12rem; min-width: 0;
  font-family: var(--mono); font-size: 13px; color: var(--ink);
  overflow-wrap: anywhere;
}

.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.step {
  display: grid; grid-template-columns: 28px 1fr; gap: var(--sp-3);
  padding: var(--sp-4); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
}
.step__n {
  display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: var(--r-pill); background: var(--surface-sunk);
  font-size: 13px; font-weight: 700; color: var(--text-soft);
}
.step--done { background: var(--ok-wash); border-color: var(--ok-line); }
.step--done .step__n { background: var(--ok); color: #fff; }
.step h3 { margin: 0 0 2px; font-size: var(--fs-md); }
.step p { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); color: var(--text-soft); }
.step p:last-child { margin-bottom: 0; }

/* List rows (products, pages) --------------------------------------------- */

.rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }

.row {
  display: grid; align-items: center;
  grid-template-columns: 56px minmax(0, 1fr);
  grid-template-areas: "photo main" "cells cells" "act act";
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
}
@media (min-width: 768px) {
  .row {
    grid-template-columns: 56px minmax(0, 1fr) auto auto;
    grid-template-areas: "photo main cells act";
    gap: var(--sp-4);
  }
}
.row--soldout { background: var(--surface-sunk); }
.row--soldout .row__name { color: var(--text-soft); }
.row--soldout .thumb, .row--soldout .thumb--empty { opacity: .72; }
.row--page { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main"; }

/* text-decoration: none on the anchor itself. Setting it on the tile inside
   does nothing — an ancestor's underline is drawn through its descendants
   whatever they ask for — which is how "Add photo" came to be underlined. */
.row__photo { grid-area: photo; display: block; text-decoration: none; }
.row__main { grid-area: main; min-width: 0; }
.row__cells { grid-area: cells; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.row__act { grid-area: act; display: flex; align-items: center; gap: var(--sp-2); }
.row__name { font-weight: 650; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.row__name:hover { text-decoration: underline; }
.row__meta { margin: var(--sp-1) 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); font-size: 13px; color: var(--text-muted); }
.row__summary { margin: var(--sp-1) 0 0; font-size: var(--fs-sm); color: var(--text-soft); }

/* Square crop, always: a phone photo is any shape, and a squashed thumbnail
   is what the old grid showed (DESIGN_SPEC §3). */
.thumb, .thumb--empty {
  display: grid; place-items: center;
  width: 56px; height: 56px; aspect-ratio: 1;
  object-fit: cover; border-radius: var(--r-md);
  background: var(--surface-sunk); overflow: hidden;
}
/* Not a bare "+": it says what tapping it does. */
.thumb--empty {
  gap: 1px; border: 1px dashed var(--line-strong); background: var(--bg);
  font-size: 9px; font-weight: 650; line-height: 1.1; text-align: center;
  color: var(--text-soft); text-decoration: none;
}
.thumb--empty .thumb__plus { font-size: 15px; font-weight: 400; line-height: 1; }

/* Inline-edit cell — every state is a server-rendered class, no JS machine. */

.cell { display: inline-flex; align-items: center; gap: var(--sp-2); }
.cell form { display: inline-flex; align-items: center; gap: var(--sp-2); margin: 0; }
.cell .input-group { border-radius: var(--r-sm); }
.cell .input-group__prefix, .cell .input-group__suffix { padding: 0 var(--sp-2); font-size: var(--fs-xs); }
.cell input {
  width: 7ch; min-height: 38px; padding: var(--sp-2) 10px;
  font-size: var(--fs-md); font-variant-numeric: tabular-nums;
}
.cell input.cell__stock { width: 5ch; }
.cell__static { font-size: var(--fs-sm); color: var(--text-soft); }
.cell__flag { font-size: 13px; color: var(--text-muted); }

.cell--saving .input-group { opacity: .7; }
.cell--saved .input-group { border-color: var(--ok-line); background: #f5faf7; }
.cell--saved .input-group__prefix { background: var(--ok-wash); }
.cell--saved .cell__flag { color: var(--ok-ink); font-weight: 650; }
.cell--error { flex-direction: column; align-items: flex-start; gap: var(--sp-1); }
.cell--error .input-group { border-color: var(--danger); border-width: 1.5px; }
.cell--error .input-group__prefix { background: var(--danger-wash); }
.cell--error .cell__flag, .cell-bad { color: var(--danger); font-weight: 650; font-size: 13px; }

/* htmx shows an indicator only while its request is in flight.

   display, not visibility: a hidden-but-laid-out "saving…" reserved about
   50px beside every inline-edit cell, which was enough to push the stock box
   onto a line of its own on a 360px screen. */
.indicator { display: none; }
.indicator.htmx-request, .htmx-request .indicator { display: inline; }

/* Orders ------------------------------------------------------------------ */

.orders { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.order-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
.order-card--attention { border-color: var(--danger-line); }
.order-card__link {
  display: grid; gap: var(--sp-1); padding: var(--sp-3) var(--sp-4);
  min-height: var(--tap); color: inherit; text-decoration: none;
}
.order-card__link:hover { background: var(--bg); }
.order-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); }
.order-card__who { font-weight: 650; color: var(--ink); overflow-wrap: anywhere; }
.order-card__total { font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
.order-card__meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); font-size: 13px; color: var(--text-muted); }
.order-card__why {
  margin-top: var(--sp-1); padding: var(--sp-2) 10px; border-radius: var(--r-sm);
  background: var(--danger-wash); color: var(--danger-ink); font-size: 13px;
}

.panel {
  padding: var(--sp-4) var(--sp-5); margin: 0 0 var(--sp-4);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.panel h2 { font-size: var(--fs-md); margin: var(--sp-4) 0 var(--sp-2); }
.panel h2:first-child { margin-top: 0; }

.lines { list-style: none; margin: 0; padding: 0; }
.line { display: flex; justify-content: space-between; gap: var(--sp-4); margin: 0 0 var(--sp-2); font-size: var(--fs-sm); }
.line > :last-child { white-space: nowrap; font-variant-numeric: tabular-nums; }
.line--total {
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid var(--line); font-size: var(--fs-lg); font-weight: 700;
}

.stat-list { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-1) var(--sp-4); margin: 0; }
.stat-list dt { color: var(--text-muted); font-size: var(--fs-sm); }
.stat-list dd { margin: 0; font-weight: 650; }

.actions { display: grid; gap: var(--sp-3); margin: 0 0 var(--sp-5); }
.actions h2 { font-size: var(--fs-md); margin: 0; }
.action { display: grid; gap: var(--sp-2); margin: 0; }
.action-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; }

.payments { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.payment {
  display: grid; gap: 2px; padding: var(--sp-2) 10px;
  border-radius: var(--r-sm); border-left: 3px solid var(--line);
  background: var(--bg); font-size: var(--fs-sm);
}
.payment__head { display: flex; justify-content: space-between; gap: var(--sp-4); }
.payment--good { border-left-color: var(--ok); }
.payment--warn { border-left-color: var(--warn); }

/* Timeline — one partial, shared by the seller's order and the buyer's
   status page (DESIGN_SPEC §7). */

.timeline { list-style: none; margin: 0; padding: 0; display: grid; }
.timeline__step {
  position: relative; display: grid; gap: 2px;
  padding: 0 0 var(--sp-4) var(--sp-5);
  border-left: 2px solid var(--line);
  font-size: var(--fs-sm);
}
.timeline__step:last-child { border-left-color: transparent; padding-bottom: 0; }
.timeline__step::before {
  content: ""; position: absolute; left: -7px; top: 4px;
  width: 12px; height: 12px; border-radius: var(--r-pill);
  background: var(--surface); border: 2px solid var(--line-strong);
}
.timeline__step--done { border-left-color: var(--ok); }
.timeline__step--done::before { background: var(--ok); border-color: var(--ok); }
.timeline__step--current::before {
  border-color: var(--store-accent);
  box-shadow: 0 0 0 3px var(--store-accent-wash);
}
.timeline__what { font-weight: 650; color: var(--text); }
.timeline__step--todo { color: var(--text-muted); }
.timeline__step--todo .timeline__what { font-weight: 400; color: var(--text-muted); }
.timeline__when, .timeline__who { font-size: 13px; color: var(--text-muted); }
/* A person did this, as against something that happened on its own. */
.timeline__step--person { border-left-color: var(--accent); }
.timeline__step--person::before { background: var(--accent); border-color: var(--accent); }

/* Photo tiles ------------------------------------------------------------- */

.photos {
  list-style: none; margin: 0 0 var(--sp-4); padding: 0;
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
}
.photo { position: relative; }
.photo img {
  display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--r-md); background: var(--surface-sunk);
}
.photo-cover img, .photo--cover img { outline: 2px solid var(--brand); outline-offset: 2px; }
.photo-actions, .photo__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; margin-top: var(--sp-2); }
.tile__progress {
  position: absolute; inset: auto var(--sp-2) var(--sp-2) var(--sp-2); height: 4px;
  border-radius: var(--r-pill); background: rgb(255 255 255 / 60%); overflow: hidden;
}
.tile__progress > span { display: block; height: 100%; background: var(--brand); }
.tile--uploading img { opacity: .6; }
.tile--error img { outline: 2px solid var(--danger); outline-offset: 2px; }

/* An empty photo tile reads as "add photo", not as an ambiguous "+". */
.photo-add {
  display: grid; place-items: center; gap: var(--sp-1);
  aspect-ratio: 1; padding: var(--sp-3);
  background: var(--surface); border: 1px dashed var(--line-strong);
  border-radius: var(--r-md); color: var(--text-soft);
  font-size: 13px; font-weight: 650; text-align: center; cursor: pointer;
}
.photo-add:hover { background: var(--brand-wash); border-color: var(--brand); color: var(--brand); }
.photo-add .thumb__plus { font-size: var(--fs-2xl); font-weight: 400; line-height: 1; }
.photo-add input[type="file"] { display: none; }

/* Options table on the product form -------------------------------------- */

.fieldset {
  margin: 0 0 var(--sp-4); padding: var(--sp-4);
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
}
.fieldset > legend { padding: 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 650; color: var(--ink); }
.option-rows { list-style: none; margin: var(--sp-3) 0; padding: 0; display: grid; gap: var(--sp-3); }
.option-row {
  display: grid; gap: var(--sp-2);
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  padding-bottom: var(--sp-3); border-bottom: 1px dashed var(--line);
}
.option-row .field { margin: 0; }

/* Settings ---------------------------------------------------------------- */

.settings { display: grid; gap: var(--sp-4); }
@media (min-width: 1024px) {
  .settings--cols { grid-template-columns: 1fr 1fr; align-items: start; }
}
.settings-group {
  margin: 0; padding: var(--sp-4) var(--sp-5) var(--sp-5);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.settings-group > legend {
  padding: 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted);
}
.setting { margin: 0 0 var(--sp-4); }
.setting:last-child { margin-bottom: 0; }

/* A locked setting is information, not a broken field: no input, nothing
   posted, and a one-line reason (DESIGN_SPEC §5.6). */
.readonly-stat {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline; gap: var(--sp-1) var(--sp-3);
  margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
  background: var(--surface-sunk); border-radius: var(--r-md);
}
.readonly-stat dt { font-size: var(--fs-sm); font-weight: 600; color: var(--text-soft); }
.readonly-stat dd { grid-column: 2; grid-row: 1; margin: 0; font-weight: 650; font-variant-numeric: tabular-nums; }

/* Both children of this list are <dd>, so `.readonly-stat dd` above matches
   the explanation as well as the value — and it is the more specific of the
   two selectors, so it won. The explanation was pinned into row 1 on top of
   the value, which squeezed the label into a column one word wide and drew
   all three over each other.
   Qualified with dd so it out-specifies the rule it is correcting. */
.readonly-stat dd.readonly-stat__why {
  grid-column: 1 / -1; grid-row: 2;
  margin: var(--sp-1) 0 0; font-size: 13px; font-weight: 400;
  font-variant-numeric: normal; color: var(--text-soft);
}

.swatches { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 0 var(--sp-3); padding: 0; }
.swatch { position: relative; display: block; }
.swatch input { position: absolute; opacity: 0; width: 0; height: 0; }
.swatch__chip {
  display: block; width: var(--tap); height: var(--tap);
  border-radius: var(--r-md); border: 1px solid rgb(0 0 0 / 12%); cursor: pointer;
}
.swatch input:checked + .swatch__chip { outline: 3px solid var(--ink); outline-offset: 2px; }
.swatch input:focus-visible + .swatch__chip { outline: 3px solid var(--accent); outline-offset: 2px; }

.accent-preview {
  display: grid; gap: var(--sp-3); padding: var(--sp-4);
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md);
}

/* Safaricom's own error text, shown verbatim so a seller ringing their
   support line can quote the message they recognise (PLAN §7.2). */
.verbatim {
  display: inline-block; margin-top: var(--sp-2); padding: var(--sp-2) 10px;
  border-radius: var(--r-sm); background: rgb(255 255 255 / 60%);
  font-family: var(--mono); font-size: 13px; overflow-wrap: anywhere;
}

/* ========================================================================= */
/* Storefront — the seller's brand leads; Mtepe appears once, in the footer.  */
/* ========================================================================= */

/* The seller's preview strip wears Mtepe's own colours and sits outside
   .store, so it can never be mistaken for part of the shop
   (DESIGN_SPEC §5.14). */
.mtepe-strip {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
  margin: 0; padding: var(--sp-2) var(--sp-4);
  background: var(--ink); color: #d8e6e2; font-size: 13px;
}
/* --accent is non-text only: as 11px text on --ink it is 4.1:1, under AA.
   --accent-ink is for light grounds (2.4:1 here); the wash keeps the ochre
   family at 13.5:1. */
.mtepe-strip__mark { font-size: 13px; font-weight: 650; letter-spacing: -.01em; color: var(--accent-wash); }
.mtepe-strip a { color: #fff; }

.store { background: var(--bg); }
.store-wrap { max-width: 56rem; margin-inline: auto; padding: 0 var(--sp-4) var(--sp-7); }

.closed-bar {
  margin: 0; padding: var(--sp-3) var(--sp-4);
  background: var(--warn-wash); color: var(--warn-ink);
  font-size: var(--fs-sm); text-align: center;
}
.draft-bar {
  margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md);
  background: var(--neutral-wash); color: var(--neutral); font-size: var(--fs-sm);
}

/* Nothing is centred except this block, so the page never looks lopsided. */
.store-head { position: relative; padding: var(--sp-5) var(--sp-4) var(--sp-4); text-align: center; }
.store-head__logo { display: block; margin: 0 auto var(--sp-3); max-height: 64px; width: auto; border-radius: var(--r-md); }
.store-head__mark {
  display: grid; place-items: center; width: 56px; height: 56px; margin: 0 auto var(--sp-3);
  border-radius: var(--r-pill); background: var(--store-accent); color: var(--store-accent-ink);
  font-size: var(--fs-xl); font-weight: 700;
}
.store-head h1 { margin: 0; font-size: var(--fs-2xl); font-weight: 700; }
.store-head__tagline { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); color: var(--text-soft); }
.store-head__contact { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-2); margin: var(--sp-4) 0 0; }
.store-head__contact a {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4); min-height: 38px;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  background: var(--surface); color: var(--text);
  font-size: var(--fs-sm); font-weight: 600; text-decoration: none;
}
.store-head__contact a:hover { border-color: var(--store-accent); color: var(--store-accent); }

.store-banner {
  display: block; width: 100%; aspect-ratio: 3/1; object-fit: cover;
  border-radius: var(--r-lg); margin-bottom: var(--sp-4); background: var(--surface-sunk);
}

/* Two across on a phone, which is what a buyer arriving from Instagram
   expects; wider screens get more. */
.product-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--sp-4) var(--sp-3);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 768px) { .product-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .product-grid { grid-template-columns: repeat(4, 1fr); } }

/* The whole card is the link, so it reads as tappable. */
.product-card {
  display: grid; gap: var(--sp-1); align-content: start; padding: var(--sp-2);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  color: inherit; text-decoration: none;
}
.product-card:hover { border-color: var(--store-accent); box-shadow: var(--shadow-1); transform: translateY(-1px); }
@media (prefers-reduced-motion: no-preference) {
  .product-card { transition: transform .12s ease, box-shadow .12s ease; }
}
.product-card:focus-visible { outline: 3px solid var(--store-accent); outline-offset: 2px; }
.product-card__photo {
  display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--r-md); background: var(--surface-sunk);
}
/* Never a blank grey box: it says what it is (DESIGN_SPEC §5.9). */
.product-card__photo.thumb--empty {
  display: grid; place-items: center; width: 100%; height: auto;
  font-size: var(--fs-xs); border-style: dashed;
}
.product-card__name { margin: var(--sp-1) 0 0; font-size: var(--fs-sm); line-height: 1.3; }
.product-card__price { font-weight: 700; font-variant-numeric: tabular-nums; }
.was { margin-left: var(--sp-1); color: var(--text-muted); font-weight: 400; }
.product-card__meta { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin: var(--sp-1) 0 0; }

.trust-strip {
  display: grid; gap: 2px; margin: var(--sp-5) 0 0;
  padding: var(--sp-4); border-radius: var(--r-lg);
  background: var(--store-accent-wash); border: 1px solid rgb(0 0 0 / 6%);
}
.trust-strip strong { font-size: var(--fs-sm); }
.trust-strip p { margin: 0; font-size: 13px; color: var(--text-soft); }

.store-foot {
  max-width: 56rem; margin-inline: auto;
  padding: var(--sp-5) var(--sp-4) var(--sp-6);
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm); color: var(--text-muted);
}
.store-foot nav { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.store-foot__by { margin: var(--sp-4) 0 0; font-size: 13px; }

/* Product page ------------------------------------------------------------ */

.product { display: grid; gap: var(--sp-5); }
@media (min-width: 768px) {
  .product { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
}

/* A scroll-snap track: it swipes with no JavaScript at all. */
.gallery {
  display: flex; gap: var(--sp-2); overflow-x: auto;
  scroll-snap-type: x mandatory; scrollbar-width: none;
}
.gallery::-webkit-scrollbar { display: none; }
.gallery img, .gallery .thumb--empty {
  flex: 0 0 100%; scroll-snap-align: center;
  width: 100%; height: auto; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--r-lg); background: var(--surface-sunk);
}
.gallery__dots { display: flex; justify-content: center; gap: var(--sp-2); margin: var(--sp-3) 0 0; }
.gallery__dots a { width: 9px; height: 9px; border-radius: var(--r-pill); background: var(--line-strong); }
.gallery__dots a:first-child { background: var(--store-accent); }

.product-detail h1 { font-size: var(--fs-2xl); margin: 0 0 var(--sp-2); }
.product-price {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2);
  margin: 0 0 var(--sp-3); font-size: var(--fs-xl); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.product-words { margin: var(--sp-4) 0; line-height: 1.6; font-size: var(--fs-sm); }

.options { display: grid; gap: var(--sp-2); margin: 0 0 var(--sp-4); padding: 0; border: 0; }
.options > legend { padding: 0 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 650; }
.option {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); min-height: var(--tap);
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--r-md); cursor: pointer;
}
.option:has(input:checked) {
  border-color: var(--store-accent); border-width: 2px;
  background: var(--store-accent-wash); padding: 11px 15px;
}
.option:has(input:disabled) { color: var(--text-muted); background: var(--surface-sunk); cursor: default; }
.option input { width: auto; min-height: 0; margin: 0; }
.option-list { list-style: none; margin: 0 0 var(--sp-4); padding: 0; display: grid; gap: var(--sp-2); }
.option-list li {
  padding: var(--sp-3) var(--sp-4); border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--surface); font-size: var(--fs-sm);
}
.option-gone { color: var(--text-muted); }

/* − / + around a number input: two submit buttons, so it works with no JS. */
.stepper {
  display: flex; align-items: stretch; width: max-content;
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  overflow: hidden; background: var(--surface);
}
.stepper button {
  font: inherit; font-size: var(--fs-xl); line-height: 1;
  width: var(--tap); min-height: var(--tap);
  border: 0; background: var(--surface); color: var(--text); cursor: pointer;
}
.stepper button:hover { background: var(--bg); }
.stepper input {
  width: 3.5rem; min-height: var(--tap); padding: 0;
  text-align: center; border: 0; border-inline: 1px solid var(--line);
  border-radius: 0; font-variant-numeric: tabular-nums;
}

.buy { display: grid; gap: var(--sp-4); margin: var(--sp-4) 0 0; }
.buy-shut {
  margin: var(--sp-4) 0; padding: var(--sp-4);
  border: 1px dashed var(--line-strong); border-radius: var(--r-md);
  background: var(--surface); color: var(--text-soft); font-size: var(--fs-sm);
}

/* Nothing near Buy now should leave a buyer wondering how they pay
   (DESIGN_SPEC §5.11). */
.reassure {
  display: grid; gap: var(--sp-1); margin: var(--sp-4) 0 0;
  padding: var(--sp-4); border-radius: var(--r-md); background: var(--store-accent-wash);
}
.reassure strong { font-size: var(--fs-sm); }
.reassure p { margin: 0; font-size: 13px; color: var(--text-soft); }

.sticky-buy {
  position: sticky; bottom: 0; z-index: 10;
  margin: var(--sp-5) calc(var(--sp-4) * -1) 0;
  padding: var(--sp-3) var(--sp-4);
  padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom));
  background: var(--bg); box-shadow: var(--shadow-sticky);
}
@media (min-width: 768px) {
  .sticky-buy { position: static; margin: var(--sp-4) 0 0; padding: 0; background: none; box-shadow: none; }
}

/* Mtepe's own pages: landing, About, Terms, Privacy (PLAN D40) ------------ */

.site-head { padding: var(--sp-4); border-bottom: 1px solid var(--line); background: var(--surface); }
.site-head__mark { display: inline-block; vertical-align: middle; line-height: 0; }
.site-head__mark svg { display: block; }
.site-head__boat { fill: var(--brand); }
.site-head__word { stroke: var(--ink); }
.site-wrap { max-width: 44rem; margin-inline: auto; padding: var(--sp-5) var(--sp-4) var(--sp-7); }
.site-prose { line-height: var(--lh-body); overflow-wrap: anywhere; }
.site-prose h1 { font-size: var(--fs-2xl); margin: var(--sp-4) 0 var(--sp-3); }
.site-prose h2 { font-size: var(--fs-xl); margin: var(--sp-7) 0 var(--sp-3); }
.site-prose ol, .site-prose ul { padding-left: 1.25rem; }
.site-prose li + li { margin-top: var(--sp-2); }
.site-prose hr { margin: var(--sp-7) 0; border: 0; border-top: 1px solid var(--line); }
.site-prose code { font-size: .9em; }
/* A WhatsApp link on a line of its own is the page's call to action, so it
   looks like a button without the Markdown having to say so. */
.site-prose p > a[href^="https://wa.me/"]:only-child {
  display: inline-flex; align-items: center; min-height: var(--tap);
  padding: 0 var(--sp-5); border-radius: var(--r-md);
  background: var(--brand); color: #fff; font-weight: 600; text-decoration: none;
}
.site-prose p > a[href^="https://wa.me/"]:only-child:hover { background: var(--brand-hi); }

/* A button that reads as a link, for a secondary step inside a form. */
.link-button {
  font: inherit; padding: 0; border: 0; background: none;
  color: var(--brand); text-decoration: underline; cursor: pointer;
}

.stat-big { margin: var(--sp-2) 0; font-size: var(--fs-3xl); font-weight: 700; font-variant-numeric: tabular-nums; }

/* WhatsApp updates (PLAN D37) */
.whatsapp-update__message {
  white-space: pre-wrap; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md);
  background: var(--bg); border: 1px solid var(--line); font-size: var(--fs-sm);
}

/* Cart (PLAN D33) --------------------------------------------------------- */

.cart-lines { list-style: none; margin: 0 0 var(--sp-5); padding: 0; display: grid; gap: var(--sp-3); max-width: var(--measure); }
.cart-line {
  display: grid; grid-template-columns: 64px 1fr auto; gap: var(--sp-3);
  padding: var(--sp-3); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-lg);
}
.cart-line--problem { border-color: var(--danger-line); }
.cart-line__photo img, .cart-line__photo .thumb--empty {
  display: block; width: 64px; height: 64px; object-fit: cover; border-radius: var(--r-md);
}
.cart-line__body { min-width: 0; }
.cart-line__name { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.cart-line__name a { color: inherit; text-decoration: none; }
.cart-line__option { display: block; font-weight: 400; font-size: var(--fs-sm); color: var(--text-soft); }
.cart-line__each { margin: var(--sp-1) 0 0; font-size: var(--fs-sm); color: var(--text-soft); }
.cart-line__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: var(--sp-2) 0 0; }
.cart-line__remove {
  font: inherit; font-size: var(--fs-sm); min-height: var(--tap); padding: 0 var(--sp-2);
  border: 0; background: none; color: var(--text-soft); text-decoration: underline; cursor: pointer;
}
.cart-line__total { margin: 0; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.stepper__value {
  display: grid; place-items: center; min-width: 3rem; padding: 0 var(--sp-2);
  border-inline: 1px solid var(--line); font-variant-numeric: tabular-nums;
}
.buy__add { margin-top: var(--sp-2); }
.store-head__cart {
  position: absolute; top: var(--sp-4); right: var(--sp-4);
  font-size: var(--fs-sm); font-weight: 600; text-decoration: none; color: var(--text);
}

/* Checkout ---------------------------------------------------------------- */

/* Delivery methods (PLAN D34): only the chosen method's panel shows. A
   browser without :has() shows every panel, which is still usable. */
.delivery:has([name=delivery_method]:checked) .delivery-panel { display: none; }
.delivery:has([value=pickup_mtaani]:checked) .delivery-panel[data-method=pickup_mtaani],
.delivery:has([value=matatu_sacco]:checked) .delivery-panel[data-method=matatu_sacco],
.delivery:has([value=shop_pickup]:checked) .delivery-panel[data-method=shop_pickup] { display: block; }
.delivery-panel { margin-top: var(--sp-4); }

.checkout { display: grid; gap: var(--sp-5); max-width: var(--measure); }
.summary-card {
  padding: var(--sp-4) var(--sp-5); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-lg);
}

/* In normal page flow — no scroll box inside a scrolling page
   (DESIGN_SPEC §5.12). */
.agents { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.agent {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); min-height: var(--tap);
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--r-md); cursor: pointer;
}
.agent:hover { border-color: var(--store-accent); }
/* The whole row is the tap target; the radio itself is out of the way. */
.agent input { position: absolute; opacity: 0; width: 0; height: 0; }
.agent:has(input:checked) {
  border-color: var(--store-accent); border-width: 2px;
  background: var(--store-accent-wash); padding: 11px 15px;
}
.agent:has(input:checked)::after { content: "✓"; margin-left: auto; font-weight: 700; color: var(--store-accent); }
.agent__words { display: grid; gap: 1px; }
.agent__area, .agent__hours { font-size: 13px; color: var(--text-muted); }
.agent-chosen {
  display: grid; gap: 2px; margin: 0;
  padding: var(--sp-4); border-radius: var(--r-md);
  background: var(--store-accent-wash); border: 2px solid var(--store-accent);
}
.agent-chosen__label { font-size: 13px; font-weight: 650; color: var(--store-accent); }
.agent-chosen__change { justify-self: start; margin-top: var(--sp-1); }

/* Waiting, and the rest of the buyer's order page ------------------------- */

.status {
  margin: 0 0 var(--sp-4); padding: var(--sp-5);
  border-radius: var(--r-lg); border: 1px solid var(--line); background: var(--surface);
}
.status h2 { font-size: var(--fs-xl); margin: 0 0 var(--sp-2); }
.status p { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); }
.status p:last-child { margin-bottom: 0; }
.status form { margin: var(--sp-4) 0 var(--sp-2); }

/* Waiting is normal, so it looks calm: the store's own tint, not a warning.
   Warning colour is kept for real problems (DESIGN_SPEC §5.13). */
.status--waiting { background: var(--store-accent-wash); border-color: rgb(0 0 0 / 8%); }
.status--good { background: var(--ok-wash); border-color: var(--ok-line); }
.status--warn { background: var(--warn-wash); border-color: var(--warn-line); }
.status--danger { background: var(--danger-wash); border-color: var(--danger-line); }

.status__timer {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3);
  margin: var(--sp-4) 0 0; padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md); background: rgb(255 255 255 / 55%);
}
.status__timer > span:first-child { font-size: 13px; color: var(--text-soft); }
.countdown { font-size: var(--fs-xl); font-weight: 700; }
.deadline { font-size: var(--fs-md); font-weight: 700; }

.status__ticker { display: flex; align-items: center; gap: var(--sp-2); font-size: 13px; color: var(--text-soft); }
.status__ticker::before {
  content: ""; width: 12px; height: 12px; border-radius: var(--r-pill);
  border: 2px solid currentColor; border-right-color: transparent;
}
@media (prefers-reduced-motion: no-preference) {
  .status__ticker::before { animation: spin 1s linear infinite; }
}

/* The boat on "check your phone" (storefront/order.html). Present only
   while the status panel is prompting; hidden, too, in a browser without
   :has(), which is the right way to fail. */
.order-boat { display: none; width: 160px; height: 64px; margin: 0 auto var(--sp-2); color: var(--text-soft); }
.order:has(.status--prompting) .order-boat { display: block; }
.order-boat__hull { fill: currentColor; }
.order-boat__mast { stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.order-boat__sail { fill: var(--store-accent); }
.order-boat__waves { fill: none; stroke: var(--store-accent); stroke-width: 2; stroke-linecap: round; opacity: .45; }
.order-boat__waves--far { opacity: .25; }
@media (prefers-reduced-motion: no-preference) {
  /* Slow and small: a few pixels over four seconds reads as calm; anything
     quicker reads as "hurry". transform only, so no repaint per frame. */
  .order-boat__vessel {
    transform-box: fill-box; transform-origin: 50% 90%;
    animation: boat-bob 4s ease-in-out infinite;
  }
  .order-boat__waves { animation: boat-waves 6s linear infinite; }
  .order-boat__waves--far { animation-duration: 9s; }
}
@keyframes boat-bob {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50% { transform: translateY(2px) rotate(2deg); }
}
/* Exactly one wave period, so the loop has no seam. */
@keyframes boat-waves { to { transform: translateX(-20px); } }

.paid-mark {
  display: grid; place-items: center; width: 48px; height: 48px; margin: 0 0 var(--sp-3);
  border-radius: var(--r-pill); background: var(--ok); color: #fff; font-size: var(--fs-xl);
}

/* "Keep this page" was alarming; a button that sends the link is not. */
.keep-link {
  display: grid; gap: var(--sp-2); margin: var(--sp-4) 0 0;
  padding: var(--sp-4); border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line);
}
.keep-link p { margin: 0; font-size: 13px; color: var(--text-soft); }
.keep-link__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.keep-link input { font-family: var(--mono); font-size: 13px; }

.order { max-width: var(--measure); }

/* Written pages ----------------------------------------------------------- */

.written { max-width: var(--measure); }
.written h1 { font-size: var(--fs-2xl); margin: 0 0 var(--sp-4); }
.prose, .preview { line-height: 1.65; }
.prose h2, .preview h2 { font-size: var(--fs-lg); margin: var(--sp-5) 0 var(--sp-2); }
.prose h3, .preview h3 { font-size: var(--fs-md); margin: var(--sp-4) 0 var(--sp-2); }
.prose p, .preview p { margin: 0 0 var(--sp-3); }
.prose ul, .prose ol, .preview ul, .preview ol { margin: 0 0 var(--sp-3); padding-left: var(--sp-5); }
.prose li, .preview li { margin-bottom: var(--sp-1); }
.prose table, .preview table { border-collapse: collapse; margin: 0 0 var(--sp-3); }
.prose th, .prose td, .preview th, .preview td { border: 1px solid var(--line); padding: var(--sp-2) 10px; text-align: left; }
.prose blockquote, .preview blockquote {
  margin: 0 0 var(--sp-3); padding-left: var(--sp-3);
  border-left: 3px solid var(--line); color: var(--text-muted);
}

/* The logo control on the store-look screen.

   Each branch is styled to match what the storefront actually renders — the
   uploaded picture as a rectangle capped in height, the fallback as the round
   accent mark — rather than being made to look alike here. A preview that
   flatters a logo the shop would not show is worse than no preview. */
.logo-setting { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4); }
.logo-setting__now {
  display: grid; place-items: center; flex: 0 0 auto;
  min-width: 96px; min-height: 96px; padding: var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface-sunk);
}
.logo-setting__image { display: block; max-height: 64px; width: auto; border-radius: var(--r-md); }
.logo-setting__mark {
  display: grid; place-items: center; width: 56px; height: 56px;
  border-radius: var(--r-pill); background: var(--brand); color: #fff;
  font-size: var(--fs-xl); font-weight: 700;
}
.logo-setting__controls { flex: 1 1 14rem; min-width: 0; }
.logo-setting__controls .btn { margin-top: var(--sp-3); }
.logo-remove { margin-top: calc(var(--sp-3) * -1); }

/* Where to send the money, for a shop that takes payment by hand.
   The numbers are large and selectable because a buyer is copying them into
   the M-Pesa menu on the same phone they are reading this on. */
.pay-to { margin: var(--sp-4) 0 0; padding-left: var(--sp-5); display: grid; gap: var(--sp-2); }
.pay-to li { line-height: 1.5; }
.pay-to__number {
  display: inline-block; padding: 2px var(--sp-2);
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font-size: var(--fs-lg); font-variant-numeric: tabular-nums; letter-spacing: .03em;
  user-select: all;
}
.pay-to__confirm {
  margin: var(--sp-3) 0 0; padding: var(--sp-3);
  border: 1px solid var(--line-strong); border-left: 3px solid var(--store-accent);
  border-radius: var(--r-sm); background: var(--surface); line-height: 1.5;
}
