/* =========================================================================
   Rambler Safety — signed-in surfaces
   =========================================================================

   The layer the trade portal and the back office add on top of public/app.css.
   Loaded second, and only by the screens rendered through `shell()` in
   src/views/auth.ts: sign in, the trade application, the portal, the account
   page and the four staff queues.

   WHAT BELONGS HERE, AND WHAT DOES NOT
   ------------------------------------
   app.css owns the vocabulary the whole system shares — buttons, pills, data
   tables, fields, banners, cards, the sticky summary bar. Nothing in that list
   is redefined below. This file adds only the components that exist because
   somebody is signed in:

     the credit position, the order document, the staff decision forms,
     the queue tiles, and the exception readout.

   No new colours. Every value below is a token from BRAND_TOKENS
   (src/platform/html.ts); the only literals are the same rgba() shadows and
   hatch fills app.css already uses, which are opacity on ink rather than new
   hues.

   FIVE RULES, INHERITED AND UNBROKEN
   ----------------------------------
   1. YELLOW IS A SIGNAL. It appears here on exactly three things: the commit
      button (from app.css), the focus halo (from app.css), and the left edge
      of the one figure a reader is looking for — available credit, value at
      risk. Never as decoration, never twice on one screen for the same reason.
   2. SENTENCE CASE. Uppercase only below 11px with letter-spacing:
      .stat__label, .tile__label, .form-section__legend, .field__optional.
   3. NUMBERS ARE TABULAR AND RIGHT-ALIGNED. Money is never centred. Every
      figure that a buyer or an accounts clerk compares down a column carries
      font-variant-numeric: tabular-nums.
   4. CORNERS ARE CONTROLLED — the shared small radius, never pill-card chrome.
   5. DENSE AND CALM. Whitespace separates sections; it never pads a table.

   ORDER OF SECTIONS
   -----------------
     1. Page furniture      .page-head__stats .section-block .ref-link .reason
     2. Auth and forms      .auth-alt .form-shell .form-section .field--reason
     3. Figures             .stats .stat .meter
     4. Credit              .credit
     5. Documents           .doc-meta .doc-totals .line-item .facts-list
     6. Queues              .tiles .tile .row-action .exceptions .error-text
     7. Decisions           .decide
     8. Responsive          phone first-class: staff work off phones too
     9. Print               an order detail is a document people file
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Page furniture
   ---------------------------------------------------------------------- */

/* Sits under the h1: the two or three facts that qualify the title. Inline
   rather than flex, so a run of words stays a sentence — a flex row turns
   every text node into its own gapped item and "2 orders · 78 pairs" comes
   apart into four floating pieces. Only the pills need the spacing. */
.page-head__stats {
  margin: var(--space-2) 0 0;
  font-size: var(--fs-md);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  line-height: 1.7;
}

.page-head__stats > .pill,
.page-head__stats > span {
  margin-right: var(--space-3);
  vertical-align: middle;
}

.page-head + .notice,
.page-head + .banner,
.page-head + .panel,
.page-head + .credit,
.page-head + .empty-state,
.page-head + .table-scroll,
.page-head + .tiles,
.page-head + .stats,
.page-head + .doc-meta,
.page-head + .split {
  margin-top: var(--space-5);
}

/* A titled block of secondary content: the audit trail, the hold history, the
   Zoho events under an order. */
.section-block {
  margin-top: var(--space-6);
}

/* A correction to the shared shell, made here because only the signed-in
   screens put anything in the actor strip. `.site-actor__name` truncates but
   the role/account line under it does not, so "Approved trade account ·
   Boksburg Safety Supplies (Pty) Ltd" runs out under the sign-out button on a
   phone. If this ever moves into app.css, delete it here. */
.site-actor__meta {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The reference in a queue: the thing a person is actually scanning for, so it
   is set in the mono face at reading weight rather than as a blue link. */
.ref-link {
  font-family: var(--mono);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid var(--hairline);
}

.ref-link:hover {
  color: var(--ink);
  border-bottom-color: var(--yellow);
}

/* Words a human typed, reproduced as typed. Line breaks in a decision reason
   are the reviewer's paragraphing and are worth keeping. */
.reason {
  white-space: pre-wrap;
}

.reason--cell {
  min-width: 18ch;
  max-width: 44ch;
  color: var(--ink-2);
}

.reason--quote {
  margin: 0 0 var(--space-4);
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--hairline-strong);
  background: var(--card);
  font-size: var(--fs-md);
  color: var(--ink-2);
}

/* A short table has no scrollbar and therefore needs no reserved height; the
   pane exists to bound the tall ones so their headers have something to stick
   to. Without this override a two-row audit trail is 200px of empty box. */
.table-scroll--pane {
  min-height: 0;
}

.section-block .table-scroll--pane {
  max-height: 60vh;
}

/* -------------------------------------------------------------------------
   2. Auth screens and long forms
   The sign-in card comes from app.css. What is added here is the routes out
   of it, and the sectioning a six-field application needs to stay legible.
   ---------------------------------------------------------------------- */

/* The alternatives under the sign-in card. A list, not a paragraph of links:
   "apply" and "reset" are different journeys and each one earns a line saying
   what it leads to. */
.auth-alt {
  list-style: none;
  width: 100%;
  max-width: var(--measure-form);
  margin: var(--space-4) auto 0;
  padding: 0;
  border-top: var(--line-1);
}

.auth-alt li {
  padding: var(--space-3) 0;
  border-bottom: var(--line-1);
}

.auth-alt a {
  display: block;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  width: fit-content;
}

.auth-alt a:hover {
  border-bottom-color: var(--yellow);
}

.auth-alt span {
  display: block;
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-top: 2px;
}

/* The trade application. Wider than the sign-in card because every field
   carries a sentence explaining why it is being asked for, and a hint that
   wraps to four lines is a hint nobody reads. */
.form-shell {
  width: 100%;
}

.form--wide,
.form--wide .field {
  max-width: none;
}

.form-section {
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  padding: var(--space-4) var(--space-4) var(--space-2);
  margin: 0 0 var(--space-4);
}

/* A legend inside a bordered fieldset sits on the border by default; pulling
   it onto the card fill keeps the rule unbroken and the label attached to the
   group it names. */
.form-section__legend {
  float: left;
  width: 100%;
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0;
  margin: 0 0 var(--space-1);
}

.form-section__note {
  clear: both;
  margin: 0 0 var(--space-4);
  font-size: var(--fs-md);
  color: var(--ink-2);
  max-width: 62ch;
}

.field__optional {
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-left: var(--space-1);
}

/* THE EXPLAINED CHOICE.
   Two places in this system ask a question whose answer decides a price: the
   trade application asks a shop owner what kind of business they are, and the
   approval screen asks a Rambler reviewer to confirm it. A `<select>` with two
   words in it would make both of those look like a formality. Each option is
   therefore a card the whole of which is the label — a 44px target on a phone —
   carrying the name, a sentence saying who that option is, and (on the approval
   screen) the consequence of choosing it.

   No option is pre-selected by the CSS and none is visually preferred: the two
   are peers, because Rambler's answer is genuinely one or the other. */
.choice {
  border: 0;
  padding: 0;
  margin: 0 0 var(--space-4);
  display: grid;
  gap: var(--space-2);
}

.choice__legend {
  float: left;
  width: 100%;
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0;
  margin: 0 0 var(--space-1);
}

.choice__note {
  clear: both;
  margin: 0 0 var(--space-1);
  font-size: var(--fs-md);
  color: var(--ink-2);
  max-width: 62ch;
}

.choice__option {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  padding: var(--space-3);
  cursor: pointer;
}

.choice__option:hover {
  border-color: var(--hairline-strong);
}

/* The selected card carries a teal edge, not a fill: the answer has to be
   legible at a glance without the chosen option shouting over the one the
   reader is still considering. */
.choice__option:has(input:checked) {
  border-left: 3px solid var(--teal);
  background: var(--teal-wash);
}

.choice__option:focus-within {
  outline: 3px solid var(--yellow);
  outline-offset: 2px;
}

.choice__option input {
  margin-top: 3px;
  flex: 0 0 auto;
}

.choice__body {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.choice__label {
  font-weight: 600;
  font-size: var(--fs-lg);
}

.choice__hint {
  font-size: var(--fs-md);
  color: var(--ink-2);
  max-width: 58ch;
}

/* What choosing this one does. Monospaced because it names a price list id,
   which a reviewer may have to quote to somebody at Rambler. */
.choice__consequence {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--muted);
}

.choice--invalid .choice__option {
  border-color: var(--danger);
}

/* The retail basket and checkout put the lines beside the money. `.split` from
   app.css does the two columns; these two only say which side is which and
   keep the total in view while the lines scroll. */
.shop-main {
  min-width: 0;
}

.shop-side {
  min-width: 0;
  align-self: start;
  position: sticky;
  top: var(--space-4);
}

@media (max-width: 900px) {
  .shop-side {
    position: static;
  }
}

/* THE REASON BOX.
   Every staff decision that changes commercial state carries one. It is given
   the look of the record rather than the look of an input, because it IS the
   record: six months later it is the only honest answer to "why does this
   customer have terms?". A teal edge marks it as part of the audit trail, the
   same accent the audit surfaces use elsewhere. */
.field--reason {
  border-left: 3px solid var(--teal);
  background: var(--teal-wash);
  padding: var(--space-3);
  margin-bottom: var(--space-4);
}

.field--reason .field__label {
  font-family: var(--display);
  font-size: var(--fs-lg);
}

.field--reason .field__hint {
  color: var(--ink-2);
  max-width: 58ch;
}

.field--reason textarea {
  background: var(--surface);
  border-color: var(--teal);
}

/* An error inside the reason box must still read as an error, not as more
   teal. */
.field--reason.field--invalid textarea {
  border-color: var(--danger);
  background: var(--danger-wash);
}

/* -------------------------------------------------------------------------
   3. Figures
   A number, what it is, and one line of provenance. Used by the credit panel
   and by the exceptions summary — the two places where the figure is the
   whole point of the screen.
   ---------------------------------------------------------------------- */

/* The track minimum is set by the widest thing that can land in it: a rand
   figure at display size. Too narrow and "R 47,102.00" breaks after the R,
   which is a number a person can misread. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0;
  margin: 0;
  border-top: var(--line-1);
}

.stats--inline {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  border: var(--line-1);
  border-radius: var(--radius);
  margin: 0 0 var(--space-4);
}

.stat {
  padding: var(--space-3) var(--space-4);
  border-left: var(--line-1);
  min-width: 0;
}

.stat:first-child {
  border-left: none;
}

.stat dd {
  margin: 0;
}

.stat__label {
  display: block;
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--space-1);
}

.stat__value {
  display: block;
  font-family: var(--display);
  font-size: var(--fs-2xl);
  font-weight: 700;
  line-height: 1.05;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.stat__note {
  display: block;
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-top: var(--space-1);
  max-width: 34ch;
}

/* The one figure the reader came for. Marked with an ink edge and a heavier
   size, not with yellow: several of these screens also carry a commit button,
   and a screen that spends the signal colour twice has stopped signalling. */
.stat--grand {
  background: var(--card);
  box-shadow: inset 3px 0 0 var(--ink);
}

.stat--grand .stat__value {
  font-size: var(--fs-3xl);
}

/* How much of the limit is spoken for. A bar because "84%" and "R 4,200 of
   R 5,000" are both true and neither of them, on its own, shows how close the
   line is. */
.meter {
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-top: var(--line-1);
}

.meter__track {
  display: block;
  height: 8px;
  background: var(--sunk);
  border: var(--line-1);
  border-radius: var(--radius);
  overflow: hidden;
}

.meter__fill {
  display: block;
  height: 100%;
  background: var(--teal);
  transition: width var(--dur) linear;
}

/* `account.ts` emits `.meter__fill--{tone}` for all four credit bands. The "ok"
   arm had no rule and was surviving on the base fill happening to be teal —
   correct by accident, and silently wrong the day the base changes. */
.meter__fill--ok {
  background: var(--teal);
}

.meter__fill--warn {
  background: var(--warn);
}

.meter__fill--bad {
  background: var(--danger);
}

.meter__fill--idle {
  background: var(--hairline-strong);
}

.meter__caption {
  margin: var(--space-2) 0 0;
  font-size: var(--fs-sm);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.meter__caption strong {
  color: var(--ink);
}

/* -------------------------------------------------------------------------
   4. Credit
   Read in this order: the band (an answer), available (the number that
   decides the next order), the three figures behind it, the meter. A reader
   who stops after two lines has still read the useful part.
   ---------------------------------------------------------------------- */

.credit {
  background: var(--surface);
}

.credit__band {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-left: 4px solid var(--hairline-strong);
  background: var(--card);
}

.credit__band--ok {
  border-left-color: var(--ok);
  background: var(--ok-wash);
}

.credit__band--warn {
  border-left-color: var(--warn);
  background: var(--warn-wash);
}

.credit__band--bad {
  border-left-color: var(--danger);
  background: var(--danger-wash);
}

.credit__band--idle {
  border-left-color: var(--hairline-strong);
  background: var(--card);
}

.credit__band-text {
  min-width: 0;
}

.credit__band .eyebrow {
  margin-bottom: var(--space-1);
}

/* The band label IS the heading. A pill repeating it beside the words would be
   the same fact twice, and the tinted edge already carries the colour. */
.credit__title {
  font-size: var(--fs-2xl);
  margin: 0;
}

.credit__explain {
  margin: var(--space-1) 0 0;
  font-size: var(--fs-md);
  color: var(--ink-2);
  max-width: 72ch;
}

.credit__body {
  display: block;
}

/* The banner keeps its own colour but loses its margins: inside the panel it
   is a section of the panel, not a floating alert. */
.credit__hold {
  margin: 0;
  border-left-width: 3px;
  border-right: 0;
  border-bottom: 0;
  border-radius: 0;
}

.credit__hold h3 {
  font-size: var(--fs-lg);
  margin: 0 0 var(--space-1);
}

.credit__hold p {
  margin: 0;
  font-size: var(--fs-md);
}

.credit__stamp {
  margin: 0;
  padding: var(--space-2) var(--space-4);
  border-top: var(--line-1);
  background: var(--card);
}

/* -------------------------------------------------------------------------
   5. Documents
   An order detail is handed to accounts. It has to read like a document:
   identity at the top, lines in the middle, money squared off at the bottom.
   ---------------------------------------------------------------------- */

.doc-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0;
  margin: 0 0 var(--space-4);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
}

.doc-meta__item {
  padding: var(--space-3) var(--space-4);
  border-left: var(--line-1);
  min-width: 0;
}

.doc-meta__item:first-child {
  border-left: none;
}

.doc-meta dt {
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--space-1);
}

.doc-meta dd {
  margin: 0;
  font-size: var(--fs-base);
  color: var(--ink);
}

.doc-meta__item--grand {
  background: var(--card);
  box-shadow: inset 3px 0 0 var(--ink);
}

/* Money and counts read out of a definition list still line up with money and
   counts read out of a table. */
.numeric-inline {
  font-family: var(--display);
  font-size: var(--fs-xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Totals square off to the right of the lines they total, the way they do on
   an invoice — not as a tfoot row whose colspan has to be recounted every time
   a column is added. */
.doc-totals {
  display: flex;
  justify-content: flex-end;
  margin: var(--space-4) 0 0;
}

.doc-totals dl {
  width: 100%;
  max-width: 22rem;
  margin: 0;
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
}

.doc-totals__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-4);
  border-bottom: var(--line-1);
}

.doc-totals__row dt {
  font-size: var(--fs-md);
  color: var(--ink-2);
}

.doc-totals__row dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  text-align: right;
}

.doc-totals__row--grand {
  border-bottom: 0;
  border-top: 2px solid var(--ink);
  background: var(--card);
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
}

.doc-totals__row--grand dt {
  font-family: var(--display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--ink);
}

.doc-totals__row--grand dd {
  font-family: var(--display);
  font-size: var(--fs-2xl);
  font-weight: 700;
}

/* A line on an order: photograph, name, SKU. The picture is what turns nine
   near-identical rows of text into something a person can scan, and it is the
   same thumbnail the ordering grid and the cart use. */
.line-item {
  min-width: 220px;
  font-weight: 400;
}

.row-identity__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 1px;
}

.row-identity__name {
  font-family: var(--display);
  font-size: var(--fs-lg);
  font-weight: 600;
  line-height: 1.15;
  color: var(--ink);
}

.row-identity__text .sku {
  font-size: var(--fs-xs);
}

.col-line {
  width: 1%;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.size-cell {
  font-family: var(--display);
  font-size: var(--fs-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Label/value pairs inside a card: the account's own particulars. */
.facts-list {
  margin: 0;
}

.fact-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
  border-bottom: var(--line-1);
}

.fact-row:last-child {
  border-bottom: 0;
}

.fact-row dt {
  font-size: var(--fs-md);
  color: var(--muted);
  flex: 0 0 auto;
}

.fact-row dd {
  margin: 0;
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* A saved size curve, printed inline. Each point is one chip so the eye can
   count them without reading them. */
.curve {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.curve__point {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--muted);
  border: var(--line-1);
  border-radius: var(--radius);
  padding: 0 4px;
  white-space: nowrap;
}

.curve__point b {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* -------------------------------------------------------------------------
   6. Queues
   The back office is four lists and a number on each of them. Everything here
   optimises for a staff member scanning at speed, on a laptop or a phone,
   several times a day.
   ---------------------------------------------------------------------- */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0;
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  margin: 0 0 var(--space-5);
}

.tile {
  display: block;
  padding: var(--space-4);
  border-left: var(--line-1);
  color: var(--ink);
  text-decoration: none;
  transition: background-color var(--dur) linear;
}

.tile:first-child {
  border-left: none;
}

.tile:hover {
  background: var(--card);
  color: var(--ink);
}

.tile__label {
  display: block;
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.tile__value {
  display: block;
  font-family: var(--display);
  font-size: var(--fs-4xl);
  font-weight: 700;
  line-height: 1;
  margin: var(--space-1) 0;
  font-variant-numeric: tabular-nums;
}

.tile__note {
  display: block;
  font-size: var(--fs-md);
  color: var(--ink-2);
}

/* Work is waiting. Normal, and marked in ink — a queue that shouts every
   morning stops being read by lunchtime. */
.tile--due {
  box-shadow: inset 3px 0 0 var(--ink);
}

/* Something has gone wrong and will not fix itself. The only red on the
   dashboard, and the rule is on the left edge rather than on the digits: a red
   number reads as a broken number rather than as an urgent one. */
.tile--stuck {
  box-shadow: inset 3px 0 0 var(--danger);
  background: var(--danger-wash);
}

.tile--stuck .tile__label {
  color: var(--danger);
}

/* The action at the end of a queue row. Held to the right and to one line, so
   the rows keep their rhythm. */
.row-action {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}

/* THE ERROR ZOHO SENT BACK.
   The one piece of text on these screens nobody should have to squint at or
   dig out of a clipped table cell, because it is the only thing that says what
   to fix. Mono, wrapped, on the danger wash, selectable in one gesture. */
.error-text {
  display: block;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--ink);
  background: var(--danger-wash);
  border-left: 3px solid var(--danger);
  padding: var(--space-2) var(--space-3);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 90ch;
}

.error-cell {
  min-width: 22ch;
  max-width: 46ch;
}

.error-cell .error-text {
  font-size: var(--fs-xs);
}

/* Exceptions carry two rows each: the facts, then the error underneath at full
   width. A message that matters is not worth truncating into a column. */
.exceptions__head-row th,
.exceptions__head-row td {
  border-bottom: 0;
  padding-bottom: var(--space-1);
}

/* The error cell is pinned to the left of the scroll port and its content is
   held to the viewport, so scrolling the facts sideways on a phone never
   scrolls the message out of reach. It is the one thing on this screen that
   must be readable without moving anything. */
.exceptions__error-row td {
  padding-top: 0;
  border-bottom: 2px solid var(--hairline);
  position: sticky;
  left: 0;
  background: var(--surface);
}

.exceptions__error-row .eyebrow,
.exceptions__error-row .error-text {
  max-width: min(90ch, calc(100vw - 3rem));
}

.exceptions__error-row .eyebrow {
  margin-bottom: var(--space-1);
}

.exceptions tbody tr:hover {
  background: transparent;
}

.exceptions__head-row:hover,
.exceptions__head-row:hover + .exceptions__error-row {
  background: var(--card);
}

/* -------------------------------------------------------------------------
   7. Decisions
   Approve and decline sit side by side, the same size, so neither is the one
   you press by accident. The commit colour, and only the commit colour, says
   which is which.
   ---------------------------------------------------------------------- */

.decide {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--space-4);
  align-items: start;
  margin: 0 0 var(--space-5);
}

.decide__primary {
  border-color: var(--hairline-strong);
}

.decide__secondary .card__head {
  background: var(--surface);
}

.decide__single {
  max-width: 46rem;
  margin: 0 0 var(--space-5);
}

.decide .card__body {
  gap: 0;
}

/* The card is already the measure; a field that stops 34rem short of its own
   card edge reads as a mistake rather than as a reading width. */
.decide .form,
.decide .field {
  max-width: none;
}

.decide .form-actions {
  margin-top: var(--space-3);
}

/* -------------------------------------------------------------------------
   8. Responsive
   Staff work off phones at the warehouse door, and buyers work off phones at
   a trade counter. Nothing below is a concession; it is the same screen at a
   width where a grid of four would be a column of slivers.
   ---------------------------------------------------------------------- */

@media (max-width: 900px) {
  .stats,
  .doc-meta,
  .tiles {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  }

  .stat,
  .doc-meta__item,
  .tile {
    border-left: none;
    border-top: var(--line-1);
  }

  .stats > :first-child,
  .doc-meta > :first-child,
  .tiles > :first-child {
    border-top: none;
  }
}

@media (max-width: 560px) {
  .stats,
  .doc-meta,
  .tiles {
    grid-template-columns: minmax(0, 1fr);
  }

  .stat--grand .stat__value {
    font-size: var(--fs-2xl);
  }

  /* Stacked, these are one fact per row; four rows of desktop padding is a
     screenful of nothing. */
  .doc-meta__item,
  .stat {
    padding: var(--space-2) var(--space-3);
  }

  .site-actor__who {
    max-width: 52vw;
  }

  .tile__value {
    font-size: var(--fs-3xl);
  }

  .doc-totals dl {
    max-width: none;
  }

  .fact-row {
    flex-direction: column;
    gap: 0;
  }

  .fact-row dd {
    text-align: left;
  }

  .form-section {
    padding: var(--space-3) var(--space-3) var(--space-1);
  }

  /* Fingers, not cursors. */
  .row-action .btn,
  .form-actions .btn,
  .auth-card .btn {
    min-height: 44px;
  }

  .form-actions .btn {
    width: 100%;
  }

  .section-block .table-scroll--pane {
    max-height: none;
  }
}

/* -------------------------------------------------------------------------
   9. Print
   An order detail gets printed and filed against a purchase order. app.css
   already strips the chrome; these are the pieces it does not know about.
   ---------------------------------------------------------------------- */

@media print {
  .tiles,
  .decide,
  .auth-alt,
  .row-action {
    display: none;
  }

  .table-scroll--pane,
  .section-block .table-scroll--pane {
    max-height: none;
    overflow: visible;
    border: 0;
  }

  .doc-meta,
  .doc-totals dl,
  .stats--inline {
    border-color: #999999;
  }

  .doc-meta__item--grand,
  .stat--grand {
    box-shadow: none;
  }

  .error-text {
    border-left-color: #999999;
    background: transparent;
  }
}

/* -------------------------------------------------------------------------
   Wholesale analytics
   ---------------------------------------------------------------------- */

.analytics-truth {
  margin: var(--space-5) 0;
  padding: var(--space-3) var(--space-4);
  border-left: 4px solid var(--teal);
  background: var(--teal-wash);
  color: var(--ink-2);
  font-size: var(--fs-md);
}

.analytics-truth strong {
  color: var(--ink);
}

.metric-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-5);
}

.metric-card {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4);
  border: var(--line-1);
  border-top: 3px solid var(--ink);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.metric-card__label,
.analytics-card__head > span {
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

.metric-card > strong {
  font-family: var(--display);
  font-size: clamp(1.65rem, 3vw, 2.45rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.metric-card > small {
  color: var(--muted);
  line-height: 1.35;
}

.metric-change {
  min-height: 1.35em;
  color: var(--ink-3);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

.metric-change--up,
.metric-change--new {
  color: var(--teal);
  font-weight: 600;
}

.metric-change--down {
  color: var(--warn);
  font-weight: 600;
}

.analytics-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-3);
}

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

.analytics-card {
  min-width: 0;
  border: var(--line-1);
  background: var(--surface);
  padding: var(--space-4);
}

.analytics-card--wide {
  margin: var(--space-3) 0 var(--space-5);
}

.analytics-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--ink);
}

.analytics-card__head h2 {
  margin: 0;
  font-size: var(--fs-xl);
}

.status-list,
.bar-chart {
  list-style: none;
  margin: 0;
  padding: 0;
}

.status-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: var(--line-1);
}

.status-list li:last-child {
  border-bottom: 0;
}

.status-list strong {
  font-family: var(--display);
  font-size: var(--fs-xl);
  font-variant-numeric: tabular-nums;
}

.bar-chart {
  display: grid;
  gap: var(--space-3);
  padding-top: var(--space-3);
}

.bar-chart__meta {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--fs-md);
}

.bar-chart__meta strong {
  font-variant-numeric: tabular-nums;
}

.bar-chart__track {
  height: 7px;
  margin-top: var(--space-1);
  background: var(--sunk);
  overflow: hidden;
}

.bar-chart__track span {
  display: block;
  height: 100%;
  min-width: 2px;
  background: var(--teal);
}

@media (max-width: 900px) {
  .metric-grid,
  .analytics-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 620px) {
  .metric-grid,
  .analytics-grid,
  .analytics-grid--statuses {
    grid-template-columns: minmax(0, 1fr);
  }

  .metric-card > strong {
    font-size: var(--fs-3xl);
  }
}

/* An inline proportion bar, for a table cell.
   Distinct from `.meter`, which is a padded card footer with its own border and
   looks wrong inside a row. This one is a bare track sized to the column and
   scaled to the LARGEST value in its own table rather than to 100% — on a size
   curve the interesting shape is the relative height of the middle sizes, and
   against a 100% axis every bar would be a stub. */
.bar {
  display: block;
  height: 10px;
  min-width: 60px;
  background: var(--sunk);
  border: var(--line-1);
  border-radius: var(--radius);
  overflow: hidden;
}

.bar__fill {
  display: block;
  height: 100%;
  background: var(--teal);
}
.capture-image {
  display: block;
  width: 100%;
  max-height: 38rem;
  object-fit: contain;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--sunk);
}

/* -------------------------------------------------------------------------
   10. The administrator's analytics, the order desk and marketing
   ---------------------------------------------------------------------- */

/* The date range: named presets as a row of small links, a custom pair of
   dates beside them, and the comparison period stated in words underneath.
   Shopify's picker is a popover; a row of links needs no script and prints. */
.ov-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-4);
}

.ov-range {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.ov-range__item {
  padding: var(--space-1) var(--space-2);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  font-size: var(--fs-sm);
}

.ov-range__item--current {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--surface);
}

.ov-custom {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-2);
}

.ov-custom label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.ov-compare {
  flex-basis: 100%;
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

/* Headline figures: the value, its movement against the period before, and
   one line saying what it counts. Four across; two on a tablet; one on a phone. */
.ov-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
}

.kpi {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.kpi__label {
  font-family: var(--display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

.kpi__value {
  font-family: var(--display);
  font-size: clamp(1.35rem, 2.4vw, 1.9rem);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.kpi > small {
  color: var(--muted);
  line-height: 1.35;
}

.kpi__delta {
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}

.kpi__delta--up {
  color: var(--teal);
  font-weight: 600;
}

.kpi__delta--down {
  color: var(--warn);
  font-weight: 600;
}

/* The card grid. Three across, the sales chart taking two. */
.ov-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
}

.ov-card {
  min-width: 0;
  display: flex;
  flex-direction: column;
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.ov-card--wide {
  grid-column: span 2;
}

.ov-card__head {
  padding: var(--space-3) var(--space-4) 0;
}

.ov-card__head h2 {
  margin: 0;
  font-size: var(--fs-base);
  font-weight: 600;
}

.ov-card__headline {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: var(--space-1) 0 0;
  font-family: var(--display);
  font-size: var(--fs-xl);
  font-variant-numeric: tabular-nums;
}

.ov-card__body {
  flex: 1;
  padding: var(--space-3) var(--space-4);
}

.ov-card__foot {
  padding: 0 var(--space-4) var(--space-3);
}

.ov-card .empty {
  margin: 0;
  color: var(--muted);
}

/* Charts are inline SVG drawn on the server; colour comes from the tokens so
   a chart and a pill say "good" in the same teal. */
.chart {
  display: block;
  width: 100%;
  height: auto;
}

.chart__grid {
  stroke: var(--hairline);
  stroke-width: 1;
}

.chart__tick {
  font-family: var(--mono);
  font-size: 15px;
  fill: var(--muted);
}

.chart__line {
  fill: none;
  stroke: var(--teal);
  stroke-width: 2.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.chart__line--before {
  stroke: var(--ink-3);
  stroke-width: 1.5;
  stroke-dasharray: 4 4;
}

.chart__dot {
  fill: var(--teal);
}

.chart__legend {
  display: flex;
  gap: var(--space-3);
  margin: var(--space-2) 0 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.chart__key::before {
  content: "";
  display: inline-block;
  width: 18px;
  height: 0;
  margin-right: 6px;
  border-top: 3px solid var(--teal);
  vertical-align: middle;
}

.chart__key--before::before {
  border-top: 2px dashed var(--ink-3);
}

.donut {
  display: grid;
  grid-template-columns: 140px minmax(0, 1fr);
  gap: var(--space-3);
  align-items: center;
}

.donut svg {
  width: 140px;
  height: 140px;
}

.donut__track {
  fill: none;
  stroke: var(--sunk);
  stroke-width: 16;
}

.donut__seg {
  fill: none;
  stroke-width: 16;
  transform: rotate(-90deg);
  transform-origin: 60px 60px;
}

.donut__seg--1 { stroke: var(--teal); }
.donut__seg--2 { stroke: var(--ink); }
.donut__seg--3 { stroke: var(--teal-deep); }
.donut__seg--4 { stroke: var(--ink-3); }

.donut__swatch--1 { background: var(--teal); }
.donut__swatch--2 { background: var(--ink); }
.donut__swatch--3 { background: var(--teal-deep); }
.donut__swatch--4 { background: var(--ink-3); }

.donut__total {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 600;
  fill: var(--ink);
}

.donut__legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.donut__legend li {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto auto;
  gap: var(--space-2);
  align-items: center;
  font-variant-numeric: tabular-nums;
}

.donut__legend small {
  color: var(--muted);
}

.donut__swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
}

.funnel {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
}

.funnel__step {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.funnel__label {
  font-size: var(--fs-sm);
  color: var(--muted);
}

.funnel__step strong {
  font-family: var(--display);
  font-size: var(--fs-lg);
  font-variant-numeric: tabular-nums;
}

.funnel__step small {
  color: var(--teal);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.funnel__bar {
  display: flex;
  align-items: flex-end;
  height: 110px;
  margin-top: var(--space-1);
  background: var(--sunk);
}

.funnel__bar span {
  display: block;
  width: 100%;
  background: var(--teal);
}

.ov-breakdown {
  display: flex;
  flex-direction: column;
  margin: 0;
}

.ov-breakdown > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--hairline);
}

.ov-breakdown dt,
.ov-breakdown dd {
  margin: 0;
}

.ov-breakdown dd {
  font-variant-numeric: tabular-nums;
}

.ov-breakdown__sub dt,
.ov-breakdown__sub dd {
  font-weight: 600;
}

.ov-breakdown__total {
  border-top: 2px solid var(--ink);
  font-weight: 700;
}

.ov-uncosted th,
.ov-uncosted td {
  color: var(--muted);
}

/* The order desk's four views, as tabs with their counts. */
.desk-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0 0 var(--space-4);
}

.desk-tabs__item {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
}

.desk-tabs__item strong {
  font-variant-numeric: tabular-nums;
}

.desk-tabs__item--current {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--surface);
}

.desk-tabs__item--bench {
  margin-left: auto;
}

.desk-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
}

.desk-actions form {
  margin: 0;
}

.desk-book {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-3) 0;
}

/* Marketing: a feed URL to copy, and the clicks to paste it. */
.mk-url {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0 0 var(--space-3);
}

.mk-url span {
  font-size: var(--fs-sm);
  color: var(--muted);
}

.mk-url input {
  width: 100%;
  padding: var(--space-2);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--sunk);
  font-family: var(--mono);
  font-size: var(--fs-sm);
}

.mk-steps {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0 0 var(--space-3);
  padding-left: 1.2em;
}

@media (max-width: 1100px) {
  .ov-kpis,
  .ov-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 700px) {
  .ov-kpis,
  .ov-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .ov-card--wide {
    grid-column: auto;
  }

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

  .donut {
    grid-template-columns: minmax(0, 1fr);
  }

  .desk-tabs__item--bench {
    margin-left: 0;
  }
}

.chart__key--now::before {
  border-top-color: var(--teal);
}

/* -------------------------------------------------------------------------
   Analytics overview — a quieter, Shopify-inspired working surface
   ---------------------------------------------------------------------- */
body:has(.analytics-workspace) {
  background: #f6f6f7;
}

.analytics-workspace {
  max-width: 1480px;
  margin-inline: auto;
  padding-bottom: 64px;
}

.analytics-workspace > .page-head {
  align-items: center;
  margin-bottom: 20px;
}

.analytics-workspace > .page-head h1 {
  font-size: clamp(1.75rem, 3vw, 2.35rem);
  letter-spacing: -.035em;
}

.analytics-workspace > .page-head .page-head__lede {
  max-width: 64ch;
}

.analytics-workspace .ov-toolbar {
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  padding: 14px;
  border: 1px solid #dedee3;
  border-radius: var(--radius);
  background: #fff;
  box-shadow: 0 1px 0 rgba(0,0,0,.03);
}

.analytics-workspace .ov-range {
  padding: 3px;
  border-radius: var(--radius);
  background: #f1f1f3;
}

.analytics-workspace .ov-range__item {
  padding: 7px 11px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: #4b4b50;
  font-weight: 550;
}

.analytics-workspace .ov-range__item--current {
  background: #fff;
  color: #202024;
  box-shadow: 0 1px 3px rgba(0,0,0,.13);
}

.analytics-workspace .ov-custom {
  margin-left: auto;
}

.analytics-workspace .ov-custom input {
  min-height: 36px;
  border-color: #c9c9cf;
  border-radius: var(--radius);
  background: #fff;
}

.analytics-workspace .ov-custom .btn {
  min-height: 36px;
  border-radius: var(--radius);
}

.analytics-workspace .ov-compare {
  padding-top: 2px;
  border-top: 1px solid #ececef;
}

.analytics-workspace .ov-kpis {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0;
  margin-bottom: 16px;
  overflow: hidden;
  border: 1px solid #dedee3;
  border-radius: var(--radius);
  background: #fff;
  box-shadow: 0 1px 0 rgba(0,0,0,.03);
}

.analytics-insight {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr) 340px;
  min-height: 174px;
  margin-bottom: 16px;
  overflow: hidden;
  border: 1px solid #dedee3;
  border-radius: var(--radius);
  background: #fff;
  box-shadow: 0 1px 0 rgba(0,0,0,.03);
}

.analytics-insight nav {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px;
  border-right: 1px solid #e4e4e8;
  background: #f6f6f7;
}

.analytics-insight nav strong,
.analytics-insight nav span {
  padding: 8px 10px;
  border-radius: var(--radius);
  font-size: .77rem;
}

.analytics-insight nav strong { background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.analytics-insight nav span { color: #65656a; }
.analytics-insight > div:nth-child(2) { align-self: center; padding: 24px; }
.analytics-insight__eyebrow { color: #68686e; font-size: .72rem; }
.analytics-insight h2 { margin: 6px 0 8px; font-family: inherit; font-size: 1rem; letter-spacing: -.01em; }
.analytics-insight p { max-width: 66ch; color: #56565b; font-size: .82rem; }

.analytics-insight__bars {
  display: flex;
  align-items: end;
  justify-content: center;
  gap: 22px;
  padding: 28px 22px;
}

.analytics-insight__bars i { width: 72px; height: 48%; background: #2ba6df; }
.analytics-insight__bars i:nth-child(2) { height: 76%; }
.analytics-insight__bars i:nth-child(3) { height: 60%; }

.analytics-workspace .kpi {
  min-height: 156px;
  padding: 19px 18px;
  border: 0;
  border-right: 1px solid #e6e6ea;
  border-radius: 0;
  box-shadow: none;
}

.analytics-workspace .kpi:last-child {
  border-right: 0;
}

.analytics-workspace .kpi__label {
  color: #68686e;
  font-family: inherit;
  font-size: .75rem;
  font-weight: 650;
  letter-spacing: 0;
  text-transform: none;
}

.analytics-workspace .kpi__value {
  margin-top: 6px;
  color: #1f1f23;
  font-size: clamp(1.3rem, 2vw, 1.8rem);
  letter-spacing: -.035em;
}

.analytics-workspace .kpi > small {
  margin-top: auto;
  color: #77777c;
  font-size: .72rem;
}

.analytics-workspace .kpi__delta {
  width: fit-content;
  margin-top: 2px;
  padding: 2px 6px;
  border-radius: var(--radius);
  background: #f1f1f3;
  font-size: .72rem;
}

.analytics-workspace .kpi__delta--up {
  background: #e6f5f0;
  color: #086b57;
}

.analytics-workspace .kpi__delta--down {
  background: #fff0ed;
  color: #a13629;
}

.analytics-pulse {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  margin-bottom: 16px;
  overflow: hidden;
  border: 1px solid #dedee3;
  border-radius: var(--radius);
  background: #dedee3;
}

.analytics-pulse > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 4px 12px;
  padding: 14px 18px;
  background: #fff;
}

.analytics-pulse span:first-child {
  color: #68686e;
  font-size: .78rem;
}

.analytics-pulse strong {
  grid-row: 2;
  font-size: 1.02rem;
}

.analytics-pulse .kpi__delta {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
}

.analytics-workspace .ov-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.analytics-workspace .ov-card {
  min-height: 320px;
  border: 1px solid #dedee3;
  border-radius: var(--radius);
  box-shadow: 0 1px 0 rgba(0,0,0,.03);
  overflow: hidden;
}

.analytics-workspace .ov-card--wide {
  grid-column: span 2;
  min-height: 390px;
}

.analytics-workspace .ov-card__head {
  padding: 20px 22px 0;
}

.analytics-workspace .ov-card__head h2 {
  color: #4d4d52;
  font-size: .84rem;
  font-weight: 650;
}

.analytics-workspace .ov-card__headline {
  margin-top: 7px;
  color: #1f1f23;
  font-size: 1.55rem;
  letter-spacing: -.03em;
}

.analytics-workspace .ov-card__body {
  padding: 18px 22px 22px;
}

.analytics-workspace .ov-card__foot {
  margin-top: auto;
  padding: 12px 22px 17px;
  border-top: 1px solid #eeeeF1;
  background: #fbfbfc;
}

.analytics-workspace .ref-link {
  color: #3569a8;
  font-size: .78rem;
  font-weight: 600;
}

.analytics-workspace .chart__line {
  stroke: #3569a8;
  stroke-width: 2.25;
}

.analytics-workspace .chart__dot {
  fill: #3569a8;
}

.analytics-workspace .chart__key::before {
  border-color: #3569a8;
}

.analytics-workspace .bar-chart__track span,
.analytics-workspace .funnel__bar span {
  background: #3569a8;
}

@media (max-width: 1180px) {
  .analytics-insight { grid-template-columns: 220px minmax(0, 1fr); }
  .analytics-insight__bars { display: none; }
  .analytics-workspace .ov-kpis {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .analytics-workspace .kpi:nth-child(3) {
    border-right: 0;
  }

  .analytics-workspace .kpi:nth-child(-n+3) {
    border-bottom: 1px solid #e6e6ea;
  }
}

@media (max-width: 760px) {
  .analytics-insight { grid-template-columns: minmax(0, 1fr); }
  .analytics-insight nav { border-right: 0; border-bottom: 1px solid #e4e4e8; }
  .analytics-workspace .ov-toolbar { align-items: stretch; }
  .analytics-workspace .ov-range { width: 100%; overflow-x: auto; flex-wrap: nowrap; }
  .analytics-workspace .ov-range__item { flex: 0 0 auto; }
  .analytics-workspace .ov-custom { width: 100%; margin-left: 0; }
  .analytics-workspace .ov-custom label { flex: 1 1 120px; }
  .analytics-workspace .ov-custom input { width: 100%; }
  .analytics-workspace .ov-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .analytics-workspace .kpi,
  .analytics-workspace .kpi:nth-child(3) { border-right: 1px solid #e6e6ea; border-bottom: 1px solid #e6e6ea; }
  .analytics-workspace .kpi:nth-child(even) { border-right: 0; }
  .analytics-workspace .kpi:nth-last-child(-n+2) { border-bottom: 0; }
  .analytics-pulse { grid-template-columns: minmax(0, 1fr); }
  .analytics-workspace .ov-grid { grid-template-columns: minmax(0, 1fr); }
  .analytics-workspace .ov-card--wide { grid-column: auto; }
}

/* Shopify-shaped order management. The retail site keeps Rambler branding;
   only the information architecture and working density follow the familiar
   admin reference. */
body:has(.commerce-admin-frame) {
  margin: 0;
  background: #f1f1f1;
  color: #202223;
}

body:has(.commerce-admin-frame) > .site-header,
body:has(.commerce-admin-frame) > .site-footer {
  display: none;
}

body:has(.commerce-admin-frame) > .page {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
}

.commerce-admin-frame {
  display: grid;
  grid-template-columns: 238px minmax(0, 1fr);
  grid-template-rows: 48px minmax(calc(100vh - 48px), auto);
  min-height: 100vh;
  background: #f1f1f1;
}

.commerce-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 220px minmax(280px, 640px) 1fr;
  align-items: center;
  gap: 18px;
  min-height: 48px;
  padding: 0 16px;
  background: #1a1a1a;
  color: #fff;
}

.commerce-wordmark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: #fff;
  text-decoration: none;
  font-size: 1rem;
}

.commerce-wordmark > span {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius);
  background: var(--yellow);
  color: #111;
  font-weight: 900;
}

.commerce-global-search {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 34px;
  padding: 0 12px;
  border: 1px solid #555;
  border-radius: var(--radius);
  background: #303030;
  color: #e8e8e8;
  text-decoration: none;
  font-size: .875rem;
}

.commerce-admin-user {
  display: grid;
  grid-template-columns: 32px auto;
  grid-template-rows: auto auto;
  align-items: center;
  justify-self: end;
  column-gap: 9px;
  line-height: 1.1;
  color: #fff;
  text-decoration: none;
}

.commerce-admin-user > span:last-child { display: grid; gap: 2px; }
.commerce-admin-user strong { font-size: .8rem; }
.commerce-admin-user small { color: #aaa; font-size: .68rem; }
.commerce-admin-avatar {
  grid-row: 1 / span 2;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius);
  background: #8a3ffc;
  font-size: .72rem;
  font-weight: 750;
}

.commerce-sidebar {
  position: sticky;
  top: 48px;
  align-self: start;
  height: calc(100vh - 48px);
  padding: 14px 10px;
  background: #ebebeb;
  border-right: 1px solid #dedede;
  overflow-y: auto;
}

.commerce-sidebar > a,
.commerce-subnav a {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 34px;
  padding: 6px 10px;
  border-radius: var(--radius);
  color: #303030;
  text-decoration: none;
  font-size: .875rem;
}

.commerce-sidebar > a span:not(.commerce-nav-icon) { flex: 1; }
.commerce-nav-icon {
  flex: 0 0 16px;
  width: 16px;
  color: #515151;
  text-align: center;
  font-size: .9rem;
}
.commerce-sidebar > a strong {
  min-width: 28px;
  padding: 2px 7px;
  border-radius: var(--radius);
  background: #ddd;
  font-size: .75rem;
  text-align: center;
}

.commerce-sidebar a:hover,
.commerce-sidebar a.is-current {
  background: #ddd;
  color: #151515;
}

.commerce-sidebar a.is-current { font-weight: 650; }
.commerce-subnav { margin: -2px 0 10px 31px; }
.commerce-subnav a { min-height: 28px; padding: 4px 9px; color: #626262; }

.commerce-sidebar__channels {
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid #d8d8d8;
}

.commerce-sidebar__channels > span {
  display: block;
  padding: 0 10px 7px;
  color: #6b6b6b;
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.commerce-sidebar__channels a {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 32px;
  padding: 5px 10px;
  border-radius: var(--radius);
  color: #3f3f3f;
  text-decoration: none;
  font-size: .82rem;
}

.commerce-admin-content {
  min-width: 0;
  padding: 20px 28px 48px;
}

.commerce-admin-content .orders-workspace,
.commerce-admin-content > .page-head,
.commerce-admin-content > .index,
.commerce-admin-content > .abandoned-consent-note,
.commerce-admin-content > .note {
  width: min(100%, 1500px);
  max-width: none;
  margin-inline: auto;
}

.commerce-admin-content .page-head { margin-bottom: 10px; }
.commerce-admin-content .page-head h1 {
  font-size: 1.25rem;
  letter-spacing: -.02em;
}

.admin-home-workspace,
.admin-products-workspace,
.admin-discounts-workspace,
.marketing-workspace {
  width: min(100%, 1500px);
  margin-inline: auto;
}

.admin-home-workspace .tiles {
  overflow: hidden;
  gap: 0;
  border: 1px solid #d8d8d8;
  border-radius: var(--radius);
  background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,.06);
}

.admin-home-workspace .tile {
  min-height: 128px;
  border: 0;
  border-right: 1px solid #e4e4e4;
  border-radius: 0;
  background: #fff;
  box-shadow: none;
}

.admin-home-workspace .tile:last-child { border-right: 0; }
.admin-home-workspace .tile__label { color: #666; font-size: .73rem; letter-spacing: 0; text-transform: none; }
.admin-home-workspace .tile__value { font-size: 1.65rem; letter-spacing: -.04em; }
.admin-home-workspace .tile__note { color: #777; font-size: .74rem; }

.marketing-workspace .ov-kpis { margin-bottom: 16px; }
.marketing-workspace .analytics-grid { gap: 16px; }
.marketing-workspace .card {
  border-color: #dedee3;
  border-radius: var(--radius);
  background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,.05);
}

.marketing-workspace .mk-url input {
  border-color: #c9c9cf;
  background: #f7f7f8;
}

.commerce-admin-content .page-head .actions { gap: 8px; }
.commerce-admin-content .page-head .btn {
  min-height: 32px;
  padding: 5px 12px;
  border-radius: var(--radius);
  font-size: .8rem;
}

.commerce-admin-content .btn--primary {
  border-color: #303030;
  background: #303030;
  color: #fff;
}

.commerce-admin-content .index {
  border-color: #d7d7d7;
  border-radius: var(--radius);
  box-shadow: 0 1px 1px rgba(0,0,0,.04), 0 1px 4px rgba(0,0,0,.08);
}

.commerce-admin-content .index__tabs {
  padding: 5px 12px 0;
  background: #fff;
}

.commerce-admin-content .index__tab {
  min-height: 38px;
  padding: 8px 11px;
  border-radius: var(--radius);
  font-size: .82rem;
}

.commerce-admin-content .index__tab--current { border-bottom-color: #303030; }
.commerce-admin-content .index__search { flex-wrap: nowrap; padding: 9px 12px; background: #fff; }
.commerce-admin-content .index__search input[type="search"] {
  min-height: 34px;
  border-radius: var(--radius);
  font-size: .84rem;
}

.commerce-admin-content .index-table thead th {
  height: 36px;
  padding: 8px 12px;
  background: #f7f7f7;
  color: #555;
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}

.commerce-admin-content .index-table tbody th,
.commerce-admin-content .index-table tbody td {
  padding: 10px 12px;
  background: #fff;
  font-size: .8rem;
}

.commerce-admin-content .index-table__ref { color: #1d1d1d; font-weight: 700; }
.commerce-admin-content .index__count { display: none; }
.commerce-admin-content .index__foot { justify-content: flex-end; min-height: 46px; background: #fff; }

.abandoned-search {
  flex: 1;
  min-height: 34px;
  padding: 7px 11px;
  border: 1px solid #c9c9c9;
  border-radius: var(--radius);
  color: #777;
  background: #fff;
  font-size: .84rem;
}

.abandoned-consent-note {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid #ddd;
  border-radius: var(--radius);
  background: #fff;
  color: #626262;
  font-size: .8rem;
}

@media (max-width: 900px) {
  .commerce-admin-frame { grid-template-columns: 72px minmax(0, 1fr); }
  .commerce-topbar { grid-template-columns: 54px minmax(180px, 1fr) auto; }
  .commerce-wordmark strong,
  .commerce-sidebar > a span,
  .commerce-sidebar > a strong,
  .commerce-subnav,
  .commerce-admin-user strong,
  .commerce-admin-user small { display: none; }
  .commerce-sidebar > a { justify-content: center; font-size: 1.1rem; }
  .commerce-admin-content { padding-inline: 14px; }
}

@media (max-width: 620px) {
  .commerce-admin-frame { display: block; padding-top: 48px; }
  .commerce-topbar { position: fixed; inset: 0 0 auto; grid-template-columns: 44px 1fr auto; }
  .commerce-sidebar {
    position: static;
    display: flex;
    gap: 4px;
    width: 100%;
    height: auto;
    overflow-x: auto;
    padding: 7px;
    border-right: 0;
    border-bottom: 1px solid #d8d8d8;
    scrollbar-width: thin;
  }
  .commerce-sidebar > a { flex: 0 0 auto; min-width: 48px; }
  /* Sales channels repeat destinations already present in the main strip. On
     a phone the nested block made the horizontal navigation two hundred pixels
     tall and pushed the workspace sideways. Keep the primary icons and remove
     only the duplicate channel group at this breakpoint. */
  .commerce-sidebar__channels { display: none; }
  .commerce-admin-content { padding: 14px 10px 36px; }
  .commerce-admin-content .page-head { align-items: flex-start; }
  .commerce-admin-content .index__search { flex-wrap: wrap; }
}

/* -------------------------------------------------------------------------
   Shopify-inspired order workspace

   The useful pattern is hierarchy, not imitation: a quiet canvas, saved
   views, one readable row per order and a single action at the right edge.
   Rambler's payment, courier and Zoho facts remain visible without becoming
   ten equally loud columns.
   ---------------------------------------------------------------------- */

body:has(.orders-workspace) {
  background: #f4f5f7;
}

.orders-workspace {
  max-width: 1560px;
  margin-inline: auto;
}

.orders-workspace > .page-head {
  align-items: center;
  margin-bottom: var(--space-4);
}

.orders-workspace .page-head__text {
  max-width: 78ch;
}

.orders-workspace .desk-tabs {
  margin: 0;
  padding: 0 var(--space-3);
  gap: var(--space-1);
  border: var(--line-1);
  border-bottom: 0;
  border-radius: var(--radius);
  background: var(--surface);
}

.orders-workspace .desk-tabs__item {
  position: relative;
  min-height: 46px;
  padding: 0 var(--space-3);
  border: 0;
  border-radius: 0;
  color: var(--ink-3);
}

.orders-workspace .desk-tabs__item:hover {
  color: var(--ink);
  background: var(--card);
}

.orders-workspace .desk-tabs__item--current {
  color: var(--ink);
  background: transparent;
  font-weight: 700;
}

.orders-workspace .desk-tabs__item--current::after {
  content: "";
  position: absolute;
  inset: auto var(--space-3) -1px;
  height: 3px;
  border-radius: var(--radius);
  background: var(--teal);
}

.orders-workspace .desk-tabs__item strong {
  min-width: 22px;
  padding: 2px 7px;
  border-radius: var(--radius);
  background: #eceef1;
  color: var(--ink-2);
  font-size: var(--fs-xs);
  text-align: center;
}

.orders-workspace .table-scroll {
  border-radius: var(--radius);
  border-color: #d8dadd;
  box-shadow: 0 1px 2px rgb(20 24 32 / 8%);
}

.order-desk-table {
  min-width: 1050px;
}

.order-desk-table thead th {
  padding-block: 11px;
  background: #f7f7f8;
  border-bottom-color: #d8dadd;
  color: #50545b;
  font-size: var(--fs-xs);
  text-transform: none;
  letter-spacing: .01em;
}

.order-desk-table tbody th,
.order-desk-table tbody td {
  padding: 14px 12px;
  background: var(--surface);
  border-bottom-color: #e4e5e7;
  vertical-align: middle;
}

.order-desk-table tbody tr:hover > * {
  background: #f6faf9;
}

.order-desk-ref {
  color: var(--teal-deep);
  font-weight: 750;
  text-decoration: none;
}

.order-desk-ref:hover,
.order-desk-open a:hover {
  text-decoration: underline;
}

.order-desk-open {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}

.order-desk-open a {
  color: var(--ink);
  font-weight: 700;
  text-decoration: none;
}

.order-desk-table .pill {
  min-height: 24px;
  padding-inline: 9px;
  border-radius: var(--radius);
  white-space: nowrap;
}

@media (max-width: 720px) {
  .orders-workspace > .page-head .actions,
  .orders-workspace > .page-head .actions .btn {
    width: 100%;
  }

  .orders-workspace .desk-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
  }

  .orders-workspace .desk-tabs__item {
    flex: 0 0 auto;
  }
}

body:has(.order-detail-workspace) {
  background: #f4f5f7;
}

.order-detail-workspace {
  width: min(100%, 1280px);
  margin-inline: auto;
}

.order-detail-workspace > .page-head {
  align-items: center;
  margin-bottom: var(--space-5);
}

.order-detail-workspace > .doc-meta,
.order-detail-workspace > .panel,
.order-detail-workspace > .section-block,
.order-detail-workspace > .table-scroll {
  border: 1px solid #d8dadd;
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 1px 2px rgb(20 24 32 / 7%);
}

.order-detail-workspace > .panel,
.order-detail-workspace > .section-block {
  margin-top: var(--space-4);
  padding: var(--space-5);
}

.order-detail-workspace > .table-scroll {
  margin-top: var(--space-4);
}

.order-detail-workspace > .section-block .section-head {
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid #e4e5e7;
}

.order-detail-workspace .doc-meta {
  overflow: hidden;
}

.order-detail-workspace .data-table thead th {
  background: #f7f7f8;
  color: #50545b;
}

@media (min-width: 1100px) {
  .order-detail-workspace > .doc-meta {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* One order on the desk: the row the tabs and counts are about. */
.order-desk-row > th,
.order-desk-row > td {
  vertical-align: top;
}

/* -------------------------------------------------------------------------
   11. The index and the order document, Shopify-shaped
   ----------------------------------------------------------------------
   The orders and customers indexes are drawn the way Shopify's admin draws
   them because that is the screen the owner has read every morning for
   years: tabs across the top of one white panel, a search row, the table,
   and "1-50 of 458" at the foot. The order page is Shopify's two columns.
   Nothing here is a new colour: badges are the status washes app.css
   already has, and the yellow stays on the commit button. */

.index {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  overflow: hidden;
}

.index__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-2);
  padding: var(--space-2) var(--space-3) 0;
  border-bottom: 1px solid var(--hairline);
}

.index__tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-2) var(--space-3);
  margin-bottom: -1px;
  color: var(--ink-2);
  text-decoration: none;
  font-weight: 500;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.index__tab:hover {
  color: var(--ink);
  background: var(--card);
}

.index__tab--current {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--ink);
}

.index__count {
  font-size: var(--fs-xs);
  color: var(--ink-3);
  background: var(--sunk);
  border-radius: var(--radius);
  padding: 1px 6px;
  font-variant-numeric: tabular-nums;
}

.index__search {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  padding: var(--space-3);
  border-bottom: 1px solid var(--hairline);
  margin: 0;
}

.index__search input[type="search"] {
  flex: 1 1 260px;
  min-width: 0;
}

.index__search select {
  min-height: 38px;
}

.index__clear {
  font-size: var(--fs-md);
}

.index .table-scroll {
  border: 0;
  border-radius: 0;
}

.index-table th,
.index-table td {
  white-space: nowrap;
  vertical-align: middle;
}

.index-table__ref {
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
}

.index-table__ref:hover {
  text-decoration: underline;
}

.index-table__row--cancelled .index-table__ref {
  text-decoration: line-through;
  color: var(--muted);
}

.index-table__date {
  color: var(--ink-2);
}

.index-table__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-width: 260px;
  white-space: normal;
}

.tag {
  display: inline-block;
  font-size: var(--fs-xs);
  line-height: 1.5;
  padding: 0 6px;
  background: var(--sunk);
  color: var(--ink-2);
  border-radius: var(--radius);
  white-space: nowrap;
}

.index__foot {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--hairline);
}

.index__pager {
  display: inline-flex;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  overflow: hidden;
}

.index__page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 30px;
  color: var(--ink);
  text-decoration: none;
  font-size: var(--fs-xl);
  line-height: 1;
}

.index__page + .index__page {
  border-left: 1px solid var(--hairline-strong);
}

.index__page:hover {
  background: var(--card);
}

.index__page--off {
  color: var(--hairline-strong);
}

.index__range {
  margin: 0;
  font-size: var(--fs-md);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

/* Status badges. The mark says how far along: a filled dot is done, a ring
   is not started, a half ring is part way. The wash says whether a person
   is needed: attention (amber) or critical (red); neutral is grey. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1;
  padding: 4px 8px 4px 6px;
  border-radius: var(--radius);
  background: var(--sunk);
  color: var(--ink-2);
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: var(--radius);
  border: 2px solid currentColor;
  box-sizing: border-box;
  flex: 0 0 auto;
}

.badge--complete::before {
  background: currentColor;
}

.badge--incomplete::before {
  background: transparent;
}

.badge--partial::before {
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
}

.badge--none::before {
  display: none;
}

.badge--attention,
.badge--warning {
  background: var(--warn-wash);
  color: var(--warn);
}

.badge--critical {
  background: var(--danger-wash);
  color: var(--danger);
}

.badge--success {
  background: var(--ok-wash);
  color: var(--ok);
}

/* The order document: main column and aside. */
.od-columns {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}

.od-main,
.od-aside {
  display: grid;
  gap: var(--space-4);
  min-width: 0;
}

.od-card .ov-card__head h2 {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-lg);
}

.od-card__count {
  font-family: var(--display);
}

.od-card__actions {
  display: grid;
  gap: var(--space-3);
}

.od-card__actions .doc-meta {
  margin: 0;
}

.od-lines {
  list-style: none;
  margin: 0;
  padding: 0;
}

.od-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--space-2) var(--space-4);
  align-items: center;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--hairline);
}

.od-line:last-child {
  border-bottom: 0;
}

.od-line__what {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.od-line__variant {
  display: inline-block;
  align-self: flex-start;
  font-size: var(--fs-xs);
  padding: 0 6px;
  background: var(--sunk);
  color: var(--ink-2);
  border-radius: var(--radius);
}

.od-line__price {
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.od-line__total {
  font-weight: 600;
  white-space: nowrap;
}

.od-line__cost {
  grid-column: 1 / -1;
  font-size: var(--fs-sm);
  color: var(--ink-3);
}

.od-money {
  display: grid;
  gap: var(--space-2);
  margin: 0;
}

.od-money > div {
  display: grid;
  grid-template-columns: 9rem minmax(0, 1fr) auto;
  gap: var(--space-3);
  align-items: baseline;
}

.od-money dt {
  font-weight: 500;
}

.od-money dd {
  margin: 0;
}

.od-money__note {
  color: var(--ink-3);
  font-size: var(--fs-md);
}

.od-money__total,
.od-money__paid {
  padding-top: var(--space-2);
  border-top: 1px solid var(--hairline);
}

.od-money__total dt,
.od-money__total dd:last-child {
  font-weight: 700;
}

.od-side .ov-card__body {
  display: block;
}

.od-side__title {
  font-size: var(--fs-lg);
  margin: 0 0 var(--space-2);
}

.od-side__sub {
  font-family: var(--body);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--ink-2);
  margin: var(--space-4) 0 var(--space-1);
}

.od-side p {
  margin: 0 0 var(--space-2);
}

.od-side__address {
  white-space: normal;
}

.od-notes {
  margin: 0;
  display: grid;
  gap: var(--space-2);
}

.od-notes dt {
  font-size: var(--fs-sm);
  color: var(--ink-3);
}

.od-notes dd {
  margin: 0;
}

.od-despatch {
  margin: 0 0 var(--space-3);
}

.od-timeline {
  list-style: none;
  margin: 0;
  padding: 0 0 0 var(--space-4);
  border-left: 2px solid var(--hairline);
  display: grid;
  gap: var(--space-3);
}

.od-timeline li {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
}

.od-timeline li::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--space-4) - 6px);
  top: 6px;
  width: 10px;
  height: 10px;
  border-radius: var(--radius);
  background: var(--hairline-strong);
}

.od-timeline__text {
  flex: 1 1 200px;
  min-width: 0;
}

.od-timeline__at {
  color: var(--muted);
  font-size: var(--fs-sm);
  white-space: nowrap;
}

@media (min-width: 960px) {
  .od-columns {
    grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
  }
}

@media (max-width: 640px) {
  .od-line {
    grid-template-columns: minmax(0, 1fr);
  }

  .od-money > div {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .od-money__note {
    grid-column: 1 / -1;
    order: 3;
  }
}

/* -------------------------------------------------------------------------
   12. Customers, Shopify-shaped (see src/views/customers.ts)
   ---------------------------------------------------------------------- */

/* =========================================================================
   Rambler Safety — the customer screens
   =========================================================================

   The layer src/views/customers.ts needs on top of public/app.css and
   public/admin.css. Written as its own file so it can be merged into
   admin.css by hand; nothing here redefines anything those two already own.

   It reuses the shared vocabulary wherever the shared vocabulary already says
   the right thing — .data-table, .ov-card, .ov-kpis, .kpi, .btn, .muted,
   .numeric — and adds only what is specific to a customer:

     .cust-tabs      the segment tabs with their counts
     .cust-filters   search and sort, one GET form
     .cust-table     the index table, name over email
     .cust-badge     Shopify's small dotted label for a consent state
     .cust-pager     "1-50 of 2,033" between two arrows
     .cust-layout    the detail page's two columns
     .cust-card      the contact card in the narrow column

   THE RULES THE REST OF THE SYSTEM KEEPS, KEPT HERE
   -------------------------------------------------
   1. No new colours. Every value is a token from BRAND_TOKENS
      (src/platform/html.ts) or a hairline shorthand from app.css.
   2. Every radius is var(--radius), var(--radius-control),
      var(--radius-panel) or 0. A test enforces it.
   3. Sentence case. Uppercase only below 11px with letter-spacing.
   4. Figures are tabular and right-aligned.
   5. The two columns become one under 900px: staff read these off phones.
   ========================================================================= */

/* -------------------------------------------------------------------------
   Segment tabs — All, New, Returning, Email subscribers, Trade accounts
   ---------------------------------------------------------------------- */

.cust-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0 0 var(--space-3);
}

.cust-tabs__item {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
}

.cust-tabs__item strong {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.cust-tabs__item--current {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--surface);
}

.cust-tabs__item--current strong {
  color: var(--surface);
}

/* -------------------------------------------------------------------------
   Search and sort
   ---------------------------------------------------------------------- */

.cust-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}

.cust-filters__search {
  flex: 1 1 260px;
  min-width: 0;
}

.cust-filters__search input {
  width: 100%;
}

.cust-filters__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--ink-2);
  font-size: var(--fs-sm);
}

/* -------------------------------------------------------------------------
   The index table
   ---------------------------------------------------------------------- */

.cust-table {
  width: 100%;
}

/* Name over email, the way Shopify stacks them: the email is the thing that
   tells two people with the same name apart, so it is never truncated away. */
.cust-cell-name {
  min-width: 220px;
}

.cust-name {
  display: block;
  font-weight: 600;
  color: var(--ink);
}

.cust-name__email {
  display: block;
  color: var(--muted);
  font-size: var(--fs-sm);
  word-break: break-word;
}

/* -------------------------------------------------------------------------
   The consent badge
   ---------------------------------------------------------------------- */

/* Shopify's label: a small grey rounded chip with a dot. Green — the shared
   success token, not a new hue — only when the consent is an actual yes,
   because that is the one state that permits an email to be sent. */
.cust-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 1px var(--space-2);
  min-height: 22px;
  border: 1px solid currentColor;
  border-radius: var(--radius);
  background: var(--card);
  color: var(--muted);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
}

.cust-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  flex: 0 0 auto;
  background: currentColor;
  border-radius: var(--radius);
}

.cust-badge--on {
  color: var(--ok);
  background: var(--ok-wash);
}

/* -------------------------------------------------------------------------
   Pagination
   ---------------------------------------------------------------------- */

.cust-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
}

.cust-pager__count {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

.cust-pager__step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  min-height: 34px;
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
}

.cust-pager__step--off {
  color: var(--hairline-strong);
  background: var(--sunk);
}

/* -------------------------------------------------------------------------
   The detail page
   ---------------------------------------------------------------------- */

.cust-sub {
  margin: 0;
  color: var(--ink-2);
}

/* Shopify's customer summary is three figures, not four. */
.cust-figures {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.cust-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  align-items: start;
  gap: var(--space-3);
}

.cust-layout__main {
  display: grid;
  gap: var(--space-3);
  min-width: 0;
}

.cust-layout__side {
  min-width: 0;
}

/* The contact card's five labelled blocks. */
.cust-block + .cust-block {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: var(--line-1);
}

.cust-block h3 {
  margin: 0 0 var(--space-1);
  font-size: var(--fs-base);
  font-weight: 600;
}

.cust-block p {
  margin: 0 0 var(--space-1);
  line-height: 1.5;
  word-break: break-word;
}

.cust-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

/* The last order: its date and states, its lines, then what it came to. */
.cust-order-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  color: var(--ink-2);
  font-size: var(--fs-sm);
}

.cust-lines {
  width: 100%;
}

.cust-totals {
  margin: var(--space-3) 0 0;
  padding-top: var(--space-2);
  border-top: var(--line-1);
}

.cust-totals > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 2px 0;
}

.cust-totals dt {
  color: var(--ink-2);
}

.cust-totals dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.cust-totals__grand {
  margin-top: var(--space-1);
  padding-top: var(--space-2);
  border-top: 2px solid var(--ink);
  font-weight: 600;
}

.cust-orders {
  width: 100%;
}

/* -------------------------------------------------------------------------
   Responsive — one column on a narrow screen
   ---------------------------------------------------------------------- */

@media (max-width: 900px) {
  .cust-layout {
    grid-template-columns: minmax(0, 1fr);
  }

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

@media (max-width: 560px) {
  .cust-figures {
    grid-template-columns: minmax(0, 1fr);
  }

  .cust-filters__sort {
    flex: 1 1 100%;
  }

  .cust-pager {
    justify-content: space-between;
  }
}

/* -------------------------------------------------------------------------
   13. Reports, Shopify-shaped (see src/views/analytics-reports.ts)
   ---------------------------------------------------------------------- */

/* =========================================================================
   THE REPORTS LIBRARY
   =========================================================================

   Everything the reports screens need that admin.css did not already have.
   Which is very little on purpose: the date toolbar is `.ov-toolbar` /
   `.ov-range` / `.ov-custom` / `.ov-compare`, the chart card is `.ov-card`,
   the tables are `.data-table` inside `.table-scroll--pane`, and the buttons,
   notes and empty states are the shared ones. What is left is the library's
   own furniture — the search row, the section headings, and the two cells
   that carry a report's name and the sentence explaining it.

   RULES THIS FILE KEEPS, the same as admin.css:
     - every colour comes from a token, never a literal;
     - every border-radius is var(--radius) or 0, per the brand;
     - uppercase only at var(--fs-xs) with letter-spacing, and only on labels;
     - focus outlines are never removed.
   ====================================================================== */

/* The search row: one field, one button, and a way back to the whole list.
   A GET form, so the result has a URL that can be shared or printed. */
.rep-search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
}

.rep-search label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.rep-search__input {
  flex: 1 1 260px;
  min-width: 0;
  max-width: 420px;
  padding: var(--space-1) var(--space-2);
  border: var(--line-1);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-sm);
}

.rep-count {
  margin: 0 0 var(--space-4);
  color: var(--muted);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

/* One block per category. The heading names the section the way Shopify's
   library does; the line under it says what the section is for, so a reader
   choosing between "Sales" and "Finances" does not have to open both. */
.rep-section {
  margin: 0 0 var(--space-5);
}

.rep-section h2 {
  margin: 0 0 var(--space-1);
  font-size: var(--fs-lg);
  color: var(--ink);
}

.rep-section__note {
  margin: 0 0 var(--space-2);
  color: var(--muted);
  font-size: var(--fs-sm);
}

/* The listing table. The name column is the link and stays narrow; the
   sentence beside it is allowed to be long, and the section tag is the quiet
   third column that makes a filtered list still say where each row came from. */
.rep-table .rep-name {
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-strong);
}

.rep-table .rep-name:hover,
.rep-table .rep-name:focus-visible {
  color: var(--teal-deep);
  border-bottom-color: var(--teal-deep);
}

.rep-table .rep-why {
  color: var(--ink-2);
  max-width: 62ch;
}

.rep-table .rep-tag {
  color: var(--muted);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
}

/* The chart above a report's table. `.ov-card--wide` already gives it the full
   grid width on the overview; here it stands alone, so it needs its own
   bottom margin and nothing else. */
.rep-chart {
  margin: 0 0 var(--space-4);
}

/* The export sits in the page head's actions, beside the title. */
.rep-export {
  white-space: nowrap;
}

@media (max-width: 720px) {
  .rep-search label {
    flex-basis: 100%;
  }

  .rep-search__input {
    max-width: none;
  }

  .rep-table .rep-tag {
    display: none;
  }
}
