/* Cards Realm Gestão de Lojas - design system. Light by default, dark via [data-theme="dark"]
   (explicit toggle, static/js/theme.js) or prefers-color-scheme (no toggle set yet). */

:root {
  --bg: #f5f6fb;
  --bg-elevated: #ffffff;
  --bg-subtle: #eef0f7;
  --text: #14171f;
  --text-muted: #676e7d;
  --border: #e6e8f0;
  --primary: #3d5afe;
  --primary-hover: #2f46e0;
  --primary-contrast: #ffffff;
  --success: #16a34a;
  --success-bg: #e8f8ee;
  --danger: #dc2626;
  --danger-bg: #fdecec;
  --warning: #d97706;
  --warning-bg: #fdf3e2;
  --radius-lg: 16px;
  --radius: 12px;
  --radius-sm: 8px;
  --shadow-sm: 0 1px 2px rgba(20, 23, 31, 0.06);
  --shadow: 0 2px 8px rgba(20, 23, 31, 0.06), 0 8px 24px rgba(20, 23, 31, 0.06);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;

  --store-primary: #1c1c1c;
  --store-secondary: #eae393;
  --store-accent: #ffffff;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0d0f14;
    --bg-elevated: #171a22;
    --bg-subtle: #1e222c;
    --text: #eef0f5;
    --text-muted: #9aa1b0;
    --border: #2a2f3c;
    --primary: #6684ff;
    --primary-hover: #869cff;
    --success: #34d377;
    --success-bg: #113321;
    --danger: #f45b5b;
    --danger-bg: #3a1818;
    --warning: #f0a83c;
    --warning-bg: #3a2c11;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow: 0 2px 8px rgba(0, 0, 0, 0.35), 0 12px 32px rgba(0, 0, 0, 0.35);
  }
}

:root[data-theme="dark"] {
  --bg: #0d0f14;
  --bg-elevated: #171a22;
  --bg-subtle: #1e222c;
  --text: #eef0f5;
  --text-muted: #9aa1b0;
  --border: #2a2f3c;
  --primary: #6684ff;
  --primary-hover: #869cff;
  --success: #34d377;
  --success-bg: #113321;
  --danger: #f45b5b;
  --danger-bg: #3a1818;
  --warning: #f0a83c;
  --warning-bg: #3a2c11;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow: 0 2px 8px rgba(0, 0, 0, 0.35), 0 12px 32px rgba(0, 0, 0, 0.35);
}

* { box-sizing: border-box; }

html { color-scheme: light dark; }

body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.15s ease, color 0.15s ease;
}

h1, h2, h3 { letter-spacing: -0.02em; line-height: 1.2; }
h1 { font-size: 1.75rem; font-weight: 700; margin: 0 0 0.25rem; }
h2 { font-size: 1.3rem; font-weight: 650; }
h3 { font-size: 1.05rem; font-weight: 650; margin: 0.5rem 0 0.15rem; }

a { color: var(--primary); }

/* ---------- App shell / top nav ---------- */
.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 0.85rem 1.5rem;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 20;
}

/* Breadcrumb trail (templates/breadcrumb.html) - below the topbar on every
   merchant-admin page (base.html), one store's worth of settings pages was
   getting hard to navigate back out of with no trail. */
.breadcrumb {
  padding: 0.6rem 1.5rem;
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.breadcrumb a { color: var(--text-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--primary); text-decoration: underline; }
.breadcrumb-sep { color: var(--border); }
.breadcrumb-current { color: var(--text); font-weight: 600; }

.topbar .brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 750;
  font-size: 1.05rem;
  text-decoration: none;
  color: var(--text);
}
.topbar .brand .brand-mark {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--primary), #8fa4ff);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 800;
  font-size: 0.85rem;
}

.topbar nav { display: flex; align-items: center; gap: 1.1rem; }
.topbar nav a { color: var(--text-muted); text-decoration: none; font-size: 0.92rem; font-weight: 550; }
.topbar nav a:hover { color: var(--text); }
.topbar .user-name { color: var(--text-muted); font-size: 0.9rem; }

.theme-toggle {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text);
  width: 36px;
  height: 36px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}
.theme-toggle:hover { background: var(--border); }
.icon-moon { display: none; }
:root[data-theme="dark"] .icon-sun { display: none; }
:root[data-theme="dark"] .icon-moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .icon-sun { display: none; }
  :root:not([data-theme="light"]) .icon-moon { display: block; }
}

/* Storefront cart icon (templates/cart_icon.html) - sits next to the
   theme toggle on every public storefront-family page. The badge only
   appears once there's at least one item (server-rendered on page load,
   updated live by erpUpdateCartBadge() right after an add-to-cart POST). */
/* These sit ON the store's own coloured header, whose background is the
   merchant's --store-primary and can be any colour at all - so they must NOT
   be a bare glyph tinted with the page's --text. That is exactly what they
   were, and a store with a dark primary rendered a black cart icon on a dark
   header in light mode: invisible.

   The fix is the same chip .theme-toggle already used (and which was visible
   for that reason): a real surface from the page palette plus the page's own
   text colour. Contrast is guaranteed by construction - the pair always
   contrasts with itself - so it holds for ANY store colour, in both themes,
   which deriving from --store-accent would not (a store can legitimately pick
   an accent close to its primary). */
.cart-icon-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text);
  text-decoration: none;
  width: 36px;
  height: 36px;
  justify-content: center;
}
.cart-icon-link:hover { background: var(--border); }
.cart-badge {
  position: absolute;
  top: -4px;
  right: -6px;
  background: var(--danger);
  /* Separates the badge from the chip it now overlaps, so the count stays
     legible instead of merging into the button's own edge. */
  box-shadow: 0 0 0 2px var(--bg-subtle);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  min-width: 18px;
  height: 18px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
}

/* Floating WhatsApp chat button (templates/whatsapp_button.html) - fixed
   bottom-right on every storefront page when the store enabled it. Uses
   WhatsApp's own brand green deliberately, NOT the store's --store-primary:
   it's a recognizable third-party affordance, and a store whose brand color
   happens to be white/dark would otherwise render an unrecognizable or
   invisible button. */
.whatsapp-float {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 1000;
  width: 56px;
  height: 56px;
  border-radius: 999px;
  background: #25d366;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow);
  transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.whatsapp-float:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25); }

.main-content { max-width: 1020px; margin: 0 auto; padding: 2rem 1.5rem 4rem; }

/* ---------- Cards / surfaces ---------- */
.card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}
.page-header a { font-size: 0.9rem; font-weight: 600; text-decoration: none; }

.muted { color: var(--text-muted); font-size: 0.9rem; }

/* ---------- Forms ---------- */
label { display: block; margin-bottom: 0.9rem; font-size: 0.88rem; font-weight: 600; color: var(--text); }
/* [hidden] must win over any other display rule on the same element - the
   input/select/textarea rule below sets `display: block` unconditionally,
   which silently overrides the browser's own `[hidden] { display: none }`
   default the moment `hidden` is used on one of those elements (found by
   actually rendering a hidden file input, not by reading the CSS - it had
   simply never been exercised on a form control before). */
[hidden] { display: none !important; }

input, select, textarea {
  display: block;
  width: 100%;
  padding: 0.6rem 0.75rem;
  margin-top: 0.35rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  font-family: inherit;
  background: var(--bg-elevated);
  color: var(--text);
  font-weight: 400;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 20%, transparent);
}

button, .button {
  background: var(--primary);
  color: var(--primary-contrast);
  border: none;
  border-radius: var(--radius-sm);
  padding: 0.65rem 1.3rem;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  font-size: 0.95rem;
  font-weight: 650;
  transition: background-color 0.15s ease, transform 0.05s ease;
}
button:hover, .button:hover { background: var(--primary-hover); }
button:active, .button:active { transform: translateY(1px); }
button.secondary, .button.secondary {
  background: var(--bg-subtle);
  color: var(--text);
  border: 1px solid var(--border);
}
button.secondary:hover { background: var(--border); }
button.danger-button, .danger-button {
  background: var(--danger);
  color: #fff;
}
button.danger-button:hover, .danger-button:hover { filter: brightness(0.92); }

.form-error { color: var(--danger); margin-top: 0.75rem; font-size: 0.9rem; font-weight: 600; }

.color-row { display: flex; gap: 1rem; }
.color-row label { flex: 1; }
.color-row input { width: 100%; padding: 0.25rem; height: 42px; cursor: pointer; }

.slug-input { display: flex; align-items: center; gap: 0.4rem; }
.slug-input span { color: var(--text-muted); white-space: nowrap; }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 650;
}
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-warning { background: var(--warning-bg); color: var(--warning); }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-muted { background: var(--bg-subtle); color: var(--text-muted); }

/* ---------- Dashboard store grid ---------- */
/* "What can I do in my store" menu (templates/store_settings.html) - the
   user pointed out the old flat row of bare "Nome →" text links was too
   simple/unclear about what each one actually does - each tile now has a
   one-line description, not just a label. */
.menu-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
.menu-tile {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.1rem;
  text-decoration: none;
  color: inherit;
  transition: box-shadow 0.15s ease, transform 0.1s ease, border-color 0.15s ease;
}
.menu-tile:hover { box-shadow: var(--shadow); transform: translateY(-2px); border-color: var(--primary); }
.menu-tile strong { color: var(--text); font-size: 0.98rem; }
.menu-tile span { color: var(--text-muted); font-size: 0.85rem; line-height: 1.4; }

/* Groups of menu tiles on a store's admin home (templates/store_home.html).
   The heading is deliberately small and quiet - it's a signpost between
   groups of tiles, not a page title competing with the store name above. */
.menu-section { margin-bottom: 1.75rem; }
.menu-section > h2 {
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0 0 0.75rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
}

/* Search/filter bars above a data table (clients, service sales, ...). Wraps on
   a phone rather than pushing the page sideways - see CLAUDE.md's Mobile layout
   section on why nothing here may be a fixed-width row. */
.filter-row { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: flex-end; }
.filter-row label { flex: 0 1 auto; margin: 0; }
.filter-row .button, .filter-row button { flex: none; }

/* An archived/inactive row: still readable, visibly not current. Opacity rather
   than a grey colour so the row's own badges keep their meaning. */
.row-muted { opacity: 0.55; }

/* Month picker shared by the payouts, fixed-costs, tasks and P&L screens. Same
   visual language as .range-picker on the reports dashboard, but the options
   are dynamic (a store's real months), so it scrolls instead of wrapping into
   a block of chips. */
.month-picker { display: flex; gap: 0.4rem; overflow-x: auto; padding-bottom: 0.35rem; margin-bottom: 1rem; }
.month-picker a {
  flex: none;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 8px);
  text-decoration: none;
  color: var(--text-muted);
  font-size: 0.85rem;
  white-space: nowrap;
}
.month-picker a.active { background: var(--primary); border-color: var(--primary); color: #fff; }

/* The P&L chain (templates/dre.html). A ledger reads as a column of numbers
   that add up, so the value column is right-aligned and tabular-figured -
   proportional digits make totals visibly fail to line up. */
.dre-table { width: 100%; border-collapse: collapse; }
.dre-table td { padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--border); }
.dre-table td:last-child { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dre-table tr.dre-subtotal td { font-weight: 600; background: var(--bg-elevated); }
.dre-table tr.dre-total td { font-weight: 700; font-size: 1.05rem; border-top: 2px solid var(--border); }
.dre-table tr.dre-deduction td:last-child { color: var(--danger); }
.dre-table .dre-hint { display: block; font-size: 0.78rem; color: var(--text-muted); font-weight: 400; }

/* Per-store feature toggles on the settings page (features.py, migration 33).
   The whole row is the label, so the click target is the description too, not
   a 13px checkbox - there are ~17 of these and hitting the box exactly is the
   kind of small friction that makes a settings screen feel hostile.
   `align-items: start` keeps the checkbox pinned to the first line of a
   two-line description instead of floating to its vertical middle. */
.feature-toggle-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 0.6rem; }
.feature-toggle {
  display: flex;
  align-items: start;
  gap: 0.6rem;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  cursor: pointer;
  margin: 0;
  font-weight: 400;
}
.feature-toggle:hover { border-color: var(--primary); }
/* The global `input { display: block; width: 100% }` rule would stretch these
   checkboxes across the whole tile - same class of collision as the
   `[hidden]` one documented in CLAUDE.md's CSV import section. */
.feature-toggle input[type="checkbox"] { width: auto; margin: 0.2rem 0 0; flex: none; }
.feature-toggle > span { display: flex; flex-direction: column; gap: 0.15rem; }
.feature-toggle strong { font-size: 0.92rem; }
.feature-toggle .muted { font-size: 0.8rem; line-height: 1.35; }

.store-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 1.1rem; }

.docs-category-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.1rem; }
.docs-category-card h2 { margin-top: 0; font-size: 1.15rem; }
.docs-article-list { list-style: none; padding: 0; margin: 0.75rem 0 0; }
.docs-article-list li { margin-bottom: 0.5rem; }
.docs-article-list a { text-decoration: none; font-weight: 600; }
.docs-article-list a:hover { text-decoration: underline; }
.docs-article h1 { margin-top: 0; }
.docs-article p { line-height: 1.6; }
.docs-breadcrumb { text-transform: uppercase; font-size: 0.8rem; letter-spacing: 0.03em; margin-bottom: 0.25rem; }
.store-card { transition: box-shadow 0.15s ease, transform 0.1s ease; }
.store-card:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
.store-card h2 { margin-bottom: 0.2rem; }
.store-card-badges { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.5rem 0; }
/* Was a flat vertical list of ~13 undifferentiated text links - too many
   with no hierarchy to be legible at a glance (see templates/store_home.html
   for the one clear entry point that replaced most of them). Now just a
   primary "open the store" button + a couple of real secondary shortcuts. */
.store-card-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.9rem; }
.store-card-actions .button { font-size: 0.85rem; padding: 0.5rem 0.9rem; }

.empty-state {
  text-align: center;
  padding: 3rem 1.5rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
}

/* ---------- Auth ---------- */
.auth-card { max-width: 380px; margin: 3rem auto 0; }

/* ---------- Add-card / search ---------- */
.add-card-row { position: relative; }
.search-results {
  position: absolute;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  width: 100%;
  max-height: 260px;
  overflow-y: auto;
  z-index: 10;
  margin-top: 0.25rem;
}
.search-results div { padding: 0.55rem 0.75rem; cursor: pointer; display: flex; align-items: center; gap: 0.6rem; }
.search-results div:hover { background: var(--bg-subtle); }
.search-results img { width: 32px; border-radius: 4px; }

.add-card-selected { display: flex; align-items: center; gap: 0.6rem; margin: 0.6rem 0; }
.add-card-selected img { width: 48px; border-radius: var(--radius-sm); }

.flags-row { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 0.9rem; }
.flag-label {
  display: flex; align-items: center; gap: 0.35rem; width: auto; font-size: 0.85rem;
  font-weight: 500; background: var(--bg-subtle); padding: 0.3rem 0.6rem; border-radius: 999px;
}
.flag-label input { width: auto; display: inline; margin: 0; }

/* ---------- Inventory table ---------- */
/* `display: block` faz a própria tabela ser o container de rolagem, em QUALQUER
   largura - não só no celular. No desktop a tabela de estoque pede 1023px dentro
   de um .card de 972px, e como .card tem overflow visível a linha vazava para
   fora da borda arredondada ("a linha ficou maior que a tabela e está saindo
   como se estivesse desconfigurado"). Medido: com esta regra a tabela fica 25px
   DENTRO do card, e cabeçalho e corpo mantêm exatamente as mesmas larguras de
   coluna (o risco clássico desse truque é desalinhar os dois - não desalinha
   aqui porque thead/tbody continuam com seus display padrão).
   Feito em CSS em vez de embrulhar as 12 tabelas do app numa div. */
.inventory-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1rem;
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.inventory-table th {
  text-align: left; padding: 0.6rem; font-size: 0.78rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--text-muted); border-bottom: 1px solid var(--border);
}
.inventory-table td { text-align: left; padding: 0.65rem 0.6rem; border-bottom: 1px solid var(--border); font-size: 0.92rem; }
.inventory-table tr:hover td { background: var(--bg-subtle); }
.inventory-table .thumb { width: 32px; vertical-align: middle; margin-right: 0.5rem; border-radius: 4px; }
.qty-input, .price-input { width: 90px; margin-top: 0; }

.inventory-search { display: flex; gap: 0.6rem; margin-bottom: 1.25rem; }
.inventory-search input { margin: 0; }

/* ---------- Storefront (branded per-store) ---------- */
body.storefront { background: var(--bg); }
.storefront-header {
  background: linear-gradient(135deg, var(--store-primary), color-mix(in srgb, var(--store-primary) 70%, black));
  color: var(--store-accent);
  padding: 2.75rem 1.5rem 3.25rem;
  text-align: center;
}
.storefront-header h1 { margin: 0.6rem 0 0; font-size: 1.9rem; }
.storefront-header p { color: color-mix(in srgb, var(--store-accent) 80%, transparent); }
/* Same defect as the cart/profile chips above, in its other form: a link here
   kept the global link colour (a blue tuned for the page background) while
   sitting on the merchant's own header colour, so a dark store rendered dark
   blue on near-black. Header links follow the header's declared foreground -
   which is what --store-accent is FOR - and keep the underline so they still
   read as links without depending on colour alone. */
.storefront-header a {
  color: var(--store-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.storefront-header a:hover { color: color-mix(in srgb, var(--store-accent) 80%, transparent); }
/* ...except the icon chips, which are surfaces of their own and must keep the
   page's text colour against their own background. */
.storefront-header a.cart-icon-link { color: var(--text); text-decoration: none; }
.storefront-logo { max-height: 64px; border-radius: var(--radius-sm); }

.product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 1.1rem; margin-top: 1.5rem; }
.product-card {
  display: block;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 1.1rem;
  text-align: center;
  text-decoration: none;
  color: inherit;
  transition: box-shadow 0.15s ease, transform 0.1s ease;
}
.product-card:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
.product-card img { max-width: 100%; border-radius: var(--radius-sm); margin-bottom: 0.5rem; }
/* Uses a text token, not --store-primary - a merchant's branding color has
   no guaranteed contrast against the page's own background (it's chosen to
   pair with a button, not to stand alone as body text) - found by actually
   looking at a storefront with the schema's default #1c1c1c primary color
   in dark mode, where the price was nearly invisible. */
.product-price { font-weight: 750; color: var(--text); font-size: 1.05rem; margin: 0.3rem 0; }
.product-card form { margin-top: 0.6rem; }
.product-card button { width: 100%; }

/* Generic drag-and-drop file dropzone - originally built for CSV bulk
   import (templates/custom_products.html), reused as-is for the image
   upload widget (static/js/image_upload.js) since the visual language
   (dashed border, hover/active highlight) is identical for any single-
   file drop target. */
.dropzone {
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  padding: 2rem 1rem;
  text-align: center;
  cursor: pointer;
  color: var(--text-muted);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.dropzone:hover, .dropzone-active {
  border-color: var(--primary);
  background: color-mix(in srgb, var(--primary) 6%, transparent);
}
.csv-import-progress { margin-top: 1rem; }
.csv-import-bar { height: 8px; border-radius: 999px; background: var(--bg-subtle); overflow: hidden; }
.csv-import-bar-fill { height: 100%; width: 0%; background: var(--primary); transition: width 0.15s ease; }

/* Image dropzone (static/js/image_upload.js) - store logo / custom product
   photo. The dropzone itself doubles as the preview frame once a file is
   chosen (or an existing image is already set) - a data URI shown in the
   same box that says "drop here" when empty, not two separate elements. */
.image-dropzone { padding: 1rem; min-height: 120px; display: flex; align-items: center; justify-content: center; }
.dropzone-preview-img { max-width: 100%; max-height: 160px; border-radius: var(--radius-sm); }
.dropzone-hint { margin: 0; font-size: 0.9rem; }

/* Non-blocking toast notifications - one per CSV row imported, so a
   multi-row import doesn't require dismissing a native alert() per row */
.toast-container {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.toast {
  background: var(--success);
  color: #fff;
  padding: 0.6rem 1rem;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  font-size: 0.9rem;
  font-weight: 600;
  animation: toast-in 0.15s ease;
}
.toast-error { background: var(--danger); }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Store style screen (templates/store_settings.html) - live preview mockup
   of the storefront header/card so a lojista sees the effect of a color/
   logo/name change before saving, without needing to open the real public
   page in another tab. */
.style-editor { display: flex; gap: 1.5rem; flex-wrap: wrap; align-items: flex-start; }
.style-editor .card { flex: 1; min-width: 300px; }
.style-preview {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: background-color 0.15s ease;
}
.style-preview-header {
  padding: 1.25rem 1rem;
  text-align: center;
  color: #fff;
  transition: background-color 0.15s ease;
}
.style-preview-header img { max-height: 40px; display: block; margin: 0 auto 0.4rem; border-radius: 4px; }
.style-preview-body { padding: 1.25rem; }
.style-preview-card-mock {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1rem;
  text-align: center;
}
.style-preview-price { font-weight: 750; font-size: 1.1rem; margin-bottom: 0.6rem; transition: color 0.15s ease; }
.style-preview-card-mock button { width: 100%; border: none; color: #fff; padding: 0.5rem; border-radius: var(--radius-sm); cursor: default; transition: background-color 0.15s ease; }

/* Promotional (compare-at) pricing - original price struck through, sale
   price in the store's accent color so it reads as "the deal" */
.price-was { text-decoration: line-through; color: var(--text-muted); margin-right: 0.4rem; }
.price-now { font-weight: 750; color: var(--danger); }

/* Variant selector on a grouped card product page (Mox Land/Meruru-style) */
.variant-list { display: flex; flex-direction: column; gap: 0.6rem; margin: 1rem 0; }
.variant-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.75rem 1rem; border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.variant-row.out-of-stock { opacity: 0.55; }
.variant-badges { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-top: 0.25rem; }
.variant-badge {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  padding: 0.15rem 0.5rem; border-radius: 999px; background: var(--bg-subtle); color: var(--text-muted);
}

.cart-row { display: flex; align-items: center; gap: 0.9rem; padding: 0.7rem 0; border-bottom: 1px solid var(--border); }
.cart-row:last-child { border-bottom: none; }
/* Caixa FIXA: a foto de uma carta é retrato e a de um produto pode ter
   qualquer proporção - só `width` deixava cada linha do carrinho com uma
   altura diferente. `object-fit: contain` mostra a imagem inteira em vez de
   cortá-la, e `flex-shrink: 0` impede que ela seja esmagada num celular. */
.cart-row .thumb {
  width: 48px; height: 48px; flex-shrink: 0;
  object-fit: contain; border-radius: var(--radius-sm); background: var(--bg-subtle);
}
.cart-row .thumb-empty { display: block; border: 1px solid var(--border); }

/* Página de produto (card_product.html / custom_product_page.html).
   Estava duplicada inline nos dois templates e só limitava a LARGURA, o que
   funciona para carta e falha para o resto: medido, uma foto 1:4 renderizava
   280x1120px e empurrava a página inteira para baixo, enquanto uma 4:1 virava
   uma tira de 70px. O teto de altura resolve o caso ruim; `object-fit:
   contain` mostra a imagem inteira dentro da caixa em vez de cortá-la - e sem
   ele o teto DEFORMARIA a foto, que seria pior que o problema original.
   420px passa folgado dos 390px de uma carta, então carta não muda. */
.product-detail { display: flex; gap: 2rem; flex-wrap: wrap; }
.product-detail img {
  max-width: 280px; width: 100%; max-height: 420px;
  object-fit: contain; border-radius: var(--radius);
}
.product-detail-info { flex: 1; min-width: 280px; }
.cart-row-info { flex: 1; }
.cart-row-price { font-weight: 650; }
.cart-summary { margin-top: 1rem; }
.cart-total { font-size: 1.2rem; font-weight: 750; }

.site-footer { text-align: center; padding: 2rem 1.5rem; color: var(--text-muted); font-size: 0.85rem; }
.storefront-contact { margin-bottom: 1rem; }
.storefront-contact p { margin: 0.15rem 0; }
.legal-links { margin-top: 0.25rem; }
.legal-links a { color: var(--text-muted); text-decoration: underline; }

/* ---------- Redes sociais da loja no rodapé (migração 52) ----------
   Pastilha própria (--bg-subtle + --border + --text), NÃO --store-primary:
   a cor primária é escolhida pelo lojista, então um ícone tingido com ela
   pode cair em cima de si mesmo numa loja quase branca ou quase preta. É a
   mesma correção que os ícones de carrinho e perfil já receberam - ver
   info/BEAUTIFY.md §4, "na vitrine o contraste tem de ser autossuficiente".
   O hover também não pinta com --store-primary: o par que sobraria seria a cor
   do lojista contra --text, e não existe token de texto contrastante da marca
   para ancorar isso (--primary-contrast é do azul da plataforma, não da loja).
   Então o realce vem do que a plataforma controla, e o par continua medido. */
.storefront-social {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
}
.storefront-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 40px de alvo de toque: abaixo disso o dedo erra, e o rodapé é justamente
     onde os links ficam mais juntos. */
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.storefront-social a:hover,
.storefront-social a:focus-visible {
  background: var(--bg-elevated);
  border-color: var(--text-muted);
  color: var(--text);
}
.social-icon { display: block; }

/* Os campos em Configurações. Grade própria, e não a `.color-row` que o resto
   da página usa: aquela é um flex de uma linha só, pensado para dois ou três
   campos curtos, e com sete redes cada campo cabia ~90px - o suficiente para
   mostrar "https://www.face" e esconder o resto justamente do campo que o
   lojista precisa conferir. minmax(220px, 1fr) quebra em quantas linhas
   couberem e mantém a URL legível em qualquer largura, celular incluído. */
.social-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}
.social-grid input { width: 100%; }
/* O rótulo do campo: ícone e nome na mesma linha de base. */
.social-field-label { display: inline-flex; align-items: center; gap: 0.35rem; }

/* ---------- Legal pages (Terms / Privacy) ---------- */
.legal-doc { max-width: 760px; margin: 0 auto; line-height: 1.6; }
.legal-doc h2 { margin-top: 1.75rem; }
.legal-doc ul { padding-left: 1.25rem; }
.legal-doc li { margin-bottom: 0.4rem; }
.legal-notice {
  background: var(--warning-bg);
  color: var(--warning);
  border-radius: var(--radius-sm);
  padding: 0.85rem 1rem;
  font-size: 0.9rem;
  font-weight: 600;
}

.consent-checkbox { display: flex; align-items: flex-start; gap: 0.5rem; font-weight: 400; font-size: 0.88rem; }
.consent-checkbox input { width: auto; margin: 0.2rem 0 0; }

/* ---------- API docs code blocks ---------- */
.legal-doc code {
  background: var(--bg-subtle);
  padding: 0.15rem 0.4rem;
  border-radius: 4px;
  font-size: 0.85em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.legal-doc pre {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1rem;
  overflow-x: auto;
}
.legal-doc pre code { background: none; padding: 0; font-size: 0.85rem; }

/* ---------- Reports: stat tiles + chart (see dataviz skill guidance) ---------- */
:root {
  --chart-series: #2a78d6;
  --chart-series-dark: #3987e5;
  --chart-grid: var(--border);
}
:root[data-theme="dark"] { --chart-series: var(--chart-series-dark); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --chart-series: var(--chart-series-dark); }
}

.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
.stat-tile {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
  box-shadow: var(--shadow-sm);
}
.stat-tile .stat-label { color: var(--text-muted); font-size: 0.82rem; font-weight: 600; }
.stat-tile .stat-value { font-size: 1.6rem; font-weight: 700; margin-top: 0.2rem; letter-spacing: -0.01em; }

.range-picker { display: flex; gap: 0.5rem; margin-bottom: 1.25rem; }
.range-picker a {
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 600;
}
.range-picker a.active { background: var(--primary); color: #fff; border-color: var(--primary); }

.chart-wrap { position: relative; }
.chart-tooltip {
  position: absolute;
  background: var(--text);
  color: var(--bg-elevated);
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  font-size: 0.78rem;
  pointer-events: none;
  white-space: nowrap;
  transform: translate(-50%, -110%);
  opacity: 0;
  transition: opacity 0.1s ease;
  z-index: 5;
}
.chart-tooltip.visible { opacity: 1; }
.chart-bar { fill: var(--chart-series); rx: 4; }
.chart-bar:hover { opacity: 0.85; cursor: pointer; }
.chart-axis-label { fill: var(--muted, var(--text-muted)); font-size: 11px; }
.chart-gridline { stroke: var(--chart-grid); stroke-width: 1; }
/* Diverging profit chart (static/js/dre.js). The sign carries meaning here, so
   a loss gets its own colour - and the zero line is drawn stronger than the
   gridlines because it is the reference the whole chart is read against. */
.chart-bar-negative { fill: var(--danger); }
.chart-zeroline { stroke: var(--text-muted); stroke-width: 1.5; opacity: 0.55; }

/* ---------- Responsive ---------- */
/* ---- Landing page nav (templates/landing.html) ----
   Was inline flex with no wrap: brand on the left, 5 links + the theme toggle
   on the right totalling 443px, which overflowed a 390px phone by 176px. */
.landing-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  max-width: 1020px;
  margin: 0 auto 1.5rem;
}
.landing-brand {
  color: #fff;
  font-weight: 750;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.landing-nav-links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.25rem;
}
.landing-nav-links a { color: #fff; }

@media (max-width: 640px) {
  .main-content { padding: 1.25rem 1rem 3rem; }
  .topbar { padding: 0.7rem 1rem; }
  .color-row { flex-direction: column; }

  /* A rolagem interna da tabela agora vale em qualquer largura (ver
     .inventory-table acima). O que é específico de celular é o nowrap: sem ele
     uma tabela de 10 colunas numa tela de 390px quebra em uma palavra por
     linha, o que é pior de ler do que rolar. */
  .inventory-table { white-space: nowrap; }

  /* iOS Safari zooms the entire page when a focused input's font-size is under
     16px - and a zoomed page IS a page that scrolls sideways, which is the
     other half of the reported symptom. The base rule is 0.95rem (15.2px), so
     every form in the app triggered it on every tap. 16px only on small
     screens; the desktop sizing is unchanged. */
  input, select, textarea { font-size: 16px; }

  /* The two inline stock inputs are fixed at 90px, which is fine inside the
     scrolling table but leaves no room for the 16px text above. */
  .qty-input, .price-input { width: 84px; }

  /* On a phone the landing nav becomes two centred rows instead of trying to
     put a 5-link menu beside the brand. */
  .landing-nav { justify-content: center; }
  .landing-nav-links { justify-content: center; gap: 0.9rem; font-size: 0.92rem; }

  /* The rename to "Cards Realm Gestão de Lojas" made the brand long enough to
     wrap the sticky header onto four lines on a 390px screen, eating a third of
     the viewport on every page. Drop the suffix and tighten the nav; the mark
     plus "Cards Realm" is still unambiguous. */
  .topbar { flex-wrap: wrap; gap: 0.5rem; }
  .topbar .brand { font-size: 0.98rem; white-space: nowrap; }
  .brand-suffix { display: none; }
  .topbar nav { gap: 0.85rem; flex-wrap: wrap; }
  .topbar nav a, .topbar .user-name { font-size: 0.88rem; }
}

/* ---- Storefront browse navigation (templates/storefront_breadcrumb.html and
   the automatic per-game/per-type sections on storefront.html) ----
   Separate from .breadcrumb above, which is the merchant admin shell's trail:
   this one sits INSIDE the storefront's own page body and follows the store's
   branding (--store-primary), not the app's neutral admin theme. */
.storefront-breadcrumb {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin-bottom: 1rem;
}
.storefront-breadcrumb ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
}
/* The separator is generated rather than sitting in the markup, so screen
   readers announce the list structure instead of a run of stray slashes. */
.storefront-breadcrumb li + li::before {
  content: "/";
  color: var(--border);
  margin-right: 0.35rem;
}
.storefront-breadcrumb a { color: var(--text-muted); text-decoration: none; }
.storefront-breadcrumb a:hover { color: var(--store-primary, var(--primary)); text-decoration: underline; }
.storefront-breadcrumb [aria-current="page"] { color: var(--text); font-weight: 600; }

.store-sections { margin-bottom: 1.5rem; }
.store-sections .section-game + .section-game { margin-top: 0.75rem; }
.store-sections .section-game > a {
  font-weight: 700;
  text-decoration: none;
  color: var(--text);
}
.store-sections .section-game > a:hover { color: var(--store-primary, var(--primary)); }
.store-sections .section-types {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.store-sections .section-types a {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.8rem;
  color: var(--text-muted);
  text-decoration: none;
  background: var(--bg-subtle);
}
.store-sections .section-types a:hover {
  border-color: var(--store-primary, var(--primary));
  color: var(--store-primary, var(--primary));
}
.store-sections .section-types a.active {
  background: var(--store-primary, var(--primary));
  border-color: var(--store-primary, var(--primary));
  color: #fff;
}
.store-sections .section-count { color: var(--text-muted); font-weight: 400; font-size: 0.8rem; }

/* Cookie-consent banner (static/js/consent.js) - built in JS, not markup, so
   a storefront page only needs the one {% include %} in its <head>. z-index
   sits above .whatsapp-float (1000) because it must be dismissible without
   the chat button covering its buttons on a narrow screen. */
.cookie-consent {
  position: fixed;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  z-index: 1100;
  margin: 0 auto;
  max-width: 640px;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  justify-content: space-between;
  background: var(--bg-elevated);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1rem 1.25rem;
}
.cookie-consent p { margin: 0; font-size: 0.9rem; flex: 1; min-width: 220px; }
.cookie-consent a { color: var(--primary); }
.cookie-consent-actions { display: flex; gap: 0.5rem; }
.cookie-consent-actions button { margin: 0; white-space: nowrap; }

/* ==========================================================================
   PUBLIC / MARKETING PAGES
   Landing, planos, contato, canal de denúncias, status.

   Kept in one clearly-fenced block at the end of the file, and every selector
   is prefixed `mk-`, because these pages want a DIFFERENT visual register from
   the admin shell above: bigger type, more air, alternating section
   backgrounds, a display face for headlines. The admin app is a tool people
   use for hours and should stay quiet; this is a page that has about six
   seconds to explain what the product is.

   Visual reference is lojaintegrada.com.br, as asked: warm off-white ground,
   one deep brand colour, one bright accent, generous rounding, a highlighted
   plan card. It reuses the existing --primary/--danger tokens rather than
   introducing a second palette, so a rebrand still happens in one place.
   ========================================================================== */

:root {
  --mk-ink: #10233a;
  --mk-ink-soft: #4a5b70;
  --mk-cream: #f6f4ee;
  --mk-surface: #ffffff;
  --mk-line: #e4e0d6;
  --mk-accent: var(--primary);
  --mk-radius: 18px;
  --mk-max: 1140px;
  /* A dark surface used as a BACKGROUND (announcement bar, footer, the
     featured plan card). Deliberately its own token instead of reusing
     --mk-ink: that one is a TEXT colour and therefore inverts in dark mode, so
     anything painting a background with it turned light-on-light and became
     unreadable - which is exactly what happened to the announcement bar. This
     one stays dark in both themes, because a dark panel is dark in both. */
  --mk-deep: #10233a;
  --mk-on-deep: #ffffff;
}
:root[data-theme="dark"], html[data-theme="dark"] {
  --mk-deep: #0b1017;
  --mk-ink: #eef2f7;
  --mk-ink-soft: #a8b6c6;
  --mk-cream: #141922;
  --mk-surface: #1b2230;
  --mk-line: #2c3646;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --mk-deep: #0b1017;
    --mk-ink: #eef2f7;
    --mk-ink-soft: #a8b6c6;
    --mk-cream: #141922;
    --mk-surface: #1b2230;
    --mk-line: #2c3646;
  }
}

body.marketing { background: var(--mk-cream); color: var(--mk-ink); }
.mk-wrap { max-width: var(--mk-max); margin: 0 auto; padding: 0 1.25rem; }

/* A section is the unit of rhythm on these pages: alternating ground colour is
   what stops a long landing page reading as one undifferentiated scroll. */
.mk-section { padding: 4.5rem 0; }
.mk-section.alt { background: var(--mk-surface); }
.mk-section > .mk-wrap > h2 {
  font-size: clamp(1.7rem, 3.4vw, 2.6rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
  color: var(--mk-ink);
}
.mk-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--mk-ink-soft);
  margin: 0 0 0.6rem;
}
.mk-lead { font-size: 1.05rem; line-height: 1.6; color: var(--mk-ink-soft); max-width: 58ch; }
.mk-center { text-align: center; }
.mk-center .mk-lead { margin-left: auto; margin-right: auto; }

/* Announcement bar - the reference site's, and a genuinely useful place to put
   the one thing every visitor should know before scrolling. */
.mk-announce {
  background: var(--mk-deep);
  color: var(--mk-on-deep);
  text-align: center;
  padding: 0.6rem 1rem;
  font-size: 0.88rem;
}
.mk-announce a { color: var(--mk-on-deep); text-decoration: underline; }

.mk-nav {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--mk-cream) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--mk-line);
}
.mk-nav-inner { display: flex; align-items: center; gap: 1.25rem; padding: 0.85rem 1.25rem; max-width: var(--mk-max); margin: 0 auto; }
.mk-nav-links { display: flex; align-items: center; gap: 1.1rem; margin-left: auto; flex-wrap: wrap; }
.mk-nav-links a { color: var(--mk-ink-soft); text-decoration: none; font-size: 0.92rem; font-weight: 500; }
.mk-nav-links a:hover { color: var(--mk-ink); }
.mk-brand { display: flex; align-items: center; gap: 0.55rem; font-weight: 700; color: var(--mk-ink); text-decoration: none; }

/* --- Menu do topo no celular (static/js/mk_nav.js) --------------------------
   São 8 itens com flex-wrap: numa tela de 390px o header quebrava em várias
   linhas e comia boa parte da primeira dobra, em toda página pública. Abaixo
   de 861px os links viram painel; o botão de tema fica fora dele, porque
   trocar o tema é um toque só. O CSS lê `aria-expanded` em vez de uma classe,
   para não existir um segundo estado capaz de discordar do que o leitor de
   tela anuncia. */
.mk-nav-actions { display: flex; align-items: center; gap: 0.5rem; }
.mk-nav-toggle {
  display: none; width: 42px; height: 42px; padding: 0;
  align-items: center; justify-content: center;
  background: var(--mk-surface); border: 1px solid var(--mk-line);
  border-radius: 10px; cursor: pointer;
}
/* O traço do meio é o próprio elemento; os de cima e de baixo são pseudos. */
/* Os traços de cima e de baixo são pseudo-elementos posicionados por `top`.
   Deslocá-los por `transform` não serviria: virar X exige rotacionar, e a
   rotação substituiria o deslocamento - foi assim que o ícone aberto virou
   um ">" em vez de um X. */
.mk-burger { position: relative; display: block; width: 18px; height: 2px;
  border-radius: 2px; background: var(--mk-ink); transition: background 0.18s ease; }
.mk-burger::before, .mk-burger::after {
  content: ""; position: absolute; left: 0; width: 18px; height: 2px;
  border-radius: 2px; background: var(--mk-ink); transition: top 0.18s ease, transform 0.18s ease;
}
.mk-burger::before { top: -6px; }
.mk-burger::after { top: 6px; }
.mk-nav-toggle[aria-expanded="true"] .mk-burger { background: transparent; }
.mk-nav-toggle[aria-expanded="true"] .mk-burger::before { top: 0; transform: rotate(45deg); }
.mk-nav-toggle[aria-expanded="true"] .mk-burger::after { top: 0; transform: rotate(-45deg); }

@media (max-width: 860px) {
  .mk-nav-toggle { display: inline-flex; }
  .mk-nav-inner { gap: 0.75rem; }
  .mk-nav-links {
    position: absolute; left: 0; right: 0; top: 100%;
    display: none; flex-direction: column; flex-wrap: nowrap;
    align-items: stretch; gap: 0;
    margin-left: 0; padding: 0.4rem 1.25rem 1rem;
    background: var(--mk-cream); border-bottom: 1px solid var(--mk-line);
    /* O painel é a única coisa que rola se a lista crescer - a página atrás
       dele não pode ganhar barra por causa do menu. */
    max-height: calc(100vh - 100%); overflow-y: auto;
  }
  .mk-nav-links[data-open] { display: flex; }
  .mk-nav-links a {
    padding: 0.8rem 0.2rem; font-size: 1rem;
    border-bottom: 1px solid var(--mk-line);
  }
  .mk-nav-links a:last-child { border-bottom: 0; }
  .mk-nav-cta { margin-top: 0.8rem; text-align: center; }
}

.mk-hero { padding: 4rem 0 3.5rem; }
.mk-hero h1 {
  font-size: clamp(2.1rem, 5.6vw, 3.9rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  margin: 0 0 1rem;
  color: var(--mk-ink);
}
/* The reference's italic accent on the second half of the headline - it makes
   one phrase the promise instead of the whole sentence competing with itself. */
.mk-hero h1 em { font-style: italic; color: var(--mk-accent); }
.mk-hero .mk-lead { font-size: 1.15rem; }

.mk-cta-row { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.75rem; }
.mk-center .mk-cta-row { justify-content: center; }
.mk-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.85rem 1.6rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: 1rem;
  text-decoration: none;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.1s ease, box-shadow 0.15s ease, background 0.15s ease;
  width: auto;
}
.mk-btn:hover { transform: translateY(-1px); }
.mk-btn-primary { background: var(--mk-accent); color: #fff; box-shadow: 0 6px 20px -8px var(--mk-accent); }
/* Um botão dentro de um container que estiliza `a` perdia a PRÓPRIA cor:
   `.mk-nav-links a` (0,1,1) vence `.mk-btn-primary` (0,1,0), então o "Criar
   loja grátis" do topo saía com o cinza dos links sobre o azul do botão -
   1,35:1 medido, praticamente ilegível. Ancorar no elemento faz o componente
   defender a cor dele em qualquer container, agora e no próximo que aparecer. */
a.mk-btn-primary { color: #fff; }
a.mk-btn-ghost { color: var(--mk-ink); }
.mk-btn-ghost { background: transparent; color: var(--mk-ink); border-color: var(--mk-line); }
.mk-btn-ghost:hover { border-color: var(--mk-ink); }
.mk-btn-dark { background: var(--mk-deep); color: var(--mk-on-deep); }
.mk-note { font-size: 0.85rem; color: var(--mk-ink-soft); margin-top: 0.75rem; }

/* Feature grid. `align-items: start` so a card with two lines of copy does not
   stretch to match a card with five. */
.mk-grid { display: grid; gap: 1.1rem; align-items: start; }
.mk-grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.mk-grid-4 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.mk-card {
  background: var(--mk-surface);
  border: 1px solid var(--mk-line);
  border-radius: var(--mk-radius);
  padding: 1.4rem;
}
.mk-section.alt .mk-card { background: var(--mk-cream); }
.mk-card h3 { margin: 0 0 0.4rem; font-size: 1.05rem; color: var(--mk-ink); }
.mk-card p { margin: 0; color: var(--mk-ink-soft); font-size: 0.93rem; line-height: 1.55; }
.mk-card-icon {
  width: 38px; height: 38px; border-radius: 11px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--mk-accent) 14%, transparent);
  color: var(--mk-accent);
  font-size: 1.1rem; font-weight: 700;
  margin-bottom: 0.8rem;
}

/* Plans. The highlighted card is raised and inverted rather than merely
   outlined: on a four-card row a border alone is not a recommendation. */
.mk-plans { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); align-items: stretch; }
.mk-plan {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--mk-surface);
  border: 1px solid var(--mk-line);
  border-radius: var(--mk-radius);
  padding: 1.6rem 1.4rem;
}
.mk-plan.featured {
  background: var(--mk-deep);
  border-color: var(--mk-deep);
  box-shadow: 0 24px 50px -28px rgba(0,0,0,0.55);
}
.mk-plan.featured, .mk-plan.featured h3, .mk-plan.featured .mk-price { color: var(--mk-on-deep); }
.mk-plan.featured .mk-plan-tagline, .mk-plan.featured li { color: color-mix(in srgb, var(--mk-on-deep) 78%, transparent); }
.mk-plan-badge {
  position: absolute; top: -0.75rem; left: 50%; transform: translateX(-50%);
  background: var(--mk-accent); color: #fff;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em;
  padding: 0.3rem 0.8rem; border-radius: 999px; white-space: nowrap;
}
.mk-plan h3 { margin: 0 0 0.25rem; font-size: 1.35rem; }
.mk-plan-tagline { font-size: 0.86rem; color: var(--mk-ink-soft); min-height: 2.6em; margin: 0 0 0.9rem; line-height: 1.35; }
.mk-price { font-size: 2.6rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1; }
.mk-price small { font-size: 0.9rem; font-weight: 500; color: var(--mk-ink-soft); }
.mk-plan.featured .mk-price small { color: color-mix(in srgb, var(--mk-on-deep) 70%, transparent); }
.mk-plan ul { list-style: none; padding: 0; margin: 1.1rem 0 0; display: grid; gap: 0.45rem; }
.mk-plan li { font-size: 0.9rem; color: var(--mk-ink-soft); padding-left: 1.4rem; position: relative; line-height: 1.45; }
.mk-plan li::before { content: "✓"; position: absolute; left: 0; color: var(--mk-accent); font-weight: 700; }
.mk-plan .mk-btn { margin-top: 1.2rem; width: 100%; }
/* The CTA sits at the same height on every card even when the bullet lists
   differ in length - a ragged row of buttons reads as an unfinished page. */
.mk-plan-foot { margin-top: auto; }

/* Comparison table - the "todas as features" ask. Scrolls inside its own card
   on a phone, same rule as .inventory-table (see CLAUDE.md's Mobile layout). */
/* `display:block` fazia a tabela ignorar o width:100% e encolher até o
   conteúdo - a rolagem horizontal mora no invólucro (.mk-compare-wrap), que
   é o que permite ocupar a largura toda no desktop e ainda rolar no celular. */
.mk-compare-wrap { overflow-x: auto; }
.mk-compare { width: 100%; border-collapse: collapse; table-layout: auto; }
/* Sem um teto na coluna de rótulo, o layout automático dava metade da tabela a
   ela e amontoava os planos à direita - a tabela ocupava a largura sem usá-la.
   As colunas de plano dividem o resto por igual. */
.mk-compare thead th:first-child, .mk-compare tbody th { width: 34%; }
.mk-compare thead th:not(:first-child) { width: 16.5%; }
.mk-compare th, .mk-compare td { padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--mk-line); text-align: left; font-size: 0.9rem; white-space: nowrap; }
.mk-compare thead th { color: var(--mk-ink); font-weight: 700; }
.mk-compare td:not(:first-child), .mk-compare th:not(:first-child) { text-align: center; }
.mk-compare tbody th { font-weight: 500; color: var(--mk-ink-soft); white-space: normal; min-width: 15rem; }
.mk-compare .yes { color: var(--mk-accent); font-weight: 700; }
.mk-compare .no { color: var(--mk-ink-soft); opacity: 0.5; }
.mk-compare tr.group th { background: var(--mk-cream); font-weight: 700; color: var(--mk-ink); text-transform: uppercase; font-size: 0.75rem; letter-spacing: 0.08em; }
.mk-section.alt .mk-compare tr.group th { background: var(--mk-surface); }

/* Forms on the public pages (contato, denúncia) */
.mk-form { display: grid; gap: 0.9rem; max-width: 640px; }
.mk-form label { font-weight: 600; font-size: 0.9rem; color: var(--mk-ink); display: grid; gap: 0.35rem; }
.mk-form input, .mk-form select, .mk-form textarea {
  background: var(--mk-surface); border: 1px solid var(--mk-line); color: var(--mk-ink);
  border-radius: 10px; padding: 0.7rem 0.85rem; font-size: 1rem; font-weight: 400; width: 100%;
}
.mk-form-row { display: grid; gap: 0.9rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.mk-form-note { font-size: 0.85rem; color: var(--mk-ink-soft); }

/* FAQ */
.mk-faq { display: grid; gap: 0.6rem; max-width: 780px; margin: 0 auto; }
.mk-faq details { background: var(--mk-surface); border: 1px solid var(--mk-line); border-radius: 12px; padding: 0.9rem 1.1rem; }
.mk-section.alt .mk-faq details { background: var(--mk-cream); }
.mk-faq summary { font-weight: 600; cursor: pointer; color: var(--mk-ink); }
.mk-faq p { margin: 0.7rem 0 0; color: var(--mk-ink-soft); font-size: 0.93rem; line-height: 1.6; }

/* Status page */
.mk-status-banner { border-radius: var(--mk-radius); padding: 1.4rem 1.6rem; margin-bottom: 1.5rem; border: 1px solid var(--mk-line); background: var(--mk-surface); }
.mk-status-banner h2 { margin: 0.2rem 0 0.3rem; font-size: 1.45rem; }
.mk-status-list { display: grid; gap: 0.6rem; }
.mk-status-row { display: flex; align-items: center; gap: 0.9rem; flex-wrap: wrap; background: var(--mk-surface); border: 1px solid var(--mk-line); border-radius: 12px; padding: 0.85rem 1.1rem; }
.mk-status-row .name { font-weight: 600; color: var(--mk-ink); }
.mk-status-row .detail { color: var(--mk-ink-soft); font-size: 0.88rem; margin-left: auto; }
.mk-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.mk-dot.operational { background: #1faa62; }
.mk-dot.degraded { background: #e2a230; }
.mk-dot.down { background: var(--danger); }
.mk-dot.not_configured { background: var(--mk-ink-soft); opacity: 0.45; }

/* Footer */
.mk-footer { background: var(--mk-deep); color: color-mix(in srgb, var(--mk-on-deep) 72%, transparent); padding: 3.5rem 0 1.5rem; }
.mk-footer a { color: color-mix(in srgb, #ffffff 78%, transparent); text-decoration: none; font-size: 0.9rem; }
.mk-footer a:hover { color: #fff; text-decoration: underline; }
.mk-footer-cols { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.mk-footer h4 { color: #fff; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.1em; margin: 0 0 0.9rem; }
.mk-footer ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.55rem; }
.mk-social { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.4rem; }
.mk-social a {
  width: 38px; height: 38px; border-radius: 10px;
  display: grid; place-items: center;
  background: rgba(255,255,255,0.09);
}
.mk-social a:hover { background: rgba(255,255,255,0.2); }
.mk-social svg { width: 18px; height: 18px; fill: #fff; display: block; }
.mk-footer-bottom {
  margin-top: 2.5rem; padding-top: 1.4rem;
  border-top: 1px solid rgba(255,255,255,0.14);
  display: flex; flex-wrap: wrap; gap: 0.6rem 1.1rem; align-items: center;
  font-size: 0.83rem;
}
.mk-footer-legal { display: flex; flex-wrap: wrap; gap: 0.6rem 1.1rem; }
.mk-footer-company { margin-left: auto; text-align: right; line-height: 1.5; opacity: 0.75; }

/* Este rodapé serve os DOIS shells (ver templates/base.html), e cada um tem a
   sua própria coluna de conteúdo: 1140px no site público, 1020px no painel.
   Medido: sem isto o primeiro link do rodapé começava 64px à ESQUERDA do
   conteúdo que a pessoa acabou de ler - a borda esquerda desalinhada é
   exatamente o que o olho percebe. Casa com .main-content (max-width e padding
   iguais aos da linha 249), e não com a topbar, que é full-bleed: seguir a
   topbar espalharia as cinco colunas por 1520px numa tela larga enquanto o
   conteúdo ocupa 972. `body:not(.marketing)` porque é o site público que
   carrega a classe - o painel não marca nada. */
body:not(.marketing) .mk-footer .mk-wrap { max-width: 1020px; padding: 0 1.5rem; }

/* No MODO ESCURO do painel o rodapé sumia como banda: --bg é #0d0f14 e
   --mk-deep é #0b1017, ou seja, a mesma cor a olho nu. No site público isso não
   acontece porque ali o fundo é --mk-cream (#141922), mais claro que o rodapé.
   A borda é a mesma que a topbar já usa (var(--border)), então a separação
   segue o tema em vez de ser um cinza fixo que só serve para um dos dois. */
body:not(.marketing) .mk-footer { border-top: 1px solid var(--border); }

@media (max-width: 640px) {
  .mk-section { padding: 3rem 0; }
  .mk-hero { padding: 2.5rem 0; }
  .mk-btn { width: 100%; }
  .mk-footer-company { margin-left: 0; text-align: left; }
  .mk-nav-links { gap: 0.75rem; }
  .mk-nav-links a { font-size: 0.85rem; }
}

/* Hex code beside each colour picker (static/js/color_hex.js). Monospace and
   narrow: it holds exactly "#1c1c1c" and a proportional face makes a hex code
   noticeably harder to read back. */
.hex-input {
  width: 8.5rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  text-transform: lowercase;
  margin-top: 0.35rem;
}
.hex-input:invalid { border-color: var(--danger); }

/* Global failure banner (static/js/fetch_guard.js). The last-resort surface
   for an async handler that blew up on a page with no toast container - it
   must be visible without the page having prepared anything for it, hence
   fixed positioning and its own colours rather than a component class. */
.erp-global-error {
  position: fixed;
  left: 50%;
  top: 1rem;
  transform: translateX(-50%);
  z-index: 9999;
  max-width: min(92vw, 520px);
  background: var(--danger);
  color: #fff;
  padding: 0.75rem 1.1rem;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  font-size: 0.92rem;
  font-weight: 550;
  text-align: center;
}

/* Uploaded platform logo (/admin/site) standing in for the "CR" mark. Height
   is capped rather than the width, so a wide wordmark and a square icon both
   sit on the same header line without either one changing its height. */
.brand-logo {
  height: 34px;
  width: auto;
  max-width: 220px;
  display: block;
  object-fit: contain;
}
@media (max-width: 640px) { .brand-logo { height: 26px; max-width: 150px; } }
