/* Aurum operations — the interface, built from the brand's own rules.
 *
 * The identity system (design_assets/AURUM-brand-identity.html) is not a
 * mood board; it is a specification, and this file implements it:
 *
 *   - Black is the ground, not a theme. "Place on black wherever you can."
 *   - Gold is an accent that marks value, never a surface. The ratio the
 *     brand sets is ~85% black / ~10% neutral / ~5% gold, and it is the
 *     single easiest thing to lose: gold used everywhere reads as cheap.
 *   - No gradients, glows, bevels or drop shadows. Depth comes from
 *     hairlines and from one surface sitting a shade above another, the
 *     way ink and foil do it.
 *   - Corners are 2px. The mark is cut from straight edges at whole-number
 *     ratios, and a 12px radius next to it looks borrowed from somewhere
 *     else.
 *   - Balances are tabular. "A gram balance that shifts its digits is a
 *     trust failure" — so every figure in this file is tabular-nums.
 *   - Labels are assay stamps: 10px, uppercase, +0.28em, used to name a
 *     region, never as decoration.
 *
 * Direction-agnostic by construction. The dashboard is Arabic-first, so
 * every inline-axis rule uses logical properties (inline-start/inline-end,
 * margin-inline, padding-inline, text-align: start) rather than left/right.
 * Switching language flips the entire layout with no mirrored stylesheet
 * and no [dir="rtl"] block to keep in sync. The only physical concepts
 * left are the block axis (top/bottom, which does not flip) and a handful
 * of transforms, which are written with a --flip multiplier instead.
 */

/* ==========================================================================
   The Arabic face
   ==========================================================================
   The same Noto Kufi Arabic the app bundles and the PDF receipts are set in,
   so an operator reading a figure here and a customer reading it there are
   looking at one typeface. Served, not hoped for: a font-family naming a
   face nobody has installed is a font-family that does nothing.

   One variable file covers 100-900, so every weight the interface uses comes
   from a single 168KB request instead of four static cuts.

   unicode-range is what makes this work. Scoped to the Arabic blocks, the
   browser downloads it only on pages that actually contain Arabic and never
   applies it to Latin — so digits, references and English labels keep the
   system UI face, which is better at small sizes and in dense tables.

   font-display: swap — an ops dashboard should render its numbers
   immediately and restyle a moment later, never hold the page blank. */
@font-face {
  font-family: "Aurum Kufi";
  src: url("fonts/NotoKufiArabic-Variable.03d34d35e8c8.woff2") format("woff2-variations"),
       url("fonts/NotoKufiArabic-Variable.03d34d35e8c8.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+08A0-08FF,
                 U+FB50-FDFF, U+FE70-FEFF, U+10E60-10E7E, U+1EE00-1EEFF,
                 U+204F, U+2670-2671;
}

/* ==========================================================================
   01 — Tokens
   ========================================================================== */

:root {
  /* Ground and surfaces. Four steps, all within a whisker of black: the
     hierarchy is carried by hairlines, so the surfaces themselves must not
     compete with the gold. */
  --ink: #0f1115;          /* Vault Black — the page */
  --ink-sunk: #0b0d10;     /* below the page: table heads, wells, code */
  --surface: #14171d;      /* a panel resting on the page */
  --surface-raised: #1a1d23;  /* Graphite — a panel resting on a panel */
  --surface-hover: #1e222a;

  /* Type. Bone is the reading colour; ash is everything that supports it. */
  --bone: #e9e7e2;
  --ash: #8a8c92;
  --dim: #62656d;

  /* The metal. gold-quiet is for hairlines and washes — the only places
     gold is allowed to cover area. */
  --gold: #d4af37;
  --gold-bright: #e8c65a;   /* hover only; nothing rests at this value */
  --gold-deep: #9a7b25;
  --gold-hair: rgba(212, 175, 55, 0.22);
  --gold-wash: rgba(212, 175, 55, 0.07);

  /* Hairlines. The brand's dividers are 1px and nearly invisible; that is
     the point — structure you feel rather than read. */
  --hair: rgba(233, 231, 226, 0.09);
  --hair-strong: rgba(233, 231, 226, 0.16);

  /* Semantics, deliberately desaturated. On this ground a saturated green
     would out-shout the gold, and the gold is the thing that means value. */
  --up: #6fae86;
  --down: #cf7b72;
  --warn: #d8a63f;
  --danger: #d8564c;
  --danger-wash: rgba(216, 86, 76, 0.10);
  --warn-wash: rgba(216, 166, 63, 0.10);
  --up-wash: rgba(111, 174, 134, 0.12);

  /* Type stacks.

     This used to list Latin faces first and Arabic after, on the theory that
     "a Latin family carries no Arabic glyphs, so the browser falls through".
     It does not: -apple-system and Segoe UI both ship full Arabic coverage,
     so the fallthrough never happened and every Arabic screen rendered in
     whatever the viewer's OS reached for first — Segoe UI on Windows, Tahoma
     where that was missing. None of those are the brand face, none of them
     were served, and the result read as an unstyled page.

     The fix is unicode-range, not ordering: Aurum Kufi is declared for the
     Arabic blocks ONLY (see @font-face above), so it wins for Arabic while
     Latin still gets the crisp system UI face. One stack, both scripts, and
     now it is actually true. */
  --font: "Aurum Kufi", ui-sans-serif, -apple-system, "Segoe UI",
    "Helvetica Neue", "SF Arabic", "Noto Kufi Arabic", Tahoma, Arial,
    sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas,
    monospace;

  /* Spacing — a 4px grid. Named by intent so a panel and a page gutter
     cannot drift apart. */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;

  --radius: 2px;
  --rail: 16.5rem;
  --page-max: 88rem;

  /* Mirrors a transform on the inline axis without a [dir] override. */
  --flip: 1;

  /* --- surfaces of the accent, as opposed to the accent as ink ---------
     `--gold` is the accent used for TEXT and hairlines and changes with the
     theme so it stays legible; `--gold-solid` is the metal used as a FILL
     (the primary button, the coverage bar, the price line) and does not,
     because the metal is the same metal on paper as on screen. Anything
     sitting on that fill uses `--on-gold`. */
  --gold-solid: #d4af37;
  --on-gold: #0f1115;

  /* A wash of the text colour: hovers, quiet chips, tag grounds. */
  --tint: rgba(233, 231, 226, 0.05);
  --tint-strong: rgba(233, 231, 226, 0.07);

  /* Borders derived from the semantic hues, and the border an input takes
     on hover. Tokens rather than literals so the light theme moves them
     with everything else. */
  --up-line: rgba(111, 174, 134, 0.35);
  --warn-line: rgba(216, 166, 63, 0.35);
  --danger-line: rgba(216, 86, 76, 0.40);
  --hair-hover: rgba(233, 231, 226, 0.26);

  /* Form fields. On black a field is a well, sunk below the panel; on
     paper the same treatment reads as disabled, so there it is the
     lightest surface on the screen with a rule around it. */
  --field: var(--ink-sunk);
  --field-focus: var(--ink);

  --owed: #4a4f5a;              /* the non-gold bar in the assay gap */
  --scroll-thumb: #262a32;
  --scroll-thumb-hover: #333842;
  --topbar-bg: rgba(15, 17, 21, 0.92);
  --scrim: rgba(11, 13, 16, 0.7);
  --watermark: 0.09;
  /* Native date/time pickers draw their glyph in the platform's colour. */
  --picker-filter: invert(0.7);

  color-scheme: dark;
}

/* --- The light interface ---------------------------------------------------
 *
 * Black is the brand's ground and stays the default. But this console is
 * also used at a counter in daylight with the shutters open, and a screen
 * nobody can read is not a brand asset — so the same design system has a
 * second ground: the brand's own paper. Ivory rather than white, because
 * the identity's stock is ivory and because a pure-white field under
 * hairline rules glares.
 *
 * Nothing here changes shape, spacing or type. Only the twenty values
 * below move, which is the whole reason the tokens exist. Gold as ink goes
 * darker so it clears 4.5:1 on paper; gold as metal does not move at all.
 */
[data-theme="light"] {
  --ink: #f2efe7;
  --ink-sunk: #e7e3d8;
  --surface: #ffffff;
  --surface-raised: #faf8f2;
  --surface-hover: #f5f2ea;

  --bone: #16181d;
  --ash: #5c5f66;
  --dim: #74777e;

  --gold: #8a6a12;
  --gold-bright: #a4801a;
  --gold-deep: #b8912a;
  --gold-hair: rgba(138, 106, 18, 0.30);
  --gold-wash: rgba(212, 175, 55, 0.14);

  --hair: rgba(22, 24, 29, 0.13);
  --hair-strong: rgba(22, 24, 29, 0.24);

  --up: #2f7a51;
  --down: #b0463d;
  --warn: #96690e;
  --danger: #b3352c;
  --danger-wash: rgba(179, 53, 44, 0.10);
  --warn-wash: rgba(150, 105, 14, 0.12);
  --up-wash: rgba(47, 122, 81, 0.12);

  --tint: rgba(22, 24, 29, 0.045);
  --tint-strong: rgba(22, 24, 29, 0.075);

  --up-line: rgba(47, 122, 81, 0.40);
  --warn-line: rgba(150, 105, 14, 0.40);
  --danger-line: rgba(179, 53, 44, 0.42);
  --hair-hover: rgba(22, 24, 29, 0.34);

  --field: #ffffff;
  --field-focus: #ffffff;

  --owed: #b6b2a5;
  --scroll-thumb: #d3cfc2;
  --scroll-thumb-hover: #bfbbae;
  --topbar-bg: rgba(242, 239, 231, 0.92);
  --scrim: rgba(22, 24, 29, 0.45);
  --watermark: 0.16;
  --picker-filter: none;

  color-scheme: light;
}

[dir="rtl"] {
  --flip: -1;
}

/* ==========================================================================
   02 — Reset
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--font);
  font-size: 0.9375rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Every number in this interface is money, weight or a count, and all
     three are read in columns. */
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4, p, figure, dl, dd, ol, ul {
  margin: 0;
}

ul, ol {
  padding: 0;
  list-style: none;
}

img, svg {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

button, input, select, textarea {
  font: inherit;
  font-variant-numeric: inherit;
  color: inherit;
}

::selection {
  background: var(--gold-solid);
  color: var(--on-gold);
}

/* One focus treatment, everywhere, and it is gold — the operator's own
   position on the page is worth the accent. */
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 1px;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: var(--ink-sunk);
}

::-webkit-scrollbar-thumb {
  background: var(--scroll-thumb);
  border: 2px solid var(--ink-sunk);
  border-radius: 6px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--scroll-thumb-hover);
}

/* ==========================================================================
   03 — Type roles
   ========================================================================== */

.eyebrow {
  display: block;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ash);
}

.eyebrow-gold {
  color: var(--gold);
}

h1, .h1 {
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.2;
}

h2, .h2 {
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: -0.01em;
}

h3, .h3 {
  font-size: 0.9375rem;
  font-weight: 500;
}

.lede {
  max-width: 68ch;
  color: var(--ash);
}

.muted, .note, .hint {
  color: var(--ash);
}

.note, .hint {
  font-size: 0.8125rem;
}

.dim {
  color: var(--dim);
}

.mono, code, pre, .ref {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: -0.01em;
}

/* A reference an operator reads down a column or dictates over the phone:
   spaced a touch wider so 0/O and 1/l separate. */
.mono, .ref {
  letter-spacing: 0.01em;
}

code {
  padding: 0.05em 0.35em;
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  color: var(--bone);
}

.figure {
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.figure-lg {
  font-size: 2.25rem;
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

.figure-sm {
  font-size: 1.125rem;
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* The unit is not the number. Gold gets its weight from the digits, so the
   unit steps back rather than doubling the emphasis. */
.unit {
  font-size: 0.6em;
  font-weight: 400;
  color: var(--ash);
  letter-spacing: 0.02em;
}

.gold {
  color: var(--gold);
}

.up { color: var(--up); }
.down { color: var(--down); }
.error, .danger-text { color: var(--danger); }

/* ==========================================================================
   04 — The shell
   ========================================================================== */

.skip {
  position: absolute;
  inset-block-start: -100%;
  inset-inline-start: var(--s4);
  z-index: 100;
  padding: var(--s2) var(--s4);
  background: var(--gold-solid);
  color: var(--on-gold);
  font-weight: 600;
}

.skip:focus {
  inset-block-start: var(--s2);
}

.shell {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100svh;
}

/* -- the rail ------------------------------------------------------------ */

.rail {
  position: sticky;
  inset-block-start: 0;
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100svh;
  background: var(--ink-sunk);
  border-inline-end: 1px solid var(--hair);
}

.rail-head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s5) var(--s5) var(--s4);
}

.rail-nav {
  flex: 1;
  overflow-y: auto;
  padding: var(--s2) var(--s3) var(--s5);
}

.rail-foot {
  padding: var(--s3) var(--s5) var(--s5);
  border-block-start: 1px solid var(--hair);
}

/* The mark. Two closed polygons, one flat colour, exactly as governed. */
.mark {
  width: 1.75rem;
  height: 1.4rem;
  color: var(--gold);
  flex: none;
}

.mark-lg {
  width: 3rem;
  height: 2.4rem;
}

.wordmark {
  width: 5.25rem;
  color: var(--gold);
}

/* The lockup keeps its own reading order in both languages. Arabic flips
   the interface, but the mark is a drawing, not a sentence: the governance
   rules forbid mirroring it, and "symbol then wordmark" is the lockup. */
.brand {
  display: flex;
  align-items: center;
  gap: var(--s3);
  direction: ltr;
}

.brand-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

/* -- nav ----------------------------------------------------------------- */

.nav-group + .nav-group {
  margin-block-start: var(--s5);
}

.nav-group > .eyebrow {
  padding: 0 var(--s3) var(--s2);
  font-size: 0.5625rem;
  color: var(--dim);
}

.nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: 0.5rem var(--s3);
  border-radius: var(--radius);
  color: var(--ash);
  font-size: 0.875rem;
  transition: color 0.12s ease, background-color 0.12s ease;
}

.nav-link:hover {
  color: var(--bone);
  background: var(--tint);
}

/* Active is a gold rule on the inline edge — the assay mark against the
   item you are in, not a filled pill. */
.nav-link[aria-current="page"] {
  color: var(--bone);
  background: var(--gold-wash);
}

.nav-link[aria-current="page"]::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block: 0.35rem;
  width: 2px;
  background: var(--gold);
}

.nav-link .ico {
  width: 1rem;
  height: 1rem;
  flex: none;
  opacity: 0.75;
}

.nav-link[aria-current="page"] .ico {
  color: var(--gold);
  opacity: 1;
}

/* A count riding a nav item: only drawn when there is work in it. */
.nav-count {
  margin-inline-start: auto;
  padding: 0 0.35rem;
  min-width: 1.35rem;
  border: 1px solid var(--gold-hair);
  border-radius: var(--radius);
  background: var(--gold-wash);
  color: var(--gold);
  font-size: 0.6875rem;
  text-align: center;
}

/* -- who is signed in ---------------------------------------------------- */

.who {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-block-end: var(--s3);
}

.who-mark {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  flex: none;
  border: 1px solid var(--gold-hair);
  color: var(--gold);
  font-size: 0.75rem;
  font-weight: 600;
}

.who-lines {
  min-width: 0;
  line-height: 1.3;
}

.who-phone {
  font-size: 0.8125rem;
  direction: ltr;
  text-align: start;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* -- main ---------------------------------------------------------------- */

.main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.topbar {
  position: sticky;
  inset-block-start: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: 0 var(--s5);
  min-height: 3.5rem;
  background: var(--topbar-bg);
  backdrop-filter: blur(8px);
  border-block-end: 1px solid var(--hair);
}

.topbar-end {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-inline-start: auto;
}

.page {
  flex: 1;
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding: var(--s6) var(--s5) var(--s7);
}

.page-head {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--s4);
  margin-block-end: var(--s5);
  padding-block-end: var(--s4);
  border-block-end: 1px solid var(--hair);
}

.page-head .titles {
  min-width: 0;
  flex: 1;
}

.page-head h1 {
  margin-block-start: 0.35rem;
}

.page-actions {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
}

/* Back to where this page came from. */
.backlink {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--ash);
  font-size: 0.8125rem;
}

.backlink:hover { color: var(--gold); }

.backlink svg {
  width: 0.75rem;
  height: 0.75rem;
  transform: scaleX(var(--flip));
}

/* -- language switch ----------------------------------------------------- */

.langswitch {
  display: flex;
  flex: none;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  overflow: hidden;
}

.langswitch button {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.6rem;
  white-space: nowrap;
  border: 0;
  background: transparent;
  color: var(--ash);
  font-size: 0.75rem;
  cursor: pointer;
}

.langswitch button:hover {
  color: var(--bone);
  background: var(--tint);
}

.langswitch button[disabled] {
  background: var(--gold-wash);
  color: var(--gold);
  cursor: default;
}

/* -- the rail on small screens ------------------------------------------- */

/* A checkbox drives the slide-over so navigation works with JavaScript
   off — the console is used on a phone in a branch, and a nav that needs a
   script is a nav that can fail there. The input stays in the tab order
   (it is the control); it is its label that is painted, so focus is
   forwarded onto the label below. */
.rail-toggle,
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}

.rail-toggle:focus-visible ~ .shell .rail-button {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.rail-button,
.rail-scrim {
  display: none;
}

/* ==========================================================================
   05 — Panels
   ========================================================================== */

/* One container idiom, sized by content rather than repeated at a fixed
   height. A panel is a bordered region with an optional hairline header —
   not a card with a coloured edge, and not a tile in a grid of identical
   tiles. */
.panel {
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
}

.panel + .panel,
.panel + .section,
.section + .section,
.section + .panel {
  margin-block-start: var(--s5);
}

.panel-head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-block-end: 1px solid var(--hair);
}

.panel-head .eyebrow {
  margin-inline-end: auto;
}

.panel-body {
  padding: var(--s4);
}

.panel-body > * + * {
  margin-block-start: var(--s4);
}

.panel-foot {
  padding: var(--s3) var(--s4);
  border-block-start: 1px solid var(--hair);
  font-size: 0.8125rem;
}

.section {
  margin-block-start: var(--s6);
}

.section-head {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  flex-wrap: wrap;
  margin-block-end: var(--s3);
}

.section-head .eyebrow {
  margin-inline-end: auto;
}

/* Two columns that collapse. Used for detail pages: the record on one
   side, what can be done to it on the other. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(18rem, 1fr);
  gap: var(--s5);
  align-items: start;
}

.split > *,
.split-even > * {
  min-width: 0;
}

.split-even {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--s5);
  align-items: start;
}

.stack {
  display: grid;
  /* One column that never grows past its container. Left as the implicit
     auto track, a wide table inside (the customer ledger) sized the column
     to the table and ran underneath the panels beside it. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s5);
}

.stack-tight {
  display: grid;
  gap: var(--s3);
}

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

/* ==========================================================================
   06 — The ledger strip
   ========================================================================== */

/* What replaces a row of identical statistic cards. Figures that belong to
   one story sit in one bordered strip, divided by hairlines, reading like
   a line on a balance sheet rather than four boxes that happen to be
   adjacent. Each cell is free to hold a different shape of content. */
.ledger {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  overflow: hidden;
}

.ledger > * {
  padding: var(--s4);
  border-inline-start: 1px solid var(--hair);
}

.ledger > *:first-child {
  border-inline-start: 0;
}

/* On a narrow grid the cells wrap, and an inline border on a wrapped row
   lands in the wrong place; the block border below is the honest divider. */
@supports (grid-template-columns: subgrid) {
  .ledger > * {
    border-block-start: 1px solid var(--hair);
  }

  .ledger > *:first-child {
    border-block-start: 0;
  }
}

.cell-label {
  display: block;
  margin-block-end: var(--s2);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--dim);
}

.cell-note {
  display: block;
  margin-block-start: var(--s1);
  font-size: 0.75rem;
  color: var(--ash);
}

/* ==========================================================================
   07 — The price band
   ========================================================================== */

/* The one place on the console where gold is allowed to be the loudest
   thing: this is the number the whole business is priced off. */
.price {
  display: grid;
  grid-template-columns: minmax(16rem, 1.1fr) minmax(0, 1.4fr);
  background: var(--surface);
  border: 1px solid var(--gold-hair);
  border-radius: var(--radius);
  overflow: hidden;
}

.price-mid {
  padding: var(--s5);
  background:
    linear-gradient(to bottom, var(--gold-wash), transparent 60%);
}

.price-mid .figure-lg {
  color: var(--gold);
}

.price-sides {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-block-start: 1px solid var(--hair);
}

.price-sides > * {
  padding: var(--s3) var(--s5);
}

.price-sides > * + * {
  border-inline-start: 1px solid var(--hair);
}

.price-chart {
  display: flex;
  flex-direction: column;
  border-inline-start: 1px solid var(--hair);
}

.price-chart-head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-block-end: 1px solid var(--hair);
}

.spark {
  flex: 1;
  width: 100%;
  min-height: 6.5rem;
}

.spark path {
  vector-effect: non-scaling-stroke;
}

/* The change figure, with its own arrow. Direction is meaning here, so it
   is drawn rather than left to a colour alone. */
.delta {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.875rem;
}

.delta svg {
  width: 0.6rem;
  height: 0.6rem;
}

/* A live feed announces itself with one slow pulse, not a spinner. */
.pulse {
  display: inline-block;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--up);
}

.pulse-live {
  animation: pulse 2.4s ease-in-out infinite;
}

.pulse-stale {
  background: var(--warn);
}

.pulse-off {
  background: var(--dim);
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

/* The ticker in the top bar: the same number, following the operator from
   screen to screen. */
.ticker {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: 0.3rem var(--s3);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  font-size: 0.8125rem;
}

.ticker .figure-sm {
  color: var(--gold);
}

.spark-line {
  fill: none;
  stroke: var(--gold-solid);
  stroke-width: 1.5;
  stroke-linejoin: round;
}

.spark-area {
  fill: var(--gold-wash);
  stroke: none;
}

/* Volume, day by day. Bars rather than a second line: a line implies a
   continuous quantity, and a day's trading is a discrete tally. */
.bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 8rem;
}

.bar-col {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  flex: 1;
  min-width: 0;
  height: 100%;
}

.bar {
  width: 100%;
  min-height: 1px;
  background: var(--gold-deep);
  transition: background-color 0.12s ease;
}

.bar-col:hover .bar {
  background: var(--gold);
}

/* The figure appears on hover rather than under every column: fourteen
   amounts printed at once is a table, and a worse one than the table. */
.bar-value {
  position: absolute;
  inset-block-end: calc(100% - 1.1rem);
  padding: 0.1rem 0.35rem;
  background: var(--ink-sunk);
  border: 1px solid var(--gold-hair);
  border-radius: var(--radius);
  font-size: 0.6875rem;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 2;
}

.bar-col:hover .bar-value:not(:empty) {
  opacity: 1;
}

.bar-day {
  margin-block-start: var(--s2);
  font-size: 0.625rem;
  color: var(--dim);
  white-space: nowrap;
}

/* ==========================================================================
   08 — The assay gap
   ========================================================================== */

/* The logo, made operational. Two bars — gold held, gold owed — with the
   measured void between them that the mark is built from. That gap IS the
   reconciliation line: held >= owed is the promise the business makes, and
   this is the one place it can be read in a second.
   Widths are set inline from the view; nothing here computes. */
.assay {
  display: grid;
  gap: var(--s2);
  padding: var(--s2) 0;
}

.assay-row {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
}

/* Both are spans, so both are told to be boxes: an inline element ignores
   the height and the width that carry the whole meaning here. */
.assay-track {
  position: relative;
  display: block;
  height: 1.5rem;
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
}

.assay-fill {
  display: block;
  height: 100%;
  /* Chamfered on the leading edge — the plinth's cut corner, at the same
     1:2 angle the mark is drawn on. */
  clip-path: polygon(0 0, calc(100% - 0.5rem) 0, 100% 100%, 0 100%);
}

[dir="rtl"] .assay-fill {
  clip-path: polygon(0.5rem 0, 100% 0, 100% 100%, 0 100%);
}

.assay-held .assay-fill {
  background: var(--gold-solid);
}

.assay-owed .assay-fill {
  background: var(--owed);
}

/* The floor: where coverage stops being allowed to fall. */
.assay-floor {
  position: absolute;
  inset-block: -0.25rem;
  inline-size: 0;
  border-inline-start: 1px dashed var(--warn);
}

.assay-value {
  font-size: 0.8125rem;
  white-space: nowrap;
}

/* ==========================================================================
   09 — Worklist
   ========================================================================== */

/* Queues are work, so they are a list you can run your eye down, not a
   grid of tiles. An empty queue stays quiet; one with work in it gets the
   gold. */
.worklist {
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}

.work {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s3) var(--s4);
  border-block-start: 1px solid var(--hair);
  color: inherit;
}

.work:first-child {
  border-block-start: 0;
}

a.work:hover {
  background: var(--surface-hover);
}

.work-count {
  min-width: 2.5rem;
  font-size: 1.25rem;
  font-weight: 500;
  color: var(--dim);
  text-align: end;
}

.work.has-work .work-count {
  color: var(--gold);
}

.work-label {
  flex: 1;
  min-width: 0;
  font-size: 0.875rem;
}

.work.has-work .work-label {
  color: var(--bone);
}

.work-go {
  width: 0.75rem;
  height: 0.75rem;
  color: var(--dim);
  transform: scaleX(var(--flip));
}

a.work:hover .work-go {
  color: var(--gold);
}

/* ==========================================================================
   10 — Tables
   ========================================================================== */

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

/* Wide financial tables scroll inside their own container. The page body
   never scrolls sideways. */
.tablescroll {
  overflow-x: auto;
}

table.grid {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

table.grid thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  padding: var(--s3) var(--s4);
  background: var(--ink-sunk);
  border-block-end: 1px solid var(--hair);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ash);
  text-align: start;
  white-space: nowrap;
}

table.grid tbody td {
  padding: var(--s3) var(--s4);
  border-block-start: 1px solid var(--hair);
  vertical-align: top;
}

table.grid tbody tr:first-child td {
  border-block-start: 0;
}

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

/* Money and weight are compared by eye down the column, so they are
   end-aligned and tabular. The header follows the cells. */
table.grid td.num,
table.grid th.num {
  text-align: end;
  white-space: nowrap;
}

table.grid td.nowrap,
table.grid th.nowrap {
  white-space: nowrap;
}

/* The action column: quiet until the row is under the cursor, so a table
   of two hundred rows is not two hundred links shouting at once. */
table.grid td.actions-cell {
  width: 1%;
  text-align: end;
  white-space: nowrap;
}

.rowlink {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--ash);
  font-size: 0.75rem;
  transition: color 0.12s ease, border-color 0.12s ease;
}

tr:hover .rowlink,
.rowlink:focus-visible {
  color: var(--gold);
  border-color: var(--gold-hair);
}

/* Sorting. django-tables2 puts the state on the th; the arrow is drawn
   with borders so it needs no icon font and no image request. */
table.grid th a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: inherit;
}

table.grid th a:hover {
  color: var(--bone);
}

table.grid th a::after {
  content: "";
  width: 0;
  height: 0;
  border-inline: 3px solid transparent;
  border-block-end: 4px solid currentColor;
  opacity: 0.25;
}

table.grid th.desc a::after {
  border-block-end: 0;
  border-block-start: 4px solid currentColor;
}

table.grid th.asc a,
table.grid th.desc a {
  color: var(--gold);
}

table.grid th.asc a::after,
table.grid th.desc a::after {
  opacity: 1;
}

/* A row that has been undone stays visible and reads as undone. */
tr.reversed {
  opacity: 0.5;
}

tr.reversed td {
  text-decoration: line-through;
}

/* A compact variant for tables nested inside a panel. */
table.grid.tight thead th,
table.grid.tight tbody td {
  padding: var(--s2) var(--s3);
}

/* ==========================================================================
   11 — Status tags
   ========================================================================== */

/* A status is a word, not a colour: the word is always there and the
   colour only reinforces it. Tags are square-cut with a hairline, so a
   screen of them reads as a stamped record rather than a bag of sweets. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--hair-strong);
  border-radius: var(--radius);
  background: var(--tint);
  color: var(--ash);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.tag::before {
  content: "";
  width: 0.3rem;
  height: 0.3rem;
  flex: none;
  background: currentColor;
}

.tag-good {
  border-color: var(--up-line);
  background: var(--up-wash);
  color: var(--up);
}

.tag-gold {
  border-color: var(--gold-hair);
  background: var(--gold-wash);
  color: var(--gold);
}

.tag-warn {
  border-color: var(--warn-line);
  background: var(--warn-wash);
  color: var(--warn);
}

.tag-bad {
  border-color: var(--danger-line);
  background: var(--danger-wash);
  color: var(--danger);
}

.tag-plain::before {
  display: none;
}

/* ==========================================================================
   12 — Alerts
   ========================================================================== */

/* Alerts are the one place a colour fills area, and even here it is a wash
   over black with a solid rule on the inline edge. */
.alert {
  display: flex;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  margin-block-end: var(--s4);
  background: var(--surface);
  border: 1px solid var(--hair);
  border-inline-start: 2px solid var(--ash);
  border-radius: var(--radius);
  font-size: 0.875rem;
}

.alert-icon {
  width: 1rem;
  height: 1rem;
  flex: none;
  margin-block-start: 0.2rem;
}

.alert-body > * + * {
  margin-block-start: var(--s2);
}

.alert-danger {
  background: var(--danger-wash);
  border-color: var(--danger-line);
  border-inline-start-color: var(--danger);
}

.alert-warn {
  background: var(--warn-wash);
  border-color: var(--warn-line);
  border-inline-start-color: var(--warn);
}

.alert-gold {
  background: var(--gold-wash);
  border-color: var(--gold-hair);
  border-inline-start-color: var(--gold);
}

.alert-good {
  background: var(--up-wash);
  border-color: var(--up-line);
  border-inline-start-color: var(--up);
}

.alert ul {
  display: grid;
  gap: var(--s2);
}

.alert li {
  padding-inline-start: var(--s3);
  border-inline-start: 1px solid var(--hair);
}

/* ==========================================================================
   13 — Facts (detail lists)
   ========================================================================== */

/* Label above value, in a wrapping grid. A two-column dl forces every
   value onto a line whose width is set by the longest label in the list,
   which is how financial detail pages end up unreadable. */
.facts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: var(--s4) var(--s5);
}

.facts > div {
  min-width: 0;
}

.facts dt {
  margin-block-end: 0.15rem;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dim);
}

.facts dd {
  margin: 0;
  overflow-wrap: anywhere;
}

/* A fact that carries the page's headline number. */
.facts .lead {
  font-size: 1.125rem;
  font-weight: 500;
}

/* Stacked variant for a narrow aside. */
.facts-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s3);
}

/* ==========================================================================
   14 — Forms
   ========================================================================== */

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--s4);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

.field-wide {
  grid-column: 1 / -1;
}

.field > label,
.label {
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ash);
}

.field .req {
  color: var(--gold);
}

.field .help {
  font-size: 0.75rem;
  color: var(--dim);
}

input[type="text"],
input[type="search"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="time"],
input[type="file"],
select,
textarea {
  width: 100%;
  padding: 0.5rem 0.65rem;
  background: var(--field);
  border: 1px solid var(--hair-strong);
  border-radius: var(--radius);
  color: var(--bone);
  font-size: 0.875rem;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

input::placeholder,
textarea::placeholder {
  color: var(--dim);
}

input:hover,
select:hover,
textarea:hover {
  border-color: var(--hair-hover);
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--gold);
  background: var(--field-focus);
}

textarea {
  min-height: 5rem;
  resize: vertical;
}

/* The native arrow is drawn by the platform in the platform's colour; on
   this ground it disappears, so it is replaced. */
select {
  appearance: none;
  padding-inline-end: 2rem;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ash) 50%),
    linear-gradient(135deg, var(--ash) 50%, transparent 50%);
  background-position:
    calc(100% - 1.05rem) calc(50% + 0.1rem),
    calc(100% - 0.7rem) calc(50% + 0.1rem);
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
}

[dir="rtl"] select {
  background-position:
    0.7rem calc(50% + 0.1rem),
    1.05rem calc(50% + 0.1rem);
}

/* Dates and times are read left-to-right in both languages. */
input[type="date"],
input[type="time"],
.ltr {
  direction: ltr;
  text-align: start;
}

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
  filter: var(--picker-filter);
  cursor: pointer;
}

input[type="file"] {
  padding: 0.35rem;
  cursor: pointer;
}

input[type="file"]::-webkit-file-upload-button,
input[type="file"]::file-selector-button {
  margin-inline-end: var(--s3);
  padding: 0.3rem 0.7rem;
  background: var(--surface-raised);
  border: 1px solid var(--hair-strong);
  border-radius: var(--radius);
  color: var(--bone);
  font-size: 0.8125rem;
  cursor: pointer;
}

input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  accent-color: var(--gold);
}

fieldset {
  margin: 0;
  padding: 0;
  border: 0;
}

/* A running total the operator can check before they commit: weight times
   price, fees added, the number that will actually be written. */
.readout {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--field);
  border: 1px solid var(--gold-hair);
  border-radius: var(--radius);
}

.readout-value {
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--gold);
}

.readout-formula {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--ash);
  direction: ltr;
}

/* ==========================================================================
   15 — Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.45rem 0.95rem;
  background: transparent;
  border: 1px solid var(--hair-strong);
  border-radius: var(--radius);
  color: var(--bone);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: border-color 0.12s ease, background-color 0.12s ease,
    color 0.12s ease;
}

.btn:hover {
  border-color: var(--hair-strong);
  background: var(--tint-strong);
}

.btn:active {
  transform: translateY(1px);
}

.btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

/* The gold button is the action the screen exists for. There is one per
   form, and screens that move money do not get one at all — see .btn-grave. */
.btn-gold {
  background: var(--gold-solid);
  border-color: var(--gold-solid);
  color: var(--on-gold);
  font-weight: 600;
}

.btn-gold:hover {
  background: var(--gold-bright);
  border-color: var(--gold-bright);
}

.btn-danger {
  border-color: var(--danger-line);
  background: var(--danger-wash);
  color: var(--danger);
}

.btn-danger:hover {
  background: var(--danger-wash);
  filter: brightness(1.15);
  border-color: var(--danger);
}

.btn-quiet {
  border-color: transparent;
  color: var(--ash);
  padding-inline: 0.5rem;
}

.btn-quiet:hover {
  color: var(--bone);
}

.btn-sm {
  padding: 0.25rem 0.6rem;
  font-size: 0.75rem;
}

.btn svg {
  width: 0.85rem;
  height: 0.85rem;
}

.actions {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
}

.actions-end {
  justify-content: flex-end;
}

/* ==========================================================================
   16 — Filters
   ========================================================================== */

/* Filtering is part of the table, not a form bolted above it: the control
   row sits inside the table's own border, and what is currently applied is
   restated as removable chips so nobody wonders why the count is low. */
.filterbar {
  display: flex;
  align-items: flex-end;
  gap: var(--s3);
  flex-wrap: wrap;
  padding: var(--s3) var(--s4);
  border-block-end: 1px solid var(--hair);
  background: var(--surface-raised);
}

.filterbar .field {
  flex: 0 1 11rem;
}

.filterbar .field-search {
  flex: 1 1 16rem;
}

.filterbar .filter-actions {
  display: flex;
  gap: var(--s2);
  margin-inline-start: auto;
}

.chips {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
  padding: var(--s2) var(--s4);
  border-block-end: 1px solid var(--hair);
  font-size: 0.75rem;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.15rem 0.5rem;
  border: 1px solid var(--gold-hair);
  border-radius: var(--radius);
  background: var(--gold-wash);
  color: var(--bone);
}

.chip .chip-x {
  color: var(--ash);
  font-size: 0.875rem;
  line-height: 1;
}

.chip:hover .chip-x {
  color: var(--gold);
}

.tablehead {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
  padding: var(--s3) var(--s4);
  border-block-end: 1px solid var(--hair);
}

.tablehead .count {
  margin-inline-start: auto;
  font-size: 0.75rem;
  color: var(--ash);
}

/* ==========================================================================
   17 — Pagination
   ========================================================================== */

.pager {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-block-start: 1px solid var(--hair);
  font-size: 0.8125rem;
  color: var(--ash);
}

.pager .pager-links {
  display: flex;
  align-items: center;
  gap: var(--s2);
  margin-inline-start: auto;
}

.pager a,
.pager span.page-current {
  display: inline-grid;
  place-items: center;
  min-width: 1.9rem;
  height: 1.9rem;
  padding-inline: 0.4rem;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
}

.pager a:hover {
  border-color: var(--gold-hair);
  color: var(--gold);
}

.pager span.page-current {
  border-color: var(--gold-hair);
  background: var(--gold-wash);
  color: var(--gold);
}

.pager .ellipsis {
  color: var(--dim);
}

/* ==========================================================================
   18 — Empty, loading and error states
   ========================================================================== */

/* An empty state says what would be here and, where there is one, what to
   do about it. The mark is drawn at 12% so the space reads as considered
   rather than broken. */
.empty {
  display: grid;
  justify-items: center;
  gap: var(--s3);
  padding: var(--s7) var(--s5);
  text-align: center;
}

.empty .mark {
  width: 2.75rem;
  height: 2.2rem;
  opacity: 0.16;
}

.empty p {
  max-width: 34ch;
  color: var(--ash);
  font-size: 0.875rem;
}

td .empty {
  padding-block: var(--s6);
}

/* Loading. There is no client-side data fetching here — pages arrive
   rendered — so what needs covering is the wait after a submit or a
   navigation. A one-pixel gold line at the top of the viewport, driven by
   app.js, is the whole treatment. */
.progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  height: 2px;
  z-index: 200;
  background: var(--gold-solid);
  transform: scaleX(0);
  transform-origin: var(--flip, 1) center;
  opacity: 0;
  pointer-events: none;
}

body.is-busy .progress {
  opacity: 1;
  animation: progress 8s cubic-bezier(0.1, 0.8, 0.2, 1) forwards;
}

@keyframes progress {
  0% { transform: scaleX(0); }
  40% { transform: scaleX(0.55); }
  100% { transform: scaleX(0.97); }
}

/* A button that has been pressed says so, because a settlement that takes
   two seconds must not look like a click that missed. */
.btn[aria-busy="true"] {
  opacity: 0.65;
  pointer-events: none;
}

/* Skeleton rows, for anything that ever renders before its data. */
.skeleton {
  background: linear-gradient(
    90deg, var(--surface-raised), var(--surface-hover), var(--surface-raised)
  );
  background-size: 200% 100%;
  animation: shimmer 1.4s linear infinite;
  border-radius: var(--radius);
  color: transparent;
}

@keyframes shimmer {
  to { background-position: -200% 0; }
}

/* The full-page error screens (403/404/500). */
.notice-page {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--s4);
  min-height: 100svh;
  padding: var(--s6);
  text-align: center;
}

.notice-page .code {
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--gold);
}

.notice-page p {
  max-width: 42ch;
  color: var(--ash);
}

/* ==========================================================================
   19 — Sign in
   ========================================================================== */

/* The one screen a stranger sees. It is the brand's hero: black, the
   lockup, a single hairline, and nothing else competing. */
.gate {
  display: grid;
  grid-template-columns: 1fr;
  min-height: 100svh;
}

.gate-aside {
  display: none;
}

.gate-main {
  display: grid;
  place-items: center;
  padding: var(--s6) var(--s5);
}

.gate-form {
  width: 100%;
  max-width: 22rem;
}

.gate-form .brand {
  margin-block-end: var(--s6);
}

/* Direct child only: the language switcher inside .gate-foot is also a
   <form>, and a descendant selector here turned its two buttons into a
   stacked grid. */
.gate-form > form {
  display: grid;
  gap: var(--s4);
  margin-block-start: var(--s5);
}

.gate-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-block-start: var(--s5);
  padding-block-start: var(--s4);
  border-block-start: 1px solid var(--hair);
}

@media (min-width: 62rem) {
  .gate {
    grid-template-columns: 1.1fr 1fr;
  }

  /* The left half is the vault: the mark, oversized and cropped by the
     edge, with the tagline. No photography, no gradient — the brand does
     not fake metal with Photoshop. */
  .gate-aside {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: var(--s7) var(--s6);
    background: var(--ink-sunk);
    border-inline-end: 1px solid var(--gold-hair);
    overflow: hidden;
  }

  /* The mark at scale, held inside the panel rather than cropped to
     abstraction: at 5% on black it is a watermark, and a watermark that
     cannot be recognised is just a smudge. */
  .gate-aside .mark-huge {
    position: absolute;
    inset-block-end: 18%;
    inset-inline-end: 8%;
    width: clamp(8rem, 18vw, 15rem);
    color: var(--gold-solid);
    opacity: var(--watermark);
  }

  .gate-aside .tag-line {
    position: relative;
    display: grid;
    gap: var(--s2);
    padding-block-start: var(--s4);
    border-block-start: 1px solid var(--gold-hair);
  }
}

/* ==========================================================================
   20 — Fulfilment board
   ========================================================================== */

.board {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(15rem, 1fr);
  gap: var(--s3);
  overflow-x: auto;
  padding-block-end: var(--s3);
}

.column {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  min-width: 0;
}

.column-head {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s2) var(--s3);
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
}

.column-head .eyebrow {
  flex: 1;
  min-width: 0;
}

.tally {
  min-width: 1.4rem;
  padding: 0 0.3rem;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  font-size: 0.6875rem;
  text-align: center;
  color: var(--ash);
}

.column-head.has-work .tally {
  border-color: var(--gold-hair);
  background: var(--gold-wash);
  color: var(--gold);
}

.ticket {
  display: grid;
  gap: 0.2rem;
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  color: inherit;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

.ticket:hover {
  background: var(--surface-raised);
  border-color: var(--gold-hair);
}

.ticket .ref {
  color: var(--bone);
  font-weight: 500;
}

.ticket .line {
  font-size: 0.75rem;
  color: var(--ash);
}

.ticket-empty {
  padding: var(--s4) var(--s3);
  border: 1px dashed var(--hair);
  border-radius: var(--radius);
  font-size: 0.75rem;
  color: var(--dim);
  text-align: center;
}

/* ==========================================================================
   21 — Trail (timelines and event histories)
   ========================================================================== */

.trail {
  display: grid;
  gap: 0;
}

.trail li {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  padding: var(--s3) 0 var(--s3) 0;
  padding-inline-start: var(--s5);
  color: var(--ash);
  font-size: 0.875rem;
}

/* The spine and its nodes. A stamped step gets a filled gold node; one
   still to come gets a hollow one. */
.trail li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0.3rem;
  inset-block: 0;
  width: 1px;
  background: var(--hair);
}

.trail li:first-child::before { inset-block-start: 50%; }
.trail li:last-child::before { inset-block-end: 50%; }

.trail li::after {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: calc(var(--s3) + 0.45rem);
  width: 0.55rem;
  height: 0.55rem;
  border: 1px solid var(--hair-strong);
  background: var(--ink);
}

.trail li.done {
  color: var(--bone);
}

.trail li.done::after {
  background: var(--gold-solid);
  border-color: var(--gold-solid);
}

.trail li.done::before {
  background: var(--gold-hair);
}

.trail .trail-label {
  flex: 1;
  min-width: 0;
}

.trail .trail-when {
  font-size: 0.75rem;
  color: var(--dim);
  white-space: nowrap;
}

/* ==========================================================================
   22 — Documents and payloads
   ========================================================================== */

.doc {
  display: block;
  width: 100%;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  background: var(--ink-sunk);
}

.doc-tile {
  display: grid;
  gap: var(--s2);
}

.doc-tile .doc {
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.payload {
  max-height: 18rem;
  margin: 0;
  padding: var(--s3);
  overflow: auto;
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  color: var(--ash);
  font-size: 0.75rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  direction: ltr;
  text-align: start;
}

/* before -> after, as the audit log renders it. */
.change {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  flex-wrap: wrap;
  font-size: 0.8125rem;
}

.change .was {
  color: var(--dim);
  text-decoration: line-through;
}

.change .arrow {
  color: var(--gold);
  transform: scaleX(var(--flip));
}

.change .now {
  color: var(--bone);
}

/* ==========================================================================
   23 — Karat table
   ========================================================================== */

/* Gold is sold by karat here, and the table of what each karat is worth
   per gram is the most gold-business object on the screen. Ruled, not
   boxed. */
.karats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
}

.karat {
  padding: var(--s3) var(--s4);
  border-inline-start: 1px solid var(--hair);
}

.karat:first-child {
  border-inline-start: 0;
}

.karat-k {
  display: flex;
  align-items: baseline;
  gap: 0.25rem;
  color: var(--gold);
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
}

.karat-value {
  font-size: 0.9375rem;
  font-weight: 500;
}

/* ==========================================================================
   24 — Responsive
   ========================================================================== */

@media (max-width: 78rem) {
  :root {
    --rail: 14rem;
  }

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

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

  .price-chart {
    border-inline-start: 0;
    border-block-start: 1px solid var(--hair);
  }
}

@media (max-width: 60rem) {
  .shell {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Off-canvas. The rail keeps its markup and its order; only its
     positioning changes, so the tab order is the same on every device. */
  .rail {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    z-index: 60;
    width: min(19rem, 84vw);
    transform: translateX(calc(-102% * var(--flip)));
    transition: transform 0.22s ease;
  }

  .rail-toggle:checked ~ .shell .rail {
    transform: none;
  }

  .rail-toggle:checked ~ .rail-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 50;
    background: var(--scrim);
  }

  .rail-button {
    display: inline-grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    flex: none;
    border: 1px solid var(--hair);
    border-radius: var(--radius);
    color: var(--ash);
    cursor: pointer;
  }

  .rail-button:hover {
    color: var(--gold);
    border-color: var(--gold-hair);
  }

  .rail-button svg {
    width: 1rem;
    height: 1rem;
  }

  .page {
    padding: var(--s5) var(--s4) var(--s6);
  }

  .topbar {
    padding-inline: var(--s4);
  }
}

@media (max-width: 44rem) {
  .page-head {
    align-items: flex-start;
  }

  .ledger {
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  }

  .price-sides {
    grid-template-columns: 1fr;
  }

  .price-sides > * + * {
    border-inline-start: 0;
    border-block-start: 1px solid var(--hair);
  }

  .facts {
    grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  }

  /* Tables keep their columns and scroll. Reflowing a financial table into
     stacked key/value pairs destroys the one thing it is for — comparing a
     column of amounts — so it scrolls instead, with the first column
     pinned so a row can still be identified. */
  table.grid tbody td,
  table.grid thead th {
    padding: var(--s2) var(--s3);
  }

  .filterbar .field,
  .filterbar .field-search {
    flex: 1 1 100%;
  }

  .filterbar .filter-actions {
    margin-inline-start: 0;
  }

  .ticker .ticker-extra {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ==========================================================================
   25 — The handover slip
   ========================================================================== */

/* The one thing this console makes that leaves the building. It is signed
   by two people at the counter as gold changes hands, so it is drawn as
   the document it becomes: certificate stock, ink black, the mark struck
   at the head, and rules where a pen goes. The screen shows the paper
   rather than a preview of it. */

body.slip {
  background: var(--ink-sunk);
  padding: var(--s5) var(--s4) var(--s7);
}

.sheet {
  max-width: 48rem;
  margin-inline: auto;
  padding: 3rem;
  background: #f6f3ec;    /* certificate stock */
  color: #14161a;
  border: 1px solid var(--gold-hair);
}

.sheet-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s5);
  padding-block-end: var(--s4);
  border-block-end: 2px solid #14161a;
}

.sheet .mark {
  width: 2.5rem;
  height: 2rem;
  color: #14161a;
}

.sheet h1 {
  font-size: 1.125rem;
  letter-spacing: 0.02em;
}

.sheet .eyebrow {
  color: #6b6d73;
}

.sheet .ref {
  font-size: 1.25rem;
  font-weight: 600;
}

.sheet h2 {
  margin-block: var(--s5) var(--s3);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: #6b6d73;
}

.sheet .facts {
  margin-block-start: var(--s5);
  gap: var(--s4) var(--s5);
}

.sheet .facts dt {
  color: #6b6d73;
}

.sheet table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.sheet th {
  padding: 0.35rem 0.5rem;
  border-block-end: 1px solid #14161a;
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #6b6d73;
  text-align: start;
}

.sheet td {
  padding: 0.4rem 0.5rem;
  border-block-end: 1px solid #d8d4c9;
}

.sheet .num {
  text-align: end;
}

.signatures {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s6);
  margin-block-start: 3.5rem;
}

.signatures .rule {
  display: block;
  height: 2.5rem;
  border-block-end: 1px solid #14161a;
}

.signatures .caption {
  display: block;
  margin-block-start: var(--s2);
  font-size: 0.6875rem;
  color: #6b6d73;
}

.sheet-foot {
  margin-block-start: var(--s5);
  padding-block-start: var(--s3);
  border-block-start: 1px solid #d8d4c9;
  font-size: 0.75rem;
  color: #6b6d73;
}

.slip-bar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  max-width: 48rem;
  margin: 0 auto var(--s4);
}

/* ==========================================================================
   26 — Print
   ========================================================================== */

/* Anything printed leaves the vault: it goes on paper, in ink, for a
   customer to sign. So print is the brand's other half — black on white,
   no fills. Screens print rarely; the handover slip prints every day. */
@media print {
  .rail,
  .topbar,
  .noprint,
  .page-actions {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }

  .shell {
    grid-template-columns: 1fr;
  }

  .panel,
  .tablewrap,
  .ledger {
    border-color: #999;
    background: #fff;
  }

  table.grid thead th {
    background: #fff;
    color: #000;
    border-color: #999;
  }

  table.grid tbody td {
    border-color: #ddd;
  }
}
