/* ==========================================================================
   Dankie se Mark — shared stylesheet
   Warm Free State palette: cream paper, veld green, terracotta, wheat gold.
   ========================================================================== */

:root {
  --cream: #faf6ef;
  --paper: #ffffff;
  --sand: #f0e8db;
  --line: #e2d7c5;
  --ink: #2b2620;
  --ink-soft: #6b6155;
  --ink-faint: #9a8f80;
  --green: #3f5d45;
  --green-dark: #2f4634;
  --green-light: #e8efe8;
  --terra: #c1653f;
  --terra-dark: #a3512f;
  --terra-light: #fbeee7;
  --gold: #d9a441;
  --gold-light: #fdf4e2;
  --danger: #b3382f;
  --danger-light: #fbeceb;
  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 1px 2px rgba(43, 38, 32, .06), 0 8px 24px rgba(43, 38, 32, .06);
  --shadow-lg: 0 2px 4px rgba(43, 38, 32, .08), 0 20px 48px rgba(43, 38, 32, .12);
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --serif: "Fraunces", Georgia, "Times New Roman", serif;
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

a { color: var(--green); text-decoration-color: var(--line); text-underline-offset: 3px; }
a:hover { color: var(--green-dark); }

h1, h2, h3, h4 { font-family: var(--serif); font-weight: 600; line-height: 1.2; margin: 0 0 .5em; }
h1 { font-size: clamp(2rem, 5vw, 3.25rem); letter-spacing: -.02em; }
h2 { font-size: clamp(1.4rem, 3vw, 2rem); }
h3 { font-size: 1.15rem; }

.wrap { width: min(1140px, 100% - 2.5rem); margin-inline: auto; }
.wrap-narrow { width: min(760px, 100% - 2.5rem); margin-inline: auto; }

.muted { color: var(--ink-soft); }
.faint { color: var(--ink-faint); font-size: .85rem; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.mono { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.hidden { display: none !important; }
.stack > * + * { margin-top: 1rem; }

/* --------------------------------------------------------------- top bar */

.topbar {
  position: sticky; top: 0; z-index: 50;
  background: rgba(250, 246, 239, .92);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.topbar-inner {
  display: flex; align-items: center; gap: 1rem;
  min-height: 64px;
}
.brand { display: flex; align-items: baseline; gap: .55rem; text-decoration: none; color: inherit; margin-right: auto; }
.brand-mark {
  font-family: var(--serif); font-size: 1.3rem; font-weight: 600;
  color: var(--green-dark); letter-spacing: -.01em; white-space: nowrap;
}
.brand-sub {
  font-size: .72rem; color: var(--ink-faint); letter-spacing: .04em;
  text-transform: uppercase; white-space: nowrap;
}
@media (max-width: 720px) {
  .brand-sub { display: none; }
  .brand-mark { font-size: 1.08rem; }
  /* Section anchors are reachable by scrolling; the login link and the
     language toggle are the two that must survive a narrow screen. */
  .topnav a[href^="#"] { display: none; }
  .wrap, .wrap-narrow { width: calc(100% - 2rem); }
}
@media (max-width: 380px) {
  .brand-mark { font-size: .98rem; }
  .topnav a, .topnav button { font-size: .85rem; }
}

/* Touch targets: a finger needs more room than a mouse pointer, so the
   header controls and the small row buttons grow on phones. */
@media (hover: none), (max-width: 760px) {
  .topnav a, .topnav button { min-height: 38px; display: inline-flex; align-items: center; }
  .btn-sm { min-height: 36px; padding: .5rem .8rem; }
  .tab { min-height: 42px; }
  .check input { width: 20px; height: 20px; }
}

.topnav { display: flex; align-items: center; gap: .35rem; min-width: 0; }
/* "Log out" splitting across two lines looked broken. It holds its line; the
   email address beside it is what gives way, shortening or stepping aside. */
.topnav a, .topnav button, .topnav .nowrap { white-space: nowrap; }
.topnav #who {
  overflow: hidden; text-overflow: ellipsis; min-width: 0;
  max-width: min(46vw, 320px);
}
@media (max-width: 520px) { .topnav #who { display: none; } }
.topnav a, .topnav button {
  font: inherit; font-size: .9rem; color: var(--ink-soft);
  background: none; border: 0; cursor: pointer;
  padding: .45rem .7rem; border-radius: var(--radius-sm); text-decoration: none;
}
.topnav a:hover, .topnav button:hover { background: var(--sand); color: var(--ink); }
.topnav a.is-active { color: var(--green-dark); font-weight: 600; }


/* ----------------------------------------------------------------- hero */

.hero {
  position: relative; overflow: hidden;
  background:
    radial-gradient(120% 80% at 80% -10%, rgba(217, 164, 65, .22), transparent 60%),
    radial-gradient(100% 90% at 10% 110%, rgba(63, 93, 69, .16), transparent 55%),
    var(--cream);
  padding: clamp(3rem, 9vw, 6.5rem) 0 clamp(2.5rem, 6vw, 4.5rem);
  border-bottom: 1px solid var(--line);
}
.hero-kicker {
  display: inline-block; font-size: .78rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--terra); font-weight: 600;
  margin-bottom: 1rem;
}
.hero h1 { margin-bottom: .4rem; }
.hero-tagline { font-size: clamp(1.05rem, 2.2vw, 1.3rem); color: var(--ink-soft); max-width: 46ch; }

/* "presented by" + the Lollie-B wordmark. The market name leads; the
   company signs it. */
.hero-by {
  display: flex; align-items: center; gap: .85rem; flex-wrap: wrap;
  margin: .1rem 0 1.4rem;
}
.hero-by span {
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600;
}
.hero-by img { width: auto; height: 62px; }

.footer-logo { width: auto; height: 46px; opacity: .8; }
@media (max-width: 560px) {
  .hero-by img { height: 48px; }
  .footer-logo { height: 38px; }
}
.hero-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2rem; }

.factbar {
  display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  margin-top: 3rem;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.fact { background: var(--paper); padding: 1.15rem 1.35rem; }
.fact-label {
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600; margin-bottom: .3rem;
}
.fact-value { font-family: var(--serif); font-size: 1.1rem; color: var(--ink); }

/* --------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font: inherit; font-size: .94rem; font-weight: 550;
  padding: .68rem 1.25rem; border-radius: var(--radius-sm);
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  transition: background .15s, border-color .15s, color .15s, transform .05s;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.btn-primary { background: var(--green); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--green-dark); color: #fff; }

.btn-accent { background: var(--terra); color: #fff; }
.btn-accent:hover:not(:disabled) { background: var(--terra-dark); color: #fff; }

.btn-ghost { background: transparent; border-color: var(--line); color: var(--ink); }
.btn-ghost:hover:not(:disabled) { background: var(--sand); color: var(--ink); }

.btn-danger { background: transparent; border-color: var(--line); color: var(--danger); }
.btn-danger:hover:not(:disabled) { background: var(--danger-light); border-color: var(--danger); }

.btn-sm { padding: .38rem .7rem; font-size: .82rem; }
.btn-block { width: 100%; }

/* ----------------------------------------------------------------- cards */

.card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.card-pad { padding: clamp(1.25rem, 3vw, 1.85rem); }
.card-head {
  padding: 1.15rem clamp(1.25rem, 3vw, 1.85rem);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
}
.card-head h2, .card-head h3 { margin: 0; }
.card-head .spacer { margin-left: auto; }

.section { padding: clamp(2.5rem, 6vw, 4.5rem) 0; }
.section-head { margin-bottom: 2rem; }

/* --------------------------------------------------------------- supplier
   grid on the public page */

.supplier-grid {
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.supplier-card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
  display: flex; flex-direction: column;
  transition: box-shadow .18s, transform .18s;
}
.supplier-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); }
.supplier-logo {
  aspect-ratio: 16 / 10; background: var(--sand);
  display: grid; place-items: center; overflow: hidden;
}
.supplier-logo img { width: 100%; height: 100%; object-fit: cover; }
.supplier-initial {
  font-family: var(--serif); font-size: 2.4rem; color: var(--green);
  opacity: .5;
}
/* With only a company name to show, the card is a simple nameplate. */
.supplier-card-simple { justify-content: center; text-align: center; }
.supplier-card-simple .supplier-body { padding: 1.5rem 1.25rem; }
.supplier-card-simple h3 { margin: 0; font-size: 1.1rem; }

.supplier-body { padding: 1.1rem 1.25rem 1.35rem; flex: 1; }
.supplier-body h3 { margin-bottom: .25rem; font-size: 1.05rem; }
.supplier-cat {
  font-size: .74rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--terra); font-weight: 600; margin-bottom: .6rem;
}
.supplier-desc { font-size: .9rem; color: var(--ink-soft); margin: 0 0 .75rem; }
.supplier-meta { display: flex; gap: .75rem; flex-wrap: wrap; font-size: .82rem; color: var(--ink-faint); }

/* ----------------------------------------------------------------- forms */

.field { margin-bottom: 1.1rem; }
.field label, .label {
  display: block; font-size: .84rem; font-weight: 600;
  color: var(--ink); margin-bottom: .35rem;
}
/* A field that is filled in for you. Not greyed out like a disabled control —
   the number matters and has to stay readable — but plainly not yours to type
   in. */
input[readonly], textarea[readonly] {
  background: var(--sand); border-style: dashed; cursor: default;
}
input[readonly]:focus, textarea[readonly]:focus { outline-color: var(--line); }

.field-hint { font-size: .8rem; color: var(--ink-faint); margin-top: .3rem; }

input[type="text"], input[type="email"], input[type="password"],
input[type="tel"], input[type="url"], input[type="number"],
input[type="search"], select, textarea {
  width: 100%; font: inherit; font-size: .95rem; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: .6rem .75rem;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(63, 93, 69, .13);
}
input:disabled, select:disabled, textarea:disabled {
  background: var(--sand); color: var(--ink-soft); cursor: not-allowed;
}
textarea { resize: vertical; min-height: 92px; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%236b6155' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .75rem center;
  padding-right: 2.2rem;
}

.grid-2 { display: grid; gap: 0 1.1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.grid-3 { display: grid; gap: 0 1.1rem; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }

.check { display: flex; align-items: flex-start; gap: .6rem; font-size: .92rem; cursor: pointer; }
.check input { width: auto; margin-top: .22rem; accent-color: var(--green); }

/* --------------------------------------------------------------- notices */

.notice {
  padding: .75rem 1rem; border-radius: var(--radius-sm);
  font-size: .9rem; border: 1px solid transparent; margin-bottom: 1rem;
}
.notice-error { background: var(--danger-light); border-color: #edc9c6; color: #7d2721; }
.notice-ok { background: var(--green-light); border-color: #c9dcc9; color: var(--green-dark); }
.notice-warn { background: var(--gold-light); border-color: #ecd6a5; color: #7a5a15; }
.notice-info { background: var(--terra-light); border-color: #eed4c6; color: var(--terra-dark); }
/* For saying what the screen is currently showing. The coloured notices all
   read as "something happened"; a filter being on is not an event. */
.notice-quiet {
  background: var(--sand); border-color: var(--line); color: var(--ink-soft);
  display: flex; gap: .75rem; align-items: center; flex-wrap: wrap;
}

.toast {
  position: fixed; left: 50%; bottom: 1.5rem; transform: translateX(-50%);
  background: var(--ink); color: var(--cream); padding: .7rem 1.2rem;
  border-radius: 999px; font-size: .9rem; box-shadow: var(--shadow-lg);
  z-index: 200; opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(-4px); }

/* ---------------------------------------------------------------- badges */

.badge {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .74rem; font-weight: 600; letter-spacing: .02em;
  padding: .2rem .55rem; border-radius: 999px;
  border: 1px solid transparent; white-space: nowrap;
}
.badge-ok { background: var(--green-light); color: var(--green-dark); border-color: #c9dcc9; }
.badge-wait { background: var(--gold-light); color: #7a5a15; border-color: #ecd6a5; }
.badge-off { background: var(--sand); color: var(--ink-soft); border-color: var(--line); }
.badge-bad { background: var(--danger-light); color: #7d2721; border-color: #edc9c6; }
/* A badge that is also a way in. Same look, but pressable. */
.badge-btn { cursor: pointer; font: inherit; font-size: .72rem; font-weight: 600; }
.badge-btn:hover { filter: brightness(.97); }
.badge-btn:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

/* ----------------------------------------------------------------- tabs */

.tabs {
  display: flex; gap: .25rem; border-bottom: 1px solid var(--line);
  margin-bottom: 1.75rem; overflow-x: auto; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
/* On a narrow screen the strip runs past the edge. Fade the last centimetre so
   it reads as "there is more this way" rather than as a tab chopped in half. */
@media (max-width: 760px) {
  .tabs {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
}
.tab {
  font: inherit; font-size: .92rem; font-weight: 550;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--ink-soft); padding: .7rem .9rem; cursor: pointer; white-space: nowrap;
}
.tab:hover { color: var(--ink); }
.tab.is-active { color: var(--green-dark); border-bottom-color: var(--green); }

/* ---------------------------------------------------------------- tables */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.data { width: 100%; border-collapse: collapse; font-size: .9rem; }

/* A table with too many columns to fit.
   width:100% alone makes a table CRUSH its columns rather than overflow, so
   the scroll on .table-scroll never engages: the suppliers list went to ten
   columns and quietly squeezed the Edit and Delete buttons off the right edge,
   where nothing could reach them. A floor on the width makes it overflow
   honestly and scroll instead. Below the phone breakpoint the rows become
   cards, so the floor is lifted there.
   The business name is what the eye runs down, so it is not the column that
   gives way first. */
table.data.wide { min-width: 1120px; }

/* A second, quieter line inside a cell — an email under a person's name. */
.under { display: block; color: var(--ink-faint); font-size: .78rem; line-height: 1.3; }
/* A count that is known to be short — some lines have no stock on them. */
.under.is-short { color: var(--terra-dark); cursor: help; }
.tick { white-space: nowrap; }

/* The running total under the products table. */
.table-total {
  display: flex; gap: .6rem 1.25rem; flex-wrap: wrap; align-items: baseline;
  padding: .9rem clamp(1.25rem, 3vw, 1.85rem);
  border-top: 1px solid var(--line); background: var(--sand);
  font-size: .92rem;
}
.table-total b { font-family: var(--serif); font-size: 1.05rem; font-weight: 600; }
.table-total .spacer { flex: 1; }
.table-total .warn-note { color: var(--terra-dark); font-size: .85rem; }
table.data.wide td[data-label="Business"] { min-width: 13rem; }
table.data.wide td[data-label="Labels"] { white-space: nowrap; }
@media (max-width: 760px) {
  table.data.wide { min-width: 0; }
  table.data.wide td[data-label="Business"] { min-width: 0; }
}
table.data th {
  text-align: left; font-size: .74rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-faint); font-weight: 600;
  padding: .6rem .75rem; border-bottom: 1px solid var(--line); white-space: nowrap;
}
table.data td { padding: .7rem .75rem; border-bottom: 1px solid var(--sand); vertical-align: middle; }
table.data tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: #fdfbf7; }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* A supplier's address.
   Kept to one line on a wide screen so one long address cannot stretch the
   whole row — the full text is on the cell's title, and on a phone, where the
   table becomes cards, it wraps and shows in full. */
.addr {
  display: inline-block; max-width: 22ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: bottom;
}
/* The cell version is a button: one line here, the whole thing in a dialog. */
button.addr { text-align: left; max-width: 22ch; }

/* The address inside that dialog, set the way it would be on an envelope. */
.addr-full {
  margin: 0; font-size: 1.05rem; line-height: 1.5;
  font-family: var(--serif);
}

/* The "labels printed" tick, one per supplier.
   Deliberately a real checkbox: it is a tick list the manager works down with
   a printer running beside him, and a tick list should look like one. */
.tick {
  display: inline-flex; align-items: center; gap: .4rem;
  cursor: pointer; white-space: nowrap; font-size: .86rem;
  color: var(--ink-soft);
}
.tick input { width: auto; margin: 0; accent-color: var(--green); cursor: pointer; }
.tick input:disabled { cursor: wait; opacity: .5; }
.tick.is-done { color: var(--green-dark); font-weight: 600; }
.tick small { color: var(--ink-faint); font-weight: 400; font-size: .76rem; }
@media (max-width: 760px) {
  .addr { max-width: none; white-space: normal; overflow: visible; }
}
.row-actions { display: flex; gap: .35rem; justify-content: flex-end; }


/* The sticky header would otherwise cover the top of whatever we scroll to. */
[id^="pane-"] { scroll-margin-top: 80px; }

/* A number or word that acts like a link: no button chrome, but a real button
   underneath so it is reachable by keyboard and reads as pressable. */
.linkish {
  font: inherit; color: var(--green-dark); background: none; border: 0;
  padding: 0; cursor: pointer; text-decoration: underline;
  text-underline-offset: 3px; text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--green) 45%, transparent);
}
.linkish:hover { text-decoration-color: var(--green); }
.linkish:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; border-radius: 3px; }
/* A finger needs more than a digit's worth of target. */
@media (hover: none), (max-width: 760px) {
  .linkish { padding: .35rem .2rem; }
}

.empty {
  padding: 3rem 1.5rem; text-align: center; color: var(--ink-faint);
  font-size: .95rem;
}

/* ---- tables on a phone --------------------------------------------------
   Below this width each row becomes its own card and every value carries the
   column heading beside it (from data-label, which each cell carries). Reading
   a supplier's details beats scrolling a grid sideways. */
@media (max-width: 760px) {
  .table-scroll { overflow-x: visible; }

  table.data, table.data tbody, table.data tr, table.data td { display: block; width: 100%; }
  table.data thead { display: none; }

  table.data tr {
    background: var(--paper); border: 1px solid var(--line);
    border-radius: var(--radius-sm); margin-bottom: .6rem; padding: .4rem .1rem;
  }
  table.data tbody tr:hover { background: var(--paper); }
  table.data tr:last-child td { border-bottom: 0; }

  /* Grid, not flex: the label holds column one while a cell's several
     children (a name plus its category, say) stack down column two instead
     of crowding onto one line. */
  table.data td {
    display: grid; grid-template-columns: auto 1fr;
    gap: .15rem 1rem; align-items: baseline; text-align: right;
    border: 0; border-bottom: 1px solid var(--sand);
    padding: .45rem .85rem;
  }
  table.data td:last-child { border-bottom: 0; }
  table.data td::before {
    content: attr(data-label);
    grid-column: 1; grid-row: 1; text-align: left; align-self: baseline;
    font-size: .68rem; letter-spacing: .07em; text-transform: uppercase;
    color: var(--ink-faint); font-weight: 600;
  }
  /* justify-self keeps a badge at its own width instead of stretching
     across the whole column. */
  table.data td > * { grid-column: 2; justify-self: end; }

  /* Columns with a blank heading (row actions) get no label, and cells left
     empty by variant rows disappear entirely. */
  table.data td:not([data-label]) { grid-template-columns: 1fr; }
  table.data td:not([data-label])::before { content: none; }
  table.data td:not([data-label]) > * { grid-column: 1; justify-self: end; }
  table.data td:empty { display: none; }

  /* The first thing in the card is its title — a product name, or a variant
     name on a continuation row. A heading reads better than a field called
     "Product" whose value happens to be the product. */
  table.data td[data-card-title] {
    grid-template-columns: 1fr;
    text-align: left;
    padding: .7rem .85rem .6rem;
    border-bottom: 1px solid var(--line);
  }
  table.data td[data-card-title]::before { content: none; }
  table.data td[data-card-title] > * { grid-column: 1; justify-self: start; }
  table.data td[data-card-title],
  table.data td[data-card-title] strong {
    font-family: var(--serif);
    font-size: 1.05rem; font-weight: 600; color: var(--ink);
  }

  /* The sizes of one product are not four separate products. A continuation
     row hangs under the card it belongs to: tucked in from the left, joined to
     it at the top, with a line down the side tying them together. */
  table.data tr.variant-line + tr.variant-line {
    /* width:auto matters: these are display:block rows at width 100%, so a
       left margin alone would push them off the right edge instead of
       indenting them. */
    width: auto; margin-top: -.55rem; margin-left: 1.1rem;
    border-top-left-radius: 0; border-top-right-radius: 0;
    border-left: 3px solid var(--green);
  }
  table.data tr.variant-line + tr.variant-line td[data-card-title] {
    font-size: .95rem;
  }

  /* Actions close the card, with room to tap. */
  table.data td[data-card-actions] { padding: .7rem .85rem .75rem; }
  table.data td[data-card-actions] .btn { padding-block: .5rem; }

  /* A number belongs against its label, not adrift in the middle. */
  table.data td.num { text-align: right; }

  .row-actions { flex-wrap: wrap; justify-content: flex-end; }

  /* Filters and search should use the full width rather than sit at 220px. */
  .card-head { align-items: stretch; }
  .card-head input[type="search"], .card-head select { max-width: none !important; width: 100%; }
}

/* ---------------------------------------------------------------- modal */

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(43, 38, 32, .45);
  display: grid; place-items: center; padding: 1.25rem; z-index: 150;
  overflow-y: auto;
}
.modal {
  background: var(--paper); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); width: min(660px, 100%);
  max-height: calc(100vh - 2.5rem); display: flex; flex-direction: column;
  margin: auto;
}
.modal-head {
  padding: 1.15rem 1.5rem; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 1rem;
}
.modal-head h3 { margin: 0; }
.modal-body { padding: 1.5rem; overflow-y: auto; }
.modal-foot {
  padding: 1rem 1.5rem; border-top: 1px solid var(--line);
  display: flex; gap: .6rem; justify-content: flex-end; flex-wrap: wrap;
}
.icon-btn {
  margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--ink-faint); font-size: 1.35rem; line-height: 1; padding: .2rem .4rem;
  border-radius: 6px;
}
.icon-btn:hover { background: var(--sand); color: var(--ink); }

/* --------------------------------------------------------------- the sales */

/* A product row that opens to show each individual sale. */
table.data tr.sale-head { cursor: pointer; }
table.data tr.sale-head:hover { background: var(--sand); }
.disclose {
  display: inline-block; width: .8em; color: var(--ink-faint);
  transition: transform .12s ease;
}
.disclose.is-open { transform: rotate(90deg); }

/* The individual sales under an opened product: quieter, and indented so the
   eye can tell at a glance which rows belong to the row above. */
table.data tr.sale-line > td {
  background: var(--sand);
  font-size: .9rem; color: var(--ink-soft);
  border-top: 0;
}
table.data tr.sale-line > td:first-child { padding-left: 2.4rem; }
@media (max-width: 760px) {
  table.data tr.sale-line > td:first-child { padding-left: 1rem; }
}

/* A row that needs looking at — an unclaimed sale, for instance. */
table.data tr.row-warn > td { background: var(--gold-light); }

/* ------------------------------------------------------- pick a few of these */

/* The export's supplier checklist. Scrolls rather than pushing the download
   buttons off the screen once there are thirty suppliers on the list. */
.pick { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: .85rem 1rem; }
.pick-head {
  display: flex; gap: .75rem; align-items: center; justify-content: space-between;
  flex-wrap: wrap; margin-bottom: .5rem;
}
.pick-tools { display: flex; gap: .4rem; }
.pick-list { max-height: 15rem; overflow-y: auto; }
.pick-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: .65rem;
  align-items: center; padding: .5rem .25rem; cursor: pointer;
  border-bottom: 1px solid var(--sand);
}
.pick-row:last-child { border-bottom: 0; }
.pick-row:hover { background: var(--sand); }
.pick-row input { width: auto; margin: 0; accent-color: var(--green); }
.pick-name { font-size: .95rem; }
@media (max-width: 560px) {
  .pick-row { grid-template-columns: auto 1fr; }
  .pick-row .faint { grid-column: 2; }
}

/* -------------------------------------------------------------- variants */

/* One line in the price confirmation: what it is, and what it sells for. */
.check-row {
  display: grid; grid-template-columns: 1fr 160px; gap: .6rem 1rem;
  align-items: end; padding: .75rem 0; border-bottom: 1px solid var(--sand);
}
.check-row:last-child { border-bottom: 0; }
.check-name { align-self: center; }
.check-note { grid-column: 1 / -1; margin: 0; }
.check-note:empty { display: none; }
@media (max-width: 560px) {
  .check-row { grid-template-columns: 1fr; }
}

/* The input rows inside the product form. Note the name is taken: a table row
   showing a size uses .variant-line, so that these grid rules cannot reach it. */
.variant-row {
  display: grid; gap: .6rem; align-items: end;
  grid-template-columns: 1.4fr 1fr .8fr .8fr .7fr auto;
  padding: .75rem; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: #fdfbf7; margin-bottom: .6rem;
}
.variant-row .field { margin: 0; }
.variant-row label { font-size: .72rem; }
/* The calculated price sits on its own line so it can't push the inputs
   out of alignment with each other. */
.variant-row .var-calc { grid-column: 1 / -1; margin-top: .15rem; }
.variant-row .var-calc:empty { display: none; }
@media (max-width: 720px) {
  .variant-row { grid-template-columns: 1fr 1fr; }
  .variant-row .var-del { grid-column: 1 / -1; }
}

/* ------------------------------------------------------------ image drop */

.imgpick { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.imgpick-preview {
  width: 84px; height: 84px; border-radius: var(--radius-sm);
  background: var(--sand); border: 1px dashed var(--line);
  display: grid; place-items: center; overflow: hidden; flex-shrink: 0;
}
.imgpick-preview img { width: 100%; height: 100%; object-fit: cover; }
.imgpick-preview span { font-size: 1.6rem; color: var(--ink-faint); }

/* ---------------------------------------------------------- auth screens */

.auth-page {
  min-height: 100vh; display: grid; place-items: center;
  padding: 2rem 1.25rem;
  background:
    radial-gradient(90% 70% at 85% 0%, rgba(217, 164, 65, .18), transparent 60%),
    radial-gradient(90% 70% at 0% 100%, rgba(63, 93, 69, .14), transparent 60%),
    var(--cream);
}
.auth-card { width: min(420px, 100%); }
.auth-head { text-align: center; margin-bottom: 1.75rem; }
.auth-head .brand-mark { font-size: 1.9rem; display: block; }
.auth-head .brand-sub { display: block; margin-top: .3rem; }

/* --------------------------------------------------------------- footer */

.site-footer {
  border-top: 1px solid var(--line); background: var(--sand);
  padding: 2.5rem 0; margin-top: auto; font-size: .87rem; color: var(--ink-soft);
}
.footer-inner { display: flex; gap: 1rem; flex-wrap: wrap; align-items: center; }
.footer-inner .spacer { margin-left: auto; }

.page { display: flex; flex-direction: column; min-height: 100vh; }
.page main { flex: 1; }

/* -------------------------------------------------------------- spinner */

.spinner {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--green);
  animation: spin .7s linear infinite; display: inline-block; vertical-align: -3px;
}
@keyframes spin { to { transform: rotate(360deg); } }

.loading-pane { padding: 3rem; text-align: center; color: var(--ink-faint); }

/* --------------------------------------------------------- import result */

.result-log {
  max-height: 240px; overflow-y: auto; font-size: .84rem;
  background: #fdfbf7; border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: .75rem 1rem; margin-top: 1rem;
}
.result-log div { padding: .15rem 0; }
.result-log .err { color: var(--danger); }

/* ------------------------------------------------------------- dashboard */

.dash-head {
  display: flex; align-items: flex-start; gap: 1rem; flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
/* .spacer is only given a push inside .card-head and the footer, so it does
   nothing here on its own — the button takes the margin instead. */
.dash-head .spacer { flex: 1 1 auto; }
.dash-head > .btn { margin-left: auto; }
.dash-when {
  margin: .35rem 0 0; font-size: .9rem; color: var(--ink-soft);
}
.dash-when.is-closed { color: var(--terra-dark); font-weight: 550; }

/* A quiet heading over each row of tiles, so the two rows read as two
   different kinds of thing rather than one long row of numbers. */
.dash-section {
  font-family: var(--font); font-size: .74rem; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--ink-faint);
  margin: 0 0 .6rem;
}

.stat-row {
  display: grid; gap: .85rem; margin-bottom: 1.75rem;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.stat {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1rem 1.25rem;
  text-align: left; font: inherit; color: inherit;
  /* A coloured strip down the left is what marks a tile as needing something;
     it costs no height, which matters on a phone. */
  border-left: 3px solid transparent;
}
.stat-num {
  font-family: var(--serif); font-size: 1.7rem; line-height: 1.1;
  color: var(--green-dark);
}
.stat-label {
  font-size: .76rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600; margin-top: .2rem;
}

/* A tile that counts something waiting. Only coloured while the count is
   above zero — a tile at zero should look settled, not alarming. */
.stat-warn { border-left-color: var(--gold); background: var(--gold-light); }
.stat-warn .stat-num { color: #7a5a15; }
.stat-info { border-left-color: var(--terra); background: var(--terra-light); }
.stat-info .stat-num { color: var(--terra-dark); }

/* A tile you can press to go to the work it counts. */
.stat-link { cursor: pointer; transition: border-color .12s, transform .12s; }
.stat-link:hover { border-color: var(--green); transform: translateY(-1px); }
.stat-link:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

/* With nothing waiting, the row is still shown — a line of grey zeroes says
   "checked, nothing to do", which an empty space does not. */
.stat-row.is-clear .stat-num { color: var(--ink-faint); }

@media (max-width: 560px) {
  /* Three across keeps the whole row on one screen instead of pushing the
     actual work below the fold. */
  .stat-row { grid-template-columns: repeat(3, 1fr); gap: .5rem; }
  .stat { padding: .6rem .7rem; }
  .stat-num { font-size: 1.3rem; }
  .stat-label { font-size: .62rem; letter-spacing: .05em; }
  .dash-head { margin-bottom: 1rem; }
}

@media print {
  .topbar, .site-footer, .btn, .tabs { display: none !important; }
  body { background: #fff; }
}
