/* Zolak shop — DESIGN.md §3. Every value is a token from tokens.css; the one
   exception is --zlk-card-min, the grid's sizing lever (DESIGN.md §3.2),
   which tokens.css does not declare and which this file therefore owns. */

:root {
  --zlk-card-min: 150px;
}

@media (min-width: 720px) {
  :root { --zlk-card-min: 220px; }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: var(--zlk-text-base)/1.5 system-ui, sans-serif;
  background: var(--zlk-ink-0);
  color: var(--zlk-ink-5);
}

main {
  max-width: 1100px;
  margin: 0 auto;
  padding: var(--zlk-space-4);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

h1 { font-size: var(--zlk-text-2xl); }

/* --- The entablature header, DESIGN.md §4 -------------------------------- */

.zlk-header {
  background: var(--zlk-ink-0);
  border-bottom: var(--zlk-card-border);
}

.zlk-brand {
  display: block;
  max-width: 1100px;
  margin: 0 auto;
  padding: var(--zlk-space-3) var(--zlk-space-4);
}

/* Colour comes from CSS so the mark sits inside the token system. */
.zlk-mark { color: var(--zlk-yellow); }
.zlk-mark-band { fill: currentColor; }
.zlk-mark-word { fill: var(--zlk-ink-0); font-family: var(--zlk-font-display); }
.zlk-mark-plate {
  fill: var(--zlk-green-bright);
  font-family: var(--zlk-font-display);
  transform: translate(var(--zlk-misreg-x), var(--zlk-misreg-y));
}

/* Sized by HEIGHT, never width: the viewBox is 332x100, so width:100% on a
   1520px viewport renders a 458px-tall banner. */
.zlk-mark-entablature { display: block; height: clamp(36px, 7vw, 56px); width: auto; }

/* --- Category navigation, DESIGN.md §3.3 --------------------------------- */

.zlk-chip-bar {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  /* "safe" so a rail wider than the viewport still starts at the first chip
     instead of overflowing off the left edge, unreachable. */
  justify-content: safe center;
  gap: var(--zlk-space-2);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  padding: var(--zlk-space-3) var(--zlk-space-4);
  background: var(--zlk-ink-0);
  border-bottom: var(--zlk-card-border);
}

.zlk-chip {
  scroll-snap-align: start;
  flex: none;
  min-height: var(--zlk-touch-target);
  display: inline-flex;
  align-items: center;
  padding: 0 var(--zlk-space-4);
  border-radius: var(--zlk-radius-pill);
  background: var(--zlk-ink-2);
  color: var(--zlk-ink-5);
  text-decoration: none;
  font-size: var(--zlk-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Clear the sticky bar, then leave air. The bar is a touch target PLUS the
   vertical padding declared on .zlk-chip-bar above -- modelling it as the
   touch target alone put every heading a pixel under the bar instead of the
   space-6 below it this was reaching for. (Its 1px border is the remaining
   difference, so the air is 23px rather than 24; a token for the bar's own
   height is what would close that, and DESIGN.md does not have one.) */
.zlk-cat-section {
  scroll-margin-top: calc(var(--zlk-touch-target) + var(--zlk-space-3) * 2
                          + var(--zlk-space-6));
}

.zlk-cat-heading {
  font-size: var(--zlk-text-xl);
  color: var(--zlk-ink-4);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* --- The grid, DESIGN.md §3.2 -------------------------------------------- */

.menu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--zlk-card-min), 1fr));
  gap: var(--zlk-space-4);
  margin-bottom: var(--zlk-space-8);
}

.zlk-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--zlk-space-2) var(--zlk-space-3);
  padding: var(--zlk-space-3);
  background: var(--zlk-surface-grad);
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-lg);
  box-shadow: var(--zlk-card-shadow);
  color: inherit;
  text-decoration: none;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.zlk-card-form { display: contents; }
.zlk-card-form .zlk-card { width: 100%; }

/* The image well, wherever a product photo lands (_media.html). Only the
   sizing differs between the card, the item page and an order line, so only
   the sizing is written per-place. The 1:1 is here rather than per-place: the
   well reserves its box before the photo loads, so a menu that renders ahead
   of its images does not jump (DESIGN.md §3.2). A place that fixes both width
   and height (the admin row thumb, the order-line thumb) wins over it. */
.zlk-well {
  display: block;
  position: relative;
  container-type: inline-size;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  background: var(--zlk-ink-2);
}

.zlk-well img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.zlk-card-well {
  grid-column: 1 / -1;
  border-radius: var(--zlk-radius-md);
}

.zlk-card-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background-image:
    repeating-linear-gradient(90deg,
      var(--zlk-ink-2) 0, var(--zlk-ink-2) 3px, transparent 3px, transparent 22px);
}

.zlk-card-fallback-letter {
  font-family: var(--zlk-font-display);
  font-size: 46cqw;
  opacity: 0.28;
  color: var(--zlk-ink-5);
  line-height: 1;
}

.zlk-card-name {
  font-size: var(--zlk-text-base);
  line-height: 1.25;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* The price reads as a tag on the card, not another line of copy. */
.zlk-card-price {
  justify-self: end;
  padding: var(--zlk-space-1) var(--zlk-space-2);
  border-radius: var(--zlk-radius-sm);
  background: color-mix(in srgb, var(--zlk-yellow) 12%, transparent);
  font-family: var(--zlk-font-display);
  /* Retron2000 is a pixel face and DESIGN.md 5 puts its floor at about 18px.
     --zlk-text-sm is 15px, so the one number a customer compares between
     products was the one set below the size its own face resolves at. */
  font-size: var(--zlk-text-lg);
  font-variant-numeric: tabular-nums;
  color: var(--zlk-yellow);
  white-space: nowrap;
}

/* Two ~150px cards to a phone row leave no room for the name beside the tag:
   the name takes the full width and the price sits under it. The kiosk lays
   out its own card (kiosk.css). */
@media (max-width: 719px) {
  body:not(.kiosk) .zlk-card { grid-template-columns: minmax(0, 1fr); }
  body:not(.kiosk) .zlk-card-price { justify-self: start; }
}

.zlk-card-plus {
  position: absolute;
  right: var(--zlk-space-3);
  bottom: var(--zlk-space-3);
  width: var(--zlk-touch-target);
  height: var(--zlk-touch-target);
  border-radius: var(--zlk-radius-pill);
  background: var(--zlk-yellow);
  color: var(--zlk-ink-0);
  display: grid;
  place-items: center;
  /* The "+" glyph's ink sits above its own baseline, so flex/line-box centring
     leaves it ~3px low in the circle -- and by a different amount in every
     font. Draw the two bars instead: centred by geometry, not by metrics.
     The span must stay empty: any text node becomes an anonymous grid item,
     which auto-places into a second implicit row and shoves the bars up. */
}

.zlk-card-plus::before,
.zlk-card-plus::after {
  grid-area: 1 / 1;
  content: "";
  width: 40%;
  height: 3px;
  border-radius: 1px;
  background: currentColor;
}

.zlk-card-plus::after { rotate: 90deg; }

/* --- The phone/desktop order bar, DESIGN.md §3.4 ------------------------- */

.zlk-order-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--zlk-space-3);
  padding: var(--zlk-space-3) var(--zlk-space-4);
  padding-bottom: calc(var(--zlk-space-3) + var(--zlk-safe-bottom));
  background: var(--zlk-ink-1);
  border-top: var(--zlk-card-border);
}

/* The two labels share one flexible column so they sit side by side when
   they fit and stack when they do not. The recovery variant ("Order ZB-0554"
   / "Awaiting payment" / "Open receipt") is too long for one phone line, and
   without this every one of the three broke into two ragged lines. Neither
   label ever breaks mid-word; the button keeps its full size. */
.zlk-order-bar-text {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--zlk-space-3);
  flex: 1;
  min-width: 0;
}

.zlk-order-bar-text > * { white-space: nowrap; }
.zlk-order-bar-total { margin-left: auto; font-variant-numeric: tabular-nums; }

body:has(.zlk-order-bar) main {
  padding-bottom: calc(var(--zlk-touch-target) * 2 + var(--zlk-safe-bottom));
}

/* --- Order lines, cart and kiosk pane, DESIGN.md §3.4 -------------------- */

.zlk-order-lines {
  list-style: none;
  margin: 0;
  padding: 0;
  container-type: inline-size;
}

.zlk-order-line {
  display: flex;
  align-items: center;
  gap: var(--zlk-space-3);
  padding: var(--zlk-space-3) 0;
  border-bottom: var(--zlk-card-border);
}

.zlk-order-line-name { flex: 1; }
.zlk-order-line-price { font-variant-numeric: tabular-nums; }

.zlk-order-total {
  font-size: var(--zlk-text-2xl);
  font-variant-numeric: tabular-nums;
}

button, input, .tappable {
  font: inherit;
  min-height: var(--zlk-touch-target);
}

/* One button. `button` and `.zlk-btn` are the same component; the class exists
   so an <a> that acts as a button (order bar, back to menu, new order) is that
   same component instead of a fourth copy of these nine lines. */
button,
.zlk-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--zlk-space-2);
  min-height: var(--zlk-touch-target);
  border: 0;
  border-radius: var(--zlk-radius-md);
  padding: 0 var(--zlk-space-4);
  background: var(--zlk-ink-2);
  color: var(--zlk-ink-5);
  font: inherit;
  text-decoration: none;
  cursor: pointer;
}

/* The one action that moves the order forward on any given page. Yellow is
   reserved for it (DESIGN.md §2.2); a second yellow button on a screen means
   the customer has to choose, which is the opposite of what it is for. */
.zlk-btn-primary {
  background: var(--zlk-yellow);
  color: var(--zlk-ink-0);
  font-weight: 700;
}

/* --- Item page, DESIGN.md §3.2 ------------------------------------------- */

.zlk-item {
  display: grid;
  gap: var(--zlk-space-6);
  align-items: start;
}

@media (min-width: 720px) {
  .zlk-item { grid-template-columns: minmax(0, 420px) minmax(0, 1fr); }
  .zlk-item-body { padding-top: var(--zlk-space-4); }
}

.zlk-item-well {
  width: 100%;
  border-radius: var(--zlk-radius-lg);
  border: var(--zlk-card-border);
  background: var(--zlk-ink-1);
}

.zlk-item h1 { margin: 0 0 var(--zlk-space-2); }

.zlk-item-price {
  font-family: var(--zlk-font-display);
  font-size: var(--zlk-text-2xl);
  font-variant-numeric: tabular-nums;
  color: var(--zlk-yellow);
  margin: 0 0 var(--zlk-space-4);
}

.zlk-item-desc { color: var(--zlk-ink-4); margin: 0 0 var(--zlk-space-6); }

.zlk-back {
  display: inline-block;
  margin-bottom: var(--zlk-space-4);
  color: var(--zlk-ink-4);
  text-decoration: none;
}


/* A rail that could not be reached, on the one screen where money is at
   stake. --zlk-danger, never yellow: yellow means "do this". */
.zlk-pay-error {
  padding: var(--zlk-space-3) var(--zlk-space-4);
  margin-bottom: var(--zlk-space-4);
  border: 1px solid var(--zlk-danger);
  border-radius: var(--zlk-radius-md);
  color: var(--zlk-danger);
}

/* The invoice timed out. --zlk-warn, not --zlk-danger: nothing went wrong and
   nothing was charged, the clock just ran out. Not yellow either — yellow is
   the one thing to do next, which is the rail tiles below it. */
/* Same box on /cart, for a line the admin deactivated out from under the
   customer: nothing went wrong and nothing was charged, an item just went. */
.zlk-pay-notice,
.zlk-cart-notice {
  padding: var(--zlk-space-3) var(--zlk-space-4);
  margin-bottom: var(--zlk-space-4);
  border: 1px solid var(--zlk-warn);
  border-radius: var(--zlk-radius-md);
  color: var(--zlk-ink-5);
  font-size: var(--zlk-text-sm);
}

.zlk-pay-notice p { margin: 0 0 var(--zlk-space-2); }
.zlk-pay-notice p:last-child { margin-bottom: 0; }
.zlk-pay-notice strong,
.zlk-cart-notice strong { color: var(--zlk-warn); }

.zlk-cart-notice { max-width: 62ch; margin-top: 0; }


/* --- Header nav, hero, footer: the bar.zolak.lt landing, in tokens -------- */

.zlk-header-row {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--zlk-space-4);
  padding: 0 var(--zlk-space-4);
}

.zlk-site-nav-right { justify-content: flex-end; }

.zlk-header-row .zlk-brand { margin: 0; }

.zlk-site-nav { display: flex; gap: var(--zlk-space-2); }

.zlk-site-nav a {
  min-height: var(--zlk-touch-target);
  display: inline-flex;
  align-items: center;
  padding: 0 var(--zlk-space-3);
  border-radius: var(--zlk-radius-pill);
  /* Not the display face: DESIGN.md 5 scopes that to "the wordmark, page and
     category headings, prices, the order total, the pickup number", and the
     wordmark is the ZOLAK inside the mark's own SVG, not the two links either
     side of it. At --zlk-text-xs the pixel face was being asked to resolve at
     13px, uppercased, in the chrome of every page. */
  font-size: var(--zlk-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--zlk-yellow);
  text-decoration: none;
}

/* Under ~480px the mark plus the links do not fit on one row: the mark keeps
   the top row to itself and the three links split the row under it in equal
   thirds. The right nav joins the parent grid via subgrid so "Kiosk mode" is
   not a half-width column of its own. */
@media (max-width: 479px) {
  .zlk-header-row {
    grid-template-columns: repeat(3, 1fr);
    gap: 0 var(--zlk-space-1);
    padding: 0 var(--zlk-space-2);
  }
  .zlk-header-row .zlk-brand { grid-row: 1; grid-column: 1 / -1; justify-self: center; }
  .zlk-site-nav-left { grid-row: 2; grid-column: 1; }
  .zlk-site-nav-right {
    grid-row: 2;
    grid-column: 2 / -1;
    display: grid;
    grid-template-columns: subgrid;
    gap: inherit;
  }
  .zlk-site-nav a {
    width: 100%;
    justify-content: center;
    padding: 0;
    letter-spacing: 0;
    white-space: nowrap;
  }
}

h1, h2 {
  font-family: var(--zlk-font-display);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.1;
}

h1 { color: var(--zlk-yellow); }

.zlk-hero {
  padding: var(--zlk-space-8) 0 var(--zlk-space-6);
  border-bottom: var(--zlk-card-border);
  margin-bottom: var(--zlk-space-6);
}

.zlk-hero h1 { margin: 0 0 var(--zlk-space-3); }

.zlk-hero h1 { margin-bottom: var(--zlk-space-4); }

/* A line of the h1 that must not read as heading text: body face, no caps. */
.zlk-tagline {
  display: block;
  margin-top: var(--zlk-space-3);
  font: 700 var(--zlk-text-lg)/1.5 system-ui, sans-serif;
  text-transform: none;
  letter-spacing: normal;
  /* One doubled heading per page (DESIGN.md 2.7): the name, not this line. */
  text-shadow: none;
  color: var(--zlk-green);
}

.zlk-hero-photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-md);
  margin: 0 0 var(--zlk-space-4);
}

/* Same breakpoint as the rest of the two-column layouts: text left, photo
   pulled out into its own right column spanning the whole hero. */
@media (min-width: 860px) {
  .zlk-hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 24rem);
    column-gap: var(--zlk-space-6);
    align-items: start;
    /* h1 (tagline inside it), meta, lead, need. Explicit, because `1 / -1` against
       implicit rows is just row 1: the h1's row grew to the photo's height
       and pushed the tagline a photo-height down. The last row is 1fr so any
       photo height left over lands under the text, not spread between its
       lines. */
    grid-template-rows: repeat(3, auto) 1fr;
  }
  .zlk-hero > * { grid-column: 1; }
  /* The steps go full width under both columns so the three fit on one row. */
  .zlk-hero > .zlk-steps { grid-column: 1 / -1; }
  .zlk-hero-photo {
    grid-column: 2;
    grid-row: 1 / -1;
    margin: 0 0 var(--zlk-space-6);
    /* The 3/2 from the narrow layout is kept, not handed back to the image
       with `aspect-ratio: auto`: the photo spans every row here, so until it
       decodes the grid cannot size those rows, and wherever the text column
       is the shorter of the two the address, the lead and the whole menu
       below them drop down the page when the photo arrives. */
  }
}

.zlk-hero-meta {
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-sm);
  margin: 0 0 var(--zlk-space-4);
}

.zlk-lead {
  max-width: 62ch;
  color: var(--zlk-ink-4);
  margin: 0 0 var(--zlk-space-6);
}

/* The prerequisite, above the steps that assume it. Ink-5 on the ramp, not
   yellow: yellow means "do this next" (DESIGN.md §6) and this is a condition,
   not a control. */
.zlk-hero-need {
  max-width: 62ch;
  color: var(--zlk-ink-5);
  margin: 0 0 var(--zlk-space-6);
}

.zlk-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--zlk-space-3);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.zlk-steps li {
  display: flex;
  align-items: center;
  gap: var(--zlk-space-3);
  padding: var(--zlk-space-3) var(--zlk-space-4);
  background: var(--zlk-surface-grad);
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-md);
  box-shadow: var(--zlk-card-shadow);
  font-size: var(--zlk-text-sm);
}

.zlk-step-n {
  flex: none;
  width: var(--zlk-space-8);
  height: var(--zlk-space-8);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--zlk-radius-pill);
  background: var(--zlk-yellow);
  color: var(--zlk-ink-0);
  font-family: var(--zlk-font-display);
  /* The face is declared here deliberately -- this is the numeral face the
     whole system uses -- but the size was not, so the digit inherited
     --zlk-text-sm from .zlk-steps and sat at 15px in a 32px disc. Under the
     pixel face's floor (DESIGN.md 5), and a lone digit is where that face
     fails worst: no word shape is left to read it by. */
  font-size: var(--zlk-text-lg);
  line-height: 1;
}

.zlk-crumbs {
  font-size: var(--zlk-text-sm);
  color: var(--zlk-ink-4);
  margin-bottom: var(--zlk-space-4);
  min-height: var(--zlk-touch-target);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--zlk-space-1);
}

.zlk-crumbs a {
  color: var(--zlk-yellow);
  text-decoration: none;
  min-height: var(--zlk-touch-target);
  display: inline-flex;
  align-items: center;
}

.zlk-crumb-sep { color: var(--zlk-ink-3); margin: 0 var(--zlk-space-1); }

.zlk-item-avail { color: var(--zlk-green); font-weight: 700; margin: 0 0 var(--zlk-space-4); }

.zlk-item-cat { color: var(--zlk-ink-4); font-size: var(--zlk-text-sm); margin-top: var(--zlk-space-6); }

.zlk-footer {
  max-width: 1100px;
  margin: var(--zlk-space-12) auto 0;
  padding: var(--zlk-space-8) var(--zlk-space-4) var(--zlk-space-6);
  border-top: var(--zlk-card-border);
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-sm);
}

.zlk-footer-grid {
  display: grid;
  gap: var(--zlk-space-5);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  margin-bottom: var(--zlk-space-6);
}

.zlk-footer-grid p { margin: 0; }

/* An <h2>, so `h1, h2` above puts it in Retron2000 -- which this rule then
   sets at 13px, well under the ~18px the pixel face resolves at. DESIGN.md 5
   scopes that face to "the wordmark, page and category headings, prices, the
   order total, the pickup number"; "Location" over a postal address is a small
   label, not a page heading. Take the body face rather than inflate a footer. */
.zlk-footer-heading {
  font-family: inherit;
  font-size: var(--zlk-text-xs);
  letter-spacing: 0.05em;
  color: var(--zlk-green);
  margin: 0 0 var(--zlk-space-2);
}

/* Inline links still clear the touch floor (DESIGN.md §2.6). */
.zlk-footer a,
.zlk-hero-meta a,
.zlk-item-cat a,
.zlk-note a {
  color: var(--zlk-yellow);
  display: inline-flex;
  align-items: center;
  min-height: var(--zlk-touch-target);
}

.zlk-footer-line { margin: 0; }
.zlk-footer-share { margin: 0 0 var(--zlk-space-4); }
.zlk-footer-share a { margin-right: var(--zlk-space-3); }

/* --- The questions under the menu (FAQ in routes/shop.py) --------------- */

.zlk-faq {
  margin-top: var(--zlk-space-12);
  padding-top: var(--zlk-space-8);
  border-top: var(--zlk-card-border);
}
.zlk-faq h3 {
  font-size: var(--zlk-text-base);
  color: var(--zlk-green);
  margin: var(--zlk-space-6) 0 var(--zlk-space-2);
}
.zlk-faq p { max-width: 62ch; color: var(--zlk-ink-4); margin: 0; }

/* --- The order page, DESIGN.md §3.4 --------------------------------------
   /cart is where the customer decides to spend money, so it gets the one
   two-column layout in the shop: the lines they are checking on the left, a
   summary card that follows them down the page on the right. */

.zlk-cart {
  display: grid;
  gap: var(--zlk-space-6);
  align-items: start;
}

@media (min-width: 860px) {
  .zlk-cart { grid-template-columns: minmax(0, 1fr) 320px; }
}

.zlk-cart h1 { margin: 0 0 var(--zlk-space-4); }

.zlk-cart-summary {
  position: sticky;
  top: var(--zlk-space-4);
  padding: var(--zlk-space-5);
  background: var(--zlk-surface-grad);
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-lg);
  box-shadow: var(--zlk-card-shadow);
}

.zlk-summary-count {
  margin: 0;
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.zlk-cart-summary .zlk-order-total {
  margin: var(--zlk-space-1) 0 var(--zlk-space-4);
  font-family: var(--zlk-font-display);
  color: var(--zlk-yellow);
}

.zlk-btn-block { width: 100%; }
.zlk-btn-icon { width: 1.25em; height: 1.25em; flex: none; }

.zlk-btn-quiet {
  background: transparent;
  border: var(--zlk-card-border);
  color: var(--zlk-ink-4);
}

.zlk-summary-note {
  margin: var(--zlk-space-4) 0;
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-xs);
}

.zlk-cart-empty { max-width: 46ch; padding: var(--zlk-space-8) 0; }
.zlk-cart-empty h1 { margin: 0 0 var(--zlk-space-3); }

/* A cart line is not a receipt line: it carries the photo the customer picked
   from, and the quantity control is the line itself. */

.zlk-order-line-rich {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "thumb head  head"
    "thumb qty   price";
  gap: var(--zlk-space-2) var(--zlk-space-3);
  padding: var(--zlk-space-3);
  margin-bottom: var(--zlk-space-3);
  background: var(--zlk-surface-grad);
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-lg);
  box-shadow: var(--zlk-card-shadow);
}

/* A container query, not a viewport one: the kiosk's cart pane is ~290px wide
   on a 1080px screen, and the four-column row starved the name column to 0px
   there (one letter per line). The row layout depends on the pane it sits in,
   never on the window. */
@container (min-width: 480px) {
  .zlk-order-line-rich {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas: "thumb head qty price";
    align-items: center;
  }
}

.zlk-line-thumb {
  grid-area: thumb;
  align-self: center;
  width: var(--zlk-space-16);
  height: var(--zlk-space-16);
  border-radius: var(--zlk-radius-md);
  container-type: inline-size;
}

.zlk-line-head { grid-area: head; min-width: 0; }

/* A 26px line of text is the whole link back to the item page. It carries
   .hit-target (tokens.css) rather than a min-height: the head area is already
   45px of name plus unit price, and stretching the name would push every cart
   line ~19px taller to buy a target the recipe gives for nothing. */
.zlk-line-head .zlk-order-line-name {
  display: block;
  color: inherit;
  text-decoration: none;
  overflow-wrap: anywhere;
}

.zlk-line-unit {
  display: block;
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-xs);
  font-variant-numeric: tabular-nums;
}

.zlk-qty {
  grid-area: qty;
  display: inline-flex;
  align-items: center;
  align-self: center;
  justify-self: start;
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-pill);
  background: var(--zlk-ink-2);
}

.zlk-qty-btn {
  width: var(--zlk-touch-target);
  padding: 0;
  border-radius: var(--zlk-radius-pill);
  background: transparent;
  color: var(--zlk-ink-5);
  font-size: var(--zlk-text-lg);
  line-height: 1;
}

.zlk-qty-value {
  min-width: var(--zlk-space-6);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.zlk-order-line-rich .zlk-order-line-price {
  grid-area: price;
  align-self: center;
  justify-self: end;
  min-width: 7ch;
  text-align: right;
  font-family: var(--zlk-font-display);
  /* Set the size as well as the face: inheriting 17px from the body put the
     pixel face under the ~18px it resolves at (DESIGN.md 5). A price is on
     that section's display list, so this is a size, not a face. */
  font-size: var(--zlk-text-lg);
  color: var(--zlk-yellow);
}

.zlk-cart-lines .zlk-back {
  margin-top: var(--zlk-space-5);
  min-height: var(--zlk-touch-target);
  display: inline-flex;
  align-items: center;
}

/* --- Polish shared by every surface -------------------------------------- */

/* One warm bloom behind the header, so the ground is not a flat field. */
body::before {
  content: "";
  position: fixed;
  inset: 0 0 auto;
  height: 60vh;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(80% 60% at 50% -10%,
      color-mix(in srgb, var(--zlk-yellow) 7%, transparent) 0%, transparent 70%);
}

body > * { position: relative; z-index: 1; }

.zlk-card,
.zlk-chip,
button,
.zlk-btn {
  transition: background-color var(--zlk-duration-base) var(--zlk-ease),
              border-color var(--zlk-duration-base) var(--zlk-ease),
              box-shadow var(--zlk-duration-base) var(--zlk-ease);
}

.zlk-card-well img { transition: transform var(--zlk-duration-base) var(--zlk-ease); }

@media (hover: hover) {
  .zlk-card:hover {
    border-color: color-mix(in srgb, var(--zlk-yellow) 35%, transparent);
    box-shadow: var(--zlk-card-shadow),
                0 0 0 1px color-mix(in srgb, var(--zlk-yellow) 12%, transparent);
  }
  .zlk-card:hover .zlk-card-well img { transform: scale(1.04); }
  .zlk-chip:hover { background: var(--zlk-ink-3); }
  .zlk-qty-btn:hover { background: var(--zlk-ink-3); }
}

@media (prefers-reduced-motion: reduce) {
  .zlk-card-well img { transition: none; }
  .zlk-card:hover .zlk-card-well img { transform: none; }
}

/* --- Admin, DESIGN.md §7 --------------------------------------------------
   Restyled by inheritance: the token ramp, the type scale and the touch-target floor.
   Nothing bespoke lives here — the nav borrows the chip, the tables borrow the
   card surface. Admin is one person, once a week. */

/* Form fields were never styled, so admin (the only place with real forms)
   fell back to the UA widget on a near-black ground. */
input:not([type="checkbox"]),
textarea,
select {
  font: inherit;
  min-height: var(--zlk-touch-target);
  padding: var(--zlk-space-2) var(--zlk-space-3);
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-sm);
  background: var(--zlk-ink-1);
  color: var(--zlk-ink-5);
}

textarea {
  min-height: calc(var(--zlk-touch-target) * 2);
  resize: vertical;
}

::placeholder { color: var(--zlk-ink-4); }

.admin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zlk-space-2);
  margin-bottom: var(--zlk-space-6);
  padding-bottom: var(--zlk-space-4);
  border-bottom: var(--zlk-card-border);
}

.admin form { margin-left: auto; }

.admin-table-scroll {
  overflow-x: auto;
  margin-bottom: var(--zlk-space-8);
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-md);
  background: var(--zlk-surface-grad);
  box-shadow: var(--zlk-card-shadow);
}

.admin-table-scroll table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--zlk-text-sm);
}

.admin-table-scroll th,
.admin-table-scroll td {
  padding: var(--zlk-space-2) var(--zlk-space-3);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
  border-bottom: var(--zlk-card-border);
}

.admin-table-scroll th {
  font-size: var(--zlk-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--zlk-ink-4);
}

.admin-table-scroll tr:last-child td { border-bottom: 0; }

/* A row action is a link, not a button, but a thumb still has to hit it:
   an inline <a> ignores min-height, so give it a box to be tall in. */
.admin-table-scroll td a {
  display: inline-flex;
  align-items: center;
  min-height: var(--zlk-touch-target);
  color: var(--zlk-yellow);
}

/* Deactivated products and resolved payments stay readable but recede. */
.admin-table-scroll tr.inactive td,
.admin-table-scroll tr.resolved td { color: var(--zlk-ink-4); }

/* Every row action is a control strip: the note field and its button. A row's
   form stays inline so a sibling link sits beside it, not above it. */
.admin-table-scroll .admin-row-actions,
.admin-table-scroll form {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  gap: var(--zlk-space-2);
}

.admin-table-scroll input { min-width: 20ch; }

.admin-form {
  display: grid;
  gap: var(--zlk-space-4);
  max-width: 46ch;
  margin-bottom: var(--zlk-space-8);
}

.admin-form label {
  display: grid;
  gap: var(--zlk-space-1);
  font-size: var(--zlk-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--zlk-ink-4);
}

/* The checkbox reads left-to-right, not stacked over its own label. */
.admin-form label:has(input[type="checkbox"]) {
  grid-auto-flow: column;
  justify-content: start;
  align-items: center;
  gap: var(--zlk-space-2);
}

.admin-note {
  max-width: 62ch;
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-sm);
}

/* The row thumbnail. .zlk-well already owns the crop, the ground and the
   fallback letter; only the size is new. */
.zlk-well-admin {
  width: 56px;
  height: 56px;
  border-radius: var(--zlk-radius-sm);
}

/* The cell holds a fixed square, so it must not stretch to the row's nowrap. */
.admin-table-scroll td:has(> .zlk-well) { width: 56px; padding: var(--zlk-space-2); }

.admin-actions { margin-bottom: var(--zlk-space-4); }

.admin-badge {
  margin-left: var(--zlk-space-2);
  padding: 0 var(--zlk-space-2);
  border-radius: var(--zlk-radius-sm);
  background: color-mix(in srgb, var(--zlk-yellow) 18%, transparent);
  color: var(--zlk-yellow);
  font-variant-numeric: tabular-nums;
}

.admin-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--zlk-space-3);
  margin-bottom: var(--zlk-space-4);
}

.admin-filter label {
  display: grid;
  gap: var(--zlk-space-1);
  font-size: var(--zlk-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--zlk-ink-4);
}

/* Create and edit, over the table (DESIGN.md §7). Borrows the card surface;
   the backdrop is the ground at 78%, the same color-mix pattern as the price
   tag -- a new shade would need DESIGN.md first. */
/* Opened by ?edit=N / ?new=1 with a plain `open` attribute, which is the whole
   no-JS path -- and a non-modal <dialog> is laid out in normal flow, so it was
   landing after the products table, a screen and a half down, with every field
   and both buttons below the fold. The 85dvh and the scrollbar below are the
   sizing of something that expects to be IN the viewport; this puts it there.
   No showModal() to do it, because there is no JavaScript on this page. */
.admin-dialog {
  position: fixed;
  inset: 0;
  margin: auto;
  z-index: 3;
  max-width: min(52ch, calc(100vw - var(--zlk-space-6)));
  max-height: 85dvh;
  overflow-y: auto;
  padding: var(--zlk-space-6);
  border: var(--zlk-card-border);
  border-radius: var(--zlk-radius-md);
  background: var(--zlk-surface-grad);
  box-shadow: var(--zlk-card-shadow);
  color: var(--zlk-ink-5);
}

.admin-dialog::backdrop {
  background: color-mix(in srgb, var(--zlk-ink-0) 78%, transparent);
}

.admin-dialog .admin-form { margin-bottom: 0; }

.admin-photo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zlk-space-3);
  margin-bottom: var(--zlk-space-8);
}

.admin-photo img {
  border-radius: var(--zlk-radius-sm);
  border: var(--zlk-card-border);
}

/* --- The payment screen, DESIGN.md §3.5 ----------------------------------
   Was 62 lines of inline <style> inside receipt.html: the one page that did
   not come out of the same box, with the only hex literals left in the app and
   a .zlk-hero that collided with the landing page's hero section. */

.zlk-pay { max-width: 480px; margin: 0 auto; }

.zlk-status {
  font-size: var(--zlk-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--zlk-ink-4);
}

.zlk-status.status-paid { color: var(--zlk-green); }
.zlk-status.status-expired { color: var(--zlk-danger); }

/* The receipt's line list is the order line list, one column narrower. */
.zlk-pay .zlk-order-lines { margin: var(--zlk-space-4) 0; }
.zlk-pay-total { font-size: var(--zlk-text-lg); font-weight: 700; }

/* Once the money is settled the itemisation is a record, not the subject. */
.zlk-pay-paid .zlk-order-lines,
.zlk-pay-paid .zlk-pay-total,
.zlk-pay-expired .zlk-order-lines,
.zlk-pay-expired .zlk-pay-total { font-size: var(--zlk-text-sm); }

/* Choosing a rail. */
/* The payment menu asks a question now. Five tiles that differ only by a
   three-letter ticker gave the customer nothing to decide on, and every
   switch between them cancels the open invoice -- hesitation here is not
   free. The heading frames the choice; .zlk-rail-help names the one real
   difference (euro-stable vs frozen rate vs a checkout that leaves the
   page) and is built from the registered rails, so it stays short. */
.zlk-rail-title {
  margin: 0 0 var(--zlk-space-2);
  font-size: var(--zlk-text-lg);
}

.zlk-rail-help { margin: 0; max-width: 56ch; }

.zlk-rail-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--zlk-space-4);
  margin: var(--zlk-space-6) 0;
}

.zlk-rail-form { margin: 0; }
.zlk-rail-form-wide { grid-column: 1 / -1; }

.zlk-rail-tile {
  width: 100%;
  flex-direction: column;
  padding: var(--zlk-space-5);
  background: var(--zlk-surface-grad);
  border: 1px solid var(--zlk-yellow);
  border-radius: var(--zlk-radius-lg);
  box-shadow: var(--zlk-card-shadow);
}

.zlk-rail-tile-solana {
  border-color: transparent;
  background: var(--zlk-solana-grad);
  color: var(--zlk-ink-0);
}

.zlk-rail-tile-btc {
  border-color: transparent;
  background: var(--zlk-btc-grad);
  color: var(--zlk-ink-0);
}

.zlk-tile-icon { width: 32px; height: 32px; }

/* The same mark again on the invoice, beside the ticker and the network it
   has to be sent on. Headline-sized: the wrong chain is the one mistake here
   that loses the funds outright. */
.zlk-invoice-rail {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--zlk-space-2);
  margin: 0 0 var(--zlk-space-3);
  font-size: var(--zlk-text-lg);
  color: var(--zlk-ink-5);
}
.zlk-invoice-rail .zlk-rail-mark { width: 36px; height: 36px; }

.zlk-rail-mark { width: 24px; height: 24px; flex: none; }

/* The ticker is the tile's headline, and DESIGN.md 3.5 makes a rail tile "the
   same kind of object as everything else you tap" -- so it takes the size the
   card price takes. At --zlk-text-base the pixel face was under the ~18px it
   resolves at, on the word a customer matches against their own wallet. */
.zlk-rail-asset {
  font-family: var(--zlk-font-display);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--zlk-text-lg);
}

/* Waiting on the rate lookup and the chain call. The other tiles dim so the
   grid reads as "one of these is happening", not "all five are still yours to
   choose"; the pressed one keeps full contrast because it is the answer. */
.zlk-rail-tile:disabled { opacity: 0.4; }
.zlk-rail-tile.is-busy:disabled { opacity: 1; }

.zlk-rail-network { font-size: var(--zlk-text-xs); color: var(--zlk-ink-4); }
.zlk-rail-tile-solana .zlk-rail-network,
.zlk-rail-tile-btc .zlk-rail-network { color: var(--zlk-ink-0); opacity: 0.7; }

/* Awaiting payment. The QR well stays flat and near-white on dark: no
   gradient, no tint, nothing that costs a scan (DESIGN.md §3.5). */
.zlk-invoice { margin: var(--zlk-space-6) 0; text-align: center; }

/* The code, the amount it stands for, and its deadline are one unit, centred
   on the code however wide the column gets. */
.zlk-qr-col { text-align: center; }

.zlk-qr-well {
  display: inline-block;
  background: var(--zlk-ink-1);
  border-radius: var(--zlk-radius-md);
  padding: var(--zlk-space-4);
  position: relative;
}

/* The scan line (DESIGN.md 3.5): two yellow ticks inside the well's padding
   either side of the code, sweeping top to bottom together, so a line reads
   as passing behind it. Each tick is a transparent box the well's height whose
   bottom border is the line; translateY(-100% -> 0) walks that border down
   the well's inner edge on the compositor. Nothing is painted over the code. */
.zlk-qr-well::before,
.zlk-qr-well::after {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: var(--zlk-space-2);
  border-bottom: 2px solid var(--zlk-yellow);
  box-sizing: border-box;
  opacity: 0;
  pointer-events: none;
  animation: zlk-scan var(--zlk-duration-scan) var(--zlk-ease) infinite;
}
.zlk-qr-well::before { left: var(--zlk-space-1); }
.zlk-qr-well::after { right: var(--zlk-space-1); }

@keyframes zlk-scan {
  0% { transform: translateY(-100%); opacity: 0; }
  15%, 85% { opacity: 1; }
  100% { transform: translateY(0); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .zlk-qr-well::before, .zlk-qr-well::after { animation: none; }
}

.zlk-qr-well svg.segno { display: block; width: min(72vw, 320px); height: auto; }
.zlk-qr-well svg.segno .qrline { stroke: var(--zlk-ink-5) !important; }

.zlk-amount {
  font-family: 'Courier New', monospace;
  font-variant-numeric: tabular-nums;
  font-size: var(--zlk-text-xl);
  margin: var(--zlk-space-4) 0 0;
}

/* Beside the QR: each value in full under a small uppercase title -- the
   same label voice as the pickup number's. A tap selects the whole value: the
   kiosk has no clipboard, so select-then-share is the copy path. */
.zlk-pay-fields { margin: 0; }
.zlk-pay-fields > div + div { margin-top: var(--zlk-space-3); }
.zlk-pay-fields dt {
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.zlk-pay-fields dd { margin: var(--zlk-space-1) 0 0; }
.zlk-pay-fields code {
  font-family: 'Courier New', monospace;
  font-size: var(--zlk-text-sm);
  user-select: all;
}

/* A BOLT11 is ~300 chars of unbroken text: it wraps or it blows the layout.
   Every <code> we render is a chain identifier -- address, comment, reference
   -- so the rule belongs on the element, not on one container. Scoped to
   the address line it left the reference line pushing the page sideways at 320px. */
code {
  overflow-wrap: anywhere;
  min-width: 0;
}


.zlk-note { color: var(--zlk-ink-4); font-size: var(--zlk-text-sm); }
.zlk-note strong { color: var(--zlk-ink-5); }
.zlk-countdown { font-variant-numeric: tabular-nums; }
.zlk-countdown.zlk-warn { color: var(--zlk-warn); }

/* Paid / expired: the pickup number at hero size. Its own class, because
   .zlk-hero is the landing page's hero *section* and was quietly putting a
   border and 32px of padding under this number. */
/* One line, sized to the column: "ZB-5869" at the hero size broke after the
   hyphen on the kiosk, and a clipping wrapper then showed the customer "ZB-". */
.zlk-pickup-wrap {
  container-type: inline-size;
  /* The kiosk turns .zlk-pay into a flex column that keeps the grid's
     align-items: start; a container sized to its content is 0 wide. */
  align-self: stretch;
  text-align: center;
}

.zlk-pickup {
  font-family: var(--zlk-font-display);
  font-size: min(var(--zlk-text-hero), 20cqi);
  white-space: nowrap;
  line-height: 1;
  margin: var(--zlk-space-6) 0;
  letter-spacing: 0.02em;
}

/* Names the number the viewport has become. Small, above it -- the number is
   still the screen (DESIGN.md §3.5). */
.zlk-pickup-label {
  text-align: center;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* The plate lock, DESIGN.md §2.7: arrives yellow over an offset green plate,
   settles into solid green, once. At rest there is no text-shadow at all.
   Reduced motion zeroes the offset and the duration, so it lands locked. */
/* Supernova, before the lock: the number grows out of one green point while
   a ring bursts off it, then the plates lock. transform/opacity only; every
   duration here is a token, so reduced motion lands it at rest. */
.zlk-pay-paid .zlk-pickup-wrap { position: relative; }
.zlk-pay-paid .zlk-pickup-wrap::before,
.zlk-pay-paid .zlk-pickup-wrap::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
}
/* The point. */
.zlk-pay-paid .zlk-pickup-wrap::before {
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  background: var(--zlk-green-bright);
  animation: zlk-nova-point var(--zlk-duration-settle) var(--zlk-ease) 1;
}
/* The ring. */
.zlk-pay-paid .zlk-pickup-wrap::after {
  width: 60cqi;
  height: 60cqi;
  margin: -30cqi 0 0 -30cqi;
  border: 3px solid var(--zlk-green-bright);
  animation: zlk-nova-ring var(--zlk-duration-settle) var(--zlk-ease) 1;
}
@keyframes zlk-nova-point {
  0%   { opacity: 1; transform: scale(0.2); }
  40%  { opacity: 1; transform: scale(1.4); }
  100% { opacity: 0; transform: scale(0); }
}
@keyframes zlk-nova-ring {
  0%, 25% { opacity: 1; transform: scale(0); }
  100%    { opacity: 0; transform: scale(1.6); }
}

.zlk-pickup-paid {
  color: var(--zlk-green-bright);
  animation:
    zlk-nova var(--zlk-duration-settle) var(--zlk-ease) 1,
    zlk-lock var(--zlk-duration-settle) var(--zlk-ease) var(--zlk-duration-settle) 1 backwards;
}

@keyframes zlk-nova {
  0%, 25% { transform: scale(0); }
  100%    { transform: scale(1); }
}

@keyframes zlk-lock {
  from {
    color: var(--zlk-yellow);
    text-shadow: var(--zlk-misreg-x) var(--zlk-misreg-y) 0 var(--zlk-green-bright);
  }
  to {
    color: var(--zlk-green-bright);
    text-shadow: 0 0 0 var(--zlk-green-bright);
  }
}
.zlk-pickup-expired { color: var(--zlk-danger); }

/* --- The receipt as a terminal screen ------------------------------------
   The bar's POS is a fixed 1366x768 panel with no scrollbar and no way to
   flick a page: anything below the fold does not exist. On a landscape
   screen the receipt therefore goes two-column -- the order on the left,
   what the customer has to touch on the right -- so every rail tile, and
   the QR that replaces them, stays in one viewport however many lines the
   order has. Phones keep the single tall column. */
@media (min-width: 700px) {
  .zlk-pay {
    max-width: 1100px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    align-items: start;
    gap: 0 var(--zlk-space-8);
  }
  .zlk-pay-number { font-size: var(--zlk-text-xl); margin: var(--zlk-space-2) 0; }
  .zlk-pay .zlk-order-lines { margin: var(--zlk-space-3) 0; }
  .zlk-pay .zlk-order-line { padding: var(--zlk-space-2) 0; }
  .zlk-pay-total { margin: var(--zlk-space-2) 0; }
  /* The heading keeps --zlk-text-lg here: --zlk-text-base is 17px, and the
     pixel face resolves at about 18 (DESIGN.md 5). The vertical room this
     override bought is no longer needed -- the chooser scrolls inside
     itself, so the cancel row below it stays on the panel regardless. */
  .zlk-rail-grid { gap: var(--zlk-space-3); margin: var(--zlk-space-3) 0 0; }
  .zlk-rail-tile { padding: var(--zlk-space-3); }

  /* Paid and expired are one number as big as the screen allows: no column
     to squeeze it into. */
  .zlk-pay-paid, .zlk-pay-expired { display: block; max-width: 780px; }
  /* Sized off the height, not the width: 25vw of a 1366px screen is a number
     taller than the 768px it has to fit in, itemisation and all. */
  .zlk-pickup { font-size: min(var(--zlk-text-hero), 22vh, 20cqi); margin: var(--zlk-space-4) 0; }
}

/* --- "It went in" ---------------------------------------------------------
   The add redirects back to the item page, so the confirmation has to be here,
   in the flow, where the thumb already is — the sticky bar at the bottom of
   the viewport is not where a customer on a scrolled item page is looking. */
.zlk-item-added {
  margin: 0 0 var(--zlk-space-4);
  padding: var(--zlk-space-3) var(--zlk-space-4);
  border: 1px solid var(--zlk-green);
  border-radius: var(--zlk-radius-md);
  color: var(--zlk-ink-5);
  font-size: var(--zlk-text-sm);
}

/* The destructive control, behind a native disclosure (DESIGN.md §3.4): it
   stays quiet, but it costs two deliberate actions and no dialog. */
.zlk-clear { margin-top: var(--zlk-space-4); }

.zlk-clear > summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--zlk-touch-target);
  color: var(--zlk-ink-4);
  font-size: var(--zlk-text-sm);
  cursor: pointer;
}

.zlk-clear > summary::-webkit-details-marker { display: none; }

.zlk-clear[open] > summary { color: var(--zlk-ink-5); }

.zlk-clear > form { margin-top: var(--zlk-space-2); }

.zlk-clear > form button { color: var(--zlk-danger); }

/* The way off the receipt while it is still unpaid (SPEC 5). Set apart from
   the rail tiles above it so a mis-tap costs the order, not a rail choice. */
.zlk-pay-cancel {
  grid-column: 1 / -1;
  margin-top: var(--zlk-space-6);
  text-align: center;
}
.zlk-pay-cancel .zlk-note { margin-top: var(--zlk-space-4); font-size: var(--zlk-text-xs); }
/* Both ways off side by side; wraps only when a phone cannot seat them. */
.zlk-pay-cancel-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--zlk-space-2);
}

/* The invoice goes two-column only once the half of the receipt it lives in
   can seat both. .zlk-pay has already split the page, and the QR column here
   is `auto` with a viewport-sized code inside it -- so below this width the QR
   takes the row and leaves the address, which is rendered in full precisely so
   it can be typed, a column seven characters wide. Under it, stack. */
@media (min-width: 1000px) {
  /* Stacked, the QR and the amount/address/countdown under it are taller
     than the screen. Side by side they are as tall as the QR alone. */
  .zlk-invoice {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 0 var(--zlk-space-4);
    margin: 0;
    text-align: left;
  }
  /* The room the two columns freed goes into the one thing that is scanned
     from arm's length, across a bar, by a phone camera. */
  .zlk-qr-well { padding: var(--zlk-space-3); }
  .zlk-qr-well svg.segno { width: min(34vw, 300px); }
  .zlk-pay-side > * { margin: var(--zlk-space-2) 0; }

}

