/* ============================================================
   Stoa — Merchant dashboard
   Sage Institute LLC. Confidential.
   ------------------------------------------------------------
   The working layer over the Design System tokens. Every colour
   resolves to a canon token, with two declared exceptions, both
   derived from tokens rather than new hues:

     · the pressed-in shadow on a held control, which is Stoa's
       grove at low alpha — there is no token for a press inside
       an action-coloured surface;
     · the caret drawn into the select, which carries Earth as a
       literal because a data: URI cannot read a custom property.

   Sizes, radii and rules are tokens throughout.

   Three commitments this file keeps:

   1. **Stoa's register, not the Institute's.** The surface runs
      under .theme-stoa — parchment ground, bone surfaces, grove
      as the action colour, and Stoa's larger radii (6/10/16),
      which is the softer, more tactile commerce surface the
      canon reserves for the product.

   2. **Seated press, never lift.** Sage Source forbids the
      floating-card shadow. Depth here is a 1px settle and an
      inset hairline — a thing pressed into the page, not
      hovering above it. Controls move 1px down on :active and
      deepen in tone; they never glow, scale, or bounce.

   3. **One ground.** The canon defines a single ground —
      parchment — and no dark counterpart. An invented dark
      palette would be seven colours the Institute has not
      approved, so there is none.
   ============================================================ */

/* ── Shell ─────────────────────────────────────────────────── */

body {
  min-height: 100vh;
  font-size: var(--type-base);
}

.shell {
  max-width: var(--measure-wide);
  margin: 0 auto;
  padding: 0 var(--space-xl) var(--space-4xl);
}

/* ── Masthead ──────────────────────────────────────────────── */

.masthead {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  flex-wrap: wrap;
  padding: var(--space-2xl) 0 var(--space-lg);
}

.masthead .shopname {
  font-family: var(--font-display);
  font-size: var(--type-h2);
  font-weight: var(--weight-medium);
  color: var(--stoa-ink);
  margin: 0;
}

.masthead .whereabouts {
  font-family: var(--font-label);
  font-weight: var(--weight-label);
  font-size: var(--type-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--stoa-earth);
}

.masthead .spacer { flex: 1 1 auto; }

.masthead .standing {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-label);
  font-size: var(--type-caption);
  font-weight: var(--weight-label);
  letter-spacing: 0.06em;
  color: var(--stoa-earth);
}

/* Open/closed reads as a struck dot: filled when the doors are
   open, hollow when they are not. Colour is not carrying it
   alone — fill/void is legible without hue. */
.standing .lamp {
  width: 9px; height: 9px; border-radius: var(--stoa-radius-full);
  border: 1.5px solid var(--stoa-earth);
}
.standing.is-open .lamp { background: var(--stoa-grove); border-color: var(--stoa-grove); }
.standing.is-open { color: var(--stoa-grove); }

/* The chip is a control, so it has to look touchable and press like one. */
.standing-set { display: inline-block; }
.standing-set > summary {
  list-style: none; cursor: pointer;
  padding: 4px 10px; border-radius: var(--stoa-radius-full);
  border: var(--rule-hairline) solid transparent;
  transition: border-color var(--transition), background-color var(--transition),
              transform var(--transition);
}
.standing-set > summary::-webkit-details-marker { display: none; }
.standing-set > summary:hover {
  border-color: var(--stoa-border); background: var(--stoa-bone);
}
.standing-set > summary:active { transform: translateY(1px); }
.standing-set[open] > summary {
  border-color: var(--stoa-grove); background: var(--stoa-bone);
}
/* Its panel hangs from the masthead rather than the row grid. */
.standing-set > form { left: 0; right: auto; }

/* ── Navigation ────────────────────────────────────────────── */
/* Sigil over label. The mark is the thing the eye finds; the
   label underneath carries the meaning (the canon requires the
   pairing, and a merchant should never have to guess a symbol). */

.wayfinding {
  display: flex;
  gap: var(--space-xs);
  border-top: var(--rule-hairline) solid var(--stoa-border);
  padding: var(--space-xs) 0 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.wayfinding::-webkit-scrollbar { display: none; }

.wayfinding a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 78px;
  padding: 10px var(--space-sm) 9px;
  /* The rule under the navigation is drawn by the items themselves, so the
     one under the current place replaces it rather than doubling it. */
  border-bottom: 2px solid var(--stoa-border);
  color: var(--stoa-earth);
  text-decoration: none;
  transition: color var(--transition), background-color var(--transition),
              border-color var(--transition);
}
/* The strip of rule either side of the items, so the line runs the full width. */
.wayfinding::after {
  content: ""; flex: 1 0 var(--space-md);
  border-bottom: 2px solid var(--stoa-border);
}
.wayfinding a span {
  font-family: var(--font-label);
  font-size: 10.5px;
  font-weight: var(--weight-label);
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  white-space: nowrap;
}
.wayfinding a:hover { color: var(--stoa-ink); background: var(--stoa-smoke); }
.wayfinding a.here {
  color: var(--stoa-grove);
  border-bottom-color: var(--stoa-grove);
}
/* A count riding the mark — the only place a number sits on a
   sigil, and only when it is a number that wants answering. */
.wayfinding .mark { position: relative; }
.wayfinding .tally {
  position: absolute; top: -5px; right: -9px;
  min-width: 16px; height: 16px; padding: 0 4px;
  display: grid; place-items: center;
  background: var(--stoa-amber); color: var(--stoa-bone);
  border-radius: var(--stoa-radius-full);
  font-family: var(--font-label); font-weight: var(--weight-label-bold);
  font-size: 10px; letter-spacing: 0;
}

/* ── The "as of" bar ───────────────────────────────────────── */
/* Founder direction: a prominent refresh, not a live feed. The
   page states plainly when it was last true and refreshing is
   the merchant's move to make. */

.asof {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md) 0 0;
}
.asof .stamp {
  font-family: var(--font-label);
  font-size: var(--type-caption);
  font-weight: var(--weight-label);
  letter-spacing: 0.06em;
  color: var(--stoa-earth);
}

/* ── Type ──────────────────────────────────────────────────── */

.pagetitle {
  font-family: var(--font-display);
  font-size: var(--type-h2);
  font-weight: var(--weight-medium);
  color: var(--stoa-ink);
  margin: var(--space-xl) 0 var(--space-xs);
}
.lede {
  font-family: var(--font-body);
  font-size: var(--type-body);
  color: var(--stoa-earth);
  margin: 0 0 var(--space-lg);
  max-width: var(--measure-prose);
}
.sectiontitle {
  font-family: var(--font-label);
  font-size: var(--type-label);
  font-weight: var(--weight-label-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--stoa-earth);
  margin: var(--space-xl) 0 var(--space-sm);
  display: flex; align-items: center; gap: var(--space-sm);
}
.sectiontitle::after {
  content: ""; flex: 1; height: var(--rule-hairline);
  background: var(--stoa-border);
}

/* ── Cards ─────────────────────────────────────────────────── */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: var(--space-md);
}

.card {
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  padding: var(--space-lg);
  box-shadow: var(--press-seal);
}

/* A card that is a link warms its border rather than lifting. */
a.card {
  display: block; text-decoration: none; color: inherit;
  transition: border-color var(--transition), transform var(--transition);
}
a.card:hover { border-color: var(--stoa-amber); }
a.card:active { transform: translateY(1px); }

.card .figure {
  font-family: var(--font-display);
  font-size: 2.4rem;
  line-height: 1.05;
  color: var(--stoa-ink);
  /* Cormorant defaults to oldstyle figures, where 1 is a short stroke that
     reads as a capital I at this size — "I deliveries to hand over". Lining
     figures for anything a merchant counts; tabular so a column of them
     aligns. */
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: "lnum" 1, "tnum" 1;
}
.card .figure.quiet { color: var(--stoa-earth-muted); }
.card .figure.wants { color: var(--stoa-amber); }
.card .caption {
  font-family: var(--font-label);
  font-size: var(--type-caption);
  font-weight: var(--weight-label);
  letter-spacing: 0.04em;
  color: var(--stoa-earth);
  margin-top: var(--space-xs);
}
.card .aside {
  font-family: var(--font-body);
  font-size: var(--type-small);
  color: var(--stoa-earth-muted);
  margin-top: 2px;
}
.card .cardmark { color: var(--stoa-earth-muted); margin-bottom: var(--space-sm); }

/* Nothing to do reads as settled, not as a broken panel. */
.settled {
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  padding: var(--space-2xl) var(--space-lg);
  text-align: center;
  color: var(--stoa-earth);
  font-size: var(--type-body);
}
.settled .settledmark { color: var(--stoa-earth-muted); display: block; margin-bottom: var(--space-sm); }

/* ── Rows: the working list ────────────────────────────────── */

.rows { display: flex; flex-direction: column; gap: var(--space-sm); }

.row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  padding: var(--space-md) var(--space-lg);
  box-shadow: var(--press-seal);
}
/* A row that wants an answer carries a struck edge on the left —
   an engraver's rule, not a coloured banner. */
.row.wants { border-left: 3px solid var(--stoa-amber); }
.row.overdue { border-left: 3px solid var(--stoa-danger); }

.row .body { flex: 1 1 auto; min-width: 0; }
.row .title {
  font-family: var(--font-body);
  font-size: var(--type-body);
  color: var(--stoa-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row .under {
  font-variant-numeric: lining-nums tabular-nums;
  font-family: var(--font-label);
  font-size: var(--type-caption);
  font-weight: var(--weight-label);
  letter-spacing: 0.04em;
  color: var(--stoa-earth);
  margin-top: 3px;
  display: flex; flex-wrap: wrap; gap: var(--space-sm);
  align-items: center;
}
.row .under .sep { color: var(--stoa-border); }
.row .doings { display: flex; gap: var(--space-sm); flex-shrink: 0; flex-wrap: wrap; align-items: flex-start; }

/* A disclosure whose panel opens BENEATH the row, full width, rather than
   inside whatever narrow flex cell its summary sits in. Squeezed into the
   action column, the reason field was a ~195px slot with a placeholder no one
   could read. */
.aside-form { position: relative; }
.aside-form > summary {
  list-style: none;
  cursor: pointer;
}
.aside-form > summary::-webkit-details-marker { display: none; }
.aside-form[open] > summary { border-color: var(--stoa-grove); color: var(--stoa-grove); }
.aside-form > form {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 5;
  width: min(360px, calc(100vw - 48px));
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  padding: var(--space-lg);
  box-shadow: var(--press-seal);
}
.aside-form > form .field { margin-bottom: var(--space-md); }
.aside-form > form .note { margin: 0 0 var(--space-md); }
@media (max-width: 720px) {
  .aside-form > form { position: static; width: 100%; margin-top: var(--space-sm); }
}
.row .rowmark { color: var(--stoa-earth-muted); flex-shrink: 0; }

/* ── Controls ──────────────────────────────────────────────── */
/* Tactile: every control settles 1px on press and deepens in
   tone. None of them lift, glow, or scale. */

.act {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-label);
  font-size: var(--type-caption);
  font-weight: var(--weight-label-bold);
  letter-spacing: var(--tracking-cta);
  text-transform: uppercase;
  padding: 9px var(--space-md);
  border-radius: var(--stoa-radius-sm);
  border: var(--rule-hairline) solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--transition), border-color var(--transition),
              color var(--transition), transform var(--transition),
              box-shadow var(--transition);
}
.act:active { transform: translateY(1px); }

/* One primary per view — the canon's rule. */
.act.primary { background: var(--stoa-grove); color: var(--stoa-bone); }
.act.primary:hover { background: var(--stoa-grove-deep); }
.act.primary:active { box-shadow: inset 0 1px 2px rgba(40, 61, 44, 0.45); }

.act.secondary {
  background: var(--stoa-bone); color: var(--stoa-grove);
  border-color: var(--stoa-border);
}
.act.secondary:hover { border-color: var(--stoa-grove); background: var(--stoa-smoke); }
.act.secondary:active { box-shadow: var(--press-soft); }

.act.tertiary { background: transparent; color: var(--stoa-earth); padding-inline: var(--space-sm); }
.act.tertiary:hover { color: var(--stoa-ink); }

/* Consequential, and it should look like it: outlined in the
   danger tone rather than filled, so it is never the thing a
   hand lands on by accident. */
.act.grave { background: transparent; color: var(--stoa-danger); border-color: var(--stoa-danger); }
.act.grave:hover { background: var(--stoa-danger); color: var(--stoa-bone); }

.act[disabled], .act.spent {
  color: var(--stoa-earth-muted);
  background: var(--stoa-smoke);
  border-color: var(--stoa-border);
  cursor: default; pointer-events: none;
}

/* ── Fields ────────────────────────────────────────────────── */

.field { display: block; margin-bottom: var(--space-lg); }
.field > span {
  display: block;
  font-family: var(--font-label);
  font-size: var(--type-label);
  font-weight: var(--weight-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--stoa-earth);
  margin-bottom: 6px;
}
.field input[type=text], .field input[type=email], .field input[type=password],
.field input[type=number], .field input[type=time], .field input[type=url],
.field textarea, .field select {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--type-base);
  line-height: var(--leading-body);
  color: var(--stoa-ink);
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-sm);
  padding: 10px 12px;
  transition: border-color var(--transition), box-shadow var(--transition);
}
.field textarea { resize: vertical; min-height: 96px; }

/* File inputs. The dashboard has no JavaScript, so the native control stays —
   it is given room and a baseline rather than a costume it cannot wear. */
input[type=file] {
  display: block;
  margin-bottom: var(--space-sm);
  font-family: var(--font-body);
  font-size: var(--type-sm);
  color: var(--stoa-earth);
}

/* A placeholder that renders at full ink reads as a value the shop has already
   set. Every merchant form here had that: the inputs were coloured and the
   placeholder never was, so it inherited. A merchant looking at their own
   Shopfront could reasonably believe their door already said something. */
.field input::placeholder, .field textarea::placeholder {
  color: var(--stoa-earth-muted);
  opacity: 1;                 /* Firefox dims placeholders by default */
  font-style: italic;
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--stoa-grove);
  box-shadow: var(--press-soft);
}
/* A hint is prose under a field, not a second label — it has to undo the
   label treatment it would otherwise inherit from `.field > span`. */
.field .hint {
  font-family: var(--font-body);
  font-size: var(--type-small);
  font-weight: var(--weight-body);
  letter-spacing: 0;
  text-transform: none;
  color: var(--stoa-earth-muted);
  margin-top: 5px;
  margin-bottom: 0;
}
.inline-field { display: inline-flex; align-items: center; gap: 6px; }
/* Room for the browser's own spinner. Without it the arrows sit on top of the
   last digit — the value and the control fighting for the same few pixels. */
.inline-field input[type=number] { padding-right: 4px; }
.inline-field input[type=number],
.inline-field input[type=time] {
  width: 92px; text-align: right;
  font-family: var(--font-body); font-size: var(--type-base);
  color: var(--stoa-ink); background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-sm); padding: 7px 9px;
}
.inline-field input[type=time] { width: auto; text-align: left; }
.inline-field input:focus { outline: none; border-color: var(--stoa-grove); box-shadow: var(--press-soft); }
/* The browser draws its own clock button inside a time field; tint it to the
   palette rather than leave a blue-grey control sitting on parchment. */
input[type=time]::-webkit-calendar-picker-indicator {
  filter: sepia(0.5) saturate(0.5) hue-rotate(350deg) opacity(0.55);
  cursor: pointer;
}
.inline-field .unit { font-family: var(--font-label); font-size: var(--type-caption); color: var(--stoa-earth); }

/* Native select chrome ignores the palette entirely, so the
   caret is drawn here and the control keeps the register. */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M1 1l4 4 4-4' fill='none' stroke='%238B7055' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  cursor: pointer;
}

/* The shop switcher, when an account holds more than one. */
.switcher select {
  font-family: var(--font-label);
  font-size: var(--type-caption);
  letter-spacing: 0.04em;
  color: var(--stoa-earth);
  background-color: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-full);
  padding: 7px 30px 7px 14px;
  max-width: 260px;
}
.switcher select:hover { border-color: var(--stoa-grove); color: var(--stoa-grove); }

/* ── Two-state control ─────────────────────────────────────── */
/* Not a toggle switch — a pair of struck plates where the live
   one is pressed in. The state is legible without colour. */

.plates { display: inline-flex; border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-sm); overflow: hidden; }
.plates button {
  font-family: var(--font-label); font-size: var(--type-caption);
  font-weight: var(--weight-label); letter-spacing: 0.08em; text-transform: uppercase;
  padding: 7px 14px; border: none; cursor: pointer;
  background: var(--stoa-bone); color: var(--stoa-earth);
  transition: background-color var(--transition), color var(--transition);
}
.plates button + button { border-left: var(--rule-hairline) solid var(--stoa-border); }
.plates button:hover { background: var(--stoa-smoke); color: var(--stoa-ink); }
.plates button.set {
  background: var(--stoa-grove); color: var(--stoa-bone);
  box-shadow: inset 0 1px 2px rgba(40, 61, 44, 0.45);
  cursor: default;
}

/* ── Tables ────────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; }
th {
  text-align: left;
  font-family: var(--font-label);
  font-size: var(--type-label);
  font-weight: var(--weight-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--stoa-earth);
  padding: 0 var(--space-md) var(--space-sm) 0;
  border-bottom: var(--rule-hairline) solid var(--stoa-border);
}
td.num, .stamp, .badge, .inline-field input {
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: "lnum" 1, "tnum" 1;
}
td {
  padding: var(--space-md) var(--space-md) var(--space-md) 0;
  border-bottom: var(--rule-hairline) solid var(--stoa-border);
  font-size: var(--type-base);
  vertical-align: middle;
}
tr:last-child td { border-bottom: none; }
td.num, th.num { text-align: right; padding-right: 0; }

/* A table whose columns each hold a control needs room declared, or the
   headings run together and the controls wrap mid-word. */
.ruled { table-layout: fixed; }
.ruled th, .ruled td { padding-right: var(--space-md); }
.ruled th:first-child, .ruled td:first-child { padding-left: 0; }
/* Each of these cells holds a control plus its label, and the canon requires
   the label to be visible — so the column has to be wide enough for the word,
   not just the mark. */
.ruled .c-name  { width: auto; min-width: 180px; }
.ruled .c-price { width: 196px; }
.ruled .c-count { width: 176px; }
.ruled .c-shelf { width: 112px; }
.ruled .c-hold  { width: 88px; }
.ruled .c-terms { width: 118px; }
/* Two disclosures stacked — receiving and shrinkage. Wide enough that the
   summaries sit side by side rather than wrapping onto separate lines, which
   would make one row of the table twice the height of its neighbours. */
.ruled .c-stock { width: 150px; }
.ruled .c-stock .aside-form { display: inline-block; margin-right: 4px; }
.ruled td { vertical-align: middle; }
/* Badges beside a title sit on the line rather than pushing it. */
.ruled .c-name .badge { margin-left: 6px; vertical-align: 1px; }
/* Wide tables scroll inside their own frame; the page never scrolls sideways. */
.spread { overflow-x: auto; }
.spread > table { min-width: 900px; }

/* ── Badges ────────────────────────────────────────────────── */
/* Quiet outline by default; a fill is reserved for the live
   state, per the canon's borders-vs-capsules rule. */

.badge {
  display: inline-block;
  font-family: var(--font-label);
  font-size: 10.5px;
  font-weight: var(--weight-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--stoa-radius-full);
  border: var(--rule-hairline) solid var(--stoa-border);
  color: var(--stoa-earth);
  white-space: nowrap;
}
.badge.live { background: var(--stoa-grove); border-color: var(--stoa-grove); color: var(--stoa-bone); }
.badge.wants { border-color: var(--stoa-amber); color: var(--stoa-amber); }
.badge.grave { border-color: var(--stoa-danger); color: var(--stoa-danger); }
.badge.quiet { color: var(--stoa-earth-muted); }

/* ── Notes ─────────────────────────────────────────────────── */

.note {
  border-left: 2px solid var(--stoa-border);
  padding: 2px 0 2px var(--space-md);
  margin: var(--space-md) 0;
  color: var(--stoa-earth);
  font-size: var(--type-small);
  max-width: var(--measure-prose);
}
.note.wants { border-left-color: var(--stoa-amber); }
.note strong { color: var(--stoa-ink); font-weight: var(--weight-semibold); }

.saved {
  display: flex; align-items: center; gap: 6px;
  color: var(--stoa-grove);
  font-family: var(--font-label); font-size: var(--type-caption);
  letter-spacing: 0.06em; text-transform: uppercase;
  margin-bottom: var(--space-md);
}
.warned { color: var(--stoa-danger); }

/* ── Correspondence ────────────────────────────────────────── */

.thread { margin: var(--space-sm) 0 var(--space-xl); }
.speech { border-left: 2px solid var(--stoa-border); padding: 2px 0 2px var(--space-md); margin-bottom: var(--space-lg); }
.speech.theirs { border-left-color: var(--stoa-grove); }
.speech .who {
  font-family: var(--font-label); font-size: var(--type-caption);
  font-weight: var(--weight-label); letter-spacing: 0.06em;
  color: var(--stoa-earth); margin-bottom: 4px;
}
.speech .who .when { color: var(--stoa-earth-muted); margin-left: var(--space-sm); }
.speech .said { white-space: pre-wrap; font-family: var(--font-body); }

/* ── Sign in ───────────────────────────────────────────────── */

.gate {
  max-width: 384px;
  margin: 8vh auto 0;
  padding: 0 var(--space-lg);
}
.gate .crest { text-align: center; color: var(--stoa-grove); margin-bottom: var(--space-md); }
.gate h1 {
  font-family: var(--font-display);
  font-size: var(--type-h2);
  font-weight: var(--weight-medium);
  text-align: center;
  color: var(--stoa-ink);
  margin-bottom: var(--space-xs);
}
.gate .said {
  text-align: center; color: var(--stoa-earth);
  font-size: var(--type-small); margin-bottom: var(--space-xl);
}
.gate .card { padding: var(--space-xl); }
.gate .foot {
  text-align: center; margin-top: var(--space-lg);
  font-size: var(--type-small); color: var(--stoa-earth-muted);
}

/* ── Foot ──────────────────────────────────────────────────── */

.foot {
  margin-top: var(--space-3xl);
  padding-top: var(--space-lg);
  border-top: var(--rule-hairline) solid var(--stoa-border);
  color: var(--stoa-earth);
  font-size: var(--type-small);
  display: flex; gap: var(--space-md); align-items: baseline; flex-wrap: wrap;
}
.foot .spacer { flex: 1 1 auto; }

/* ── Narrow ────────────────────────────────────────────────── */

@media (max-width: 720px) {
  .shell { padding: 0 var(--space-md) var(--space-3xl); }
  .masthead { padding-top: var(--space-xl); }
  .row { flex-wrap: wrap; }
  .row .doings { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .act:active, a.card:active { transform: none; }
}

/* ── Shelves ───────────────────────────────────────────────── */
/* The shop's layout as columns. A phone shows one aisle at a
   time because it must; a browser has the width to show the
   whole arrangement, which is the thing a merchant is actually
   reasoning about when they rearrange a shop. */

.newaisle {
  display: flex; align-items: flex-end; gap: var(--space-md);
  flex-wrap: wrap; margin-bottom: var(--space-lg);
}
.newaisle .field { flex: 1 1 260px; max-width: 340px; }

/* The counter. Sits above the held list because it is the thing a merchant
   reaches for with a person standing in front of them, and it should be the
   first control on the page rather than something found by scrolling. */
/* The promotion form is a panel, not a popover.
   `.aside-form > form` floats at 360px, which is right for a two-field
   confirmation and wrong for a form carrying a five-column stock table — the
   table rendered inside a 360px card. Spec §6.2.1 asks for a seated panel and
   the canon forbids the floating card, so this overrides both. */
.promostart > form {
  position: static;
  width: auto;
  margin-top: var(--space-md);
  padding: var(--space-lg);
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  box-shadow: var(--press-seal);
}
.promostart { margin-bottom: var(--space-xl); }
.promokept {
  font-family: var(--font-label);
  font-size: 0.85rem;
  color: var(--stoa-earth);
  margin: var(--space-sm) 0 0;
}

/* The three numbers at the top of the record. Distinct from `.wayfinding
   .tally`, which is the nav counter — this one is read, not clicked, and the
   figure is the largest thing on the page because it is what the merchant came
   for. */
.tallies {
  display: flex; flex-wrap: wrap; gap: var(--space-md);
  margin-bottom: var(--space-xl);
}
.tallies .tally {
  flex: 1 1 160px;
  padding: var(--space-md) var(--space-lg);
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  box-shadow: var(--press-seal);
}
.tallies .tally .figure {
  display: block;
  font-family: var(--font-display);
  font-size: 2.1rem; line-height: 1.1;
  color: var(--stoa-ink);
}
.tallies .tally .what {
  display: block; margin-top: 2px;
  font-family: var(--font-label); font-size: 0.82rem;
  letter-spacing: 0.04em; color: var(--stoa-earth);
}
/* Amber only when there is something to notice, and the words carry it too —
   a shop reading this in a grey-filtered window still sees "gone without a
   sale" beside the number. */
.tallies .tally.wants { border-color: var(--stoa-amber); }

.wherebox {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-label); font-size: 0.9rem;
  color: var(--stoa-ink);
  padding: 6px 10px;
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  background: var(--stoa-bone);
  margin-right: var(--space-sm);
}

.counterform {
  display: flex; align-items: flex-end; gap: var(--space-md);
  flex-wrap: wrap; margin-bottom: var(--space-xl);
  padding: var(--space-md);
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  box-shadow: var(--press-seal);
}
.counterform .field { flex: 1 1 240px; max-width: 320px; }
.counterform input {
  font-family: var(--font-label);
  font-size: 1.15rem; letter-spacing: 0.08em;
}

.shelfrun {
  display: flex;
  gap: var(--space-md);
  align-items: flex-start;
  padding-bottom: var(--space-sm);
}

.aisle {
  flex: 0 0 280px;
  background: var(--stoa-bone);
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-md);
  box-shadow: var(--press-seal);
  /* NOT overflow:hidden — the removal confirmation opens as an absolutely
     positioned panel and was being clipped by the card, so a merchant could
     not read what removing the aisle would do before doing it. */
}
.aisle > .aislehead:first-child {
  border-top-left-radius: var(--stoa-radius-md);
  border-top-right-radius: var(--stoa-radius-md);
}
/* Unshelved is a holding place, not a shelf — quieter, and marked
   as belonging to a different order of thing. */
.aisle.loose { background: var(--stoa-smoke); border-style: dashed; }

.aislehead {
  padding: var(--space-md);
  border-bottom: var(--rule-hairline) solid var(--stoa-border);
}
.aislename { display: flex; gap: 4px; align-items: center; }
.aislename input {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--font-display);
  font-size: var(--type-h4);
  color: var(--stoa-ink);
  background: transparent;
  border: var(--rule-hairline) solid transparent;
  border-radius: var(--stoa-radius-sm);
  padding: 4px 6px;
}
.aislename input:hover { border-color: var(--stoa-border); }
.aislename input:focus {
  outline: none; background: var(--stoa-parchment);
  border-color: var(--stoa-grove);
}
.aislename-static {
  font-family: var(--font-display); font-size: var(--type-h4);
  font-weight: var(--weight-medium); color: var(--stoa-earth); margin: 0 0 4px;
}
.aislenote { font-size: var(--type-small); color: var(--stoa-earth-muted); margin: 0; }
.aislemove { display: flex; gap: 4px; margin-top: 6px; flex-wrap: wrap; }
.aislemove form { display: flex; gap: 4px; }

.aislestock { padding: var(--space-sm); }
.shelfitem {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 6px;
  align-items: center;
  padding: 8px;
  border-radius: var(--stoa-radius-sm);
}
.shelfitem:hover { background: var(--stoa-parchment); }
.shelfitem .what {
  grid-column: 1 / -1;
  font-size: var(--type-small);
  color: var(--stoa-ink);
  line-height: 1.35;
}
.shelfitem select { font-size: var(--type-caption); padding: 5px 26px 5px 8px; }
.emptyaisle {
  padding: var(--space-lg) var(--space-sm);
  text-align: center;
  color: var(--stoa-earth-muted);
  font-size: var(--type-small);
  margin: 0;
}

/* ── The patron's view ─────────────────────────────────────── */
/* Set apart from the working surface with a ruled frame, so it
   reads as a thing being looked AT rather than another panel to
   act on. Nothing in here is a control. */

.asPatron {
  border: var(--rule-hairline) solid var(--stoa-border);
  border-radius: var(--stoa-radius-lg);
  background: var(--stoa-bone);
  padding: 0 0 var(--space-xl);
  overflow: hidden;
  max-width: 720px;
  box-shadow: var(--press-seal);
}
.pv-banner {
  height: 132px;
  display: grid; place-items: center;
  background: var(--stoa-smoke);
  border-bottom: var(--rule-hairline) solid var(--stoa-border);
  color: var(--stoa-earth-muted);
}
.pv-banner img { width: 100%; height: 100%; object-fit: cover; }
.pv-nobanner {
  display: inline-flex; align-items: center; gap: var(--space-sm);
  font-family: var(--font-label); font-size: var(--type-caption);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.pv-identity { padding: var(--space-lg) var(--space-xl) 0; }
.pv-identity h3 {
  font-family: var(--font-display); font-size: var(--type-h3);
  font-weight: var(--weight-medium); color: var(--stoa-ink); margin: 0;
}
.pv-where {
  font-family: var(--font-label); font-size: var(--type-caption);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  color: var(--stoa-earth); margin: 4px 0 10px;
}
.pv-facts {
  padding: 0 var(--space-xl);
  font-size: var(--type-small); color: var(--stoa-earth);
  display: flex; gap: var(--space-sm); flex-wrap: wrap;
}
.pv-facts .sep { color: var(--stoa-border); }
/* A label between rules, not a heading — the canon's bookplate-rule role,
   which is what Jost is for. Rendered as <p> in preview.html so the document
   outline does not claim a sans-serif heading level. */
.pv-section {
  font-family: var(--font-label); font-size: var(--type-label);
  font-weight: var(--weight-label); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--stoa-earth);
  margin: var(--space-xl) var(--space-xl) var(--space-sm);
}
.pv-hero {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-sm); padding: 0 var(--space-xl);
}
.pv-item {
  display: grid; gap: 2px;
  padding: var(--space-md);
  background: var(--stoa-parchment);
  border-radius: var(--stoa-radius-sm);
}
.pv-thumb { color: var(--stoa-earth-muted); }
.pv-name { font-size: var(--type-small); color: var(--stoa-ink); line-height: 1.3; }
.pv-price {
  font-size: var(--type-small); color: var(--stoa-earth);
  font-variant-numeric: lining-nums tabular-nums;
}
.pv-aisles { padding: 0 var(--space-xl); display: flex; gap: 6px; flex-wrap: wrap; }
.pv-plain {
  padding: 0 var(--space-xl); margin: 0;
  font-size: var(--type-small); color: var(--stoa-earth); line-height: 1.6;
}
.pv-quote {
  margin: 0 var(--space-xl) var(--space-md);
  padding-left: var(--space-md);
  border-left: 2px solid var(--stoa-border);
  font-family: var(--font-body); font-size: var(--type-small);
  color: var(--stoa-ink); font-style: italic;
}
.pv-quote cite {
  display: block; margin-top: 4px; font-style: normal;
  font-family: var(--font-label); font-size: var(--type-caption);
  color: var(--stoa-earth-muted);
}

/* ── The shop's sign ─────────────────────────────────────────────────────────
   A fascia is the band over a shop's door carrying its name. The swatch shows
   the shop's own initials on each candidate ground, because a colour chip tells
   a shopkeeper nothing about whether their name will read on it. */
.signpicker { border: 0; padding: 0; margin: 0 0 1.25rem; }
.signpicker legend { font: inherit; padding: 0; margin-bottom: .25rem; }
.signrow { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .5rem; }
.signswatch { display: flex; flex-direction: column; align-items: center; gap: .3rem; cursor: pointer; }
.signswatch input { position: absolute; opacity: 0; pointer-events: none; }
.signchip {
  display: flex; align-items: center; justify-content: center;
  width: 3.25rem; height: 2.25rem; border-radius: 2px;
  color: var(--stoa-bone); font-family: var(--font-body);
  font-size: .95rem; letter-spacing: .04em;
  box-shadow: var(--press-soft);
}
.signswatch input:checked + .signchip {
  box-shadow: var(--press-soft), 0 0 0 2px var(--stoa-ink);
}
.signswatch input:focus-visible + .signchip {
  outline: 2px solid var(--stoa-grove); outline-offset: 2px;
}
.signname {
  font-size: var(--type-label); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--stoa-earth);
}
