/* ==========================================================================
   AutoRemit marketing site — single stylesheet
   --------------------------------------------------------------------------
   Contents
     1. Design tokens (custom properties)
     2. Reset + base typography
     3. Utilities (layout wrap, kickers, chips, buttons, reveal)
     4. Header + navigation
     5. Hero + processing vignette
     6. Audience strip
     7. How it works (steps)
     8. Guardrails (dark band)
     9. References (three cards)
    10. Proof: activity feed + demo (two-up)
    11. FAQ
    12. Final CTA
    13. Footer
    14. Legal pages (privacy.html / terms.html)
    15. Responsive
    16. Reduced motion
   --------------------------------------------------------------------------
   Brand palette is fixed — do not change these three:
     deep blue #1A5BAD · brand blue #1F7AC4 · brand green #6CB33F
   Neutrals are derived cool greys/navies and may be tuned.
   ========================================================================== */

/* 1. Design tokens ------------------------------------------------------- */
:root {
  /* brand — fixed */
  --c-deep:  #1A5BAD;
  --c-blue:  #1F7AC4;

  /* neutrals */
  --ink:    #17273F;   /* near-navy body text */
  --ink-2:  #4C5D77;   /* muted text */
  --ink-3:  #8090A8;   /* faint text, captions */
  --paper:  #FBFCFE;   /* page background */
  --wash:   #F2F6FA;   /* alternate section background */
  --line:   #DFE7F0;   /* hairlines */

  /* dark band */
  --navy:      #13233F;
  --navy-line: rgba(255, 255, 255, 0.14);
  --on-navy:   #C4D2E6; /* body text on navy */
  --on-navy-2: #8FA3C0; /* muted text on navy */

  /* functional tints (UI states, not brand recolours) */
  --blue-wash:  #E9F1FA;

  /* type */
  --font-sans: "Montserrat", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Consolas, monospace;

  /* Surfaces — taken from the application (frontend/src/components/ui.jsx).
     The product is BORDERED AND FLAT, not floating: across Dashboard, Settings
     and AdminSettings there is exactly one box-shadow, and it is an inset
     hairline. The site previously used a 40px ambient drop shadow on every card,
     which is the single biggest reason the two read as different products. */
  --radius: 12px;        /* ui.jsx Card */
  --radius-sm: 8px;      /* ui.jsx Button / StatCard */
  --radius-bar: 10px;    /* ui.jsx blue CardHeader */
  --card-line: #e5e7eb;  /* ui.jsx Card border */
  --app-bg: #f9fafb;     /* index.css body background */
  --shadow: 0 1px 2px rgba(19, 35, 63, 0.04);
  --header-h: 88px;

  /* Layout + rhythm. Declared once so spacing is a system rather than a set of
     per-element margins — §10/§12 of the review. */
  --container: 1120px;
  --gutter: clamp(18px, 4vw, 34px);
  --space-section: clamp(56px, 7vw, 88px);   /* was up to 108px: the page read as
                                                disconnected slabs rather than one
                                                document */
  --space-block: 34px;     /* block -> block inside a section */
  --pad-card: 22px;        /* card padding, closer to the product's density */

  /* Button system — copied from ui.jsx Button, including the 2px bottom edge
     and the press-down interaction, which is the product's most recognisable
     control behaviour. */
  --btn-primary-bg: #1F7AC4;
  --btn-primary-border: #1A5BAD;
  --btn-primary-edge: #0F4A8E;
  --btn-default-bg: linear-gradient(to bottom, #fff, #f3f4f6);
  --btn-default-border: #d1d5db;
  --btn-default-edge: #c4c7cc;
  --btn-default-text: #374151;

  /* Badge pairs — copied verbatim from ui.jsx Badge. Note that the product's
     "matched/confirmed" badge is INDIGO, not green: green is reserved for true
     success (posted). The site previously used green for matched, which
     contradicts the product's own status language. */
  --badge-matched-bg: #EBF0FD;  --badge-matched-text: #0D2E80;
  --badge-info-bg:    #E6F1FB;  --badge-info-text:    #0C447C;
  --badge-amber-bg:   #FAEEDA;  --badge-amber-text:   #633806;
  --badge-gray-bg:    #f3f4f6;  --badge-gray-text:    #374151;
  --badge-success-bg: #E1F5EE;  --badge-success-text: #0F6E56;

  /* Light-blue surface + its hairline, from the product's dashboard summary
     panel: a tinted rounded container holding white pill chips. This is a
     distinctive AutoRemit surface the site was not using at all. */
  --surface-blue: #EAF2FF;
  --surface-blue-line: #93B4F5;
}

/* 2. Reset + base -------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* The header is a pill with 12px of rail above and below (8px once scrolled), so
   its occupied height is --header-h + 24 unscrolled and + 16 scrolled. The offset
   was + 16, which is exact for the scrolled state only — an anchor jump landed
   the section edge 8px under the panel. Sized for the TALLER state plus a little
   clearance, so a section top is never tucked behind the pill in either state. */
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--header-h) + 32px); }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { margin: 0 0 0.6em; line-height: 1.15; letter-spacing: -0.015em; text-wrap: balance; }
h2 { font-size: clamp(1.55rem, 2.8vw, 2.15rem); font-weight: 700; }
h3 { font-size: 1.12rem; font-weight: 700; }

p { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: var(--c-deep); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--c-blue); }

img { max-width: 100%; height: auto; display: block; }

::selection { background: var(--blue-wash); color: var(--c-deep); }

:focus-visible { outline: 3px solid rgba(31, 122, 196, 0.5); outline-offset: 2px; border-radius: 4px; }

/* 3. Utilities ----------------------------------------------------------- */
.wrap { max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }

.section { padding-block: var(--space-section); }
.section--wash { background: var(--wash); }

/* small over-line label above headings */
/* Sans, not mono. The application's own chrome uses no monospace at all — the
   site's mono kickers/labels were reading as a different product's typography.
   Mono is retained ONLY for genuine ledger data (references, amounts, addresses)
   in the vignette, where it behaves as data rather than decoration. */
.kicker {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-blue);
  margin-bottom: 14px;
}

.lede { font-size: 1.08rem; color: var(--ink-2); max-width: 58ch; }

.mono { font-family: var(--font-mono); }

/* skip link */
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--c-deep); color: #fff; padding: 10px 16px; z-index: 100;
  font-weight: 600; border-radius: 0 0 8px 0;
}
.skip:focus { left: 0; color: #fff; }

/* Status chips = the product's Badge (ui.jsx): pill radius 20, sans, 11px/500,
   borderless tint. The site's mono/uppercase/bordered chips were a different
   component language entirely.
   SEMANTICS MATTER MORE THAN COLOUR HERE. In the product an auto-confirmed match
   is the INDIGO "matched" badge; green (#E1F5EE/#0F6E56) means posted/success,
   and amber means something needs a person. The site previously painted matched
   rows green, which promised a settled state the product does not claim yet. */
.chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-sans);
  font-size: 0.69rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  padding: 2px 8px;
  border-radius: 20px;
  border: 1px solid transparent;
  white-space: nowrap;
}
/* Status pills map 1:1 onto the application's own badge palette
   (components/ui.jsx Badge) and carry only labels that exist in the product's
   status map (lib/statusPill.js). Nothing here is invented:
     Confirmed      confirmed            -> green  #EBF0FD / #0D2E80  (indigo)
     Review         review               -> amber  #FAEEDA / #633806
     Pending        pending              -> amber
     Partially paid posted_part_payment  -> blue   #E6F1FB / #0C447C
     Scanned        parsed               -> blue
     Processing     processing           -> gray   #f3f4f6 / #374151
     Posted         posted/synced/…      -> success #E1F5EE / #0F6E56
   Note the product has TWO greens: `green` is the indigo Matched/Confirmed tint,
   and `success` is the only true green — reserved for a posted payment. */
.chip--auto   { background: var(--badge-matched-bg); color: var(--badge-matched-text); }
.chip--review { background: var(--badge-amber-bg);   color: var(--badge-amber-text); }
.chip--part   { background: var(--badge-info-bg);    color: var(--badge-info-text); }
.chip--info   { background: var(--badge-info-bg);    color: var(--badge-info-text); }
.chip--gray   { background: var(--badge-gray-bg);    color: var(--badge-gray-text); }
.chip--posted { background: var(--badge-success-bg); color: var(--badge-success-text); }

/* buttons */
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-sans);
  font-size: 0.95rem; font-weight: 600;
  padding: 13px 24px;
  border-radius: 8px;
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}
/* Press-down interaction from ui.jsx .btn3d: hover sinks 1px, active sinks 2px
   and drops the edge. Marketing keeps larger padding; everything else matches. */
.btn:hover { transform: translateY(1px); }
.btn:active { transform: translateY(2px); box-shadow: none; }
.btn--primary {
  background: var(--btn-primary-bg); color: #fff;
  border-color: var(--btn-primary-border);
  box-shadow: 0 2px 0 var(--btn-primary-edge), 0 1px 3px rgba(0, 0, 0, 0.15);
}
.btn--primary:hover { background: var(--btn-primary-bg); color: #fff; }
.btn--ghost {
  background: var(--btn-default-bg); color: var(--btn-default-text);
  border-color: var(--btn-default-border);
  box-shadow: 0 2px 0 var(--btn-default-edge), 0 1px 3px rgba(0, 0, 0, 0.08);
}
.btn--ghost:hover { background: var(--btn-default-bg); color: var(--btn-default-text); }
.btn--sm { padding: 9px 18px; font-size: 0.88rem; }
.btn .arrow { font-family: var(--font-mono); font-weight: 500; }

/* scroll-reveal: JS adds .in when the element enters the viewport.
   --d is an optional per-element stagger delay, e.g. style="--d:.15s" */
[data-reveal] { opacity: 0; transform: translateY(14px); transition: opacity 0.55s ease var(--d, 0s), transform 0.55s ease var(--d, 0s); }
[data-reveal].in { opacity: 1; transform: none; }
.no-js [data-reveal] { opacity: 1; transform: none; } /* graceful without JS */

/* 4. Header -------------------------------------------------------------- */
/* The header is an INSET ROUNDED BLUE PANEL, not a full-bleed bar.
   AutoRemit's chrome is a rounded blue panel sitting inside a light page — the
   sidebar (#1A5BAD) and every page title bar (#1F7AC4, borderRadius 10) are
   contained surfaces with the app background visible around them. A strip
   welded to both browser edges is a marketing-template convention, not this
   product's. The rail below is transparent-over-paper so the panel floats in the
   page, and it stays sticky. */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--paper);
  /* The page gutter lives HERE, not on .wrap: the header markup is
     `<div class="wrap header-in">`, i.e. the container and the blue panel are the
     SAME element, so any padding on .wrap becomes padding INSIDE the panel and the
     panel still touches both edges. Putting the gutter on the header insets the
     panel itself, which is the whole point of the treatment. */
  padding: 10px var(--gutter);
  transition: padding 0.2s ease;
}

.header-in {
  display: flex; align-items: center; gap: 28px;
  /* Positioning context for the mobile dropdown. Without this the dropdown
     resolved against .site-header (sticky) and used top:var(--header-h) with
     left/right:0 — i.e. it opened 12px too high, overlapping the pill's lower
     edge, and spanned the full page width while the pill is inset by the gutter.
     Anchored to the pill instead, it lines up with the panel at every width and
     survives the .scrolled padding change automatically. */
  position: relative;
  height: var(--header-h);
  background: var(--c-deep);
  border-radius: 14px;          /* panel language, scaled up from the app's 10 */
  /* The panel's INNER padding must equal the page gutter, or the header contents
     sit on a different vertical alignment from the page contents. With a fixed
     22px the logo landed 12px left of the hero headline and the panel overhung
     the vignette by 34px at every width — the header read as a separate object
     bolted above the page rather than the top of the same column. */
  padding-inline: var(--gutter);
  box-shadow: 0 1px 2px rgba(19, 35, 63, 0.06);
  transition: box-shadow 0.2s ease;
}
/* On scroll the panel lifts slightly instead of the page growing a hard edge. */
.site-header.scrolled { padding-block: 8px; }
.site-header.scrolled .header-in { box-shadow: 0 10px 24px -14px rgba(19, 35, 63, 0.55); }

/* Buttons sitting ON the blue chrome take the product's DEFAULT (white) variant,
   not the primary blue one — brand blue on deep blue has almost no contrast and
   stops reading as a control. This mirrors Settings.jsx, where the "Add rule"
   button inside a blue CardHeader is the default white button. */
.site-header .btn--primary {
  background: var(--btn-default-bg); color: var(--btn-default-text);
  border-color: var(--btn-default-border);
  box-shadow: 0 2px 0 var(--btn-default-edge), 0 1px 3px rgba(0, 0, 0, 0.18);
}
.site-header .btn--primary:hover { background: var(--btn-default-bg); color: var(--btn-default-text); }

/* clear space rule: the logo keeps ≥ one chevron height of padding on all
   sides — the header height and flex gaps provide it. Don't crowd this. */
.logo-link { display: inline-flex; flex-shrink: 0; }
/* The wordmark is the dominant element on the left of the bar. 60px against
   14.4px nav text is a ~4x relationship, close to the product's own sidebar,
   where a 168px logo sits in a 220px rail. The panel height moved with it
   (--header-h 68 -> 88) so the enlarged mark keeps real clear space above and
   below rather than filling the bar edge to edge. Height-only sizing preserves
   the SVG's 460x120 aspect ratio. */
.logo-link img { height: 60px; width: auto; }

.site-nav { display: flex; align-items: center; gap: 28px; margin-left: auto; }
/* Sidebar link treatment from Layout.jsx: white at 0.6 opacity, full white on
   hover, weight 500 (the product uses 400/500, not 600). */
.site-nav a:not(.btn) {
  font-size: 0.9rem; font-weight: 500; color: rgba(255, 255, 255, 0.75); text-decoration: none;
}
.site-nav a:not(.btn):hover { color: #fff; }

/* mobile toggle (hidden on desktop) */
.nav-toggle {
  display: none;
  margin-left: auto;
  /* White-on-blue, matching the header chrome. This mirrors the product's
     on-blue controls (Layout.jsx: 1px solid rgba(255,255,255,0.2), transparent
     fill, white content). The previous near-navy bars were nearly invisible once
     the header became deep blue. */
  background: none; border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 8px;
  width: 42px; height: 38px; padding: 0; cursor: pointer; position: relative;
}
.nav-toggle span, .nav-toggle span::before, .nav-toggle span::after {
  content: ""; position: absolute; left: 50%; translate: -50% 0;
  width: 18px; height: 2px; background: #fff; border-radius: 2px;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle span { top: 50%; margin-top: -1px; }
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after { top: 6px; }
.nav-toggle[aria-expanded="true"] span { background: transparent; }
.nav-toggle[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span::after { transform: translateY(-6px) rotate(-45deg); }

/* 5. Hero ----------------------------------------------------------------- */
/* Section 1 reads in one screen, so its rhythm is tighter than the site
   default. The generic --space-section (56-88px) still governs every section
   below the fold. */
.hero { padding-block: clamp(12px, 1.4vw, 18px) clamp(8px, 1vw, 12px); }
#how { padding-block: clamp(14px, 1.8vw, 20px) clamp(8px, 1.2vw, 12px); }
#how .kicker { margin-bottom: 3px; }
/* Scoped to section 1 only - every heading below the fold keeps the site scale. */
#how h2 { margin-bottom: 6px; font-size: clamp(1.45rem, 2.4vw, 1.95rem); }
/* The Dashboard preview is its own section directly beneath the hero. */
/* The Dashboard section shares the page's container width - it previously ran
   to 1420px so the framed app kept its full content area, but that made the
   section visibly wider than every other block on the page. Aligned instead, and
   the two consequences are the application's own behaviour at a narrow content
   width: the KPI pills wrap, and the remittance table scrolls inside its card
   (components/ui.jsx Table wraps every table in overflow-x:auto). */
/* The Dashboard and the remittance analysis are two views of the same example,
   so they sit closer than the site's default section rhythm: 88px + 88px of
   stacked padding put 176px of empty page between them. ~36px each keeps them
   distinct without the void. */
.dash-section { padding-block: 0 clamp(24px, 3vw, 36px); }
.detail-section { padding-block: clamp(24px, 3vw, 36px) var(--space-section); }
.detail-section .kicker { margin-bottom: 12px; }
.dash-section .kicker { margin-bottom: 12px; }
.dash-section .dash { margin-top: 0; }

/* ── Application frame around the Dashboard preview ─────────────────────
   components/Layout.jsx:36-45. The sidebar is where AutoRemit's logo actually
   lives in the product, so the preview carries it there rather than in an
   invented position. Values verbatim: rail width 220, #1A5BAD; logo block
   padding 18px 16px with a 1px rgba(255,255,255,.15) rule beneath and the
   wordmark at 168px; nav rows 13px / radius 8 / padding 8px 10px, the active
   row on rgba(255,255,255,.2); section labels 11px rgba(255,255,255,.5)
   tracked .05em. */
/* The rail is presented as a full-width masthead rather than a 220px column.
   In a 1120px marketing container a 220px column leaves only 803px for the app
   content, which forced the remittance table to scroll and hid the Action column
   - including the Post to Xero control and the posted tick. This is the same
   reflow the component already uses at narrow widths: the logo stays in the real
   sidebar component with its real treatment, just laid across the top. */
.app-frame {
  display: flex; flex-direction: column; align-items: stretch;
  background: var(--app-bg);
  border: 1px solid var(--card-line);
  border-radius: var(--radius);
  overflow: hidden;
}
.app-side { width: 100%; flex-shrink: 0; background: var(--c-deep); display: flex; flex-direction: column; }
.app-side-logo {
  padding: 14px 18px; display: flex; align-items: center; justify-content: flex-start;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}
.app-side-logo img { width: 168px; height: auto; display: block; }
.app-side-nav { display: none; }
.app-side-lbl {
  font-size: 11px; color: rgba(255, 255, 255, 0.5); font-weight: 500;
  letter-spacing: 0.05em; padding: 0 8px; margin: 8px 0 4px;
}
.app-side-lbl:first-child { margin-top: 0; }
.app-side-item {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: 8px;
  font-size: 13px; font-weight: 400; color: #fff;
}
.app-side-item.is-active { background: rgba(255, 255, 255, 0.2); font-weight: 500; }
.app-main { flex: 1; min-width: 0; padding: 14px; }

/* 5b. AutoRemit Dashboard mock ------------------------------------------------
   Reproduction of the application's Dashboard screen. Values are lifted from
   source, NOT measured from a screenshot. Component -> source mapping:

     .dash-title      Dashboard.jsx:726   #1A5BAD, radius 10, padding 6px 20px,
                                          min-height 56, margin-bottom 13
     .dash-title-t    Dashboard.jsx:733   Montserrat 700 ITALIC 20px #fff
     .dash-org-l      Dashboard.jsx:740   12px rgba(255,255,255,.8)
     .dash-select     Dashboard.jsx:760   padding 5px 10px, radius 7,
                                          1px #d1d5db, 13px, #fff
     .dash-banner     Dashboard.jsx:783   flex wrap, gap 12, margin-bottom 6
     .dash-l/.dash-r  Dashboard.jsx:791/912  flex 1.4 1 440px / 1 1 320px
     .kpi-panel       Dashboard.jsx:795,866  grid, gap 8, padding 13px 12px,
                                          #EAF2FF, 1px #93B4F5, radius 6
     .kpi             Dashboard.jsx:35    flex, gap 6, padding 4px 10px, #fff,
                                          1px transparent, radius 14
     .kpi-i           Dashboard.jsx:76    18x18, radius 5, tinted fill
     .kpi-v/.kpi-l    Dashboard.jsx:84-85 13px/700 #111827 | 11px #6b7280
     KPI icon colours lib/bucketStyles.js KPI_BUCKET_STYLES (bg/iconColor/iconPath)
     .dash-drop       Dashboard.jsx:986   2px dashed #93B4F5, radius 6,
                                          min-height 108, padding 14px 12px,
                                          #EAF2FF; icon tile 28x28 radius 6
     .drop-t1/.drop-t2 Dashboard.jsx:1026 12px/600 | 10px #9ca3af
     .up-panel        Dashboard.jsx:912   (already reproduced above)
     .dash-card       components/ui.jsx Card  #fff, 1px #e5e7eb, radius 12
     .dash-card-head  Dashboard.jsx:1063  #1F7AC4, border-bottom 1px #1A5BAD,
                                          radius 10/10/0/0, padding 6px 12px,
                                          min-height 44; title 14px/600 #fff
     .dash-btn        Dashboard.jsx:1077  #fff, #0D2E80, 1px #1A5BAD, radius 6,
                                          height 30, padding 0 12px, 12px/600
     .dash-search     Dashboard.jsx:1104  same chrome, padding 0 10px, 12px
     .remit-table th  Dashboard.jsx:1156  padding 8px 12px, 11px/600 #6b7280,
                                          tracking .04em, inset 0 -1px 0 #e5e7eb
     .remit-table td  Dashboard.jsx:1210  padding 9px 12px, 1px #e5e7eb
     .payer           Dashboard.jsx:1216  500, #1F7AC4
     .cell-muted      Dashboard.jsx:1219  11px #6b7280
     .conf-*          Dashboard.jsx:1288  track 36x4 #e5e7eb radius 2; fill
                                          >=90 #1D9E75 / 60-89 #EF9F27 /
                                          <60 #E24B4A; pct 11px/600; sub 9px #9ca3af
     .is-posted       Dashboard.jsx:1206  #FAFBFC row, #9ca3af text
     .act--part       Dashboard.jsx:1385  10px #0C447C on #fff, 1px #93B4F5,
                                          padding 2px 8px, radius 10, 500
     .act--review     Dashboard.jsx:1377  10px #92400E on #FEF3C7, 1px #F59E0B
     .act--wait       Dashboard.jsx:1394  same shape, slate register
     .chip            components/ui.jsx Badge + lib/statusPill.js (see section 3)

   Deliberate reductions (structure unchanged): five table rows instead of the
   live list, and no interactive states - this is a still image of the screen,
   not a working one. */

.dash-title {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 6px 12px;
  background: var(--c-deep); border-radius: 10px;
  padding: 6px 20px; min-height: 56px; margin-bottom: 13px;
}
.dash-title-t { font-weight: 700; font-style: italic; font-size: 20px; color: #fff; letter-spacing: -0.01em; }
.dash-org { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dash-org-l { font-size: 12px; color: rgba(255, 255, 255, 0.8); }
.dash-select {
  padding: 5px 10px; border-radius: 7px; border: 1px solid #d1d5db;
  font-size: 13px; background: #fff; color: var(--ink);
}
.dash-select::after { content: " \25BE"; color: #6b7280; }

.dash-banner { display: flex; flex-wrap: wrap; align-items: stretch; gap: 12px; margin-bottom: 6px; }
/* The app uses flex 1.4:1 here (Dashboard.jsx:791/912). At its ~1650px content
   width that leaves the summary panel enough room for four pills across; in this
   1120px column the same ratio gives 141px tracks while the widest summary pill
   measures 146px, so the fourth pill wrapped to a second row - the reference
   screenshot shows all four across. (The real app would wrap here too: at a
   1280px laptop its own content column produces 138px tracks. It is only wider
   canvases that hide this.) The ratio is widened to 2.2:1 so the app's 4-across
   summary row is preserved, rather than dropping the currency's cents or
   shrinking the pill. Every component VALUE - colour, radius, padding,
   typography - remains verbatim from source; only this layout ratio moves.
   Recorded as a deliberate deviation. */
.dash-l { flex: 3 1 440px; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.dash-r { flex: 1 1 260px; min-width: 0; display: flex; flex-direction: column; gap: 8px; }

.kpi-panel {
  display: grid; align-items: center; gap: 8px;
  padding: 13px 12px;
  background: var(--surface-blue);
  border: 1px solid var(--surface-blue-line);
  border-radius: 6px;
}
/* The app fixes these at 3 and 4 columns (Dashboard.jsx:798, 869) because its
   left banner column is ~955px wide. In this 1120px marketing container the same
   column is ~606px, so a fixed 4-up clipped the pill labels ("$96,240.55 V..").
   auto-fit keeps the app's pill format and panel exactly and lets the pills wrap
   instead of truncating - which is the behaviour the app's own Chip comment
   describes wanting ("a chip that can't fit the current row must move to the next
   row"). The minimums are the measured widths of the longest pill in each panel. */
.kpi-3 { flex: 1 1 auto; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); }
.kpi-4 { grid-template-columns: repeat(auto-fit, minmax(154px, 1fr)); }
.kpi {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 4px 10px; background: #fff;
  border: 1px solid transparent; border-radius: 14px;
  white-space: nowrap; min-width: 0;
}
.kpi-i {
  width: 18px; height: 18px; border-radius: 5px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.kpi-v { font-size: 13px; font-weight: 700; color: #111827; line-height: 1; }
.kpi-l { font-size: 11px; color: #6b7280; line-height: 1; overflow: hidden; text-overflow: ellipsis; }

.dash-drop {
  flex: 1 1 auto; min-height: 108px;
  border: 2px dashed var(--surface-blue-line); border-radius: 6px;
  padding: 14px 12px;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--surface-blue);
}
.drop-i {
  width: 28px; height: 28px; background: #EBF0FD; border-radius: 6px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.drop-t { display: block; }
.drop-t1 { display: block; font-weight: 600; font-size: 12px; color: var(--ink); }
.drop-t2 { display: block; font-size: 10px; color: #9ca3af; margin-top: 1px; }
.drop-link { color: var(--c-blue); font-weight: 500; }

.dash-card {
  background: #fff; border: 1px solid var(--card-line);
  border-radius: var(--radius); overflow: hidden;
}
.dash-card-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px;
  background: var(--c-blue); border-bottom: 1px solid var(--c-deep);
  border-radius: var(--radius-bar) var(--radius-bar) 0 0;
  padding: 6px 12px; min-height: 44px;
}
.dash-card-t { flex: 1 1 240px; min-width: 0; font-weight: 600; font-size: 14px; color: #fff; }
.dash-card-actions { flex: 1 1 420px; min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 12px; flex-wrap: wrap; }
.dash-btn, .dash-search {
  background: #fff; color: #0D2E80; border: 1px solid var(--c-deep); border-radius: 6px;
  height: 30px; box-sizing: border-box; display: inline-flex; align-items: center;
  font-size: 12px; white-space: nowrap;
}
.dash-btn { padding: 0 12px; font-weight: 600; }
.dash-search { padding: 0 10px; flex: 0 1 280px; min-width: 160px; color: #9ca3af; }

/* table-layout:fixed + the app's COL_WIDTHS percentages (Dashboard.jsx:600).
   Source calls this map "LAPTOP-SAFE - tuned so the fixed-layout table never
   horizontally overflows at laptop width", which is precisely the failure seen
   here before: an auto-layout table sized to its content ran past the card and
   `overflow:hidden` sliced the Action column in half. The app also sets
   overflow:hidden on every cell (Dashboard.jsx:1050) so long values ellipsise
   instead of forcing the table wider. */
/* components/ui.jsx Table wraps EVERY table in overflow-x:auto. Same here, at
   all widths - not just on phones. Without it the fixed-layout table simply
   compressed below ~1000px and the card's overflow:hidden clipped amounts,
   headers and action pills. With it the table holds its real proportions and
   the card scrolls, which is the application's own behaviour. The page itself
   never scrolls sideways. */
.dash-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.remit-table { width: 100%; min-width: 980px; border-collapse: collapse; table-layout: fixed; }
.remit-table td, .remit-table th { overflow: hidden; }
/* COL_WIDTHS_WIDE (Dashboard.jsx:606), not the laptop map. Source describes it
   as reclaiming "width from the low-content columns and [giving] it to the
   high-content Payer + File/Subject columns". The app applies it at >=1600px
   VIEWPORT; here it is applied unconditionally because this mock lives in a
   fixed 1120px text column rather than the app's ~1650px content area, and the
   laptop map at that width truncated payer names to "Example Ca..." - a visible
   difference from the real screen, where payer names read in full.
   The percentages below are interpolated between the app's TWO maps, because
   this 1120px marketing column sits below both content widths they were tuned
   for (laptop ~1200px, wide ~1650px): the wide map's 7% Amount column clipped
   "$11,482.50" here, so Amount takes 9% (laptop map value) and the surplus comes
   off File/Subject, the column with the most slack. Recorded as a deliberate
   deviation - every other value in this mock is verbatim from source. */
.remit-table col.c-date   { width: 9%; }
.remit-table col.c-amt    { width: 9%; }
.remit-table col.c-payer  { width: 17%; }
.remit-table col.c-file   { width: 15%; }
.remit-table col.c-conf   { width: 11%; }
.remit-table col.c-status { width: 16%; }
.remit-table col.c-acct   { width: 8%; }
.remit-table col.c-action { width: 15%; }
.remit-table th {
  padding: 8px 12px; font-size: 11px; font-weight: 600; color: #6b7280;
  /* The app sets white-space:nowrap here; at this narrower content column that
     truncated "Date uploaded" to "Date uplo...". Wrapping the header is a
     smaller departure from the real screen than clipping its label. */
  letter-spacing: 0.04em; vertical-align: middle; line-height: 1.25;
  background: #fff; box-shadow: inset 0 -1px 0 var(--card-line); text-align: left;
}
.remit-table th.c-date, .remit-table th.c-conf, .remit-table th.c-status,
.remit-table th.c-acct, .remit-table th.c-action { text-align: center; }
.th-i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; margin-left: 4px; border-radius: 50%;
  background: var(--card-line); font-size: 10px; font-weight: 600; color: #6b7280;
}
.remit-table td {
  padding: 9px 12px; border-bottom: 1px solid var(--card-line);
  font-size: 13px; color: var(--ink); vertical-align: middle;
}
.remit-table td.c-date, .remit-table td.c-conf, .remit-table td.c-status,
.remit-table td.c-acct, .remit-table td.c-action { text-align: center; }
.remit-table td.c-amt, .remit-table td.c-date { white-space: nowrap; }
.remit-table tbody tr:last-child td { border-bottom: 0; }
.remit-table .is-posted td { background: #FAFBFC; color: #9ca3af; }
.payer { font-weight: 500; color: var(--c-blue); }
.cell-muted { font-size: 11px; color: #6b7280; }
.c-file .cell-muted, .c-payer .payer { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.conf { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; }
.conf-row { display: inline-flex; align-items: center; gap: 5px; }
.conf-track { width: 36px; height: 4px; background: var(--card-line); border-radius: 2px; overflow: hidden; }
.conf-fill { display: block; height: 4px; border-radius: 2px; }
.conf-pct { font-size: 11px; font-weight: 600; }
.conf-sub { font-size: 9px; color: #9ca3af; }

.act {
  display: inline-block; font-size: 10px; font-weight: 500;
  padding: 2px 8px; border-radius: 10px; white-space: nowrap;
}
.act--part   { color: #0C447C; background: #fff;    border: 1px solid #93B4F5; }
.act--review { color: #92400E; background: #FEF3C7; border: 1px solid #F59E0B; }
.act--wait   { color: #374151; background: #fff;    border: 1px solid #d1d5db; }
/* A fully matched remittance offers the real posting control: ui.jsx Button
   variant="primary" (#1F7AC4 on #1A5BAD with the 2px bottom edge), scaled to the
   row's action size. */
.act--post {
  color: #fff; background: var(--btn-primary-bg);
  border: 1px solid var(--btn-primary-border);
  box-shadow: 0 2px 0 var(--btn-primary-edge), 0 1px 3px rgba(0, 0, 0, 0.15);
  font-weight: 600; padding: 3px 10px;
}
/* Once posted the action becomes a completion tick in the app's success green
   (#1D9E75) - the same green used for the workflow check and nowhere else. */
.act--posted {
  display: inline-flex; align-items: center; justify-content: center;
  background: #1D9E75; border: 1px solid #178A64; border-radius: 5px;
  padding: 3px 9px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}
.act--posted svg { width: 13px; height: 13px; display: block; }

/* Status pills stay on ONE line so every pill in the column is the same height.
   The application lets them wrap ("Awaiting Bank Feed" runs to two lines there),
   but in a five-row marketing table that produced 42px pills next to 24px ones,
   which reads as three different components rather than one. The Status column
   is widened to 16% instead - measured: the longest pill needs 159px including
   cell padding, and 16% of the content width is 164px.
   Only text-align is scoped here: the shared .chip rule already carries
   white-space: nowrap, so restating it was duplication, not an override. */
.remit-table .chip, .rd-table .chip { text-align: center; }

.dash-caption { margin-top: 12px; font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-3); letter-spacing: 0.04em; }

/* ── Three-stage workflow hero ─────────────────────────────────────
   Structure and wording from the supplied sketch; styling from the application.
     container  #EAF2FF / 1px #93B4F5 / radius 12  (Dashboard.jsx:795 surface,
                                                    ui.jsx Card radius)
     stage      #fff / 1px #e5e7eb / radius 12      (ui.jsx Card)
     header     #1F7AC4, min-height 44, white 14px/600  (Dashboard.jsx:1063)
     body       13px                                 (ui.jsx Td scale)
     arrow      #1F7AC4 stroke
     check      #1D9E75 - the app's success green, used nowhere else in the hero
   No shadows beyond the site's 1px, no gradients, no pills, no step numbers. */
/* The statement is set EXACTLY like the #how heading pair beneath it: the same
   kicker ("AutoRemit's aim" / "How it works") and the same h2 size, weight,
   leading and tracking as "From inbox to reconciled, with one button press."
   (#how h2, above). Keep the two rules in step - if #how h2 changes, this
   changes with it. One line at the content width. */
.wf-intro .kicker { margin-bottom: 3px; }
.wf-statement {
  max-width: none;
  margin: 0 0 clamp(12px, 1.4vw, 16px);
  font-size: clamp(1.45rem, 2.4vw, 1.95rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.wf {
  /* flex-start, not stretch: stretch forced all three cards to the tallest, so
     the Input card carried 108px of blank below one line of text and Xero 55px.
     Tops stay aligned; each card is now only as tall as its content. */
  display: flex; align-items: flex-start; gap: clamp(10px, 1.4vw, 18px);
  background: var(--surface-blue);
  border: 1px solid var(--surface-blue-line);
  border-radius: var(--radius);
  padding: clamp(14px, 1.6vw, 18px);
}
/* AutoRemit is the largest stage; Input and Xero stay narrower, per the sketch. */
.wf-in   { flex: 1 1 190px; }
.wf-ar   { flex: 1.65 1 260px; }
.wf-xero { flex: 1.15 1 215px; }

.wf-stage {
  display: flex; flex-direction: column; min-width: 0;
  background: #fff; border: 1px solid var(--card-line);
  border-radius: var(--radius); overflow: hidden;
}
.wf-head {
  display: flex; align-items: center;
  min-height: 44px; padding: 6px 14px;
  background: var(--c-blue);
  font-size: 14px; font-weight: 600; color: #fff;
}
.wf-body { list-style: none; margin: 0; padding: 10px 14px 12px; display: grid; gap: 7px; align-content: start; }
.wf-body li { font-size: 13px; line-height: 1.35; color: var(--ink); }

.wf-arrow, .wf-check { display: flex; align-items: center; flex: 0 0 auto; }
.wf-arrow svg { width: 26px; height: 12px; }
.wf-check svg { width: 26px; height: 26px; }

/* the vignette: email in → remittance extracted → invoices matched */
/* Named query container for .up-panel. This MUST live on whatever element
   actually bounds the panel: the panel used to sit inside .vig-doc-body and
   queried a container declared there, so lifting it out to stage 1 would have
   left the query with no container to match — it would have failed SILENTLY,
   locking the panel to its two-row form at every width with no error and no
   overflow for a scan to catch. */
.vig { margin: 0; container: vig-col / inline-size; }
/* EMAIL UPLOAD PANEL - reproduction of the product's component
   (frontend/src/pages/Dashboard.jsx:912): #EAF2FF fill, 1px #93B4F5 border,
   radius 6, padding 13px 12px, a 28px #EBF0FD icon tile, an 11px/600 #0D2E80
   label, a white mono address field with a #d1d5db border, and a #1F7AC4 Copy
   button.
   The product composes it as ONE flex row that wraps, which works there because
   the dashboard column is always wide. In this narrower illustration a bare
   flex-wrap orphaned the Copy button onto a row of its own, so the two documented
   states are declared explicitly with grid: below the threshold row 1 is
   [icon][label] and row 2 is [address][Copy]; at or above it, the single row the
   product shows on a wide screen. Deterministic at every width. */
.up-panel {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "icon  label label"
    "addr  addr  copy";
  align-items: center;
  gap: 8px 10px;
  background: var(--surface-blue);
  border: 1px solid var(--surface-blue-line);
  border-radius: 6px;
  padding: 13px 12px;
}
/* 520px is the width at which the address renders IN FULL on one line. The query
   targets the illustration column (.vig), because the panel's width tracks that
   column rather than the viewport. */
@container vig-col (min-width: 520px) {
  .up-panel {
    grid-template-columns: auto auto 1fr auto;
    grid-template-areas: "icon label addr copy";
  }
}
.up-icon {
  grid-area: icon;
  width: 26px; height: 26px; border-radius: 6px;
  background: #EBF0FD; display: inline-flex; align-items: center; justify-content: center;
}
.up-label { grid-area: label; font-size: 0.72rem; font-weight: 600; color: #0D2E80; white-space: nowrap; }
.up-addr {
  grid-area: addr;
  background: #fff; border: 1px solid #d1d5db; border-radius: 6px;
  padding: 3px 8px; font-family: var(--font-mono); font-size: 0.7rem; color: #0D2E80;
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Styled exactly as the product's Copy button, but inert: pointer-events:none
   means a click passes straight through, so the mock cannot look like it took
   an action it never performs. Appearance is unchanged. */
.up-copy {
  grid-area: copy;
  background: var(--c-blue); color: #fff; border: 0; border-radius: 6px;
  padding: 4px 12px; font-size: 0.7rem; font-weight: 500; white-space: nowrap; justify-self: end;
  pointer-events: none;
}

/* ── Remittance Detail pane ────────────────────────────────────────────────
   Reproduced from frontend/src/pages/RemittanceDetail.jsx. The screen this
   mirrors has NO blue section bars - that treatment belongs to Settings and the
   Dashboard card, not here - and it carries extraction and reconciliation in one
   pane. Values are from source, not measured off a screenshot. */
.rd {
  background: #fff; border: 1px solid var(--card-line);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
}
/* Action bar. The blue "Post N to Xero" is ui.jsx Button variant="primary",
   size="sm" (RemittanceDetail.jsx:1893) - the real control that sends the
   payment to Xero, and the reason this pane is the AutoRemit-to-Xero step. */
.rd-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px;
  padding: 10px 14px; border-bottom: 1px solid var(--card-line); background: #fff;
}
.rd-file { font-size: 13px; font-weight: 600; color: var(--ink); }
.rd-up { font-size: 12px; color: #6b7280; }
.rd-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }

/* ui.jsx Button, size "sm": 12px, padding 5px 11px, radius 8, 1px border,
   weight 600, 2px bottom edge + 1px ambient. */
.btn-ar {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; padding: 5px 11px; border-radius: 8px;
  background: var(--btn-default-bg); color: var(--btn-default-text);
  border: 1px solid var(--btn-default-border);
  box-shadow: 0 2px 0 var(--btn-default-edge), 0 1px 3px rgba(0, 0, 0, 0.08);
  white-space: nowrap;
}
.btn-ar--primary {
  background: linear-gradient(to bottom, #1F7AC4, #1F7AC4); color: #fff;
  border-color: #1A5BAD; box-shadow: 0 2px 0 #0F4A8E, 0 1px 3px rgba(0, 0, 0, 0.15);
}
.btn-ar--danger {
  background: linear-gradient(to bottom, #fff, #fef2f2); color: #991b1b;
  border-color: #fca5a5; box-shadow: 0 2px 0 #f5a3a3, 0 1px 3px rgba(0, 0, 0, 0.08);
}

/* Two panes: source document left, extracted data right - the shape of the real
   Remittance Detail screen. The document pane is the wider of the two only when
   there is room; below 980px the panes stack so neither is squeezed into
   illegibility. */
.rd-split { display: flex; align-items: stretch; }
.rd-doc {
  flex: 1 1 46%; min-width: 0; display: flex; flex-direction: column;
  border-right: 1px solid var(--card-line); background: #fff;
}
.rd-doc-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; border-bottom: 1px solid var(--card-line);
}
.rd-doc-name { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A caption, not a control. The real pane offers a blue "Open in new tab" link;
   here there is no separate artefact to open - and there must not be one, since
   a real remittance PDF would be customer data - so this is set in faint grey
   rather than link blue, so nothing invites a click that cannot be honoured. */
.rd-doc-open { font-size: 11px; color: var(--ink-3); white-space: nowrap; }
/* Grey stage behind the page, as a document viewer shows it. */
.rd-doc-stage { flex: 1; background: #f3f4f6; padding: 12px; display: flex; align-items: flex-start; justify-content: center; }

/* The facsimile page. Sized in px, not rem, so it reads as a document rather
   than as page furniture. */
.rd-page {
  width: 100%; background: #fff; border: 1px solid #e5e7eb;
  box-shadow: 0 1px 3px rgba(19, 35, 63, 0.10);
  padding: 16px 18px; font-size: 10px; line-height: 1.45; color: #1f2937;
}
.rd-page-top { display: flex; justify-content: space-between; gap: 16px; align-items: flex-start; }
.rd-page-from { display: flex; flex-direction: column; min-width: 0; }
.rd-page-from strong { font-size: 12px; color: #111827; }
.rd-page-from span { color: #4b5563; }
.rd-page-title { text-align: right; flex-shrink: 0; }
.rd-page-title h4 { margin: 0 0 4px; font-size: 13px; font-weight: 700; letter-spacing: 0.01em; color: #111827; }
.rd-page-title dl { margin: 0; display: grid; gap: 1px; }
.rd-page-title dl div { display: flex; justify-content: flex-end; gap: 8px; }
.rd-page-title dt { color: #4b5563; }
.rd-page-title dd { margin: 0; font-weight: 600; color: #111827; min-width: 48px; text-align: right; }

.rd-page-to { margin: 12px 0 10px; border: 1px solid #d1d5db; padding: 6px 8px; display: flex; flex-direction: column; }
.rd-page-to-lbl { background: #e5e7eb; margin: -6px -8px 5px; padding: 2px 8px; font-weight: 600; color: #374151; }
.rd-page-to strong { color: #111827; }
.rd-page-to span { color: #4b5563; }

.rd-page-table { width: 100%; border-collapse: collapse; }
.rd-page-table th, .rd-page-table td { border: 1px solid #d1d5db; padding: 3px 6px; text-align: left; }
.rd-page-table th { background: #f3f4f6; font-weight: 600; color: #374151; }
.rd-page-table .rd-num { text-align: right; white-space: nowrap; }
.rd-page-table tfoot td { font-weight: 600; background: #fafafa; }

.rd-body { padding: 12px 14px 14px; }

/* Pipeline pills - RemittanceDetail.jsx:2246. Done state only. */
.rd-pipe { display: flex; gap: 6px; margin-bottom: 10px; flex-wrap: wrap; }
.pipe {
  display: inline-flex; align-items: center; gap: 4px;
  background: #E1F5EE; color: #085041;
  padding: 2px 8px; border-radius: 20px; font-size: 10px; font-weight: 500;
}
.pipe i { width: 5px; height: 5px; border-radius: 50%; background: #1D9E75; }

/* Section micro-labels - RemittanceDetail.jsx:2261 / :2788. */
.rd-legend {
  font-size: 10px; font-weight: 600; color: #6b7280;
  letter-spacing: 0.05em; margin-bottom: 6px;
}

/* Extracted-data fields - RemittanceDetail.jsx:2263-2290. */
.rd-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 8px; }
.rd-l { display: block; font-size: 10px; color: #9ca3af; margin-bottom: 2px; }
.rd-v {
  display: block; border: 1px solid var(--card-line); border-radius: 5px;
  padding: 4px 8px; font-size: 11px; background: #fafafa; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rd-v--amt { font-weight: 500; color: #0D2E80; }
.rd-v--mono { font-family: var(--font-mono); }
.rd-acct { margin-bottom: 10px; }
/* Payment Account is a <select> in the app; rendered here as its resting state. */
.rd-select {
  display: flex; align-items: center; justify-content: space-between;
  border: 1px solid #d1d5db; border-radius: 5px; padding: 4px 8px;
  font-size: 11px; background: #fff; color: var(--ink);
}
.rd-select::after { content: "\25BE"; color: #6b7280; margin-left: 8px; }

/* Invoice reconciliation table - RemittanceDetail.jsx:2789-2810. */
.rd-scroll { overflow-x: auto; border: 1px solid var(--card-line); border-radius: 6px; }
.rd-table { width: 100%; min-width: 500px; border-collapse: collapse; font-size: 11px; }
.rd-table thead tr { background: #f9fafb; }
.rd-table th {
  padding: 3px 5px; font-size: 10px; font-weight: 600; color: #6b7280;
  border-bottom: 1px solid var(--card-line); white-space: nowrap; text-align: left;
}
.rd-table td { padding: 5px 5px; border-bottom: 1px solid #f3f4f6; vertical-align: middle; }
.rd-table th.rd-num, .rd-table td.rd-num { text-align: right; }
/* Contact absorbs the slack, as it does on the real screen. The app's pane is
   ~620px wide so its table sits near its 500px min-width and every column is
   content-sized; at this section's full width the surplus otherwise pooled
   between Contact and Xero Inv, spreading Match % away from Status. */
.rd-table th:nth-child(3), .rd-table td:nth-child(3) { width: 100%; }
/* nowrap on the identifier + amount columns: with Contact absorbing the slack,
   "INV-2041" and "Total (4)" otherwise broke across two lines. */
.rd-table .rd-inv { font-weight: 500; color: var(--ink); white-space: nowrap; }
.rd-table td.rd-num, .rd-table .rd-total td { white-space: nowrap; }
/* Match % on the DETAIL screen is a blue value, not the Dashboard's bar. */
.rd-pct { color: var(--c-blue); font-weight: 500; }
.rd-view { color: #9ca3af; }
.rd-table .rd-total td { background: #f9fafb; font-weight: 600; border-bottom: 0; }

.vig figcaption { margin-top: 12px; font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-3); letter-spacing: 0.04em; }

/* 6. Audience strip -------------------------------------------------------- */
/* Rendered as the product's dashboard summary panel: a light-blue rounded
   container with a blue hairline. Previously a plain grey full-bleed band,
   which existed nowhere in the application.
   The .aud-pills rules that sat here went with the sector chips they styled.
   The paragraph's 9px bottom margin went with them too - it spaced the text
   from the pill row, and with nothing below it only padded the panel. The gap
   is now carried by the adjacent-sibling rule instead, so it applies between
   the two lines and never below the last one. */
.aud-strip { padding-block: 0; margin-block: clamp(8px, 2vw, 20px); }
.aud-strip .wrap > div {
  background: var(--surface-blue); border: 1px solid var(--surface-blue-line);
  border-radius: var(--radius); padding: 12px 16px;
}
.aud-strip p { margin: 0; font-size: 0.9rem; color: var(--ink-2); max-width: none; text-align: center; }
.aud-strip p + p { margin-top: 5px; }

/* 7. How it works ----------------------------------------------------------- */
/* Five steps laid out 3 + 2, not 5 across.
   Five equal columns measured 191px AT EVERY DESKTOP WIDTH — the container is
   capped at 1120px, so a wider screen does not widen them — which is ~26
   characters a line and paragraphs running to eight or nine lines. That is well
   under a comfortable measure, and shrinking the type to fit would have made it
   worse rather than better.
   Both rows are full: the first three steps take two tracks each and the last
   two take three each, so there is no empty cell in the corner. The blue rule
   over each step carries the sequence across the break, and the wider bottom row
   suits steps 4 and 5, which have the longest copy. */
/* This section's lede is a single sentence that must hold ONE line at the
   content width - .lede's 58ch cap forced it to wrap. The cap is lifted and the
   size steps down just enough to fit 1052px; below the container width it wraps
   naturally, because no type size keeps 139 characters on one line on a phone. */
.lede--wide { max-width: none; font-size: 0.9rem; }

/* Step marks. The AutoRemit chevron rides steps 01-04 (the work AutoRemit does);
   step 05 happens inside Xero, so it carries a Xero label instead. */
.step-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.step-mark { display: inline-flex; align-items: center; flex-shrink: 0; }
/* Was 15px - barely distinguishable from a text glyph. At 26px the mark reads
   as the AutoRemit chevron on each step it owns. */
.step-mark img { height: 26px; width: auto; }
/* Word-mark only, set in the site's own type - NOT a reproduction of the Xero
   logo. Swap in the official SVG when it is supplied; see the note in index.html. */
.step-mark--xero {
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em;
  color: var(--ink-2); border: 1px solid var(--card-line); border-radius: 5px;
  padding: 3px 9px; line-height: 1.4;
}

.steps { display: grid; grid-template-columns: repeat(6, 1fr); gap: clamp(10px, 1.2vw, 14px) clamp(18px, 2vw, 26px); margin-top: clamp(10px, 1.4vw, 16px); }
.steps .step:nth-child(-n+3) { grid-column: span 2; }
.steps .step:nth-child(n+4)  { grid-column: span 3; }
/* The rule was near-black (--ink). AutoRemit accents with blue; a black rule
   reads as a generic editorial grid. */
.step { border-top: 2px solid var(--c-blue); padding-top: 12px; }
.step .num { font-family: var(--font-sans); font-size: 0.76rem; font-weight: 600; color: var(--c-deep); letter-spacing: 0.1em; }
.step h3 { margin: 6px 0 7px; font-size: 1.05rem; }
.step p { font-size: 0.92rem; color: var(--ink-2); }

/* 8. Guardrails (dark band) ------------------------------------------------- */
.dark { background: var(--navy); color: var(--on-navy); }
.dark h2 { color: #fff; max-width: 22ch; }
/* Was brand green. In the product green means posted/success — using it as a
   decorative over-line on a section about BLOCKING and HOLDING inverted its
   meaning. Light blue is the product's neutral accent on dark. */
.dark .kicker { color: #8FB8E8; }
.dark .lede { color: var(--on-navy); }

.gr-head { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: clamp(24px, 5vw, 64px); align-items: end; margin-bottom: 48px; }

.gr-rows { border-top: 1px solid var(--navy-line); }
.gr-row {
  display: grid; grid-template-columns: 150px minmax(0, 1fr);
  gap: 10px 32px;
  padding-block: 26px;
  border-bottom: 1px solid var(--navy-line);
}
.gr-row h3 { color: #fff; font-size: 1.08rem; margin-bottom: 8px; }
.gr-row p { color: var(--on-navy); font-size: 0.95rem; max-width: 62ch; margin: 0; }

/* chips on navy */
/* On-dark status pill, matching the product's sidebar pills (Layout.jsx:90):
   padding '6px 10px', borderRadius 8, 1px solid rgba(255,255,255,0.2), 12px text.
   Sans rather than mono/uppercase, for the same reason as the light-surface
   chips. */
.gr-chip {
  justify-self: start; align-self: start;
  font-family: var(--font-sans); font-size: 0.75rem; font-weight: 500;
  letter-spacing: 0; text-transform: none;
  padding: 5px 11px; border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.2);
  color: var(--on-navy); white-space: nowrap; margin-top: 2px;
}

.gr-close {
  margin-top: 36px; padding-top: 22px;
  font-family: var(--font-mono); font-size: 0.8rem; line-height: 1.7;
  color: var(--on-navy-2); max-width: 74ch;
}
.gr-close strong { color: var(--on-navy); font-weight: 500; }

/* 8b. Payer payment routes ---------------------------------------------------- */
/* Reproduction of the product's "Payer Payment Routes" card (Settings.jsx +
   ui.jsx). Values are copied, not approximated — see the note in index.html for
   the mapping. The marketing version drops two columns and the row actions; the
   styling of what remains is unchanged, so the feature is recognisable when the
   customer opens Settings for the first time. */
.routes-grid { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(32px, 4.5vw, 56px); align-items: start; }
.routes-grid > div:first-child p:not(.lede) { font-size: 0.93rem; color: var(--ink-2); margin: 14px 0 0; }

/* ui.jsx Card: #fff, 1px #e5e7eb, radius 12, overflow hidden. */
.rt-panel {
  background: #fff; border: 1px solid var(--card-line);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
}
/* Settings.jsx CardHeader override: #1F7AC4, radius 10 10 0 0, height 44,
   padding 0 18px, title white 14px/600, action button pinned right. */
.rt-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 44px; padding: 0 18px;
  background: var(--c-blue);
  border-radius: var(--radius-bar) var(--radius-bar) 0 0;
}
.rt-head strong { font-size: 0.86rem; font-weight: 600; color: #fff; }
/* ui.jsx Button, variant "default", size "sm" — the white variant, because this
   button sits ON the blue header exactly as "Add rule" does in the product. */
.rt-btn {
  flex-shrink: 0;
  background: var(--btn-default-bg); color: var(--btn-default-text);
  border: 1px solid var(--btn-default-border); border-radius: 8px;
  box-shadow: 0 2px 0 var(--btn-default-edge), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 5px 11px; font-size: 0.72rem; font-weight: 600; white-space: nowrap;
}
/* Settings.jsx CardBody override: padding 10px 14px (denser than the 18px default). */
.rt-body { padding: 10px 14px 14px; }
/* Settings.jsx explanatory copy: 11px, #6b7280. */
.rt-note { font-size: 0.7rem; line-height: 1.55; color: var(--ink-3); margin: 0 0 10px; }

.ar-table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
/* ui.jsx Th — note SENTENCE CASE, not uppercase: the product's shared Th sets
   only letter-spacing, never text-transform.
   .ar-table is the shared product-table class: the routes panel and the activity
   feed both use it, so the app's Th/Td values live in exactly one place. */
.ar-table th {
  text-align: left; padding: 0 14px 10px;
  font-size: 0.69rem; font-weight: 600; color: var(--ink-3);
  letter-spacing: 0.04em; border-bottom: 1px solid var(--card-line);
}
/* ui.jsx Td — row rule is #f3f4f6, LIGHTER than the header's #e5e7eb. */
.ar-table td { padding: 10px 14px; border-bottom: 1px solid #f3f4f6; vertical-align: middle; }
.ar-table tbody tr:last-child td { border-bottom: 0; }
.rt-payer { font-weight: 500; }

/* Status note, in the product's muted register rather than as a coloured banner:
   this is a statement about how the suggestion arose, not an alert. */
.rt-status {
  margin: 12px 0 0; padding-top: 10px;
  border-top: 1px solid var(--card-line);
  font-size: 0.69rem; line-height: 1.5; color: var(--ink-3);
}
.rt-caption { margin-top: 14px; font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-3); letter-spacing: 0.04em; }

/* 9. References -------------------------------------------------------------- */
.ref-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: var(--space-block); }
.ref-card { background: #fff; border: 1px solid var(--card-line); border-radius: var(--radius); padding: var(--pad-card); }
.ref-card .lbl {
  display: block; font-family: var(--font-sans); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-deep); margin-bottom: 14px;
}
.ref-card .ex {
  display: inline-block; font-family: var(--font-mono); font-size: 0.82rem; font-weight: 500;
  background: var(--wash); border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 10px; margin-bottom: 14px; color: var(--ink);
}
.ref-card p { font-size: 0.9rem; color: var(--ink-2); margin: 0; }

/* 9b. Pricing ---------------------------------------------------------------
   Same three-across card grid as .ref-cards, and it collapses at the same
   980px breakpoint, so pricing inherits the page's existing rhythm rather than
   introducing a second responsive system. Cards are equal-height with the CTA
   pinned to the bottom (margin-top:auto) so the three buttons align regardless
   of how many lines the amounts take. */
.price-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: var(--space-block); align-items: stretch; }
.price-card {
  display: flex; flex-direction: column;
  background: #fff; border: 1px solid var(--card-line); border-radius: var(--radius); padding: var(--pad-card);
}
.price-card .lbl {
  display: block; font-family: var(--font-sans); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-deep); margin-bottom: 14px;
}
/* The allowance lines read as one group: tight between themselves, with the
   existing 14px gap kept before the amounts. Every card carries BOTH lines
   (organisations, then remittances) so the three cards keep identical spacing
   above the price without a per-card override. */
.price-orgs { font-size: 0.9rem; color: var(--ink-2); margin: 0 0 4px; }
.price-rems { font-size: 0.9rem; color: var(--ink-2); margin: 0 0 14px; }
.price-amounts { display: flex; flex-direction: column; gap: 4px; margin-bottom: 18px; }
.price-main { font-size: 1rem; color: var(--ink); }
.price-main strong { font-size: 1.9rem; font-weight: 800; letter-spacing: -0.01em; }
/* A worded price ("Price on application") must not inherit the numeral size —
   at 1.9rem it wraps to two lines and unbalances the card against the two
   priced plans. */
.price-main--text strong { font-size: 1.15rem; font-weight: 700; letter-spacing: 0; }
.price-gst { font-size: 0.8rem; color: var(--ink-2); }
.price-alt { font-size: 0.85rem; color: var(--ink-2); }
.price-alt strong { font-weight: 600; color: var(--ink); }
/* Assurance lines on the self-service cards, between the amounts and the CTA.
   Same muted register as .price-alt; the tick is the site's stroke icon in brand
   blue (not the success green, which the page reserves for posted/complete). */
.price-assure { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.price-assure li { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; color: var(--ink-2); }
.price-assure svg { width: 14px; height: 14px; flex-shrink: 0; }
/* Pinned to the card foot so the three CTAs line up across the row. */
.price-cta { margin-top: auto; align-self: flex-start; }
/* Trial terms, with the section intro ABOVE the cards so they are read before
   either trial CTA at every width. Body ink (not the muted register) and the
   lede's size so it reads as a statement, not fine print; the lead phrase takes
   the accent colour already used for the card labels and links. */
.price-trial { margin: 14px 0 0; font-size: 1.02rem; color: var(--ink); max-width: 58ch; }
.price-trial strong { font-weight: 700; color: var(--c-deep); }

/* Prominence for the middle plan using the existing accent colour only — no
   badge, no "most popular" claim, nothing comparative. */
.price-card--featured { border-color: var(--c-deep); box-shadow: 0 0 0 1px var(--c-deep) inset; }

/* 10. Proof: activity feed + Xero connection --------------------------------- */
.proof-grid { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 18px; align-items: stretch; }
.proof-card { background: #fff; border: 1px solid var(--card-line); border-radius: var(--radius); padding: 0; display: flex; flex-direction: column; overflow: hidden; }
/* Blue card header, same as every other panel on the site and in the app
   (Dashboard.jsx:1063 / ui.jsx CardHeader): #1F7AC4, min-height 44, white
   14px/600. This rule was collateral damage when the old vignette CSS block was
   removed - the heading had been rendering as plain near-black text on white,
   and the card contents sat flush against the border with no gutter. */
.proof-card h3 {
  display: flex; align-items: center;
  min-height: 44px; margin: 0; padding: 6px 18px;
  background: var(--c-blue);
  font-size: 14px; font-weight: 600; color: #fff; letter-spacing: 0;
}
.proof-card > *:not(h3) { margin-inline: var(--pad-card); }
.proof-card > *:nth-child(2) { margin-top: 16px; }
.proof-card > *:last-child { margin-bottom: var(--pad-card); }
.proof-card > p { font-size: 0.93rem; color: var(--ink-2); }

/* Activity history table. The log used to render as monospace green-on-grey
   with dotted separators and "·" separators — a developer console, not a
   product view. AutoRemit has no such surface: history is shown as tables and
   status badges. This reuses .ar-table (the app's Th/Td) and adds only a mono
   timestamp column, which IS how the product renders times and IDs. */
/* width:auto, NOT the .ar-table default of 100%. .proof-card is a column flex
   container whose children are inset with margin-inline, and a percentage width
   resolves against the card's FULL content box — so 100% + 2x22px of margin made
   the table 21px wider than the card and `overflow:hidden` sliced the end off the
   "Confirmed" pill. As a stretched flex item, width:auto fills the line minus its
   own margins, which is what was intended. (.ar-table keeps 100% for the routes
   panel, where the parent has real padding and 100% is correct.) */
.feed-table { width: auto; margin-block: 14px 16px; }
.feed-table th:first-child, .feed-table td:first-child { width: 1%; white-space: nowrap; }
.feed-table th:last-child,  .feed-table td:last-child  { width: 1%; white-space: nowrap; }
.feed-t { font-family: var(--font-mono); font-size: 0.74rem; color: var(--ink-3); }

/* Data-protection infographic. One <picture>, two self-contained SVGs: the wide
   file (1200x770) above 860px, the stack file (360-wide, single column) below
   it - the same content re-flowed, not a scaled-down desktop image, so the
   type stays legible on a phone. Both embed their own Montserrat subset, so
   they render the same as <img> in every browser without touching page fonts.
   The stack file renders at its natural 360px, centred, rather than stretching
   to a tablet's full width. */
.sec-figure { margin: 18px 0 var(--space-block); }
.sec-figure img { width: 100%; height: auto; }
.sec-figure figcaption { margin-top: 12px; font-size: 0.86rem; line-height: 1.5; color: var(--ink-3); max-width: 72ch; }
@media (max-width: 860px) {
  .sec-figure img { max-width: 360px; margin-inline: auto; }
  .sec-figure figcaption { text-align: center; margin-inline: auto; }
}

/* 11. FAQ ---------------------------------------------------------------------- */
/* Centred rather than pinned left: at 780px inside a 1120px column the FAQ left
   a third of the section empty on the right, which read as unbalanced dead space
   rather than deliberate whitespace. Width unchanged — line length is already
   right; only the placement moves. */
.faq { max-width: 780px; margin-inline: auto; }
.faq details { border-bottom: 1px solid var(--line); }
.faq details:first-of-type { border-top: 1px solid var(--line); }
.faq summary {
  display: flex; justify-content: space-between; align-items: center; gap: 20px;
  padding: 20px 4px;
  font-weight: 600; font-size: 1rem;
  cursor: pointer; list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; font-family: var(--font-mono); font-size: 1.1rem; color: var(--c-deep);
  transition: transform 0.2s ease; flex-shrink: 0;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details p { padding: 0 4px 22px; color: var(--ink-2); font-size: 0.95rem; max-width: 64ch; }

/* 12. Final CTA ------------------------------------------------------------------ */
.cta-final { text-align: center; border-top: 1px solid var(--line); }
/* 130px, as it was before the whitespace trim: the closing mark is the largest
   AutoRemit branding on the page and should not shrink. */
.cta-final img { height: 130px; width: auto; margin: 0 auto 24px; }
.cta-final h2 { margin-bottom: 14px; }
.cta-final .lede { margin-inline: auto; }
.cta-final .hero-ctas { justify-content: center; }

/* 13. Footer ----------------------------------------------------------------------- */
.site-footer { background: var(--navy); color: var(--on-navy); padding-block: 52px 28px; }
.site-footer a { color: var(--on-navy); text-decoration: none; }
.site-footer a:hover { color: #fff; }

.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 40px; padding-bottom: 44px; }
.footer-brand img { height: 30px; width: auto; margin-bottom: 16px; }
.footer-brand p { font-size: 0.88rem; color: var(--on-navy-2); max-width: 30ch; }

.footer-col h4 {
  font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--on-navy-2);
  margin-bottom: 16px;
}
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { margin-bottom: 10px; font-size: 0.9rem; }

.footer-fine {
  border-top: 1px solid var(--navy-line); padding-top: 24px;
  font-size: 0.8rem; line-height: 1.7; color: var(--on-navy-2);
}
.footer-fine p { max-width: 84ch; }
.footer-bottom {
  display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: space-between;
  margin-top: 24px; font-size: 0.8rem; color: var(--on-navy-2);
}
.footer-bottom .mono { font-size: 0.74rem; }

/* 14. Legal pages ------------------------------------------------------------------- */
.legal-main { max-width: 780px; margin-inline: auto; padding: clamp(40px, 6vw, 72px) clamp(20px, 5vw, 40px) 80px; }
.legal-main h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); }
.legal-main h2 { font-size: 1.25rem; margin-top: 2.2em; }
.legal-main p, .legal-main li { color: var(--ink-2); font-size: 0.96rem; }
.legal-main ul { padding-left: 22px; }
.legal-main li { margin-bottom: 8px; }

.legal-updated { font-family: var(--font-mono); font-size: 0.78rem; color: var(--ink-3); margin-bottom: 36px; }

/* the draft banner — remove before launch */
.draft-banner {
  border: 1.5px solid var(--c-blue); background: var(--blue-wash);
  border-radius: var(--radius-sm); padding: 16px 20px; margin-bottom: 40px;
  font-size: 0.9rem; color: var(--ink);
}
.draft-banner strong { font-family: var(--font-mono); font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-deep); display: block; margin-bottom: 6px; }

/* inline placeholder for values the client must fill in.
   `white-space: nowrap` used to be set here and could not hold: several of these
   placeholders are full sentences of drafting instruction, and an unwrappable
   sentence sets the width of the whole document. The Terms liability placeholder
   rendered 2105px wide and pushed the page to 2707px against a 1920px viewport —
   a horizontal scrollbar on desktop, and far worse on a phone. Placeholders now
   wrap like any other inline text, and long unbroken values break rather than
   overflow. */
.ph {
  font-family: var(--font-mono); font-size: 0.85em; font-weight: 500;
  background: var(--blue-wash); color: var(--c-deep);
  padding: 1px 7px; border-radius: 4px;
  overflow-wrap: break-word; word-break: break-word;
  /* box-decoration-break keeps the tinted background and padding intact on every
     line once a placeholder wraps, instead of only on the first. */
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}

/* No bottom border: the header is a floating panel now, so a rule across the
   full page width would cut across the gutter beside it. */
.legal-header { border-bottom: 0; }
.legal-header .header-in { height: 64px; }
.legal-header .logo-link img { height: 40px; }
/* On the deep-blue header this link inherited the dark-blue anchor colour and
   became invisible. It carries the same white treatment as the primary nav. */
.legal-header .back { margin-left: auto; font-size: 0.85rem; font-weight: 500; text-decoration: none; color: rgba(255, 255, 255, 0.75); white-space: nowrap; }
.legal-header .back:hover { color: #fff; }

.legal-footer { border-top: 1px solid var(--line); padding: 28px 0; }
.legal-footer .wrap { display: flex; flex-wrap: wrap; gap: 10px 28px; justify-content: space-between; font-size: 0.82rem; color: var(--ink-3); }
.legal-footer a { color: var(--ink-2); }
.legal-footer .legal-fine { flex-basis: 100%; margin: 6px 0 0; font-size: 0.74rem; line-height: 1.5; color: var(--ink-3); }

/* 15. Responsive ---------------------------------------------------------------------- */
@media (max-width: 980px) {
  /* Stacked rather than scaled: a two-pane document view compressed into half a
     tablet width makes both halves unreadable, which is the compromise the brief
     allows against. Order is source document, then what AutoRemit extracted. */
  .rd-split { flex-direction: column; }
  .rd-doc { flex: 0 0 auto; border-right: 0; border-bottom: 1px solid var(--card-line); }

  .app-side-logo { padding: 12px 14px; }
  .app-side-logo img { width: 150px; }
  .app-main { padding: 10px; }

  /* Stack the workflow. Source order preserves Input -> AutoRemit -> Xero ->
     check top to bottom; the arrows simply rotate to point down. */
  .wf { flex-direction: column; align-items: stretch; }
  .wf-in, .wf-ar, .wf-xero { flex: 0 0 auto; }
  .wf-arrow, .wf-check { justify-content: center; }
  .wf-arrow svg { transform: rotate(90deg); }

  .steps { grid-template-columns: repeat(2, 1fr); gap: clamp(20px, 3vw, 32px); }
  /* Spans from the 3+2 layout are cleared, but five items in two columns still
     leaves the fifth alone in the last row — so it takes the full width there
     rather than sitting in a half-empty row. */
  .steps .step:nth-child(-n+3), .steps .step:nth-child(n+4) { grid-column: auto; }
  .steps .step:nth-child(5) { grid-column: span 2; }
  .gr-head { grid-template-columns: 1fr; align-items: start; }
  .ref-cards { grid-template-columns: 1fr; }
  .price-cards { grid-template-columns: 1fr; }
  .proof-grid { grid-template-columns: 1fr; }
  .routes-grid { grid-template-columns: 1fr; gap: 34px; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

/* The nav collapses on its OWN breakpoint, separate from the content-density
   rules below, because what forces the collapse is the header's width budget,
   not the page's. Measured: logo 176 + gap 28 + nav 488 = 692, plus 2x gutter,
   so the desktop nav needs ~825px. It was collapsing at 720, which left a live
   740-810px band where the full nav rendered and overflowed the pill — the
   enlarged logo raised the requirement and this breakpoint was never moved with
   it. 880px gives headroom for the gutter's clamp. */
@media (max-width: 880px) {
  /* The enlarged wordmark steps down once the bar is sharing space with the
     menu control: at 320px a 230px logo plus the 42px toggle exceeded the
     panel's 248px interior by 17px. It stays the dominant element, just scaled
     to the narrower bar. */
  .logo-link img { height: 50px; }
  .nav-toggle { display: block; }
  .site-nav {
    display: none;
    /* Anchored to the pill (.header-in), not the page: sits just below the
       panel, matches its width, and carries the same rounded-panel language. */
    position: absolute; left: 0; right: 0; top: calc(100% + 8px);
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper);
    border: 1px solid var(--card-line); border-radius: var(--radius);
    padding: 8px 18px 18px;
    box-shadow: 0 18px 30px -20px rgba(19, 35, 63, 0.45);
  }
  .site-nav.open { display: flex; }
  /* The panel itself is white (var(--paper)), so links revert to dark ink —
     the white-on-blue treatment only applies to the bar. */
  .site-nav a:not(.btn) { color: var(--ink-2); padding: 13px 4px; border-bottom: 1px solid var(--line); }
  .site-nav a:not(.btn):hover { color: var(--ink); }
  .site-nav .btn { margin-top: 14px; justify-content: center; }
  /* The dropdown panel is WHITE, so the primary CTA takes the product's blue
     primary button again. The white-button override on .site-header exists only
     because brand blue on the deep-blue pill has no contrast — that reasoning
     stops at the panel edge, and inheriting it here left the main call to action
     rendering as a secondary control. */
  .site-header .site-nav .btn--primary {
    background: var(--btn-primary-bg); color: #fff;
    border-color: var(--btn-primary-border);
    box-shadow: 0 2px 0 var(--btn-primary-edge), 0 1px 3px rgba(0, 0, 0, 0.15);
  }
  .site-header .site-nav .btn--primary:hover { background: var(--btn-primary-bg); color: #fff; }
}

@media (max-width: 720px) {
  /* The detail pane's own table already scrolls inside its bordered wrapper
     (RemittanceDetail.jsx:2789 overflow-x:auto), so no phone-specific layout
     is invented for it - the app's behaviour carries. */
  .rd-fields { grid-template-columns: 1fr; }
  .rd-actions { margin-left: 0; }

  .steps { grid-template-columns: 1fr; }
  /* Clear the two-column tier's span. A `span 2` left in place against a
     single-column track list does not collapse — grid creates an IMPLICIT second
     column to satisfy it, so the whole section silently became two lopsided
     columns (108px / 211px at 390px) with steps 1 and 3 crushed into the narrow
     one. No overflow, so a scan for escaping elements sees nothing wrong. */
  .steps .step:nth-child(5) { grid-column: auto; }
  .gr-row { grid-template-columns: 1fr; gap: 8px; }
  .footer-grid { grid-template-columns: 1fr; gap: 28px; }

  /* Dashboard mock at phone widths. The application has no phone layout for this
     screen, so rather than redesign it the table keeps its real structure and
     the panel becomes horizontally scrollable within its own card - the same
     device the app's own <Table> uses (components/ui.jsx wraps every table in
     overflow-x:auto). The page itself never scrolls sideways. */
  .dash-title { padding: 8px 14px; min-height: 0; }
  .dash-title-t { font-size: 17px; }
  .dash-card-actions { justify-content: flex-start; }
  .dash-search { flex: 1 1 100%; min-width: 0; }


  /* Routes table -> stacked rows. Three columns cannot hold their meaning at
     390px, and a horizontally scrolling table inside a card is not a shape the
     product uses anywhere. Each row becomes its own labelled block, keeping the
     product's label register (11px #6b7280) against the value — the same
     label-above-value pairing the app uses for extracted data. The <table> markup
     is untouched, so the reading order and header association survive for
     assistive technology. */
  .ar-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .ar-table, .ar-table tbody, .ar-table tr, .ar-table td { display: block; }
  /* width:auto on the table for the same reason as .feed-table above — once
     display:block makes it an ordinary block box it fills the line minus its own
     margins, which is correct inside both the padded routes panel and the
     margin-inset proof card. A literal 100% overflows the latter. */
  .ar-table { width: auto; }
  .ar-table tbody, .ar-table tr, .ar-table td { width: 100%; }
  .ar-table tr {
    padding: 10px 0; border-bottom: 1px solid #f3f4f6;
  }
  .ar-table tbody tr:last-child { border-bottom: 0; padding-bottom: 0; }
  .ar-table td { padding: 3px 0; border-bottom: 0; display: flex; gap: 10px; align-items: baseline; }
  .ar-table td::before {
    content: attr(data-label);
    flex: 0 0 84px;
    font-size: 0.69rem; font-weight: 600; color: var(--ink-3); letter-spacing: 0.04em;
  }
}

/* The legal header carries logo + "Back to site" on one line with no toggle to
   collapse into. At 320px that came to 278px of content in 248px of space — a
   28px overflow. Scaling the wordmark and tightening the gap fits it with room
   to spare; measured at 320px, the narrowest width tested. */
@media (max-width: 420px) {
  /* The facsimile is a document, so at phone width it reflows rather than
     shrinking further - the brief allows compromising the preview before
     readability. */
  .rd-page { padding: 12px 12px; font-size: 9px; }
  .rd-page-top { flex-direction: column; gap: 8px; }
  .rd-page-title { text-align: left; }
  .rd-page-title dl div { justify-content: flex-start; }
  .rd-page-title dd { text-align: left; min-width: 0; }
  .rd-page-from strong, .rd-page-from span, .rd-page-to strong, .rd-page-to span { overflow-wrap: break-word; }
  .logo-link img { height: 42px; }

  .legal-header .header-in { gap: 12px; }
  .legal-header .logo-link img { height: 32px; }
  .legal-header .back { font-size: 0.8rem; }
}

/* 16. Reduced motion -------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .btn, .nav-toggle span, .faq summary::after { transition: none; }
}
