/* Component styles for shared/ui.html, ported from
 * ~/Projects/fuel-trading-system (app/static/css/app.css).
 *
 * Every value here comes from tokens.css. There are no colour literals in this
 * file and there should never be: it is the first stylesheet written after the
 * token layer landed, so it is the one that has no excuse.
 *
 * Loaded after styles.css so a converted page wins over the legacy rules
 * without either sheet having to know about the other.
 */

/* ── status badges ─────────────────────────────────────────────────────────
 * Scoped to `.badge.badge-*` on purpose. A bare `.badge-ok` already exists in
 * admin/dashboard.html as a local class, and a single-class selector here
 * would have reached inside it.
 */
.badge.badge-ok,
.badge.badge-info,
.badge.badge-warn,
.badge.badge-danger,
.badge.badge-neutral {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 3px var(--s-2);
  border: 1px solid transparent;
  /* A pill, and sentence case. The reference writes a state the way a sentence
     would — `Active`, `Loaded`, `Partially paid` — and reserves uppercase
     letter-spacing for section labels, where it means "this is a heading"
     rather than "this is shouting". */
  border-radius: var(--r-pill);
  font-size: var(--fs-11);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}

/* The dot is not decoration: it is the second channel that keeps status
 * legible without colour (WCAG 2.2 §1.4.1). Never remove it. */
.badge > .dot {
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: var(--r-pill);
  background: currentColor;
}

.badge.badge-ok      { background: var(--pos-50);  border-color: var(--pos-200);  color: var(--pos-700); }
.badge.badge-info    { background: var(--info-50); border-color: var(--info-200); color: var(--info-700); }
.badge.badge-warn    { background: var(--warn-50); border-color: var(--warn-200); color: var(--warn-700); }
.badge.badge-danger  { background: var(--neg-50);  border-color: var(--neg-200);  color: var(--neg-700); }
.badge.badge-neutral { background: var(--bg-sunken); border-color: var(--border); color: var(--text-muted); }

.badge.badge-sm { padding: 1px var(--s-1); font-size: var(--fs-11); }

/* ── document header ─────────────────────────────────────────────────────── */
.document-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s-4) var(--s-6);
  margin-bottom: var(--s-4);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--border);
}
.document-type {
  color: var(--text-subtle);
  font-size: var(--fs-11);
  font-weight: var(--fw-semibold);
  letter-spacing: .07em;
  text-transform: uppercase;
}
.document-title-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-1);
}
/* The document number is the identity of the record, so it is set in the mono
 * face with tabular figures: two numbers that differ by one character have to
 * look different at a glance. */
.document-title-row h1 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-22);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  color: var(--text);
}
.document-subtitle { margin: var(--s-2) 0 0; color: var(--text-muted); font-size: var(--fs-13); }
.document-subtitle a { color: var(--brand-600); text-decoration: none; }
.document-subtitle a:hover { text-decoration: underline; }

.document-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
  gap: var(--s-3) var(--s-6);
  align-items: start;
}
.document-fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.document-fact-label {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  color: var(--text-subtle);
  font-size: var(--fs-11);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.document-fact-value {
  color: var(--text);
  font-size: var(--fs-13);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.document-fact-value a { color: var(--brand-600); text-decoration: none; }
.document-fact-value a:hover { text-decoration: underline; }

/* A derived value must not look editable. The tint and the rule say "this was
 * computed"; document-fact-source says what from. */
.document-fact.is-calculated .document-fact-value {
  padding: 2px var(--s-2);
  border-left: 2px solid var(--fin-border);
  background: var(--fin-bg);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.document-fact-calc { color: var(--text-subtle); font-size: var(--fs-11); }
.document-fact-source { color: var(--text-subtle); font-size: var(--fs-11); }

/* ── action bar ──────────────────────────────────────────────────────────── */
.document-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-4);
  margin-bottom: var(--s-4);
}
.document-action-group { display: flex; align-items: center; gap: var(--s-2); }
.document-action-label {
  color: var(--text-subtle);
  font-size: var(--fs-11);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.document-action-controls { display: flex; align-items: center; gap: var(--s-2); }
.document-action-controls > form { display: inline-flex; margin: 0; }
/* Destructive actions are pushed to the end of the bar and separated, so
 * "Cancel this document" is never adjacent to the primary action. */
.document-action-group.is-destructive {
  margin-left: auto;
  padding-left: var(--s-4);
  border-left: 1px solid var(--border);
}

/* ── two-column document layout ──────────────────────────────────────────── */
.document-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(250px, 300px);
  align-items: start;
  gap: var(--s-4);
}
.document-main, .factbox-pane { min-width: 0; }
.factbox-pane {
  position: sticky;
  top: calc(var(--topbar-h) + var(--s-4));
  display: grid;
  gap: var(--s-3);
}
@media (max-width: 1200px) {
  .document-layout { grid-template-columns: minmax(0, 1fr); }
  .factbox-pane { position: static; }
}

/* ── FastTab ─────────────────────────────────────────────────────────────── */
.fasttab {
  margin-bottom: var(--s-3);
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-surface);
}
.fasttab > summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--s-3);
  min-height: 46px;
  padding: var(--s-3) var(--s-4);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.fasttab > summary::-webkit-details-marker { display: none; }
.fasttab > summary:hover { background: var(--bg-hover); }
.fasttab > summary:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.fasttab-title { font-size: var(--fs-13); font-weight: var(--fw-semibold); color: var(--text); }
.fasttab-hint { color: var(--text-subtle); font-size: var(--fs-11); }
.fasttab-chevron { color: var(--text-subtle); transition: transform var(--dur-fast) var(--ease); }
.fasttab[open] .fasttab-chevron { transform: rotate(180deg); }
.fasttab-body { padding: var(--s-4); border-top: 1px solid var(--border); }
.fasttab-body.flush { padding: 0; }

/* ── FactBox ─────────────────────────────────────────────────────────────── */
.factbox {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-surface);
}
.factbox-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border);
  background: var(--bg-sunken);
}
.factbox-head h2 {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-muted);
}
.factbox-hint { color: var(--text-subtle); font-size: var(--fs-11); }
.factbox-body { padding: var(--s-3) var(--s-4); }
.factbox-empty { margin: 0; color: var(--text-subtle); font-size: var(--fs-12); }
.factbox-foot-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  margin-top: var(--s-3);
  color: var(--brand-600);
  font-size: var(--fs-12);
  text-decoration: none;
}
.factbox-foot-link:hover { text-decoration: underline; }

/* ── related documents ───────────────────────────────────────────────────── */
.related-list { display: grid; gap: var(--s-1); }
.related-link {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2);
  border-radius: var(--r-sm);
  color: var(--text);
  text-decoration: none;
}
.related-link:hover { background: var(--bg-hover); }
.related-link-copy { display: flex; flex-direction: column; min-width: 0; }
.related-link-copy strong { font-size: var(--fs-13); font-weight: var(--fw-medium); }
.related-link-copy small { color: var(--text-subtle); font-size: var(--fs-11); }
.related-chevron { color: var(--text-subtle); }

/* ── attachments ─────────────────────────────────────────────────────────── */
.attachment-upload { display: grid; gap: var(--s-2); margin-bottom: var(--s-3); }
.attachment-upload input[type="text"] {
  width: 100%;
  min-height: var(--control-h);
  padding: 0 var(--s-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-surface);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-12);
}
.attachment-picker {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-sm);
  color: var(--text-muted);
  font-size: var(--fs-12);
  cursor: pointer;
}
.attachment-picker:hover { border-color: var(--brand-600); color: var(--brand-600); }
.attachment-list { display: grid; gap: var(--s-2); }
.attachment-item { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-2); align-items: start; }
.attachment-copy { display: flex; flex-direction: column; min-width: 0; }
.attachment-copy strong { font-size: var(--fs-12); font-weight: var(--fw-medium); }
.attachment-copy small { color: var(--text-subtle); font-size: var(--fs-11); overflow-wrap: anywhere; }

/* ── audit timeline ──────────────────────────────────────────────────────── */
.factbox-timeline { display: grid; gap: var(--s-3); margin: 0; padding: 0; list-style: none; }
.factbox-timeline > li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-3); align-items: start; }
.timeline-dot {
  width: 7px;
  height: 7px;
  margin-top: 5px;
  border-radius: var(--r-pill);
  background: var(--brand-400);
}
.timeline-copy { display: flex; flex-direction: column; min-width: 0; }
.timeline-copy strong { font-size: var(--fs-12); font-weight: var(--fw-medium); }
.timeline-copy small { color: var(--text-subtle); font-size: var(--fs-11); }

/* ── empty state ─────────────────────────────────────────────────────────── */
.empty {
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  padding: var(--s-10) var(--s-4);
  text-align: center;
  color: var(--text-muted);
}
.empty-ico { font-size: 28px; color: var(--text-subtle); }
.empty h3 { margin: 0; font-size: var(--fs-14); font-weight: var(--fw-semibold); color: var(--text); }
.empty p { margin: 0; font-size: var(--fs-13); max-width: 44ch; }
.empty-sm { padding: var(--s-5) var(--s-3); }
.empty-sm .empty-ico { font-size: 20px; }

/* ── responsive record cards ───────────────────────────────────────────────
 * A data table cannot be made to work on a 375px screen. Horizontal scroll
 * inside .table-responsive looks like it works and does not: the status and
 * action columns sit off-screen with nothing indicating they are there, which
 * is how a phone user concludes a quotation has no status.
 *
 * So every list carries a second rendering of the same rows — a card per
 * record, showing the two or three fields that identify it plus its status.
 * It is authored per table, not generated: which fields identify a record is
 * an editorial judgement, and a mechanical row-to-card transform just moves
 * all six columns somewhere else.
 *
 * The two never show at once, so there is no duplicate content for a screen
 * reader to read twice.
 */
.as-cards { display: none; }

@media (max-width: 768px) {
  /* Hide a table ONLY where a card fallback actually follows it. The first
     version of this rule hid every table inside a .card-body, which on a page
     with no fallback — a worksheet, a two-column summary — left an empty card
     and simply lost the content on a phone.
     Three selectors because the table may be bare, wrapped by ux.js in .dgrid,
     or wrapped in Bootstrap's .table-responsive; in each case the fallback is
     the next sibling of whichever element is outermost. */
  table.table:has(+ .as-cards),
  .dgrid:has(+ .as-cards),
  .table-responsive:has(+ .as-cards) { display: none; }

  /* The toolbar needs no rule of its own: ux.js builds it inside .dgrid, so
     hiding that wrapper takes the filter and column picker with the table
     they control — which is right, since a filter that narrows rows nobody
     can see is worse than no filter. */

  .as-cards { display: grid; gap: var(--s-2); padding: var(--s-3); }
}

.rec-card {
  display: block;
  padding: var(--s-3);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-surface);
  color: inherit;
  text-decoration: none;
}
a.rec-card:hover { border-color: var(--brand-300); background: var(--bg-hover); }
a.rec-card:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.rec-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-3);
}
.rec-card-title {
  font-size: var(--fs-13);
  font-weight: var(--fw-semibold);
  color: var(--text);
  overflow-wrap: anywhere;
}
.rec-card-sub { margin-top: 2px; color: var(--text-muted); font-size: var(--fs-12); }

/* Money and quantity keep tabular figures and right alignment on a phone for
 * the same reason they have them in the table: a column of amounts is read by
 * comparing digit positions. */
.rec-card-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-2);
  padding-top: var(--s-2);
  border-top: 1px solid var(--border);
}
.rec-card-label { color: var(--text-subtle); font-size: var(--fs-11); text-transform: uppercase; letter-spacing: .05em; }
.rec-card-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-13);
  font-weight: var(--fw-semibold);
  color: var(--text);
  text-align: right;
}

/* ── filter forms on a phone ───────────────────────────────────────────────
 * A date range is two <input type="date"> in a flex row. Flex items default to
 * min-width:auto, so they refuse to shrink below the intrinsic width the
 * browser gives a date control — about 150px each. In a half-width column on a
 * 375px screen that is 301px of content in 155px of space, and since nothing
 * clips it, the whole PAGE scrolls sideways. Measured at 113px of overflow on
 * /admin/coupons.
 *
 * Two changes, both scoped to controls inside a form so no other .d-flex in
 * the product starts wrapping: let the pair wrap onto a second line, and let
 * each control shrink. Wrapping is preferred to squeezing — a date input
 * narrower than its own placeholder is not usable.
 */
@media (max-width: 768px) {
  form .d-flex:has(> input[type="date"]),
  form .d-flex:has(> input[type="time"]) { flex-wrap: wrap; }

  form input[type="date"],
  form input[type="time"],
  form input[type="number"] { min-width: 0; }

  /* Same reasoning for the row itself: a grid column must be allowed to be
     narrower than its contents' intrinsic width, or it pushes the page. */
  .card-body.row > [class*="col-"] { min-width: 0; }
}

/* ── the tables that keep their table ──────────────────────────────────────
 * Five tables have no card fallback on purpose (three worksheets, a cross-tab,
 * and one whose rows are built by script). They still must not push the page
 * sideways — the rule is that wide content scrolls inside its own box, not
 * that the body scrolls. Measured: the dispatch board's allocation grid is
 * 648px wide and was taking the whole document with it.
 *
 * Where a fallback DOES exist the table is display:none by the rule above, so
 * this costs nothing there.
 */
@media (max-width: 768px) {
  .card-body:has(> table.table) { overflow-x: auto; }
}

/* ── page toolbars ─────────────────────────────────────────────────────────
 * A row of four buttons above a list is 447px wide and will not wrap on its
 * own: .btn-group is explicitly nowrap, and .d-flex defaults to it. Both push
 * the page on a phone. Wrapping is the only sane answer — the alternative is a
 * horizontally scrolling strip of primary actions, which people do not find.
 */
@media (max-width: 768px) {
  /* The header row has to wrap FIRST. Wrapping the button group on its own
     while it is still sitting beside a heading just stacks the buttons into a
     narrow column on top of the title — which is what the first version of
     this rule did. Once the row wraps, the group gets the full width and its
     four buttons fall into two sensible rows. */
  .d-flex.justify-content-between { flex-wrap: wrap; }
  .btn-group,
  .d-flex.gap-2 { flex-wrap: wrap; }
}

/* A figure inside a FactBox: label left, value right, tabular so a column of
   them lines up on the decimal the way the tables do. */
.factbox-figure {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-1) 0;
}
.factbox-figure + .factbox-figure { border-top: 1px solid var(--border); }
.factbox-figure-label { color: var(--text-muted); font-size: var(--fs-12); }
.factbox-figure-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-14);
  font-weight: var(--fw-semibold);
  color: var(--text);
}

/* The Lines FastTab holds a full-bleed table, so its body must not pad it —
   the table draws its own edges. */
.fasttab-lines { margin: calc(-1 * var(--s-4)); }
.fasttab-lines > .as-cards { padding: var(--s-3); }

/* ── table cells ───────────────────────────────────────────────────────────
 * The second line under a cell's main value — a reference number under a
 * name, a date under a document number. Reference: .cell-sub. */
.cell-sub {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-12);
  color: var(--text-subtle);
}

/* ── the way into a record ─────────────────────────────────────────────────
 * Reference: .text-link and the chevron that ends a row. The name in the
 * first cell is a link, and the row's last cell is a quiet chevron rather
 * than an "Open" button — the button repeated the same word on every row and
 * competed with the real actions beside it. The chevron keeps an accessible
 * name; only the visible word goes. */
.text-link {
  color: var(--brand-700);
  font-weight: var(--fw-medium);
  text-decoration: none;
}
.text-link:hover { color: var(--brand-800); text-decoration: underline; }
.row-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-sm);
  color: var(--text-subtle);
  text-decoration: none;
}
.row-go:hover { background: var(--bg-hover); color: var(--brand-700); }
.row-go:focus-visible { outline: 2px solid var(--brand-600); outline-offset: 2px; }

