/* NO SCROLLBAR EVER SHOWS (owner, 2026-09-11). Scrolling still works everywhere; only the bar
   is hidden. On a phone the soft keyboard shrinks the viewport and every overflowing box grew a
   bar the moment it appeared. Firefox honours scrollbar-width, WebKit/Blink the pseudo-element. */
*, *::before, *::after { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { display: none; width: 0; height: 0; }

/* Vendesso — marketing site.
   One stylesheet for every page. No build step, no framework, no external requests. */

:root {
    --paper:      #FBF8F3;
    --paper-2:    #FFFFFF;
    --ink:        #14201C;
    --muted:      #5C6B66;
    --accent:     #B8562F;   /* terracotta — CTAs, emphasis */
    --accent-ink: #FFFFFF;
    --green:      #0E6B4F;   /* deep green — confirmations, "never lies" marks */
    --border:     #E7E0D5;
    --shadow:     0 1px 2px rgba(20, 32, 28, .05), 0 8px 24px rgba(20, 32, 28, .06);
    --radius:     14px;
    --wide:       1080px;
    --narrow:     720px;
}

@media (prefers-color-scheme: dark) {
    :root {
        --paper:   #0E1512;
        --paper-2: #16201C;
        --ink:     #EDE7DC;
        --muted:   #9AA8A2;
        --accent:  #E8845C;
        --accent-ink: #1A0F0A;
        --green:   #34C08D;
        --border:  #26312C;
        --shadow:  0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px rgba(0, 0, 0, .25);
    }
}

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

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font: 17px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.2; letter-spacing: -0.02em; margin: 0 0 .5em; }
/* The site header is sticky, so an anchored heading would land underneath it. This matters
   beyond tidiness: /privacy#data-deletion is the URL Meta is given for data deletion, and a
   reviewer following it must land ON the heading, not halfway down the section. */
[id] { scroll-margin-top: 5.5rem; }
h1 { font-size: clamp(2.1rem, 5.5vw, 3.4rem); font-weight: 800; }
h2 { font-size: clamp(1.5rem, 3.4vw, 2.1rem); font-weight: 700; }
h3 { font-size: 1.12rem; font-weight: 700; }
p  { margin: 0 0 1.1em; }
a  { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }

.wrap   { max-width: var(--wide);   margin: 0 auto; padding: 0 22px; }
.narrow { max-width: var(--narrow); margin: 0 auto; padding: 0 22px; }
.muted  { color: var(--muted); }
.lede   { font-size: 1.16rem; color: var(--muted); }

/* ---------------------------------------------------------------- header */

header.site {
    position: sticky; top: 0; z-index: 20;
    background: color-mix(in srgb, var(--paper) 88%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--border);
}
/* A blurred sticky bar is re-composited every time anything beneath it repaints — every tap,
   highlight and keystroke on the catalogue — and on a phone that is the whole cost of the page.
   Touch devices get an opaque header instead (2026-09-11). */
@media (hover: none) {
    header.site { background: var(--paper); backdrop-filter: none; }
}
header.site .wrap {
    display: flex; align-items: center; gap: 26px;
    min-height: 66px; flex-wrap: wrap;
}
.brand {
    font-weight: 800; font-size: 1.2rem; letter-spacing: -.03em;
    color: var(--ink); text-decoration: none; margin-right: auto;
}
/* The mark, from the same file the browser tab uses — one source, so the lockup and the
   favicon can never drift apart. It carries its own dark-scheme colours internally; a
   browser that ignores those still renders terracotta, which reads on both backgrounds.

   Deliberately an inline-block rather than a flex item: .brand holds bare text next to a
   <span> (and the admin header adds a pill after it), so making it a flex container turns
   each of those into an item and collapses the spaces between them — "Vend esso". */
.brand::before {
    content: ""; display: inline-block; vertical-align: -.22em;
    width: 1.25em; height: 1.25em; margin-right: .4em;
    background: url("/favicon.svg") center / contain no-repeat;
}
.brand span { color: var(--accent); }
nav.site a {
    color: var(--muted); text-decoration: none; font-size: .95rem;
    margin-right: 20px; white-space: nowrap;
}
nav.site a:hover, nav.site a[aria-current="page"] { color: var(--ink); }

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

.btn {
    display: inline-block; padding: 12px 22px; border-radius: 999px;
    font-weight: 650; font-size: .98rem; text-decoration: none;
    border: 1px solid transparent; cursor: pointer; transition: transform .08s ease;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-ghost   { background: transparent; color: var(--ink); border-color: var(--border); }
.btn-row     { display: flex; gap: 12px; flex-wrap: wrap; margin: 26px 0 14px; }

/* ---------------------------------------------------------------- sections */

section { padding: 66px 0; }
section.tight { padding: 40px 0; }
.eyebrow {
    text-transform: uppercase; letter-spacing: .12em; font-size: .74rem;
    font-weight: 700; color: var(--accent); margin-bottom: 12px;
}

.hero { padding: 78px 0 56px; }
.hero h1 { max-width: 15ch; }
.hero .lede { max-width: 54ch; font-size: 1.24rem; }

.grid  { display: grid; gap: 20px; }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

.card {
    background: var(--paper-2); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 24px; box-shadow: var(--shadow);
}
.card h3 { margin-bottom: .35em; }
.card p:last-child { margin-bottom: 0; }

/* numbered steps */
.steps { counter-reset: step; display: grid; gap: 18px; }
.step { display: flex; gap: 18px; align-items: flex-start; }
.step::before {
    counter-increment: step; content: counter(step);
    flex: 0 0 34px; height: 34px; border-radius: 50%;
    background: var(--accent); color: var(--accent-ink);
    display: grid; place-items: center; font-weight: 700; font-size: .95rem;
}
.step h3 { margin-bottom: .2em; }
.step p  { margin-bottom: 0; }

/* chat sample */
.chat {
    background: var(--paper-2); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 18px; box-shadow: var(--shadow);
    display: grid; gap: 10px; font-size: .96rem;
}
.bubble { padding: 10px 14px; border-radius: 16px; max-width: 78%; width: fit-content; }
.bubble.them { background: color-mix(in srgb, var(--muted) 14%, transparent); }
.bubble.us {
    background: color-mix(in srgb, var(--green) 16%, transparent);
    margin-left: auto; border-bottom-right-radius: 5px;
}
.bubble.them { border-bottom-left-radius: 5px; }

/* pricing */
.plans { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.plan { display: flex; flex-direction: column; }
.plan.featured { border-color: var(--accent); border-width: 2px; }
.price { font-size: 2.3rem; font-weight: 800; letter-spacing: -.03em; margin: 6px 0 2px; }
.price small { font-size: .95rem; font-weight: 500; color: var(--muted); letter-spacing: 0; }
.plan ul { list-style: none; padding: 0; margin: 18px 0 24px; display: grid; gap: 9px; }
.plan li { padding-left: 26px; position: relative; }
.plan li::before {
    content: "✓"; position: absolute; left: 0; color: var(--green); font-weight: 700;
}
.plan .btn { margin-top: auto; text-align: center; }

/* FAQ */
details {
    border-bottom: 1px solid var(--border); padding: 18px 0;
}
details summary {
    cursor: pointer; font-weight: 650; list-style: none;
    display: flex; justify-content: space-between; gap: 16px;
}
details summary::-webkit-details-marker { display: none; }
details summary::after { content: "+"; color: var(--accent); font-weight: 700; }
details[open] summary::after { content: "–"; }
details p { margin: 12px 0 0; color: var(--muted); }

/* callout */
/* Longhand, not shorthand — .callout is combined with .narrow on the pricing page, and a
   `margin` shorthand here overrides that class's `margin: 0 auto`, so the callout sat flush
   left while every other block on the page was centred. `padding` shorthand loses .narrow's
   22px right padding the same way, running the text to the screen edge on a phone. Same trap
   the .legal rule below documents. Leaving margin-left/right and padding-right unset lets
   .narrow supply them, and changes nothing for the seven standalone callouts. */
.callout {
    border-left: 3px solid var(--accent);
    padding-top: 4px; padding-bottom: 4px; padding-left: 20px;
    margin-top: 28px; margin-bottom: 28px;
    color: var(--muted);
}

/* legal pages.
   Vertical padding only — these elements also carry .narrow, and a `padding` shorthand
   here would wipe out its horizontal padding, running the text into the screen edge. */
.legal { padding-top: 48px; padding-bottom: 72px; }
.legal h2 { margin-top: 2em; font-size: 1.3rem; }
.legal ul { padding-left: 22px; }
.legal li { margin-bottom: .5em; }

/* ---------------------------------------------------------------- portal */

.portal-centre {
    min-height: 100vh; display: grid; place-items: center; padding: 24px;
}
.portal-card { max-width: 480px; width: 100%; padding: 34px 30px; }
.portal-card .brand { display: inline-block; margin-bottom: 22px; }
.portal-card h1 { font-size: 1.6rem; }
.portal-card .btn { width: 100%; text-align: center; margin-top: 8px; }
.portal-note { font-size: .88rem; margin: 20px 0 0; }

/* --------------------------------------------- second factor: keys and codes

   Both of these are strings a person copies BETWEEN two devices by eye. Monospace and generous
   letter-spacing are not decoration here — an O read as a 0 costs a failed enrolment, and the
   recovery alphabet already drops the confusable characters for the same reason. */

.setup-key {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    /* Wrap only at the spaces between groups. break-all would split a group across two lines,
       which defeats the point of grouping it — the eye loses its place mid-key. */
    font-size: 1.05rem; font-weight: 650; letter-spacing: .12em;
    word-break: normal; overflow-wrap: normal;
    background: var(--paper-2); border: 1px solid var(--border);
    border-radius: 10px; padding: 14px 16px; margin: 0 0 10px;
}
.recovery-codes {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 1rem; letter-spacing: .06em; line-height: 1.9;
    background: var(--paper-2); border: 1px solid var(--border);
    border-radius: 12px; padding: 18px 20px; margin: 6px 0 20px;
    columns: 2; column-gap: 20px; white-space: pre-wrap;
}
.warn { color: var(--accent); font-weight: 650; }

@media (max-width: 460px) { .recovery-codes { columns: 1; } }

/* The codes are the only thing worth printing on this whole site. */
@media print {
    header.site, nav, .btn, .btn-row, .portal-note { display: none !important; }
    .recovery-codes { border: 1px solid #000; columns: 2; }
}

/* ------------------------------------------------------- catalogue manager */

.crumbs { margin: 26px 0 14px; font-size: .95rem; color: var(--muted); }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:last-child { color: var(--ink); font-weight: 650; }
.crumbs a:hover { color: var(--ink); }
.crumbs span { opacity: .5; margin: 0 2px; }

.rows { display: grid; gap: 10px; margin-top: 8px; }
.row {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    background: var(--paper-2); border: 1px solid var(--border);
    border-radius: 12px; padding: 15px 18px;
}
/* The order row's controls. `flex: none` so a long product name never squeezes them; on narrow
   screens .row turns column and they drop below on their own. */
.row-act { flex: none; display: flex; gap: 8px; align-items: center; }
.row[data-open] { cursor: pointer; }
.row[data-open]:hover { border-color: var(--accent); }
.small { font-size: .86rem; }

.thumb {
    width: 46px; height: 46px; flex: 0 0 46px; border-radius: 9px;
    object-fit: cover; background: color-mix(in srgb, var(--muted) 12%, transparent);
}
.thumb-empty {
    display: grid; place-items: center; font-size: 1rem; opacity: .45;
}
.photo-current { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.photo-current img {
    width: 82px; height: 82px; object-fit: cover; border-radius: 10px;
    border: 1px solid var(--border);
}
.sheet input[type="file"] { padding: 9px; font-size: .9rem; }
.btn-sm { padding: 7px 13px; font-size: .86rem; }

label {
    display: block; font-weight: 650; font-size: .92rem;
    margin: 18px 0 6px;
}
.sheet input {
    width: 100%; padding: 11px 13px; font: inherit; font-size: .97rem;
    background: var(--paper); color: var(--ink);
    border: 1px solid var(--border); border-radius: 10px;
}
.sheet input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.sheet .muted.small { margin: 6px 0 0; }

.attr-row { display: flex; gap: 8px; margin-bottom: 8px; align-items: center; }
.attr-row input { flex: 1; min-width: 0; }

.veil {
    position: fixed; inset: 0; z-index: 50; padding: 20px;
    background: rgba(10, 16, 14, .55);
    display: grid; place-items: center; overflow-y: auto;
}
/* An author `display` beats the browser's [hidden] rule, so the dialog would sit open on
   load. Restate it here — every element toggled by the `hidden` attribute needs this. */
.veil[hidden] { display: none; }
.sheet { max-width: 460px; width: 100%; max-height: 90vh; overflow-y: auto; }
.sheet h3 { margin-bottom: 4px; }
.sheet-error {
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    border-left: 3px solid var(--accent);
    padding: 10px 14px; border-radius: 0 8px 8px 0; margin: 18px 0 0; font-size: .92rem;
}

@media (max-width: 560px) {
    .row { flex-direction: column; align-items: flex-start; gap: 10px; }
    .attr-row { flex-wrap: wrap; }
}

.field {
    width: 100%; padding: 11px 13px; font: inherit; font-size: .97rem;
    background: var(--paper); color: var(--ink);
    border: 1px solid var(--border); border-radius: 10px;
}
.field:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.field:disabled { opacity: .45; }

.hour-row {
    display: grid; grid-template-columns: 52px 1fr 1fr 1fr;
    gap: 8px; align-items: center; margin-bottom: 8px;
}
.hour-day { font-weight: 650; font-size: .9rem; }
.zone-row .zname { flex: 2; }
.zone-row .zfee { flex: 1; }

@media (max-width: 560px) {
    .hour-row { grid-template-columns: 46px 1fr; grid-template-areas: "day state" "open close"; }
    .hour-row .hour-day { grid-area: day; }
    .hour-row .hstate { grid-area: state; }
    .hour-row .hopen { grid-area: open; }
    .hour-row .hclose { grid-area: close; }
}

/* ------------------------------------------------------------ charts */

.chart-wrap { overflow-x: auto; margin-top: 14px; }
.chart-wrap svg { width: 100%; min-width: 420px; height: auto; display: block; }
.chart-wrap .bar { fill: var(--accent); }
.chart-wrap .grid { stroke: var(--border); stroke-width: 1; }
.chart-wrap .axis { fill: var(--muted); font-size: 11px; }

.hbars { display: grid; gap: 10px; margin-top: 14px; }
.hbar { display: grid; grid-template-columns: minmax(90px, 1.4fr) 2fr auto; gap: 12px; align-items: center; }
.hbar-label { font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hbar-track { background: color-mix(in srgb, var(--muted) 16%, transparent); border-radius: 999px; height: 10px; }
.hbar-fill { display: block; background: var(--green); border-radius: 999px; height: 10px; }
.hbar-val { font-size: .84rem; color: var(--muted); white-space: nowrap; }

.stat { display: flex; flex-direction: column; gap: 4px; }
.stat-label { font-size: .8rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
/* A tile that wants attention — delivery falling behind, sends failing. */
.stat-warn { border-color: var(--accent); }
.stat-warn .stat-value { color: var(--accent); }
.stat-value { font-size: 1.7rem; font-weight: 800; letter-spacing: -.02em; }

.pill {
    display: inline-block; font-size: .72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; padding: 3px 9px; border-radius: 999px; vertical-align: 2px;
    background: color-mix(in srgb, var(--muted) 18%, transparent); color: var(--muted);
}
.pill-paid, .pill-closed { background: color-mix(in srgb, var(--green) 18%, transparent); color: var(--green); }
.pill-pending_payment { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
/* Between paid and delivered: the money is in and the goods have left her, but the order is not
   finished. Green like paid — it is good news — and outlined so it still reads as in-flight. */
.pill-dispatched {
    background: color-mix(in srgb, var(--green) 10%, transparent);
    color: var(--green);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--green) 35%, transparent);
}

@media (max-width: 560px) {
    .hbar { grid-template-columns: 1fr auto; }
    .hbar-track { grid-column: 1 / -1; }
}

.idle-warn {
    position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
    z-index: 60; max-width: min(560px, calc(100vw - 32px));
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    background: var(--paper-2); border: 1px solid var(--accent);
    border-radius: 12px; padding: 14px 18px; box-shadow: var(--shadow);
    font-size: .93rem;
}

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

footer.site {
    border-top: 1px solid var(--border); padding: 40px 0; margin-top: 40px;
    color: var(--muted); font-size: .92rem;
}
footer.site .cols { display: flex; gap: 40px; flex-wrap: wrap; justify-content: space-between; }
footer.site a { color: var(--muted); text-decoration: none; display: block; margin-bottom: 8px; }
footer.site a:hover { color: var(--ink); }
footer.site h4 { font-size: .8rem; text-transform: uppercase; letter-spacing: .1em; color: var(--ink); margin: 0 0 12px; }

@media (max-width: 640px) {
    section { padding: 48px 0; }
    .hero  { padding: 52px 0 40px; }
    nav.site a { margin-right: 14px; font-size: .9rem; }
    /* The header CTA wraps to its own line on narrow screens and swallows the fold.
       Every page carries an in-body CTA, so drop it here rather than stack it. */
    header.site .btn { display: none; }
    header.site .wrap { min-height: 58px; flex-wrap: nowrap; }
    /* ⚠ THE NAV WAS CLIPPED, NOT WRAPPED, AND THREE PAGES WERE UNREACHABLE. With six portal
       links the row runs to ~566px inside a 375px viewport, and because the header does not
       scroll horizontally the tail was simply cut off: Orders, Settings and Excluded could not
       be opened on a phone at all. Measured, not guessed — scrollWidth equalled clientWidth,
       which is what says "clipped" rather than "scrollable".
       Scrolled rather than wrapped: wrapping doubles the header height and swallows the fold on
       the one screen where vertical space is scarcest. */
    /* ⚠ A SCROLLABLE THING THAT DOES NOT LOOK SCROLLABLE IS A HIDDEN THING. The fade alone was
       not an affordance — it reads as a rendering artifact, and the last link was cut mid-word
       with nothing to say another one existed. `data-more` is set by the header script whenever
       there is content past the right edge and cleared at the end of the scroll, so the cue is
       honest: it appears only when there IS more, and goes away once she has seen it.
       The fade is kept as well: together they read as "this continues", where either alone is a
       smudge or a floating character. */
    nav.site {
        display: flex; flex-wrap: nowrap; min-width: 0;
        overflow-x: auto; -webkit-overflow-scrolling: touch;
        scrollbar-width: none; -ms-overflow-style: none;
    }
    nav.site::-webkit-scrollbar { display: none; }
    /* Hung off header.site .wrap, which every portal page already has. A wrapper element around
       the nav would have meant editing nine duplicated headers to add a hint. */
    header.site .wrap { position: relative; }
    header.site .wrap[data-more="1"] nav.site {
        mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    }
    header.site .wrap[data-more="1"]::after {
        content: "›"; position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
        font-size: 1.25rem; line-height: 1; color: var(--accent); pointer-events: none;
    }
    nav.site a:last-child { margin-right: 0; padding-right: 4px; }
    /* The ADMIN header carries eight links where the marketing one carries four, and with the
       links set to nowrap that pushed the whole document 267px wider than a phone — every admin
       page scrolled sideways, which reads as broken long before anyone works out why. Scroll the
       nav itself instead: wrapping would stack it two rows deep and eat the fold, which is what
       hiding the CTA above was avoiding. min-width:0 is the part that matters — a flex item
       defaults to min-width:auto and refuses to shrink below its content. */
    nav.site {
        min-width: 0; overflow-x: auto; scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }
    nav.site::-webkit-scrollbar { display: none; }
}

/* ------------------------------------------------- share: consent toggles

   Each sensitive layer is its own row with its own warning, rather than one "share my
   catalogue" switch. "Include my bargaining limits — the lowest price you'll accept" is a
   decision a vendor can actually weigh; "share my catalogue" is not. */

.opt {
    display: flex; align-items: flex-start; gap: 12px;
    background: var(--paper-2); border: 1px solid var(--border);
    border-radius: 12px; padding: 14px 16px; margin-top: 10px; cursor: pointer;
}
.opt input { margin-top: 3px; flex: 0 0 auto; }
.opt span { display: flex; flex-direction: column; gap: 3px; }
.opt em { font-style: normal; }

/* ── a buyer waiting for a human (dashboard) ──────────────────────────────────
   One row per handed-over thread. The button sits at the end of the line it is
   about, so "I've replied" can never be read as applying to the whole list. */
.wait-row { display: flex; align-items: center; justify-content: space-between;
            gap: 12px; padding: 10px 0; border-top: 1px solid var(--border); }
.wait-row:first-of-type { margin-top: 6px; }
@media (max-width: 480px) {
  .wait-row { flex-direction: column; align-items: flex-start; gap: 6px; }
}
