/* Scroll Theory Forms — neutral base stylesheet for the hosted checkout, v1.

   Styles every class client shop.v1.js writes, on a strange page, with zero
   work from the shop owner. The knobs are the variables below: a later install
   panel (or a style block in the hosted page) overrides accent, radius and font
   and the whole sheet follows. Templates do NOT load this file — each template
   keeps its own look; this sheet exists so a checkout with no template behind
   it still looks deliberate. */

:root {
  /* Deep ink, not a color: the default has to sit beside ANY brand without
     arguing (the first teal default read as "tacky off-green" on a real
     page). Shops pick their own in Products -> Your shop -> Checkout color. */
  --shop-accent: #20262b;
  --shop-accent-ink: #ffffff;
  --shop-ink: #23272b;
  --shop-muted: #6a7076;
  --shop-bg: #f7f6f4;
  --shop-panel: #ffffff;
  --shop-line: #e3e1dd;
  --shop-danger: #a33c2e;
  --shop-good: #2e6e46;
  --shop-radius: 10px;
  --shop-font: system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font: 16px/1.55 var(--shop-font);
  color: var(--shop-ink);
  background: var(--shop-bg);
}
/* height:auto is load-bearing, not tidiness. Every photo carries width and
   height ATTRIBUTES (the widget sets them so the layout reserves space before
   the bytes arrive). Constraining only the width then leaves the attribute
   height standing, and a square 900x900 loaf rendered 316 wide x 810 tall on a
   phone — Chad's stretched bread, 2026-08-24. */
img { max-width: 100%; height: auto; display: block; }
button { font: inherit; cursor: pointer; }

/* ---- the hosted page's own chrome ------------------------------------- */

.hosted-head {
  max-width: 1100px; margin: 0 auto; padding: 28px 20px 4px;
}
.hosted-head h1 { margin: 0; font-size: 1.5rem; letter-spacing: -.01em; }
.hosted-main { max-width: 1100px; margin: 0 auto; padding: 16px 20px 64px; }
/* Inside the popup iframe the frame is the chrome; the page keeps only content. */
body.embedded .hosted-head { display: none; }
body.embedded .hosted-main { padding-top: 20px; }

/* ---- load-bearing hides ------------------------------------------------ */

/* The honeypot. If this rule is lost, humans see "Leave this field empty",
   some of them fill it, and their real orders land in quarantine. */
.hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; clip: rect(0 0 0 0); overflow: hidden;
}

/* ---- layout: products beside the cart --------------------------------- */

.shopwrap { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 28px; align-items: start; }
@media (max-width: 880px) { .shopwrap { display: block; } }

/* ---- toolbar: tabs, search, count -------------------------------------- */

.shopbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 0 0 18px; }
.shoptabs { display: flex; flex-wrap: wrap; gap: 6px; }
.shoptab {
  border: 1px solid var(--shop-line); background: var(--shop-panel); color: var(--shop-ink);
  border-radius: 999px; padding: 6px 14px; font-size: .9rem;
}
/* The widget marks the pressed tab with .on (plus aria-pressed) — .active is
   kept only because old snapshots used it. The mismatch left the open tab
   looking identical to the rest (Chad, 2026-08-24). */
.shoptab.on, .shoptab.active, .shoptab[aria-pressed="true"] {
  background: var(--shop-accent); border-color: var(--shop-accent); color: var(--shop-accent-ink);
}
/* .shopsearch is a WRAPPER around the label and the input (found glued
   together on Ugly Duck, 2026-08-23) — the pill is the wrapper, the input
   inside it goes bare. The divider marks where typing actually lands; the
   label half is a real <label>, so clicking it focuses the input anyway. */
/* Allowed to SHRINK. The label refuses to wrap and the input carried a
   170px floor, so the pill was ~330px of unbreakable width — wider than the
   content column of a 360px phone, which is where the horizontal scroll on
   Chad's embed came from (2026-08-24). flex-shrink plus min-width:0 lets it
   give way; it still takes the whole row when the row has room. */
.shopsearch {
  display: flex; align-items: center; gap: .6rem; margin-left: auto;
  border: 1px solid var(--shop-line); border-radius: 999px; padding: 6px 14px;
  background: var(--shop-panel); cursor: text;
  flex: 1 1 220px; min-width: 0; max-width: 100%;
}
.shopsearch-lab { font-size: .85rem; color: var(--shop-muted); white-space: nowrap; cursor: pointer; }
.shopq {
  border: 0; background: none; font: inherit; color: var(--shop-ink); outline: none;
  border-left: 1px solid var(--shop-line); border-radius: 0; padding-left: 10px;
  flex: 1 1 auto; min-width: 0; width: 100%;
}
.shopcount, .shopempty { width: 100%; margin: 0; color: var(--shop-muted); font-size: .9rem; }
/* Opt-in heading for embeds (Products -> Your shop). Deliberately restrained:
   it sits on someone else's page, under their own branding. */
.shopname { margin: 0 0 14px; font-size: 1.5rem; line-height: 1.2; color: var(--shop-ink); }

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

.prodgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 18px; }
.prod {
  background: var(--shop-panel); border: 1px solid var(--shop-line);
  border-radius: var(--shop-radius); padding: 14px; display: flex; flex-direction: column; gap: 8px;
}
.prodmedia { position: relative; margin: -14px -14px 4px; }
.prodshot {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--shop-radius) var(--shop-radius) 0 0;
}
.prodzoom {
  position: absolute; right: 8px; bottom: 8px; border: 0; border-radius: 999px;
  width: 30px; height: 30px; background: rgba(20,24,28,.55); color: #fff; font-size: .9rem;
}
.prodcat { color: var(--shop-muted); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; margin: 0; }
.prod h3, .prod h4 { margin: 0; font-size: 1.05rem; line-height: 1.3; }
.desc { margin: 0; color: var(--shop-muted); font-size: .92rem; }
.pp, .lineprice, .amt, .cl-price, .fc-price, .cl-txt strong { font-variant-numeric: tabular-nums; }
.pp { font-weight: 600; }
.prodstock { color: var(--shop-muted); font-size: .85rem; margin: 0; }
.prodsold { color: var(--shop-danger); font-weight: 600; font-size: .85rem; margin: 0; }
.prodcount { min-width: 1.5em; text-align: center; font-variant-numeric: tabular-nums; }

/* The product opener: the text block under the photo IS the click target — a
   button when the product opens a panel, a plain div when it is simple enough
   to add directly. Unstyled it wore the browser's gray button chrome, which
   read as a broken element in every screenshot until someone asked (2026-08-23). */
.prodpick {
  display: block; width: 100%; border: 0; background: none; padding: 2px 0 0;
  font: inherit; color: inherit; text-align: center; cursor: pointer;
}
div.prodpick { cursor: default; }
.prodpick h3 { margin: 0 0 2px; }
.prodpick p { margin: 0 0 4px; color: var(--shop-muted); font-size: .92rem; }
/* Price and the stock note are sibling spans — inline they read as one word
   ("$10All of them are in your order", Ugly Duck 2026-08-23). */
.prodpick .pp, .prodpick .prodstock, .prodpick .prodsold { display: block; }
.prodpick .prodstock, .prodpick .prodsold { margin-top: .2rem; }
button.prodpick:hover h3 { color: var(--shop-accent); }

/* quantity steppers, size grids, add-ons, tiers.
   .prodstep is EACH +/- button, with the .prodcount span between them. */
/* Centered, because the card's text is centered — a left-hugging button under
   centered words reads as a mistake (Dave's Dough, 2026-08-23). */
.prodadd, .qtyrow { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: auto; }
.prodstep {
  width: 30px; height: 30px; border: 1px solid var(--shop-line); background: var(--shop-panel);
  border-radius: 999px; font-weight: 600; line-height: 1; color: inherit;
}
.prodstep:hover { border-color: var(--shop-accent); }
.prodstep[disabled] { opacity: .45; cursor: default; }
.prodaddbtn {
  border: 1px solid var(--shop-accent); background: var(--shop-accent); color: var(--shop-accent-ink);
  border-radius: 999px; padding: 7px 16px; font-weight: 600;
}
.prodaddbtn:hover { filter: brightness(1.08); }
/* The panel photo IS a button (click to enlarge) — it must look like a photo,
   not like a call-to-action. Caught live on GHL: the CTA pill treatment
   squeezed the image inside a teal capsule. */
.cfgshotbtn {
  border: 0; background: none; padding: 0; display: block; width: fit-content;
  line-height: 0; border-radius: var(--shop-radius); overflow: hidden; cursor: zoom-in;
}
.sizegrid { display: flex; flex-wrap: wrap; gap: 6px; }
/* The chip is radio + label + price in a row; without flex they typeset as one
   word ("3 tacos$12", Chad 2026-08-24). Written with the container prefix
   because the chip is a <label> inside .cfg, and ".cfg label" (display:block,
   margins) outranks a bare class — the same fight ".cartbox form" documents. */
.sizegrid .sizeopt, .tierrow .sizeopt {
  border: 1px solid var(--shop-line); border-radius: 999px; padding: 6px 14px;
  background: var(--shop-panel); font-size: .88rem; margin: 0; font-weight: 400;
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
}
.sizeopt.sel, .sizeopt[aria-pressed="true"] { border-color: var(--shop-accent); background: var(--shop-accent); color: var(--shop-accent-ink); }
.addonrow, .tierrow { display: flex; align-items: center; gap: 8px; font-size: .92rem; }
.addonrow .ap { margin-left: 2px; }

/* the per-item configurator panel (cottage/dropdown styles) */
.cfg {
  background: var(--shop-panel); border: 1px solid var(--shop-line);
  border-radius: var(--shop-radius); padding: 16px; margin: 0 0 16px;
}
.cfg label { display: block; font-weight: 600; margin: 10px 0 4px; }
.cfg select { width: 100%; }
/* Stacked, not side-by-side: the config column is narrow even on desktop, and
   side-by-side squeezed "Pick a size" into a two-line sliver beside the button
   (Chad, 2026-08-24). Price/note centered above a full-width Add to Order. */
.cfgfoot { display: flex; flex-direction: column; align-items: stretch; gap: 8px; margin-top: 12px; }
.cfgfoot .lineprice { text-align: center; }
.cfgfoot .btn { width: 100%; }
/* The quantity stepper's plus and minus are real buttons, not keyboard keys. */
.qtyrow button {
  min-width: 34px; min-height: 34px; border: 1px solid var(--shop-line);
  background: var(--shop-panel); border-radius: 8px; cursor: pointer;
  font-size: 1rem; line-height: 1;
}
.qtyrow span { min-width: 2ch; text-align: center; font-variant-numeric: tabular-nums; }
.cfgshot { width: min(240px, 100%); height: auto; border-radius: var(--shop-radius); }
.fc-txt { margin: 0; }
.fc-note { color: var(--shop-muted); font-size: .88rem; margin: 4px 0 0; }

/* ---- the cart ----------------------------------------------------------- */

.cartbox {
  background: var(--shop-panel); border: 1px solid var(--shop-line);
  border-radius: var(--shop-radius); padding: 18px; position: sticky; top: 16px;
}
.cartbox h2, .cartbox h3 { margin: 0 0 10px; font-size: 1.15rem; }
.cartcount { color: var(--shop-muted); font-size: .9rem; margin-left: .5rem; }
.cartline b { margin-right: .4rem; }
.cartempty { color: var(--shop-muted); margin: 8px 0; }
.cartline {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--shop-line); font-size: .95rem;
}
.cartline button { border: 0; background: none; color: var(--shop-muted); font-size: .85rem; }
.cartline button:hover { color: var(--shop-danger); }
.carttotal, .sub, .grand { display: flex; justify-content: space-between; gap: 10px; padding: 6px 0; margin: 0; }
.grand { font-weight: 700; border-top: 1px solid var(--shop-line); margin-top: 4px; padding-top: 10px; }
.cartnote { color: var(--shop-muted); font-size: .85rem; }
@keyframes shop-added { from { background: color-mix(in srgb, var(--shop-accent) 18%, transparent); } to { background: none; } }
.justadded { animation: shop-added 1.2s ease-out; }

/* ---- the order form ----------------------------------------------------- */

.cartbox form { margin-top: 12px; }
.cartbox form label { display: block; font-weight: 600; font-size: .92rem; margin: 12px 0 4px; }
.cartbox input[type="text"], .cartbox input[type="email"], .cartbox input[type="tel"],
.cartbox textarea, .cartbox select, .cfg select {
  width: 100%; border: 1px solid var(--shop-line); border-radius: calc(var(--shop-radius) - 3px);
  padding: 9px 12px; font: inherit; color: var(--shop-ink); background: var(--shop-panel);
}
.cartbox textarea { min-height: 74px; resize: vertical; }

/* fulfilment + payment choices are radio rows that read as buttons.
   .fulrow is the bare pickup/ship pair; .fulchoice the shop's own delivery
   options (inside .shiplist); .paychoice how they pay. Written with the
   .cartbox form prefix on purpose: the generic ".cartbox form label" rule
   above says display:block, and these must outrank it — the live symptom of
   losing that fight was bare radios glued to their words (Chad, 2026-08-23). */
.fulrow, .shiplist, .paywrap { display: flex; flex-direction: column; gap: 6px; }
.cartbox form .fulrow label, .cartbox form .fulchoice,
.cartbox form .paychoice, .cartbox form .payrow label {
  display: flex; align-items: center; gap: 10px; font-weight: 400;
  border: 1px solid var(--shop-line); border-radius: calc(var(--shop-radius) - 3px);
  padding: 10px 12px; margin: 0; background: var(--shop-panel);
}
.cartbox form .fulrow label.sel, .cartbox form .fulchoice.sel,
.cartbox form .paychoice.sel { border-color: var(--shop-accent); }
.fc-txt, .pc-txt { display: flex; flex-direction: column; flex: 1; }
.fc-price { margin-left: auto; }
.pc-detail { color: var(--shop-muted); font-size: .85rem; }
.shiplist { margin: 6px 0 0; }
.paynote { color: var(--shop-muted); font-size: .85rem; margin: 4px 0 0; }
/* Even split, not 2fr 1fr: the state is picked from a list now, and the third
   of a narrow cart column that a typed "OH" needed clips "Massachusetts". */
.addrrow { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.codewrap { margin-top: 12px; }
.coderow { display: flex; gap: 8px; }
.coderow input { flex: 1; }
.coderow button {
  border: 1px solid var(--shop-line); background: var(--shop-panel);
  border-radius: calc(var(--shop-radius) - 3px); padding: 0 16px;
}
.codenote { font-size: .85rem; margin: 4px 0 0; }
.codenote.ok { color: var(--shop-good); }
.codenote.err { color: var(--shop-danger); }

.ts-mount { margin-top: 14px; }

.btn, button.btn {
  display: block; width: 100%; margin-top: 14px;
  border: 1px solid var(--shop-accent); background: var(--shop-accent); color: var(--shop-accent-ink);
  border-radius: 999px; padding: 12px 18px; font-weight: 700; font-size: 1rem;
}
.btn:hover { filter: brightness(1.08); }
.btn[disabled] { opacity: .6; cursor: default; }
.btn-solid { background: var(--shop-accent); color: var(--shop-accent-ink); }

.form-note { min-height: 1.4em; margin: 10px 0 0; font-size: .95rem; }
.form-note.success { color: var(--shop-good); }
.form-note.error { color: var(--shop-danger); }

/* ---- lightbox, holding state ------------------------------------------- */

.lightbox {
  position: fixed; inset: 0; z-index: 2147483000; background: rgba(20,24,28,.72);
  display: flex; align-items: center; justify-content: center; padding: 4vw;
}
/* width:auto beside max-height, so a TALL photo shrinks its width to fit the
   viewport instead of keeping the attribute width and overflowing. */
.lb-img { max-width: 100%; max-height: 90vh; width: auto; height: auto; border-radius: var(--shop-radius); }
.lb-close {
  position: absolute; top: 14px; right: 14px; width: 36px; height: 36px;
  border: 0; border-radius: 999px; background: rgba(255,255,255,.14); color: #fff; font-size: 1.1rem;
}
.stocking {
  background: var(--shop-panel); border: 1px solid var(--shop-line);
  border-radius: var(--shop-radius); padding: 28px; text-align: center; color: var(--shop-muted);
}

/* The item sheet: the configurator, given the whole phone. Its GEOMETRY is set
   inline by the widget (so it works on template sites that never loaded this
   file); what follows is only how it looks where this stylesheet is present. */
.cfg-sheet {
  padding: 18px 16px calc(18px + env(safe-area-inset-bottom, 0px));
  background: var(--shop-panel);
}
.cfg-sheet .cfgshotbtn { width: 100%; }
.cfg-sheet .cfgshot { width: 100%; max-height: 42vh; object-fit: cover; }
/* The commit button rides the bottom of the sheet where a thumb reaches it. */
.cfg-sheet .cfgfoot {
  position: sticky; bottom: 0; background: var(--shop-panel);
  padding: 10px 0 calc(4px + env(safe-area-inset-bottom, 0px)); margin-top: 16px;
  border-top: 1px solid var(--shop-line);
}

/* ---- foreign-page armor -------------------------------------------------- */
/* Inline installs render inside someone else's stylesheet (first seen live on
   GoHighLevel, 2026-08-23: theme borders leaking onto product text, radio
   buttons losing their gap, images losing their crop). EVERY selector here is
   wrapped in :where() — including #shop-root itself, because a bare ID carries
   top specificity and the first version of this armor beat this file's own
   named rules with it: label borders vanished from the choice rows and the
   submit button stopped stretching. Zero specificity beats browser defaults
   and host-theme element rules, and loses to every named rule below and every
   classed host rule alike. */
:where(#shop-root), :where(#shop-root) * { box-sizing: border-box; }
:where(#shop-root) :where(img) { border: 0; max-width: 100%; }
:where(#shop-root) :where(input[type="radio"], input[type="checkbox"]) {
  width: auto; min-width: 0; margin: 0; flex: none; accent-color: var(--shop-accent);
}
:where(#shop-root) :where(p, h2, h3, h4, span, b, label) {
  border: 0; box-shadow: none; text-transform: none; letter-spacing: normal;
}
:where(#shop-root) :where(button) { text-transform: none; letter-spacing: normal; width: auto; }
:where(#shop-root) :where(input, select, textarea) { max-width: 100%; }
/* The crop must hold even against a theme's img rules: a portrait product
   photo otherwise renders at full height and the card grows around it. */
:where(#shop-root) .prodshot { height: auto; aspect-ratio: 4 / 3; object-fit: cover; }

/* ---- access + motion ---------------------------------------------------- */

:focus-visible { outline: 2px solid var(--shop-accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .justadded { animation: none; }
  * { scroll-behavior: auto !important; }
}

/* ---- phones -------------------------------------------------------------
   LAST IN THE FILE ON PURPOSE. The armor above re-states .prodshot's 4/3 crop
   at the same specificity, so anything written earlier lost the tie and the
   thumbnail stayed letterboxed.

   A card built for a grid column becomes a poster on a phone: photo, name,
   description and price stacked ~390px tall, so one product filled the screen
   and browsing meant scrolling past everything (Chad, 2026-08-24). Below 560px
   the card becomes a ROW — square thumbnail left, words right — the shape every
   food-ordering app settled on, at under a third the height. Grid rather than
   flex so a two-child card (photo + text) and a three-child one (photo + text +
   Add row) both land right, and a card with NO photo leaves an auto column that
   collapses to nothing. */
@media (max-width: 560px) {
  .prodgrid { grid-template-columns: 1fr; gap: 10px; }
  .prod {
    display: grid; grid-template-columns: auto 1fr; column-gap: 12px; row-gap: 6px;
    align-items: start; padding: 10px;
  }
  .prodmedia { grid-column: 1; grid-row: 1 / -1; margin: 0; width: 92px; }
  .prod > :not(.prodmedia) { grid-column: 2; min-width: 0; }
  .prodshot, :where(#shop-root) .prodshot {
    aspect-ratio: 1 / 1; border-radius: calc(var(--shop-radius) - 2px);
  }
  /* Kept, not hidden: a simple product has no sheet to open, so this stays the
     only way to see its photo big. Just sized for a 92px thumbnail. */
  .prodzoom { right: 3px; bottom: 3px; width: 22px; height: 22px; font-size: .68rem; }
  .prodpick { text-align: left; }
  .prod h3, .prod h4, .prodpick h3 { font-size: 1rem; }
  /* Two lines is enough to recognise the thing; the rest is one tap away. */
  .prodpick p, .prod .desc {
    font-size: .85rem; display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical; overflow: hidden;
  }
  .prodadd, .qtyrow { justify-content: flex-start; margin-top: 4px; }
  .prodaddbtn { padding: 6px 14px; font-size: .9rem; }
  .shopbar { gap: 8px; }
  .cartbox { padding: 14px; }
}
