/* ============================================================================
   dashboard.css — the Fitox store dashboard, in the light language.

   This replaces the Obsidian theme the dashboard shipped with (theme.css,
   deleted) and the ~14KB of inline CSS every page carried of its own. It is the
   SAME language as the admin portal and the app: the token block and the
   furniture below were lifted verbatim from fitox-admin/admin.css rather than
   retyped, because two surfaces meant to look alike should never disagree
   because somebody transcribed a hex.

   MASTER DOC: fitox-admin/styleguide.html. If a value here disagrees with the
   styleguide, the styleguide is right and this file is a bug.

   WHO THIS IS FOR, and why it is not the admin. The admin is ours; this is a
   PARTNER'S workspace — the store owner signs in with an API key, and the
   things on screen are their products, their credits and their money. So the
   voice is plainer, destructive actions are slower, and nothing assumes the
   reader knows how Fitox is built.

   RESPONSIVE. The old dashboard had a 220px sidebar pinned at every width and
   no breakpoint anywhere: on a phone it sat on top of the content. Here the
   rail is a rail at >=1024px and a drawer behind a top bar below it, and every
   table becomes a stack of labelled records under 760px — same markup, only
   the reading direction changes.
   ========================================================================== */

@layer base {
  *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
}

:root {
  color-scheme: only light;

  /* ---- GROUND & INK ---------------------------------------------------- */
  --bg:     #ededed;   /* the page */
  --card:   #e3e3e1;   /* an inset ON the page: table heads, sub-panels */
  --raise:  #fdfdfd;   /* a plate lifted OFF the page: every card */
  --ink:    #141412;
  --ink-2:  #57574f;   /* working ink: labels, glyphs, table cells */
  --dim:    #8a8a86;   /* decorative and switched-off ink only */
  --dim-2:  #6e6e69;   /* 4.5:1 — every quiet line a human must READ */
  --mute:   #b4b4ad;
  --on-ink: var(--raise);
  --ink-busy: #2a2a26;
  --ink-rgb: 20, 20, 18;
  --raise-rgb: 253, 253, 253;

  --line:        #d6d6d2;
  --line-soft:   #dcdcd7;
  --line-strong: #c6c6c0;
  --line-hover:  #a9a9a2;

  /* ---- SEMANTIC -------------------------------------------------------- */
  --bad:   #9a2f2f;
  --warn:  #9a6b1f;
  --ok:    #1c7c4a;
  --spark: #ac671a;   /* the bronze — AI, and the portal's accent */
  /* The series set. These are the same ten hues admin.js hands to Chart.js —
     named here so a KPI stripe and the chart underneath it can be the same
     colour without either one typing a hex. Muted on purpose: on a #ededed
     ground a saturated ramp reads as a warning, and most of these are not. */
  --blue: #2f5d8a;
  --teal: #1f6f6b;
  --plum: #6b4a7c;
  --clay: #a15c3e;
  --sage: #5d7a4a;

  --bad-wash:  #9a2f2f14;
  --warn-wash: #9a6b1f14;
  --ok-wash:   #1c7c4a14;
  --spark-wash:#ac671a14;

  /* ---- THE GOLD -------------------------------------------------------- */
  /* The CTA metal, static: the shipped element's ramp and ink, without its two
     animation loops. An admin has a Save button on every card; a glare cycle on
     each of them would be a fairground. --gold-lo is the AA floor for the ink,
     not a taste value — keep it above #a07b3e. */
  --gold-hi:  #d6b67d;
  --gold-mid: #bd9855;
  --gold-lo:  #a98444;
  --gold-ink: #2e2009;
  --gold-angle: 150deg;

  /* ---- TYPE. One scale, two faces -------------------------------------- */
  --font-body: "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-head: "Barlow Condensed", "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace;

  --fs-micro:    10px;
  --fs-kicker:   11px;
  --fs-caption:  12px;
  --fs-body:     13px;
  --fs-emph:     14px;
  --fs-input:    15px;
  --fs-label:    17px;
  --fs-title:    20px;
  --fs-title-lg: 22px;
  --fs-headline: 25px;
  --fs-display:  30px;

  /* ---- CONTROLS -------------------------------------------------------- */
  --ctl-xs:   30px;
  --ctl-chip: 36px;
  --ctl-md:   40px;   /* the admin's working height: input, button, select */

  /* ---- RADIUS ---------------------------------------------------------- */
  --r-xs:   6px;
  --r-sm:   9px;
  --r-md:  12px;
  --r-lg:  14px;
  --r-card:16px;
  --r-xl:  20px;
  --r-pill:999px;

  /* ---- ELEVATION ------------------------------------------------------- */
  --shadow-1: 0 1px 2px rgba(var(--ink-rgb), .05);
  --shadow-2: 0 8px 18px -5px rgba(var(--ink-rgb), .18), 0 3px 7px rgba(var(--ink-rgb), .07);
  --shadow-3: 0 10px 26px -12px rgba(var(--ink-rgb), .35);

  /* ---- SPACING --------------------------------------------------------- */
  --gap-sm:   6px;
  --gap:     10px;
  --gap-lg:  14px;
  --gap-edge:18px;
  --sect:    28px;

  /* ---- SHELL GEOMETRY -------------------------------------------------- */
  --side-w:  236px;
  --bar-h:   58px;
  --page-max:1280px;
}

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.5;
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
}

/* The dashboard is plain JS — no Alpine, so no x-cloak. `hidden` is the only
   thing that hides a block here, and it must beat display:flex/grid. */
[hidden] { display: none !important; }

::selection { background: rgba(var(--ink-rgb), .12); }

:where(a) { color: inherit; text-decoration: none; }

:where(button, input, select, textarea) { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--spark);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.num  { font-variant-numeric: tabular-nums; }

/* ============================================================================
   1 · THE SHELL
   ========================================================================== */

.shell { min-height: 100dvh; }

/* ---- the rail / drawer ---------------------------------------------------
   One element, two lives. At >=1024px it is a fixed column and the main
   content is inset by its width. Below that it leaves the flow entirely and
   slides in over the page from the left, behind a scrim. */
.rail {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--side-w);
  z-index: 60;
  display: flex;
  flex-direction: column;
  background: var(--raise);
  border-right: 1px solid var(--line);
}

/* ---- the wordmark ------------------------------------------------------
   The mark is drawn geometry (logo.svg — the brand master), so it is sized by
   HEIGHT and never by a font size: the lockup is portrait, and matching it to a
   cap-height would shrink it to nothing beside a 22px heading. `admin` sits
   beside it as a wordlabel in the heading face — it is a label on the portal,
   not a second line of the logo, so it never touches the mark's own spacing. */
.brandmark { display: block; width: auto; flex: none; }
.brandmark.lg { height: 72px; }
.brandmark.md { height: 46px; }
.brandmark.sm { height: 32px; }

.brandlabel {
  font-family: var(--font-head);
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--dim-2);
  line-height: 1;
}

.rail-brand {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 20px var(--gap-edge) 18px;
  flex: none;
}
.rail-brand span {
  font-family: var(--font-head);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--dim-2);
  line-height: 1;
}
.rail-brand:hover span { color: var(--ink-2); }

.rail-scroll {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 10px 10px;
}

.rail-group { margin-bottom: 14px; }
.rail-group > h6 {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--dim);
  padding: 8px;
}

.rail-link {
  display: flex;
  align-items: center;
  gap: 10px;
  height: var(--ctl-chip);
  padding: 0 8px;
  border-radius: var(--r-md);
  color: var(--ink-2);
  font-size: var(--fs-emph);
  transition: background .14s, color .14s;
}
.rail-link svg { width: 18px; height: 18px; flex: none; color: var(--dim); transition: color .14s; }
.rail-link .tail { margin-left: auto; color: var(--mute); font-size: var(--fs-micro); }
.rail-link:hover { background: var(--card); color: var(--ink); }
.rail-link:hover svg { color: var(--ink-2); }
.rail-link[aria-current="page"] {
  background: var(--ink);
  color: var(--on-ink);
  font-weight: 600;
}
.rail-link[aria-current="page"] svg,
.rail-link[aria-current="page"] .tail { color: var(--on-ink); opacity: .85; }

.rail-foot {
  flex: none;
  border-top: 1px solid var(--line-soft);
  padding: 10px;
}

/* ---- the mobile bar ---------------------------------------------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: none;
  align-items: center;
  gap: var(--gap);
  height: var(--bar-h);
  padding: 0 var(--gap-edge);
  background: rgba(var(--raise-rgb), .88);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.topbar-brand { display: flex; align-items: center; flex: none; }
.topbar .here {
  font-family: var(--font-head);
  font-size: var(--fs-emph);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--dim-2);
  line-height: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topbar .spacer { margin-left: auto; }

.burger {
  display: grid;
  place-items: center;
  width: var(--ctl-xs);
  height: var(--ctl-xs);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--raise);
  cursor: pointer;
  flex: none;
}
.burger svg { width: 16px; height: 16px; }

.scrim {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(var(--ink-rgb), .38);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  display: none;
}

/* ---- the page ---------------------------------------------------------- */
.main {
  padding: 26px var(--gap-edge) 72px;
  margin-left: var(--side-w);
}
.main > .inner { max-width: var(--page-max); }
.main.narrow > .inner { max-width: 880px; }

@media (max-width: 1023px) {
  .rail {
    transform: translateX(-100%);
    transition: transform .22s cubic-bezier(.2, .7, .2, 1);
    box-shadow: var(--shadow-3);
    width: min(var(--side-w), 82vw);
  }
  .shell[data-drawer="open"] .rail { transform: none; }
  .shell[data-drawer="open"] .scrim { display: block; }
  .topbar { display: flex; }
  .main { margin-left: 0; padding: 20px 14px 64px; }
}
@media (prefers-reduced-motion: reduce) {
  .rail { transition: none; }
}

/* ---- page head --------------------------------------------------------- */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--gap-lg);
  flex-wrap: wrap;
  margin-bottom: var(--gap-lg);
}
.page-head .acts {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  flex-wrap: wrap;
}
.kicker {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 5px;
}
h1.page-title {
  font-family: var(--font-head);
  font-size: var(--fs-display);
  font-weight: 700;
  letter-spacing: -.005em;
  line-height: 1.05;
}
.lede {
  color: var(--dim-2);
  max-width: 78ch;
  margin-top: 7px;
  line-height: 1.6;
}
.lede a { text-decoration: underline; text-underline-offset: 2px; }
.lede a:hover { color: var(--ink); }

.sect-title {
  font-family: var(--font-head);
  font-size: var(--fs-title);
  font-weight: 700;
  line-height: 1.2;
}

/* ============================================================================
   2 · LAYOUT HELPERS
   ========================================================================== */

.stack   { display: flex; flex-direction: column; gap: var(--gap-lg); }
.stack-sm{ display: flex; flex-direction: column; gap: var(--gap); }
.row     { display: flex; align-items: center; gap: var(--gap-sm); flex-wrap: wrap; }
.row-end { margin-left: auto; }
.sep     { margin-top: var(--sect); }

.grid      { display: grid; gap: var(--gap-lg); }
.grid-kpi  { grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); }
.grid-2    { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3    { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
/* A wide chart beside a narrow one. Collapses to a stack under 900px, which is
   where a doughnut legend stops fitting next to a 30-day series. */
.grid-wide { grid-template-columns: 2fr 1fr; }
.grid-side { grid-template-columns: minmax(280px, 340px) 1fr; align-items: start; }
@media (max-width: 900px) {
  .grid-wide, .grid-side { grid-template-columns: 1fr; }
}

/* ============================================================================
   3 · CARDS & KPIs
   ========================================================================== */

.card {
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-1);
}
.card-pad  { padding: var(--gap-edge); }
.card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--gap);
  padding: 14px var(--gap-edge);
  border-bottom: 1px solid var(--line-soft);
}
.card-head.plain { border-bottom: 0; padding-bottom: 0; }
.card-title {
  font-family: var(--font-head);
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1.2;
}
.card-sub { color: var(--dim-2); font-size: var(--fs-caption); margin-top: 3px; }
.card-body { padding: var(--gap-edge); }

/* The KPI plate. The accent is a stripe down the leading edge, not a coloured
   background: an admin shows eight of these at once and eight tinted plates is
   a paint chart, not a dashboard. */
.kpi {
  position: relative;
  overflow: hidden;
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-1);
  padding: 15px 16px 16px;
}
.kpi::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--c, var(--spark));
}
.kpi-label {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 7px;
}
.kpi-value {
  font-family: var(--font-head);
  font-size: var(--fs-display);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.kpi-value.sm { font-size: var(--fs-headline); }
/* A figure that is not a KPI: a readout inside a plain card. Same face and
   tabular figures, one step down, no accent stripe. */
.figure {
  font-family: var(--font-head);
  font-size: var(--fs-title);
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.kpi-meta { font-size: var(--fs-caption); color: var(--dim-2); margin-top: 6px; }
.kpi-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm);
  margin-bottom: 10px;
}
.kpi-glyph {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--c, var(--spark)) 12%, transparent);
  color: var(--c, var(--spark));
}
.kpi-glyph svg { width: 16px; height: 16px; }

.canvas-wrap { position: relative; height: 240px; }
.canvas-wrap.sm { height: 200px; }
.canvas-wrap.lg { height: 280px; }

/* ============================================================================
   4 · CONTROLS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-sm);
  height: var(--ctl-md);
  padding: 0 15px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--raise);
  color: var(--ink);
  font-size: var(--fs-emph);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background .14s, border-color .14s, color .14s;
  -webkit-tap-highlight-color: transparent;
}
.btn:hover:not(:disabled) { background: var(--card); border-color: var(--line-hover); }
.btn:active:not(:disabled) { transform: translateY(.5px); }
.btn:disabled { opacity: .42; cursor: not-allowed; }
.btn svg { width: 16px; height: 16px; }

.btn-sm { height: var(--ctl-xs); padding: 0 11px; font-size: var(--fs-caption); border-radius: var(--r-sm); }
.btn-block { width: 100%; }

.btn-ink { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.btn-ink:hover:not(:disabled) { background: var(--ink-busy); border-color: var(--ink-busy); }

.btn-bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 34%, var(--line)); }
.btn-bad:hover:not(:disabled) { background: var(--bad-wash); }

.btn-ok  { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 34%, var(--line)); }
.btn-ok:hover:not(:disabled) { background: var(--ok-wash); }

.btn-warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 34%, var(--line)); }
.btn-warn:hover:not(:disabled) { background: var(--warn-wash); }

/* The gold. Off-axis light pooling in one corner, a narrow ramp, brown ink —
   the shipped CTA's rules, minus its motion. Never overflow:hidden. */
.btn-gold {
  border: 0;
  color: var(--gold-ink);
  font-family: var(--font-head);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  background:
    radial-gradient(120% 140% at 12% 0%, rgba(255, 255, 255, .34), transparent 46%),
    linear-gradient(var(--gold-angle), var(--gold-hi) 0%, var(--gold-mid) 46%, var(--gold-lo) 100%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .28), var(--shadow-1);
}
.btn-gold:hover:not(:disabled) {
  background:
    radial-gradient(120% 140% at 12% 0%, rgba(255, 255, 255, .44), transparent 48%),
    linear-gradient(var(--gold-angle), var(--gold-hi) 0%, var(--gold-mid) 42%, var(--gold-lo) 100%);
}
.btn-gold:disabled { opacity: .45; }

/* ---- fields ------------------------------------------------------------ */
.field {
  width: 100%;
  height: var(--ctl-md);
  padding: 0 12px;
  background: var(--raise);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  font-size: var(--fs-emph);
  color: var(--ink);
  transition: border-color .14s, box-shadow .14s;
}
textarea.field { height: auto; padding: 10px 12px; line-height: 1.55; resize: vertical; }
select.field {
  appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2357574f' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px;
  cursor: pointer;
}
.field::placeholder { color: var(--dim); }
.field:hover:not(:disabled) { border-color: var(--line-hover); }
.field:focus {
  outline: none;
  border-color: var(--spark);
  box-shadow: 0 0 0 3px var(--spark-wash);
}
.field:disabled { opacity: .5; cursor: not-allowed; }
.field.mono { font-family: var(--font-mono); font-size: var(--fs-caption); }
.field.w-search { max-width: 280px; }
.field.w-auto { width: auto; min-width: 130px; }
.field.right { text-align: right; }

.label {
  display: block;
  font-size: var(--fs-kicker);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim-2);
  margin-bottom: 6px;
}
.label em {
  font-style: normal;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--dim);
}
.hint { font-size: var(--fs-caption); color: var(--dim-2); margin-top: 6px; line-height: 1.55; }
.hint-xs { font-size: var(--fs-kicker); color: var(--dim); margin-top: 5px; }

/* ---- chips & segments -------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-sm);
  height: var(--ctl-chip);
  padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--raise);
  color: var(--ink-2);
  font-size: var(--fs-body);
  cursor: pointer;
  transition: background .14s, border-color .14s, color .14s;
}
.chip:hover { border-color: var(--line-hover); color: var(--ink); }
.chip[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--on-ink);
  font-weight: 600;
}

.seg {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.seg > button {
  min-width: 38px;
  height: 30px;
  padding: 0 11px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  cursor: pointer;
  transition: background .14s, color .14s;
}
.seg > button:hover:not(:disabled) { background: var(--raise); }
.seg > button[aria-pressed="true"] { background: var(--ink); color: var(--on-ink); font-weight: 600; }
.seg > button:disabled { opacity: .45; cursor: not-allowed; }

/* ---- the switch -------------------------------------------------------- */
.switch {
  position: relative;
  width: 42px;
  height: 24px;
  flex: none;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--mute);
  cursor: pointer;
  transition: background .18s;
}
.switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--raise);
  box-shadow: var(--shadow-1);
  transition: transform .18s cubic-bezier(.2, .7, .2, 1);
}
.switch[aria-checked="true"] { background: var(--ok); }
.switch[aria-checked="true"]::after { transform: translateX(18px); }
.switch:disabled { opacity: .5; cursor: not-allowed; }

.check { width: 16px; height: 16px; accent-color: var(--ink); cursor: pointer; flex: none; }

/* ============================================================================
   5 · BADGES, NOTES, MESSAGES
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: var(--fs-kicker);
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}
.badge-neutral { background: var(--card);      border-color: var(--line);  color: var(--ink-2); }
.badge-ok      { background: var(--ok-wash);   border-color: color-mix(in srgb, var(--ok) 30%, transparent);   color: var(--ok); }
.badge-warn    { background: var(--warn-wash); border-color: color-mix(in srgb, var(--warn) 30%, transparent); color: var(--warn); }
.badge-bad     { background: var(--bad-wash);  border-color: color-mix(in srgb, var(--bad) 30%, transparent);  color: var(--bad); }
.badge-spark   { background: var(--spark-wash);border-color: color-mix(in srgb, var(--spark) 30%, transparent);color: var(--spark); }

.dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--mute); }

.note {
  border: 1px solid var(--line);
  border-left: 3px solid var(--dim);
  border-radius: var(--r-md);
  background: var(--card);
  padding: 11px 14px;
  font-size: var(--fs-caption);
  color: var(--ink-2);
  line-height: 1.6;
}
.note-warn  { border-left-color: var(--warn);  background: var(--warn-wash); }
.note-bad   { border-left-color: var(--bad);   background: var(--bad-wash); color: var(--bad); }
.note-spark { border-left-color: var(--spark); background: var(--spark-wash); }
.note code, .note .mono { font-family: var(--font-mono); font-size: .95em; }

.msg { font-size: var(--fs-emph); font-weight: 500; }
.msg-ok  { color: var(--ok); }
.msg-bad { color: var(--bad); }

.empty {
  text-align: center;
  color: var(--dim-2);
  padding: 34px 16px;
  font-size: var(--fs-emph);
}

/* ---- progress ---------------------------------------------------------- */
.progress { height: 7px; border-radius: var(--r-pill); background: var(--card); overflow: hidden; }
.progress > span {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--gold-lo), var(--gold-hi));
  transition: width .8s cubic-bezier(.2, .7, .2, 1);
}
@media (prefers-reduced-motion: reduce) { .progress > span { transition: none; } }

/* ============================================================================
   6 · TABLES — and their second shape
   ========================================================================== */

.table-wrap { overflow-x: auto; }

.tbl {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);
}
.tbl thead th {
  text-align: left;
  padding: 10px var(--gap-edge);
  background: var(--card);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-kicker);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--dim-2);
  white-space: nowrap;
}
.tbl tbody td {
  padding: 11px var(--gap-edge);
  border-bottom: 1px solid var(--line-soft);
  color: var(--ink-2);
  vertical-align: top;
}
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover td { background: color-mix(in srgb, var(--card) 55%, transparent); }
.tbl .strong { color: var(--ink); font-weight: 600; }
.tbl .right, .tbl th.right { text-align: right; }
.tbl .nowrap { white-space: nowrap; }
.tbl .num { font-variant-numeric: tabular-nums; }
.tbl tr.head-row td { background: var(--card); font-weight: 600; color: var(--ink); }
.tbl td.indent { padding-left: 34px; }

/* The second shape. Below 760px a table is not a grid any more — it is a list
   of records, each cell prefixed by the column name it lost. `data-l` on the
   <td> carries that name; a cell with no data-l (an action row) spans clean. */
@media (max-width: 760px) {
  .tbl, .tbl tbody, .tbl tr, .tbl td { display: block; width: 100%; }
  .tbl thead { display: none; }
  .tbl tbody tr {
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--raise);
    padding: 4px 12px;
    margin-bottom: var(--gap);
  }
  .tbl tbody tr:hover td { background: transparent; }
  .tbl tbody td {
    display: flex;
    gap: var(--gap-lg);
    align-items: baseline;
    justify-content: space-between;
    padding: 7px 0;
    border-bottom: 1px solid var(--line-soft);
    text-align: right;
  }
  .tbl tbody td:last-child { border-bottom: 0; }
  .tbl tbody td::before {
    content: attr(data-l);
    flex: none;
    text-align: left;
    font-size: var(--fs-kicker);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--dim);
  }
  .tbl tbody td:not([data-l]) { justify-content: flex-start; text-align: left; }
  .tbl tbody td.empty, .tbl tbody td[colspan] { display: block; text-align: center; }
  .tbl tbody td[colspan]::before { content: none; }
  .tbl td.indent { padding-left: 0; }
  .table-wrap { overflow-x: visible; }
}

/* ============================================================================
   7 · MODALS
   ========================================================================== */

.modal {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--gap-edge);
  background: rgba(var(--ink-rgb), .42);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  overflow-y: auto;
}
.modal-card {
  width: 100%;
  max-width: 480px;
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-2);
  padding: 22px;
  margin: auto;
}
.modal-card.wide { max-width: 600px; }
.modal-title {
  font-family: var(--font-head);
  font-size: var(--fs-headline);
  font-weight: 700;
  line-height: 1.15;
  margin-bottom: var(--gap-lg);
}
/* On a phone the dialog stops floating and becomes the screen — a 480px card
   centred in a 380px viewport is a card with no margins pretending otherwise. */
@media (max-width: 560px) {
  .modal { padding: 0; align-items: flex-end; }
  .modal-card {
    max-width: none;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-bottom: 0;
    max-height: 92dvh;
    overflow-y: auto;
    margin: 0;
  }
}

/* An inset panel inside a card or modal: a read-only fact, a result box. */
.inset {
  background: var(--card);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  padding: 11px 13px;
}
.inset .k {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 4px;
}
.inset .v { font-size: var(--fs-emph); color: var(--ink); word-break: break-word; }

/* ============================================================================
   9 · UTILITIES — few, and each earns its place
   ========================================================================== */

.dim   { color: var(--dim-2); }
.faint { color: var(--dim); }
.ok    { color: var(--ok); }
.bad   { color: var(--bad); }
.warn  { color: var(--warn); }
.spark { color: var(--spark); }
.xs    { font-size: var(--fs-caption); }
.xxs   { font-size: var(--fs-kicker); }
.b     { font-weight: 600; }
.trunc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wrap-any { word-break: break-word; overflow-wrap: anywhere; }
.flex-1 { flex: 1; min-width: 0; }
.hide   { display: none !important; }
@media (max-width: 760px) { .hide-sm { display: none !important; } }

/* A block of code / a stack trace inside a table cell. */
.pre {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--card);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: var(--fs-kicker);
  color: var(--ink-2);
  white-space: pre-wrap;
  overflow-x: auto;
  line-height: 1.5;
}

details > summary {
  cursor: pointer;
  font-size: var(--fs-caption);
  color: var(--dim-2);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
  content: "";
  width: 0;
  height: 0;
  border: 4px solid transparent;
  border-left-color: currentColor;
  transition: transform .15s;
}
details[open] > summary::before { transform: rotate(90deg) translateX(-1px); }
details > summary:hover { color: var(--ink); }

/* ============================================================================
   10 · THE DASHBOARD'S OWN — pieces the admin has no use for
   ========================================================================== */

/* ---- the store pill: who is signed in, at the foot of the rail ---------- */
.store-pill {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--r-md);
  background: var(--card);
  margin-bottom: var(--gap-sm);
}
.store-avatar {
  width: 30px;
  height: 30px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--ink);
  color: var(--on-ink);
  font-family: var(--font-head);
  font-size: var(--fs-emph);
  font-weight: 700;
  line-height: 1;
}
.store-meta { min-width: 0; flex: 1; }
.store-name {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.store-state { font-size: var(--fs-kicker); color: var(--ok); display: flex; align-items: center; gap: 5px; }
.store-state.is-off { color: var(--bad); }

/* ---- the credits ring --------------------------------------------------
   The one figure a store owner opens this dashboard to see. It is a ring
   rather than a bar because it answers "how much is left", not "how far along
   am I" — and it goes amber, not red, when it runs low: low credits are a
   thing to act on, not a failure. */
.credits {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sect);
  align-items: center;
  padding: var(--gap-edge);
}
@media (max-width: 700px) {
  .credits { grid-template-columns: 1fr; justify-items: center; text-align: center; gap: var(--gap-lg); }
  .credits .credit-acts { justify-content: center; }
}
.ring-wrap { position: relative; width: 160px; height: 160px; flex: none; }
.ring-wrap svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ring-bg { fill: none; stroke: var(--card); stroke-width: 12; }
.ring-fill {
  fill: none;
  stroke: var(--ok);
  stroke-width: 12;
  stroke-linecap: round;
  transition: stroke-dashoffset 1s cubic-bezier(.2, .7, .2, 1);
}
.ring-fill.is-low { stroke: var(--warn); }
.ring-center {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
}
.ring-number {
  font-family: var(--font-head);
  font-size: 42px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.ring-label {
  font-size: var(--fs-kicker);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
  margin-top: 4px;
}
.credit-heading {
  font-family: var(--font-head);
  font-size: var(--fs-headline);
  font-weight: 700;
  line-height: 1.15;
}
.credit-sub { color: var(--dim-2); margin-top: 6px; max-width: 56ch; line-height: 1.6; }
.credit-meta { display: flex; gap: var(--sect); margin-top: var(--gap-lg); }
.credit-meta .v { font-family: var(--font-head); font-size: var(--fs-title); font-weight: 700; font-variant-numeric: tabular-nums; }
.credit-meta .l { font-size: var(--fs-kicker); color: var(--dim); margin-top: 2px; }
.credit-acts { display: flex; gap: var(--gap-sm); flex-wrap: wrap; margin-top: var(--gap-edge); }
@media (prefers-reduced-motion: reduce) { .ring-fill { transition: none; } }

/* ---- an action tile ----------------------------------------------------- */
.action {
  display: block;
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-1);
  padding: 16px;
  transition: border-color .14s, transform .14s;
}
.action:hover { border-color: var(--line-hover); transform: translateY(-1px); }
.action .glyph {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  background: var(--card);
  color: var(--ink-2);
  margin-bottom: 11px;
}
/* block, not inline: these are spans so the whole tile can be one <a>, and an
   inline title runs straight into its own description. */
.action .t { display: block; font-weight: 600; font-size: var(--fs-emph); }
.action .d { display: block; font-size: var(--fs-caption); color: var(--dim-2); margin-top: 3px; }

/* ---- the activity feed -------------------------------------------------- */
.feed { list-style: none; }
.feed li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 11px var(--gap-edge);
  border-bottom: 1px solid var(--line-soft);
}
.feed li:last-child { border-bottom: 0; }
.feed .dot { margin-top: 6px; }
.feed .dot.tryon { background: var(--ok); }
.feed .dot.click { background: var(--blue); }
.feed .dot.order { background: var(--spark); }
.feed .t { display: block; font-size: var(--fs-body); color: var(--ink); }
.feed .s { display: block; font-size: var(--fs-kicker); color: var(--dim); margin-top: 2px; }
.feed .when { margin-left: auto; font-size: var(--fs-kicker); color: var(--dim); white-space: nowrap; }

/* ---- a block of code the store copies ----------------------------------- */
.code {
  position: relative;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 14px 15px;
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  line-height: 1.65;
  color: var(--ink-2);
  white-space: pre-wrap;
  overflow-x: auto;
  word-break: break-word;
}
.code-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  margin-bottom: var(--gap-sm);
}
/* Three token colours, drawn from the ramp — enough to find your place in a
   snippet, not enough to turn it into a paint chart. */
.code .c-comment { color: var(--dim); font-style: italic; }
.code .c-string  { color: var(--ok); }
.code .c-key     { color: var(--ink); font-weight: 600; }

/* ---- paging a long list ------------------------------------------------- */
.pager { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; padding: var(--gap-lg) var(--gap-edge); }
.pager button {
  min-width: var(--ctl-xs);
  height: var(--ctl-xs);
  padding: 0 9px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--raise);
  color: var(--ink-2);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.pager button:hover:not(:disabled):not([aria-current]) { background: var(--card); }
.pager button[aria-current] { background: var(--ink); border-color: var(--ink); color: var(--on-ink); font-weight: 600; }
.pager button:disabled { opacity: .4; cursor: not-allowed; }
.pager .gap { color: var(--dim); padding: 0 4px; }
.pager .count { margin-left: auto; font-size: var(--fs-caption); color: var(--dim-2); }

/* ---- a numbered instruction ---------------------------------------------- */
.steps { display: flex; flex-direction: column; gap: var(--gap-lg); counter-reset: step; }
.steps li { display: flex; gap: 12px; list-style: none; }
.steps li::before {
  counter-increment: step;
  content: counter(step);
  flex: none;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--ink);
  color: var(--on-ink);
  font-size: var(--fs-kicker);
  font-weight: 700;
}
.steps li > span { color: var(--ink-2); line-height: 1.6; }
.steps code { font-family: var(--font-mono); font-size: .95em; background: var(--card); border-radius: var(--r-xs); padding: 1px 5px; }

/* ---- the skeleton, while the API answers -------------------------------- */
.skel {
  background: linear-gradient(90deg, var(--card) 25%, var(--line-soft) 50%, var(--card) 75%);
  background-size: 200% 100%;
  border-radius: var(--r-xs);
  animation: skel 1.4s ease-in-out infinite;
  color: transparent !important;
}
@keyframes skel { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

/* ---- a key/value list: the quiet facts beside a headline figure -------- */
.kv { display: flex; align-items: baseline; justify-content: space-between; gap: var(--gap-lg); padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
.kv:last-child { border-bottom: 0; }
.kv .k { color: var(--dim-2); font-size: var(--fs-body); }
.kv .v { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }

/* ---- a pickable option row (credit packages) ---------------------------
   A radio in everything but markup: it carries a price, so it is a row you
   read rather than a dot you aim at. The selected state is the ink border, not
   a tint — a tinted row beside three plain ones reads as "recommended". */
.opt-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-lg);
  width: 100%;
  text-align: left;
  padding: 13px 15px;
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
  background: var(--raise);
  cursor: pointer;
  transition: border-color .14s;
}
.opt-row:hover { border-color: var(--line-hover); }
.opt-row[aria-pressed="true"] { border-color: var(--ink); }
.opt-row .n { font-weight: 600; font-size: var(--fs-emph); }
.opt-row .m { font-size: var(--fs-caption); color: var(--dim-2); margin-top: 2px; }
.opt-row .p { font-family: var(--font-head); font-size: var(--fs-title); font-weight: 700; }

/* ---- the toast: what just happened, and then gone --------------------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translate(-50%, 16px);
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 9px;
  max-width: min(440px, calc(100vw - 32px));
  padding: 11px 16px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--on-ink);
  font-size: var(--fs-emph);
  box-shadow: var(--shadow-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s, transform .18s;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.is-bad { background: var(--bad); }
.toast svg { flex: none; }
@media (prefers-reduced-motion: reduce) { .toast { transition: none; } }

/* ---- file drop / picker ------------------------------------------------- */
.dropzone {
  flex: 1;
  min-width: 0;
  border: 1.5px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: var(--card);
  padding: 16px;
  text-align: center;
  cursor: pointer;
  transition: border-color .14s, background .14s;
}
.dropzone:hover, .dropzone.is-over { border-color: var(--spark); background: var(--spark-wash); }
.dropzone b { display: block; font-size: var(--fs-emph); }
.dropzone span { display: block; font-size: var(--fs-caption); color: var(--dim-2); margin-top: 3px; }

.logo-preview {
  width: 74px;
  height: 74px;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card);
  color: var(--dim);
  overflow: hidden;
}
.logo-preview img { width: 100%; height: 100%; object-fit: cover; }

/* ---- a checkbox that is a tile (delivery areas) ------------------------- */
.check-tile {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--raise);
  font-size: var(--fs-body);
  cursor: pointer;
  transition: border-color .14s;
}
.check-tile:hover { border-color: var(--line-hover); }
.check-tile:has(input:checked) { border-color: var(--ink); }
.check-tile:has(input:disabled) { opacity: .5; cursor: not-allowed; }

/* ============================================================================
   11 · THE SIGN-IN PAGE
   Its own page here, not an overlay: a store arrives at this URL cold, often
   from an email, and a dashboard that paints itself behind a modal it cannot
   dismiss is a worse first impression than a page that simply asks.
   ========================================================================== */
.auth-page {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: var(--gap-edge);
}
.auth-box { width: 100%; max-width: 400px; }
.auth-brand {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: var(--gap-edge);
}
.auth-brand span {
  font-family: var(--font-head);
  font-size: var(--fs-title);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--dim-2);
  line-height: 1.2;
}
.auth-card {
  background: var(--raise);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-2);
  padding: 26px 24px 24px;
}
.auth-title {
  font-family: var(--font-head);
  font-size: var(--fs-headline);
  font-weight: 700;
  line-height: 1.15;
}
.auth-sub { color: var(--dim-2); margin: 7px 0 var(--gap-edge); line-height: 1.6; }
.auth-foot { text-align: center; color: var(--dim-2); font-size: var(--fs-caption); margin-top: var(--gap-edge); }
.auth-foot a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }

/* the reveal button inside the key field */
.field-wrap { position: relative; }
.field-wrap .reveal {
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  width: 40px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  color: var(--dim);
  cursor: pointer;
}
.field-wrap .reveal:hover { color: var(--ink); }
.field-wrap .field { padding-right: 42px; }

.spinner {
  width: 15px;
  height: 15px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2s; } }
