/* ==========================================================================
   Storefront — one company's menu.
   No search: customers arrive here from that company's own link.
   ========================================================================== */

.shopfront {
  display: grid;
  gap: 0.75rem;
  padding-bottom: 1.75rem;
  margin-bottom: 2rem;
  border-bottom: 1px solid var(--line);
}

/* The mark sits beside the name when a shop has uploaded one, and the head is a
   plain flex row so that a shop without one loses the row rather than an empty
   column (slice Y-D, Y13). */
.shopfront__head {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.shopfront__head .display {
  /* The company name is the loudest thing on the page. It is why you are here. */
  max-width: 14ch;
}

.shopfront__meta {
  display: flex;
  gap: 0.5rem 1.25rem;
  align-items: center;
  flex-wrap: wrap;
  font-size: var(--step--1);
  color: var(--ink-soft);
}

/* The two money facts are data, and reading them is why anyone looks here. */
.shopfront__meta .mono { color: var(--ink); }

/* --- Menu groups -----------------------------------------------------------
   A restaurant menu is read in sections — pizzas, kebabs, salads, drinks — and
   the heading is what a customer scans for before they read a single item.
   -------------------------------------------------------------------------- */

.menu-group + .menu-group { margin-top: 2.5rem; }

.menu-group__title {
  margin: 0 0 0.9rem;
  font-size: var(--step-2);
  letter-spacing: -0.01em;
}

/* --- Menu grid ------------------------------------------------------------ */

.menu {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}

@media (min-width: 640px)  { .menu { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .menu { grid-template-columns: repeat(3, 1fr); } }

/*
  Two card shapes, one grid.

  A shop that has photographed its menu gets pictures; a shop that has not gets
  a typographic card that spends the same space on its ingredient run. They
  share width and footer position so a half-photographed menu — which is what a
  shop uploading its pictures one evening actually looks like — does not read as
  a broken grid.
*/
.dish {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color 160ms ease, box-shadow 200ms ease, transform 200ms ease;
}

/*
  Inset rather than bled to the card edge: a full-bleed image fought the card's
  own border-radius and rendered square top corners against a rounded card,
  which reads as a broken image. The photo carries its own radius instead.
*/
.dish__photo {
  width: 100%;
  margin-bottom: 0.35rem;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--line-soft);
}

.dish:hover {
  border-color: var(--ink);
  box-shadow: var(--shadow-lift);
  transform: translateY(-2px);
}

.dish__name { font-size: var(--step-2); font-weight: 750; letter-spacing: -0.025em; }
.dish__desc { color: var(--ink-soft); font-size: var(--step--1); }

/*
  Ingredients listed as a comma run, the way a menu board writes them.

  **The monospace went with slice R.** It was there because the design system's
  motif was the kitchen ticket and mono was the data face; direction B retires
  that motif, and mono now keeps only the jobs it earns — money, order numbers,
  timers. A list of toppings is prose, and prose set in mono on a customer's
  phone is harder to read for no gain.
*/
.dish__toppings {
  display: flex;
  flex-wrap: wrap;
  font-size: var(--step--1);
  color: var(--ink-faint);
  padding-top: 0.5rem;
}

/* On an unphotographed card this is the most useful text there is, and it used
   to be the faintest thing on it. Where there is a picture, the picture is
   doing that job and the run stays quiet. */
.dish--text .dish__toppings { color: var(--ink-soft); }

.dish__toppings li + li::before { content: " · "; white-space: pre; }

.dish__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  /* On the foot, not on the ingredient run: a photographed card may have no
     run to push, and the price still has to sit at the bottom. */
  margin-top: auto;
  padding-top: 0.9rem;
  border-top: 1px dashed var(--line);
}

.dish__price { font-size: var(--step-1); font-weight: 700; }

/* A shut shop looks shut, rather than like a working menu with dead buttons. */
.is-closed .dish { opacity: 0.72; }
.is-closed .dish:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--line);
}

/* --- Limited runs ----------------------------------------------------------
   A count only appears when it is worth acting on: "5 left" is a reason to
   decide now, a count on every item all evening is noise.                     */

.dish__stock {
  margin: 0.35rem 0 0;
  font-size: var(--step--1);
  font-weight: 650;
  color: var(--basil);
}

.dish__stock--out { color: var(--ink-faint); }

/* --- Opening hours and contact (slice W8) ---------------------------------- //

   A <details>, not a scripted panel: the hours are the last thing on this page
   that should need a working script to read. It is open by default when the
   shop is closed, because that is exactly when somebody is looking for it.
*/
.shopinfo {
  margin: 0 0 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}

.shopinfo__toggle {
  cursor: pointer;
  padding: 0.85rem 1rem;
  font-weight: 650;
  list-style: none;
}

/* The default triangle sits badly against a full-width row; a rotating caret of
   our own follows the open state without any script. */
.shopinfo__toggle::-webkit-details-marker { display: none; }

.shopinfo__toggle::after {
  content: "▾";
  float: right;
  transition: transform 0.15s ease;
}

.shopinfo[open] .shopinfo__toggle::after { transform: rotate(180deg); }

.shopinfo__body {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 3rem;
  padding: 0 1rem 1rem;
  border-top: 1px solid var(--line);
  padding-top: 1rem;
}

.shopinfo__hours { border-collapse: collapse; }

.shopinfo__hours caption {
  text-align: left;
  padding-bottom: 0.4rem;
}

.shopinfo__hours th {
  text-align: left;
  font-weight: 400;
  color: var(--ink-soft);
  padding-right: 1.5rem;
}

.shopinfo__hours td { text-align: right; }

.shopinfo__hours th,
.shopinfo__hours td { padding-block: 0.15rem; }

/* Today, so the eye lands on the row it came for. */
.shopinfo__hours .is-today th,
.shopinfo__hours .is-today td {
  font-weight: 700;
  color: var(--ink);
}

.shopinfo__contact {
  font-style: normal;
}

.shopinfo__contact p { margin: 0 0 0.35rem; }

.shopinfo__tel {
  font-weight: 650;
  white-space: nowrap;
}


/*
  Booking a table, in the shop's header (slice R, reworked 2026-09-05).

  It was a `.chip`, which put it in a row of statements — open, delivering from,
  minimum order — and the owner read it as an annotation rather than as a
  control. It is a real button now, and slightly taller than the chips beside it
  so the eye lands on it first; it stays IN the row because the header is one
  line and a second row for one link would be a second row on every shop page.
*/
.shopfront__book {
  margin-left: auto;
  padding-inline: 1.25rem;
  text-decoration: none;
  white-space: nowrap;
}

@media (max-width: 599px) {
  /* On a phone the meta row wraps, and a full-width button is the easiest
     target on the page rather than a word squeezed against the minimum order. */
  .shopfront__book { margin-left: 0; width: 100%; }
}
