/* MaxMyCC — design tokens from the "Precision Rewards" Stitch design system */
:root {
  --navy: #0f172a;
  --navy-800: #1e293b;
  --navy-700: #334155;
  --navy-50: #f1f5f9;
  --emerald: #10b981;
  --emerald-dark: #047857;
  --emerald-50: #ecfdf5;
  --slate: #64748b;
  --slate-100: #f1f5f9;
  --slate-200: #e2e8f0;
  --slate-300: #cbd5e1;
  --slate-400: #94a3b8;
  --bg: #f8fafc;
  --white: #ffffff;
  --amber: #f59e0b;
  --amber-bg: #fffbeb;

  /* THE THREE RAMPS THAT WERE NEVER TOKENISED. Warning, danger and success each had a text
     colour, a fill and a border living as loose hex across 30 pages — #b45309 alone appeared 18
     times. A recolour that only moved --emerald and --navy left all three behind, which is the
     failure that makes a restyle feel impossible: the buttons change and the alert banners don't.
     Named on the 50-900 scale like --navy-*/--slate-*, not semantically, so a reference palette
     can be dropped in ramp for ramp. */
  --amber-100: #fef3c7;
  --amber-200: #fde68a;
  --amber-300: #fcd34d;
  --amber-700: #b45309;
  --amber-800: #92400e;

  --red-50: #fef2f2;
  --red-200: #fecaca;
  --red-700: #b91c1c;

  --emerald-200: #a7f3d0;
  --emerald-800: #065f46;

  --slate-600: #475569;
  /* Zebra striping on legal tables, and the border used inside .dark-section where --slate-200
     would glare against navy. Neither is on a standard scale; both are real surfaces. */
  --surface-subtle: #fafbfc;
  --dark-border: #2c3a52;
  --font-sans: "Hanken Grotesk", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
  --radius-sm: 4px;
  --radius-lg: 8px;
  /* CHANNEL TRIPLETS. Any colour that is used at partial opacity somewhere has to exist here as
     bare "r, g, b" as well as as a hex, because rgba() cannot take a hex. Without these, a recolour
     changes the solid emerald button but leaves its glow the old green — the two drift apart and
     the drift is invisible until someone looks at the two side by side. */
  --navy-rgb: 15, 23, 42;
  --emerald-rgb: 16, 185, 129;
  --emerald-dark-rgb: 4, 120, 87;
  --bg-rgb: 248, 250, 252;
  --white-rgb: 255, 255, 255;

  /* Shadows are navy, not black — but they point at their own token so depth can be re-hued
     without touching the text colour that happens to share the value. */
  --shadow-rgb: var(--navy-rgb);
  --shadow-float: 0 4px 20px rgba(var(--shadow-rgb), 0.08);
  /* Soft depth for info-card surfaces. Two stacked layers rather than one: a tight, barely
     visible contact shadow plus a wider diffuse one reads as lift instead of as a grey halo.
     Deepened 2026-08-07 (was .04 / 0 2px 8px .05). The contact layer keeps its 1px offset so
     edges stay crisp; the lift comes from pushing the DIFFUSE layer further down and wider,
     which is what reads as height. Raising alpha alone just greys the card. */
  --shadow-card: 0 1px 2px rgba(var(--shadow-rgb), .07), 0 4px 12px rgba(var(--shadow-rgb), .09);
  /* The nav's static right-hand edge on desktop — a hairline plane separator, not a lift.
     Deepened 2026-08-07 (was 1px 0 3px .04). */
  --shadow-edge: 1px 0 5px rgba(var(--shadow-rgb), .08);
  /* The nav when it floats ABOVE content: the hover-expanded rail and the mobile drawer. This one
     genuinely overlaps the page, so it carries the most weight of the three.
     Deepened 2026-08-07 (was 4px 0 16px .10). */
  --shadow-drawer: 4px 0 18px rgba(var(--shadow-rgb), .15);
  --scrim: rgba(var(--shadow-rgb), .4);
  /* The hero receipt and guarantee card sit on navy and cast a deep BLACK shadow, not a navy one —
     a navy shadow on a navy section is invisible. Separate token so it is retunable, and so nobody
     later "consolidates" it into --shadow-rgb and flattens the signature element. */
  --shadow-paper-rgb: 0, 0, 0;
  --max-width: 1440px;
  --content-width: 1120px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  color: var(--navy);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; }
a { color: inherit; }

.container {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0 24px;
}

/* Typography */
h1, h2, h3 { font-weight: 700; letter-spacing: -0.02em; }
.display { font-size: clamp(34px, 5vw, 52px); line-height: 1.12; }
.headline { font-size: clamp(26px, 3.4vw, 34px); line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; }
.label-caps {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--emerald-dark);
}
.mono { font-family: var(--font-mono); }
.muted { color: var(--slate); }

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 24px;
  border-radius: var(--radius-sm);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
  white-space: nowrap;
}
.btn-primary { background: var(--emerald); color: var(--white); }
.btn-primary:hover { background: var(--emerald-dark); }
.btn-outline { border-color: var(--navy); color: var(--navy); background: transparent; }
.btn-outline:hover { background: var(--navy); color: var(--white); }
.btn-outline-light { border-color: rgba(var(--white-rgb), .4); color: var(--white); background: transparent; }
.btn-outline-light:hover { border-color: var(--white); }
.btn-sm { padding: 9px 18px; font-size: 14px; }

/* Nav */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(var(--white-rgb), .92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--slate-200);
}
.nav-inner {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0 24px;
  height: 68px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.wordmark {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--navy);
}
.wordmark em { font-style: normal; color: var(--emerald); }
.nav-links { display: flex; align-items: center; gap: 28px; list-style: none; }
.nav-links a { text-decoration: none; font-size: 15px; font-weight: 500; color: var(--navy-700); }
.nav-links a:hover, .nav-links a.active { color: var(--navy); }
.nav-links a.active { border-bottom: 2px solid var(--emerald); padding-bottom: 2px; }
.nav-cta { display: flex; align-items: center; gap: 20px; }
/* `mnav-toggle`, NOT `nav-toggle`: the app sidebar's collapse/pin control (further down this
   file, under `.side-head`) already owns `.nav-toggle`. Two unrelated components shared the
   name, and because the sidebar's rule comes LATER it won the cascade on every marketing page
   — the hamburger sat visible at desktop width doing nothing (`.nav.open .nav-links` is
   720px-only), and the sidebar's own `@media (max-width:1000px){display:none}` then hid it on
   mobile, where it is the only navigation there is. Keep the prefix. */
.mnav-toggle { display: none; background: none; border: 1px solid var(--slate-300); border-radius: var(--radius-sm); padding: 8px 10px; font-size: 18px; line-height: 1; cursor: pointer; }

/* Sections */
section { padding: 88px 0; }
section.tight { padding: 48px 0; }
.section-head { max-width: 620px; margin-bottom: 48px; }
.section-head .headline { margin: 10px 0 12px; }
.on-white { background: var(--white); border-top: 1px solid var(--slate-200); border-bottom: 1px solid var(--slate-200); }

/* Hero */
.hero { padding: 96px 0; }
.hero-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: 64px; align-items: center; }
.hero p.lede { font-size: 18px; line-height: 1.6; color: var(--navy-700); margin: 20px 0 32px; max-width: 520px; }
.hero .actions { display: flex; gap: 16px; flex-wrap: wrap; }
.hero .mono-inline { font-family: var(--font-mono); font-size: .92em; color: var(--emerald-dark); font-weight: 600; }

/* Hero mock card */
.mock-card {
  background: var(--white);
  border: 1px solid var(--slate-200);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float);
  padding: 28px;
}
.mock-card .row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--emerald-50);
  color: var(--emerald-dark);
}
.mock-points { font-family: var(--font-mono); font-size: 34px; font-weight: 700; margin: 6px 0 22px; }
.mock-points small { font-size: 15px; color: var(--slate); font-weight: 500; }
.bar-row { display: grid; grid-template-columns: 26px 1fr 48px; align-items: center; gap: 12px; margin-bottom: 14px; }
.bar-row .icon { display: inline-flex; align-items: center; color: var(--slate); }
.bar-row .icon svg { width: 17px; height: 17px; }
.bar-track { height: 6px; background: var(--slate-100); border-radius: 999px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--emerald); border-radius: 999px; }
.bar-val { font-family: var(--font-mono); font-size: 12px; color: var(--slate); text-align: right; }
.mock-tip {
  margin-top: 22px;
  background: var(--navy);
  color: var(--slate-200);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  font-size: 13px;
  display: flex;
  gap: 10px;
  align-items: flex-start;
}
.mock-tip strong { color: var(--white); }
.mock-tip .dot { color: var(--emerald); font-size: 15px; }

/* Stat strip */
.stat-strip { background: var(--white); border-top: 1px solid var(--slate-200); border-bottom: 1px solid var(--slate-200); padding: 36px 0; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; text-align: center; }
.stat .num { font-family: var(--font-mono); font-size: 30px; font-weight: 700; color: var(--navy); }
.stat .lbl { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--slate); margin-top: 6px; }

/* Cards & grids */
.card {
  background: var(--white);
  border: 1px solid var(--slate-200);
  border-radius: var(--radius-lg);
  padding: 28px;
 box-shadow: var(--shadow-card); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.step-num { font-family: var(--font-mono); font-size: 13px; font-weight: 600; color: var(--emerald-dark); }
.card h3 { font-size: 19px; font-weight: 600; margin: 12px 0 8px; letter-spacing: -0.01em; }
.card p { font-size: 15px; color: var(--slate); line-height: 1.55; }
.feature-icon { display: inline-flex; color: var(--emerald-dark); }
.feature-icon svg { width: 26px; height: 26px; }

/* Split cards */
.split-card { padding: 36px; display: flex; flex-direction: column; }
.split-card ul { list-style: none; margin: 18px 0 26px; flex: 1; }
.split-card li { padding: 7px 0 7px 26px; position: relative; font-size: 15px; color: var(--navy-700); }
.split-card li::before { content: "✓"; position: absolute; left: 0; color: var(--emerald-dark); font-weight: 700; }
.split-card .from { font-family: var(--font-mono); font-size: 14px; color: var(--slate); margin-top: 4px; }
.arrow-link { font-weight: 600; text-decoration: none; color: var(--navy); }
.arrow-link:hover { color: var(--emerald-dark); }

/* Pricing */
.toggle { display: inline-flex; background: var(--slate-100); border: 1px solid var(--slate-200); border-radius: var(--radius-sm); padding: 4px; margin: 28px 0 8px; }
.toggle button {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 9px 26px;
  border: none;
  background: transparent;
  color: var(--slate);
  border-radius: 3px;
  cursor: pointer;
  font-weight: 600;
}
.toggle button.active { background: var(--navy); color: var(--white); }

.price-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 24px; max-width: 860px; margin: 40px auto 0; }
.price-card { position: relative; background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); padding: 32px; display: flex; flex-direction: column;  box-shadow: var(--shadow-card); }
.price-card.featured { border: 2px solid var(--emerald); }
.plan-badge {
  position: absolute; top: -12px; left: 50%; transform: translateX(-50%);
  background: var(--emerald); color: var(--white);
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .08em;
  padding: 4px 14px; border-radius: 999px; white-space: nowrap;
}
.plan-badge.navy { background: var(--navy); }
.price-card h3 { font-size: 20px; font-weight: 600; }
.price-card .sub { font-size: 14px; color: var(--slate); margin: 6px 0 20px; min-height: 42px; }
.price { font-family: var(--font-mono); font-size: 40px; font-weight: 700; }
.price small { font-size: 14px; font-weight: 500; color: var(--slate); }
.price-alt { font-family: var(--font-mono); font-size: 14px; color: var(--slate); margin-top: 4px; }
.price-card ul { list-style: none; margin: 24px 0 28px; flex: 1; }
.price-card li { padding: 7px 0 7px 26px; position: relative; font-size: 14.5px; color: var(--navy-700); }
.price-card li::before { content: "✓"; position: absolute; left: 0; color: var(--emerald-dark); font-weight: 700; }

.teaser-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 40px; }
.teaser { position: relative; background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); padding: 24px 20px; text-align: center; }
.teaser .t-name { font-size: 14px; font-weight: 600; margin-bottom: 8px; }
.teaser .t-price { font-family: var(--font-mono); font-size: 24px; font-weight: 700; }
.teaser .t-alt { font-family: var(--font-mono); font-size: 12px; color: var(--slate); margin-top: 4px; }

/* Info banner */
.info-banner {
  display: flex; gap: 14px; align-items: flex-start;
  background: var(--navy-50); border: 1px solid var(--slate-300); border-left: 4px solid var(--navy);
  border-radius: var(--radius-sm); padding: 18px 20px; margin-top: 28px;
  font-size: 14.5px; color: var(--navy-700); max-width: 860px; margin-left: auto; margin-right: auto;
}
.info-banner .icon { font-size: 18px; line-height: 1.3; }

/* Comparison table */
.table-wrap { overflow-x: auto; background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); margin-top: 40px; }
table.compare { width: 100%; border-collapse: collapse; min-width: 760px; }
.compare th, .compare td { padding: 14px 18px; text-align: left; border-bottom: 1px solid var(--slate-100); font-size: 14px; }
.compare thead th {
  background: var(--bg);
  font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--slate);
}
.compare tbody tr:last-child td, .compare tbody tr:last-child th { border-bottom: none; }
/* The feature-name column is <th scope="row"> so a screen reader can say WHICH feature a cell's
   "Included" belongs to. Weight held at 400 so the table looks exactly as it did — the change is
   for the accessibility tree, not the design. */
.compare tbody th { font-weight: 400; }
/* The ✓ / — column is the ONLY thing separating one plan from another in this table, and it was
   the least legible ink on the page: --emerald on white is 2.54:1 and --slate-300 is 1.48:1,
   against the 4.5:1 AA floor. A shopper who cannot resolve these cannot compare the plans they
   are being asked to choose between. --emerald-dark (5.48:1) and --slate (4.76:1) keep the same
   green/grey reading at a weight that survives a dim screen or ordinary low vision.
   The glyphs also carry their meaning in an .sr-only span — see pricing.html. */
.compare td.check { color: var(--emerald-dark); font-weight: 700; }
.compare td.dash { color: var(--slate); }
.compare td .mono-val { font-family: var(--font-mono); font-size: 13px; }

/* FAQ */
.faq { max-width: 760px; margin: 40px auto 0; }
.faq-item { background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); margin-bottom: 12px; }
.faq-item summary {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 18px 22px; cursor: pointer; font-weight: 600; font-size: 15.5px; list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; font-family: var(--font-mono); font-size: 18px; color: var(--slate); transition: transform .15s; }
.faq-item[open] summary::after { content: "–"; }
.faq-item .answer { padding: 0 22px 20px; font-size: 14.5px; color: var(--slate); line-height: 1.6; }

/* Security / dark sections */
.dark-section { background: var(--navy); color: var(--slate-200); }
.dark-section .headline, .dark-section h3 { color: var(--white); }
.dark-section .label-caps { color: var(--emerald); }
.dark-section .card { background: var(--navy-800); border-color: var(--dark-border); }
.dark-section .card p { color: var(--slate-400); }

/* CTA band */
.cta-band { background: var(--navy); color: var(--white); text-align: center; padding: 80px 24px; }
.cta-band .headline { color: var(--white); margin-bottom: 12px; }
.cta-band p { color: var(--slate-400); margin-bottom: 32px; }

/* Footer */
footer { background: var(--navy); color: var(--slate-400); padding: 64px 0 40px; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 40px; }
.footer-grid .wordmark { color: var(--white); }
.footer-grid p { font-size: 14px; margin-top: 12px; max-width: 260px; }
.footer-col h4 { font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--slate-400); margin-bottom: 16px; }
.footer-col ul { list-style: none; }
.footer-col li { margin-bottom: 10px; }
.footer-col a { color: var(--slate-300); text-decoration: none; font-size: 14.5px; }
.footer-col a:hover { color: var(--white); }
.footer-bottom { border-top: 1px solid var(--dark-border); margin-top: 48px; padding-top: 24px; font-size: 13px; display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }

/* Page header (pricing) */
.page-head { text-align: center; padding: 72px 0 0; }
.page-head .display { margin: 12px 0 16px; }
.page-head p { max-width: 560px; margin: 0 auto; color: var(--navy-700); font-size: 17px; }

.hidden { display: none !important; }

/* Responsive */
@media (max-width: 960px) {
  .hero-grid, .grid-3, .grid-2, .price-grid { grid-template-columns: 1fr; }
  .teaser-grid, .stats { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  section { padding: 64px 0; }
  .hero { padding: 64px 0; }
}
@media (max-width: 720px) {
  .nav-links, .nav-cta .btn-ghost-link { display: none; }
  .mnav-toggle { display: block; }
  .nav.open .nav-links {
    display: flex; flex-direction: column; align-items: flex-start;
    position: absolute; top: 68px; left: 0; right: 0;
    background: var(--white); border-bottom: 1px solid var(--slate-200);
    padding: 20px 24px; gap: 16px;
  }
  .teaser-grid, .stats { grid-template-columns: 1fr 1fr; }
  /* Panel headers carry a heading plus a row of buttons/links. Below this width the row no longer
     fits beside the heading, and without wrapping the heading was squeezed to ~70px and its
     legend text broke one word per line (audit.html "Category routing analysis", seen on a
     540px viewport 2026-09-02). The inner row is an inline-styled flex div, so it needs its own
     wrap rule too. */
  .panel-head { flex-wrap: wrap; gap: 10px; }
  .panel-head > div { flex-wrap: wrap; }
}
@media (max-width: 480px) {
  .teaser-grid, .stats { grid-template-columns: 1fr; }
}

/* ============ App shell (authenticated pages) ============ */
.app { display: flex; min-height: 100vh; }
.sidebar {
  width: 260px; flex-shrink: 0; background: var(--white);
  border-right: 1px solid var(--slate-200);
  padding: 24px 16px; display: flex; flex-direction: column; gap: 4px;
  position: sticky; top: 0; height: 100vh;
}
/* Desktop: the nav is FIXED, not sticky.
   `position: sticky; top: 0` pins only against VERTICAL scroll. Anything that pushes the page
   sideways — a wide comparison table, a long category row — scrolled the whole nav off-screen to
   the left, because sticky has no horizontal anchor. Fixed positioning holds on both axes.
   Scoped to >1000px so the off-canvas mobile drawer below is untouched; .main takes a matching
   left margin because a fixed sidebar is out of the flex flow and no longer reserves its own space.
   overflow-y so the nav can scroll internally once the Annual Tools list makes it taller than the
   viewport. */
@media (min-width: 1001px) {
  .sidebar { position: fixed; top: 0; left: 0; overflow-y: auto; z-index: 50; transition: width .16s ease, padding .16s ease; }
  .main { margin-left: 260px; transition: margin-left .16s ease; }

  /* Collapsed: an icon rail, with the reclaimed width handed to .main. */
  .app.nav-collapsed .sidebar { width: 64px; padding-left: 8px; padding-right: 8px; }
  .app.nav-collapsed .main { margin-left: 64px; }

  /* Hovering (or tabbing into) the rail expands it and the content slides right with it, so the
     page never sits underneath the nav (operator decision 2026-08-01, reversing the earlier
     overlay behaviour: the left edge of the body should always meet the right edge of the menu).
     .main transitions on the same curve, so the two move as one. */
  .app.nav-collapsed .sidebar:hover,
  .app.nav-collapsed .sidebar:focus-within {
    width: 260px; padding-left: 16px; padding-right: 16px;
    box-shadow: var(--shadow-drawer);
  }
  /* .main is the adjacent sibling of .sidebar, so it can follow the hover state directly. */
  .app.nav-collapsed .sidebar:hover + .main,
  .app.nav-collapsed .sidebar:focus-within + .main { margin-left: 260px; }

  /* PEEK: carried across a navigation that was started from a hover-expanded rail. Browsers do not
     apply :hover until the first mouse move after load, so without this the next page rendered
     collapsed under a stationary cursor and then snapped open — the jump the operator saw. It is
     presentation only; the pinned preference is untouched, and JS drops the class as soon as the
     pointer is shown to be elsewhere. */
  .app.nav-collapsed.nav-peek .sidebar {
    width: 260px; padding-left: 16px; padding-right: 16px;
    box-shadow: var(--shadow-drawer);
  }
  .app.nav-collapsed.nav-peek .main { margin-left: 260px; }
  .app.nav-collapsed.nav-peek .nav-toggle .tg-logo { display: none; }
  .app.nav-collapsed.nav-peek .nav-toggle .tg-pin { display: inline-flex; }
  /* No reveal delay here: the page is already open on arrival, so the text should simply be there. */
  .app.nav-collapsed.nav-peek .side-label { opacity: 1; transition-delay: 0s; }

  /* A soft edge on the nav so it reads as a separate plane from the content. */
  .sidebar { box-shadow: var(--shadow-edge); }

  /* Labels fade rather than display:none, and they NEVER wrap.
     Two separate causes of the jump when opening, both fixed here:
       - without nowrap the labels wrapped at the rail's narrow intermediate widths, growing every
         row and shoving the icons around until the animation finished;
       - revealing them at the START of the open meant that reflow happened in full view. Closing
         never looked jumpy because the text disappears instantly, before the width changes — so
         opening now mirrors that, holding the text back until the slide has finished. */
  /* At rest the label is display:none — it must not occupy the row, or a ~115px nowrap label in a
     47px row pushes the icon clean off the left edge of the rail. While hovering it returns to the
     flow (the row reverts to normal padding, so the icon sits at its usual x and nothing shoves it)
     but starts transparent, fading in only after the width has finished animating. */
  .app.nav-collapsed .side-label { opacity: 0; }
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .side-label { display: none; }
  .app.nav-collapsed .sidebar:hover .side-label,
  .app.nav-collapsed .sidebar:focus-within .side-label { opacity: 1; transition-delay: .15s; }
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .side-link { justify-content: center; padding-left: 0; padding-right: 0; }
  .app.nav-collapsed .sidebar { overflow-x: hidden; }

  /* The wordmark and the plan chip use visibility, NOT display. display:none would remove their
     boxes and every nav icon below would jump upward as the rail collapsed; visibility keeps the
     exact same vertical rhythm in both states, so the icons never move. */
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .wordmark,
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .plan-chip,
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .plan-status-chip,
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .side-legal,
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .tools-heading { visibility: hidden; transition-delay: 0s; }
  .app.nav-collapsed .sidebar:hover .wordmark,
  .app.nav-collapsed .sidebar:hover .plan-chip,
  .app.nav-collapsed .sidebar:hover .plan-status-chip,
  .app.nav-collapsed .sidebar:hover .tools-heading,
  .app.nav-collapsed .sidebar:focus-within .wordmark,
  .app.nav-collapsed .sidebar:focus-within .plan-chip,
  .app.nav-collapsed .sidebar:focus-within .plan-status-chip,
  .app.nav-collapsed .sidebar:focus-within .tools-heading { transition-delay: .15s; }
  /* nowrap now lives on the unconditional rules below, because it has to hold DURING the
     64->260px animation too, not just at the resting width. */
  /* The wordmark is wider than the rail; clip it to zero width rather than let it stretch the flex
     row. white-space:nowrap is load-bearing — at width:0 the text would otherwise wrap to one
     character per line, making the header tall and pushing every nav icon DOWN as it collapsed. */
  /* justify-content:center puts the mark on the same vertical axis as the nav icons below,
     which are centred by .side-link. space-between would pin it to the right edge. */
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .side-head { overflow: hidden; justify-content: center; }
  /* min-width:0 is required alongside width:0 — a flex item defaults to min-width:auto and will
     not shrink below its content, which left ~20px of wordmark plus the 8px gap nudging the
     brand mark off the icons' centre line. gap:0 removes the last of that offset. */
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .wordmark { width: 0; min-width: 0; padding: 0; white-space: nowrap; }
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .side-head { gap: 0; }

  /* Toggle icon by state: chevron when open, brand mark on the resting rail, pin once you hover
     the rail (that pin is what locks it open again). */
  .app.nav-collapsed .nav-toggle .tg-collapse { display: none; }
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .nav-toggle .tg-logo { display: inline-flex; }
  .app.nav-collapsed .sidebar:hover .nav-toggle .tg-pin,
  .app.nav-collapsed .sidebar:focus-within .nav-toggle .tg-pin { display: inline-flex; }
  /* On the resting rail the control is the logo, so drop the button chrome. */
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .nav-toggle { border-color: transparent; }

  /* Account type on the collapsed rail, rotated to read bottom-to-top above the sign-out icon. */
  .app.nav-collapsed:not(.nav-peek) .sidebar:not(:hover):not(:focus-within) .rail-plan { display: block; }
}

/* Wordmark and the collapse/pin control share the top row. */
.side-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.nav-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex-shrink: 0; padding: 0;
  border: 1px solid var(--slate-200); border-radius: 6px;
  background: transparent; color: var(--slate); cursor: pointer;
}
.nav-toggle:hover { background: var(--bg); color: var(--navy); }
.nav-toggle:focus-visible { outline: 2px solid var(--emerald); outline-offset: 1px; }
/* Fixed icon box, and an explicit line-height on the row. Both are load-bearing for "icons must not
   move when the rail collapses": the icon is 18px but the label's line box is ~21px, so a link
   containing only an icon is SHORTER than one containing text, and every row below would creep
   upward. Pinning both to 20px makes the row height identical with or without the label. */
.side-icon { width: 18px; height: 20px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.side-link { line-height: 20px; }
.side-label { white-space: nowrap; transition: opacity .12s ease; }
.sidebar .wordmark, .sidebar .plan-chip, .sidebar .tools-heading { transition: visibility 0s; }
/* Unconditional: while the rail animates open, an intermediate width would wrap these onto
   extra lines, grow the header and make every icon below jump — the flicker seen on open.
   None of them should ever wrap at any width. */
.sidebar .plan-chip, .sidebar .tools-heading, .sidebar .wordmark { white-space: nowrap; }
.nav-toggle .tg { display: inline-flex; align-items: center; justify-content: center; }
.nav-toggle .tg-pin, .nav-toggle .tg-logo { display: none; }
/* Rail-only. `vertical-rl` + 180° reads bottom-to-top, which is the counterclockwise direction
   asked for; plain vertical-rl would read top-to-bottom. */
.rail-plan {
  display: none; writing-mode: vertical-rl; transform: rotate(180deg);
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .08em;
  color: var(--emerald-dark); align-self: center; margin: 0 0 12px;
  white-space: nowrap; max-height: 220px; overflow: hidden;
}
/* The mobile drawer has its own open/close button; a second control would just confuse it. */
@media (max-width: 1000px) { .nav-toggle { display: none; } }
.sidebar .wordmark { font-size: 20px; padding: 0 10px; }
.sidebar .plan-chip {
  margin: 8px 10px 20px; font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .07em;
  color: var(--emerald-dark); background: var(--emerald-50); border: 1px solid var(--emerald-200);
  border-radius: 3px; padding: 3px 8px; display: inline-block; width: fit-content;
}
/* INACTIVE gets its own chip on its own line, in red.
   It used to be appended to the plan chip as " · INACTIVE". The plan chip is `white-space: nowrap`
   inside a 260px rail — deliberately, so the label cannot reflow and make every icon below it jump
   while the rail animates — so "PERSONAL · ONE-TIME AUDIT · INACTIVE" simply ran off the edge and
   the word that mattered most was the part clipped off.
   The sidebar is a flex column, so a second element is on its own line for free. The negative top
   margin cancels the plan chip's 20px bottom margin plus the column's 4px gap, pulling this up to
   sit directly beneath it; hidden, it takes no space and the plan chip's own spacing stands. */
.sidebar .plan-status-chip {
  display: none; margin: -20px 10px 20px; font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: .07em; color: var(--red-700); background: var(--red-50);
  border: 1px solid var(--red-200); border-radius: 3px; padding: 3px 8px; width: fit-content;
  white-space: nowrap;
}
.side-link {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  font-size: 14.5px; font-weight: 500; color: var(--navy-700); text-decoration: none;
  border-left: 2px solid transparent; border-radius: 0 4px 4px 0;
}
.side-link:hover { background: var(--bg); }
.side-link.active { border-left-color: var(--emerald); background: var(--bg); color: var(--navy); font-weight: 600; }
/* Visually hidden but announced by screen readers. The app had no such utility, so inputs that
   could not carry a visible label (the 2FA code fields) had no accessible name at all. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Skip to content. Every app page opens with the same ~14 nav links, so reaching the actual report
   by keyboard meant tabbing past all of them on every single page load. Hidden until focused. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--navy); color: var(--white); padding: 10px 16px;
  border-radius: 0 0 var(--radius-sm) 0; font-size: 14px; font-weight: 600; text-decoration: none;
}
.skip-link:focus { left: 0; }
.sidebar .spacer { flex: 1; }
/* Legal links under Sign out. Deliberately quiet — these must be reachable from inside the app,
   not compete with navigation. Wraps rather than overflows, because the rail is only 260px. */
.side-legal {
  display: flex; flex-wrap: wrap; gap: 4px 10px;
  padding: 12px 14px 4px; margin-top: 4px;
  border-top: 1px solid var(--slate-200);
}
.side-legal a { font-size: 12px; color: var(--slate); text-decoration: none; white-space: nowrap; }
.side-legal a:hover { color: var(--navy); text-decoration: underline; }
.main { flex: 1; min-width: 0; padding: 32px 40px 64px; max-width: 1180px; }
.topbar { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 28px; }
.topbar h1 { font-size: 28px; letter-spacing: -0.01em; }
.topbar .sub { color: var(--slate); font-size: 14.5px; margin-top: 4px; }
.user-chip { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; white-space: nowrap; }
.user-chip .avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--navy); color: var(--white); display: flex; align-items: center; justify-content: center; font-size: 13px; }

/* Help: a "?" that grows the word "Help" on hover.
   The word is always in the DOM and always readable by assistive tech — it is revealed by
   animating max-width from 0, not by display:none, because display cannot be transitioned and a
   hidden label is a control that announces itself as "?" to a screen reader. */
.user-chip .help-link {
  display: inline-flex; align-items: center; gap: 0;
  color: var(--slate); text-decoration: none; font-weight: 600; font-size: 14px;
  border: 1px solid var(--slate-200); border-radius: 999px; padding: 5px 6px;
  margin-right: 4px; transition: color .15s, border-color .15s, background-color .15s;
}
.user-chip .help-q {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none; font-family: var(--font-mono); font-size: 13px; line-height: 1;
}
.user-chip .help-word {
  max-width: 0; overflow: hidden; white-space: nowrap;
  transition: max-width .22s ease, padding-left .22s ease; padding-left: 0;
}
.user-chip .help-link:hover, .user-chip .help-link:focus-visible {
  color: var(--navy); border-color: var(--navy); background: var(--white);
}
.user-chip .help-link:hover .help-word,
.user-chip .help-link:focus-visible .help-word { max-width: 60px; padding-left: 6px; padding-right: 2px; }
/* Touch devices have no hover, so the word would never appear and the control would be a bare "?".
   Show it permanently there instead — the space is affordable in a topbar. */
@media (hover: none) {
  .user-chip .help-word { max-width: 60px; padding-left: 6px; padding-right: 2px; }
}
/* Respect a reduced-motion preference: reveal the same word, just without the sweep. */
@media (prefers-reduced-motion: reduce) {
  .user-chip .help-word { transition: none; }
}

/* Point-of-use estimate disclaimer, sitting directly under the KPI row on every page that
   shows a headline number. The same words are already in terms.html §3/§4 and in every page
   footer, but a disclaimer that is present is not the same as one that is conspicuous, and
   conspicuousness is what decides whether it does any work. Deliberately NOT inside a .kpi card:
   it would double that card's height and unbalance the row. Neutral background rather than the
   amber warning treatment — this shows on every dashboard load, and a permanent alarm is an
   ignored alarm. */
.advice-note { background: var(--slate-100); border: 1px solid var(--slate-200);
  border-left: 3px solid var(--amber); border-radius: var(--radius-lg);
  padding: 12px 16px; margin: -6px 0 24px;
  font-size: 12.5px; line-height: 1.55; color: var(--navy-700); }
.advice-note strong { color: var(--navy); font-weight: 700; }
.advice-note a { color: var(--emerald-dark); font-weight: 600; }

.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }
.kpi { background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); padding: 18px 20px;  box-shadow: var(--shadow-card); }
.kpi .k-label { font-family: var(--font-mono); font-size: 11px; letter-spacing: .07em; text-transform: uppercase; color: var(--slate); }
.kpi .k-value { font-family: var(--font-mono); font-size: 26px; font-weight: 700; margin-top: 8px; }
.kpi .k-delta { font-size: 12.5px; margin-top: 6px; color: var(--emerald-dark); font-weight: 600; }
.kpi .k-delta.bad { color: var(--amber-700); }
/* The basis line under a KPI: what the number is measured against ("at standard point values").
   Was declared inline on dashboard.html and again on dashboard-biz2.html, and a third caller
   (tool-vendor-sprawl.html) would have been a third copy — or, as it first shipped, an unstyled
   class that silently rendered at body size. One declaration, here with the rest of .kpi. */
.kpi .kpi-basis, .kpi-basis { font-size: 11px; color: var(--slate-400); line-height: 1.35; margin-top: 1px; }

.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table th {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--slate); background: var(--bg);
  text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--slate-200);
}
.data-table td { padding: 12px 14px; border-bottom: 1px solid var(--slate-100); vertical-align: middle; }
.data-table tr:last-child td { border-bottom: none; }
.data-table .mono { font-size: 13px; }
.data-table .pos { color: var(--emerald-dark); font-weight: 600; }
.chip {
  display: inline-block; font-size: 12px; font-weight: 600; padding: 3px 10px;
  border-radius: 3px; background: var(--navy-50); color: var(--navy-700); white-space: nowrap;
}
.chip.green { background: var(--emerald-50); color: var(--emerald-dark); }
.chip.amber { background: var(--amber-bg); color: var(--amber-700); }

/* Inline status messages. upload.html had defined these locally and account.html had not, so
   account.html's three toasts — billing errors, 2FA results, and the refund decision — rendered as
   unstyled body text with no colour and no boundary. The refusal that tells a customer their
   refund request was declined looked like a stray paragraph. Shared here so both pages agree;
   upload.html's local block still wins where it differs (its own margins). Announced to screen
   readers by the role="status" wrapper each toast sits in — see the pages. */
.toast { display: none; font-size: 13px; padding: 10px 14px; border-radius: var(--radius-sm); border: 1px solid transparent; }
.toast.show { display: block; }
.toast.ok { background: var(--emerald-50); color: var(--emerald-dark); border-color: var(--emerald-200); }
.toast.warn { background: var(--amber-bg); color: var(--amber-700); border-color: var(--amber); }

.warn-banner {
  display: flex; gap: 14px; align-items: flex-start;
  background: var(--amber-bg); border: 1px solid var(--amber); border-left: 4px solid var(--amber);
  border-radius: var(--radius-sm); padding: 16px 18px; margin-bottom: 24px; font-size: 14px;
}
.panel { background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); margin-bottom: 24px;  box-shadow: var(--shadow-card); }
.panel-head { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--slate-100); }
.panel-head h2 { font-size: 17px; font-weight: 600; }
.panel-body { padding: 20px; }
.panel .table-scroll { overflow-x: auto; }

/* Sign-in */
.auth-wrap { min-height: calc(100vh - 68px); display: flex; align-items: center; justify-content: center; padding: 40px 20px; }
.auth-card { width: 100%; max-width: 400px; background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); padding: 36px; }
.field { margin-bottom: 18px; }
.field label { display: block; font-family: var(--font-mono); font-size: 11px; letter-spacing: .07em; text-transform: uppercase; color: var(--slate); margin-bottom: 6px; }
.field input { width: 100%; padding: 11px 12px; border: 1px solid var(--slate-300); border-radius: var(--radius-sm); font-family: var(--font-sans); font-size: 15px; }
.field input:focus { outline: 2px solid var(--navy); outline-offset: -1px; border-color: var(--navy); }
.auth-error { color: var(--red-700); font-size: 13.5px; margin-bottom: 14px; display: none; }
.hint { font-size: 12.5px; color: var(--slate); margin-top: 16px; text-align: center; }
.hint code { font-family: var(--font-mono); background: var(--bg); border: 1px solid var(--slate-200); padding: 1px 5px; border-radius: 3px; }

/* Card comparison */
/* minmax(0, 1fr), not 1fr: a grid item defaults to min-width:auto and refuses to shrink below
   its content's min-content width. The comparison table is ~1700px at business width, so the
   panel was blown out to that size and the PAGE scrolled sideways — .table-scroll's
   overflow-x never got the chance to do its job. minmax(0,…) lets the column shrink so the
   table scrolls inside its own container, which is what was intended all along. */
.compare-layout { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 20px; align-items: start; }
.picker { background: var(--white); border: 1px solid var(--slate-200); border-radius: var(--radius-lg); padding: 16px; position: sticky; top: 24px; max-height: calc(100vh - 48px); overflow-y: auto;  box-shadow: var(--shadow-card); }
.picker h3 { font-size: 14px; margin-bottom: 4px; }
.picker .picker-sub { font-size: 12px; color: var(--slate); margin-bottom: 12px; }
.pick-item { display: flex; align-items: center; gap: 10px; padding: 8px 8px; border-radius: 4px; font-size: 13.5px; cursor: pointer; }
.pick-item:hover { background: var(--bg); }
.pick-item input { accent-color: var(--emerald); width: 15px; height: 15px; }
.pick-item .own { font-family: var(--font-mono); font-size: 9.5px; color: var(--emerald-dark); background: var(--emerald-50); padding: 1px 5px; border-radius: 3px; }
.mult { font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; padding: 2px 8px; border-radius: 3px; display: inline-block; min-width: 34px; text-align: center; white-space: nowrap; }
/* The value figure is the one the ranking uses, but the multiplier is the one the customer
   recognises, so the multiplier leads and this sits behind it — present and legible, not shouting.
   min-width above was sized for "2×" alone; nowrap stops "2× 3.2¢/$" breaking across two lines in
   a narrow column. */
.mult .mult-val { font-weight: 500; opacity: .75; font-size: 11.5px; }
.mult.hi { background: var(--emerald-50); color: var(--emerald-dark); }
.mult.mid { background: var(--navy-50); color: var(--navy-700); }
/* --slate-400 on white is 2.56:1. Both of these are load-bearing: .mult.lo is the earn rate on a
   card (the number the whole comparison exists to show) and .rm-btn is the only way to take a card
   back out of the comparison. --slate is 4.76:1 and still reads as the quiet end of the scale. */
.mult.lo { color: var(--slate); }
.rm-btn { border: none; background: none; color: var(--slate); cursor: pointer; font-size: 15px; padding: 2px 6px; border-radius: 3px; }
.rm-btn:hover { color: var(--red-700); background: var(--red-50); }

.mobile-menu-btn {
  display: none; position: fixed; top: 14px; left: 14px; z-index: 101;
  width: 42px; height: 42px; border-radius: 8px; background: var(--white);
  border: 1px solid var(--slate-200); align-items: center; justify-content: center;
  font-size: 19px; cursor: pointer; box-shadow: 0 1px 3px rgba(var(--shadow-rgb), .08);
}
.mobile-menu-btn:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.sidebar-backdrop { display: none; position: fixed; inset: 0; background: rgba(var(--shadow-rgb), .4); z-index: 99; }
.sidebar-backdrop.open { display: block; }

@media (max-width: 1000px) {
  .app { flex-direction: column; }
  .sidebar {
    width: 260px; height: 100vh; position: fixed; top: 0; left: 0; z-index: 100;
    flex-direction: column; flex-wrap: nowrap; align-items: stretch;
    transform: translateX(-100%);
    box-shadow: var(--shadow-drawer);
    /* translateX alone only moves the drawer OFF-SCREEN — it stays in the accessibility tree and
       in the tab order. On a phone the first ~12 Tab presses went to invisible nav links, and a
       screen reader read the whole closed menu before reaching the page. visibility:hidden takes
       it out of both.
       The two transitions are deliberately asymmetric. Closing delays the flip to hidden by the
       .2s the slide-out takes, so the drawer is still on screen while it leaves. Opening flips it
       at 0s, because `transition: visibility .2s` holds the value at hidden for the first frame —
       long enough that the .focus() call in mmccMobileDrawer() lands on an element that cannot
       take focus yet and silently does nothing. Measured, not assumed. */
    visibility: hidden;
    transition: transform .2s ease, visibility 0s linear .2s;
  }
  .sidebar.open {
    transform: translateX(0);
    visibility: visible;
    transition: transform .2s ease, visibility 0s linear 0s;
  }
  .sidebar { padding-top: 76px; }
  .sidebar .spacer { display: block; }
  .main { padding: 24px 20px 48px; padding-top: 76px; }
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .compare-layout { grid-template-columns: 1fr; }
  .picker { position: static; max-height: none; }
  .mobile-menu-btn { display: flex; }
}

/* Best-in-category cell + apply buttons + picker sections */
td.best-cell { background: var(--emerald-50); box-shadow: inset 3px 0 0 var(--emerald); }
td.best-cell strong { color: var(--emerald-dark); }
.btn-apply { padding: 6px 14px; font-size: 12.5px; }
.picker .section-label { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--slate); margin: 14px 4px 6px; }
.picker .section-label:first-child { margin-top: 0; }
.pick-check { width: 15px; height: 15px; display: inline-flex; align-items: center; justify-content: center; color: var(--emerald-dark); font-weight: 800; font-size: 14px; flex-shrink: 0; }

/* ============ Print (app shell pages) ============ */
/* Accountant-ready printing for audit/detailed-spend/dashboard pages: strip chrome that only makes
   sense on-screen (nav, mobile menu, sort/search controls, action buttons, toasts), let the actual
   report data (panels, tables, KPIs) take the full page width, and avoid splitting a table row or a
   KPI card across a page break. Elements can opt out individually with .no-print instead of requiring
   every page to hand-maintain its own print stylesheet. */
@media print {
  .sidebar, .sidebar-backdrop, .mobile-menu-btn, .user-chip,
  .toast, .btn, .arrow-link, .no-print,
  th.sortable .arrow, .search-row, .inline-picker {
    display: none !important;
  }
  th.sortable { cursor: default; }
  .app { display: block; }
  .main { max-width: none; padding: 0; }
  .topbar { margin-bottom: 16px; }
  .panel { border: 1px solid #999; box-shadow: none; break-inside: avoid; }
  .kpi { border: 1px solid #999; box-shadow: none; break-inside: avoid; }
  .data-table { break-inside: auto; }
  .data-table tr { break-inside: avoid; }
  .table-scroll { overflow: visible; }
  a { color: inherit; text-decoration: none; }
  body { background: var(--white); }
}


/* Inline "working" spinner. Used by the run-gate import notice, which otherwise only changes every
   15 seconds and so reads as frozen at exactly the moment a customer is waiting on us. Honours
   prefers-reduced-motion: the notice already carries the same information in text, so removing the
   animation costs nothing. */
.mmcc-spin {
  display: inline-block; width: 12px; height: 12px; vertical-align: -1px; margin-right: 7px;
  border: 2px solid var(--amber); border-top-color: transparent; border-radius: 50%;
  animation: mmcc-spin 0.8s linear infinite;
}
@keyframes mmcc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .mmcc-spin { animation: none; opacity: .5; } }
