/* AGC Paymaster — production theme derived from the approved interactive preview. */
:root {
  --preview-navy: #171d2a;
  --preview-navy-2: #1d2534;
  --preview-green: #46ad2f;
  /* Text, and anything white sits on. See --accent-ink in design-tokens:
     #278b22 was 4.35:1 on white, just under, and it is set at 9-10px here. */
  --preview-green-dark: var(--accent-ink);
  --preview-green-pale: #eef8ea;
  /* The accent as channels: tints of it were written as literal
     rgba(70,173,47,…) in a dozen rules, which held them at AGC green while
     var(--preview-green) followed the subsidiary theme. */
  --preview-green-rgb: 70, 173, 47;
  /* The three dark surfaces, named so a light house style can replace them.
     Sun Electronics is white-chromed; without these its sidebar and app bar
     would stay near-black under a teal accent. */
  /* The hero card keeps a dark surface in every house style, so its soft ink
     is its own token — the chrome greys above follow the sidebar, and under a
     light chrome they would go dark-on-dark here. */
  --preview-on-hero-soft: var(--ui-ink-ghost);
  --preview-canvas-hi: #f3f2ee; /* the desktop canvas, top and bottom */
  --preview-canvas-lo: #ecece7;
  --preview-chrome-bg: linear-gradient(180deg, #1c2431, #151b28 72%);
  --preview-topbar-bg: linear-gradient(90deg, #19202d, #171c28);
  --preview-hero-bg: linear-gradient(135deg, #202735, #16241e);
  --preview-ink: #171b25;
  /* These two were separate shades of tiers that already exist in
     design-tokens.css, close enough to be the same colour on screen. Point
     them at the resolved neutrals so the theme has one hairline and one muted
     ink rather than its own private pair. */
  --preview-slate: var(--ui-ink-muted);
  --preview-line: var(--ui-line);
  --preview-canvas: #efeee9;
  --preview-white: #fff;
  --preview-amber: var(--amber-ink);
  --preview-amber-pale: #fff7df;
  /* Set as text (the required-field asterisk), so it is an ink: #d8434f is
     4.34:1 on white and the asterisk is the only mark saying a field is
     required. */
  --preview-red: var(--danger-ink);
  --preview-red-pale: #fff0f1;
}

html, body.app-shell { min-height: 100%; }
body.app-shell {
  background-color: var(--preview-canvas);
  color: var(--preview-ink);
  font-family: Inter, Arial, sans-serif;
}
body.app-shell::before {
  background-size: 34px 34px;
  opacity: .32;
}
.app-shell a,
.app-shell a:hover,
.app-shell a:focus { text-decoration: none; }
.app-shell .accent-bar { height: 4px; background: var(--preview-green); }
.app-shell .shell {
  display: grid;
  grid-template-columns: 252px minmax(0, 1fr);
  /* A fixed frame, not a growing page. `.main` is already `100vh` with its
     own scroller, so a *taller* sidebar made the grid row taller than the
     window: the body grew to 1798px, the page got a second scrollbar that
     scrolled nothing, and the main column — still 100vh — clipped its own
     content halfway down the new-payment form. Twenty-five nav entries is
     taller than a laptop screen, so the sidebar scrolls itself instead. */
  height: calc(100vh - 4px);
  min-height: 0; overflow: hidden;
}

/* Sidebar */
.app-shell .sidebar {
  width: 252px;
  height: 100%; min-height: 0;
  display: flex; flex-direction: column;
  padding: 20px 16px 14px;
  background:
    radial-gradient(circle at 0 0, rgba(var(--preview-green-rgb), .13), transparent 35%),
    var(--preview-chrome-bg);
  border: 0;
  box-shadow: none;
}
.app-shell .brand-lockup { min-height: 48px; padding: 0 5px 18px; gap: 11px; }
.app-shell .brand-lockup svg { width: 37px; height: 37px; }
.app-shell .brand-lockup .brand-mark { height: 32px; max-width: 68px; padding: 5px 6px; border-radius: 8px; }
.app-shell .brand-name { font-size: 18px; letter-spacing: -.02em; }
.app-shell .subs-switch { margin: 16px 0 0; padding: 5px; border-radius: 12px; }
.app-shell .subs-opt { width: 100%; min-height: 40px; border-radius: 8px; font-size: 11.5px; }
.app-shell .new-btn {
  width: 100%; min-height: 43px; margin: 8px 0 23px;
  border: 1px solid rgba(var(--preview-green-rgb), .38);
  border-radius: 8px; background: rgba(var(--preview-green-rgb), .1);
  /* Sentence case, like the nav under it. It is the one button on the chrome;
     shouted at 9px it read as a section label with a border round it. */
  color: var(--chrome-accent-ink); font-size: 12px; font-weight: 600;
  letter-spacing: 0; text-transform: none;
}
.app-shell .new-btn:hover { background: rgba(var(--preview-green-rgb), .18); }
.app-shell .nav {
  gap: 1px; flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  /* Hairline, and only while scrolling — a scrollbar drawn permanently down
     the middle of the chrome is a second edge next to the real one. */
  scrollbar-width: thin; scrollbar-color: var(--chrome-line) transparent;
}
.app-shell .sidebar-foot { flex: none; }
.app-shell .brand-lockup,
.app-shell .new-btn,
.app-shell .subs-switch { flex: none; }
.app-shell .nav-section {
  margin: 14px 5px 4px; padding: 0;
  color: var(--chrome-section); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
}
.app-shell .nav-section:first-child { margin-top: 2px; }
/* A link that belongs to nothing above it — Admin, Feedback. A hairline
   instead of a section heading: a title over one entry is a heading nobody
   needed. */
.app-shell .nav a.nav-tail {
  margin-top: 10px; border-top: 1px solid var(--chrome-line-soft);
  padding-top: 10px;
}
.app-shell .nav a {
  /* Sentence case at 12px, not 10px uppercase with letter-spacing. Twenty-five
     shouted labels down the side of every screen is most of what "overbearing"
     meant, and uppercase is also the setting people read slowest. */
  min-height: 34px; margin: 0 -16px; padding: 0 20px;
  border-left: 3px solid transparent; border-radius: 0;
  color: var(--ui-ink-ghost); font-size: 12px; font-weight: 500;
  letter-spacing: 0; text-transform: none;
}
.app-shell .nav a svg { width: 17px; height: 17px; color: var(--ui-ink-dim); }
.app-shell .nav a:hover { background: var(--chrome-hover-bg); color: var(--chrome-ink); }
.app-shell .nav a.active {
  color: var(--chrome-ink); background: rgba(var(--preview-green-rgb), .1);
  border-left-color: var(--preview-green);
}
.app-shell .nav a.active svg { color: var(--preview-green); }
.app-shell .nav-count {
  min-width: 20px; padding: 1px 6px; font-size: 9px;
  background: var(--chrome-line); color: var(--chrome-ink);
}
.app-shell .nav-count--alert { background: rgba(216,67,79,.75); }
.app-shell .sidebar-foot {
  margin: auto 0 0; padding: 15px 4px 0;
  border-top-color: var(--chrome-line-soft);
}
/* The account block is a link to your own settings, so it needs to read as
   one: the avatar and name travel together and light up together. */
.app-shell .sidebar-foot .sidebar-account {
  display: flex; align-items: center; gap: 9px; min-width: 0;
  margin: -4px -6px; padding: 4px 6px; border-radius: 8px;
  color: inherit; transition: background .12s ease;
}
.app-shell .sidebar-foot .sidebar-account:hover { background: var(--chrome-hover-bg); }
.app-shell .sidebar-foot .avatar {
  flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 8px;
  background: var(--accent-ink); color: var(--color-on-primary);
}
.app-shell .sidebar-foot .who { display: block; min-width: 0; }
.app-shell .sidebar-foot .who { color: var(--chrome-ink); font-size: 11px; }
.app-shell .sidebar-foot .who small {
  margin-top: 3px; color: var(--ui-ink-mist); font-size: 9px; letter-spacing: .08em;
}
/* Sized like the other small buttons rather than a 7px label in a 50×46 box.
   .btn--ghost is drawn for a light card — its ink is --color-text-muted and
   its keyline a light grey — and this is the one that sits on the near-black
   chrome, where that ink was 2.7:1. */
.app-shell .sidebar-foot form .btn {
  min-height: 30px; padding: 0 12px; font-size: 9px; white-space: nowrap;
  color: var(--chrome-ink); box-shadow: inset 0 0 0 1px var(--chrome-line);
}
.app-shell .sidebar-foot form .btn:hover {
  background: var(--chrome-hover-bg); color: var(--chrome-ink);
  box-shadow: inset 0 0 0 1px var(--chrome-ink-muted);
}

/* Desktop application bar */
/* A column, not two boxes each guessing the other's height. `.app-content`
   used to be `calc(100vh - 74px)` — the topbar's height, written down twice —
   and any width where the topbar grew by a row put the bottom of the scroller
   below the window, with `.main` clipping and no page scrollbar to reach it.
   That is the Integrations page losing its last card. Now the topbar takes
   what it takes and the content is whatever is left. */
.app-shell .main {
  min-width: 0; height: calc(100vh - 4px); overflow: hidden;
  display: flex; flex-direction: column;
}
.app-shell .desktop-topbar { flex: none; }

/* When a payment is meant to go out, on the row. Late is stated in the ink
   as well as the date — a queue is scanned, not read. */
.preview-request-due strong.is-overdue { color: var(--danger-ink); }
.preview-request-due strong.is-undated { color: var(--color-text-muted); font-weight: 500; }
.desktop-topbar {
  height: 70px; display: flex; align-items: center; gap: 16px;
  padding: 0 42px;
  background: var(--preview-topbar-bg);
  color: var(--chrome-ink); border-bottom: 1px solid var(--chrome-line-soft);
}
/* The breadcrumb takes whatever is spare and truncates; it must never hold a
   width the bar cannot afford. `min-width: 260px` here used to push the search,
   the bell and the account block off the right-hand end between roughly 760 and
   880px — and `.main` clips rather than scrolls, so the account block (the only
   way to reach Log out) simply disappeared. */
.topbar-context {
  display: flex; align-items: center; gap: 10px;
  flex: 0 1 auto; min-width: 0; overflow: hidden;
  font-size: 10px; font-weight: 700; letter-spacing: .11em; text-transform: uppercase;
}
.topbar-context span { color: var(--chrome-ink-muted); }
.topbar-context i { color: var(--chrome-section); font-style: normal; }
/* Every step before the last one is a step back. They need to look pressable
   without turning the bar into a row of links — colour on hover, and the
   underline only then. */
/* A trail of links is not an inline link in a sentence, so WCAG 2.2's 24px
   target minimum applies. These were 11px tall. */
.topbar-context a {
  display: inline-flex; align-items: center; min-height: 24px;
  color: var(--chrome-ink-muted); text-decoration: none; white-space: nowrap;
  border-radius: 4px; transition: color .12s;
}
.topbar-context a:hover { color: var(--chrome-ink); text-decoration: underline; }
.topbar-context strong {
  max-width: 260px; overflow: hidden; color: var(--chrome-ink);
  text-overflow: ellipsis; white-space: nowrap;
}
.global-search {
  flex: 0 1 410px; min-width: 132px; height: 48px; margin-left: auto;
  display: flex; align-items: center; gap: 12px; padding: 0 13px;
  border: 1px solid var(--chrome-line); border-radius: 8px;
  background: var(--chrome-hover-bg);
}
.global-search svg { width: 17px; color: var(--ui-ink-soft); }
.global-search input {
  min-width: 0; flex: 1; border: 0 !important; outline: 0;
  padding: 0 !important; color: var(--chrome-ink); background: transparent !important;
  box-shadow: none !important; font-size: 10px;
}
.global-search input::placeholder { color: var(--ui-ink-dim); }
.global-search kbd {
  padding: 4px 6px; border: 1px solid var(--ui-line-dark); border-radius: 4px;
  color: var(--ui-ink-mist); font: 9px Inter, sans-serif;
}
.topbar-notifications {
  position: relative; display: grid; place-items: center;
  width: 38px; height: 38px; border: 1px solid var(--ui-line-dark);
  border-radius: 8px; color: var(--ui-ink-ghost);
}
.topbar-notifications svg { width: 17px; }
.topbar-notifications i {
  position: absolute; right: 8px; top: 8px; width: 5px; height: 5px;
  border-radius: 50%; background: var(--preview-green);
}
/* The account block is the only route to Log out, so it keeps its width while
   everything to its left gives way. */
.topbar-profile { display: flex; align-items: center; gap: 9px; white-space: nowrap; flex: 0 0 auto; }
.topbar-profile > span {
  display: grid; place-items: center; width: 32px; height: 32px;
  border-radius: 8px; background: var(--accent-ink);
  color: var(--color-on-primary); font-size: 9px; font-weight: 800;
}
.topbar-profile b { color: var(--chrome-ink); font-size: 9px; }
.app-content {
  flex: 1 1 auto; min-height: 0;
  overflow: auto; scrollbar-gutter: stable;
}

/* ── PAGE TITLE ─────────────────────────────────────────────────────────────
   One shape on every page, because a title that moves between screens reads
   as a different app on each of them. Left column: the name of the page, a
   line saying what it is for, and any badges describing *it*. Right column:
   the things you can do here. They share a top edge, so the eye finds the
   title in the same place every time, and the sub-line and the badges hang
   off it rather than floating at their own margins.
   ------------------------------------------------------------------------ */
.app-shell .pagehead {
  padding: 30px 42px 20px;
  border: 0; background: transparent; box-shadow: none;
}
.app-shell .pagehead .ph-row {
  display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap;
}
.app-shell .ph-title { flex: 1 1 340px; min-width: 0; }
/* Which part of the app the page is in, in the sidebar's own words. */
.app-shell .ph-kicker {
  margin: 0 0 2px; color: var(--preview-green-dark);
  font-size: 10.5px; font-weight: 600; letter-spacing: .13em; text-transform: uppercase;
}
.app-shell .pagehead h1 {
  color: var(--preview-ink); font-family: var(--font-display);
  font-size: clamp(22px, 2.4vw, 31px);
  font-weight: 500; line-height: 1.08; letter-spacing: -.035em;
  overflow-wrap: anywhere;
}
/* A message subject is not a page name — it is a sentence someone typed, and
   at 32px a long one takes the whole head. */
.app-shell.notification-page .pagehead h1 {
  font-size: clamp(19px, 1.5vw, 24px); letter-spacing: -.02em; line-height: 1.2;
}
.app-shell .page-summary {
  margin: 9px 0 0; color: var(--preview-slate);
  font-size: 12px; line-height: 1.5; max-width: 68ch;
}
/* Badges describe the page; buttons act on it. Keeping them on separate rows
   is what stopped the head reading as one long sentence of chips. */
.app-shell .ph-meta {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 11px;
}
.app-shell .ph-actions {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-left: auto; justify-content: flex-end; padding-top: 3px;
}
.app-shell .ph-actions form { display: flex; }
.app-shell .body { padding: 0 42px 42px; }
.app-shell .card,
.preview-surface {
  border: 1px solid rgba(213,216,210,.92);
  border-radius: 12px; background: rgba(255,255,255,.95);
  box-shadow: 0 5px 18px rgba(22,27,37,.055);
}
.app-shell .btn.preview-primary,
.app-shell .preview-primary {
  min-height: 43px; padding: 0 18px; border: 0;
  /* One flat accent, with the ink that reads on it.
     This was a gradient from --accent-ink to --agc-green-deep carrying a white
     label. Both of those tokens follow the operator's colour scheme, so on a
     dark page the button became a bright mint gradient and the label went to
     1.6:1 — the primary action on the screen, unreadable. The accent is a
     mid-tone on a light page and a bright one on a dark page; near-black reads
     on both ends of that, and white on neither. */
  border-radius: 8px; background: var(--accent-ink);
  color: var(--color-on-primary); box-shadow: 0 5px 14px rgba(var(--preview-green-rgb), .19);
  /* Sentence case, like every other button. This one was missed when the
     rest stopped shouting, so "SAVE DETAILS" was the loudest thing on a page
     whose job is a name and a phone number. */
  font-size: 12.5px; font-weight: 600; letter-spacing: 0; text-transform: none;
}
.app-shell .btn.preview-primary:hover,
.app-shell .preview-primary:hover {
  background: color-mix(in srgb, var(--accent-ink) 88%, var(--color-text));
  color: var(--color-on-primary);
}
.preview-eyebrow {
  display: block; color: var(--ui-ink-soft); font-size: 10px; font-weight: 800;
  letter-spacing: .2em; text-transform: uppercase;
}
.preview-eyebrow--light { color: var(--ui-ink-ghost); }
.preview-amber { color: var(--preview-amber) !important; }
.preview-section-heading {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  min-height: 42px; padding-bottom: 13px;
  border-bottom: 1px solid var(--ui-line-soft);
}
.preview-section-heading h2 {
  /* Sentence case. Uppercase at weight 800 turned every card heading into a
     banner, and a screen of banners has no hierarchy left to spend. */
  margin: 5px 0 0; padding: 0; border: 0;
  color: var(--preview-ink); font-size: 14px; font-weight: 600;
  letter-spacing: -.01em; text-transform: none;
}
.preview-section-heading > a {
  /* Sentence case, like the heading it sits opposite. Shouted at 10px it read
     as a second label rather than as the way out of the card. */
  color: var(--ui-ink-soft); font-size: 11.5px; font-weight: 600;
  letter-spacing: 0; text-transform: none;
}
.preview-section-heading > a span { margin-left: 5px; color: var(--preview-green-dark); }
.preview-vendor-logo {
  display: grid; place-items: center; width: 36px; height: 36px;
  flex: 0 0 auto; border: 1px solid rgba(var(--preview-green-rgb), .28); border-radius: 8px;
  background: var(--preview-green-pale); color: var(--preview-green-dark);
  font-size: 10px; font-weight: 800;
}
.preview-clear-state {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  min-height: 98px; color: var(--preview-slate);
}
.preview-clear-state > span {
  display: grid; place-items: center; width: 35px; height: 35px;
  border-radius: 50%; background: var(--preview-green-pale);
  color: var(--preview-green-dark); font-size: 16px; font-weight: 800;
}
.preview-clear-state strong,
.preview-clear-state small { display: block; }
.preview-clear-state strong { color: var(--preview-ink); font-size: 10px; }
.preview-clear-state small { margin-top: 3px; font-size: 10px; }

/* Dashboard */
.preview-dashboard-body {
  display: flex; flex-direction: column; gap: 14px;
}
.preview-hero-grid {
  /* minmax(0, …) or the tracks never go below their content: the two KPI
     cards hold unbreakable figures, so in GHS they took width from the
     exposure card until it was 233px wide and its own amount wrapped to three
     lines. The floor has to be 0 for the ratios to mean anything. */
  display: grid; gap: 14px;
  grid-template-columns: minmax(0, 1.52fr) minmax(0, .96fr) minmax(0, .96fr);
}
.preview-hero-card {
  min-height: 150px; display: flex; justify-content: space-between; gap: 20px;
  padding: 27px 25px 21px; border-radius: 12px; color: #fff;
  background:
    radial-gradient(circle at 92% 10%, rgba(var(--preview-green-rgb), .19), transparent 35%),
    var(--preview-hero-bg);
  box-shadow: 0 10px 25px rgba(20,28,34,.13);
}
.preview-hero-card strong {
  /* Sized for the longest figure this actually shows. A seven-digit GHS
     amount is "GH₵ 1,076,650.00" — sixteen characters against the four of
     "$ 386,222.00" — and the old size ran it past the edge of the card. It
     wraps rather than clips if a bigger number ever turns up. */
  display: block; margin-top: 10px; color: #fff;
  font-size: clamp(26px, 2.2vw, 34px); line-height: 1.02;
  letter-spacing: -.04em; font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
/* The whole symbol, however many characters it is — `::first-letter` took one
   and left "H₵" white. */
.preview-hero-card strong .cur-sym { color: var(--preview-green); font-style: normal; }
.preview-hero-card p { margin-top: 10px; color: var(--preview-on-hero-soft); font-size: 9px; }
.preview-hero-progress {
  width: 150px; align-self: flex-end; flex: 0 0 auto;
}
.preview-hero-progress span {
  display: flex; justify-content: space-between; color: var(--preview-on-hero-soft);
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
}
.preview-hero-progress span b { color: #fff; }
.preview-hero-progress > div {
  height: 5px; margin-top: 8px; overflow: hidden;
  border-radius: 999px; background: rgba(255,255,255,.12);
}
.preview-hero-progress i {
  display: block; height: 100%; border-radius: inherit;
  background: linear-gradient(90deg, var(--preview-green-dark), var(--preview-green));
}
.preview-quick-stat {
  min-height: 150px; display: flex; align-items: center; gap: 15px;
  padding: 25px 23px; border: 1px solid var(--preview-line);
  border-radius: 12px; background: var(--color-surface); color: var(--preview-ink);
  box-shadow: 0 5px 18px rgba(22,27,37,.055);
}
.preview-stat-icon {
  display: grid; place-items: center; width: 40px; height: 40px;
  flex: 0 0 auto; border-radius: 8px;
}
.preview-stat-icon svg { width: 20px; }
.preview-stat-icon--green { color: var(--preview-green-dark); background: var(--preview-green-pale); }
.preview-stat-icon--amber { color: var(--preview-amber); background: var(--preview-amber-pale); }
.preview-quick-stat small,
.preview-quick-stat strong,
.preview-quick-stat em { display: block; }
.preview-quick-stat small {
  color: var(--ui-ink-soft); font-size: 10px; font-weight: 800;
  letter-spacing: .16em; text-transform: uppercase;
}
.preview-quick-stat strong {
  margin-top: 7px; font-size: 24px; letter-spacing: -.035em;
  font-variant-numeric: tabular-nums;
}
.preview-quick-stat em {
  margin-top: 7px; color: var(--preview-green-dark); font-size: 10px; font-style: normal;
}
.preview-quick-stat em.preview-amber { color: var(--preview-amber); }
.preview-workflow-surface { padding: 17px 22px 20px; }
/* The workflow is a stepper: five stages in order, joined by one line.
   It used to lay each stage out sideways — the numbered node on the left with
   its label beside it — while the connector ran horizontally behind the whole
   row. The line therefore passed through the labels rather than between the
   nodes, and no label sat under the node it belonged to, so the five stages
   read as a loose row of text with circles scattered through it.

   Each stage now stacks under its own node, the columns are equal, and the
   line joins node centres only: at 5 equal columns and no gap, the first and
   last centres are at 10% and 90%. The nodes are opaque and sit above it. */
.preview-workflow {
  position: relative; display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 0; padding: 18px 0 2px;
}
.preview-workflow::before {
  content: ""; position: absolute; left: 10%; right: 10%; top: 37px;
  height: 2px; background: var(--ui-line); border-radius: 2px;
}
.preview-workflow > a {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 0 8px; color: inherit; min-width: 0;
}
.preview-workflow > a > span {
  display: grid; place-items: center; width: 40px; height: 40px;
  flex: 0 0 auto; border: 2px solid var(--ui-line); border-radius: 50%;
  background: var(--color-surface); color: var(--ui-ink-dim); font-size: 10px; font-weight: 800;
  transition: border-color .12s ease, color .12s ease;
}
.preview-workflow > a:hover > span {
  border-color: var(--preview-green); color: var(--preview-ink);
}
.preview-workflow > a.attention > span {
  border-color: #fff; background: var(--preview-amber);
  color: #fff; box-shadow: 0 0 0 5px var(--preview-amber-pale);
}
.preview-workflow > a > div { margin-top: 12px; min-width: 0; width: 100%; }
.preview-workflow small,
.preview-workflow strong,
.preview-workflow em { display: block; }
.preview-workflow small {
  color: var(--preview-ink); font-size: 10px; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.preview-workflow strong { margin-top: 5px; color: var(--preview-green-dark); font-size: 17px; }
.preview-workflow em { margin-top: 3px; color: var(--ui-ink-faint); font-size: 9px; font-style: normal; }
.preview-workflow .attention strong { color: var(--preview-amber); }
.preview-dashboard-grid {
  display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(300px, 1fr); gap: 14px;
}
.preview-attention-surface,
.preview-performance-card,
.preview-recent-surface { padding: 17px 22px; }
.preview-attention-list > a {
  min-height: 63px; display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto auto 12px;
  align-items: center; gap: 12px; color: inherit;
  border-bottom: 1px solid var(--ui-line-soft);
}
.preview-attention-list > a:last-child { border-bottom: 0; }
.preview-attention-list strong,
.preview-attention-list small { display: block; }
.preview-attention-list strong { font-size: 9px; }
.preview-attention-list small { margin-top: 3px; color: var(--ui-ink-faint); font-size: 9px; }
.preview-attention-amount { text-align: right; font-size: 10px; font-weight: 800; }
.preview-attention-amount small { font-weight: 400; }
.preview-chevron { color: var(--ui-ink-dim); font-size: 17px; }
.preview-legend {
  display: flex; align-items: center; gap: 6px;
  color: var(--ui-ink-faint); font-size: 9px; text-transform: uppercase;
}
.preview-legend i { width: 6px; height: 6px; border-radius: 4px; background: #536b7b; }
.preview-legend i:nth-of-type(2) { margin-left: 4px; background: var(--preview-green); }
.preview-chart { position: relative; height: 130px; margin-top: 10px; }
.preview-chart-grid {
  position: absolute; inset: 0 0 18px; display: flex;
  flex-direction: column; justify-content: space-between;
}
.preview-chart-grid i { display: block; border-top: 1px solid var(--ui-line-soft); }
.preview-chart-bars {
  position: absolute; inset: 10px 8px 0;
  display: grid; grid-template-columns: repeat(4, 1fr); align-items: end; gap: 14px;
}
.preview-chart-bars > span {
  height: 100%; display: flex; justify-content: center; align-items: end;
  gap: 5px; position: relative; padding-bottom: 18px;
}
.preview-chart-bars i,
.preview-chart-bars b {
  width: 10px; min-height: 2px; border-radius: 4px 4px 0 0;
  background: #536b7b;
}
.preview-chart-bars b { background: var(--preview-green); }
.preview-chart-bars small {
  position: absolute; bottom: 0; color: var(--ui-ink-dim); font-size: 9px;
}
.preview-period-tabs { display: flex; gap: 3px; }
.preview-period-tabs a {
  padding: 6px 10px; border-radius: 999px; color: var(--ui-ink-faint);
  font-size: 11px; font-weight: 600; text-transform: none;
}
/* A selected tab/chip is a dark pill, so it takes the theme's dark surface —
   --ui-line-darker is a hairline colour, and under a light chrome it left white
   text on a near-white pill. */
.preview-period-tabs a.active { color: var(--color-on-primary); background: var(--accent-ink); }
.preview-recent-table { margin-top: 14px; }
.preview-recent-row {
  min-height: 50px; display: grid;
  grid-template-columns: 1fr 1.55fr 1fr 1.1fr 1fr 18px;
  align-items: center; gap: 16px; padding: 0 13px;
  border-bottom: 1px solid var(--ui-line-soft); color: inherit; font-size: 10px;
}
.preview-recent-row:last-child { border-bottom: 0; }
.preview-recent-row > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.preview-recent-row small { display: block; margin-top: 2px; color: var(--ui-ink-faint); font-size: 9px; }
.preview-recent-head {
  min-height: 30px; border-radius: 8px 8px 0 0;
  /* A dark surface, so its ink is the one that goes ON a dark surface.
     --color-text is ink for a LIGHT one, and rendered #191e2b on #171d2a —
     1.01:1, a header row nobody could read. */
  background: var(--preview-navy); color: #fff;
  font-size: 9px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
}
.preview-mini-progress {
  display: inline-block; width: 75%; height: 5px; overflow: hidden;
  border-radius: 999px; background: #eceee9;
}
.preview-mini-progress b {
  display: block; height: 100%; border-radius: inherit; background: var(--preview-green);
}

/* Requests */
.preview-action-strip {
  min-height: 42px; margin-bottom: 10px; padding: 0 15px;
  display: flex; align-items: center; gap: 8px;
  border-left: 3px solid var(--preview-green); border-radius: 8px;
  background: var(--color-surface); color: var(--preview-slate); box-shadow: 0 3px 11px rgba(22,27,37,.04);
  font-size: 9px;
}
.preview-action-strip > span {
  display: grid; place-items: center; width: 21px; height: 21px;
  border-radius: 8px; background: var(--preview-green-pale);
  color: var(--preview-green-dark); font-weight: 800;
}
.preview-action-strip i {
  margin-left: auto; color: var(--preview-green-dark);
  font-size: 11.5px; font-style: normal; font-weight: 600; text-transform: none;
}
.preview-request-surface { padding: 20px; }
.preview-filter-bar {
  display: grid; grid-template-columns: minmax(270px, 360px) auto minmax(0, 1fr);
  align-items: center; gap: 8px; margin-bottom: 16px;
}
.preview-list-search {
  height: 43px; display: flex; align-items: center; gap: 11px;
  padding: 0 13px; border: 1px solid var(--ui-line); border-radius: 8px;
  background: var(--color-surface);
}
.preview-list-search svg { width: 16px; color: var(--ui-ink-soft); }
.preview-list-search input {
  min-width: 0; flex: 1; padding: 0 !important; border: 0 !important;
  background: transparent !important; box-shadow: none !important; font-size: 9px;
}
.preview-search-submit {
  height: 34px; padding: 0 12px; border: 1px solid var(--ui-line);
  border-radius: 8px; background: var(--color-surface); color: var(--ui-ink-muted);
  font-size: 11.5px; font-weight: 600; text-transform: none;
}
.preview-filter-chips {
  display: flex; align-items: center; gap: 5px; overflow-x: auto; scrollbar-width: none;
}
.preview-filter-chips::-webkit-scrollbar { display: none; }
.preview-filter-chips a {
  min-height: 31px; display: inline-flex; align-items: center; gap: 5px;
  padding: 0 11px; flex: 0 0 auto; border: 1px solid var(--ui-line);
  border-radius: 999px; color: var(--ui-ink-dim); background: var(--color-surface); font-size: 10px;
}
.preview-filter-chips a b { font-size: 9px; }
.preview-filter-chips a.active { border-color: var(--accent-ink); background: var(--accent-ink);
  color: var(--color-on-primary); }
.preview-request-list { display: flex; flex-direction: column; gap: 8px; }
/* Every row is its own grid container, so a content-sized track resolves
   independently on each one. The status column was `auto`, and the badges run
   from "Approved" to "Confirmed & closed" — 85px to 148px — so each row placed
   its columns somewhere different and the progress bars came out at three
   different lengths, none of them starting at the same x. The status column is
   fixed at the width of the longest badge; every other track is fr or fixed,
   which resolves identically against the same container width. */
.preview-request-row {
  /* Seven cells: vendor, requested, paid, due, progress, status, view. The
     due date went in as a seventh child of a six-column grid, so it took the
     progress bar's track and pushed the View button onto an implicit second
     row — a full-width button under every row, and the row itself wider than
     the list. A cell added here needs a track added with it. */
  min-height: 64px; display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, .62fr) minmax(0, .62fr)
                         minmax(0, .78fr) minmax(0, .8fr) 155px 108px;
  align-items: center; gap: 12px; padding: 0 14px;
  border: 1px solid var(--ui-line); border-radius: 8px;
  color: inherit; background: var(--color-surface); transition: border-color .14s, transform .14s;
}
.preview-request-row:hover {
  transform: translateY(-1px); border-color: rgba(var(--preview-green-rgb), .42);
  box-shadow: 0 4px 12px rgba(22,27,37,.05);
}
.preview-request-main { display: flex; align-items: center; gap: 11px; min-width: 0; }
.preview-request-main div { min-width: 0; }
.preview-request-main small,
.preview-request-main strong,
.preview-request-money small,
.preview-request-money strong,
.preview-request-progress small { display: block; }
.preview-request-main small { color: var(--ui-ink-faint); font-size: 9px; }
.preview-request-main strong {
  margin-top: 4px; overflow: hidden; font-size: 9px;
  text-overflow: ellipsis; white-space: nowrap;
}
.preview-request-money small,
.preview-request-progress small { color: var(--ui-ink-faint); font-size: 9px; }
.preview-request-money strong { margin-top: 5px; font-size: 9px; }
.preview-request-progress {
  display: grid; grid-template-columns: 1fr 25px; align-items: center; gap: 5px;
}
.preview-request-progress small { grid-column: 1 / -1; }
.preview-request-progress i {
  height: 5px; overflow: hidden; border-radius: 999px; background: #eceee9;
}
.preview-request-progress i b {
  display: block; height: 100%; border-radius: inherit; background: var(--preview-green);
}
.preview-request-progress em { color: var(--ui-ink-faint); font-size: 9px; font-style: normal; text-align: right; }
/* Left, not end: the column is now a fixed width, so ending them flush right
   would still leave the dots ragged down the list. */
.preview-request-status { justify-self: start; white-space: nowrap; }
.preview-view-button {
  display: grid; place-items: center; min-width: 42px; height: 31px;
  border: 1px solid var(--ui-line); border-radius: 8px;
  color: var(--ui-ink-muted); font-size: 11.5px; font-weight: 600; text-transform: none;
}
/* The decision, on the row. The invoice comes first because it has to be
   opened before the button beside it will work. */
.preview-request-act {
  display: flex; align-items: center; justify-content: flex-end; gap: 6px;
  min-width: 0;
}
.preview-request-act .btn { white-space: nowrap; }
.preview-request-act .btn[disabled] { opacity: .45; cursor: not-allowed; }
.preview-act-invoice {
  display: grid; place-items: center; height: 31px; padding: 0 8px;
  flex: 0 0 auto; border: 1px solid var(--ui-line); border-radius: 8px;
  color: var(--ui-ink-muted); font-size: 10px; font-weight: 700;
}
.preview-act-invoice.is-seen {
  border-color: rgba(var(--accent-rgb), .45); color: var(--accent-ink);
}

/* Vendor intake and request form */
.preview-portal-layout {
  display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(330px, 1fr);
  align-items: start; gap: 16px;
}
.preview-portal-field,
.preview-form-field {
  min-width: 0; display: flex; flex-direction: column; gap: 6px;
}
.preview-portal-field > span,
.preview-form-field > span {
  color: var(--color-text); font-size: 10px; font-weight: 700;
}
.preview-portal-field > span b,
.preview-form-field > span b { color: var(--preview-red); }
.preview-portal-field input:not([type="checkbox"]):not([type="radio"]),
.preview-portal-field select,
.preview-portal-field textarea,
.preview-form-field input:not([type="checkbox"]):not([type="radio"]),
.preview-form-field select,
.preview-form-field textarea {
  width: 100%; max-width: none; min-width: 0; height: 42px;
  border-color: var(--ui-line); border-radius: 8px;
  background: var(--color-surface); box-shadow: none; font-size: 9px;
}
.preview-portal-field textarea,
.preview-form-field textarea { height: 68px; min-height: 68px; resize: vertical; }
.preview-portal-field--vendor,
.preview-portal-field--description,
.preview-form-field--wide { grid-column: 1 / -1; }

/* ── The request, one question at a time ────────────────────────────────────
   The same fields and the same controls; what changed is how many of them are
   on screen. `.is-stepped` is set by the script, so with no JavaScript every
   panel stays visible and the page is the plain long form it always was. */
.wizard { display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: 26px; align-items: start; }
.wizard .errsum { grid-column: 1 / -1; }
.wizard-rail { display: flex; flex-direction: column; gap: 2px; position: sticky; top: 0; }
.wizard-step {
  display: flex; align-items: center; gap: 10px; text-align: left;
  padding: 9px 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--color-text-muted);
  font: inherit; font-size: 12.5px; cursor: pointer;
}
.wizard-step:hover { background: var(--color-surface-alt); }
.wizard-step.is-on { background: var(--color-surface); color: var(--color-text); font-weight: 600; box-shadow: var(--shadow-sm); }
.wizard-num {
  display: grid; place-items: center; width: 22px; height: 22px; flex: 0 0 auto;
  border: 1px solid var(--color-border); border-radius: 50%; font-size: 11px;
}
.wizard-step.is-on .wizard-num,
.wizard-step.is-done .wizard-num {
  border-color: var(--accent-ink); background: var(--accent-ink); color: var(--color-on-primary);
}
.wizard-step.is-done .wizard-num::after { content: "✓"; }
.wizard-step.is-done .wizard-num { font-size: 0; }
.wizard-panel {
  margin: 0; padding: 22px 24px; border: 1px solid var(--color-border);
  border-radius: 12px; background: var(--color-surface); box-shadow: var(--shadow-sm);
}
.wizard-panel + .wizard-panel { margin-top: 14px; }
.wizard.is-stepped .wizard-panel { display: none; margin-top: 0; }
.wizard.is-stepped .wizard-panel.is-on { display: block; }
/* A legend sits *on* the fieldset's top border by default, so the panel title
   straddled the card's edge — half on the white, half on the canvas behind
   it. Floated full-width it is an ordinary first line inside the card. */
.wizard-panel > legend {
  float: left; width: 100%; padding: 0; margin: 0;
  color: var(--color-text); font-size: 15px; font-weight: 600;
  letter-spacing: -.01em;
}
.wizard-panel > legend + * { clear: both; }
.wizard-hint { margin: 6px 0 0; color: var(--color-text-muted); font-size: 12px; line-height: 1.5; }
.wizard-fields {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px 16px; margin-top: 18px;
}
.wizard-move {
  display: flex; justify-content: flex-end; gap: 8px;
  margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--ui-line-soft);
}
.wizard-move [data-back] { margin-right: auto; }

/* The plan: amounts and dates, in the control an instalment date deserves. */
.plan-build {
  grid-column: 1 / -1; margin-top: 4px;
  /* The month on the left, the lines it makes on the right: picking a day and
     seeing what it did to the split is one movement, not a scroll. */
  display: grid; grid-template-columns: 320px minmax(0, 1fr);
  gap: 0 24px; align-items: start;
}
.plan-cal, .plan-cal-hint { grid-column: 1; }
.plan-split { grid-column: 2; grid-row: 1 / span 2; min-width: 0; }
/* The month the days are picked on. Sized so a whole month is one look:
   seven columns, square cells, and no scrolling inside it. */
.plan-cal {
  border: 1px solid var(--color-border); border-radius: 10px;
  padding: 10px 12px 12px; background: var(--color-surface-alt);
}
.plan-cal-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 8px;
}
.plan-cal-head strong { font-size: 12.5px; font-weight: 600; }
.plan-cal-nav {
  width: 28px; height: 28px; flex: none; cursor: pointer;
  border: 1px solid var(--color-border); border-radius: 8px;
  background: var(--color-surface); color: var(--color-text-muted);
  font-size: 15px; line-height: 1;
}
.plan-cal-nav:hover { color: var(--color-text); border-color: var(--agc-grey); }
.plan-cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px;
}
.plan-cal-dow {
  padding-bottom: 3px; text-align: center;
  color: var(--ui-ink-faint); font-size: 9.5px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
}
.plan-cal-day {
  aspect-ratio: 1; cursor: pointer;
  border: 1px solid transparent; border-radius: 8px;
  background: var(--color-surface); color: var(--color-text);
  font: inherit; font-size: 12px;
}
.plan-cal-day:hover { border-color: var(--agc-grey); }
/* A picked day is the loudest thing on the month — it is the whole answer
   the control is being asked for. */
.plan-cal-day.is-picked {
  background: var(--accent-ink); border-color: var(--accent-ink);
  color: var(--color-on-primary); font-weight: 600;
}
.plan-cal-day.is-today { border-color: var(--color-border); font-weight: 600; }
.plan-cal-day.is-today.is-picked { border-color: var(--accent-ink); }
.plan-cal-hint { margin: 9px 0 12px; }
.plan-build-head,
.plan-build-row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1.1fr) 76px minmax(0, 1fr) 30px;
  align-items: center; gap: 10px;
}
.plan-build-row--plain {
  grid-template-columns: 26px minmax(0, 1fr) minmax(0, 1fr);
}
.plan-build-date { font-size: 12.5px; color: var(--color-text); }
/* A line somebody typed a figure into keeps it; the others share what is
   left, so which is which has to be visible. */
.plan-build-row.is-fixed .plan-build-pct,
.plan-build-row.is-fixed .plan-build-amt { border-color: var(--accent-ink); }
.plan-build-head {
  padding-bottom: 6px; color: var(--ui-ink-faint); font-size: 10px;
  font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.plan-build-head > span { min-width: 0; overflow: hidden; }
.plan-build-row + .plan-build-row { margin-top: 8px; }
.plan-build-n { color: var(--color-text-muted); font-size: 12px; text-align: center; }
.plan-build-drop {
  width: 26px; height: 26px; border: 1px solid var(--color-border);
  border-radius: 8px; background: var(--color-surface);
  color: var(--color-text-muted); font-size: 15px; line-height: 1; cursor: pointer;
}
.plan-build-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 12px; flex-wrap: wrap;
}
.plan-build-total { font-size: 12px; color: var(--color-text-muted); }
.plan-build-total.is-ok { color: var(--accent-ink); }
.plan-build-total.is-off { color: var(--danger-ink); }

@media (max-width: 900px) {
  .wizard { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .wizard-rail { position: static; flex-direction: row; overflow-x: auto; }
  .wizard-step .wizard-name { display: none; }
  .wizard.is-stepped .wizard-step.is-on .wizard-name { display: inline; }
  .wizard-fields { grid-template-columns: minmax(0, 1fr); }
  .plan-build-head { display: none; }
  .plan-build-row {
    grid-template-columns: 22px minmax(0, 1fr) 62px minmax(0, 1fr) 26px; gap: 6px;
  }
  .plan-build-row--plain { grid-template-columns: 22px minmax(0, 1fr) minmax(0, 1fr); }
  .plan-build { grid-template-columns: minmax(0, 1fr); }
  .plan-cal, .plan-cal-hint, .plan-split { grid-column: 1; }
  .plan-split { grid-row: auto; }
}

/* A tick box is not a box you type in. The rules above size every control in
   the grid to the height of a text field, and a checkbox stretched to that
   came out a 42px square with its question sitting above it — which is what
   "to big" meant. It reads left to right instead: the box, then the sentence
   it answers, on one line. */
.preview-check {
  display: flex; align-items: center; gap: 9px;
  min-height: 42px; font-weight: 500;
}
.preview-check input[type="checkbox"] {
  width: 16px; height: 16px; flex: 0 0 auto; margin: 0;
  accent-color: var(--accent-ink);
}
.preview-money-input { position: relative; }
.preview-money-input .money-field-prefix { left: 12px; color: var(--preview-green-dark); }
.preview-money-input input { padding-left: 31px !important; }
.preview-form-field small {
  color: var(--ui-ink-faint); font-size: 10px; line-height: 1.3;
}
/* Bring remaining server-rendered pages into the same design system. */
.app-shell:not(.dashboard-page):not(.requests-page):not(.request-form-page) .body > .card,
.app-shell:not(.dashboard-page):not(.requests-page):not(.request-form-page) .body .card {
  border-radius: 12px;
}
.app-shell .tbl-wrap { border-radius: 8px; box-shadow: 0 4px 15px rgba(22,27,37,.045); }
.app-shell table.data thead th { background: var(--preview-navy); }
.app-shell .toolbar,
.app-shell .logbar { margin-bottom: 13px; }
.app-shell .search { border-radius: 8px; background: var(--color-surface); }
.app-shell table.data.plan .plan-action .btn,
.app-shell [data-pay-line].btn {
  min-width: 58px; white-space: nowrap; writing-mode: horizontal-tb;
}

/* Mobile implementation */
@media (max-width: 760px) {
  body.app-shell {
    min-height: 100dvh; padding: 0 0 64px;
    overflow-x: hidden; background: var(--preview-canvas);
  }
  .app-shell .accent-bar,
  .desktop-topbar { display: none; }
  .app-shell .mobile-dashboard-bar {
    height: 58px; padding: 0 13px; border-bottom: 1px solid var(--ui-line);
    background: rgba(255,255,255,.97); backdrop-filter: blur(12px);
  }
  .app-shell .mobile-menu-button {
    width: 36px; height: 36px; border-radius: 8px;
    border: 1px solid var(--ui-line); background: var(--color-surface);
  }
  .app-shell .mobile-brand { margin-left: 8px; font-size: 15px; }
  .app-shell .mobile-brand svg { width: 23px; height: 23px; color: var(--preview-navy); }
  .app-shell .mobile-brand .brand-mark { height: 24px; max-width: 50px; }
  .app-shell .mobile-module {
    margin-left: auto; padding: 5px 10px; border: 1px solid var(--ui-line);
    border-radius: 999px; color: var(--ui-ink-muted); background: var(--color-surface-alt);
    font-size: 9px; font-weight: 800; letter-spacing: .08em;
  }
  .app-shell .mobile-new-request {
    width: 38px; height: 38px; margin-left: 8px; border-radius: 8px;
    background: var(--preview-green); box-shadow: 0 4px 10px rgba(var(--preview-green-rgb), .2);
  }
  .app-shell .shell { display: block; min-height: 0; }
  .app-shell .main { height: auto; min-height: calc(100dvh - 122px); overflow: visible; }
  .app-content { height: auto; overflow: visible; }
  .app-shell .sidebar {
    width: min(300px, 84vw); min-height: 100dvh; padding-top: 20px;
  }
  .app-shell .pagehead {
    min-height: 0; padding: 10px 12px 9px; background: transparent;
  }
  /* On a phone the two columns become two rows: the title, then whatever you
     can do about it. Nothing is held on one line here — that is what used to
     push a page head past the edge of the screen. */
  .app-shell .pagehead .ph-row { align-items: flex-start; flex-wrap: wrap; gap: 8px; }
  .app-shell .pagehead h1 { font-size: 20px; letter-spacing: -.035em; }
  /* The app bar above already says AGC Group / <company> / <page>, and the
     dashboard head here is clipped to a fixed height — a second line naming
     the section would be the one that got cut in half. */
  .app-shell .ph-kicker,
  .app-shell .page-summary { display: none; }
  .app-shell .ph-title { flex: 1 1 100%; }
  .app-shell .ph-meta { margin-top: 7px; }
  .app-shell .ph-meta .badge { font-size: 9px; }
  .app-shell .ph-actions { margin-left: 0; width: 100%; justify-content: flex-start; }
  .app-shell .ph-actions .btn.preview-primary,
  .app-shell .ph-actions .chips { display: grid; grid-template-columns: 1fr 1fr; width: 100%; gap: 7px; }
  .app-shell .ph-actions .chips .chip { padding: 8px 7px; text-align: center; }
  .app-shell .body { padding: 0 10px 14px; }
  .app-shell .mobile-bottom-nav {
    height: 64px; padding: 6px 7px 5px;
    border-top: 1px solid var(--ui-line);
    background: rgba(255,255,255,.97); backdrop-filter: blur(13px);
    box-shadow: 0 -7px 22px rgba(22,27,37,.06);
  }
  .app-shell .mobile-bottom-nav a {
    min-width: 0; gap: 3px; color: var(--ui-ink-muted); font-size: 9px;
  }
  .app-shell .mobile-bottom-nav a svg { width: 19px; height: 19px; }
  .app-shell .mobile-bottom-nav a.active { color: var(--preview-green-dark); }
  .app-shell .mobile-bottom-nav .mobile-bottom-create {
    width: 48px; height: 48px; min-height: 48px; margin-top: -16px;
    border-radius: 16px; color: #fff; background: var(--preview-green);
    box-shadow: 0 8px 20px rgba(var(--preview-green-rgb), .3);
  }
  .app-shell .mobile-bottom-nav .mobile-bottom-create svg { width: 23px; height: 23px; }

  .preview-section-heading { min-height: 31px; padding-bottom: 8px; }
  .preview-section-heading h2 { margin-top: 3px; font-size: 13px; }
  .preview-eyebrow { font-size: 9px; }
  .preview-vendor-logo { width: 30px; height: 30px; border-radius: 8px; font-size: 9px; }

  /* Dashboard stays on one phone canvas, as in the approved preview. */
  body.preview-dashboard { height: 100dvh; overflow: hidden; padding-bottom: 0; }
  .preview-dashboard .main { height: calc(100dvh - 58px); min-height: 0; overflow: hidden; }
  .preview-dashboard .app-content { height: 100%; overflow: hidden; }
  .preview-dashboard .pagehead { height: 48px; overflow: hidden; }
  .preview-dashboard .preview-dashboard-body {
    height: calc(100% - 48px); gap: 7px; padding-bottom: 70px; overflow: hidden;
  }
  .preview-hero-grid { grid-template-columns: 1fr 1fr; gap: 6px; }
  .preview-hero-card {
    grid-column: 1 / -1; min-height: 76px; padding: 11px 14px;
    border-radius: 12px;
  }
  .preview-hero-card strong { margin-top: 5px; font-size: 24px; }
  .preview-hero-card p { margin-top: 4px; font-size: 9px; }
  .preview-hero-progress { width: 100px; }
  .preview-hero-progress span { font-size: 9px; }
  .preview-hero-progress > div { margin-top: 5px; height: 4px; }
  .preview-quick-stat {
    min-height: 58px; padding: 8px 10px; gap: 8px; border-radius: 8px;
  }
  .preview-stat-icon { width: 28px; height: 28px; border-radius: 8px; }
  .preview-stat-icon svg { width: 14px; }
  .preview-quick-stat small { font-size: 9px; }
  .preview-quick-stat strong { margin-top: 3px; font-size: 14px; }
  .preview-quick-stat em { margin-top: 2px; font-size: 9px; }
  .preview-workflow-surface { padding: 8px 9px 9px; }
  .preview-workflow-surface .preview-section-heading { min-height: 24px; padding-bottom: 5px; }
  .preview-workflow-surface .preview-section-heading > a { display: none; }
  .preview-workflow {
    grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; padding: 6px 0 0;
  }
  .preview-workflow::before { display: none; }
  .preview-workflow > a {
    min-height: 48px; padding: 4px 2px; flex-direction: column; gap: 2px;
    border: 1px solid var(--ui-line-soft); border-radius: 8px; background: var(--color-surface-alt); text-align: center;
  }
  .preview-workflow > a > span { width: 20px; height: 20px; border-width: 1px; font-size: 9px; }
  .preview-workflow > a > div { min-width: 0; width: 100%; }
  .preview-workflow small { overflow: hidden; font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }
  .preview-workflow strong { margin-top: 1px; font-size: 10px; }
  .preview-workflow em { display: none; }
  .preview-dashboard-grid { display: block; }
  .preview-attention-surface { padding: 8px 10px; }
  .preview-attention-list > a {
    min-height: 47px; grid-template-columns: 28px minmax(0, 1fr) auto auto;
    gap: 7px;
  }
  .preview-attention-list .preview-vendor-logo { width: 28px; height: 28px; }
  .preview-attention-list strong { font-size: 9px; }
  .preview-attention-list small { margin-top: 1px; font-size: 9px; }
  .preview-attention-amount { font-size: 9px; }
  .preview-attention-amount small,
  .preview-attention-list .preview-chevron { display: none; }
  .preview-attention-list .badge { font-size: 9px; }
  .preview-performance-card,
  .preview-recent-surface { display: none; }

  /* Requests retain the reference design but collapse cleanly. */
  .preview-action-strip {
    min-height: 30px; margin-bottom: 6px; padding: 0 9px; font-size: 9px;
  }
  .preview-action-strip > span { width: 17px; height: 17px; font-size: 9px; }
  .preview-action-strip i { display: none; }
  .preview-request-surface { padding: 8px; }
  .preview-filter-bar {
    grid-template-columns: minmax(0, 1fr) auto; gap: 5px; margin-bottom: 7px;
  }
  .preview-list-search { height: 33px; padding: 0 9px; gap: 7px; }
  .preview-list-search svg { width: 14px; }
  .preview-list-search input { font-size: 9px; }
  .preview-search-submit { height: 29px; padding: 0 8px; font-size: 9px; }
  .preview-filter-chips {
    grid-column: 1 / -1; display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 3px;
  }
  .preview-filter-chips a {
    min-width: 0; min-height: 25px; padding: 0 2px;
    justify-content: center; gap: 2px; font-size: 9px; white-space: nowrap;
  }
  .preview-filter-chips a b { font-size: 9px; }
  .preview-request-list { gap: 5px; }
  .preview-request-row {
    min-height: 66px; grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto auto auto; gap: 3px 8px; padding: 6px 8px;
  }
  .preview-request-main { grid-column: 1; grid-row: 1; gap: 7px; }
  .preview-request-main .preview-vendor-logo { display: none; }
  .preview-request-main small { font-size: 9px; }
  .preview-request-main strong { margin-top: 2px; font-size: 9px; }
  /* Placed by class, not by nth-of-type: a third money block was added and
     the counting rules put it in the wrong column. */
  .preview-request-money { grid-row: 2; padding-top: 2px; border-top: 1px solid var(--ui-line-soft); }
  .preview-request-money--requested { grid-column: 1; }
  .preview-request-money--paid { grid-column: 2; text-align: right; }
  /* The due date reads as a sentence on its own line here rather than as a
     third column 80px wide. */
  .preview-request-due {
    grid-column: 1 / -1; grid-row: 3; border-top: 0; padding-top: 0;
    display: flex; align-items: baseline; gap: 5px;
  }
  .preview-request-due small { display: inline; }
  .preview-request-money small { font-size: 9px; }
  .preview-request-money strong { margin-top: 1px; font-size: 9px; }
  .preview-request-progress { grid-column: 1 / -1; grid-row: 4; grid-template-columns: 1fr 20px; }
  .preview-request-progress small { display: none; }
  .preview-request-status { grid-column: 2; grid-row: 1; align-self: center; }
  .preview-request-status .badge { font-size: 9px; }
  /* On a phone the decision gets its own full-width row rather than being
     dropped: a manager approving from a phone is the ordinary case, not the
     exception. "View" is what goes — the whole row opens the payment. */
  .preview-request-act { grid-column: 1 / -1; grid-row: 5; justify-content: stretch; }
  .preview-request-act form { flex: 1 1 auto; }
  .preview-request-act .btn { width: 100%; justify-content: center; }
  .preview-view-button { display: none; }
  .preview-request-act:has(> .preview-view-button) { display: none; }

  /* Vendor form and request creation fit without losing required fields. */
  .preview-portal-layout{ grid-template-columns: minmax(0, 1fr); gap: 7px; }
  .preview-portal-field,
  .preview-form-field { gap: 3px; }
  .preview-portal-field > span,
  .preview-form-field > span { font-size: 9px; }
  .preview-portal-field input:not([type="checkbox"]):not([type="radio"]),
  .preview-portal-field select,
  .preview-form-field input:not([type="checkbox"]):not([type="radio"]),
  .preview-form-field select { height: 33px; font-size: 9px; }
  .preview-check { min-height: 33px; gap: 7px; }
  .preview-portal-field--description,
  .preview-form-field--description { display: none; }
.preview-form-field small { display: none; }
  .request-detail-page .tbl-wrap:not(.recent-table) table.data.plan tbody > tr.plan-row {
    display: grid; grid-template-columns: 24px minmax(0, 1fr) minmax(64px, auto);
    gap: 4px 8px; margin-bottom: 6px; padding: 8px 9px;
  }
  /* app.css right-aligns cells in its stacked-table treatment below 560px, and
     that selector out-specifies a plain `.plan-row > td`. This row is a grid,
     not a stacked table, so it has to win outright — otherwise the plan reads
     left-aligned at 700px and right-aligned at 375px. `.app-shell` and
     `.request-detail-page` are both on <body>. */
  .app-shell.request-detail-page .tbl-wrap table.data.plan tbody > tr.plan-row > td {
    display: block; width: auto; min-width: 0; padding: 0; text-align: left;
  }
  .request-detail-page table.data.plan tr.plan-row > td::before { display: none; }
  .request-detail-page table.data.plan .plan-sequence {
    grid-column: 1; grid-row: 1 / 3; display: grid; place-items: center;
    border-radius: 8px; background: var(--color-surface-alt); color: var(--ui-ink-dim);
    font-size: 9px; font-weight: 800;
  }
  .request-detail-page table.data.plan .plan-status { grid-column: 2; grid-row: 1; align-self: center; }
  .request-detail-page table.data.plan .plan-date {
    grid-column: 2; grid-row: 2; color: var(--ui-ink-faint); font-size: 9px;
  }
  .request-detail-page table.data.plan .plan-amount {
    grid-column: 3; grid-row: 1; align-self: center; justify-self: end;
    font-size: 9px; font-weight: 800; white-space: nowrap;
  }
  .request-detail-page table.data.plan .plan-action {
    grid-column: 3; grid-row: 2; display: flex; justify-content: flex-end;
  }
  .request-detail-page table.data.plan .plan-action .btn {
    min-width: 58px; min-height: 27px; padding: 5px 10px;
    line-height: 1; white-space: nowrap; writing-mode: horizontal-tb;
  }
  /* Method and reference are dropped from the narrow row by default — a
     scheduled line has nothing to put in them. A settled line does, and on a
     MoMo payment the reference cell carries the wallet that was credited,
     which is the one detail on this row that cannot be recovered from
     anywhere else. So paid rows get a third line spanning the row. */
  .request-detail-page table.data.plan .plan-method,
  .request-detail-page table.data.plan .plan-reference { display: none !important; }
  /* Four rows once the method and reference are back, so the number badge
     spans all of them rather than stopping short of the last line. */
  .request-detail-page table.data.plan tr.plan-row--paid .plan-sequence { grid-row: 1 / 5; }
  .request-detail-page table.data.plan tr.plan-row--paid .plan-method,
  .request-detail-page table.data.plan tr.plan-row--paid .plan-reference {
    display: block !important; grid-column: 2 / -1; min-width: 0;
    font-size: 9px; line-height: 1.35;
  }
  .request-detail-page table.data.plan tr.plan-row--paid .plan-method {
    grid-row: 3; margin-top: 5px;
    color: var(--ui-ink-dim); font-weight: 700;
  }
  .request-detail-page table.data.plan tr.plan-row--paid .plan-reference {
    grid-row: 4; color: var(--ui-ink-faint);
  }
  .request-detail-page table.data.plan tr.plan-row--paid .plan-reference code {
    font-size: 9px; overflow-wrap: anywhere;
  }
  .request-detail-page table.data.plan tr.plan-row--paid .plan-reference .plan-momo {
    margin-top: 1px; font-size: 9px; color: var(--ui-ink-soft);
  }

  .app-shell .toast-wrap { bottom: 76px; }
}

@media (max-width: 760px) and (max-height: 650px) {
  .preview-dashboard .preview-dashboard-body { gap: 5px; }
  .preview-dashboard .preview-dashboard-grid { margin-top: -1px; }
  .preview-dashboard .preview-attention-surface { padding: 5px 8px; }
  .preview-dashboard .preview-attention-surface .preview-section-heading {
    min-height: 18px; padding-bottom: 3px;
  }
  .preview-dashboard .preview-attention-list > a {
    min-height: 35px; padding: 3px 0;
  }
  .preview-dashboard .preview-attention-list > a:nth-child(n + 2) { display: none; }
  .preview-requests .preview-action-strip { display: none; }
  .preview-requests .preview-request-row { min-height: 52px; padding-top: 4px; padding-bottom: 4px; }
  .preview-requests .preview-request-main small { display: none; }
  .preview-requests .preview-request-money { border-top: 0; }
}

@media (min-width: 761px) and (max-width: 1100px) {
  .app-shell .shell { grid-template-columns: 218px minmax(0, 1fr); }
  .app-shell .sidebar { width: 218px; }
  .desktop-topbar { padding-left: 28px; padding-right: 28px; }
  .app-shell .pagehead { padding-left: 28px; padding-right: 28px; }
  .app-shell .body { padding-left: 28px; padding-right: 28px; }
  /* Three side-by-side hero cards do not fit once the rail takes 218px: the
     figures are unbreakable, so the fr tracks were being overrun and the
     exposure card was squeezed to ~58px with its amount sheared off. Give the
     exposure card the full width and let the two KPIs share the row below. */
  .preview-hero-grid { grid-template-columns: 1fr 1fr; }
  .preview-hero-grid > .preview-hero-card { grid-column: 1 / -1; }
  .preview-request-row {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, .72fr) minmax(0, .72fr)
                           minmax(0, .8fr) minmax(0, .85fr) 148px 104px;
    gap: 9px;
  }
  .preview-portal-layout{ grid-template-columns: minmax(0, 1.3fr) minmax(280px, .8fr); }
}

/* Desktop refinement — stronger hierarchy and soft, layered depth.
   The interface stays visually flat enough for an operations tool, while
   light, shadow and overlap make related elements feel connected. */
@media (min-width: 761px) {
  :root {
    --preview-surface-shadow:
      0 1px 1px rgba(26, 32, 43, .04),
      0 8px 20px rgba(26, 32, 43, .07),
      0 22px 48px rgba(26, 32, 43, .045);
    --preview-surface-shadow-hover:
      0 2px 3px rgba(26, 32, 43, .05),
      0 14px 30px rgba(26, 32, 43, .11);
  }

  body.app-shell {
    background:
      radial-gradient(circle at 18% 0%, rgba(var(--preview-green-rgb), .055), transparent 28rem),
      radial-gradient(circle at 95% 12%, rgba(34, 53, 68, .045), transparent 30rem),
      linear-gradient(180deg, var(--preview-canvas-hi) 0%, var(--preview-canvas-lo) 100%);
  }
  body.app-shell::before { opacity: .2; }

  .app-shell .sidebar {
    box-shadow: 12px 0 35px rgba(15, 20, 30, .12);
  }
  .app-shell .new-btn {
    min-height: 48px; border-radius: 12px; font-size: 10px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.06), 0 8px 18px rgba(0,0,0,.13);
  }
  .app-shell .nav a {
    min-height: 46px; font-size: 11px; letter-spacing: .055em;
  }
  .app-shell .nav-section { margin-top: 18px; font-size: 10px; }

  .desktop-topbar {
    height: 74px;
    box-shadow: 0 9px 26px rgba(21, 27, 39, .14);
  }
  .topbar-context { font-size: 9px; }
  .global-search {
    width: min(450px, 40vw); height: 46px; border-radius: 12px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.035);
  }
  .global-search input { font-size: 12px; }
  .topbar-profile b { font-size: 11px; }
  .topbar-profile > span { width: 36px; height: 36px; border-radius: 12px; font-size: 11px; }

  .app-shell .pagehead {
    position: static; top: auto; z-index: auto;
    padding: 32px 42px 22px;
  }
  /* Kept in step with the scale above. This asked for 46px at -.052em, and
     two rules disagreeing about the size of the h1 is how it ends up depending
     on load order. */
  .app-shell .pagehead h1 {
    font-size: clamp(24px, 2.4vw, 31px);
    line-height: 1.08; letter-spacing: -.035em;
  }
  .app-shell .page-summary {
    margin-top: 10px; max-width: 680px; font-size: 14px; line-height: 1.5;
  }
  .app-shell .body { padding: 0 42px 52px; }

  .app-shell .card,
  .preview-surface,
  .preview-quick-stat,
  .preview-request-surface {
    border-color: rgba(207, 211, 204, .82);
    border-radius: 16px;
    background: linear-gradient(145deg, rgba(255,255,255,.99), rgba(251,252,249,.96));
    box-shadow: var(--preview-surface-shadow);
  }
  .app-shell .card {
    position: relative;
  }
  .app-shell .card::after {
    content: ""; position: absolute; inset: 0; z-index: 0;
    border-radius: inherit; pointer-events: none;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.95);
  }
  .app-shell .card > * { position: relative; z-index: 1; }

  /* The accent glow belongs to the button that carries the accent. Given to
     every .btn it put a 20px green halo under outline buttons too — an Edit
     link on a white card sat in a soft green cloud, which is most of what
     "floating" meant on these screens. And 10px was a label size: a 46px
     button with a 10px word in the middle is mostly padding. */
  .app-shell .btn,
  .app-shell .btn.preview-primary,
  .app-shell .preview-primary {
    min-height: 42px; padding-left: 18px; padding-right: 18px;
    border-radius: 10px; font-size: 12.5px;
  }
  .app-shell .btn.preview-primary,
  .app-shell .preview-primary,
  .app-shell .btn:not(.btn--ghost):not(.btn--secondary):not(.btn--icon) {
    box-shadow: 0 1px 2px rgba(var(--preview-green-rgb), .22), 0 5px 12px rgba(var(--preview-green-rgb), .13);
  }
  .app-shell .btn:hover,
  .app-shell .btn.preview-primary:hover,
  .app-shell .preview-primary:hover { transform: translateY(-1px); }
  .app-shell .btn.preview-primary:hover,
  .app-shell .preview-primary:hover,
  .app-shell .btn:not(.btn--ghost):not(.btn--secondary):not(.btn--icon):hover {
    box-shadow: 0 2px 4px rgba(var(--preview-green-rgb), .26), 0 9px 18px rgba(var(--preview-green-rgb), .18);
  }
  .app-shell .btn--sm { min-height: 34px; padding-left: 13px; padding-right: 13px; font-size: 11.5px; }
  .app-shell .btn--icon { min-height: 30px; width: 30px; padding: 0; }

  .preview-eyebrow { font-size: 9px; letter-spacing: .18em; }
  .preview-section-heading {
    min-height: 50px; padding-bottom: 15px;
  }
  .preview-section-heading h2 { margin-top: 6px; font-size: 15px; }
  .preview-section-heading > a { font-size: 9px; }
  .preview-vendor-logo {
    width: 44px; height: 44px; border-radius: 12px; font-size: 10px;
    box-shadow: inset 0 1px 0 #fff, 0 5px 12px rgba(var(--preview-green-rgb), .16);
  }
  .preview-clear-state { min-height: 160px; gap: 16px; }
  .preview-clear-state > span { width: 48px; height: 48px; font-size: 20px; }
  .preview-clear-state strong { font-size: 14px; }
  .preview-clear-state small { margin-top: 5px; font-size: 11px; }

  /* Dashboard */
  .preview-dashboard-body { gap: 20px; }
  .preview-hero-grid { gap: 18px; }
  .preview-hero-card {
    position: relative; overflow: hidden;
    min-height: 176px; padding: 30px 29px 25px; border-radius: 16px;
    background:
      radial-gradient(circle at 88% 6%, rgba(var(--preview-green-rgb), .3), transparent 34%),
      radial-gradient(circle at 5% 110%, rgba(var(--preview-green-rgb), .12), transparent 38%),
      var(--preview-hero-bg-lg, var(--preview-hero-bg));
    box-shadow: 0 2px 3px rgba(11,17,24,.2), 0 18px 40px rgba(15,24,27,.2);
  }
  .preview-hero-card::before {
    content: ""; position: absolute; inset: 1px;
    border-radius: 16px; pointer-events: none;
    border: 1px solid rgba(255,255,255,.06);
  }
  .preview-hero-card strong {
    margin-top: 12px; font-size: clamp(28px, 2.2vw, 37px);
  }
  .preview-hero-card p { margin-top: 12px; font-size: 12px; }
  .preview-hero-progress {
    position: absolute; right: 29px; bottom: 27px; width: 150px;
  }
  .preview-hero-progress span { font-size: 9px; }
  .preview-hero-progress > div { height: 7px; margin-top: 10px; }

  .preview-quick-stat {
    min-height: 176px; gap: 18px; padding: 28px 25px;
  }
  .preview-quick-stat:hover {
    transform: translateY(-2px); box-shadow: var(--preview-surface-shadow-hover);
  }
  .preview-stat-icon { width: 50px; height: 50px; border-radius: 16px; }
  .preview-stat-icon svg { width: 23px; }
  .preview-quick-stat small { font-size: 9px; }
  .preview-quick-stat strong {
    /* Same reason as the exposure figure: sized for a seven-digit GHS amount
       in a third of the row, and wrapping beats clipping if a longer one
       arrives. `nowrap` here pushed it straight out of the card. */
    margin-top: 9px; font-size: clamp(17px, 1.5vw, 26px);
    overflow-wrap: anywhere;
  }
  .preview-quick-stat em { margin-top: 8px; font-size: 10px; }

  .preview-workflow-surface { padding: 22px 27px 25px; }
  /* Larger nodes, so the connector moves down to stay on their centre: 24px
     padding + half of a 48px node. Columns stay equal and gapless so 10%/90%
     still lands on the first and last centres. */
  .preview-workflow { gap: 0; padding: 24px 0 4px; }
  .preview-workflow::before { left: 10%; right: 10%; top: 48px; }
  .preview-workflow > a { padding: 0 10px; }
  .preview-workflow > a > div { margin-top: 14px; }
  .preview-workflow > a > span {
    width: 48px; height: 48px; font-size: 10px;
    box-shadow: 0 5px 12px rgba(28, 36, 43, .06);
  }
  .preview-workflow > a.attention > span {
    box-shadow: 0 0 0 7px var(--preview-amber-pale), 0 7px 15px rgba(194,128,0,.15);
  }
  .preview-workflow small { font-size: 11px; }
  .preview-workflow strong { margin-top: 5px; font-size: 21px; }
  .preview-workflow em { margin-top: 3px; font-size: 9px; }

  .preview-dashboard-grid { gap: 18px; }
  .preview-attention-surface,
  .preview-performance-card,
  .preview-recent-surface { padding: 22px 27px; }
  .preview-attention-list > a {
    min-height: 80px; grid-template-columns: 44px minmax(0,1fr) auto auto 14px;
    gap: 15px; padding: 5px 4px;
  }
  .preview-attention-list > a:hover {
    margin: 0 -10px; padding-left: 14px; padding-right: 14px;
    border-radius: 12px; background: linear-gradient(90deg, #f5faf2, rgba(245,250,242,.25));
  }
  .preview-attention-list strong { font-size: 13px; }
  .preview-attention-list small { margin-top: 5px; font-size: 10px; }
  .preview-attention-amount { font-size: 14px; }
  .preview-legend { font-size: 9px; }
  .preview-legend i { width: 8px; height: 8px; }
  .preview-chart { height: 165px; margin-top: 15px; }
  .preview-chart-bars small { font-size: 9px; }
  .preview-chart-bars i,
  .preview-chart-bars b { width: 13px; }
  .preview-period-tabs a { padding: 7px 12px; font-size: 11.5px; }

  .preview-recent-table { margin-top: 17px; }
  .preview-recent-row {
    min-height: 64px; gap: 18px; padding: 0 16px; font-size: 11px;
  }
  .preview-recent-row small { margin-top: 4px; font-size: 9px; }
  .preview-recent-head { min-height: 36px; border-radius: 8px 8px 0 0; font-size: 10px; }
  .preview-mini-progress { height: 7px; }

  /* Requests */
  .preview-action-strip {
    min-height: 52px; margin-bottom: 14px; padding: 0 18px; gap: 11px;
    border-radius: 12px; font-size: 12px;
    box-shadow: 0 7px 20px rgba(22,27,37,.055);
  }
  .preview-action-strip > span { width: 27px; height: 27px; border-radius: 8px; }
  .preview-action-strip i { font-size: 11.5px; }
  .preview-request-surface { padding: 25px; }
  .preview-filter-bar {
    grid-template-columns: minmax(310px, 410px) auto minmax(0,1fr);
    gap: 10px; margin-bottom: 20px;
  }
  .preview-list-search { height: 49px; gap: 12px; padding: 0 15px; border-radius: 12px; }
  .preview-list-search input { font-size: 12px; }
  /* The toolbar is read at the same size as the list it filters. At 9px the
     chips and the Search button were half the size of the rows underneath,
     which is what made a plain filter bar look like fine print. */
  .preview-search-submit { height: 40px; padding: 0 15px; border-radius: 8px; font-size: 11.5px; }
  /* Room enough to wrap rather than scroll: a chip cut in half at the card's
     edge reads as a broken layout, and there is no scrollbar to say otherwise
     on a desktop. Sideways scrolling stays the answer on a phone. */
  .preview-filter-chips { gap: 7px; flex-wrap: wrap; overflow: visible; }
  .preview-filter-bar { align-items: start; }
  .preview-filter-chips a { min-height: 36px; padding: 0 13px; font-size: 11.5px; }
  .preview-filter-chips a b { font-size: 11.5px; }
  .preview-request-list { gap: 11px; }
  .preview-request-row {
    min-height: 84px;
    /* Seven tracks. Every breakpoint that restates this has to restate all of
       them: a six-track version here left the due date holding the progress
       bar's column and the View button on a row of its own, which is what put
       a full-width button under every row. */
    grid-template-columns: minmax(0, 1.35fr) minmax(0, .7fr) minmax(0, .7fr)
                           minmax(0, .82fr) minmax(0, .85fr) 160px 112px;
    gap: 14px; padding: 0 17px; border-radius: 12px;
    box-shadow: 0 3px 9px rgba(22,27,37,.025);
  }
  .preview-request-row:hover {
    transform: translateY(-3px); border-color: rgba(var(--preview-green-rgb), .38);
    box-shadow: var(--preview-surface-shadow-hover);
  }
  .preview-request-main { gap: 13px; }
  .preview-request-main small { font-size: 9px; }
  .preview-request-main strong { margin-top: 5px; font-size: 12px; }
  .preview-request-money small,
  .preview-request-progress small { font-size: 9px; }
  .preview-request-money strong { margin-top: 6px; font-size: 13px; }
  .preview-request-progress { grid-template-columns: 1fr 31px; gap: 7px; }
  .preview-request-progress i { height: 7px; }
  .preview-request-progress em { font-size: 9px; }
  .preview-view-button { min-width: 56px; height: 38px; border-radius: 8px; font-size: 11.5px; }

  /* Intake and form pages */
  .preview-portal-layout{ align-items: stretch; gap: 20px; }
  .preview-portal-field,
  .preview-form-field { gap: 8px; }
  .preview-portal-field > span,
  .preview-form-field > span { font-size: 11px; }
  .preview-portal-field input:not([type="checkbox"]):not([type="radio"]),
  .preview-portal-field select,
  .preview-portal-field textarea,
  .preview-form-field input:not([type="checkbox"]):not([type="radio"]),
  .preview-form-field select,
  .preview-form-field textarea {
    height: 49px; padding-left: 14px; padding-right: 14px;
    border-radius: 12px; font-size: 12px;
    box-shadow: inset 0 1px 2px rgba(22,27,37,.025);
  }
  .preview-portal-field textarea,
  .preview-form-field textarea { height: 94px; min-height: 94px; padding-top: 13px; }
  .preview-check { min-height: 49px; gap: 11px; }
  .preview-check input[type="checkbox"] { width: 18px; height: 18px; }
  .preview-money-input .money-field-prefix { left: 14px; font-size: 14px; }
  .preview-money-input input { padding-left: 38px !important; }
  .preview-form-field small { font-size: 10px; }
  /* Remaining server-rendered screens share the same scale and rhythm. */
  .app-shell:not(.dashboard-page):not(.requests-page):not(.request-form-page) .body > .card,
  .app-shell:not(.dashboard-page):not(.requests-page):not(.request-form-page) .body .card {
    padding: 25px 27px; border-radius: 16px;
  }
  .app-shell .toolbar,
  .app-shell .logbar { margin-bottom: 17px; gap: 11px; }
  .app-shell .search { min-height: 45px; padding: 10px 14px; border-radius: 12px; }
  .app-shell .search input { font-size: 13px; }
  .app-shell .chip { min-height: 34px; padding: 8px 14px; font-size: 11px; }
  .app-shell .tbl-wrap {
    border-radius: 16px;
    box-shadow: 0 7px 22px rgba(22,27,37,.065);
  }
  .app-shell table.data { font-size: 13px; }
  .app-shell table.data thead th,
  .app-shell table.data > tr:first-child th { padding: 13px 16px; font-size: 9px; }
  .app-shell table.data td { padding: 14px 16px; }
  .app-shell .badge { font-size: 9px; }
  .app-shell .flow,
  .app-shell .grid-2 { gap: 22px; }
}

/* Between the two: seven tracks fit without overflowing, but only by
   breaking "GH₵ 18,750.00" across two lines — and a payment figure split down
   the middle is the misreading the thousand separators exist to prevent. The
   progress bar yields instead. It is a bar and a percentage; the amount is
   the number somebody reads off the row. */
@media (min-width: 1101px) and (max-width: 1330px) {
  .preview-request-row {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, .9fr) minmax(0, .9fr)
                           minmax(0, .9fr) 148px 104px;
  }
  .preview-request-progress { display: none; }
}

@media (min-width: 761px) and (max-width: 1100px) {
  .app-shell .pagehead { padding-left: 28px; padding-right: 28px; }
  .app-shell .body { padding-left: 28px; padding-right: 28px; }
  /* Progress is dropped at these widths; the decision is not. The button on
     the row is the reason the queue can be worked at all, and hiding it on a
     laptop would mean the one screen an approver lives in is the one that
     asks them to open every payment. The status badge keeps its full width —
     the badges run to "Confirmed & closed" — and the vendor name ellipses. */
  .preview-request-row {
    /* Six tracks in the width of five: the vendor name yields (it ellipses),
       the status badge is trimmed to the widest badge that actually appears
       at this size, and the gap tightens — because the alternative was
       "$ 184,500.00" breaking across two lines, which is the misreading the
       thousand separators exist to prevent. Measured, not guessed. */
    grid-template-columns: minmax(0, .95fr) minmax(0, .82fr) minmax(0, .82fr)
                           minmax(0, .82fr) 132px 96px;
    gap: 10px; padding: 0 12px;
  }
  .preview-request-progress { display: none; }
}

/* ── Page head controls ─────────────────────────────────────────────────────
   The module toggle and the create button are one row of controls, so they are
   one size: same height, same radius, same type. They previously differed in
   all three — pill chips at 11px next to a 43px uppercase button — and sat at
   the foot of the heading block, level with the summary line rather than with
   the title they belong to.

   They live in .ph-actions now — one column of controls opposite the title —
   so the rules below address that group rather than loose children of the row.
   ------------------------------------------------------------------------ */
@media (min-width: 761px) {
  .app-shell .pagehead .ph-actions .chips { flex-wrap: nowrap; gap: 8px; align-items: stretch; }
  .app-shell .pagehead .ph-actions .chips .chip,
  .app-shell .pagehead .ph-actions .btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 42px; padding: 0 18px; border-radius: 8px;
    /* Sentence case: "INTERNATIONAL · USD" is the loudest text on a page
       whose job is a queue of payments, and it is a control, not a heading. */
    font-size: 12.5px; font-weight: 600; letter-spacing: 0;
    text-transform: none; white-space: nowrap;
  }
  .app-shell .pagehead .ph-actions .chips .chip {
    border: 1px solid var(--ui-line); background: var(--color-surface); color: var(--ui-ink-soft);
  }
  .app-shell .pagehead .ph-actions .chips .chip:hover {
    border-color: var(--preview-green); color: var(--preview-ink);
  }
  /* The module you are in is drawn in the chrome, the way the sidebar draws
     the company you are in — one visual idea for "where you are standing",
     kept clear of the accent, which here means "act on this". */
  .app-shell .pagehead .ph-actions .chips .chip.on {
    background: var(--agc-dark); border-color: transparent; color: #fff;
  }
}

/* Three hero cards abreast need more room than the 1100px the stacked layout
   used to stop at — a GHS figure is "GH₵ 1,027,200.00" where a USD one is
   "$ 232,500.00", and at 1200px the three of them together simply do not fit.
   Keep the exposure card full-width, with the two KPIs beneath it, until
   there is genuinely space for a row of three. */
@media (min-width: 1101px) and (max-width: 1560px) {
  .preview-hero-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .preview-hero-grid > .preview-hero-card { grid-column: 1 / -1; }
}

/* Below about 860px the rail still takes 218px, leaving each half-width KPI
   card ~140px for its figure. A GHS amount does not fit that at a readable
   size, so the three cards take the full width one under the other rather
   than being squeezed. */
@media (min-width: 761px) and (max-width: 860px) {
  .preview-hero-grid { grid-template-columns: minmax(0, 1fr); }
  .preview-hero-grid > .preview-hero-card { grid-column: 1; }
}

/* The plan carries seven columns inside the narrower of the two detail
   columns, where the shared table padding (16px a side, so 224px of the card
   spent on padding alone) left the reference cell about 86px of usable width —
   enough to break "MP2407.9911.X" across two lines while every other column
   sat comfortably. The plan gets tighter cells than the full-width tables, and
   the reference keeps enough room for a wallet number on one line. */
@media (min-width: 761px) {
  .app-shell table.data.plan thead th,
  .app-shell table.data.plan td { padding-left: 8px; padding-right: 8px; }
  .app-shell table.data.plan td.plan-reference,
  .app-shell table.data.plan th:nth-child(5) { min-width: 152px; }
}
