/* =========================================================
   Hearthfare — platform (app) layer
   Loads AFTER styles.css and depends on its tokens.
   Reuses from styles.css: .btn .btn__label .btn__icon .field .field__label
   .field__hint .input .input--select .consent .eyebrow .site-header
   .site-footer .brand .sr-only

   1. Shell  2. Page head  3. Panels  4. Metrics  5. Pills & badges
   6. Tables  7. Banners  8. Empty states  9. Buttons (app additions)
   10. Forms (app additions)  11. Tabs  12. Stepper  13. Modal
   14. Money rows  15. Storefront  17. Dish rating  18-25. Page revisions
   Breakpoints: last, one block per width (see the end of the file)
   ========================================================= */

/* ---------- 1. Shell ---------- */
/* Shared widths: the sidebar (column and drawer) and every right-hand sheet. */
:root { --side-w: 16.5rem; --sheet-w: 34rem; }

.app {
  display: grid;
  grid-template-columns: var(--side-w) minmax(0, 1fr);
  min-height: 100vh;
  /* Platform chrome is neutral; warm tints stay for accents only. */
  --stroke: var(--line-cool);
  --app-bar-h: 4.8125rem;
  /* The shell's own side gutter: steps with the app breakpoints (32px, 20px on
     phones), not with the marketing --gutter, which changes at 834/1280px. */
  --app-gutter: var(--space-6);
  background: var(--surface);
}

.app-side {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  padding: var(--space-5) var(--space-4);
  background: var(--white);
  border-right: 1px solid var(--stroke);
}

.app-side__brand { margin-bottom: var(--space-1); }
/* The role label (Hearth dashboard / Admin / Your account) shows at every width;
   the marketing header's tagline, which shares the class, only shows from 1280px. */
.app-side__brand .brand__tagline { display: block; }

.app-side__nav { display: grid; gap: var(--space-5); }

.app-side__group { display: grid; gap: 0.125rem; }

.app-side__group-title {
  padding: 0 0.75rem 0.375rem;
  color: var(--muted-light);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.app-side__link {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5625rem 0.75rem;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  font-size: var(--text-sm);
  font-weight: 600;
}

.app-side__link:hover { background: var(--cream); }

.app-side__link--active,
.app-side__link--active:hover {
  background: var(--grad-warm);
  color: var(--white);
  box-shadow: inset 0.1875rem 0 0 #e0580f;
}

.app-side__icon {
  width: 1.0625rem;
  height: 1.0625rem;
  flex: none;
  color: var(--muted);
}

.app-side__link--active .app-side__icon { color: var(--white); }

.app-side__link--active .app-side__count {
  background: var(--white);
  color: var(--orange);
}

.app-side__label { flex: 1 1 auto; }

.app-side__count {
  flex: none;
  min-width: 1.25rem;
  padding: 0.0625rem 0.375rem;
  border-radius: var(--radius-pill);
  background: var(--orange);
  color: var(--white);
  font-size: var(--text-xs);
  font-weight: 700;
  text-align: center;
}

.app-side__count--quiet {
  background: var(--line);
  color: var(--muted);
}

.app-side__foot {
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--stroke);
}

.app-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.app-bar {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  /* Pinned so --app-bar-h stays true; the sticky dash rail sizes against it.
     flex: none so a long page body cannot squeeze the bar in the 100dvh column. */
  flex: none;
  min-height: var(--app-bar-h);
  padding: 0.875rem var(--space-6);
  background: var(--white);
  border-bottom: 1px solid var(--stroke);
}

.app-bar__context { flex: 1 1 auto; min-width: 0; }

.app-bar__eyebrow {
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* One line on every page: a long name truncates instead of growing the bar. */
.app-bar__name {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink);
  font-size: var(--text-md);
  font-weight: 700;
}

.app-bar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Hamburger + wordmark. Hidden on desktop, where the sidebar carries the
   brand; revealed at <=60rem when the sidebar becomes a drawer. */
.app-bar__lead {
  display: none;
  align-items: center;
  gap: var(--space-3);
  flex: none;
}

/* Scrim behind the open drawer. Present only in the menu-open state file. */
.app-scrim {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 35;
  background: rgba(23, 18, 14, 0.45);
}

.icon-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-pill);
  color: var(--ink-soft);
  cursor: pointer;
}

.icon-button__icon { width: 1.0625rem; height: 1.0625rem; }

.icon-button__dot {
  position: absolute;
  top: 0.375rem;
  right: 0.4375rem;
  width: 0.4375rem;
  height: 0.4375rem;
  border: 1.5px solid var(--white);
  border-radius: 50%;
  background: var(--red);
}

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: 50%;
  background: var(--sand);
  color: var(--orange);
  font-size: var(--text-sm);
  font-weight: 700;
}

.avatar--lg { width: 3rem; height: 3rem; font-size: var(--text-md); }

.app-body {
  --app-body-pad: var(--space-6); /* top/bottom; sticky bars pull out by it to sit flush */
  flex: 1 1 auto;
  padding: var(--app-body-pad);
  overflow-y: auto;
}

.app-body__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  width: 100%;
}

/* ---------- 2. Page head ---------- */
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
}

.page-head__text { max-width: 42rem; }

.page-head__title {
  color: var(--ink);
  font-size: 1.625rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.page-head__sub {
  margin-top: 0.25rem;
  color: var(--muted);
  font-size: var(--text-sm);
}

.page-head__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

/* Period filter toolbar in the page head (Reports): presets and a date range
   side by side in .page-head__actions' row. The range always shows the active
   preset's dates; editing it is the Custom range filter. */
.period__presets,
.period__range {
  display: flex;
  align-items: center;
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-card);
}

.period__presets { padding: 0.1875rem; }
.period__group { display: flex; }
.period__group + .period__group {
  margin-left: 0.25rem;
  padding-left: 0.25rem;
  border-left: 1px solid var(--stroke);
}

.period__opt {
  padding: 0.4375rem 0.8125rem;
  background: none;
  border: 0;
  border-radius: var(--radius-pill);
  color: var(--muted);
  font: 600 var(--text-sm)/1.2 var(--font-sans);
  white-space: nowrap;
  cursor: pointer;
}

.period__opt:hover { color: var(--ink); }
.period__opt--on,
.period__opt--on:hover { background: var(--sand); color: #a8490f; }

/* Longer periods live in a native <details> dropdown; closed, its menu isn't rendered. */
.period__more { position: relative; }
.period__more > summary { display: flex; align-items: center; gap: 0.3125rem; list-style: none; }
.period__more > summary::-webkit-details-marker { display: none; }
.period__chev { width: 0.875rem; height: 0.875rem; flex: none; transition: transform 0.15s; }
.period__more[open] .period__chev { transform: rotate(180deg); }

.period__menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: -0.25rem;
  z-index: 20;
  display: grid;
  min-width: 11rem;
  padding: 0.25rem;
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-md);
  box-shadow: 0 0.75rem 2rem rgba(23, 18, 14, 0.12);
}

.period__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.625rem;
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  font: 600 var(--text-sm)/1.2 var(--font-sans);
  text-align: left;
  cursor: pointer;
}

.period__item:hover { background: var(--surface); }
.period__item--on { color: #a8490f; }
.period__check { width: 0.875rem; height: 0.875rem; flex: none; color: var(--orange); visibility: hidden; }
.period__item--on .period__check { visibility: visible; }
.period__sep { height: 1px; margin: 0.25rem 0.375rem; background: var(--stroke); }

.period__range { gap: 0.25rem; padding: 0.1875rem 0.1875rem 0.1875rem 0.875rem; }

.period__label {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  margin-right: 0.25rem;
  padding-right: 0.625rem;
  border-right: 1px solid var(--stroke);
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
}

.period__icon { width: 0.9375rem; height: 0.9375rem; flex: none; color: var(--orange); }

.period__date {
  width: 8.75rem;
  padding: 0.4375rem 0.5rem;
  background: none;
  border: 0;
  border-radius: var(--radius-pill);
  color: var(--ink);
  font: 600 var(--text-sm)/1.2 var(--font-sans);
  text-align: left;
}

.period__date:hover { background: var(--surface); }
.period__date:focus-visible { outline: 2px solid var(--orange); }
.period__arrow { width: 0.875rem; height: 0.875rem; flex: none; color: var(--muted-light); }

/* ---------- 3. Panels ---------- */
.panel {
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}

.panel--flush { overflow: hidden; }

.panel--accent {
  background: var(--sand);
  border-color: #f0dcc6;
}

.panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--stroke);
}

.panel__title {
  color: var(--ink);
  font-size: var(--text-md);
  font-weight: 700;
}

.panel__sub {
  margin-top: 0.125rem;
  color: var(--muted);
  font-size: var(--text-xs);
}

.panel__body { padding: var(--space-5); }

.panel__body--tight { padding: var(--space-4); }
.panel__body--divided { border-bottom: 1px solid var(--stroke); }

.panel__foot {
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--stroke);
  background: var(--white);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.panel__link {
  color: var(--orange);
  font-size: var(--text-sm);
  font-weight: 700;
}

.grid {
  display: grid;
  gap: var(--space-5);
}

/* Short lists of choice cards, slots and notes keep an 8px gap at every width; .grid--start
   packs the rows (and a 2-up pair) to the top instead of stretching them. */
.grid.grid--tight { gap: 0.5rem; }
.grid--start { align-content: start; align-items: start; }

.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--5 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); } /* 5 across at desktop; fewer before a tile gets narrower than 12rem */
/* ---------- 4. Metrics ---------- */
.metric {
  padding: var(--space-4) var(--space-5);
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}

.metric__label {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.metric__icon { width: 0.875rem; height: 0.875rem; color: var(--orange); }

.metric__value {
  margin-top: 0.5rem;
  color: var(--ink);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.metric__note {
  margin-top: 0.25rem;
  color: var(--muted);
  font-size: var(--text-xs);
}

.metric__note--up { color: #1f7a4d; font-weight: 600; }

/* ---------- 5. Pills & badges ---------- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3125rem;
  padding: 0.1875rem 0.625rem;
  border-radius: var(--radius-pill);
  background: var(--line);
  color: var(--ink-soft);
  font-size: var(--text-xs);
  font-weight: 700;
  white-space: nowrap;
}

.pill__dot {
  width: 0.375rem;
  height: 0.375rem;
  flex: none;
  border-radius: 50%;
  background: currentColor;
}

.pill--ok     { background: #e4f4ea; color: #1f7a4d; }
.pill--warn   { background: #fdefd7; color: #96590a; }
.pill--danger { background: #fde6e2; color: #b32b17; }
.pill--info   { background: #e6eefb; color: #2a5798; }
.pill--accent { background: var(--sand); color: #a8490f; }
.pill--muted  { background: var(--line); color: var(--muted); }
.pill--pickup { background: #dff3f1; color: #0f6e66; }
.pill--dinein { background: #ede7fb; color: #5b3fa8; }

.pill__icon { width: 0.8125rem; height: 0.8125rem; flex: none; }

.verified {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.6875rem;
  border-radius: var(--radius-pill);
  background: var(--grad-trust);
  color: var(--white);
  font-size: var(--text-xs);
  font-weight: 700;
}

.verified__icon { width: 0.8125rem; height: 0.8125rem; flex: none; }
.verified__more { margin-left: -0.375rem; white-space: pre; } /* its leading space already separates it; cancel the flex gap */

.chip--compact { padding: 0.3125rem 0.75rem; color: var(--ink-soft); } /* base .chip is in styles.css */

.chip--on {
  background: var(--sand);
  border-color: var(--orange);
  color: #a8490f;
}

.chip__icon { width: 0.875rem; height: 0.875rem; flex: none; }

/* ---------- 6. Tables ---------- */
.table-wrap { overflow-x: auto; position: relative; } /* keeps .sr-only headers from widening the page */

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

.table th,
.table td {
  padding: 0.8125rem var(--space-5);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--stroke);
  white-space: nowrap;
}

.table thead th {
  background: var(--cream);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

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

.table tbody tr:hover { background: var(--cream); }

/* Sortable headers — app.js adds tabindex to every header except Actions. */
.table thead th[tabindex] { cursor: pointer; user-select: none; }
.table thead th[tabindex]:hover,
.table thead th[aria-sort] { color: var(--ink); }
.table thead th[aria-sort="ascending"]::after { content: " \2191"; }
.table thead th[aria-sort="descending"]::after { content: " \2193"; }

.table__strong { color: var(--ink); font-weight: 700; }
.table__muted { color: var(--muted); }
.table .table__wrap-cell { white-space: normal; min-width: 14rem; }
/* Wide tables whose long header labels may take two lines, so the table fits its panel. */
.table--wrap-head thead th { white-space: normal; }
.table__num { text-align: right; font-variant-numeric: tabular-nums; }
/* A copy of the column header in each cell, shown only when the table is cards. */
.table__label { display: none; }

.table__person {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

/* ---------- 7. Banners ---------- */
.banner {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--stroke);
  border-left-width: 0.1875rem;
  border-radius: var(--radius-md);
  background: var(--white);
}

.banner__icon { width: 1.125rem; height: 1.125rem; flex: none; margin-top: 0.0625rem; }
.banner__text { flex: 1 1 auto; }
.banner__title { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.banner__body { margin-top: 0.1875rem; color: var(--muted); font-size: var(--text-sm); }
.banner__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: 0.75rem; }

.banner--warn   { background: #fffaf0; border-color: #f0d9ac; border-left-color: #e0a02a; }
.banner--warn .banner__icon { color: #96590a; }
.banner--danger { background: #fff6f4; border-color: #f4cfc7; border-left-color: var(--red); }
.banner--danger .banner__icon { color: #b32b17; }
.banner--info   { background: #f5f8fd; border-color: #d3e0f4; border-left-color: #2a5798; }
.banner--info .banner__icon { color: #2a5798; }
.banner--ok     { background: #f4fbf6; border-color: #cbe8d6; border-left-color: #1f7a4d; }
.banner--ok .banner__icon { color: #1f7a4d; }

/* ---------- 8. Empty states ---------- */
.empty {
  display: grid;
  justify-items: center;
  gap: 0.5rem;
  padding: var(--space-7) var(--space-5);
  text-align: center;
}

.empty__icon {
  width: 2.5rem;
  height: 2.5rem;
  margin-bottom: 0.25rem;
  color: var(--muted-light);
}

.empty__title { color: var(--ink); font-size: var(--text-md); font-weight: 700; }
.empty__body { max-width: 26rem; color: var(--muted); font-size: var(--text-sm); }
.empty__action { margin-top: var(--space-3); }

/* ---------- 9. Buttons (app additions) ---------- */
.btn--quiet {
  background: var(--sand);
  color: #a8490f;
}

.btn--danger {
  background: var(--white);
  border: 1px solid #f0c5bc;
  color: #b32b17;
}

/* One height for every small button (33px, over the 32px tap minimum): filled
   variants have no border, so without min-height they sat 2px under outlined ones. */
.btn--sm { min-height: 2.0625rem; padding: 0.4375rem 0.875rem; }
.btn--sm .btn__label { font-size: var(--text-xs); }

.btn--block { width: 100%; }

.btn[disabled],
.btn--disabled {
  background: var(--line);
  color: var(--muted-light);
  cursor: not-allowed;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

/* Controls packed into a table cell (status + pill, row actions). */
.btn-row.btn-row--tight { gap: 0.5rem; }

/* ---------- 10. Forms (app additions) ---------- */
.form { display: grid; gap: var(--space-5); }
/* View tabs under a filter form keep the form's spacing; they stay on the page
   when the form moves into the Filters drawer (admin-operators). */
.form + .tabs { margin-top: var(--space-5); }

.form__section { display: grid; gap: var(--space-4); }

.form__legend {
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 700;
}

.field-row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field-row--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.field-row--3-1-1 { grid-template-columns: minmax(0, 3fr) minmax(0, 1fr) minmax(0, 1fr); align-items: end; }

.input--area { min-height: 6.5rem; resize: vertical; }

/* A hint that belongs to the whole row above it tucks up under that row. */
.field__hint--tuck { margin-top: -0.75rem; }

/* Short fields outside the wizard (a date or guest count) take the wizard's --w-sm width;
   inside the wizard the --fw tokens size them. */
.field--sm { max-width: 11rem; }
.wizard:not(.wizard--plain) .field--sm { max-width: none; }

.input--error {
  border-color: var(--red);
  background: #fff8f7;
}

/* .input-prefix draws its own border and zeroes the inner input's, so a
   prefixed field (e.g. the storefront address) needs the error on the wrapper. */
.input-prefix--error {
  border-color: var(--red);
  background: #fff8f7;
}

.field__error {
  display: flex;
  align-items: center;
  gap: 0.3125rem;
  color: #b32b17;
  font-size: var(--text-xs);
  font-weight: 600;
}

.field__error-icon { width: 0.8125rem; height: 0.8125rem; flex: none; }

.input-prefix {
  display: flex;
  align-items: center;
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-sm);
}

.input-prefix__mark {
  padding-left: 0.875rem;
  color: var(--muted);
  font-size: 1rem;
}

.input-prefix .input {
  height: auto; /* the wrapper carries the field height and border */
  border: 0;
  padding-left: 0.375rem;
}

.input-prefix .input:focus-visible { outline: none; }
/* The ring moves to the whole field (same ring as a plain .input), keyboard focus only. */
.input-prefix:has(.input:focus-visible) { outline: 2px solid var(--orange); outline-offset: 1px; border-color: transparent; }

.toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  cursor: pointer;
}

.toggle__track {
  position: relative;
  width: 2.5rem;
  height: 1.375rem;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--line);
}

.toggle__knob {
  position: absolute;
  top: 0.1875rem;
  left: 0.1875rem;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--white);
  box-shadow: var(--shadow-card);
}

.toggle--on .toggle__track { background: var(--orange); }
.toggle--on .toggle__knob { left: auto; right: 0.1875rem; }

.toggle__label { font-size: var(--text-sm); font-weight: 600; color: var(--ink); }

.switch-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--stroke);
}
/* A pair of toggles stays on one line; the description beside it wraps instead. */
.switch-row > .btn-row { flex: none; flex-wrap: nowrap; }

.switch-row:last-child { border-bottom: 0; }
.switch-row__title { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.switch-row__body { margin-top: 0.1875rem; color: var(--muted); font-size: var(--text-sm); }

/* ---------- 11. Tabs ---------- */
.tabs {
  display: flex;
  gap: var(--space-5);
  /* The rule is an inset shadow, not a border, so the strip can scroll sideways at
     any width without clipping the active tab's underline, which covers it. */
  box-shadow: inset 0 -1px 0 var(--stroke);
  overflow-x: auto;
  scrollbar-width: none;
}

.tabs::-webkit-scrollbar { display: none; }

/* Scroll cue for strips that scroll sideways (tabs, the settings tab strip): the
   --strip-bg layers scroll with the content and cover two edge shadows, so a soft
   shadow shows only on a side that has more tabs. A strip that fits looks unchanged. */
.tabs,
.settings__nav .stepper {
  --strip-bg: var(--white);
  background:
    linear-gradient(to right, var(--strip-bg) 50%, transparent) left center / 2rem 100% no-repeat local,
    linear-gradient(to left, var(--strip-bg) 50%, transparent) right center / 2rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(23, 18, 14, 0.18), transparent) left center / 0.875rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(23, 18, 14, 0.18), transparent) right center / 0.875rem 100% no-repeat scroll;
}
.tabs:not(.panel .tabs) { --strip-bg: var(--surface); } /* page-level tabs sit on the page ground */

.tab {
  padding: 0 0 0.75rem;
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  border-bottom: 0.125rem solid transparent;
}

.tab--on { color: var(--ink); border-bottom-color: var(--orange); }

/* A tab strip as the last thing in a panel body sits on the body's bottom edge. */
.panel__body--tabs { padding-bottom: 0; }

.tab__count {
  display: inline-block;
  min-width: 1.25rem;
  margin-left: 0.375rem;
  padding: 0.0625rem 0.375rem;
  border-radius: var(--radius-pill);
  background: var(--line);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  line-height: 1.5;
  text-align: center;
}

/* ---------- 12. Stepper ---------- */
.stepper {
  display: grid;
  gap: 0.125rem;
}

.stepper__item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 600;
}

.stepper__item--on { background: var(--sand); color: var(--ink); }
.stepper__item--done { color: var(--ink-soft); }

.stepper__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.375rem;
  height: 1.375rem;
  flex: none;
  border: 1px solid var(--stroke);
  border-radius: 50%;
  background: var(--white);
  font-size: var(--text-xs);
  font-weight: 700;
}

.stepper__item--on .stepper__mark {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--white);
}

.stepper__item--done .stepper__mark {
  background: #e4f4ea;
  border-color: #bfe3cd;
  color: #1f7a4d;
}

.stepper__check { width: 0.75rem; height: 0.75rem; }

.progress {
  height: 0.375rem;
  border-radius: var(--radius-pill);
  background: var(--line);
  overflow: hidden;
}

.progress__bar {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--grad-warm);
}

/* ---------- 13. Modal (rendered open for design review) ---------- */
.modal-scrim {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--gutter);
  background: rgba(23, 18, 14, 0.45);
}

.modal {
  width: 100%;
  max-width: 30rem;
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-field);
}

.modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-5) 0;
}

.modal__title { color: var(--ink); font-size: var(--text-md); font-weight: 700; }
.modal__sub { margin-top: 0.25rem; color: var(--muted); font-size: var(--text-sm); }
.modal__body { padding: var(--space-4) var(--space-5); }

.modal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5) var(--space-5);
}

/* ---------- 14. Money rows ---------- */
.money { display: grid; gap: 0.625rem; }

.money__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--text-sm);
}

.money__label {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  color: var(--muted);
}

/* The fee "i": a button that opens the page's #pop-fee popover; the invisible layer
   gives the 15px dot a 25px tap area. */
.money__info {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 0.9375rem;
  height: 0.9375rem;
  flex: none;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--line);
  color: var(--muted);
  font: 700 var(--text-xs)/1 var(--font-sans);
  cursor: pointer;
}
.money__info::after { content: ""; position: absolute; inset: -0.3125rem; border-radius: 50%; }
.money__info:hover { color: var(--ink); }

.money__value { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }

.money__row--total {
  padding-top: 0.75rem;
  border-top: 1px solid var(--stroke);
  font-size: var(--text-md);
}

.money__row--total .money__label { color: var(--ink); font-weight: 700; }
.money__row--total .money__value { font-weight: 700; }

.money__note {
  padding: 0.75rem;
  border-radius: var(--radius-sm);
  background: var(--cream);
  color: var(--muted);
  font-size: var(--text-xs);
  line-height: 1.55;
}

/* ---------- 15. Storefront ---------- */
/* Platform pages that keep the marketing header + footer (storefront,
   checkout). Same neutral ground as .app; warm tints stay for accents. */
.page-app {
  --stroke: var(--line-cool);
  background: var(--surface);
}

.sf-hero { position: relative; }

.sf-hero__photo {
  width: 100%;
  height: 22.5rem;
  object-fit: cover;
}

.sf-head {
  max-width: var(--page);
  margin: -5.5rem auto 0;
  padding: 0 var(--gutter);
  position: relative;
}

.sf-head__card {
  position: relative;
  container: sfhead / inline-size; /* its action row follows the card's own width (also inside the editor preview) */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-4);
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}

.sf-head__logo {
  width: 9rem;
  height: 9rem;
  flex: none;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--line);   /* stays warm — it frames a photo, not chrome */
}

.sf-head__text { flex: 1 1 18rem; min-width: 0; }

.sf-head__badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.sf-head__name {
  color: var(--ink);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.sf-head__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem var(--space-4);
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: var(--text-sm);
}

.sf-head__meta-item { display: flex; align-items: center; gap: 0.375rem; }
.sf-head__meta-icon { width: 0.875rem; height: 0.875rem; flex: none; color: var(--orange); }
.sf-head__actions { display: grid; gap: 0.5rem; min-width: 10.5rem; }
/* Too narrow for logo | text | actions on one row (648px): the actions take their own
   full row as two equal buttons, as on phones, instead of a narrow column under the logo. */
@container sfhead (width < 40.5rem) {
  .sf-head__actions { flex: 1 1 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.sf-head__policies { position: absolute; top: var(--space-4); right: var(--space-4); }
.sf-head__card:has(.sf-head__policies) .sf-head__name { padding-right: 4.5rem; } /* clears the Policies link (live storefront only) */

.sf-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 21rem;
  gap: var(--space-6);
  max-width: var(--page);
  margin: 0 auto;
  padding: var(--space-6) var(--gutter) var(--space-8);
  align-items: start;
}

.sf-section { display: grid; gap: var(--space-4); }
.sf-section + .sf-section { margin-top: var(--space-6); }

.sf-section__title {
  color: var(--ink);
  font-size: var(--text-lg);
  font-weight: 700;
}

.sf-section__body { color: var(--muted); font-size: var(--text-base); line-height: 1.65; }

.dish {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--white);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-md);
}

.dish__photo {
  width: 6.5rem;
  height: 6.5rem;
  flex: none;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.dish__text { flex: 1 1 auto; min-width: 0; }
.dish__top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
.dish__name { color: var(--ink); font-size: var(--text-md); font-weight: 700; }
.dish__price { color: var(--ink); font-weight: 700; white-space: nowrap; }
.dish__body { margin-top: 0.3125rem; color: var(--muted); font-size: var(--text-sm); line-height: 1.55; }
.dish__foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: 0.75rem; }
.dish__tags { display: flex; flex-wrap: wrap; gap: 0.375rem; }
/* cook-menu: under 1450px a card's action buttons fold into a ⋯ menu in the
   card's top-right corner (a .period__more dropdown, so outside-click and
   Escape close it); the Sold out toggle stays in the foot. */
.dish__more { display: none; }
@media (width < 90.625rem) {
  .dish:has(.dish__more) { position: relative; }
  .dish__foot > .btn-row { display: contents; }
  .dish__foot > .btn-row > .btn { display: none; }
  .dish__more { display: block; position: absolute; top: var(--space-4); right: var(--space-4); }
  .dish:has(.dish__more) .dish__top { padding-right: 2.75rem; } /* the price clears the ⋯ */
}

.cart-panel { position: sticky; top: var(--space-5); }

.cart-line {
  display: flex;
  gap: 0.75rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--stroke);
}

.cart-line:last-of-type { border-bottom: 0; }
.cart-line__qty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.0625rem 0.375rem;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--sand);
  color: #a8490f;
  font-size: var(--text-xs);
  font-weight: 700;
}
.cart-line__text { flex: 1 1 auto; min-width: 0; }
.cart-line__name { color: var(--ink); font-size: var(--text-sm); font-weight: 600; }
.cart-line__meta { margin-top: 0.125rem; color: var(--muted); font-size: var(--text-xs); }
.cart-line__price { color: var(--ink); font-size: var(--text-sm); font-weight: 600; white-space: nowrap; }

.slot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 0.625rem 0.875rem;
  border: 1px solid var(--stroke);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-size: var(--text-sm);
}

.slot--on { border-color: var(--orange); background: var(--sand); }
.slot__time { color: var(--ink); font-weight: 600; }
.slot__left { color: var(--muted); font-size: var(--text-xs); }
.slot__stack { display: flex; flex-direction: column; gap: 0.125rem; }

/* ---------- 17. Storefront dish rating ----------
   NOTE: styles.css .rating is absolutely positioned for marketing meal cards.
   App pages must use this inline variant instead. */
.dish__rating {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  white-space: nowrap;
}

.dish__rating-star {
  width: 0.8125rem;
  height: 0.8125rem;
  flex: none;
  color: var(--orange);
}

/* styles.css .field is a stretch grid; in a multi-column row an input next to a
   hinted field drifts down. Pin rows to the top. */
.field { align-content: start; }

/* Drawer header: brand plus a close control that only exists in drawer mode. */
.app-side__top {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.app-side__close { display: none; margin-left: auto; flex: none; }

/* Dashboard action-queue rail — sits to the right of the body content. Both
   columns keep their natural height and ride .app-body's scroll, the same one
   every other page uses; under 1770px the rail is hidden (below). */
.app-body--rail {
  display: flex;
  align-items: flex-start;
  gap: var(--space-6);
}

.app-body--rail > .app-body__inner {
  flex: 1 1 auto;
  min-width: 0;
  align-content: start;
}

.dash-rail {
  display: grid;
  gap: var(--space-5);
  flex: none;
  width: 22rem;        /* .app-body__inner fills the space left of it */
}

/* The rail pins beside the scrolling content — its head and foot stay put and
   only the item list scrolls. Its height is the scrollport: the viewport less
   the app bar and .app-body's padding. */
@media (width > 75rem) {
  .dash-rail { position: sticky; top: 0; }

  /* Fixed, not max-, so the card keeps its height whatever the filter leaves. */
  .dash-rail .panel {
    display: flex;
    flex-direction: column;
    height: calc(100dvh - var(--app-bar-h) - var(--space-6) * 2);
  }

  .dash-rail .panel__head,
  .dash-rail .panel__foot { flex: none; }
  .dash-rail .panel__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
}

/* Under 1770px the rail squeezes the content, so it goes; the top-bar bell
   opens the same list. */
@media (width < 110.625rem) {
  .dash-rail { display: none; }
}

/* Filter chips in a panel head — the Orders toolbar control, sized down to sit
   beside a panel title. Stacked heads put it on its own line under the sub. */
.panel__head .period__presets { box-shadow: none; flex-wrap: wrap; }
.panel__head:not(.panel__head--stack) .period__presets { margin-left: auto; }
.panel__head .period__opt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  padding: 0.3125rem 0.625rem;
  font-size: var(--text-xs);
}

/* Count rides in the label as "(n)" — a badge costs width the rail hasn't got. */
.period__opt-count { color: var(--muted-light); font-weight: 600; }
.period__opt--on .period__opt-count { color: inherit; opacity: 0.7; }

/* A stacked head (the rail) gives the bar the full panel width and keeps all
   five chips on one row, so they run tight: minimal padding, no wrapping. */
.panel__head--stack .period__presets { margin-top: var(--space-3); }
.panel__head--stack .period__group { flex: 1 1 auto; flex-wrap: nowrap; }
.panel__head--stack .period__opt {
  flex: 1 1 auto;
  min-width: 0;
  gap: 0.1875rem;
  padding-inline: 0.25rem;
}

/* Stacked name + order number, so the orders table loses its Order column and
   fits the narrower dashboard column without scrolling. */
.table__person-text { display: grid; }

.table__person-sub {
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 600;
}

/* Drawer motion. Closed is display:none, so the slide is an entry animation
   rather than a persistent off-canvas transform. */
@keyframes drawer-in {
  from { transform: translateX(-100%); }
  to   { transform: none; }
}

@keyframes scrim-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---------- Dashboard mock alignment ---------- */
.avatar { overflow: hidden; }
.avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }

/* Banner whose action sits at the right instead of under the copy */

.panel__title--accent { color: var(--orange); display: flex; align-items: center;}
.panel__head--stack { display: block; }
.panel__foot--center { text-align: center; }

/* Request rows in the dashboard rail — dividers run the full card width */
.dash-rail .panel__body { display: flex; flex-direction: column; padding-top: 0; padding-bottom: 0; }

/* Today's orders sits beside the rail, so it is narrower than the full orders
   page the table was sized for — tighten the cells so Total paid is not clipped. */
.dash-orders .table th,
.dash-orders .table td { padding-inline: var(--space-4); }
.dash-orders .table td:nth-child(3) { white-space: normal; }

.req {
  display: flex;
  gap: 0.625rem;
  padding: var(--space-5) 0;
  /* Rows bleed to the container edge by exactly its padding (16px in a phone panel). */
  margin: 0 calc(var(--req-bleed, var(--space-5)) * -1);
  padding-left: var(--req-bleed, var(--space-5));
  padding-right: var(--req-bleed, var(--space-5));
  border-bottom: 1px solid var(--stroke);
}

.req:last-child { border-bottom: 0; }
.req__timer { display: block; }
.req__icon { width: 1.0625rem; height: 1.0625rem; flex: none; margin-top: 0.15rem; }
.req__icon--warn { color: #96590a; }
.req__icon--info { color: #2a5798; }
.req__title { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.req__body { margin-top: 0.375rem; color: var(--muted); font-size: var(--text-sm); line-height: 1.55; }
.req__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }

/* Dine-in requests page — timer and buttons sit in a column right of the text.
   The dashboard rail keeps the stacked .req above (too narrow to split). */
.req--split .req__text { flex: 1 1 auto; min-width: 0; }
.req__side { display: flex; flex-direction: column; align-items: flex-end; gap: 0.75rem; flex: 0 1 auto; min-width: 0; max-width: min(16rem, 45%); }
.req__side .req__actions { margin-top: 0; flex-wrap: nowrap; }

/* Answered-today list in the rail — avatar, guest, status + amount on the right. */
.req--answer { align-items: center; padding-top: var(--space-4); padding-bottom: var(--space-4); }
.req--answer .req__text { flex: 1 1 auto; min-width: 0; }
.req--answer .req__body { margin-top: 0.125rem; font-size: var(--text-xs); }
.req--answer .req__side { gap: 0.25rem; }
.req__amount { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.req__amount--muted { color: var(--muted); font-weight: 400; }

/* Seating slot with a seat meter under the time. */
.slot--meter { flex-wrap: wrap; row-gap: 0.5rem; }
.slot--meter .progress,
.slot__note { flex-basis: 100%; }
.slot__note { color: #96590a; font-size: var(--text-xs); font-weight: 600; }
.slot__note--quiet { color: var(--muted); font-weight: 400; }


/* ---------- 18. Storefront revision (Li's Hearth mock) ----------
   Rating moves above the dish name so the foot row belongs to the tags and
   the Add button; policies become three cards; the trust note reads as a
   plain white card rather than a tinted banner. */

/* Rating as an eyebrow — only when it sits directly in .dish__text. */
.dish__text > .dish__rating { margin-bottom: 0.1875rem; }

.policy__icon {
  width: 2.5rem;
  height: 2.5rem;
  margin-bottom: var(--space-4);
}

.policy__title { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }

.policy__body {
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: 0.75rem;   /* 12px — one notch under --text-sm, as in the mock */
  line-height: 1.6;
}

/* Trust note: white card, no tint, no accent rule. */
.banner--card {
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background: var(--white);
  border: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}

.banner__icon--trust {
  width: 2.25rem;
  height: 2.25rem;
  margin-top: 0;
  color: #2a5798;
}

/* The cart's closing note is plain text, not a tinted block. */
.money__note--bare { padding: 0; background: none; }

/* ---------- 19. Licensing wizard, documents, submission ----------
   Batch B. Composes from .stepper, .progress, .field, .banner, .pill and
   .panel; only the wizard frame, document rows and the upload box are new. */
.wizard {
  display: grid;
  grid-template-columns: 17rem minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
}

.wizard__progress {
  display: grid;
  gap: 0.5rem;
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--stroke);
}

.wizard__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

/* County submission: under 700px each action takes the full width on its own line. */
@media (width < 43.75rem) {
  .wizard__foot--stack > .btn-row,
  .wizard__foot--stack > .btn-row > .btn { flex: 1 1 100%; }
}

/* Document row — generated PDFs, uploads, package attachments. */
.doc {
  display: flex;
  flex-wrap: wrap; /* the action cluster moves to its own line before the name gets narrower than 12rem */
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--stroke);
}

.doc:first-child { padding-top: 0; }
.doc:last-child { padding-bottom: 0; border-bottom: 0; }

.doc__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--sand);
  color: var(--orange);
}

.doc__glyph { width: 1.125rem; height: 1.125rem; }
.doc__text { flex: 1 1 12rem; min-width: 0; }
.doc__name { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.doc__meta { margin-top: 0.125rem; color: var(--muted); font-size: var(--text-xs); }
.doc__actions { display: flex; flex: none; flex-wrap: nowrap; align-items: center; gap: 0.5rem; margin-left: auto; } /* one line, never broken up */

/* Version / replacement history under a document, rendered open. */
.doc--sub { padding-left: 3.25rem; }
.doc--sub .doc__name { font-weight: 600; }

.dropzone {
  display: grid;
  justify-items: center;
  gap: 0.375rem;
  padding: var(--space-5);
  border: 1px dashed var(--muted-light);
  border-radius: var(--radius-md);
  background: var(--surface);
  text-align: center;
}

.dropzone--error { border-color: var(--red); background: #fff8f7; }
.dropzone__icon { width: 1.75rem; height: 1.75rem; color: var(--muted); }
.dropzone__title { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.dropzone__body { color: var(--muted); font-size: var(--text-xs); }

.input--tall { min-height: 15rem; }

/* Main column first, rail on the right — permitted branch, submission. */
.wizard--end { grid-template-columns: minmax(0, 1fr) 21rem; }

/* Steps panel rides .app-body's scroll; scrolls itself if taller than the viewport. */
/* Only the licensing step list pins; .wizard--end rails (order status, seatings, rating, details)
   scroll with the page on every page alike, whatever element they are. */
.wizard:not(.wizard--end) > aside.panel {
  position: sticky;
  top: 0;
  max-height: calc(100dvh - var(--app-bar-h) - var(--space-6) * 2);
  overflow-y: auto;
}

/* Wizard forms (licensing steps and the pages that follow them; .wizard--plain pages
   only borrow the main + rail layout and keep standard forms): hairline + air between each question group so steps scan cleanly.
   No line directly under a legend, label row, hint or banner — those introduce what follows. */
.wizard:not(.wizard--plain) .form { gap: var(--space-6); }
.wizard:not(.wizard--plain) .form__section { gap: var(--space-5); }
.wizard:not(.wizard--plain) .form__legend { font-size: var(--text-md); }
.wizard:not(.wizard--plain) :is(.form, .form__section) > :is(.form__section, .field, .field-row):not(:first-child):not(:is(.form__legend, .field__label-row, .field__hint, .banner) + *) {
  padding-top: var(--space-5);
  border-top: 1px solid var(--stroke);
}
/* Section dividers run edge to edge: bleed out through .panel__body's padding and pad back in. */
.wizard:not(.wizard--plain) .panel__body { --bleed: var(--space-5); }
.wizard:not(.wizard--plain) .form > .form__section { margin-inline: calc(var(--bleed) * -1); padding-inline: var(--bleed); }

/* Field widths — sized to the answer, not the panel. Type sets the default
   (text lg, select md, number/time/date sm, textarea full); .field--xs…full overrides.
   Rows wrap as flex so each field keeps its width and drops to a new line when tight. */
.wizard:not(.wizard--plain) .form { --w-xs: 7rem; --w-sm: 11rem; --w-md: 20rem; --w-lg: 36rem; }
.wizard:not(.wizard--plain) .field:has(> .input, > .input-prefix) { --fw: var(--w-lg); }
.wizard:not(.wizard--plain) .field:has(> select.input) { --fw: var(--w-md); }
.wizard:not(.wizard--plain) .field:has(> input:is([type="number"], [type="time"], [type="date"])) { --fw: var(--w-sm); }
.wizard:not(.wizard--plain) .field:has(> textarea.input) { --fw: 100%; }
.wizard:not(.wizard--plain) .field.field--xs { --fw: var(--w-xs); }
.wizard:not(.wizard--plain) .field.field--sm { --fw: var(--w-sm); }
.wizard:not(.wizard--plain) .field.field--md { --fw: var(--w-md); }
.wizard:not(.wizard--plain) .field.field--lg { --fw: var(--w-lg); }
.wizard:not(.wizard--plain) .field.field--full { --fw: 100%; }
.wizard:not(.wizard--plain) .field-row { display: flex; flex-wrap: wrap; align-items: flex-start; }
.wizard:not(.wizard--plain) .field-row--3-1-1 { align-items: flex-end; }
.wizard:not(.wizard--plain) .field-row > .field { flex: 1 1 var(--fw, 100%); min-width: 0; max-width: var(--fw, none); }
/* A standalone field stays full width so its divider does; its contents take the cap. */
.wizard:not(.wizard--plain) :is(.form, .form__section) > .field > * { max-width: var(--fw, none); }
.wizard:not(.wizard--plain) .field-row > .field--full { flex-basis: 16rem; }
/* Pills, hints and errors need room to read — narrow fields that carry one widen to md. */
.wizard:not(.wizard--plain) .field-row > .field:has(> .field__label-row .pill, > .field__hint, > .field__error),
.wizard:not(.wizard--plain) :is(.form, .form__section) > .field:has(> .field__label-row .pill, > .field__hint, > .field__error) > * { min-width: min(100%, var(--w-md)); }

/* Day rows (licensing step 5, Proposed hours of operation): day name left, its field right. */
.day-fields { display: grid; gap: 0.625rem; }
.day-field { display: grid; grid-template-columns: 6.5rem minmax(0, var(--w-md, 20rem)); align-items: center; gap: var(--space-3); }

/* Licensing accordion (under 1180px): every step is its own row, and the open step's form
   hangs off its row. The steps panel, nav and main column dissolve (display: contents)
   so `order` can slot the form in after the current step. Other rows are links to their
   step; the current row folds its form (app.js, .wizard--shut). */
.stepper__chev { display: none; }
@media (width < 73.75rem) {
  .wizard--accordion { gap: var(--space-2); }
  .wizard--accordion > aside.panel,
  .wizard--accordion > aside.panel > .panel__body,
  .wizard--accordion nav.stepper,
  .wizard--accordion > .grid { display: contents; }
  .wizard--accordion .wizard__progress,
  .wizard--accordion nav .stepper__item {
    background: var(--white);
    border: 1px solid var(--stroke);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
  }
  .wizard--accordion .wizard__progress { margin: 0 0 var(--space-2); padding: var(--space-4) var(--space-5); }
  .wizard--accordion nav .stepper__item { order: 1; padding: 0.875rem var(--space-5); }
  .wizard--accordion nav [aria-current="step"] { order: 2; background: var(--sand); }
  .wizard--accordion nav [aria-current="step"] ~ * { order: 4; }
  .wizard--accordion > .grid > .panel { order: 5; margin-top: var(--space-3); }
  .wizard--accordion > .grid > .panel:first-child {
    order: 3;
    margin-top: calc(-1 * var(--space-2));
    border-top: 0;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  }
  .wizard--accordion:not(.wizard--shut) nav [aria-current="step"] { border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: none; }
  .wizard--accordion > .grid > .panel:first-child .panel__title { display: none; } /* the row above names the step */
  .wizard--shut > .grid > .panel:first-child { display: none; }
  .stepper__chev { display: block; width: 1.125rem; height: 1.125rem; flex: none; margin-left: auto; color: var(--muted); }
  .wizard--accordion:not(.wizard--shut) [aria-current="step"] .stepper__chev { transform: rotate(180deg); color: var(--ink); }
  /* While the open step scrolls, its row pins to the top of .app-body and its foot to the bottom. */
  .wizard--accordion:not(.wizard--shut) nav [aria-current="step"] { position: sticky; top: calc(-1 * var(--app-body-pad)); z-index: 2; }
  .wizard--accordion > .grid > .panel:first-child > .panel__foot { position: sticky; bottom: calc(-1 * var(--app-body-pad)); z-index: 1; }
  /* Validation pill on its own line; Back left, Continue right. */
  .wizard--accordion .wizard__foot { flex-direction: column; align-items: stretch; }
  .wizard--accordion .wizard__foot > .pill { align-self: flex-start; }
  .wizard--accordion .wizard__foot > .btn-row { flex-wrap: nowrap; }
  .wizard--accordion .wizard__foot > .btn-row > :last-child { margin-left: auto; }
}

/* ---------- 20. Running the Hearth ----------
   Batch C. Orders, menu, availability, storefront editor, messages, reviews,
   payments, settings, reports. Composes from .table, .dish, .doc, .req,
   .slot, .chip and .panel; only the pieces below are new. */

/* Rows that run edge to edge inside a flush panel (.req, .switch-row, .thread). */
.panel__body--rows { padding-top: 0; padding-bottom: 0; }

/* Menu item without a photo yet. */
.dish__photo--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px dashed var(--muted-light);
  color: var(--muted-light);
}

.dish__photo-icon { width: 1.75rem; height: 1.75rem; }

/* A menu item's photo set. */
.photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
  gap: var(--space-3);
}

.photos__img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

/* Five-star rating. */
.stars { display: inline-flex; gap: 0.125rem; color: var(--orange); }
.stars__star { width: 0.875rem; height: 0.875rem; flex: none; }
.stars__star--off { color: var(--line); }

/* Operator reply to a review: a native <details> disclosure, so no JS is
   needed to reveal the reply composer. */
.review-reply { margin-top: 0.75rem; }
.review-reply > summary { display: inline-block; list-style: none; color: var(--orange); font-size: var(--text-sm); font-weight: 700; cursor: pointer; }
.review-reply > summary::-webkit-details-marker { display: none; }
.review-reply__form { margin-top: 0.625rem; display: grid; gap: 0.5rem; max-width: 28rem; }
.review-reply__posted { display: flex; gap: 0.625rem; margin-top: 0.75rem; padding: 0.75rem; border-radius: var(--radius-sm); background: var(--surface); }

/* Flag pins to the top right of the review and sits quieter than Reply —
   it is the rare action, not the everyday one. */
.review-flag {
  position: relative; /* holds its visually hidden label on phones, so it cannot extend the page */
  margin-left: auto;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.3125rem;
  flex: none;
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 700;
}

.review-flag__icon { width: 1rem; height: 1rem; flex: none; }

.review-flag:hover,
.review-flag:focus-visible { color: var(--red); }

/* The review being flagged, quoted back inside the sheet. */
.review-flag__quote {
  margin-bottom: 1rem;
  padding: 0.75rem;
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.review__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem var(--space-3);
  margin-top: 0.25rem;
}

/* Messages — one card: conversation list left, the open conversation right. */
.chat { display: grid; grid-template-columns: 20rem minmax(0, 1fr); min-height: 44rem; }
.chat__list { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--stroke); }
.chat__threads { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.chat__main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }

/* Cook messages: the card fills .app-body; only the list and the conversation scroll. */
.app-body--chat { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.app-body--chat > .chat { flex: 1 1 auto; grid-template-rows: minmax(0, 1fr); min-height: 0; border: 0; border-radius: 0; box-shadow: none; }

.chat__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
}

.chat__main > .chat__head { border-bottom: 1px solid var(--stroke); }
.chat__title { color: var(--ink); font-size: var(--text-md); font-weight: 700; }

.chat__tools {
  display: flex;
  gap: 0.5rem;
  padding: 0 var(--space-5) var(--space-4);
  border-bottom: 1px solid var(--stroke);
}

.chat__tools .input-prefix { flex: 1 1 auto; }
.chat__tools .input { padding-left: 0.875rem; }
.chat__tools .icon-button { width: 2.75rem; height: auto; flex: none; border-radius: var(--radius-sm); }
.chat__search-icon { width: 1rem; height: 1rem; flex: none; margin-right: 0.875rem; color: var(--ink-soft); }

.chat__person { display: flex; align-items: center; gap: 0.75rem; min-width: 0; }
.chat__name { color: var(--ink); font-size: var(--text-base); font-weight: 700; }

.chat__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
  margin-top: 0.125rem;
  color: var(--muted);
  font-size: var(--text-xs);
}

.chat__meta-item { display: inline-flex; align-items: center; gap: 0.3125rem; }
.chat__meta-item + .chat__meta-item { padding-left: 0.75rem; border-left: 1px solid var(--stroke); }
.chat__meta-icon { width: 0.875rem; height: 0.875rem; flex: none; }

.chat__body {
  display: grid;
  flex: 1 1 auto;
  align-content: start;
  gap: var(--space-5);
  min-height: 0;
  padding: var(--space-5);
  overflow-y: auto;
  background: var(--surface);
}

.chat__day { display: flex; align-items: center; gap: var(--space-4); color: var(--muted); font-size: var(--text-sm); }
.chat__day-line { flex: 1 1 auto; height: 1px; background: var(--stroke); }
.chat__foot { display: grid; gap: 0.5rem; padding: 0 var(--space-5) var(--space-5); background: var(--surface); }
.chat__note { color: var(--muted); font-size: var(--text-xs); }

.thread { display: flex; align-items: center; gap: 0.75rem; padding: 0.875rem var(--space-5); }
.thread:hover,
.thread--on { background: var(--surface); }
.thread__text { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.125rem; flex: 1 1 auto; min-width: 0; }
.thread__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.thread__name { color: var(--ink); font-size: var(--text-sm); font-weight: 600; }
.thread__time { color: var(--muted); font-size: var(--text-xs); white-space: nowrap; }

.thread__preview {
  overflow: hidden;
  color: var(--muted);
  font-size: var(--text-xs);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.thread__dot { width: 0.4375rem; height: 0.4375rem; flex: none; border-radius: 50%; background: var(--orange); }

/* One message: avatar, then "Name • time" over the bubble. Outgoing mirrors it. */
.msg { display: flex; align-items: flex-start; gap: 0.75rem; max-width: 36rem; }
.msg--out { flex-direction: row-reverse; justify-self: end; }
.msg__stack { display: grid; justify-items: start; gap: 0.5rem; min-width: 0; }
.msg--out .msg__stack { justify-items: end; }
.msg__meta { display: flex; align-items: center; gap: 0.375rem; color: var(--muted); font-size: var(--text-xs); }
.msg__sep { width: 0.25rem; height: 0.25rem; border-radius: 50%; background: currentColor; }

.msg__body,
.msg__item {
  border: 1px solid var(--stroke);
  border-radius: var(--radius-md);
  background: var(--white);
}

.msg__body { padding: 0.625rem 0.875rem; color: var(--ink-soft); font-size: var(--text-sm); }
.msg__item { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0.875rem 0.5rem 0.5rem; }
.msg__item-photo { width: 2.75rem; height: 2.75rem; flex: none; object-fit: cover; border-radius: var(--radius-sm); }
.msg__item-name { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.msg__item-sub { color: var(--muted); font-size: var(--text-xs); }
.msg__item-price { margin-left: var(--space-5); color: var(--ink); font-size: var(--text-sm); font-weight: 600; white-space: nowrap; }

.composer {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-md);
  background: var(--white);
}

.composer:focus-within { border-color: var(--muted-light); }

.composer__input {
  width: 100%;
  min-height: 2.75rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
  resize: none;
}

.composer__input::placeholder { color: var(--muted); }
.composer__input:focus-visible { outline: none; }
.composer__bar { display: flex; align-items: center; gap: var(--space-3); }
.composer__tools { display: flex; align-items: center; gap: 0.25rem; margin-right: auto; }

.composer__tool {
  display: inline-flex;
  padding: 0.25rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
}

.composer__tool:hover { background: var(--surface); }
.composer__tool-icon { width: 1.125rem; height: 1.125rem; }
.composer__sep { width: 1px; height: 1rem; margin: 0 0.25rem; background: var(--stroke); }

/* Customer messages on mobile: thread list first; a thread opens the conversation full-screen
   with its head pinned on top and the composer pinned on the bottom. */
.chat__back { display: none; }

/* Storefront preview — shop-storefront drawn inside a cook panel. */
.sf-frame { background: var(--surface); }

/* Storefront edit — cover photo and logo edited in place, as on a social page. */
.sf-cover { position: relative; }
.sf-cover__photo { display: block; width: 100%; height: 22.5rem; object-fit: cover; } /* the live storefront hero's height */
.sf-cover__edit { position: absolute; right: var(--space-4); bottom: var(--space-4); }

.sf-cover__id {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3) var(--space-5);
  padding: 0 var(--space-5) var(--space-5);
}

.sf-cover__logo { position: relative; flex: none; margin-top: -4.5rem; }

.sf-cover__logo-img {
  display: block;
  width: 9rem;
  height: 9rem;
  object-fit: cover;
  border: 0.25rem solid var(--white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

.sf-cover__logo-edit { position: absolute; right: -0.5rem; bottom: -0.5rem; }
.sf-cover__text { flex: 1 1 14rem; min-width: 0; }
.sf-cover__hint { flex-basis: 100%; }

/* Link rows divided by hairlines ("Also on your storefront"), each link with a trailing arrow. */
.money--rows { gap: 0; }

.money--rows .money__row {
  align-items: center;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--stroke);
}

.money--rows .money__row:first-child { padding-top: 0; }
.money--rows .money__row:last-child { padding-bottom: 0; border-bottom: 0; }

.panel__link--arrow { display: inline-flex; align-items: center; gap: 0.375rem; white-space: nowrap; }
.panel__link-icon { width: 0.875rem; height: 0.875rem; flex: none; }

/* Storefront edit — one settings panel: section tabs (.stepper) left, the open section right. */
.settings { display: grid; grid-template-columns: 15rem minmax(0, 1fr); }
.settings__nav { padding: var(--space-4); border-right: 1px solid var(--stroke); }
.settings__icon { width: 1.0625rem; height: 1.0625rem; flex: none; }

/* Cook settings — the panel fills the body, so every step is the same height and its save bar sits at the bottom. */
.app-body__inner--fill { min-height: 100%; grid-template-rows: auto minmax(0, 1fr); }
.panel--fill { display: flex; flex-direction: column; }
.panel--fill .settings { flex: 1 1 auto; grid-template-rows: minmax(0, 1fr); }
.panel--fill .settings__panes { display: flex; flex-direction: column; }
.panel--fill .settings__pane:not([hidden]) { flex: 1 1 auto; display: flex; flex-direction: column; }
.panel--fill .settings__pane .panel__body { flex: 1 1 auto; }

/* ---------- 21. Customer ----------
   Batch D. Search, confirmation, receipt and the customer account. These keep
   the marketing header (D-10) and compose from .sf-body, .meal-card, .panel,
   .table, .thread and .msg; only the layout modifiers below are new. */

/* Search bar, page head or account tabs across the whole body grid. */
.sf-body__head { grid-column: 1 / -1; display: grid; gap: var(--space-5); }

/* One reading column — account pages without a rail. */
.sf-body--single { grid-template-columns: minmax(0, 1fr); }
/* A single reading column (receipt): the page head keeps the gutter like the other shop
   pages; only the content under it is capped at 44rem. */
.sf-stack { display: grid; gap: var(--space-5); min-width: 0; }
.sf-stack--narrow > :not(.page-head) { width: 100%; max-width: 44rem; }

/* Search: filters on the left. Below 1200px it stacks, as .sf-body does. */
@media (width > 75rem) {
  .sf-body--filters { grid-template-columns: 19.5rem minmax(0, 1fr); }
}

/* Hearth result cards: the marketing meal card on the platform hairline. */
:is(.page-app, .app) .meal-card,
:is(.page-app, .app) .meal-card__foot { border-color: var(--stroke); } /* shop pages and the customer app (favorites) */

.results {
  display: grid;
  /* Columns follow the space the grid actually has (filters column, sidebar or
     neither), with the same 17rem card minimum as the marketing meal grid. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-5);
  align-items: start;
}

.stars--lg .stars__star { width: 1.75rem; height: 1.75rem; }

/* ---------- 22. Side sheet ----------
   Right-hand drawer (cook-menu "Add menu item"), full height over the top bar
   and sidebar. Closed is [hidden], so nothing lands off-canvas in Figma. */
.sheet-scrim {
  position: fixed;
  inset: 0;
  z-index: 45;
  background: rgba(23, 18, 14, 0.45);
  animation: scrim-in 0.22s ease-out;
}

.sheet {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  width: min(var(--sheet-w), 100%);
  container: sheet / inline-size; /* its content lays out by the sheet's width, not the window's */
  background: var(--white);
  border-left: 1px solid var(--stroke);
  box-shadow: var(--shadow-field);
  animation: sheet-in 0.22s ease-out;
}

.sheet__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--stroke);
}

.sheet__body { flex: 1 1 auto; overflow-y: auto; padding: var(--space-5); }

.sheet__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--stroke);
}

/* A destructive action (pickup window "Delete window") sits alone on the left. */
.sheet__foot .btn--danger { margin-right: auto; }

@keyframes sheet-in {
  from { transform: translateX(100%); }
  to   { transform: none; }
}

/* Closing plays in reverse; app.js sets [hidden] on animationend. */
@keyframes sheet-out {
  from { transform: none; }
  to   { transform: translateX(100%); }
}

@keyframes scrim-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

.sheet.sheet--closing { animation: sheet-out 0.2s ease-in forwards; }
.sheet-scrim.sheet--closing { animation: scrim-out 0.2s ease-in forwards; }

/* Phone sheet: only when the sheet itself is narrower than its 34rem, i.e. full width on a phone
   (33rem, because the 1px border makes a full sheet's content box 543px). */
@container sheet (width < 33rem) {
  .sheet__head, .sheet__body, .sheet__foot { padding: var(--space-4); }
  .sheet__foot { flex-wrap: wrap; }
  .sheet__foot .btn { flex: 1 1 9rem; }
}

/* ---------- 23. Dashboard & ordering revisions (v1 cleanup) ---------- */

/* Unavailable slots and sold-out dishes: visibly off, not selectable. */
.slot--off { background: var(--surface); border-style: dashed; cursor: not-allowed; }
.slot--off .slot__time { color: var(--muted); }
.slot--off .slot__left { color: #b32b17; font-weight: 700; }
.dish--out .dish__photo { filter: grayscale(1); opacity: 0.6; }
.dish--out .dish__name, .dish--out .dish__price { color: var(--muted); }

/* Summary cards that open a detail page. The whole card is the link target;
   inner links and buttons sit above the stretched ::after. */
a.metric { display: block; color: inherit; }
.metric--link, .panel--link { position: relative; transition: border-color 0.15s; }
.metric--link:hover, .panel--link:hover { border-color: var(--orange); }
.card-link { color: inherit; }
.card-link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.panel--link .panel__foot a, .panel--link .btn, .panel--link select { position: relative; z-index: 1; }
.metric__go { margin-left: auto; width: 0.875rem; height: 0.875rem; color: var(--muted-light); }

.panel__title-icon { width: 1.125rem; height: 1.125rem; margin-right: 0.3125rem; vertical-align: -0.2em; }

/* Compact permit/status line under the page title. */
.page-head__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 0.625rem; font-size: var(--text-xs); }
.page-head__meta-link { color: var(--ink-soft); font-weight: 600; }
/* Order detail: the customer rides in the page head, so the rail keeps to the order itself. */
.page-head__lead { display: flex; align-items: center; gap: 0.875rem; }

/* Deep links from the dashboard land on (and highlight) that exact row or request. */
tr:target td, .req:target { background: var(--sand); }
a.week__day { color: inherit; }
a.week__day:hover { border-color: var(--orange); }

/* Window details lock (disabled fieldset) once a window has orders — only capacity stays editable. */
fieldset.form { min-width: 0; margin: 0; padding: 0; border: 0; }
fieldset:disabled .input { background: var(--surface); color: var(--muted); cursor: not-allowed; }
.input:disabled { background: var(--surface); color: var(--muted); cursor: not-allowed; }

/* Next window cards — two equal cards, big time, capacity meter. */
.window-card__time { color: var(--ink); font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; }
.window-card__cap { display: flex; justify-content: space-between; gap: var(--space-3); margin: 1rem 0 0.5rem; color: var(--muted); font-size: var(--text-sm); }
.window-card__cap strong { color: var(--ink); }

/* Individual order status: a pill-shaped native select. A 4px transparent top and bottom
   border (unpainted: the background stops at the padding box) gives it a 33px tap area,
   and the negative margin keeps its 25px pill in the layout. */
.status-select {
  margin-block: -0.25rem;
  padding: 0.3125rem calc(1.75rem + 1px) 0.3125rem calc(0.625rem + 1px);
  border: solid transparent;
  border-width: 0.25rem 0;
  border-radius: var(--radius-pill);
  background: #e6eefb url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right calc(0.5rem + 1px) center / 0.75rem;
  background-clip: padding-box;
  color: #2a5798;
  font: 700 var(--text-xs)/1.4 var(--font-sans);
  appearance: none;
  cursor: pointer;
}
.status-select:hover { box-shadow: inset 0 0 0 1px currentColor; }
.status-select:focus-visible { outline-offset: -0.25rem; }
.status-select[data-status="Ready"] { background-color: #e4f4ea; color: #1f7a4d; }
.status-select[data-status="Completed"] { background-color: var(--line); color: var(--muted); }

tr[data-href] { cursor: pointer; }

/* Optional step (Ready) — dashed, so it never reads as required. */
.stepper__item--optional .stepper__mark { border-style: dashed; }

/* Week at a glance — seven day columns, scrolls sideways when narrow. */
.week { display: grid; grid-template-columns: repeat(7, minmax(7.5rem, 1fr)); gap: 0.5rem; }
.week__day { display: grid; align-content: start; gap: 0.375rem; padding: 0.75rem; border: 1px solid var(--stroke); border-radius: var(--radius-sm); background: var(--white); }
.week__day--today { border-color: var(--orange); background: var(--sand); }
/* Their tinted fills (dff3f1/ede7fb) read muddy on the sand card — white
   plate, same text color, keeps pickup/dine-in legible. */
.week__day--today .pill { background: var(--white); }
.week__date { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.week__line { color: var(--muted); font-size: var(--text-xs); }

/* Storefront: prominent Pickup / Dine-in selector. */
.fulfil { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.fulfil__opt { display: flex; align-items: center; gap: 0.75rem; padding: 0.875rem 1rem; border: 2px solid var(--stroke); border-radius: var(--radius-md); background: var(--white); color: inherit; }
.fulfil__opt--on { border-color: var(--orange); background: var(--sand); }
.fulfil__opt:disabled { background: var(--surface); color: var(--muted-light); cursor: not-allowed; }
.fulfil__opt:disabled .fulfil__icon { color: var(--muted-light); }
.fulfil__icon { width: 1.5rem; height: 1.5rem; flex: none; color: var(--orange); }
.fulfil__title { display: block; color: var(--ink); font-size: var(--text-md); font-weight: 700; }
.fulfil__sub { display: block; color: var(--muted); font-size: var(--text-xs); }
.slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: 0.5rem; }
.slots .slot { cursor: pointer; }
.slots .slot--off { cursor: not-allowed; }
.slot:has(input:checked) { border-color: var(--orange); background: var(--sand); }
a.sf-head__meta-item, a.dish__rating { color: var(--muted); }

/* Selected method + time, pinned at the top of the cart. */
.cart-method { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.75rem; border-radius: var(--radius-sm); background: var(--sand); }
.cart-method__when { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }

/* Brief explanations (Verified, policies, availability) — native popover. */
/* A zero-specificity reset (:where), so a component class on the same button keeps its look:
   .verified stays the gradient pill and .panel__link stays orange bold. */
:where(.link-button) { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline dotted; text-underline-offset: 0.2em; cursor: pointer; }
.verified.link-button { text-decoration: none; }
.pop { max-width: min(24rem, calc(100vw - 2rem)); margin: auto; padding: var(--space-5); border: 1px solid var(--stroke); border-radius: var(--radius-lg); background: var(--white); box-shadow: var(--shadow-field); }
.pop::backdrop { background: rgba(23, 18, 14, 0.35); }
.pop__title { color: var(--ink); font-size: var(--text-md); font-weight: 700; }
.pop__body { margin-top: 0.5rem; color: var(--muted); font-size: var(--text-sm); line-height: 1.6; }
.pop--form { width: min(30rem, calc(100vw - 2rem)); max-width: none; }

/* Storefront reviews: heading row with Write a review; "Read all" reveals the rest (summary hides once open). */
.sf-section__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.reviews-more > summary { list-style: none; cursor: pointer; }
.reviews-more > summary::-webkit-details-marker { display: none; }
.reviews-more[open] > summary { display: none; }

/* Star picker: radios + labels; checked star and those before it are lit, hover previews. */
.rate { display: flex; flex-wrap: wrap; align-items: center; gap: 0.125rem; margin: 0; padding: 0; border: 0; }
.rate > legend { width: 100%; margin-bottom: 0.5rem; padding: 0; }
.rate > label { color: var(--line); cursor: pointer; border-radius: 0.25rem; }
.rate > label svg { display: block; width: 1.75rem; height: 1.75rem; }
.rate:has(input:checked) > label { color: var(--orange); }
.rate > input:checked + label ~ label { color: var(--line); }
.rate.rate:hover > label { color: var(--orange); }
.rate.rate > label:hover ~ label { color: var(--line); }
.rate > input:focus-visible + label { outline: 2px solid var(--orange); outline-offset: 2px; }

/* Storefront state previews. */
.state-card__label { color: var(--muted); font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }

/* Storefront, stacked (phone + tablet): compact head pinned under the header once
   the card scrolls away, and an order summary pinned to the bottom. app.js toggles
   --on/--off; both are display:none on desktop, where the cart sits in the sidebar. */
.sf-mini,
.sf-orderbar { display: none; }

/* Demo role-switch notch (role-switch.js) docks bottom on phones and touch tablets: sit it on top of the bar. */
@media (width < 834px), (max-width: 1366px) and (pointer: coarse) { /* same touch cap as role-switch.js */
  .page-app:has(.sf-orderbar:not(.sf-orderbar--off)) .side-notch { bottom: 4.5rem; }
  /* Licensing accordion: over the pinned step foot (pill + Back/Continue, 101px). */
  @media (width < 73.75rem) { body:has(.wizard--accordion:not(.wizard--shut)) .side-notch { bottom: 6.3125rem; } }
}

/* ---------- Search results: whole card opens the Hearth ----------
   The name link stretches over the card; the invisible ::after carries no content,
   so nothing is lost on Figma import. */
.sf-body--filters .meal-card__title a::after { content: ""; position: absolute; inset: 0; }
.sf-body--filters .meal-card:hover { border-color: var(--orange); }
.sf-body--filters .toggle[role="switch"]:focus-visible { outline: 2px solid var(--orange); outline-offset: 3px; border-radius: 62.5rem; }

/* ---------- Search banner (shop-search) ----------
   The What's cooking hero, shorter, with an even scrim so the centred search bar reads. */
.hiw-hero.search-hero {
  min-height: 0;
  padding-block: var(--space-7);
  background-image: linear-gradient(rgba(11, 10, 9, 0.7), rgba(11, 10, 9, 0.7)), url("assets/whats-cooking-hero.jpg");
  background-position: center;
  text-align: center;
}
.search-hero .hiw-hero__content { margin-inline: auto; }
.search-hero .zip-search { margin-inline: auto; }
.search-hero .hero__trust { justify-content: center; }

/* ---------- Search filters (shop-search) ----------
   A <details> panel: always open beside the results, collapsed above them
   once the layout stacks (≤ 75rem). Options carry live counts; what is switched on
   is repeated as removable chips above the results. */
.sf-filters { display: block; align-self: start; }
.sf-filters__head { display: flex; width: 100%; margin: 0; justify-content: space-between; text-align: left; cursor: pointer; list-style: none; }
.sf-filters__head::-webkit-details-marker { display: none; }
.sf-filters:not([open]) .sf-filters__head { border-bottom: 0; }
.sf-filters__title { display: inline-flex; align-items: center; gap: 0.5rem; }
.sf-filters__icon { width: 1.125rem; height: 1.125rem; flex: none; color: var(--orange); }
.sf-filters__chevron { width: 1.125rem; height: 1.125rem; flex: none; color: var(--muted); }
.sf-filters[open] .sf-filters__chevron { transform: rotate(180deg); }

.sf-filters__body { display: grid; }
.sf-filters__group { display: grid; gap: 0.75rem; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--stroke); }
.sf-filters__group .switch-row { padding: 0; border: 0; }
.sf-filters__legend-row { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.sf-filters__value { color: var(--orange); font-size: var(--text-sm); font-weight: 700; }

/* the distance readout is typeable — the customer can enter a radius past the slider's reach */
.sf-filters__value-input {
  width: 3.25rem;
  padding: 0.0625rem 0.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: inherit;
  font: inherit;
  text-align: center;
}

.sf-filters__value-input:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 1px;
}

.sf-filters__count {
  min-width: 1.5rem;
  padding: 0.0625rem 0.4375rem;
  border-radius: var(--radius-pill);
  background: var(--sand);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  text-align: center;
}
.sf-filters__opt--none { opacity: 0.5; }

/* Pickup / Dine-in tiles */
.sf-filters__tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem; }
.sf-filters__tile {
  position: relative;
  display: grid;
  align-content: start;
  justify-items: start;
  gap: 0.125rem;
  padding: 0.625rem 0.75rem;
  border: 1.5px solid var(--stroke);
  border-radius: var(--radius-md);
  background: var(--white);
  cursor: pointer;
}
.sf-filters__tile:has(input:checked) { border-color: var(--orange); background: var(--sand); }
.sf-filters__tile-icon { width: 1.25rem; height: 1.25rem; margin-bottom: 0.25rem; color: var(--orange); }
.sf-filters__tile-title { color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.sf-filters__tile-sub { color: var(--muted); font-size: var(--text-xs); line-height: 1.3; }
.sf-filters__tile .sf-filters__count { position: absolute; top: 0.5rem; right: 0.5rem; }

/* Earliest available — segmented control */
.sf-filters__seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.125rem; padding: 0.1875rem; border-radius: var(--radius-pill); background: var(--sand); }
.sf-filters__seg-opt {
  position: relative;
  display: grid;
  place-items: center;
  padding: 0.4375rem 0.25rem;
  border-radius: var(--radius-pill);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
}
.sf-filters__seg-opt:has(input:checked) { background: var(--white); color: var(--ink); box-shadow: var(--shadow-card); }
.sf-filters__tile:has(input:focus-visible),
.sf-filters__seg-opt:has(input:focus-visible) { outline: 2px solid var(--orange); outline-offset: 2px; }

/* Distance slider */
.sf-filters__range { width: 100%; margin: 0; accent-color: var(--orange); cursor: pointer; }
.sf-filters__marks { display: flex; justify-content: space-between; margin-top: -0.375rem; color: var(--muted); font-size: var(--text-xs); }

/* Cuisine checklist */
.sf-filters__checks { display: grid; }
.sf-filters__check { display: flex; align-items: center; gap: 0.625rem; margin-inline: -0.5rem; padding: 0.4375rem 0.5rem; border-radius: var(--radius-sm); cursor: pointer; }
.sf-filters__check:hover { background: var(--sand); }
.sf-filters__check .consent__box { margin: 0; }
.sf-filters__check-label { flex: 1; color: var(--ink); font-size: var(--text-sm); }

.sf-filters__foot { display: none; padding: var(--space-4) var(--space-5); }

/* Results column: removable active-filter chips over the grid */
.results-col { display: grid; align-content: start; gap: var(--space-4); min-width: 0; }
.active-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.active-filters__list { display: contents; }
.active-filters__label { color: var(--muted); font-size: var(--text-sm); font-weight: 600; }
.active-filters .chip { cursor: pointer; }

@media (width > 75rem) {
  .sf-filters__head { cursor: default; }
  .sf-filters__chevron { display: none; }
  .sf-filters__group:last-of-type { border-bottom: 0; }
}

/* Search actions: View left, then Sort and — once the layout stacks — an
   icon-only Filters button together on the right that opens the panel as a right-hand
   drawer. The drawer is still the <details>: [open] is the drawer state, the
   summary is its close control, and it rides the side sheet's slide-in. */
.sf-actions { flex-wrap: nowrap; }
.sf-actions .view-switch { margin-top: 0; }
.sf-actions__sort { min-width: 15rem; }
.sf-actions__filters { display: none; flex: none; width: 2.75rem; height: 2.75rem; }
.sf-actions__filters .tab__count { position: absolute; top: -0.375rem; right: -0.375rem; margin: 0; background: var(--orange); color: var(--white); }
.sf-filters__close { display: none; width: 1.25rem; height: 1.25rem; flex: none; color: var(--ink-soft); }

/* Orders: the next pickup or dine-in, above the tables */
.next-up { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); padding: var(--space-4) var(--space-5); }
.next-up__icon { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; flex: none; border-radius: 50%; background: var(--white); color: var(--orange); }
.next-up__svg { width: 1.375rem; height: 1.375rem; }
.next-up__text { flex: 1 1 18rem; min-width: 0; }
.next-up__eyebrow { color: #a8490f; font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.next-up__title { margin-top: 0.125rem; color: var(--ink); font-size: var(--text-md); font-weight: 700; }
.next-up__sub { margin-top: 0.125rem; color: var(--muted); font-size: var(--text-sm); }

/* ---------- Customer account pages (customer-*) ---------- */
/* Short pages: the footer sits at the bottom of the window, not under the content. */
.page-app:has(> .site-footer) { display: flex; flex-direction: column; min-height: 100vh; }
.page-app:has(> .site-footer) > main { flex: 1 0 auto; width: 100%; box-sizing: border-box; }

/* Orders: one panel, Current / Past tabs in its head. */
.orders-head { align-items: flex-end; padding-bottom: 0; }
.orders-head .tabs { flex: 1 1 auto; box-shadow: none; overflow: visible; background: none; }
.orders-head .tab { margin-bottom: -1px; } /* the underline sits on the panel head's rule */

/* Order filters (Orders page only) ride along in the same head as the tabs,
   right-aligned; matching the tab's own padding-bottom keeps its gap to the
   border-bottom even with the tabs' instead of sitting flush against it. */
.orders-head .period__presets { flex: none; margin-bottom: 0.875rem; }

/* Items with a food photo each. */
.order-items { display: grid; gap: 0.5rem; min-width: 11rem; }
/* Photo on the left spanning both rows, name over quantity on the right. */
.order-item { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 0.625rem; }
.order-item__thumb { grid-row: 1 / span 2; width: 2.5rem; height: 2.5rem; border-radius: var(--radius-sm); object-fit: cover; background: var(--sand); }
.order-item__name { color: var(--ink); line-height: 1.3; }
.order-item__qty { color: var(--muted); font-size: var(--text-xs); font-weight: 700; white-space: nowrap; }
.order-items__note { color: var(--muted); font-size: var(--text-xs); }


/* ---------- Storefront and checkout revisions ---------- */
/* Pickup / Dine-in choice: buttons centre text by default; these read left. */
.fulfil__opt { text-align: left; }

/* Order lines carry a food photo. */
.cart-line { align-items: center; }
.cart-line__thumb { width: 2.75rem; height: 2.75rem; flex: none; border-radius: var(--radius-sm); object-fit: cover; background: var(--sand); }

/* Checkout: a way back to the Hearth. */
.checkout-back { display: inline-flex; align-items: center; gap: 0.375rem; margin-bottom: var(--space-3); color: var(--muted); font-size: var(--text-sm); font-weight: 600; }
.checkout-back:hover { color: var(--orange); }
.checkout-back__icon { width: 1rem; height: 1rem; flex: none; }
/* Item name on its own row; the size / note and the qty x unit price sit beside
   each other on the row under it. */
.cart-line__text { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.375rem; }
.cart-line__name { flex: 1 0 100%; }

/* Pickup / Dine-in pills on the sand order-method block: white so they don't merge into it;
   text and icon keep their own colour, with a faint outline in the same hue. */
.cart-method .pill--pickup { background: var(--white); box-shadow: inset 0 0 0 1px rgba(15, 110, 102, 0.28); }
.cart-method .pill--dinein { background: var(--white); box-shadow: inset 0 0 0 1px rgba(91, 63, 168, 0.28); }

/* ---------- Cart (shop-cart) ----------
   One Hearth's items with photos, quantity steppers and Remove; the summary
   repeats checkout's money rows. Steppers and totals are driven by app.js. */
a.cart { text-decoration: none; }
.cart-hearth { display: flex; align-items: center; gap: 0.75rem; min-width: 0; }
.cart-items { display: grid; margin-top: var(--space-4); }
.cart-item { display: grid; grid-template-columns: 5rem minmax(0, 1fr) auto; align-items: center; gap: var(--space-4); padding: var(--space-4) 0; border-bottom: 1px solid var(--stroke); }
.cart-item:last-child { padding-bottom: 0; border-bottom: 0; }
.cart-item__thumb { width: 5rem; height: 5rem; border-radius: var(--radius-md); object-fit: cover; background: var(--sand); }
.cart-item__name { color: var(--ink); font-size: var(--text-md); font-weight: 700; }
.cart-item__meta { margin-top: 0.125rem; color: var(--muted); font-size: var(--text-sm); }
.cart-item__controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem var(--space-4); margin-top: 0.625rem; }
.cart-item__stock { color: #1f7a4d; font-size: var(--text-xs); font-weight: 600; }
.cart-item__stock--low { color: #a8490f; }
.cart-item__remove { color: var(--muted); font-size: var(--text-sm); }
.cart-item__remove:hover { color: var(--orange); }
.cart-item__price { color: var(--ink); font-size: var(--text-md); font-weight: 700; text-align: right; white-space: nowrap; }

.qty { display: inline-flex; align-items: center; padding: 0.125rem; border: 1px solid var(--stroke); border-radius: var(--radius-pill); background: var(--white); }
.qty__btn { display: grid; place-items: center; width: 2rem; height: 2rem; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--ink); cursor: pointer; }
.qty__btn:hover:not(:disabled) { background: var(--sand); color: var(--orange); }
.qty__btn:disabled { color: var(--muted-light); cursor: not-allowed; }
.qty__icon { width: 0.875rem; height: 0.875rem; }
.qty__value { min-width: 1.75rem; color: var(--ink); font-size: var(--text-sm); font-weight: 700; text-align: center; }

/* Response hours hangs off a clock icon beside the dine-in toggle — the
   .period__more dropdown, so outside-click and Escape close it already. */
.switch-row__aside { display: flex; align-items: center; gap: var(--space-3); }
.period__menu--form { min-width: 20rem; padding: var(--space-4); gap: var(--space-3); text-align: left; }
.period__menu--form .switch-row { padding-top: 0; }

/* ---------- 24. Notifications drawer ----------
   The top-bar bell opens the dashboard's "Needs your attention" list as a side
   sheet, so every cook screen reaches it. The head borrows the rail's stacked
   panel head: title and sub left, close button right, filter chips on their own
   row underneath. The list is .req, which brings its own vertical padding. */
.sheet--notify .sheet__head { flex-wrap: wrap; }

.sheet--notify .sheet__head > .period__presets {
  flex: 1 0 100%;
  margin-top: var(--space-3);
  box-shadow: none;
}

/* Five chips fit one row at the 34rem drawer; on a phone they take two. */
.sheet--notify .period__group { flex: 1 1 auto; flex-wrap: wrap; }

.sheet--notify .period__opt {
  display: inline-flex;
  flex: 1 1 auto;
  min-width: 0;
  align-items: center;
  justify-content: center;
  gap: 0.1875rem;
  padding: 0.3125rem 0.25rem;
  font-size: var(--text-xs);
}

.sheet--notify .sheet__body { padding-block: 0; }
.sheet--notify .sheet__foot { justify-content: center; }

/* .req hangs off --space-5 side padding; the phone sheet drops to --space-4,
   which would push the rows past the edge. Keep this one body at --space-5. */
@container sheet (width < 33rem) {
  .sheet--notify .sheet__body { padding-inline: var(--space-5); }
}

/* ---------- 25. Search map view ----------
   Batch D. The results column swaps between the card grid and a map of the same
   Hearths. The switch is a radio pair in the page head and nothing else — :has()
   does the swap, so there is no view state in JS.

   Pins are placed from each card's data-miles and data-bearing, rescaled to the
   distance filter, which is why the dashed ring is a constant 87% of the map
   height: it is always the radius the slider is set to. The plan underneath is
   an illustration, not tiles — the mapping provider is still an open question. */

.view-switch { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 11rem; margin-top: 0.375rem; }
.view-switch .sf-filters__seg-opt { grid-auto-flow: column; gap: 0.375rem; padding-inline: 0.5rem; }
.view-switch svg { width: 0.875rem; height: 0.875rem; }

/* width first: aspect-ratio alone lets a grid item take its width from the
   height cap instead of the column, which leaves the map short of the grid. */
.map { display: none; position: relative; width: 100%; aspect-ratio: 16 / 9; max-height: 40rem; overflow: hidden; border: 1px solid var(--stroke); border-radius: var(--radius-lg); background: var(--sand); }

/* Map view is shorter than a full page of cards; without this the auto rows
   share out the leftover height on a tall screen and drift apart. */
.sf-body--filters { align-content: start; }

.sf-body__head:has([name="view"][value="map"]:checked) ~ .results-col .results { display: none; }
.sf-body__head:has([name="view"][value="map"]:checked) ~ .results-col .map { display: block; }

/* The plan: ground, two parks, the bay in the south-west, a street lattice. */
.map__plan { position: absolute; inset: 0; width: 100%; height: 100%; }
.map__ground { fill: #f6ece1; }
.map__park { fill: #e4f4ea; }
.map__water { fill: #dde8f0; }
.map__roads { fill: none; stroke: var(--white); stroke-width: 2.5; }
.map__roads--minor { stroke-width: 1.25; stroke-opacity: 0.7; }
.map__roads--major { stroke: #f3e2d0; stroke-width: 3.5; }

/* Always the current distance filter — the projection rescales, not the ring. */
.map__ring {
  position: absolute;
  top: 50%;
  left: 50%;
  height: 87%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border: 1px dashed var(--orange);
  border-radius: 50%;
  background: rgba(242, 96, 26, 0.05);
}

/* Anchored on the dot, not the middle of dot-plus-label. */
.map__here { position: absolute; top: 50%; left: 50%; display: flex; align-items: center; gap: 0.375rem; transform: translate(-0.4375rem, -50%); }
.map__here-dot { width: 0.875rem; height: 0.875rem; flex: none; border: 0.1875rem solid var(--white); border-radius: 50%; background: var(--ink); box-shadow: var(--shadow-card); }
.map__here-label { padding: 0.125rem 0.5rem; border-radius: var(--radius-pill); background: var(--ink); color: var(--white); font-size: var(--text-xs); font-weight: 700; }

.map__pin {
  position: absolute;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--orange);
  transform: translate(-50%, -100%);
  transform-origin: 50% 100%;
  cursor: pointer;
  filter: drop-shadow(0 0.125rem 0.1875rem rgba(23, 18, 14, 0.25));
}

.map__pin-svg { width: 100%; height: 100%; fill: currentColor; }
.map__pin-svg circle { fill: var(--white); }
.map__pin:hover { color: var(--orange-light); }
.map__pin:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: var(--radius-sm); }
.map__pin--on { width: 2.25rem; height: 2.25rem; z-index: 2; color: var(--ink); }

.map__note { position: absolute; top: var(--space-4); right: var(--space-4); max-width: 17rem; padding: 0.4375rem 0.75rem; border-radius: var(--radius-pill); background: rgba(255, 255, 255, 0.92); color: var(--muted); font-size: var(--text-xs); line-height: 1.4; }

/* The preview is the result card itself, cloned — laid on its side so it clears
   the map. Whatever the card grows, the popup gets. */
.map__preview { position: absolute; left: var(--space-4); bottom: var(--space-4); z-index: 3; width: min(22rem, calc(100% - 2 * var(--space-4))); }
.map__preview .meal-card { display: grid; grid-template-columns: 6.5rem minmax(0, 1fr); box-shadow: var(--shadow-field); }
.map__preview .meal-card__image { height: 100%; aspect-ratio: auto; }
.map__preview .meal-card__body { padding: 0.625rem 0.75rem 0.75rem; }
.map__preview .rating { top: 0.375rem; left: 0.375rem; }
.map__preview .dish__tags { display: none; }
.map__preview .meal-card__foot { flex-wrap: wrap; gap: 0.375rem; }

.map__preview-close {
  position: absolute;
  top: -0.625rem;
  right: -0.625rem;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  border: 1px solid var(--stroke);
  border-radius: 50%;
  background: var(--white);
  color: var(--muted);
  cursor: pointer;
  box-shadow: var(--shadow-card);
}

.map__preview-x { width: 0.75rem; height: 0.75rem; }
.map__empty { position: absolute; top: 50%; left: 50%; z-index: 4; width: min(24rem, calc(100% - 2 * var(--space-5))); padding: var(--space-5); border-radius: var(--radius-lg); background: var(--white); transform: translate(-50%, -50%); box-shadow: var(--shadow-field); }

/* Top-bar account menu: avatar opens Settings / Billing / Log out. Rides on
   .period__more, so outside-click and Escape already close it. */
.account__trigger { cursor: pointer; border-radius: 50%; }
.account__trigger:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.account__menu { min-width: 12rem; }
.account__item { justify-content: flex-start; gap: 0.625rem; text-decoration: none; }
.account__icon { width: 1.125rem; height: 1.125rem; flex: none; color: var(--ink-soft); }
.account__item--out { margin-top: 0.25rem; border-top: 1px solid var(--stroke); border-radius: 0 0 var(--radius-sm) var(--radius-sm); color: #b32b17; }
.account__item--out .account__icon { color: currentColor; }

/* Billing (cook-settings-billing, customer-account #billing): saved cards + add-card form. */
.billing__group { display: grid; gap: var(--space-3); }
.billing__group + .billing__group { padding-top: var(--space-5); border-top: 1px solid var(--stroke); }
.billing__title { margin: 0; font: 700 var(--text-md)/1.3 var(--font-sans); color: var(--ink); }
.paycards { display: grid; gap: var(--space-2); }
.paycard { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border: 1px solid var(--stroke); border-radius: var(--radius-md); background: var(--white); }
.paycard__brand { display: inline-flex; align-items: center; justify-content: center; width: 3rem; height: 2rem; flex: none; border-radius: var(--radius-sm); color: var(--white); font: 800 0.6875rem/1 var(--font-sans); letter-spacing: 0.04em; }
.paycard__brand--visa { background: #1a1f71; }
.paycard__brand--mastercard { background: #eb001b; }
.paycard__text { flex: 1; min-width: 0; }
.paycard__name { margin: 0; font-weight: 700; color: var(--ink); }
.paycard__meta { margin: 0; font-size: var(--text-sm); color: var(--ink-soft); }

/* Checkout on phones: one step at a time (shop-checkout). A radio per step in
   .co-steps; :has() shows only the blocks whose data-step matches the checked
   one. Step 4 reads Your order, then Before you order, then Pay. */
.co-steps, .co-nav { display: none; }

@media (width < 834px) {
  .co-flow { display: contents; }
  .sf-body:has(.co-flow) { gap: 0; align-content: start; }
  .sf-body:has(#co-step-1:checked) [data-step]:not([data-step="1"]),
  .sf-body:has(#co-step-2:checked) [data-step]:not([data-step="2"]),
  .sf-body:has(#co-step-3:checked) [data-step]:not([data-step="3"]),
  .sf-body:has(#co-step-4:checked) [data-step]:not([data-step="4"]) { display: none; }

  .co-steps {
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.25rem;
    margin-bottom: var(--space-5);
  }
  .co-steps .stepper__item { flex-direction: column; gap: 0.375rem; padding: 0.5rem 0.25rem; font-size: var(--text-xs); text-align: center; cursor: pointer; }
  .co-steps :checked + .stepper__item { background: var(--sand); color: var(--ink); }
  .co-steps :checked + .stepper__item .stepper__mark { background: var(--orange); border-color: var(--orange); color: var(--white); }
  .co-steps .stepper__item:has(~ :checked) .stepper__mark { background: #e4f4ea; border-color: #bfe3cd; color: #1f7a4d; }
  .co-steps :focus-visible + .stepper__item { outline: 2px solid var(--orange); outline-offset: 2px; }

  .sf-body > .cart-panel { margin-bottom: var(--space-5); }
  .co-flow > .panel[data-step="4"] { order: 2; margin-bottom: var(--space-5); }
  .cart-panel .cart-panel__pay { display: none; } /* the step nav carries Pay on phones */

  .co-nav {
    order: 3;
    position: sticky;
    bottom: 0;
    z-index: 45; /* the same layer and safe-area padding as the storefront/cart order bar */
    display: flex;
    gap: 0.75rem;
    padding: 0.75rem 0 calc(0.75rem + env(safe-area-inset-bottom));
    background: var(--surface);
  }
  .co-nav .btn { flex: 1; cursor: pointer; }
  .co-nav .btn--outline { flex: none; }
}

/* Cart: the same bottom order bar as the storefront (.sf-orderbar, section 23):
   one threshold, layer, safe-area padding and body offset, hidden while the
   Order summary it repeats is on screen (app.js). */

/* Tables whose last column is actions: it stays pinned while the rest scrolls
   sideways. With --icon-actions (buttons that carry an icon and a title), the
   buttons also drop to icons on tablet and below; the label stays for screen
   readers and the title gives the tooltip. */
.table--sticky-actions:not(.table--cards) th:last-child,
.table--sticky-actions:not(.table--cards) td:last-child { position: sticky; right: 0; z-index: 1; box-shadow: inset 1px 0 0 var(--stroke); }
.table--sticky-actions:not(.table--cards) td:last-child { background: var(--white); }
.table--sticky-actions:not(.table--cards) tbody tr:hover td:last-child { background: var(--cream); }

/* Cards: a table that would scroll sideways shows each row as a card instead
   (app.js adds .table--cards while the table is wider than its wrap). The first
   cell is the card's title, each other cell shows its column name (.table__label),
   and the Actions cell runs along the bottom. The header row goes, so its sort
   buttons are not invisible tab stops. */
.table.table--cards,
.table--cards tbody,
.table--cards tfoot { display: grid; gap: 0.75rem; }
.panel--flush .table--cards { padding: var(--space-4) var(--space-5); }
.table--cards thead { display: none; }
.table--cards tr {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
  gap: 0.875rem 0.75rem;
  padding: var(--space-4);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-md);
  background: var(--white);
}
.table--cards tr:has(.input) { grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); } /* inputs hold whole values ("7:00 – 9:00 PM (dine-in)") */
.table--cards tfoot tr { background: var(--cream); }
.table.table--cards td { min-width: 0; padding: 0; border: 0; white-space: normal; overflow-wrap: break-word; text-align: left; }
.table--cards td:first-child,
.table--cards .table__wrap-cell,
.table--sticky-actions.table--cards td:last-child { grid-column: 1 / -1; }
.table--sticky-actions.table--cards td:last-child { padding-top: 0.875rem; border-top: 1px solid var(--stroke); }
.table--cards td:empty { display: none; }
.table--cards td .pill { white-space: normal; }
.table--cards .table__label {
  display: block;
  margin-bottom: 0.25rem;
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Order cards: dashboard Today's orders, the Orders page and the customer's Your orders (.table--orders; always cards
   at 800px and below, data-cards). Avatar, name and "#order | time" with the method on the
   right, the Orders page's items under them; under a rule, Total paid and the status. The
   cells' parts become the card's own grid items. Columns: Customer, then Method + Time
   (dashboard) or Method and time + Items (Orders), then Status, Total paid. */
.table--orders.table--cards tr {
  grid-template-columns: [a] auto [b] auto [c] minmax(0, 1fr) [mid] minmax(0, 1fr) [d] auto [end];
  gap: 0;
  align-items: center;
}
.table--orders.table--cards td:first-child,
.table--orders.table--cards td:first-child .table__person,
.table--orders.table--cards td:first-child .table__person-text,
.table--orders.table--cards td:nth-child(2):has(> .table__person-text),
.table--orders.table--cards td:nth-child(2) > .table__person-text { display: contents; }
.table--orders.table--cards .avatar { grid-area: 1 / a / 3 / b; width: 2.5rem; height: 2.5rem; margin-right: 0.75rem; }
.table--orders.table--cards .table__person .table__strong,
.table--orders.table--cards td:first-child > .table__person-text > :first-child { grid-area: 1 / b / 2 / d; font-size: var(--text-md); } /* customer orders: Hearth name, no avatar */
.table--orders.table--cards td:first-child .table__person-sub { grid-area: 2 / b / 3 / c; align-self: start; margin-top: 0.125rem; font-size: var(--text-sm); font-weight: 400; }
/* Method: its own cell (dashboard) or the pill of the shared cell (Orders). */
.table--orders.table--cards td:nth-child(2),
.table--orders.table--cards td:nth-child(2) > .table__person-text > :first-child { grid-area: 1 / d / 2 / end; margin-left: 0.75rem; }
/* Time: its own cell (dashboard) or the line under the pill (Orders). */
.table--orders.table--cards td:nth-child(3):not(.table__wrap-cell),
.table--orders.table--cards td:nth-child(2) .table__person-sub { grid-area: 2 / c / 3 / end; align-self: start; margin: 0.125rem 0 0 0.625rem; padding-left: 0.625rem; border-left: 1px solid var(--stroke); color: var(--muted); font-size: var(--text-sm); font-weight: 400; }
.table--orders.table--cards td.table__wrap-cell { grid-area: 3 / b / 4 / end; margin-top: 0.625rem; } /* Orders: items and notes */
.table--orders.table--cards tr::before { content: ""; grid-area: 4 / a / 5 / end; margin: 0.875rem 0; border-top: 1px solid var(--stroke); } /* the rule above Total paid */
.table--orders.table--cards td:nth-child(4) { grid-area: 5 / mid / 6 / end; display: flex; align-items: center; justify-content: flex-end; }
.table--orders.table--cards td:nth-child(5) { grid-area: 5 / a / 6 / mid; display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.5rem; }
/* A flag beside a control (Pending acceptance + Respond, Paid + Cancellation requested):
   the control stays right of Total paid, the flag goes under it on the left. */
.table--orders.table--cards td:nth-child(4):has(> .btn-row > :is(select, .btn)),
.table--orders.table--cards td:nth-child(4) > .btn-row:has(> :is(select, .btn)) { display: contents; }
.table--orders.table--cards td:nth-child(4) > .btn-row > :is(select, .btn) { grid-area: 5 / mid / 6 / end; justify-self: end; }
.table--orders.table--cards td:nth-child(4) > .btn-row:has(> :is(select, .btn)) > .pill { grid-area: 6 / a / 7 / end; justify-self: start; margin-top: 0.625rem; }
.table--orders.table--cards td:nth-child(-n+4) .table__label { display: none; }
.table--orders.table--cards td:nth-child(5) .table__label { margin: 0; font-size: var(--text-sm); font-weight: 400; letter-spacing: 0; text-transform: none; }
.table--orders.table--cards td:nth-child(4) .status-select { width: 100%; max-width: 14rem; }
.table--orders.table--cards td:nth-child(4) .btn-row { justify-content: flex-end; }
/* Customer orders: the amount stays beside Total paid, its note ("Authorized, not charged")
   under both; the actions run along the bottom under their own rule. */
.table--orders.table--cards td:nth-child(5) > .table__person-text { display: contents; }
.table--orders.table--cards td:nth-child(5) .table__person-sub { flex-basis: 100%; }
.table--orders.table--sticky-actions.table--cards td:last-child { margin-top: 0.875rem; }

/* Window cards: Availability's pickup windows and dine-in dates (.table--windows; always
   cards at 800px and below, data-cards). Day or date with the availability pill on the
   right; "time | Orders close …"; Capacity or Seats, Taken, Left; dine-in's waiting
   requests; the pill's note; then the actions. A wrapping flex row rather than a grid,
   so a long pill ("Closed to new reservations") only narrows the title beside it;
   ::before and ::after are the two line breaks. Columns: Day, Time, Close, Capacity,
   Taken, Left, (Waiting,) Availability, Actions. */
.table--windows.table--cards tr { display: flex; flex-wrap: wrap; align-items: center; gap: 0; }
.table--windows.table--cards tr::before,
.table--windows.table--cards tr::after { content: ""; flex-basis: 100%; order: 2; }
.table--windows.table--cards tr::after { order: 4; }
.table--windows.table--cards td:first-child { order: 1; flex: 1 1 0; min-width: 50%; font-size: var(--text-md); }
.table--windows.table--cards td:nth-last-child(2),
.table--windows.table--cards td:nth-last-child(2) > .table__person-text { display: contents; }
.table--windows.table--cards td:nth-last-child(2) > .pill,
.table--windows.table--cards td:nth-last-child(2) > .table__person-text > :first-child { order: 1; max-width: calc(50% - 0.8125rem); margin-left: 0.75rem; } /* title and pill share the line, each wraps within its half */
.table--windows.table--cards td:nth-child(2) { order: 3; flex: none; margin-top: 0.125rem; color: var(--muted); }
.table--windows.table--cards td:nth-child(3) { order: 3; flex: 1 1 0; margin: 0.125rem 0 0 0.625rem; padding-left: 0.625rem; border-left: 1px solid var(--stroke); }
.table--windows.table--cards td:nth-child(n+4):nth-child(-n+6) { order: 5; flex: none; align-self: flex-start; margin: 0.875rem 1.5rem 0 0; }
.table--windows.table--cards td:nth-child(7):nth-last-child(3) { order: 6; flex-basis: 100%; margin-top: 0.75rem; } /* dine-in: waiting requests */
.table--windows.table--cards td:nth-last-child(2) .table__person-sub { order: 7; flex-basis: 100%; margin-top: 0.625rem; }
.table--windows.table--cards td:last-child { order: 8; flex-basis: 100%; margin-top: 0.875rem; }
.table--windows.table--cards td:nth-child(3),
.table--windows.table--cards td:nth-child(7):nth-last-child(3) { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.375rem; }
.table--windows.table--cards td:nth-child(2) .table__label,
.table--windows.table--cards td:nth-last-child(2) .table__label { display: none; }
.table--windows.table--cards td:nth-child(3) .table__label,
.table--windows.table--cards td:nth-child(7):nth-last-child(3) .table__label { margin: 0; font-size: var(--text-sm); font-weight: 400; letter-spacing: 0; text-transform: none; }

/* Card actions, every table: at the right of the card, wrapping (on phones they share the
   row, see the 40rem block), with the table's own button styles and order. */
.table--sticky-actions.table--cards td:last-child:not(:empty) { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem; }
.table--sticky-actions.table--cards td:last-child > .btn-row { display: contents; }
@media (max-width: 75rem) and (orientation: portrait) {
  .app-body__inner--fill:has(.settings--account) { min-height: 0; }
}

/* Filters drawer (phones and tablet portrait). The page's own filter bars move in here (app.js),
   so the head keeps just a Filters button; desktop never shows either. */
.filters-open { display: none; }
.filters__group + .filters__group { margin-top: var(--space-5); }
.filters__label { margin-bottom: 0.5rem; color: var(--ink); font-size: var(--text-sm); font-weight: 700; }
.filters__slot { display: grid; gap: 0.5rem; }
/* In the drawer each option is its own chip; there is room to wrap. */
.sheet--filters .period__presets,
.sheet--filters .period__group { flex-wrap: wrap; gap: 0.375rem; padding: 0; background: none; border: 0; box-shadow: none; }
.sheet--filters .period__group + .period__group { margin: 0; padding: 0; border: 0; }
.sheet--filters .period__opt { border: 1px solid var(--stroke); background: var(--white); }
.sheet--filters .period__opt--on { border-color: transparent; background: var(--sand); }
.sheet--filters .period__menu { right: auto; left: 0; }
.sheet--filters .period__range { box-shadow: none; }
.sheet--filters .period__date { flex: 1 1 0; min-width: 0; width: auto; }
.sheet--filters .sheet__foot .btn { flex: 1 1 auto; }

/* Admin dashboard reporting range: two dates and Apply in the page head. In the
   Filters drawer the dates share a row and the drawer's Show results applies. */
.date-range { display: grid; grid-template-columns: repeat(2, minmax(0, 11rem)) auto; align-items: end; gap: 0.75rem; width: 100%; }
.date-range .field { min-width: 0; }
.date-range .input { width: 100%; min-width: 0; } /* a date input may shrink below its ~170px default instead of overlapping the next field */
.sheet--filters .date-range { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sheet--filters .date-range__apply { display: none; }
.year-filter { min-width: 8rem; } /* admin-complaints: the Calendar year select, which moves into the Filters drawer with the other filters */

@media (max-width: 40rem), (max-width: 75rem) and (orientation: portrait) {
  .filters-open { display: inline-flex; flex: none; }
  .page-head:has(> .filters-open) { flex-wrap: wrap; align-items: center; }
  .page-head:has(> .filters-open) > .page-head__text { flex: 1 1 0; min-width: 0; }
  /* Export sits left of Filters as an icon (label kept for screen readers, title for the tooltip). */
  .page-head__actions:has(> .page-head__export:only-child) { width: auto; }
  .page-head:has(> .page-head__actions > .page-head__export:only-child) > .filters-open { order: 1; }
  .page-head__export { position: relative; width: 2.0625rem; padding: 0; } /* square, as tall as the Filters button beside it; holds its hidden label */
  .page-head__export .btn__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .panel__head:has(> .filters-open) > :first-child { flex: 1 1 0; min-width: 0; }
}

/* A long pill wraps only when it is wider than its whole container, at every
   width; in a row it keeps its width and the text beside it wraps first
   (flex-shrink: 0). Table cells keep one line, since those tables scroll sideways. */
.pill { max-width: 100%; white-space: normal; flex-shrink: 0; }
td .pill { white-space: nowrap; }

/* Storefront preview head (cook-storefront-editor). Under 1150px the status pill
   joins the title and the three actions fold into a ⋯ menu. */
.panel__title-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.preview-status,
.preview-more { display: none; }
@media (width < 71.875rem) {
  .preview-status { display: inline-flex; }
  .preview-more { display: block; flex: none; }
  .preview-more > summary { list-style: none; cursor: pointer; }
  .preview-more > summary::-webkit-details-marker { display: none; }
  .panel__head:has(> .preview-more) { flex-wrap: nowrap; }
  .panel__head:has(> .preview-more) > .page-head__actions { display: none; }
}

/* Foldable panel (cook-orders "This week at a glance"). On tablet and phone the
   head is a toggle and the panel starts folded; desktop always shows the body. */
.panel__fold { display: none; }
@media (max-width: 60rem), (max-width: 75rem) and (orientation: portrait) {
  .panel--fold > .panel__head { cursor: pointer; }
  .panel--fold > .panel__head > :first-child { flex: 1 1 0; min-width: 0; }
  .panel__fold { display: inline-flex; flex: none; }
  .panel--fold:not(.panel--folded) .panel__fold .icon-button__icon { transform: rotate(180deg); }
  .panel--folded > .panel__head { border-bottom: 0; }
  .panel--folded > .panel__body { display: none; }
}

/* Sheets lay out by their own width: a full 34rem sheet looks the same whether the
   window is 545px or 1440px wide, so the window's phone rules are undone inside it.
   Rows stack only once the sheet itself is narrower (a phone, where it is full width).
   Filter forms go two across in the drawer (three selects would be 154px each). */
@container sheet (width >= 33rem) {
  .sheet .grid--2, .sheet .field-row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sheet .field-row--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sheet .switch-row { flex-direction: row; align-items: flex-start; gap: var(--space-4); }
  .sheet--filters .field-row--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sheet--filters .field-row--3 > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* Storefront: anchors (Reviews, Policies, Your order) land below the pinned compact
   head too: header + compact head on phones, the compact head alone up to 1200px. */
@media (width < 834px) { html:has(.sf-mini) { scroll-padding-top: 7.9375rem; } }
@media (width >= 834px) and (max-width: 75rem) { html:has(.sf-mini) { scroll-padding-top: 3.875rem; } }

/* Standalone text-link actions in the app get the same ~31px tap area without moving anything:
   an invisible layer extends the clickable box 7px above and below (.card-link already
   stretches over its whole card). */
:is(.panel__link, .link-button, .checkout-back, .cart-item__remove) { position: relative; }
:is(.panel__link, .link-button, .checkout-back, .cart-item__remove)::after { content: ""; position: absolute; inset: -0.4375rem 0; }

/* Small standalone controls reach a 32px+ tap area. The phone-only icon Flag and the
   segmented options grow invisibly and the Edit-style panel links also widen. */
.review-flag::after { content: ""; position: absolute; inset: -0.625rem; }
.panel__link::after { inset: -0.4375rem -0.375rem; }
.sf-filters__seg-opt::after { content: ""; position: absolute; inset: -0.1875rem 0; }

/* ---------- Breakpoints ----------
   Two capture widths matter for the Figma import: 1440 (desktop) and 390
   (mobile). Everything between must hold up, because the client will resize.
   Every plain max-width rule, one block per width, widest first, in the order the
   components appear above, then reduced motion. Queries that combine conditions
   (orientation, pointer, width ranges) and container queries stay beside their components. */

/* 1200px and below (tablet landscape, small laptops) */
@media (max-width: 75rem) {
  /* Laptop — the two-column reading layouts give up their second column first. */
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Three-up grids step to two before one; an odd last card takes the full row. */
  .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--3 > :last-child:nth-child(odd) { grid-column: 1 / -1; }
  .sf-body { grid-template-columns: minmax(0, 1fr); }
  .cart-panel { position: static; }
  /* Stacked storefront: Your order lands after the menu, before Reviews. */
  .sf-content { display: contents; }
  .sf-body > .cart-panel { order: 1; }
  .sf-content > .sf-section--reviews,
  .sf-content > .sf-section--reviews ~ .sf-section { order: 2; }
  .sf-content > .sf-section + .sf-section { margin-top: 0; }

  .app-body--rail {
    display: grid;
    gap: var(--space-5);
    align-content: start;
    grid-template-columns: minmax(0, 1fr);
  }

  .wizard > aside.panel { position: static; max-height: none; overflow: visible; }
  .wizard { grid-template-columns: minmax(0, 1fr); }
  /* The licensing step list (nav) goes 2-up; status lists and numbered steps (div) stay one column. */
  .wizard nav.stepper { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .settings { grid-template-columns: minmax(0, 1fr); }
  .settings__nav { padding: var(--space-3) var(--space-4); border-right: 0; border-bottom: 1px solid var(--stroke); }
  .settings__nav .stepper { display: flex; overflow-x: auto; scrollbar-width: none; }
  .settings__nav .stepper::-webkit-scrollbar { display: none; }
  .settings__nav .stepper__item { flex: none; white-space: nowrap; }
  .panel--fill .settings { grid-template-rows: auto minmax(0, 1fr); }

  .verified__more { display: none; } /* "Verified", not "Verified by Hearthfare" */

  .sf-mini--on {
    position: fixed;
    left: 0;
    right: 0;
    z-index: 45; /* under the sticky site header (50) */
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem var(--gutter);
    background: var(--white);
    border-bottom: 1px solid var(--stroke);
    box-shadow: var(--shadow-field);
  }
  .sf-mini__logo { width: 2.25rem; height: 2.25rem; flex: none; object-fit: cover; border-radius: var(--radius-sm); }
  .sf-mini__text { flex: 1 1 auto; min-width: 0; }
  .sf-mini__name { display: block; color: var(--ink); font-size: var(--text-md); font-weight: 700; line-height: 1.2; }
  .sf-mini__meta { display: flex; align-items: center; gap: 0.25rem; color: var(--muted); font-size: var(--text-xs); white-space: nowrap; }

  .sf-orderbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 45;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    box-sizing: border-box;
    min-height: 4.5rem;
    padding: 0.75rem var(--gutter) calc(0.75rem + env(safe-area-inset-bottom));
    background: var(--white);
    border-top: 1px solid var(--stroke);
    box-shadow: 0 -0.5rem 1.5rem rgba(23, 18, 14, 0.1);
  }
  .sf-orderbar--off { display: none; }
  .sf-orderbar__sum { display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; color: inherit; text-decoration: none; }
  .sf-orderbar__count { color: var(--muted); font-size: var(--text-xs); }
  .sf-orderbar__total { color: var(--ink); font-size: var(--text-md); font-weight: 700; }
  .page-app:has(.sf-orderbar) { padding-bottom: 4.5rem; } /* footer clears the bar */

  .sf-filters__foot { display: block; }

  .sf-actions { width: 100%; }
  .sf-actions__sort { flex: 0 1 15rem; min-width: 0; margin-left: auto; } /* Sort sits with the Filters button */
  .sf-actions__filters { display: inline-flex; }

  .sf-filters:not([open]) { display: none; }
  .sf-filters[open] {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    width: min(26rem, 100%);
    align-self: stretch; /* the sidebar's align-self: start would shrink it to its content, past the bottom edge */
    overflow-y: auto;
    border-width: 0 0 0 1px;
    border-radius: 0;
    box-shadow: 0 0 0 100vmax rgba(23, 18, 14, 0.45); /* the scrim */
    animation: sheet-in 0.22s ease-out;
  }
  /* Catches clicks on the scrim so they don't reach the page under it; app.js closes on them. */
  .sf-filters[open]::before { content: ""; position: fixed; inset: 0; z-index: -1; }
  .sf-filters__head { position: sticky; top: 0; z-index: 1; background: var(--white); }
  .sf-filters__chevron { display: none; }
  .sf-filters__close { display: block; }
  .sf-filters__foot { position: sticky; bottom: 0; background: var(--white); border-top: 1px solid var(--stroke); }
  body:has(.sf-filters[open]) { overflow: hidden; }

  /* Phone: a squarer map (place() measures the box, so the pins follow), and the
     preview spans the full width at the bottom with the note out of its way. */
  .map { aspect-ratio: 4 / 3; }

  /* Account settings (customer-account.html, cook-settings*.html) — phone and tablet.
     Tabs span the panel below 1200px; on phones they wrap into chips instead of
     a vertical list. In portrait the panel no longer fills the body, so the save
     bar follows the form instead of floating a screen below it. */
  .settings--account .settings__nav .stepper__item { flex: 1 0 auto; justify-content: center; }

  /* Choice grids share one set of steps (licensing steps 1, 5 and 6): 3 across above 1200px,
     2 across below; cards go to one column on phones, short checkbox labels stay 2-up. */
   .consents--grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 960px and below: the sidebar becomes a drawer */
@media (max-width: 60rem) {
  /* Tablet and below — the sidebar becomes a drawer behind a hamburger.
     The top bar reads: hamburger + wordmark on the left, actions on the right.
     The drawer is display:none when closed so it does not land off-canvas in
     the Figma import. */
  /* Burger mode: the bar is 65px, the height of the marketing and shop header on phones. */
  .app { grid-template-columns: minmax(0, 1fr); --app-bar-h: 4.0625rem; }

  .app-side {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 40;
    width: min(var(--side-w), 84vw); /* same width as the column, so the links do not re-wrap */
    height: auto;   /* top/bottom pin the drawer; the base 100dvh would not */
    overflow-y: auto;
    box-shadow: var(--shadow-field);
  }

  .app-side--open { display: flex; }
  .app-scrim { display: block; }

  .app-bar__lead { display: flex; }
  .app-bar__context { display: none; }
  .app-bar__actions { margin-left: auto; }

  .app-body { --app-body-pad: var(--space-5); padding: var(--app-body-pad) var(--app-gutter); }
  .app-bar { padding: 0.75rem var(--app-gutter); }
  .sf-body { padding: var(--space-5) var(--gutter) var(--space-7); }

  .app-side__close { display: inline-flex; }

  .app-side--open { animation: drawer-in 0.22s ease-out; }
  .app-scrim { animation: scrim-in 0.22s ease-out; }

  .chat { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .chat__list { border-right: 0; border-bottom: 1px solid var(--stroke); }
  .app-body--chat { display: block; padding: 0; overflow-y: auto; } /* stays edge to edge over the .app-body step above */
  .app-body--chat > .chat { grid-template-rows: none; }

  .app-body--chat:has(> .chat--split) { display: flex; overflow: hidden; }
  .app-body--chat > .chat--split { grid-template-rows: minmax(0, 1fr); }
  .chat--split .chat__list { border-bottom: 0; }
  .chat--split:not(.chat--open) .chat__main,
  .chat--split.chat--open .chat__list { display: none; }
  .chat--split .chat__main > .chat__head { justify-content: flex-start; }
  .chat--split .chat__back { display: inline-flex; flex: none; }

  .table--icon-actions:not(.table--cards) td:last-child .btn-row { flex-wrap: nowrap; gap: 0.375rem; }
  .table--icon-actions:not(.table--cards) td:last-child .btn { width: 2.0625rem; padding: 0; } /* square, the height of a small button */
  .table--icon-actions:not(.table--cards) td:last-child .btn__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* 640px and below: phones */
@media (max-width: 40rem) {
  /* Phone. */
  .grid { gap: var(--space-4); }
  /* Every multi-column grid and form row goes to one column at this one step. */
  .grid--2, .grid--3, .grid--4, .grid--5 { grid-template-columns: minmax(0, 1fr); }
  .field-row--2, .field-row--3, .field-row--3-1-1 { grid-template-columns: minmax(0, 1fr); }

  /* Left is hamburger + wordmark, right is bell + avatar. The store-status
     pill would push that past 390. */
  .app-bar__actions .pill { display: none; }
  /* The bar sheds both optional controls (status pill and its button) at this one step. */
  .app-bar__actions .btn { display: none; }

  .page-head { align-items: flex-start; }
  .panel__head { align-items: flex-start; }
  /* A panel's own create action (Add a date, Add pickup window, Add administrator)
     goes full width on its own row, like the page-head actions. */
  .panel__head:has(> .btn--primary) { flex-wrap: wrap; }
  .panel__head > .btn--primary { flex: 1 1 100%; }

  .page-head__title { font-size: 1.375rem; }
  .page-head__actions { width: 100%; }
  .page-head__actions .btn { flex: 1 1 9rem; }
  /* Too narrow for one row: the range wraps under the presets and fills it. */
  .period { min-width: 0; }
  .period__range { flex: 1 1 100%; min-width: 0; }
  .period__date { flex: 1 1 0; min-width: 0; width: auto; }

  .app { --app-gutter: 1.25rem; }
  .app-body { --app-body-pad: var(--space-4); padding: var(--app-body-pad) var(--app-gutter); }
  .panel__head { padding: var(--space-4); }
  .panel__body { padding: var(--space-4); --req-bleed: var(--space-4); }
  /* Variants keep their own spacing over these phone steps. */
  .app-body--chat { padding: 0; }
  .orders-head { align-items: flex-end; padding-bottom: 0; }
  .panel__body--rows { padding-top: 0; padding-bottom: 0; }
  .panel__foot { padding: var(--space-4); }
  .panel--flush .table--cards { padding: var(--space-4); }
  .table--sticky-actions.table--cards td:last-child .btn { flex: 1 1 auto; } /* card actions share the row */
  .metric { padding: var(--space-4); }
  .metric__value { font-size: 1.5rem; }

  .banner { padding: var(--space-4); }
  .banner__actions .btn { flex: 1 1 9rem; }

  .table th,
  .table td { padding: 0.75rem var(--space-4); }

  .switch-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
  }

  .modal__foot { flex-wrap: wrap; }
  .modal__foot .btn { flex: 1 1 9rem; }

  .sf-hero__photo { height: 13rem; }
  .sf-head { margin-top: -2.5rem; }
  /* Head card: photo + name/meta side by side, then badges on a ruled row, then actions. */
  .sf-head__card {
    display: grid;
    grid-template-columns: 4.5rem minmax(0, 1fr);
    grid-template-areas: "logo name" "logo meta" "badges badges" "actions actions";
    align-items: start;
    gap: 0.25rem var(--space-3);
    padding: var(--space-4);
  }
  .sf-head__text { display: contents; }
  .sf-head__logo { grid-area: logo; width: 4.5rem; height: 4.5rem; }
  .sf-head__name { grid-area: name; font-size: 1.25rem; line-height: 1.2; }
  .sf-head__meta { grid-area: meta; flex-direction: column; align-items: flex-start; gap: 0.25rem; margin-top: 0; font-size: var(--text-xs); }
  /* The storefront head card's ruled badge row only: result cards reuse .sf-head__badges. */
  .sf-head__card .sf-head__badges { grid-area: badges; gap: 0.375rem; margin: var(--space-2) 0 0; padding-top: var(--space-3); border-top: 1px solid var(--stroke); }
  .sf-head__actions { grid-area: actions; width: 100%; min-width: 0; margin-top: var(--space-2); grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sf-head__actions .btn__label { white-space: nowrap; }
  .sf-body { gap: var(--space-5); }
  .sf-section__title { font-size: 1.125rem; }
  .sf-section + .sf-section { margin-top: var(--space-5); }

  .dish { flex-direction: column; padding: var(--space-3); }
  .dish__photo { width: 100%; height: 9rem; }
  .dish__top { flex-direction: column; gap: 0.125rem; }
  /* cook-menu ⋯ sits on the photo's top-right corner; the price is under the name, so no clearance. */
  .dish__more { top: calc(var(--space-3) + 0.5rem); right: calc(var(--space-3) + 0.5rem); }
  .dish:has(.dish__more) .dish__top { padding-right: 0; }

  .slot { flex-wrap: wrap; row-gap: 0.125rem; }
  .slot--meter { row-gap: 0.5rem; }

  .req--split { flex-wrap: wrap; }
  .req--split .req__text { flex-basis: calc(100% - 1.6875rem); }
  .req--split .req__side {
    flex-basis: 100%;
    max-width: none;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    padding-left: 1.6875rem;   /* icon + gap, lines up with the text */
  }

  .wizard:not(.wizard--plain) .panel__body { --bleed: var(--space-4); }
  .wizard nav.stepper { grid-template-columns: minmax(0, 1fr); }
  .wizard__foot .btn { flex: 1 1 9rem; }
  .doc { flex-wrap: wrap; }
  .doc__text { flex-basis: calc(100% - 3.25rem); }
  .doc__actions { width: 100%; padding-left: 3.25rem; }
  /* Version rows keep the 3.25rem indent, so they stay under their document's name. */
  .doc--sub .doc__text { flex-basis: 100%; }
  .doc--sub .doc__actions { padding-left: 0; }

  /* "Flag this review" is wide for a top-right control; below 40rem the icon
     carries it alone, with the label kept for screen readers. */
  .review-flag__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

  .thread { padding: 0.875rem var(--space-4); }
  .chat__head { padding: var(--space-4); }
  .chat__tools { padding: 0 var(--space-4) var(--space-4); }
  .chat__body { padding: var(--space-4); }
  .chat__foot { padding: 0 var(--space-4) var(--space-4); }
  .msg { max-width: 100%; }
  .msg__item-price { margin-left: var(--space-3); }
  .sf-cover__photo { height: 13rem; }
  .sf-cover__edit { right: var(--space-3); bottom: var(--space-3); }
  .sf-cover__id { padding: 0 var(--space-4) var(--space-4); }
  .sf-cover__logo { margin-top: -2.25rem; }
  .sf-cover__logo-img { width: 4.5rem; height: 4.5rem; } /* the live storefront head's phone logo */

  .results { gap: var(--space-4); }

  /* Pickup / Dine-in stay side by side: icon over text. */
  .fulfil { gap: var(--space-2); }
  .fulfil__opt { flex-direction: column; align-items: flex-start; gap: 0.375rem; padding: 0.75rem; text-align: left; }
  .fulfil__title { font-size: var(--text-base); }

  .sf-actions .view-switch { width: 9.5rem; }

  /* Price stays in the right-hand column, as on every other page that lists the order. */
  .cart-item { grid-template-columns: 4rem minmax(0, 1fr) auto; align-items: start; gap: var(--space-3); }
  .cart-item__thumb { width: 4rem; height: 4rem; }

  /* Phones: the switch row stacks and its trigger moves to the left edge, so the
     menu opens rightwards from it and never runs past the screen. */
  .switch-row__aside .period__menu { right: auto; left: 0; }
  .period__menu--form { min-width: min(20rem, calc(100vw - 3.75rem)); }

  .map { aspect-ratio: 1; }
  .map__note { top: var(--space-3); right: var(--space-3); left: var(--space-3); max-width: none; text-align: center; }
  .map__preview { left: var(--space-3); right: var(--space-3); bottom: var(--space-3); width: auto; }

   .paycard { flex-wrap: wrap; } .paycard__text { flex-basis: calc(100% - 4rem); }

  .settings--account .settings__nav { padding: var(--space-3); }
  /* One row of chips that scrolls sideways; the cut-off last chip says there is more. */
  .settings--account .settings__nav .stepper { display: flex; flex-wrap: nowrap; gap: 0.375rem; overflow-x: auto; margin: 0 calc(-1 * var(--space-3)); padding: 0 var(--space-3); }
  .settings--account .settings__nav .stepper__item { flex: none; padding: 0.4375rem 0.75rem; border: 1px solid var(--stroke); border-radius: 62.5rem; }
  .settings--account .settings__nav .stepper__item--on { border-color: transparent; }
  /* Address and card rows keep one compact phone layout wherever they appear
     (account pages and checkout): City full, then State | ZIP; Expiry | CVC, then a
     billing ZIP full width. */
  .field-row--address, .field-row--card { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .field-row--address > :first-child,
  .field-row--card > :nth-child(3) { grid-column: 1 / -1; }
  .settings--account .switch-row .btn-row { width: 100%; }
  .settings--account .switch-row .btn-row .toggle { flex: 1 1 0; } /* a toggle pair splits 50/50; a single toggle sits under its text */
  .settings--account .paycard .pill { margin-left: calc(3rem + var(--space-3)); }
  .settings--account .paycard .btn { margin-left: auto; }
  .settings--account .paycard__text + .btn { margin-left: calc(3rem + var(--space-3)); }
  .settings--account .panel__foot .btn { width: 100%; }

  /* Cook dashboard on phones: metric tiles stay 2-up. */
  .grid--3:has(> .metric),
  .grid--4:has(> .metric),
  .grid--5:has(> .metric) { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Storefront editor footer on phones: Discard and Publish each span the panel. */
  .btn-row--stack { width: 100%; flex-direction: column; }
  .btn-row--stack .btn { flex: none; width: 100%; }

  /* Title + chevron on one row, the link under them. */
  .panel--fold > .panel__head > .panel__link { order: 1; flex-basis: 100%; }

  /* Subtitles that wrap past one line at 390px (tagged by measurement) give the screen to the content. */
  .page-head__sub--long { display: none; }

  /* Phones: every card-like surface uses the same 16px side inset as panels, sheets
     and banners (search filter groups, the storefront trust note, modals, popovers,
     empty states and the orders Next up card). Last in the file so it follows their bases. */
  .sf-filters__group, .sf-filters__foot, .banner--card, .next-up { padding-inline: var(--space-4); }
  .modal__head, .modal__body, .modal__foot { padding-inline: var(--space-4); }
  .pop { padding: var(--space-4); }
  .empty { padding-inline: var(--space-4); }
  .window-card__time { font-size: 1.5rem; } /* the same big-number step as .metric__value */

   .grid--3.grid--short { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 416px and below: small phones */
@media (max-width: 26rem) {
  /* Narrow phone — the last places where a fixed pair still collides. */
  .page-head__actions .btn,
  .banner__actions .btn,
  .modal__foot .btn { flex: 1 1 100%; }
  /* Only these full-width buttons may wrap a long label; every other button keeps one line. */
  .page-head__actions .btn__label,
  .banner__actions .btn__label,
  .modal__foot .btn__label { white-space: normal; }
  .page-head__export .btn__label { white-space: nowrap; } /* its visually hidden label stays one line for screen readers */
  /* Burger + wordmark + up to three icons (the customer bar adds the cart) keep the gutter. */
  .app-bar, .app-bar__lead, .app-bar__actions { gap: var(--space-2); }
}

/* Reduced motion: last, so it switches off every animation above */
@media (prefers-reduced-motion: reduce) {
  .app-side--open,
  .app-scrim { animation: none; }

  .sheet, .sheet-scrim,
  .sheet.sheet--closing, .sheet-scrim.sheet--closing { animation: none; }

  .sf-filters[open] { animation: none; }
}
