/* ═══════════════════════════════════════════════════════════════════════════
   RAPID REPAIRER — hybrid-01 design system
   ---------------------------------------------------------------------------
   Warm RapidCapture canvas (#f6f3ee), RRN navy rail + navy job hero, green
   accents, Raleway / Red Hat Display type.

   STRICT RULE: portal pages compose ONLY from the component catalog documented
   in docs/rapid-repairer-design-system.md. Every class here belongs to a
   catalog component; do not add ad-hoc page styles. New needs = new catalog
   component + doc entry first.

   Everything portal-specific is namespaced rrp-*; legacy shared-component
   overrides are scoped beneath .rrp-app so RapidDispatch.UI consumers in other
   apps stay untouched.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The canvas is repeated on :root so the page behind the shell matches during
   bootstrap and overscroll, before .rrp-app tokens are in scope. themeBootstrap
   sets data-theme before first paint, so this never flashes the wrong colour. */
:root {
    color-scheme: light;
    --rrp-root-canvas: #f6f3ee;
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --rrp-root-canvas: #070f1d;
}

html,
body,
#app {
    width: 100%;
    min-width: 0;
    min-height: 100%;
    margin: 0;
}

body {
    overflow: hidden;
    background: var(--rrp-root-canvas);
}

/* ── Tokens ──────────────────────────────────────────────────────────────────
   Every colour pairing below is verified against WCAG 2.2: 4.5:1 for text,
   3:1 for non-text (control borders, focus rings, meaningful icons). Ratios in
   comments are measured against the surface the token is actually used on.

   Two rules keep this honest:
     · MUSTARD IS BRAND, AMBER IS SEMANTIC. Mustard is a fill/plate colour and
       is never text or a border on a light surface (1.86:1 there). Aliasing the
       two is what previously made every caution message unreadable.
     · --rrp-faded splits by role. The text tier must clear 4.5:1; only the icon
       tier may sit lower, and only on decorative marks.
   ─────────────────────────────────────────────────────────────────────────── */
.rrp-shell,
.rrp-app,
.rrp-auth,
.rrp-system-shell,
.rrp-bootstrap,
.rrp-toast-region,
#blazor-error-ui,
#rrp-update-ui {
    /* Brand — structural navy, accent green */
    --rrp-navy: #0c2448;
    --rrp-navy-soft: #1b365f;
    --rrp-green: #1cc478;            /* FILLS ONLY — 2.28:1 as text on paper */
    --rrp-green-dark: #08734a;       /* 5.90:1 — green text on light surfaces */
    --rrp-green-deep: var(--rrp-green-dark);
    --rrp-green-line: #9bd5b8;
    --rrp-green-wash: #eef7f2;

    /* Job chat bubbles — the conversation reads as two sides. The repairer's own
       messages carry the RRN logo navy, RRN's replies the RRN logo green, both
       with white ink. --rrp-chat-edge is invisible on the light modal but
       becomes a hairline in dark mode, where the navy bubble would otherwise sit
       too close to the near-navy surface to read as a bubble. */
    --rrp-chat-repairer: var(--rrp-navy);   /* #0c2448 — RRN logo navy */
    --rrp-chat-rrn: #169c5e;                 /* RRN logo green */
    --rrp-chat-on: #ffffff;                  /* message ink on either fill */
    --rrp-chat-on-soft: rgba(255, 255, 255, 0.8);   /* timestamps on the fills */
    --rrp-chat-edge: transparent;

    /* Surfaces — the warm canvas identity */
    --rrp-canvas: #f6f3ee;
    --rrp-paper: #ffffff;
    --rrp-canvas-sunk: #f1ede4;      /* recessed wells; warm, not blue-grey */
    --rrp-surface-muted: var(--rrp-canvas-sunk);
    --rrp-line: #e8e4d8;             /* decorative hairline */
    --rrp-line-strong: #d6d1c4;      /* dividers, card edges */
    --rrp-control-line: #8a8470;     /* 3.74:1 — input/checkbox boundaries */
    --rrp-control-on: var(--rrp-navy);   /* checked/selected fill */
    --rrp-control-on-ink: #ffffff;       /* the tick inside that fill */
    --rrp-border: var(--rrp-line-strong);

    /* Text */
    --rrp-ink: #13243b;              /* 15.63:1 on paper */
    --rrp-muted: #5f6c76;            /* 5.39:1 paper · 4.87:1 canvas */
    --rrp-faded: #6f6a58;            /* 5.41:1 paper · 4.89:1 canvas — TEXT */
    --rrp-faded-icon: #8d8672;       /* 3.63:1 — decorative marks only */

    /* Semantic — danger */
    --rrp-danger: #a83242;           /* 6.56:1 on paper */
    --rrp-danger-deep: #8c2334;
    --rrp-danger-soft: #fbeff1;

    /* Semantic — caution */
    --rrp-mustard: #e8b81c;          /* BRAND fill — never text on light */
    --rrp-mustard-soft: #fff8df;
    --rrp-amber: #8a6d1f;            /* 4.90:1 paper · 4.42:1 canvas — TEXT */
    --rrp-amber-soft: #fff8df;
    --rrp-amber-line: #e8dcae;
    --rrp-orange: #a8541e;           /* 5.06:1 — unassigned/attention edges */

    /* Focus — two layers so one rule reads on canvas, paper and navy */
    --rrp-focus: var(--rrp-navy);    /* 13.94:1 canvas · 15.63:1 paper */
    --rrp-focus-halo: rgba(255, 255, 255, 0.95);

    /* UK number plate */
    --rrp-plate-face: #f7d117;
    --rrp-plate-ink: #1a1a1a;
    --rrp-plate-strip: #003399;

    /* Geometry */
    --rrp-radius-card: 13px;
    --rrp-radius-control: 9px;

    /* Elevation */
    --rrp-shadow-card: 0 1px 2px rgba(12, 36, 72, 0.05);
    --rrp-shadow-soft: 0 8px 24px rgba(12, 36, 72, 0.06);
    --rrp-shadow-raised: 0 10px 28px rgba(12, 36, 72, 0.07);
    --rrp-shadow-pop: 0 18px 38px rgba(12, 36, 72, 0.18);

    /* Type — replaces 24 literal sizes. 11px is the floor, metadata only. */
    --rrp-font-body: "Raleway", "Red Hat Display", system-ui, "Segoe UI", sans-serif;
    --rrp-font-heading: "Red Hat Display", "Raleway", system-ui, sans-serif;
    --rrp-text-3xs: 11px;
    --rrp-text-xs: 11.5px;
    --rrp-text-sm: 13px;
    --rrp-text-base: 14px;
    --rrp-text-md: 16px;
    --rrp-text-lg: 20px;
    --rrp-text-h1: clamp(24px, 4vw, 32px);

    /* Space — the documented 4/7/10/14/18/27 rhythm */
    --rrp-space-1: 4px;
    --rrp-space-2: 7px;
    --rrp-space-3: 10px;
    --rrp-space-4: 14px;
    --rrp-space-5: 18px;
    --rrp-space-6: 27px;
    --rrp-gutter: clamp(14px, 4vw, 27px);

    /* Shell metrics — the flow bar sits directly on top of the dock, so both
       read the same token rather than repeating a literal that can drift. */
    --rrp-dock-height: 63px;

    /* Stacking — named tiers for the values already in use, so the layering
       order is stated once instead of being rediscovered from 28 scattered
       literals. Values are deliberately unchanged: naming them must not
       reshuffle anything. Anything below --rrp-z-menu is local to a component
       and stays a bare 1/2/3. */
    --rrp-z-menu: 20;       /* dropdowns anchored to their trigger */
    --rrp-z-sticky: 30;     /* in-page sticky headers (job bar, day head) */
    --rrp-z-overlay: 45;    /* flow bar, impersonation banner */
    --rrp-z-topbar: 50;
    --rrp-z-dock: 60;       /* also the scrim tier for full-height panels */
    --rrp-z-panel: 61;      /* a panel that must cover the dock */
    --rrp-z-rail: 70;       /* desktop navy rail */
    --rrp-z-sheet: 80;      /* search results, bottom sheets */
    --rrp-z-modal: 1000;    /* matches .modal-backdrop in RapidDispatch.UI */
    --rrp-z-skip: 7000;
    --rrp-z-error: 9000;

    /* Motion — neutralised by the reduced-motion block further down */
    --rrp-motion-fast: 140ms;
    --rrp-motion-base: 190ms;
    --rrp-ease: cubic-bezier(0.22, 0.61, 0.36, 1);

    font-family: var(--rrp-font-body);
}

/* ── Tokens: dark theme ──────────────────────────────────────────────────────
   Navy-based, sharing the RapidDispatch.UI dark surfaces so the suite reads as
   one product. Only colour is re-pointed; geometry, type and space are shared
   with the light theme above. Verified on all three dark surfaces.

   Note navy inverts role here: on light it is structural chrome, on dark it
   becomes the paper surface, so the green accent carries brand identity alone.
   ─────────────────────────────────────────────────────────────────────────── */
[data-theme="dark"] .rrp-shell,
[data-theme="dark"] .rrp-app,
[data-theme="dark"] .rrp-auth,
[data-theme="dark"] .rrp-system-shell,
[data-theme="dark"] .rrp-bootstrap,
[data-theme="dark"] .rrp-toast-region,
[data-theme="dark"] #blazor-error-ui,
[data-theme="dark"] #rrp-update-ui {
    color-scheme: dark;

    /* Navy is NOT remapped. It is the brand chrome colour — the rail, the
       mobile topbar, primary button fills — and those should stay navy in both
       themes; it is also what keeps the portal recognisable next to the rest of
       the suite. Text that happens to be navy on a light surface uses
       --rrp-ink instead, which does flip. Remapping navy here would have made
       136 navy-on-navy text declarations invisible. */
    --rrp-green: #1cc478;            /* 8.42:1 on canvas — safe as a fill */
    --rrp-green-dark: #3ddc93;       /* 10.83:1 — green text on dark */
    --rrp-green-deep: var(--rrp-green-dark);
    --rrp-green-line: #2f6b50;
    --rrp-green-wash: #0f2b20;

    /* The navy repairer bubble sits on a near-navy dark surface, so give it a
       hairline edge to keep its shape; the green bubble separates on its own. */
    --rrp-chat-edge: rgba(255, 255, 255, 0.16);

    --rrp-canvas: #070f1d;
    --rrp-paper: #0c1628;
    --rrp-canvas-sunk: #050b16;
    --rrp-surface-muted: var(--rrp-canvas-sunk);
    --rrp-line: #1a2d55;
    --rrp-line-strong: #2b3f66;
    --rrp-control-line: #54709e;     /* 3.61:1 on paper — control boundaries */
    /* Navy is the paper surface here, so a navy "checked" fill would be
       invisible. The accent takes over, with dark ink for the tick. */
    --rrp-control-on: var(--rrp-green);
    --rrp-control-on-ink: #04121c;
    --rrp-border: var(--rrp-line-strong);

    --rrp-ink: #e8eef6;              /* 15.50:1 on paper */
    --rrp-muted: #9fb3cc;            /* 8.44:1 on paper */
    --rrp-faded: #8098b4;            /* 6.09:1 on paper — TEXT */
    --rrp-faded-icon: #6b819c;       /* 4.52:1 — decorative marks */

    --rrp-danger: #ff8a95;           /* 8.03:1 on paper */
    --rrp-danger-deep: #ffb3ba;
    --rrp-danger-soft: #2c1218;
    --rrp-mustard: #e8b81c;
    --rrp-mustard-soft: #2b2208;
    --rrp-amber: #e8b81c;            /* 9.74:1 on dark — safe as text here */
    --rrp-amber-soft: #2b2208;
    --rrp-amber-line: #5c4a12;
    --rrp-orange: #ff9f6b;

    /* Mustard reads at 9.74:1 on dark, so it returns as the ring; the halo
       inverts to a dark band so the ring separates from pale surfaces too. */
    --rrp-focus: var(--rrp-mustard);
    --rrp-focus-halo: rgba(4, 9, 18, 0.92);

    /* Shadows do little on dark, so elevation leans on surface steps instead */
    --rrp-shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4);
    --rrp-shadow-soft: 0 8px 24px rgba(0, 0, 0, 0.45);
    --rrp-shadow-raised: 0 10px 28px rgba(0, 0, 0, 0.5);
    --rrp-shadow-pop: 0 18px 38px rgba(0, 0, 0, 0.62);
}

/* Re-point the shared RapidDispatch.UI tokens at the warm palette so shared
   components (CrmDocumentGallery, RrnList, toasts…) sit on the canvas.

   This must cover the auth and system shells too, not just .rrp-app. The shared
   .rrn-theme block hardcodes a light palette with no dark counterpart, and
   because it sits closer to the element than :root[data-theme] it wins on
   custom-property inheritance. Scoping these aliases to .rrp-app alone left the
   login inputs painting #ffffff on the dark theme. */
.rrp-app,
.rrp-auth,
.rrp-system-shell {
    --navy: var(--rrp-navy);
    --navy-mid: var(--rrp-navy-soft);
    --green: var(--rrp-green);
    --green-dim: var(--rrp-green-dark);
    --green-soft: var(--rrp-green-wash);
    --mustard: var(--rrp-mustard);
    --mustard-soft: var(--rrp-mustard-soft);
    --red: var(--rrp-danger);
    --red-soft: var(--rrp-danger-soft);
    --red-dim: var(--rrp-danger-soft);
    --danger: var(--rrp-danger);
    --success: var(--rrp-green);
    --warning: var(--rrp-mustard);
    --amber: var(--rrp-amber);
    --green-tint: var(--rrp-green-wash);
    --green-tint-2: var(--rrp-green-wash);
    --green-dark: var(--rrp-green-dark);
    /* --bg is the page behind shared panels; several shared inputs read it
       directly, so it has to be the canvas rather than the shared default. */
    --bg: var(--rrp-canvas);
    --surface: var(--rrp-paper);
    --surface2: var(--rrp-canvas);
    --surface3: var(--rrp-canvas);
    --panel-2: var(--rrp-canvas);
    --line: var(--rrp-line);
    --border: var(--rrp-line-strong);
    /* border2 is the shared *control* border, so it takes the AA-passing token
       rather than the decorative hairline. */
    --border2: var(--rrp-control-line);
    --text: var(--rrp-ink);
    /* Ink, not navy: navy is a fixed brand colour, so pointing "bright" text at
       it would leave shared components with dark text on the dark theme. */
    --text-bright: var(--rrp-ink);
    --text-mid: var(--rrp-muted);
    --text-dim: var(--rrp-muted);
    --muted: var(--rrp-muted);
    --accent: var(--rrp-green);
    --sans: var(--rrp-font-body);
    --shadow-sm: var(--rrp-shadow-card);
    --shadow: var(--rrp-shadow-soft);
    --r: var(--rrp-radius-card);
    --r-sm: var(--rrp-radius-control);
    /* The shared stylesheet enforces one !important focus ring for every app and
       reads its colour from these two tokens, so pointing them at Repairer's
       values is what keeps the navy ring instead of the shared mustard. Re-point
       them on a container to change the ring for everything inside it. */
    --focus-ring: var(--rrp-focus);
    --focus-halo: var(--rrp-focus-halo);
}

.rrp-app *,
.rrp-app *::before,
.rrp-app *::after,
.rrp-auth *,
.rrp-auth *::before,
.rrp-auth *::after,
.rrp-system-shell *,
.rrp-system-shell *::before,
.rrp-system-shell *::after,
.rrp-bootstrap *,
.rrp-bootstrap *::before,
.rrp-bootstrap *::after {
    box-sizing: border-box;
}

.rrp-app :where(button, input, select, textarea),
.rrp-auth :where(button, input, select, textarea) {
    font: inherit;
}

.rrp-app :where(button) {
    cursor: pointer;
}

.rrp-app :where(h1, h2, h3),
.rrp-auth :where(h1, h2, h3),
.rrp-system-shell :where(h1, h2, h3) {
    font-family: var(--rrp-font-heading);
}

.rrp-app :where(img, svg) {
    max-width: 100%;
}

/* ── Focus ────────────────────────────────────────────────────────────────────
   Two layers, so a single rule stays visible on every surface the portal has.
   The ring itself is navy (13.94:1 on canvas); the halo is a white band that
   guarantees separation when the ring sits on a dark surface. Mustard was used
   here previously and measured 1.68:1 on the canvas — effectively invisible.

   The outline is not set here. The shared stylesheet draws one ring for all six
   apps and marks it !important, precisely so no component can drop it, and it
   takes its colour from --focus-ring. Repairer therefore contributes the halo and
   re-points --focus-ring/--focus-halo; setting outline-color on a component would
   lose to the shared shorthand. */
.rrp-app :where(a, button, input, select, textarea, summary):focus-visible,
.rrp-auth :where(a, button, input, select, textarea):focus-visible,
.rrp-system-shell :where(a, button):focus-visible,
#blazor-error-ui :where(a, button):focus-visible,
#rrp-update-ui :where(a, button):focus-visible {
    box-shadow: 0 0 0 6px var(--focus-halo);
}

/* Navy chrome inverts: mustard clears 8.3:1 against the rail and topbar, where
   a navy ring would disappear. The halo darkens to hold the same separation.
   Re-pointed on the container, not the focused control, because --focus-ring is
   substituted where it is used — reassigning --rrp-focus deeper would have no
   effect on the already-computed --focus-ring inherited from .rrp-app. */
.rrp-sidebar,
.rrp-topbar,
.rrp-jobbar {
    --focus-ring: var(--rrp-mustard);
    --focus-halo: rgba(12, 36, 72, 0.9);
}

/* On dark the shell chrome and the canvas are the same family, so the inversion
   above would double up on an already-mustard ring. Reset the halo. */
[data-theme="dark"] :is(.rrp-sidebar, .rrp-topbar, .rrp-jobbar) {
    --focus-halo: var(--rrp-focus-halo);
}

.rrp-visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

.rrp-brand-logo {
    display: block;
    width: auto;
    max-width: 100%;
    height: auto;
}

/* ── Component: Wordmark — RapidRepairer product logotype ──────────────────── */
.rrp-product {
    display: inline-flex;
    align-items: baseline;
    gap: 0;
    color: #fff;
    font-family: var(--rrp-font-heading);
    font-size: 19px;
    font-weight: 800;
    letter-spacing: -0.035em;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
}

.rrp-product b {
    color: var(--rrp-green);
    font-weight: 800;
}

.rrp-product--ink {
    color: var(--rrp-ink);
}

/* ── Component: AppShell (navy rail + workspace) ───────────────────────────── */
.rrp-shell {
    position: fixed;
    inset: 0;
    min-width: 0;
    overflow: hidden;
    background: var(--rrp-canvas);
}

.rrp-app {
    position: relative;
    display: flex;
    width: 100%;
    min-width: 0;
    height: 100vh;
    height: 100dvh;
    flex-direction: column;
    overflow: hidden;
    background: var(--rrp-canvas);
    color: var(--rrp-ink);
    font-size: 14px;
    font-weight: 500;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

.rrp-skip-link {
    position: fixed;
    z-index: var(--rrp-z-skip);
    top: max(8px, env(safe-area-inset-top));
    left: max(8px, env(safe-area-inset-left));
    min-height: 44px;
    padding: 11px 16px;
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-mustard);
    color: var(--rrp-navy);
    font-weight: 800;
    text-decoration: none;
    transform: translateY(calc(-100% - 24px));
    transition: transform 120ms ease-out;
}

.rrp-skip-link:focus {
    transform: translateY(0);
}

.rrp-sidebar {
    display: none;
}

.rrp-workspace {
    display: flex;
    min-width: 0;
    min-height: 0;
    flex: 1 1 auto;
    flex-direction: column;
}

.rrp-topbar {
    position: relative;
    /* Above the impersonation banner so the user-menu dropdown is never clipped. */
    z-index: var(--rrp-z-topbar);
    display: flex;
    min-width: 0;
    min-height: 58px;
    flex: 0 0 auto;
    align-items: center;
    gap: 14px;
    padding: 8px max(13px, env(safe-area-inset-right)) 8px max(13px, env(safe-area-inset-left));
    padding-top: max(8px, env(safe-area-inset-top));
    background: var(--rrp-navy);
}

.rrp-topbar__brand {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    border-radius: 7px;
}

.rrp-topbar__spacer {
    flex: 1 1 auto;
}

/* ── Component: UserMenu — topbar account control with dropdown ────────────── */
.rrp-user {
    position: relative;
    flex: 0 0 auto;
    order: 3;
}

.rrp-user > summary {
    display: flex;
    min-height: 44px;
    align-items: center;
    gap: 10px;
    padding: 3px;
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
    list-style: none;
}

.rrp-user > summary::-webkit-details-marker {
    display: none;
}

.rrp-user__avatar {
    display: grid;
    width: 38px;
    height: 38px;
    flex: 0 0 auto;
    place-items: center;
    border: 1px solid rgba(255, 255, 255, 0.32);
    border-radius: 50%;
    font-size: 11px;
    font-weight: 800;
}

/* Phones show the avatar only; the dropdown carries the identity. */
.rrp-user__name {
    display: none;
    min-width: 0;
    text-align: left;
}

.rrp-user__name strong {
    display: block;
    font-size: 12px;
    font-weight: 800;
    line-height: 1.25;
}

.rrp-user__name small {
    display: block;
    font-size: var(--rrp-text-3xs);
    font-weight: 700;
    line-height: 1.3;
    opacity: 0.75;
}

.rrp-user > summary > svg {
    display: none;
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
    stroke-width: 2.4;
}

.rrp-user[open] > summary > svg {
    transform: rotate(180deg);
}

.rrp-user__menu {
    width: 250px;
}

/* Invisible full-bleed layer that gives the dropdown outside-click dismissal.
   <details> only toggles from its own summary, so without this the menu can
   only be closed by returning to the avatar.

   It must sit just BELOW the menu, not above it. .rrp-user is position:relative
   with no z-index, so it opens no stacking context of its own — the menu
   (--rrp-z-menu) and this scrim therefore compare directly inside the topbar's
   context. Tying the scrim to the topbar tier (which is higher) put it over the
   menu, so every click on an option hit the scrim and closed it. One below the
   menu keeps the menu clickable while the scrim still covers the page beneath
   (it is a child of the z-topbar context, so it floats above ordinary content
   regardless of this local value). Inert to assistive tech. */
.rrp-menu-scrim {
    position: fixed;
    z-index: calc(var(--rrp-z-menu) - 1);
    inset: 0;
    background: transparent;
}

/* Appearance choice. A three-way control rather than a two-state switch, so
   "follow the system" stays reachable after an explicit choice is made. */
.rrp-appearance {
    display: grid;
    gap: var(--rrp-space-2);
    padding: var(--rrp-space-3) 12px;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
}

.rrp-appearance__label {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.rrp-appearance__group {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--rrp-space-1);
    padding: 3px;
    border: 1px solid var(--rrp-control-line);
    border-radius: 999px;
    background: var(--rrp-paper);
}

.rrp-appearance__btn {
    min-height: 34px;
    padding: 0 var(--rrp-space-1);
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-xs);
    font-weight: 750;
    cursor: pointer;
    transition: background var(--rrp-motion-fast) var(--rrp-ease),
                color var(--rrp-motion-fast) var(--rrp-ease);
}

.rrp-appearance__btn:hover {
    color: var(--rrp-ink);
}

/* The selected state carries a fill as well as a colour change, so it survives
   greyscale and does not depend on hue alone. */
.rrp-appearance__btn.is-active {
    background: var(--rrp-navy);
    color: var(--rrp-paper);
}

[data-theme="dark"] .rrp-appearance__btn.is-active {
    background: var(--rrp-green-dark);
    color: #04121c;
}

.rrp-user__head {
    display: grid;
    gap: 2px;
    padding: 11px 12px;
    border-bottom: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
}

.rrp-user__head strong {
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
}

.rrp-user__head small {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 650;
    overflow-wrap: anywhere;
}

/* ── Component: GlobalSearch — the topbar job finder. Phones show a search
      icon that expands the input across the topbar; desktop keeps the input
      always on (press / to focus) with a type-ahead results dropdown. ──────── */
.rrp-gsearch {
    position: relative;
    display: flex;
    min-width: 0;
    flex: 0 1 auto;
    align-items: center;
    /* Phones park the search icon on the right beside the avatar. */
    order: 2;
}

.rrp-gsearch.is-open {
    flex: 1 1 auto;
}

/* The expanded phone search needs the row; the wordmark steps aside. */
.rrp-topbar:has(.rrp-gsearch.is-open) .rrp-topbar__brand,
.rrp-topbar:has(.rrp-gsearch.is-open) .rrp-bell,
.rrp-topbar:has(.rrp-gsearch.is-open) .rrp-topbar__spacer {
    display: none;
}

.rrp-gsearch__toggle {
    display: grid;
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #fff;
    cursor: pointer;
}

.rrp-gsearch__toggle svg {
    width: 20px;
    height: 20px;
    stroke-width: 2.2;
}

.rrp-gsearch__box {
    position: relative;
    display: none;
    min-width: 0;
    flex: 1 1 auto;
    align-items: center;
    border: 1px solid var(--rrp-control-line);
    border-radius: 10px;
    background: var(--rrp-paper);
}

.rrp-gsearch.is-open .rrp-gsearch__box {
    display: flex;
}

.rrp-gsearch__box > svg {
    position: absolute;
    left: 12px;
    width: 17px;
    height: 17px;
    color: var(--rrp-muted);
    stroke-width: 2.2;
    pointer-events: none;
}

.rrp-gsearch__box input {
    min-width: 0;
    min-height: 44px;
    flex: 1 1 auto;
    padding: 10px 12px 10px 38px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--rrp-ink);
    font-size: 16px;
}

.rrp-gsearch__box input::placeholder {
    color: var(--rrp-faded);
    font-weight: 550;
}

/* --focus-ring, not --rrp-focus: the box sits on the navy topbar, where the
   container override above swaps the navy ring for mustard. Offset 0 because the
   topbar has no room to spare for a detached ring. */
.rrp-gsearch__box:focus-within {
    border-color: var(--focus-ring);
    outline: 3px solid var(--focus-ring);
    outline-offset: 0;
}

.rrp-gsearch__box input:focus {
    outline: none;
}

/* The keyboard hint only earns its space beside a pointer + keyboard. */
.rrp-gsearch__box kbd {
    display: none;
    flex: 0 0 auto;
    margin-right: 10px;
    padding: 2px 7px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 5px;
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-family: inherit;
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
}

.rrp-gsearch__panel {
    position: absolute;
    z-index: var(--rrp-z-sheet);
    top: calc(100% + 7px);
    right: 0;
    left: 0;
    overflow: hidden auto;
    max-height: min(430px, 62vh);
    border: 1px solid var(--rrp-line-strong);
    border-radius: 12px;
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-raised);
}

.rrp-gsearch__note {
    margin: 0;
    padding: 14px;
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 650;
}

.rrp-gsearch__result {
    display: grid;
    width: 100%;
    min-width: 0;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 11px;
    padding: 10px 13px;
    border: 0;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    text-align: left;
    cursor: pointer;
    box-shadow: 0 -1px 0 var(--rrp-line);
}

.rrp-gsearch__result:first-child {
    box-shadow: none;
}

.rrp-gsearch__result.is-active {
    background: var(--rrp-canvas);
}

.rrp-gsearch__result-main {
    min-width: 0;
}

.rrp-gsearch__result-main strong {
    display: block;
    overflow: hidden;
    font-size: 12.5px;
    font-weight: 800;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-gsearch__result-main small {
    display: block;
    overflow: hidden;
    margin-top: 3px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 650;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-gsearch__all {
    display: block;
    width: 100%;
    min-height: 44px;
    padding: 11px 13px;
    border: 0;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
    color: var(--rrp-green-dark);
    font-size: 11.5px;
    font-weight: 800;
    text-align: left;
    cursor: pointer;
}

/* Pull-to-refresh: the chip that rides the pull gesture at the top of the
   scroll viewport. JS drives --rrp-ptr-pull and the state classes. */
.rrp-app .rrp-ptr {
    position: absolute;
    z-index: var(--rrp-z-overlay);
    top: -44px;
    left: 50%;
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 50%;
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-soft);
    opacity: 0;
    pointer-events: none;
    /* JS drives this while the finger pulls; declared here so it always exists. */
    --rrp-ptr-pull: 0px;
    transform: translate(-50%, var(--rrp-ptr-pull));
    transition: transform 0.2s ease, opacity 0.2s ease;
}

.rrp-app .rrp-ptr.is-pulling {
    opacity: 1;
}

/* The finger owns the position while dragging; a transition would lag it. */
.rrp-app .rrp-ptr.is-dragging {
    transition: opacity 0.2s ease;
}

.rrp-app .rrp-ptr__spinner {
    width: 18px;
    height: 18px;
    border: 2px solid var(--rrp-line);
    border-top-color: var(--rrp-ink);
    border-radius: 50%;
    transform: rotate(45deg);
    transition: transform 0.15s ease;
}

/* Past the threshold: the arc snaps round as the "let go now" cue. */
.rrp-app .rrp-ptr.is-armed .rrp-ptr__spinner {
    transform: rotate(225deg);
}

.rrp-app .rrp-ptr.is-refreshing .rrp-ptr__spinner {
    animation: rrp-ptr-spin 0.7s linear infinite;
}

@keyframes rrp-ptr-spin {
    to {
        transform: rotate(360deg);
    }
}

/* Offline mode: the shell-level strip saying the connection is gone, and the
   page-level "saved copy" notice above read-only content. */
.rrp-offline-banner {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 8px;
    padding: 7px max(14px, env(safe-area-inset-right)) 7px max(14px, env(safe-area-inset-left));
    border-bottom: 1px solid var(--rrp-amber-line);
    background: var(--rrp-amber-soft);
    color: var(--rrp-amber);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.35;
}

.rrp-offline-banner svg {
    flex: 0 0 auto;
}

.rrp-app .rrp-offline-note {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 8px;
    padding: 10px 14px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: var(--rrp-text-sm);
    line-height: 1.4;
}

.rrp-app .rrp-offline-note span {
    color: var(--rrp-muted);
}

.rrp-impersonation {
    position: relative;
    z-index: var(--rrp-z-overlay);
    display: flex;
    min-width: 0;
    flex: 0 0 auto;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 7px max(14px, env(safe-area-inset-right)) 7px max(14px, env(safe-area-inset-left));
    background: var(--rrp-mustard);
    color: #382d00;
    font-size: 12px;
    line-height: 1.35;
}

.rrp-impersonation__text {
    flex: 1 1 auto;
    min-width: 0;
}

.rrp-impersonation__exit {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 7px 12px;
    border: 1px solid rgba(56, 45, 0, 0.35);
    border-radius: var(--rrp-radius-control);
    background: rgba(255, 255, 255, 0.34);
    color: #382d00;
    font-weight: 800;
}

/* ── Component: EnvironmentBanner — non-production environment notice ───────── */
/* The portal is exempt from RrnAppShell, so it cannot use the suite's shared
   EnvironmentBanner. This is its rrp- equivalent: a slim, dismissible bar at the
   top of the workspace that names the environment (Local / Development /
   Staging) so a test build is never mistaken for the live site. Never rendered
   on Production. Ink-on-tint text and stable navy/paper pill inks keep every
   variant AA in both themes. */
.rrp-envbar {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 6px max(14px, env(safe-area-inset-right)) 6px max(14px, env(safe-area-inset-left));
    border-bottom: 1px solid var(--rrp-line-strong);
    background: var(--rrp-canvas-sunk);
    color: var(--rrp-ink);
    font-size: var(--rrp-text-xs);
    line-height: 1.35;
}

.rrp-envbar__pill {
    flex: 0 0 auto;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--rrp-ink);
    color: var(--rrp-paper);
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.rrp-envbar__text {
    min-width: 0;
    font-weight: 600;
}

.rrp-envbar__spacer {
    flex: 1 1 auto;
}

.rrp-envbar__dismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: var(--rrp-radius-control);
    background: transparent;
    color: var(--rrp-muted);
    cursor: pointer;
}

.rrp-envbar__dismiss:hover {
    background: color-mix(in srgb, var(--rrp-ink) 8%, transparent);
    color: var(--rrp-ink);
}

/* Local — your own machine: the calm, safe end of the scale. */
.rrp-envbar--local {
    background: var(--rrp-green-wash);
    border-bottom-color: var(--rrp-green-line);
}

.rrp-envbar--local .rrp-envbar__pill {
    background: var(--rrp-green);
    color: var(--rrp-navy);
}

/* Development — the shared dev build: caution. */
.rrp-envbar--development {
    background: var(--rrp-amber-soft);
    border-bottom-color: var(--rrp-amber-line);
}

.rrp-envbar--development .rrp-envbar__pill {
    background: var(--rrp-mustard);
    color: var(--rrp-navy);
}

/* Staging — nearest to live: the strongest heads-up. */
.rrp-envbar--staging {
    background: color-mix(in srgb, var(--rrp-orange) 14%, var(--rrp-paper));
    border-bottom-color: color-mix(in srgb, var(--rrp-orange) 45%, var(--rrp-line));
}

.rrp-envbar--staging .rrp-envbar__pill {
    background: var(--rrp-orange);
    color: var(--rrp-paper);
}

.rrp-viewport {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    scrollbar-color: #c2bca9 transparent;
    scrollbar-width: thin;
    background: var(--rrp-canvas);
    scroll-behavior: smooth;
}

.rrp-viewport:focus {
    outline: none;
}

.rrp-scroll {
    display: flex;
    width: 100%;
    min-height: 100%;
    flex-direction: column;
}

/* The gutter grows with the viewport rather than sitting at 14px until the
   desktop breakpoint takes over. 3.2vw matches the rule at 761px, so the two
   meet at the same value and the gutter never jumps at the breakpoint; the 14px
   floor keeps phones exactly as they were, where the content needs the width
   more than the margin does. */
.rrp-page {
    width: 100%;
    min-width: 0;
    flex: 1 0 auto;
    margin-inline: auto;
    padding: 19px clamp(14px, 3.2vw, 24px) 28px;
}

/* ── Component: JobBar (sticky job identity strip) ─────────────────────────
   Replaces the back row, hero and next-action header on the job page. The
   work starts immediately under it, so this is the only chrome above the
   task. It sticks so the plate and status stay readable while working. */
.rrp-jobbar {
    position: sticky;
    top: 0;
    z-index: var(--rrp-z-sticky);
    margin: -19px -14px 15px;
    background: var(--rrp-navy);
    color: #fff;
}

.rrp-jobbar__row {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
}

.rrp-jobbar__back {
    display: inline-flex;
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, 0.24);
    border-radius: var(--rrp-radius-control);
    color: #fff;
    text-decoration: none;
}

.rrp-jobbar__back svg {
    width: 17px;
    height: 17px;
    stroke-width: 2.2;
}

.rrp-jobbar__id {
    display: grid;
    min-width: 0;
    flex: 1;
    margin: 0;
    gap: 1px;
}

.rrp-jobbar__ref {
    overflow: hidden;
    color: rgba(255, 255, 255, 0.68);
    font-size: var(--rrp-text-3xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
}

.rrp-jobbar__title {
    overflow: hidden;
    color: #fff;
    font-family: var(--rrp-font-heading);
    font-size: 14px;
    font-weight: 750;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-jobbar__more {
    position: relative;
    flex: 0 0 auto;
}

.rrp-jobbar__assign {
    position: relative;
    flex: 0 0 auto;
}

.rrp-jobbar__assign > summary {
    display: inline-flex;
    max-width: 180px;
    min-height: 34px;
    align-items: center;
    padding: 0 10px;
    border: 1px solid rgba(255, 255, 255, 0.24);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    cursor: pointer;
    font-size: 12px;
    font-weight: 750;
    list-style: none;
}

.rrp-jobbar__assign > summary::-webkit-details-marker {
    display: none;
}

.rrp-jobbar__assign > summary span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-jobbar__assign-menu {
    z-index: var(--rrp-z-menu);
    width: min(320px, calc(100vw - 24px));
    padding: 12px;
}

.rrp-jobbar__assign-menu .rrp-assignment-control {
    grid-template-columns: minmax(0, 1fr);
}

.rrp-jobbar__assign-menu .btn {
    width: 100%;
}

.rrp-jobbar__more > summary {
    display: inline-flex;
    width: 34px;
    height: 34px;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, 0.24);
    border-radius: var(--rrp-radius-control);
    background: transparent;
    color: #fff;
    cursor: pointer;
    list-style: none;
}

.rrp-jobbar__more > summary::-webkit-details-marker {
    display: none;
}

.rrp-jobbar__more > summary svg {
    width: 18px;
    height: 18px;
    stroke-width: 2.4;
}

/* The chat control: opens the "Chat with RRN" conversation in one tap, so the
   single most-used way to talk to RRN sits on the bar rather than behind the
   kebab. Sized to match the back button and kebab beside it, and carries a
   small unread-count badge when RRN has sent messages not yet read. */
.rrp-jobbar__chat {
    position: relative;
    display: inline-flex;
    width: 34px;
    height: 34px;
    /* This control is a <button>, so the shared UI layer's coarse-pointer
       min-height/min-width: var(--tap-min) (44px on touch) would otherwise
       inflate it past the back link and kebab beside it — both non-buttons
       that stay 34px. Pin our own minimums so all three match on every
       pointer; 34px still clears the WCAG 2.2 SC 2.5.8 24px floor. */
    min-width: 34px;
    min-height: 34px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, 0.24);
    border-radius: var(--rrp-radius-control);
    background: transparent;
    color: #fff;
    cursor: pointer;
}

.rrp-jobbar__chat svg {
    width: 18px;
    height: 18px;
    stroke-width: 2.2;
}

/* Green count cut-out against the navy job bar — the portal's established
   unread treatment (matching the notification bell), never the danger red the
   design system reserves for genuinely late work. */
.rrp-jobbar__chat-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    display: grid;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    place-items: center;
    border: 2px solid var(--rrp-navy);
    border-radius: 999px;
    background: var(--rrp-green);
    color: #fff;
    font-size: var(--rrp-text-3xs);
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    line-height: 1;
}

/* ── Component: DetailSheet (reference material, one tap away) ─────────────
   Phone: a row that opens a bottom sheet over the work. Desktop (>=900px):
   the row vanishes and the panel sits open in the job page's side column. */
.rrp-detail + .rrp-detail {
    margin-top: 9px;
}

.rrp-detail__row {
    display: flex;
    width: 100%;
    min-height: 56px;
    align-items: center;
    gap: 12px;
    padding: 11px 14px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.rrp-detail__row-copy {
    display: grid;
    min-width: 0;
    flex: 1;
    gap: 2px;
}

.rrp-detail__row-copy strong {
    font-size: 13.5px;
    font-weight: 750;
}

.rrp-detail__row-copy small {
    overflow: hidden;
    color: var(--rrp-muted);
    font-size: 11.5px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-detail__chev {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    color: var(--rrp-muted);
    stroke-width: 2.2;
}

.rrp-detail__scrim {
    position: fixed;
    z-index: var(--rrp-z-dock);
    inset: 0;
    background: rgba(12, 36, 72, 0.42);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s ease;
}

.rrp-detail.is-open .rrp-detail__scrim {
    opacity: 1;
    pointer-events: auto;
}

.rrp-detail__panel {
    position: fixed;
    z-index: var(--rrp-z-panel);
    right: 0;
    bottom: 0;
    left: 0;
    max-height: 84vh;
    overflow-y: auto;
    border-radius: 18px 18px 0 0;
    background: var(--rrp-canvas);
    box-shadow: 0 -12px 34px rgba(12, 36, 72, 0.24);
    transform: translateY(102%);
    transition: transform 0.26s cubic-bezier(0.32, 0.72, 0.32, 1);
    visibility: hidden;
}

.rrp-detail.is-open .rrp-detail__panel {
    transform: translateY(0);
    visibility: visible;
}

@media (prefers-reduced-motion: reduce) {
    .rrp-detail__panel,
    .rrp-detail__scrim {
        transition: none;
    }
}

.rrp-detail__head {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 15px 16px 11px;
    border-bottom: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
}

.rrp-detail__head h2 {
    flex: 1;
    margin: 0;
    font-family: var(--rrp-font-heading);
    font-size: 16px;
    font-weight: 750;
}

.rrp-detail__done {
    border: 0;
    background: transparent;
    color: var(--rrp-ink);
    font: inherit;
    font-size: 13px;
    font-weight: 750;
    cursor: pointer;
}

.rrp-detail__body {
    /* A sheet is a phone-width bottom sheet or one of three desktop panels, so
       its contents size against the sheet rather than the viewport. */
    container: rrp-sheet / inline-size;
    display: grid;
    gap: 12px;
    padding: 14px 16px calc(20px + env(safe-area-inset-bottom, 0px));
}

@media (min-width: 900px) {
    /* The side column has room, so the reference is simply present. */
    .rrp-detail__row,
    .rrp-detail__scrim,
    .rrp-detail__done {
        display: none;
    }

    .rrp-detail + .rrp-detail {
        margin-top: 12px;
    }

    .rrp-detail__panel {
        position: static;
        max-height: none;
        overflow: visible;
        border: 1px solid var(--rrp-line);
        border-radius: var(--rrp-radius-card);
        background: var(--rrp-paper);
        box-shadow: none;
        transform: none;
        visibility: visible;
    }

    .rrp-detail__head {
        position: static;
        padding: 13px 15px 10px;
        background: transparent;
    }

    .rrp-detail__head h2 {
        font-size: 14px;
    }

    .rrp-detail__body {
        padding: 12px 15px 15px;
    }
}

/* ── Layout: job page (work first, reference behind it at every width) ─────── */
.rrp-job {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 15px;
    align-items: start;
}

.rrp-job__work {
    min-width: 0;
    /* Leave room for the sticky job bar above and the pinned flow bar below
       when anything in here is scrolled into view. */
    scroll-margin-top: 60px;
    scroll-margin-bottom: var(--rrp-flow-bar-clearance, 160px);
}

@media (min-width: 900px) {
    /* Everything runs the full content width. A side column was tried and
       pulled: squeezing the work into ~60% of the page left invoice lines
       unreadable, and the reader wanted the desk to match mobile. */
    .rrp-job {
        gap: 22px;
    }
}

/* ── Component: ChatDialog — the RRN conversation, shown in the shared large
      modal (desktop ~3/4 width; a full-width bottom sheet on phones). The
      thread reads oldest-to-newest and the composer grows a line at a time as
      the message overflows, so it becomes the input box rather than opening a
      popup within a popup. ─────────────────────────────────────────────────── */
.rrp-chat {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.rrp-chat__empty {
    margin: 0;
    padding: 18px 14px;
    border: 1px dashed var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: 12.5px;
    text-align: center;
}

/* Newest-first in the DOM + column-reverse renders oldest on top and newest at
   the bottom while pinning the initial scroll to the newest message. */
.rrp-chat__thread {
    display: flex;
    max-height: min(52vh, 460px);
    flex-direction: column-reverse;
    gap: 8px;
    overflow-y: auto;
    padding: 2px;
}

/* WhatsApp-style bubbles: each message is a rounded fill on its sender's side,
   capped at 3/5 of the thread width. The repairer's own messages sit on the
   left in RRN navy; RRN's replies sit on the right in RRN green. Both carry
   white ink. The rules keep the shared .crm-note base (padding, radius,
   structure) and out-specify .rrp-app .crm-note for the fill, edge, ink and
   alignment. */
.rrp-chat__thread .crm-note.rrp-chat__msg {
    max-width: 60%;
    border: 1px solid var(--rrp-chat-edge);
    color: var(--rrp-chat-on);
}

.rrp-chat__thread .crm-note.rrp-chat__msg--repairer {
    align-self: flex-start;
    background: var(--rrp-chat-repairer);
    border-bottom-left-radius: 3px;
}

.rrp-chat__thread .crm-note.rrp-chat__msg--rrn {
    align-self: flex-end;
    background: var(--rrp-chat-rrn);
    border-bottom-right-radius: 3px;
}

.rrp-chat__thread .rrp-chat__msg .crm-note-author,
.rrp-chat__thread .rrp-chat__msg .crm-note-body {
    color: var(--rrp-chat-on);
}

.rrp-chat__thread .rrp-chat__msg .crm-note-time {
    color: var(--rrp-chat-on-soft);
}

/* A deep-linked newest message keeps its fill — the shared green wash would
   strand the white ink — so the chat pulse is an ink-tinted ring rather than a
   background swap. Out-specifying the shared rule swaps the whole animation. */
.rrp-chat__thread .crm-note.rrp-chat__msg.crm-note--new {
    animation: rrp-chat-pulse 1.1s ease-in-out 3;
}

@keyframes rrp-chat-pulse {
    50% {
        box-shadow: 0 0 0 4px color-mix(in srgb, var(--rrp-chat-on) 45%, transparent);
    }
}

@media (prefers-reduced-motion: reduce) {
    .rrp-chat__thread .crm-note.rrp-chat__msg.crm-note--new {
        animation: none;
    }
}

.rrp-chat__composer {
    display: flex;
    align-items: flex-end;
    gap: 9px;
}

/* Autosizing input: the wrapper's ::after mirrors the typed value and sets the
   grid row height; the textarea fills that one cell, so it grows with the
   content in every browser without any script. The two must share identical
   box metrics, hence the shared declaration below. */
.rrp-chat__grow {
    display: grid;
    flex: 1 1 auto;
    min-width: 0;
}

.rrp-chat__grow::after {
    content: attr(data-replicated-value) " ";
    visibility: hidden;
}

.rrp-chat__grow > .rrp-chat__input,
.rrp-chat__grow::after {
    grid-area: 1 / 1 / 2 / 2;
    max-height: 40vh;
    padding: 10px 12px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    font: inherit;
    /* 16px keeps iOS from zooming the page when the field takes focus. */
    font-size: 16px;
    line-height: 1.4;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
    word-break: break-word;
}

.rrp-chat__input {
    min-height: var(--tap-min);
    resize: none;
    overflow-y: auto;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
}

.rrp-chat__send {
    flex: 0 0 auto;
}

.rrp-chat__hint {
    margin: 0;
}

/* ── Component: Nav (rail + mobile dock) ───────────────────────────────────── */
.rrp-nav--rail {
    display: grid;
    gap: 5px;
}

.rrp-nav--rail .rrp-nav__link,
.rrp-nav--dock .rrp-nav__link {
    display: flex;
    min-width: 0;
    min-height: 44px;
    align-items: center;
    gap: 11px;
    border: 0;
    background: transparent;
    color: rgba(255, 255, 255, 0.72);
    font-size: 12.5px;
    font-weight: 750;
    text-align: left;
    text-decoration: none;
}

.rrp-nav--rail .rrp-nav__link {
    padding: 10px 12px;
    border-radius: var(--rrp-radius-control);
}

.rrp-nav--rail .rrp-nav__link--active {
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
}

.rrp-nav--rail .rrp-nav__link--active::before {
    width: 3px;
    height: 20px;
    margin-left: -12px;
    border-radius: 0 3px 3px 0;
    background: var(--rrp-green);
    content: "";
}

.rrp-nav__link svg {
    width: 19px;
    height: 19px;
    flex: 0 0 auto;
    stroke-width: 1.9;
}

/* Docked to the viewport bottom; the shell's last in-flow child, so nothing
   can hide behind it at rest. */
.rrp-nav--dock {
    position: relative;
    z-index: var(--rrp-z-dock);
    display: grid;
    min-height: var(--rrp-dock-height);
    flex: 0 0 auto;
    grid-template-columns: repeat(auto-fit, minmax(54px, 1fr));
    padding-bottom: env(safe-area-inset-bottom, 0);
    border-top: 1px solid var(--rrp-line-strong);
    background: color-mix(in srgb, var(--rrp-paper) 98%, transparent);
}

/* The dock is the most-used control in the product, so its labels have to be
   readable at a glance and at arm's length. 9px made them decorative and forced
   navigation by icon shape alone; 4px of extra height buys real legibility. */
.rrp-nav--dock .rrp-nav__link {
    min-height: 62px;
    flex-direction: column;
    justify-content: center;
    gap: var(--rrp-space-1);
    color: var(--rrp-muted);
    font-size: var(--rrp-text-xs);
    letter-spacing: -0.005em;
    text-align: center;
}

.rrp-nav--dock .rrp-nav__link svg {
    width: 23px;
    height: 23px;
    stroke-width: 2;
}

.rrp-nav--dock .rrp-nav__link--active {
    box-shadow: inset 0 3px 0 var(--rrp-green);
    color: var(--rrp-ink);
}

/* ── Component: InstallPrompt — in-app PWA install banner ──────────────────── */
/* Sits in flow between the viewport and the dock, so it never covers content:
   the browser's own install affordance is a small address-bar icon nobody
   finds on Windows, and iOS offers nothing at all. */
.rrp-install {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 0 0 auto;
    margin: 0 10px 10px;
    padding: 9px 10px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-soft);
}

.rrp-install__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 9px;
    background: color-mix(in srgb, var(--rrp-navy) 8%, var(--rrp-paper));
    color: var(--rrp-ink);
}

.rrp-install__text {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    flex: 1 1 auto;
}

.rrp-install__text strong {
    color: var(--rrp-ink);
    font-size: var(--rrp-text-sm);
    font-weight: 750;
}

.rrp-install__text small {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-xs);
}

.rrp-install__cta {
    flex: none;
    min-height: 40px;
    padding: 8px 16px;
    border: 0;
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-navy);
    color: #fff;
    font-size: var(--rrp-text-sm);
    font-weight: 750;
    cursor: pointer;
}

.rrp-install__cta:hover:not(:disabled) {
    background: var(--rrp-navy-soft);
}

.rrp-install__dismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: var(--rrp-muted);
    cursor: pointer;
}

.rrp-install__dismiss:hover {
    background: color-mix(in srgb, var(--rrp-navy) 6%, var(--rrp-paper));
    color: var(--rrp-ink);
}

/* On the desktop canvas a full-width bar reads like a system failure; a card
   pinned to the corner reads like the aside it is. */
@media (min-width: 781px) {
    .rrp-install {
        position: fixed;
        right: 18px;
        bottom: 18px;
        z-index: var(--rrp-z-overlay);
        max-width: 400px;
        margin: 0;
        box-shadow: var(--rrp-shadow-raised);
    }
}

/* ── Component: SideFoot — RRN parent brand in the desktop rail ────────────── */
.rrp-side-foot {
    margin-top: auto;
    padding: 14px 12px 2px;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
}

.rrp-side-foot .rrp-brand-logo {
    display: block;
    width: 118px;
}

.rrp-side-foot small {
    display: block;
    margin-top: 7px;
    color: rgba(255, 255, 255, 0.55);
    font-size: var(--rrp-text-3xs);
    line-height: 1.4;
}

.rrp-side-foot .rrp-cookie-link {
    display: block;
    margin-top: 8px;
    color: rgba(255, 255, 255, 0.55);
    font-size: var(--rrp-text-3xs);
}

/* ── Component: PageHead ───────────────────────────────────────────────────── */
.rrp-pagehead {
    display: grid;
    min-width: 0;
    gap: 13px;
    margin-bottom: 16px;
}

.rrp-pagehead__copy {
    min-width: 0;
}

.rrp-eyebrow {
    margin: 0 0 5px;
    color: var(--rrp-green-dark);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.rrp-pagehead h1 {
    margin: 0;
    color: var(--rrp-ink);
    font-size: 25px;
    font-weight: 800;
    letter-spacing: -0.045em;
    line-height: 1.08;
    overflow-wrap: anywhere;
}

.rrp-pagehead__desc {
    margin: 7px 0 0;
    color: var(--rrp-muted);
    font-size: 13px;
}

.rrp-pagehead__side {
    min-width: 0;
}

/* ── Component: AvailabilityToggle — one immediate on/off control. Sits
      directly on the warm canvas (no card box); a little vertical padding
      keeps it optically level with the greeting in the pagehead. ───────────── */
.rrp-avail {
    display: grid;
    width: 100%;
    min-width: 0;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 2px 11px;
    padding: 6px 0;
}

.rrp-avail strong {
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
}

.rrp-avail span {
    grid-column: 2;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 650;
}

.rrp-switch {
    position: relative;
    grid-row: 1 / span 2;
    width: 46px;
    height: 26px;
    /* The shared UI layer gives every <button> min-height/min-width: var(--tap-min),
       which becomes 44px under a coarse pointer (touch devices and DevTools device
       mode). Without pinning our own minimums, that inflated this 26px-tall track to
       ~44px and, with border-radius:999px, it rendered as a circle. This is a real
       phone bug, not just an emulation artefact. */
    min-width: 46px;
    min-height: 26px;
    flex: 0 0 auto;
    box-sizing: border-box;
    padding: 0;
    /* iOS Safari gives <button> its native push-button chrome unless told
       otherwise, which turned the track into a shapeless grey blob. */
    appearance: none;
    -webkit-appearance: none;
    -webkit-tap-highlight-color: transparent;
    /* The off state is a neutral derived from the surface, so the track stays
       visibly "off" on dark instead of reading as a pale filled pill. */
    border: 1px solid var(--rrp-control-line);
    border-radius: 999px;
    background: color-mix(in srgb, var(--rrp-ink) 22%, var(--rrp-paper));
    cursor: pointer;
}

.rrp-switch::after {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(12, 36, 72, 0.35);
    content: "";
    transition: transform 140ms ease;
}

.rrp-switch[aria-checked="true"] {
    border-color: var(--rrp-green-dark);
    background: var(--rrp-green);
}

.rrp-switch[aria-checked="true"]::after {
    background: var(--rrp-navy);
    transform: translateX(20px);
}

.rrp-switch:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.rrp-avail-confirm p {
    margin: 0 0 14px;
    color: var(--rrp-ink);
    font-size: 13.5px;
    font-weight: 750;
}

.rrp-avail-confirm ul {
    display: grid;
    margin: 0;
    padding: 0;
    gap: 10px;
    list-style: none;
}

.rrp-avail-confirm li {
    padding: 11px 13px;
    border-left: 3px solid var(--rrp-green);
    background: var(--rrp-canvas);
    color: var(--rrp-ink);
    font-size: 12.5px;
    line-height: 1.5;
}

.rrp-avail-confirm li strong {
    display: block;
    color: var(--rrp-ink);
    font-weight: 800;
}

/* Switching off is not a green outcome, so the accent stays neutral rather
   than fighting the destructive confirm button. */
.rrp-avail-confirm.is-stopping li {
    border-left-color: var(--rrp-line-strong);
}

/* ── Job action dialogs (change booking, return to RRN) ────────────────────── */
.rrp-dialog__lead {
    margin: 0 0 14px;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 700;
    line-height: 1.5;
}

.rrp-dialog__current {
    margin: 0 0 14px;
    padding: 10px 12px;
    border-left: 3px solid var(--rrp-line-strong);
    background: var(--rrp-canvas);
    color: var(--rrp-ink);
    font-size: 12.5px;
}

/* Plain explanatory body text for a dialog — no box, just the words. */
.rrp-dialog__note {
    margin: 0 0 14px;
    color: var(--rrp-ink);
    font-size: 12.5px;
    line-height: 1.55;
}

.rrp-dialog__fields {
    display: grid;
    gap: 12px;
}

.rrp-dialog__warn {
    margin: 16px 0 0;
    padding-top: 14px;
    border-top: 1px solid var(--rrp-line);
    color: var(--rrp-muted);
    font-size: 12px;
    line-height: 1.5;
}

/* ── Component: UkPlate — shared .uk-plate treatment lives in
      RapidDispatch.UI; the portal only supplies the wrapper spacing. ───────── */
.rrp-plate-wrap {
    display: inline-flex;
    min-width: 0;
    align-items: center;
}

/* A display plate always reserves the width a full seven-character registration
   needs and centres a shorter one, so a plate is the same size whatever it reads
   — the numbers beside it line up on the jobs list and on a phone. A fixed-width
   (number-plate-like) face keeps that width tied to the registration's length,
   never to which characters it happens to use, so nothing overflows the plate. */
.rrp-app .rrp-plate-wrap .uk-plate--compact .uk-plate-text {
    width: 84px;
    justify-content: center;
    font-family: 'UKNumberPlate', ui-monospace, 'Segoe UI Mono', 'Consolas', monospace;
    font-variant-numeric: tabular-nums;
}

/* ── Component: ResumeCard — only rendered when a job was started today ────── */
.rrp-resume {
    display: grid;
    width: 100%;
    min-width: 0;
    grid-template-columns: minmax(0, 1fr) 20px;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
    padding: 13px;
    border: 1px solid var(--rrp-green-line);
    border-left: 5px solid var(--rrp-green);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    text-align: left;
    text-decoration: none;
    box-shadow: var(--rrp-shadow-raised);
}

.rrp-resume__tag {
    display: block;
    margin-bottom: 8px;
    color: var(--rrp-green-dark);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.rrp-resume strong {
    display: flex;
    min-width: 0;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 9px;
    font-size: 12.5px;
    font-weight: 800;
}

.rrp-resume small {
    display: block;
    margin-top: 6px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 650;
}

.rrp-resume > svg {
    width: 18px;
    height: 18px;
    color: var(--rrp-faded-icon);
    stroke-width: 2.2;
}

/* ── Component: ActionList — calm triage counts. Stacked rows on phones; the
      tiles variant becomes a full-width card row on desktop. ────────────────── */
.rrp-actions {
    overflow: hidden;
    margin-bottom: 14px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-action {
    display: grid;
    width: 100%;
    min-width: 0;
    min-height: 58px;
    grid-template-columns: 44px minmax(0, 1fr) auto 18px;
    align-items: center;
    gap: 10px;
    padding: 11px 13px;
    border: 0;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    text-align: left;
    text-decoration: none;
    box-shadow: 0 -1px 0 var(--rrp-line);
}

/* Labour value of the jobs behind the row — money next to the count. */
.rrp-action__value {
    font-family: var(--rrp-font-heading);
    font-size: 12.5px;
    font-style: normal;
    font-weight: 800;
    color: var(--rrp-green-dark);
    white-space: nowrap;
}

.rrp-action strong {
    font-family: var(--rrp-font-heading);
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.04em;
    line-height: 1;
}

.rrp-action.is-urgent strong {
    color: var(--rrp-danger);
}

.rrp-action > span {
    overflow: hidden;
    font-size: 12.5px;
    font-weight: 800;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-action > span small {
    display: block;
    margin-top: 2px;
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
}

.rrp-action > svg {
    width: 18px;
    height: 18px;
    color: var(--rrp-faded-icon);
    stroke-width: 2.2;
    justify-self: end;
}

/* Nothing in this list is the repairer's to do, so it reads quieter than the
   work above it — a long queue at RRN must not look like their backlog. */
/* ── Component: Panel (Next up / This week / generic card sections) ────────── */
.rrp-panel {
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-panel + .rrp-panel {
    margin-top: 16px;
}

.rrp-panel__head {
    display: flex;
    min-width: 0;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 13px 15px 11px;
    border-bottom: 1px solid var(--rrp-line);
}

.rrp-panel__head :is(h2, h3) {
    margin: 0;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 800;
    letter-spacing: -0.01em;
}

.rrp-panel__meta {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    white-space: nowrap;
}

.rrp-panel__head--stacked {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
}

.rrp-panel__head--stacked .rrp-panel__meta {
    white-space: normal;
}

.rrp-panel__link {
    min-height: 30px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--rrp-green-dark);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    text-decoration: underline;
    text-underline-offset: 3px;
    white-space: nowrap;
}

.rrp-panel__body {
    min-width: 0;
    padding: 13px 15px;
}

.rrp-panel__body > :first-child {
    margin-top: 0;
}

.rrp-panel__body > :last-child {
    margin-bottom: 0;
}

/* ── Component: MiniRow (Next up rows) ─────────────────────────────────────── */
.rrp-minirow {
    display: grid;
    width: 100%;
    min-width: 0;
    min-height: 56px;
    grid-template-columns: auto minmax(0, 1fr) 16px;
    align-items: center;
    gap: 11px;
    padding: 10px 15px;
    border: 0;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    text-align: left;
    text-decoration: none;
    box-shadow: 0 -1px 0 var(--rrp-line);
}

.rrp-panel__head + .rrp-minirow {
    box-shadow: none;
}

.rrp-minirow__main {
    min-width: 0;
}

.rrp-minirow__main strong {
    display: block;
    overflow: hidden;
    font-size: 12.5px;
    font-weight: 800;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-minirow__main small {
    display: block;
    overflow: hidden;
    margin-top: 4px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 650;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-minirow > svg {
    width: 16px;
    height: 16px;
    color: var(--rrp-faded-icon);
    stroke-width: 2.2;
    justify-self: end;
}

/* ── Component: Overview grid (dashboard columns) ──────────────────────────── */
.rrp-overview-grid {
    display: block;
    min-width: 0;
    /* Every home row spaces itself from the next; without this the money
       tiles (or the setup checklist) sit flush against Today's visits. */
    margin-bottom: 14px;
}

.rrp-overview-grid > * {
    min-width: 0;
}

.rrp-home-col {
    min-width: 0;
}

.rrp-side-col {
    display: none;
}

/* ── Component: FilterBar (SearchForm) — search + optional centre scope ────── */
.rrp-search {
    position: relative;
    display: flex;
    min-width: 0;
    align-items: stretch;
    margin-bottom: var(--rrp-space-4);
    border: 1px solid var(--rrp-control-line);
    border-radius: 10px;
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-soft);
}

.rrp-search > svg {
    position: absolute;
    top: 50%;
    left: 16px;
    width: 20px;
    height: 20px;
    color: var(--rrp-ink);
    stroke-width: 2;
    transform: translateY(-50%);
    pointer-events: none;
}

.rrp-search input {
    min-width: 0;
    min-height: 50px;
    flex: 1 1 auto;
    padding: 13px 14px 13px 49px;
    border: 0;
    border-radius: 10px 0 0 10px;
    background: transparent;
    color: var(--rrp-ink);
    font-size: 16px;
}

.rrp-search input:focus {
    outline: none;
}

.rrp-search:focus-within {
    outline: 3px solid var(--rrp-mustard);
    outline-offset: 2px;
}

/* The inline centre scope: part of the same bar, divided from the input. */
.rrp-search__scope {
    display: flex;
    min-width: 0;
    flex: 0 1 auto;
    align-items: center;
    border-left: 1px solid var(--rrp-line);
}

.rrp-search__scope select {
    max-width: clamp(110px, 26vw, 210px);
    min-height: 44px;
    padding: 8px 8px 8px 12px;
    border: 0;
    background: transparent;
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 750;
    text-overflow: ellipsis;
    cursor: pointer;
}

.rrp-search__scope select:focus {
    border-radius: 7px;
    outline: 3px solid rgba(28, 196, 120, 0.28);
    outline-offset: -3px;
}

.rrp-search > button {
    flex: 0 0 auto;
    min-height: 44px;
    margin: 5px;
    padding: 9px 12px;
    border: 0;
    border-radius: 7px;
    background: var(--rrp-navy);
    color: #fff;
    font-size: 12px;
    font-weight: 800;
}

/* ── Component: ListHead + FilterChip ──────────────────────────────────────── */
.rrp-list-head {
    display: flex;
    min-width: 0;
    min-height: 38px;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    margin-bottom: 7px;
}

.rrp-list-head h2 {
    margin: 0;
    color: var(--rrp-ink);
    font-size: 16px;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.rrp-list-head > span {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
}

/* ── Component: SortSelect — list order, in the ListHead ───────────────────── */
.rrp-sortselect {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* The one thing in the head that claims the free space, so it holds the
       trailing edge. The chips used to do this; they now sit with the count they
       describe, and only one auto margin can win a flex row anyway. */
    margin-left: auto;
}

.rrp-sortselect label {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    white-space: nowrap;
}

.rrp-sortselect select {
    min-height: 32px;
    max-width: 190px;
    padding: 4px 8px;
    border: 1px solid var(--rrp-control-line);
    border-radius: 8px;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-family: inherit;
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
}

/* Sortable column headers in the JobTable grid header. */
.rrp-app .rrp-job-table .rrn-lhead .rrp-job-th {
    display: inline-flex;
    min-width: 0;
    min-height: 26px;
    align-items: center;
    gap: 4px;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-align: left;
    cursor: pointer;
}

.rrp-app .rrp-job-table .rrn-lhead .rrp-job-th:hover {
    color: var(--rrp-ink);
    text-decoration: underline;
}

.rrp-app .rrp-job-table .rrn-lhead .rrp-job-th.is-sorted {
    color: var(--rrp-ink);
}

/* "Job" is not sortable, so it stays a plain label — but it must read at the
   same size, weight and case as the sortable headers beside it rather than the
   smaller uppercase treatment a bare header span would otherwise inherit. */
.rrp-app .rrp-job-table .rrn-lhead .rrp-job-th--static {
    text-transform: none;
    cursor: default;
}

.rrp-app .rrp-job-table .rrn-lhead .rrp-job-th--static:hover {
    color: inherit;
    text-decoration: none;
}

.rrp-job-th__dir {
    color: var(--rrp-green-dark);
    font-weight: 800;
}

/* Active filters as removable chips, beside the count they have narrowed. */
.rrp-list-head__chips {
    display: flex;
    min-width: 0;
    flex-wrap: wrap;
    gap: 6px;
}

.rrp-list-head__chips:empty {
    display: none;
}

.rrp-chip {
    display: inline-flex;
    min-height: 32px;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border: 1px solid var(--rrp-green-dark);
    border-radius: 999px;
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
}

.rrp-chip svg {
    width: 13px;
    height: 13px;
    stroke-width: 2.6;
}

/* The chip row's one-tap reset for every chip filter (centre scope stays). */
.rrp-chips-clear {
    min-height: 32px;
    padding: 5px 8px;
    border: 0;
    background: transparent;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    text-decoration: underline;
    cursor: pointer;
}

/* ── Component: FilterMenu — the filter bar's "Filters" affordance. Bottom
      sheet on phones; an anchored popover on desktop. The toggle carries a
      live badge counting active filters. ─────────────────────────────────── */
.rrp-fmenu {
    position: relative;
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    border-left: 1px solid var(--rrp-line);
}

.rrp-fmenu__toggle {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    gap: 6px;
    padding: 8px 10px;
    border: 0;
    background: transparent;
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 750;
    cursor: pointer;
}

/* Phones keep just the funnel icon + badge; the text label is desktop-only. */
.rrp-fmenu__toggle > span {
    display: none;
}

.rrp-fmenu__toggle svg {
    width: 16px;
    height: 16px;
    stroke-width: 2.2;
}

.rrp-fmenu__toggle strong {
    display: inline-grid;
    min-width: 18px;
    height: 18px;
    place-items: center;
    padding-inline: 4px;
    border-radius: 999px;
    background: var(--rrp-green);
    color: var(--rrp-navy);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
}

/* Phone: a bottom sheet the thumb can reach. It has to sit above the docked
   bottom nav, which shares --rrp-z-dock and is the shell's last in-flow child:
   at an equal tier the dock paints over the sheet's footer, hiding the Clear
   filters / Done row. --rrp-z-sheet (the bottom-sheet tier) lifts it clear. */
.rrp-fmenu__panel {
    position: fixed;
    z-index: var(--rrp-z-sheet);
    inset-inline: 0;
    bottom: 0;
    display: grid;
    max-height: min(78vh, 520px);
    gap: 16px;
    padding: 18px 18px calc(18px + env(safe-area-inset-bottom, 0px));
    border: 1px solid var(--rrp-line-strong);
    border-radius: 14px 14px 0 0;
    background: var(--rrp-paper);
    box-shadow: 0 -12px 32px rgba(11, 30, 51, 0.18);
    overflow: auto;
}

.rrp-fmenu__group {
    display: grid;
    gap: 8px;
}

.rrp-fmenu__label {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.rrp-fmenu__presets {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.rrp-fmenu__presets button {
    min-height: 34px;
    padding: 7px 12px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 999px;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: 11px;
    font-weight: 750;
}

.rrp-fmenu__presets button.is-active {
    border-color: var(--rrp-navy);
    background: var(--rrp-navy);
    color: #fff;
}

.rrp-fmenu__dates {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.rrp-fmenu__dates label {
    display: grid;
    gap: 4px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
}

.rrp-fmenu__dates input,
.rrp-fmenu__group select {
    min-height: 44px;
    padding: 8px 10px;
    border: 1px solid var(--rrp-control-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: var(--rrp-text-sm);
    font-weight: 650;
}

.rrp-fmenu__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.rrp-fmenu__clear {
    min-height: 38px;
    padding: 8px 12px;
    border: 0;
    background: transparent;
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 750;
    text-decoration: underline;
}

.rrp-fmenu__clear:disabled {
    opacity: 0.5;
    text-decoration: none;
}

.rrp-fmenu__done {
    min-height: 38px;
    padding: 8px 16px;
    border: 0;
    border-radius: 7px;
    background: var(--rrp-navy);
    color: #fff;
    font-size: 11.5px;
    font-weight: 800;
}

/* ── Component: BucketPills (jobs status switcher) — pills on desktop, a
      single compact Status select on phones (one line instead of three). ───── */
.rrp-pills {
    display: none;
    min-width: 0;
    flex-wrap: wrap;
    gap: 7px;
    margin-bottom: 14px;
}

.rrp-pills-select {
    min-width: 0;
    margin-bottom: 14px;
}

/* The desktop pills each carry their own label, but the phone select collapses
   to a lone control reading "All (1)"; a visible label above it names the
   filter (matches the portal's field-label treatment). Hidden with the select
   on desktop, where the labelled pills take over. */
.rrp-pills-select__label {
    display: block;
    margin-bottom: 6px;
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
}

.rrp-pills-select select {
    width: 100%;
    min-height: 48px;
    padding: 10px 12px;
    border: 1px solid var(--rrp-control-line);
    border-radius: 10px;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: var(--rrp-text-base);
    font-weight: 750;
    box-shadow: var(--rrp-shadow-soft);
}

.rrp-pills button {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    gap: 7px;
    padding: 8px 12px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 999px;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: 11.5px;
    font-weight: 750;
}

.rrp-pills button.is-active {
    border-color: var(--rrp-navy);
    background: var(--rrp-navy);
    color: #fff;
}

.rrp-pills button strong {
    display: inline-grid;
    min-width: 22px;
    height: 22px;
    place-items: center;
    padding-inline: 5px;
    border-radius: 999px;
    background: var(--rrp-canvas);
    color: var(--rrp-ink);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
}

.rrp-pills button.is-active strong {
    background: var(--rrp-green);
    color: var(--rrp-navy);
}

/* ── Component: BulkAssignBar — appears above the job list once rows are ticked,
      holding the count, the technician select and the apply button. Styled as a
      raised panel rather than a toolbar so it reads as something acting ON the
      list below it. ─────────────────────────────────────────────────────────── */
.rrp-bulkbar {
    display: flex;
    flex-direction: column;
    gap: var(--rrp-space-2);
    margin-bottom: var(--rrp-space-2);
    padding: var(--rrp-space-3);
    border: 1px solid var(--rrp-navy);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-card);
}

.rrp-bulkbar__count {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rrp-space-2);
    color: var(--rrp-ink);
    font-size: var(--rrp-text-xs);
    font-weight: 800;
}

.rrp-bulkbar__clear {
    min-height: var(--tap-min);
    padding-inline: var(--rrp-space-1);
    border: 0;
    background: none;
    color: var(--rrp-muted);
    font-family: inherit;
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    text-decoration: underline;
    cursor: pointer;
}

.rrp-bulkbar__clear:hover:not(:disabled) {
    color: var(--rrp-ink);
}

.rrp-bulkbar__status {
    margin: 0;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 650;
}

/* One column on a phone, then the two fields side by side with the button holding
   the trailing edge once there is room for all three. */
.rrp-bulkbar__controls {
    display: grid;
    gap: var(--rrp-space-2);
    align-items: end;
}

@media (min-width: 640px) {
    .rrp-bulkbar__controls {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
    }
}

.rrp-bulkbar__controls .field {
    display: flex;
    min-width: 0;
    flex-direction: column;
    gap: 4px;
}

.rrp-bulkbar__controls label {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
}

.rrp-bulkbar__controls .optional {
    color: var(--rrp-faded);
    font-weight: 650;
}

.rrp-bulkbar__controls select,
.rrp-bulkbar__controls input {
    min-height: 40px;
    padding: 8px 10px;
    border: 1px solid var(--rrp-control-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-family: inherit;
    font-size: var(--rrp-text-xs);
    font-weight: 700;
}

/* ── Utility: Stack — vertical rhythm between stacked panels ───────────────── */
.rrp-stack {
    display: grid;
    gap: 14px;
}

/* ── Component: JobTable — the shared Rapid-apps RrnList, restyled minimally
      for the warm canvas. Desktop keeps the grid header; mobile stacks each
      row into a card-like block. ───────────────────────────────────────────── */
.rrp-app .rrp-job-table.rrn-list {
    border-color: var(--rrp-line-strong);
    border-radius: 10px;
    box-shadow: none;
}

.rrp-app .rrp-job-table .rrn-lhead {
    border-bottom-color: var(--rrp-line);
    background: var(--rrp-paper);
}

.rrp-app .rrp-job-table .rrn-lhead span {
    color: var(--rrp-muted);
}

/* The row the user just returned from — held softly until the filters change. */
.rrp-app .rrp-job-table .rrn-row.rrp-job-row--origin {
    background: var(--rrp-green-wash);
    box-shadow: inset 3px 0 0 var(--rrp-green);
}

.rrp-app .rrp-job-table .rrn-row {
    min-height: 60px;
    /* Trimmed from the shared 15px: the row now carries repair type and
       customer on their own lines, so a little vertical padding is given back
       to keep the list scannable, as the design brief allows. */
    padding-block: 11px;
    border-top: 1px solid var(--rrp-line);
    border-left: 0;
    color: var(--rrp-ink);
}

.rrp-app .rrp-job-table .rrn-row:hover {
    background: var(--rrp-canvas);
}

.rrp-app .rrp-job-table .rrn-row:first-of-type {
    border-top: 0;
}

.rrp-job-cell {
    min-width: 0;
}

.rrp-job-cell strong {
    display: block;
    overflow: hidden;
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-job-cell small {
    display: block;
    overflow: hidden;
    margin-top: 4px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 650;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The row title line: the action title takes the room and ellipsizes, and the
   unread-chat chip sits at its right — the right of the Job column on desktop,
   the row's top-right on phones (the job cell leads the stacked row). */
.rrp-job-cell__head {
    display: flex;
    min-width: 0;
    align-items: center;
    gap: 8px;
}

.rrp-job-cell__head .rrp-job-cell__link {
    min-width: 0;
    flex: 0 1 auto;
    overflow: hidden;
}

/* Repair type then customer name, each on its own line — a calmer row than the
   old job-number / type / name / postcode run, with the name given its own line
   rather than trailing the type. */
.rrp-job-cell__type,
.rrp-job-cell__customer {
    display: block;
    overflow: hidden;
    margin-top: 3px;
    font-size: var(--rrp-text-3xs);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-job-cell__type {
    color: var(--rrp-muted);
    font-weight: 650;
}

.rrp-job-cell__customer {
    color: var(--rrp-ink);
    font-weight: 750;
}

/* Unread-messages CTA pill. Green wash with contrast-safe green text is the
   portal's established unread treatment (matching the bell and chat badge) and
   a clear "read this", without the danger red reserved for genuinely late work.
   It draws above the row's stretched link but ignores pointer events, so a tap
   still opens the job. */
.rrp-job-chat {
    position: relative;
    z-index: 1;
    flex: 0 0 auto;
    margin-left: auto;
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--rrp-green-wash);
    color: var(--rrp-green-deep);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    white-space: nowrap;
    pointer-events: none;
}

.rrp-app .rrp-job-table .rrn-row {
    position: relative;
}

.rrp-job-cell__link {
    color: inherit;
    text-decoration: none;
}

.rrp-job-cell__link::after {
    position: absolute;
    inset: 0;
    content: "";
}

.rrp-job-cell--when {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
}

.rrp-job-cell--when b {
    display: block;
    margin-top: 3px;
    color: var(--rrp-ink);
    font-size: 11.5px;
}

.rrp-job-cell--value {
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 800;
    white-space: nowrap;
}

/* The tick column. Sits above the row's stretched link — that link covers the
   whole row via an inset ::after, so without raising this the checkbox would be
   unclickable and every tick would open the job instead. */
.rrp-job-select {
    position: relative;
    z-index: 1;
    display: flex;
    min-height: var(--tap-min);
    align-items: center;
    justify-content: flex-start;
    cursor: pointer;
}

.rrp-job-select input {
    cursor: pointer;
    accent-color: var(--rrp-green-dark);
}

.rrp-job-cell--chevron {
    display: flex;
    justify-content: flex-end;
}

.rrp-job-cell--chevron svg {
    width: 18px;
    height: 18px;
    color: var(--rrp-faded-icon);
    stroke-width: 2.2;
}

/* ── Component: BackLink (slim back row) ───────────────────────────────────── */
.rrp-backrow {
    display: flex;
    min-width: 0;
    align-items: center;
    margin: -8px 0 2px;
}

.rrp-back {
    display: inline-flex;
    min-height: 42px;
    align-items: center;
    gap: 7px;
    padding: 6px 3px;
    border: 0;
    background: transparent;
    color: var(--rrp-ink);
    font-size: 11.5px;
    font-weight: 800;
    text-decoration: none;
}

.rrp-back svg {
    width: 18px;
    height: 18px;
    stroke-width: 2.2;
}

/* ── Component: Journey — transparent strip on desktop, compact expandable
      summary on mobile. No card, border or shadow: it sits on the canvas.
      Generous by design: large ticked dots, a thick track and a celebrated
      current stage. ─────────────────────────────────────────────────────────── */
.rrp-journey {
    display: none;
    margin: 4px 0 28px;
    padding: 0;
    list-style: none;
}

.rrp-step {
    position: relative;
    display: grid;
    min-width: 0;
    justify-items: center;
    padding: 44px 6px 0;
    color: var(--rrp-faded);
    text-align: center;
}

/* Track segment joining this step to the previous one. */
.rrp-step::before {
    position: absolute;
    top: 12px;
    right: 50%;
    left: -50%;
    height: 4px;
    border-radius: 2px;
    background: var(--rrp-line-strong);
    content: "";
}

.rrp-step:first-child::before {
    display: none;
}

.rrp-step__dot {
    position: absolute;
    z-index: 1;
    top: 0;
    left: 50%;
    display: grid;
    width: 28px;
    height: 28px;
    place-items: center;
    border: 3px solid #c2bca9;
    border-radius: 50%;
    background: var(--rrp-canvas);
    transform: translateX(-50%);
}

.rrp-step__label {
    font-size: 12.5px;
    font-weight: 800;
    letter-spacing: -0.01em;
}

.rrp-step__meta {
    margin-top: 3px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 700;
}

/* The current step's date is the most useful fact on the strip, so it is a
   filled chip rather than tinted text: mustard text measured 1.86:1 here, and
   9.5px was below the 11px floor. Shape now carries the state as well as
   colour, so the "you are here" signal survives greyscale. */
.rrp-step__meta--now {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--rrp-navy);
    color: var(--rrp-paper);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.01em;
    text-transform: none;
    white-space: nowrap;
}

/* On dark the navy chip would vanish into the canvas; invert to the accent. */
[data-theme="dark"] .rrp-step__meta--now {
    background: var(--rrp-green-dark);
    color: #04121c;
}

.rrp-step.is-done,
.rrp-step.is-current {
    color: var(--rrp-ink);
}

.rrp-step.is-done::before,
.rrp-step.is-current::before {
    background: var(--rrp-green-dark);
}

.rrp-step.is-done .rrp-step__dot {
    border-color: var(--rrp-green-dark);
    background: var(--rrp-green-dark);
}

/* Tick inside completed dots. */
.rrp-step.is-done .rrp-step__dot::after {
    width: 6px;
    height: 11px;
    margin-top: -3px;
    border: solid #fff;
    border-width: 0 2.5px 2.5px 0;
    content: "";
    transform: rotate(45deg);
}

.rrp-step.is-current .rrp-step__dot {
    border-color: var(--rrp-navy);
    background: var(--rrp-mustard);
    box-shadow: 0 0 0 6px color-mix(in srgb, var(--rrp-mustard) 24%, transparent);
}

.rrp-step.is-current .rrp-step__dot::after {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--rrp-navy);
    content: "";
}

.rrp-step.is-current .rrp-step__label {
    font-size: 14.5px;
    letter-spacing: -0.02em;
}

.rrp-jsum {
    display: grid;
    width: 100%;
    min-height: 52px;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    padding: 10px 2px;
    border: 0;
    background: transparent;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 800;
    text-align: left;
}

.rrp-jsum__dots {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.rrp-jsum__dots i {
    width: 10px;
    height: 10px;
    border: 2px solid #c2bca9;
    border-radius: 50%;
    background: var(--rrp-canvas);
}

.rrp-jsum__dots i.is-done {
    border-color: var(--rrp-green-dark);
    background: var(--rrp-green-dark);
}

.rrp-jsum__dots i.is-current {
    width: 14px;
    height: 14px;
    border-color: var(--rrp-navy);
    background: var(--rrp-mustard);
    box-shadow: 0 0 0 3px rgba(28, 196, 120, 0.25);
}

.rrp-jsum > svg {
    width: 17px;
    height: 17px;
    stroke-width: 2.4;
    transition: transform 140ms ease;
}

.rrp-jsum[aria-expanded="true"] > svg {
    transform: rotate(180deg);
}

.rrp-jfull {
    margin-bottom: 15px;
    padding: 0 2px 4px;
}

.rrp-jfull ol {
    margin: 0;
    padding: 0;
    list-style: none;
}

.rrp-jfull li {
    display: grid;
    grid-template-columns: 26px minmax(0, 1fr) auto;
    align-items: center;
    gap: 11px;
    padding: 12px 0;
    border-top: 1px solid var(--rrp-line);
    color: var(--rrp-muted);
    font-size: 12.5px;
    font-weight: 750;
}

.rrp-jfull li:first-child {
    border-top: 0;
}

.rrp-jfull li i {
    display: grid;
    width: 18px;
    height: 18px;
    place-items: center;
    border: 2.5px solid #c2bca9;
    border-radius: 50%;
    background: var(--rrp-canvas);
}

.rrp-jfull li.is-done {
    color: var(--rrp-ink);
}

.rrp-jfull li.is-done i {
    border-color: var(--rrp-green-dark);
    background: var(--rrp-green-dark);
}

.rrp-jfull li.is-done i::after {
    width: 4px;
    height: 8px;
    margin-top: -2px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    content: "";
    transform: rotate(45deg);
}

.rrp-jfull li.is-current {
    color: var(--rrp-ink);
    font-weight: 800;
}

.rrp-jfull li.is-current i {
    border-color: var(--rrp-navy);
    background: var(--rrp-mustard);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--rrp-mustard) 26%, transparent);
}

.rrp-jfull__label {
    display: grid;
    min-width: 0;
    gap: 2px;
}

.rrp-jfull__label em {
    color: var(--rrp-green-dark);
    font-size: var(--rrp-text-3xs);
    font-style: normal;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.rrp-jfull li small {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 700;
    text-align: right;
}

/* ── Utility: inline status / message / form — the quiet text and small forms
      that sit inside a panel, beneath whatever they are explaining.

      These were the body of a NextAction card, which no longer exists: primary
      actions moved to the FlowBar, and the card's own shell (heading, eyebrow,
      integrated kebab) went with it. What the pages actually kept using were
      these three, so they are named for what they are rather than for a component
      they are no longer part of. ─────────────────────────────────────────────── */
.rrp-inline-status {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 650;
}

.rrp-inline-message {
    min-width: 0;
    margin-bottom: 4px;
    padding: 10px 12px;
    border-radius: var(--rrp-radius-control);
    font-size: 12px;
    font-weight: 700;
}

.rrp-inline-form {
    display: grid;
    gap: 10px;
    margin-top: 12px;
    max-width: min(420px, 100%);
}

.rrp-inline-form .field {
    margin: 0;
}

.rrp-note-form {
    display: grid;
    gap: 10px;
    margin-top: 12px;
}

.rrp-note-form .btn {
    justify-self: start;
}

.rrp-primary {
    display: inline-flex;
    min-width: 154px;
    min-height: 48px;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 16px;
    border: 0;
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-navy);
    color: #fff;
    font-size: 12.5px;
    font-weight: 800;
    text-decoration: none;
    white-space: nowrap;
}

.rrp-primary:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.rrp-primary svg {
    width: 17px;
    height: 17px;
    stroke-width: 2.2;
}

.rrp-more {
    position: absolute;
    top: 13px;
    right: 13px;
}

.rrp-more > summary {
    display: inline-flex;
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    cursor: pointer;
    list-style: none;
}

.rrp-more > summary::-webkit-details-marker {
    display: none;
}

.rrp-more > summary svg {
    width: 20px;
    height: 20px;
    stroke-width: 2.2;
}

.rrp-menu {
    position: absolute;
    z-index: var(--rrp-z-menu);
    top: calc(100% + 7px);
    right: 0;
    width: 230px;
    overflow: hidden;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 9px;
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-pop);
}

.rrp-menu :is(button, a) {
    display: flex;
    width: 100%;
    min-height: 44px;
    align-items: center;
    gap: 9px;
    padding: 10px 12px;
    border: 0;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: 11.5px;
    font-weight: 750;
    text-align: left;
    text-decoration: none;
}

.rrp-menu :is(button, a):first-child {
    border-top: 0;
}

.rrp-menu .is-danger {
    color: var(--rrp-danger-deep);
}

/* ── Component: FactGroup + Fact — full-width column of labelled rows ──────── */
.rrp-summary {
    min-width: 0;
}

.rrp-fact-group {
    min-width: 0;
    padding: 10px 0 4px;
}

.rrp-fact-group + .rrp-fact-group {
    border-top: 1px solid var(--rrp-line);
}

.rrp-fact-group h3 {
    margin: 0 0 10px;
    color: var(--rrp-ink);
    font-size: 11.5px;
    font-weight: 800;
}

/* The label column is capped by a share of the row as well as by 200px. A
   minmax() track grows to its maximum before the 1fr beside it gets anything, so
   a flat 200px ceiling took 200px even in a 334px row on a phone — leaving 120px
   for the value and wrapping addresses and names onto two lines while a
   six-letter label sat in a 200px column. The share only binds below about
   530px, so wide rows are unchanged and every row in the same panel still
   resolves the same width, which is what keeps the values aligned. */
.rrp-fact {
    display: grid;
    grid-template-columns: minmax(104px, min(200px, 38%)) minmax(0, 1fr);
    gap: 12px;
    padding: 8px 0;
    border-top: 1px solid var(--rrp-line);
}

.rrp-fact:first-of-type {
    border-top: 0;
}

.rrp-fact > span {
    display: block;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding-top: 2px;
}

.rrp-fact > b {
    min-width: 0;
    color: var(--rrp-ink);
    font-size: 11.5px;
    line-height: 1.55;
    overflow-wrap: anywhere;
}

.rrp-fact > b a {
    color: inherit;
    text-underline-offset: 3px;
}

.rrp-fact-note {
    margin: 6px 0 0;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
}

/* The CRM damage memo, rendered verbatim with its newlines. */
.rrp-damage-text {
    margin: 0;
    color: var(--rrp-ink);
    font-size: 12.5px;
    line-height: 1.65;
    overflow-wrap: anywhere;
    white-space: pre-line;
}

/* ── Component: OrderLines — work and parts lines as a readable table ───────── */

.rrp-lines {
    min-width: 0;
    padding: 10px 0 4px;
}

.rrp-lines + .rrp-lines {
    border-top: 1px solid var(--rrp-line);
}

.rrp-lines h3 {
    margin: 0 0 6px;
    color: var(--rrp-ink);
    font-size: 11.5px;
    font-weight: 800;
}

.rrp-lines__table {
    width: 100%;
    border-collapse: collapse;
}

.rrp-lines__table td {
    padding: 8px 0 2px;
    border-top: 1px solid var(--rrp-line);
    vertical-align: top;
}

.rrp-lines__table tr:first-child td {
    border-top: 0;
}

.rrp-lines__name {
    display: block;
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 700;
    line-height: 1.5;
    overflow-wrap: anywhere;
}

/* A part number, or a free-text name that differs from the repair line. */
.rrp-lines__alt {
    display: block;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    line-height: 1.5;
    overflow-wrap: anywhere;
}

.rrp-lines__cost {
    width: 1%;
    text-align: right;
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    padding-left: 12px;
}

/* The CRM's memo_details — the instruction for the line above it. It hangs off
   the line's row (no border of its own) so the pair reads as one entry. */
.rrp-lines__memo td {
    border-top: 0;
    padding: 0 0 8px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    line-height: 1.6;
    overflow-wrap: anywhere;
    white-space: pre-line;
}

/* Per-section subtotal (labour / parts) closing each lines table. */
.rrp-lines__table tfoot td {
    padding-top: 8px;
    border-top: 1px solid var(--rrp-line-strong);
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 800;
}

/* Combined figure when a job carries both labour and parts. */
.rrp-lines__grandtotal {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 2px solid var(--rrp-line-strong);
}

.rrp-lines__grandtotal span {
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.rrp-lines__grandtotal strong {
    color: var(--rrp-ink);
    font-size: 14px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

/* ── Component: History list (safe timeline) ───────────────────────────────── */
/* ── Component: LocationMap — formatted repair address, Navigate link and the
      keyless OpenStreetMap embed; address-only when no map is possible. ─────── */
.rrp-location {
    display: grid;
    min-width: 0;
    gap: 16px;
    padding-top: 6px;
}

.rrp-location__address {
    display: grid;
    justify-items: start;
    gap: 7px;
}

.rrp-location__address > span {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.rrp-location__address > b {
    display: grid;
    min-width: 0;
    gap: 2px;
    color: var(--rrp-ink);
    font-size: 12.5px;
    line-height: 1.5;
    overflow-wrap: anywhere;
}

.rrp-location__navigate {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
}

.rrp-location__navigate svg {
    width: 16px;
    height: 16px;
    stroke-width: 2;
}

.rrp-location__map {
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 10px;
    background: var(--rrp-canvas);
}

.rrp-location__map iframe {
    display: block;
    width: 100%;
    height: clamp(260px, 46vh, 420px);
    border: 0;
}

/* Address beside the map once the sheet itself is wide enough — which is a
   question about the sheet, not the screen it is on. */
@container rrp-sheet (min-width: 560px) {
    .rrp-location {
        grid-template-columns: minmax(230px, 320px) minmax(0, 1fr);
        align-items: start;
        gap: clamp(18px, 2.5vw, 28px);
    }
}

.rrp-location__note {
    margin: 0;
    grid-column: 1 / -1;
    color: var(--rrp-muted);
    font-size: 11.5px;
}

/* ── Forms — field, buttons, checks (used inside panels and sheets) ────────── */
.rrp-app .field {
    min-width: 0;
    margin-bottom: 14px;
}

/* .rrp-field-label is for the rare read-only row that sits in the field rhythm
   and has no control of its own — a <label> pointing at nothing is a broken
   promise to a screen reader. */
.rrp-app .field :where(label, .rrp-field-label) {
    display: block;
    margin-bottom: 6px;
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
}

.rrp-app .field label span {
    color: var(--rrp-muted);
    font-weight: 650;
}

.rrp-app .field :where(input, select, textarea) {
    width: 100%;
    min-width: 0;
    min-height: 44px;
    padding: 10px 11px;
    border: 1px solid var(--rrp-control-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: 16px;
}

.rrp-app .field textarea {
    min-height: 92px;
    resize: vertical;
}

/* Safari gives date inputs an intrinsic width and a right-aligned, margined
   value that both ignore width:100%, so the picker ran off the edge of the
   booking form on a phone. Reset the native chrome and let it shrink. */
.rrp-app .field input[type="date"] {
    max-width: 100%;
    -webkit-appearance: none;
    appearance: none;
}

.rrp-app .field input[type="date"]::-webkit-date-and-time-value {
    margin: 0;
    text-align: left;
}

.rrp-app .field input[type="date"]::-webkit-calendar-picker-indicator {
    margin-inline-start: auto;
    flex: 0 0 auto;
}

.rrp-app .field :where(input, select, textarea):focus {
    border-color: var(--rrp-navy-soft);
    outline: 3px solid rgba(28, 196, 120, 0.28);
    outline-offset: 0;
}

.rrp-app .field .hint {
    margin-top: 5px;
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 550;
}

.rrp-link-button {
    display: inline;
    padding: 0;
    border: 0;
    background: none;
    color: var(--rrp-green-dark);
    font: inherit;
    font-weight: 750;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

/* "(optional)" beside a label. Scoped to the whole app rather than to the one
   component that first needed it — every form uses this wording. */
.rrp-app .optional {
    color: var(--rrp-faded);
    font-weight: 650;
}

/* ── Field problems ────────────────────────────────────────────────────────────
   A field's own error sits under the control it belongs to and stays there:
   the thing being corrected and the sentence describing the correction have to
   be on screen together, which a toast at the top of a twelve-field form can
   never manage on a phone. Written by RepairerField, which also owns the
   aria-invalid and aria-describedby wiring, so the red border and the
   announcement can never disagree. ───────────────────────────────────────────*/
.rrp-app .field :where(input, select, textarea)[aria-invalid="true"] {
    border-color: var(--rrp-danger);
}

.rrp-app .field :where(input, select, textarea)[aria-invalid="true"]:focus {
    border-color: var(--rrp-danger);
    outline-color: color-mix(in srgb, var(--rrp-danger) 30%, transparent);
}

.rrp-app .rrp-field-error {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: 6px;
    color: var(--rrp-danger-deep);
    font-size: 11.5px;
    font-weight: 700;
    line-height: 1.45;
}

.rrp-app .rrp-field-error svg {
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    margin-top: 1px;
}

/* The panel- or form-level error: a save that failed, an invite that was
   refused. Used in ten places and — until now — defined in none of them, so
   every one of those messages rendered as unstyled body text. */
.rrp-inline-error {
    display: grid;
    gap: 2px;
    padding: 10px 12px;
    border: 1px solid color-mix(in srgb, var(--rrp-danger) 35%, var(--rrp-paper));
    border-left: 4px solid var(--rrp-danger);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger-deep);
    font-size: 12.5px;
    font-weight: 650;
    line-height: 1.5;
}

.rrp-app .btn {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 16px;
    border: 1px solid transparent;
    border-radius: var(--rrp-radius-control);
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
    line-height: 1.25;
    text-decoration: none;
    cursor: pointer;
}

.rrp-app .btn.primary {
    background: var(--rrp-navy);
    color: #fff;
}

.rrp-app .btn.ghost {
    border-color: var(--rrp-line-strong);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
}

.rrp-app .btn.danger {
    border-color: color-mix(in srgb, var(--rrp-danger) 35%, var(--rrp-paper));
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger-deep);
}

/* A text action that sits inside a row without competing with the step's one
   real button — used for Change, Remove and Read it again. */
.rrp-app .btn.link {
    min-height: 0;
    padding: 0;
    background: none;
    color: var(--rrp-ink);
    font-size: 12px;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.rrp-app .btn.link.is-danger {
    color: var(--rrp-danger-deep);
}

.rrp-app .btn:disabled,
.rrp-app .btn[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
}

.rrp-app .check-row {
    display: flex;
    min-height: 44px;
    align-items: center;
    gap: 10px;
    padding: 7px 0;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 650;
    cursor: pointer;
}

/* The native controls do not pick up the portal's radius, line colour or
   focus ring, so they are drawn here instead of tinted with accent-color. */
.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"]) {
    display: grid;
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    place-items: center;
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    border: 1.5px solid var(--rrp-control-line);
    border-radius: 6px;
    background: var(--rrp-paper);
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease;
}

.rrp-app .check-row input[type="radio"] {
    border-radius: 50%;
}

.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"])::before {
    width: 11px;
    height: 11px;
    background: var(--rrp-control-on-ink);
    clip-path: polygon(14% 46%, 0 60%, 40% 100%, 100% 22%, 86% 10%, 38% 72%);
    content: "";
    transform: scale(0);
    transition: transform 0.12s ease;
}

.rrp-app .check-row input[type="radio"]::before {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    clip-path: none;
}

.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"]):checked {
    border-color: var(--rrp-control-on);
    background: var(--rrp-control-on);
}

.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"]):checked::before {
    transform: scale(1);
}

/* Deliberately no outline override here: a 0.28-alpha green ring sat well below
   3:1. The global focus rule already covers these controls. */
.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"]):focus-visible {
    outline-offset: 2px;
}

.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"]):disabled {
    background: var(--rrp-canvas);
    cursor: not-allowed;
}

.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"]):disabled:checked {
    background: var(--rrp-line-strong);
    border-color: var(--rrp-line-strong);
}

.rrp-app .check-row :is(input[type="checkbox"], input[type="radio"]):disabled + * {
    color: var(--rrp-muted);
}

.rrp-app .rrp-fieldset {
    margin: 0 0 14px;
    padding: 0;
    border: 0;
}

.rrp-app .rrp-fieldset legend {
    margin-bottom: 6px;
    padding: 0;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 750;
}

.rrp-app .check-row span small {
    display: block;
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 550;
}

.rrp-app .rrp-field-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 14px;
}

@media (max-width: 560px) {
    .rrp-app .rrp-field-grid {
        grid-template-columns: 1fr;
    }
}

/* Business sub-navigation: left rail on desktop, scrollable pills on mobile. */
.rrp-app .rrp-business {
    display: grid;
    grid-template-columns: 236px minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

.rrp-app .rrp-subnav {
    display: flex;
    flex-direction: column;
    gap: 6px;
    position: sticky;
    top: 16px;
}

.rrp-app .rrp-subnav__item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 11px 13px;
    border: 1px solid transparent;
    border-radius: 12px;
    background: transparent;
    text-align: left;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}

.rrp-app .rrp-subnav__item:hover {
    background: color-mix(in srgb, var(--rrp-navy) 6%, var(--rrp-paper));
}

.rrp-app .rrp-subnav__item.is-active {
    background: color-mix(in srgb, var(--rrp-navy) 8%, var(--rrp-paper));
    border-color: color-mix(in srgb, var(--rrp-navy) 22%, var(--rrp-line-strong));
}

.rrp-app .rrp-subnav__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 9px;
    background: color-mix(in srgb, var(--rrp-navy) 8%, var(--rrp-paper));
    color: var(--rrp-ink);
}

.rrp-app .rrp-subnav__item.is-active .rrp-subnav__icon {
    background: var(--rrp-navy);
    color: #fff;
}

.rrp-app .rrp-subnav__label {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.rrp-app .rrp-subnav__label strong {
    font-size: 14px;
    font-weight: 750;
    color: var(--rrp-ink);
}

.rrp-app .rrp-subnav__label small {
    font-size: 11.5px;
    color: var(--rrp-muted);
}

.rrp-app .rrp-subnav__body {
    min-width: 0;
}

/* The dropdown is the phone presentation of the rail; desktop hides it. */
.rrp-app .rrp-subnav-select {
    display: none;
    position: relative;
}

.rrp-app .rrp-subnav-select__button {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 44px;
    padding: 11px 13px;
    border: 1px solid var(--rrp-control-line);
    border-radius: 12px;
    background: var(--rrp-paper);
    text-align: left;
    cursor: pointer;
}

.rrp-app .rrp-subnav-select__chev {
    width: 18px;
    height: 18px;
    flex: none;
    /* The label is only as wide as its text, so without this the chevron sits
       against the end of the words rather than at the edge of the control. */
    margin-left: auto;
    color: var(--rrp-muted);
    transition: transform .15s ease;
}

.rrp-app .rrp-subnav-select.is-open .rrp-subnav-select__chev {
    transform: rotate(180deg);
}

.rrp-app .rrp-subnav-select__scrim {
    position: fixed;
    inset: 0;
    z-index: var(--rrp-z-sticky);
}

.rrp-app .rrp-subnav-select__menu {
    position: absolute;
    z-index: calc(var(--rrp-z-sticky) + 1);
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    list-style: none;
    margin: 0;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 12px;
    background: var(--rrp-paper);
    box-shadow: 0 14px 34px rgba(16, 24, 40, .16);
}

@media (max-width: 780px) {
    .rrp-app .rrp-business {
        grid-template-columns: 1fr;
        gap: 14px;
    }

    .rrp-app .rrp-subnav-select {
        display: block;
    }

    .rrp-app .rrp-subnav {
        display: none;
    }
}

.rrp-app .rrp-callout {
    display: flex;
    gap: 12px;
    padding: 14px 16px;
    margin: 0 0 16px;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, #c47f00 34%, var(--rrp-line-strong));
    background: color-mix(in srgb, #c47f00 10%, var(--rrp-paper));
}

.rrp-app .rrp-callout__icon {
    font-size: 18px;
    line-height: 1.2;
}

.rrp-app .rrp-callout strong {
    display: block;
    color: var(--rrp-ink);
    font-size: 13.5px;
    font-weight: 750;
}

.rrp-app .rrp-callout p {
    margin: 2px 0 0;
    color: var(--rrp-muted);
    font-size: 12.5px;
    line-height: 1.45;
}

.rrp-app .rrp-selfbill-toggle {
    margin-bottom: 12px;
}

.rrp-app .rrp-field-hint {
    display: block;
    margin-top: 4px;
    color: var(--rrp-muted);
    font-size: 11.5px;
}

/* The line under the tiles: the demoted buckets. It wraps rather than shrinks,
   so a repairer with three demoted buckets on a phone gets two rows instead of
   three cramped columns. */
.rrp-app .rrp-home-viewall {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px 14px;
    margin: -4px 0 16px;
}

.rrp-app .rrp-home-viewall a {
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
    padding: 4px 2px;
}

.rrp-app .rrp-home-viewall a:hover {
    text-decoration: underline;
}

/* The buckets that did not make the tile row. Deliberately light: these are the
   ones with nothing to decide, so they read as a footnote to the tiles. */
.rrp-app .rrp-home-more {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 12px;
    margin: 0;
    padding: 0;
}

.rrp-app .rrp-home-more a {
    color: var(--rrp-muted);
    font-weight: 600;
}

.rrp-app .rrp-home-more a:hover {
    color: var(--rrp-ink);
}

.rrp-app .rrp-home-more b {
    color: var(--rrp-ink);
    font-variant-numeric: tabular-nums;
}

/* Every bucket empty. Said plainly rather than left as a blank space where the
   tiles were, which reads as something having failed to load. */
.rrp-app .rrp-home-clear {
    margin: 0 0 12px;
    padding: 16px 18px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-surface-muted);
    color: var(--rrp-muted);
    font-size: 13.5px;
}

/* Home money strip: this month invoiced/approved, sitting directly above the
   earnings chart it summarises. Hidden without ViewSensitiveInvoices. */
.rrp-app .rrp-home-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
    margin-bottom: 14px;
}

.rrp-app .rrp-home-stat {
    display: grid;
    gap: 2px;
    padding: 12px 14px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-soft);
    color: inherit;
    text-decoration: none;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.rrp-app .rrp-home-stat:hover {
    border-color: var(--rrp-navy-soft);
    box-shadow: var(--rrp-shadow-card);
}

.rrp-app .rrp-home-stat small {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.rrp-app .rrp-home-stat strong {
    color: var(--rrp-ink);
    font-family: var(--rrp-font-heading);
    font-size: clamp(19px, 2vw, 24px);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.15;
}

.rrp-app .rrp-home-stat--good strong {
    color: var(--rrp-green-dark);
}

.rrp-app .rrp-home-stat span {
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 600;
}

.rrp-app .rrp-home-earnings {
    margin-top: 16px;
}

/* Home "finish setting up" checklist. */
.rrp-app .rrp-setup-panel {
    position: relative;
    margin-bottom: 14px;
}

.rrp-app .rrp-setup__item {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Each step carries its own dismiss, sitting beside the link row. */
.rrp-app .rrp-setup__dismiss {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--rrp-muted);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.rrp-app .rrp-setup__dismiss:hover {
    background: color-mix(in srgb, var(--rrp-navy) 8%, var(--rrp-paper));
    color: var(--rrp-ink);
}

.rrp-app .rrp-setup__lead {
    margin: 0 0 10px;
}

.rrp-app .rrp-setup__collapse {
    margin-top: 10px;
}

/* The checklist once it has made its point: one line, openable, dismissable.
   Sized and coloured to sit below the resume card rather than compete with it. */
.rrp-app .rrp-setup-banner {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 14px;
    padding: 8px 10px 8px 14px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-app .rrp-setup-banner__text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 8px;
}

/* .btn.link zeroes its own min-height, which is right for a link inside a
   sentence and wrong for the one control that opens this. Named alongside
   .btn.link because that rule would otherwise outspecify this one. */
.rrp-app .btn.link.rrp-setup-banner__show {
    flex: none;
    min-height: var(--tap-min);
    padding-inline: 6px;
}

.rrp-app .rrp-setup-banner__text strong {
    color: var(--rrp-ink);
    font-size: 13.5px;
}

.rrp-app .rrp-setup-banner__text small {
    color: var(--rrp-muted);
    font-size: 12px;
}

.rrp-app .rrp-setup {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.rrp-app .rrp-setup__row {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 12px;
    text-decoration: none;
    background: var(--rrp-paper);
    transition: border-color .15s ease, background .15s ease;
}

.rrp-app .rrp-setup__row:hover {
    border-color: color-mix(in srgb, var(--rrp-navy) 30%, var(--rrp-line-strong));
    background: color-mix(in srgb, var(--rrp-navy) 4%, var(--rrp-paper));
}

.rrp-app .rrp-setup__check {
    flex: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--rrp-navy) 35%, var(--rrp-line-strong));
}

.rrp-app .rrp-setup__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.rrp-app .rrp-setup__text strong {
    color: var(--rrp-ink);
    font-size: 14px;
    font-weight: 750;
}

.rrp-app .rrp-setup__text small {
    color: var(--rrp-muted);
    font-size: 12px;
    line-height: 1.4;
}

.rrp-app .rrp-setup__go {
    flex: none;
    color: var(--rrp-ink);
    font-size: 18px;
    font-weight: 700;
    opacity: .5;
    transition: opacity .15s ease, transform .15s ease;
}

.rrp-app .rrp-setup__row:hover .rrp-setup__go {
    opacity: 1;
    transform: translateX(2px);
}

.rrp-app .rrp-fieldset--nested {
    margin-top: 4px;
    padding: 12px 14px;
    border: 1px solid var(--rrp-border, #e2e6ee);
    border-radius: 12px;
    background: var(--rrp-surface-muted, #f7f9fc);
}

.rrp-app .rrp-logo {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin: 4px 0 16px;
    padding: 12px 14px;
    border: 1px dashed var(--rrp-border, #cfd6e4);
    border-radius: 12px;
}

.rrp-app .rrp-logo__label {
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 750;
}

.rrp-app .rrp-logo__img {
    max-height: 56px;
    max-width: 200px;
    object-fit: contain;
    border-radius: 8px;
    background: #fff;
    padding: 4px 8px;
    border: 1px solid var(--rrp-border, #e2e6ee);
}

.rrp-app .rrp-logo__name {
    color: var(--rrp-muted);
    font-size: 13px;
    font-weight: 600;
    word-break: break-all;
}

.rrp-app .rrp-logo__actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

.rrp-app .rrp-logo__actions .btn.ghost {
    cursor: pointer;
}

/* ── CRM notes (Summary tab notes group) ───────────────────────────────────── */
.rrp-app .crm-notes {
    display: flex;
    max-height: 320px;
    min-width: 0;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
}

/* Each note stacks top to bottom: author, then message, then a bottom-right
   timestamp on its own line. Keeping the name and time off one shared row stops
   a long author and the date from colliding and overflowing on a narrow phone. */
.rrp-app .crm-note {
    display: flex;
    min-width: 0;
    flex-direction: column;
    padding: 9px 11px;
    border: 1px solid var(--rrp-line);
    border-radius: 9px;
    background: var(--rrp-canvas);
}

.rrp-app .crm-note-author {
    min-width: 0;
    margin-bottom: 2px;
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 750;
    overflow-wrap: anywhere;
}

.rrp-app .crm-note-body {
    color: var(--rrp-ink);
    font-size: 12.5px;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

.rrp-app .crm-note-time {
    align-self: flex-end;
    margin-top: 4px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    white-space: nowrap;
}

/* The note a notification deep link points at: it keeps a green ring and wash
   so it stays findable, and pulses three times on arrival to pull the eye. */
.rrp-app .crm-note--new {
    border-color: var(--rrp-green);
    background: var(--rrp-green-wash);
    animation: rrp-note-pulse 1.1s ease-in-out 3;
}

@keyframes rrp-note-pulse {
    50% {
        background: color-mix(in srgb, var(--rrp-green) 22%, var(--rrp-canvas));
        box-shadow: 0 0 0 4px color-mix(in srgb, var(--rrp-green) 28%, transparent);
    }
}

@media (prefers-reduced-motion: reduce) {
    .rrp-app .crm-note--new {
        animation: none;
    }
}

/* ── Component: Skeleton ───────────────────────────────────────────────────── */
.rrp-skeleton {
    display: grid;
    width: 100%;
    gap: 10px;
}

.rrp-skeleton__item {
    display: flex;
    min-height: 74px;
    overflow: hidden;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-skeleton--text .rrp-skeleton__item {
    min-height: auto;
    border: 0;
    background: transparent;
}

.rrp-skeleton__accent {
    width: 5px;
    flex: 0 0 auto;
    background: var(--rrp-line);
}

.rrp-skeleton__body {
    display: grid;
    width: 100%;
    align-content: center;
    gap: 9px;
    padding: 16px;
}

.rrp-skeleton__line {
    display: block;
    width: 88%;
    height: 10px;
    overflow: hidden;
    border-radius: 999px;
    background: var(--rrp-line);
}

.rrp-skeleton__line::after {
    display: block;
    width: 50%;
    height: 100%;
    /* The sweep has to be lighter than the skeleton on light and on dark, so it
       is derived from the paper surface rather than being a fixed white. */
    background: linear-gradient(90deg,
        transparent,
        color-mix(in srgb, var(--rrp-paper) 90%, transparent),
        transparent);
    content: "";
    transform: translateX(-100%);
    animation: rrp-shimmer 1.35s ease-in-out infinite;
}

.rrp-skeleton__line--title {
    width: 54%;
    height: 14px;
}

.rrp-skeleton__line--short {
    width: 34%;
}

@keyframes rrp-shimmer {
    to {
        transform: translateX(220%);
    }
}

/* ── Component: State (empty / error / loading) ────────────────────────────── */
.rrp-state {
    display: flex;
    width: min(100%, 560px);
    min-width: 0;
    flex-direction: column;
    align-items: center;
    margin-inline: auto;
    padding: clamp(28px, 8vw, 52px) 20px;
    color: var(--rrp-ink);
    text-align: center;
}

.rrp-state__icon {
    display: grid;
    width: 50px;
    height: 50px;
    place-items: center;
    margin-bottom: 15px;
    border-radius: 14px;
    background: var(--rrp-green-wash);
    color: var(--rrp-ink);
}

.rrp-state--error .rrp-state__icon {
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger);
}

.rrp-state__icon svg {
    width: 26px;
    height: 26px;
    stroke-width: 1.9;
}

.rrp-state__spinner,
.rrp-bootstrap__spinner {
    width: 24px;
    height: 24px;
    border: 3px solid rgba(12, 36, 72, 0.2);
    border-top-color: var(--rrp-green);
    border-radius: 50%;
    animation: rrp-spin 700ms linear infinite;
}

@keyframes rrp-spin {
    to {
        transform: rotate(360deg);
    }
}

.rrp-state__title {
    margin: 0;
    color: var(--rrp-ink);
    font-size: clamp(20px, 5vw, 27px);
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.18;
}

.rrp-state__message {
    max-width: 48ch;
    margin: 8px 0 0;
    color: var(--rrp-muted);
    font-size: 13px;
    line-height: 1.55;
}

.rrp-state__content {
    width: 100%;
    margin-top: 16px;
}

.rrp-state__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-top: 20px;
}

.rrp-state__action {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    padding: 10px 16px;
    border: 1px solid transparent;
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-navy);
    color: #fff;
    font-weight: 800;
    text-decoration: none;
    cursor: pointer;
}

.rrp-not-found {
    display: grid;
    min-height: min(62vh, 560px);
    place-items: center;
    padding: 16px;
}

/* ── Component: Pagination — the list footer: previous/status/next plus the
      quiet per-page selector on the right. ──────────────────────────────────── */
.rrp-pagination {
    display: flex;
    min-width: 0;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
    padding: 14px 0;
}

.rrp-pagination__button {
    display: inline-flex;
    min-width: 0;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px 12px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 750;
    cursor: pointer;
}

.rrp-pagination__button svg {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    stroke-width: 2.2;
}

.rrp-pagination__button:disabled {
    opacity: 0.48;
    cursor: not-allowed;
}

.rrp-pagination__status {
    color: var(--rrp-muted);
    font-size: 11.5px;
    text-align: center;
    white-space: nowrap;
}

.rrp-pagination__status strong {
    color: var(--rrp-ink);
}

.rrp-pagination__size {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 7px;
    margin-left: auto;
}

.rrp-pagination__size label {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    white-space: nowrap;
}

.rrp-pagination__size select {
    min-height: 44px;
    padding: 8px 10px;
    border: 1px solid var(--rrp-control-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: var(--rrp-text-sm);
    font-weight: 750;
    cursor: pointer;
}

/* ── Shared MFA panel, hosted on the warm canvas ───────────────────────────── */
.rrp-mfa-page {
    min-width: 0;
    padding: 8px 0 28px;
}

.rrp-app .mfa-setup-shell {
    padding-top: 18px;
}

.rrp-app .mfa-setup-shell__badge {
    border-color: var(--rrp-green-line);
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
}

.rrp-app .mfa-setup-shell__title,
.rrp-app .mfa-setup-panel__title {
    color: var(--rrp-ink);
}

.rrp-app .mfa-setup-shell__summary,
.rrp-app .mfa-setup-panel__lead,
.rrp-app .mfa-setup-panel__loading {
    color: var(--rrp-muted);
}

.rrp-app .mfa-setup-panel__card {
    border-color: var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    box-shadow: var(--rrp-shadow-soft);
}

.rrp-app .mfa-setup-panel__alert--ok {
    border-color: var(--rrp-green-line);
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
}

/* ── Auth (login) — hybrid look over the shared LoginShell ─────────────────── */
.rrp-auth {
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--rrp-canvas);
    color: var(--rrp-ink);
    -webkit-font-smoothing: antialiased;
}

.rrp-auth .login-split {
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--rrp-canvas);
}

.rrp-auth .login-panel-left {
    min-width: 0;
    padding: clamp(34px, 5vw, 68px);
    background:
        radial-gradient(circle at 88% 90%, rgba(28, 196, 120, 0.22), transparent 34%),
        linear-gradient(145deg, var(--rrp-navy) 0%, var(--rrp-navy-soft) 100%);
    color: #fff;
}

.rrp-auth .login-panel-left::before,
.rrp-auth .login-panel-left::after {
    display: none;
}

.rrp-auth #repairer-login-canvas {
    position: absolute;
    inset: 0;
    opacity: 0.22;
    pointer-events: none;
}

.rrp-auth .login-panel-content {
    position: relative;
    z-index: 1;
    justify-content: space-between;
    padding: 0;
}

.rrp-auth-hero {
    width: min(100%, 560px);
    margin-block: auto;
}

.rrp-auth-hero .rrp-product {
    font-size: clamp(30px, 3.6vw, 44px);
}

.rrp-auth-hero h2 {
    max-width: 520px;
    margin: 26px 0 0;
    color: #fff;
    font-size: clamp(30px, 4vw, 46px);
    font-weight: 800;
    letter-spacing: -0.04em;
    line-height: 1.05;
}

.rrp-auth-hero > p {
    max-width: 480px;
    margin: 16px 0 0;
    color: rgba(255, 255, 255, 0.78);
    font-size: 15px;
    line-height: 1.6;
}

.rrp-auth-hero__points {
    display: grid;
    gap: 10px;
    margin: 26px 0 0;
    padding: 0;
    list-style: none;
}

.rrp-auth-hero__points li {
    position: relative;
    padding-left: 28px;
    color: rgba(255, 255, 255, 0.92);
    font-size: 13.5px;
    font-weight: 650;
}

.rrp-auth-hero__points li::before {
    position: absolute;
    top: 0.12em;
    left: 0;
    display: grid;
    width: 20px;
    height: 20px;
    place-items: center;
    border-radius: 50%;
    background: var(--rrp-green);
    color: var(--rrp-navy);
    content: "\2713";
    font-size: 12px;
    font-weight: 900;
}

.rrp-auth-hero__foot {
    display: grid;
    gap: 8px;
    padding-top: 20px;
    border-top: 1px solid rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.7);
    font-size: 12px;
}

.rrp-auth-hero__foot .rrp-brand-logo {
    width: 118px;
    opacity: 0.85;
}

.rrp-auth-hero__foot a {
    color: #fff;
    font-weight: 750;
    text-underline-offset: 3px;
}

.rrp-auth .login-panel-right {
    width: min(100%, 500px);
    min-width: min(100%, 420px);
    padding: clamp(24px, 5vw, 56px);
    border: 0;
    background: var(--rrp-paper);
}

.rrp-auth-form {
    width: 100%;
}

.rrp-auth-form__brand {
    display: none;
    margin-bottom: 34px;
}

.rrp-auth-form__brand .rrp-product {
    font-size: 27px;
}

.rrp-auth-form__brand span {
    display: block;
    margin-top: 9px;
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 750;
}

.rrp-auth .login-form-wrap {
    max-width: 390px;
    gap: 0;
}

.rrp-auth .login-form-header {
    margin-bottom: 24px;
}

.rrp-auth .login-form-title {
    color: var(--rrp-ink);
    font-family: var(--rrp-font-heading);
    font-size: 27px;
    font-weight: 800;
    letter-spacing: -0.025em;
}

.rrp-auth .login-form-sub,
.rrp-auth .login-footer {
    color: var(--rrp-muted);
}

.rrp-auth .login-field label {
    color: var(--rrp-ink);
    font-weight: 750;
}

.rrp-auth .login-field input {
    min-height: 46px;
    border-color: var(--rrp-control-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: 16px;
}

/* :focus rather than :focus-visible, because a text field should show its focus
   on click as well as on keyboard entry. Uses the shared ring tokens so it
   matches every other focusable control and stays visible on both themes. */
.rrp-auth .login-field input:focus {
    border-color: var(--rrp-focus);
    outline: 3px solid var(--rrp-focus);
    outline-offset: 1px;
    box-shadow: 0 0 0 6px var(--rrp-focus-halo);
}

.rrp-auth .login-btn {
    min-height: 46px;
    border-radius: var(--rrp-radius-control);
}

.rrp-auth .login-btn:not(.login-btn--ghost):not(.login-btn-sso) {
    background: var(--rrp-navy);
    color: #fff;
}

.rrp-auth .login-btn:not(.login-btn--ghost):not(.login-btn-sso):hover:not(:disabled) {
    background: var(--rrp-navy-soft);
    color: #fff;
}

.rrp-auth .login-btn--ghost,
.rrp-auth .login-btn-sso {
    border-color: var(--rrp-line-strong);
    color: var(--rrp-ink);
}

.rrp-auth .login-links a,
.rrp-auth .login-identity-change {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    color: var(--rrp-muted);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Shorter target than the standalone links so it stays tight to the password box. */
.rrp-auth .login-forgot {
    display: inline-flex;
    min-height: 32px;
    align-items: center;
    color: var(--rrp-muted);
    font-size: 13px;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.rrp-auth .login-error {
    border-color: color-mix(in srgb, var(--rrp-danger) 45%, var(--rrp-paper));
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger);
}

.rrp-auth-form__legal {
    display: flex;
    justify-content: center;
    gap: 16px;
    margin-top: 8px;
}

.rrp-auth-form__legal a {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 700;
    text-underline-offset: 3px;
}

/* ── Loading, handoff and framework error states ───────────────────────────── */
.rrp-system-shell,
.rrp-bootstrap {
    display: flex;
    width: 100%;
    min-height: 100vh;
    min-height: 100dvh;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: max(24px, env(safe-area-inset-top))
        max(18px, env(safe-area-inset-right))
        max(24px, env(safe-area-inset-bottom))
        max(18px, env(safe-area-inset-left));
    background: var(--rrp-canvas);
    color: var(--rrp-ink);
    text-align: center;
}

.rrp-system-shell .rrp-product,
.rrp-bootstrap .rrp-product {
    color: var(--rrp-ink);
    font-size: clamp(27px, 6vw, 34px);
}

.rrp-system-shell .rrp-state {
    flex: 0 0 auto;
    padding-block: 14px;
}

.rrp-system-shell__byline,
.rrp-bootstrap__byline {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 650;
}

.rrp-bootstrap__spinner {
    margin-top: 10px;
}

.rrp-bootstrap p {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 13px;
    font-weight: 700;
}

#blazor-error-ui {
    position: fixed;
    z-index: var(--rrp-z-error);
    right: 14px;
    bottom: max(14px, env(safe-area-inset-bottom));
    left: 14px;
    display: none;
    max-width: 620px;
    min-height: 52px;
    align-items: center;
    gap: 12px;
    margin-inline: auto;
    padding: 10px 10px 10px 14px;
    border: 1px solid #e3b6bd;
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-pop);
    color: var(--rrp-ink);
    font-family: var(--rrp-font-body);
    font-size: 13px;
    font-weight: 650;
}

#blazor-error-ui .reload {
    display: inline-flex;
    min-height: 40px;
    align-items: center;
    margin-left: auto;
    color: var(--rrp-ink);
    font-weight: 800;
}

#blazor-error-ui .dismiss {
    display: inline-grid;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
}

/* ── Component: Update prompt — a cached build has a newer version waiting ──── */
#rrp-update-ui {
    position: fixed;
    z-index: var(--rrp-z-error);
    right: 14px;
    bottom: max(14px, env(safe-area-inset-bottom));
    left: 14px;
    display: flex;
    max-width: 620px;
    min-height: 52px;
    align-items: center;
    gap: 12px;
    margin-inline: auto;
    padding: 10px 10px 10px 14px;
    border: 1px solid var(--rrp-green-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-pop);
    color: var(--rrp-ink);
    font-family: var(--rrp-font-body);
    font-size: 13px;
    font-weight: 650;
}

#rrp-update-ui[hidden] {
    display: none;
}

#rrp-update-ui .update {
    display: inline-flex;
    min-height: 40px;
    align-items: center;
    margin-left: auto;
    padding-inline: 14px;
    border: 0;
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
    font: inherit;
    font-weight: 800;
    cursor: pointer;
}

#rrp-update-ui .dismiss {
    display: inline-grid;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: var(--rrp-radius-control);
    background: transparent;
    color: var(--rrp-ink);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
}


/* ── Toasts stay clear of shell navigation ─────────────────────────────────── */
/* The toast host sits outside .rrp-app, so it re-declares the shared aliases for
   itself. These were hardcoded light values, which meant a toast raised on the
   dark theme arrived as a white card with near-black text; they now point at the
   same tokens as the rest of the portal and follow whichever theme is active. */
.rrp-toast-region {
    --surface: var(--rrp-paper);
    --surface2: var(--rrp-canvas);
    --border: var(--rrp-line-strong);
    --text: var(--rrp-muted);
    --text-bright: var(--rrp-ink);
    --rrn-navy: var(--rrp-navy);
    --green: var(--rrp-green);
    --green-dim: var(--rrp-green-wash);
    --red: var(--rrp-danger);
    --red-dim: var(--rrp-danger-soft);
    --teal: var(--rrp-navy-soft);
    font-family: var(--rrp-font-body);
}

/* Toasts drop from the top, under the sticky job bar — the bottom of the
   screen belongs to the dock, the floating flow bar and the sticky primary
   action, and a toast sitting on top of those blocks the very button the
   repairer is trying to press. */
.rrp-toast-region .app-toast-stack {
    top: calc(64px + env(safe-area-inset-top));
    right: max(10px, env(safe-area-inset-right));
    bottom: auto;
    left: max(10px, env(safe-area-inset-left));
    width: auto;
    max-width: 390px;
    margin-left: auto;
}

.rrp-toast-region .app-toast-close {
    width: 44px;
    height: 44px;
}

.rrp-toast-region .app-toast {
    grid-template-columns: 34px minmax(0, 1fr) 44px;
}

/* ── Keyboard shortcuts ────────────────────────────────────────────────────────
   The ? sheet, and the user-menu entry that leads to it. Both are for a keyboard
   and a fine pointer, so both stay out of the way of a touch phone — see the
   rule inside the hover block below, which is the only place the menu entry is
   shown. */
.rrp-app .rrp-keys {
    margin: 0;
    display: grid;
    gap: 2px;
}

.rrp-app .rrp-keys__group {
    margin: 16px 0 6px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.rrp-app .rrp-keys__group:first-of-type {
    margin-top: 0;
}

.rrp-app .rrp-keys__row {
    display: grid;
    grid-template-columns: 92px minmax(0, 1fr);
    gap: 12px;
    align-items: baseline;
    padding: 7px 0;
    border-top: 1px solid var(--rrp-line);
}

.rrp-app .rrp-keys__row dt {
    display: flex;
    gap: 4px;
}

.rrp-app .rrp-keys__row dd {
    margin: 0;
    color: var(--rrp-ink);
    font-size: 12.5px;
}

.rrp-app .rrp-keys kbd,
.rrp-app .rrp-user__keys kbd {
    padding: 2px 7px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas-sunk);
    color: var(--rrp-ink);
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 700;
    line-height: 1.5;
}

/* The menu entry is a button among links, so it has to be talked back into
   looking like them. Hidden until the hover block below says otherwise. */
.rrp-app .rrp-user__keys {
    display: none;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

/* The running build, quietly at the foot of the account menu — the answer to
   "has this device picked the update up yet?". */
.rrp-app .rrp-user__version {
    padding: 6px 14px 8px;
    border-top: 1px solid var(--rrp-line);
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    letter-spacing: 0.02em;
}

/* ── Hover refinements ─────────────────────────────────────────────────────── */
@media (hover: hover) and (pointer: fine) {
    .rrp-app .rrp-user__keys {
        display: flex;
    }

    .rrp-nav--rail .rrp-nav__link:hover {
        background: rgba(255, 255, 255, 0.07);
        color: #fff;
    }

    .rrp-nav--dock .rrp-nav__link:hover {
        color: var(--rrp-ink);
    }

    .rrp-action:hover,
    .rrp-minirow:hover,
    /* Hover tints mix the ink into the surface, which darkens on the light
       theme and lightens on the dark one from a single declaration. */
    .rrp-resume:hover {
        background: color-mix(in srgb, var(--rrp-ink) 4%, var(--rrp-paper));
    }

    .rrp-primary:hover:not(:disabled),
    .rrp-state__action:hover,
    .rrp-app .btn.primary:hover:not(:disabled) {
        background: var(--rrp-navy-soft);
    }

    .rrp-app .btn.ghost:hover:not(:disabled),
    .rrp-pagination__button:hover:not(:disabled),
    .rrp-more > summary:hover {
        border-color: var(--rrp-control-line);
        background: var(--rrp-canvas);
    }

    .rrp-app .check-row:hover
        :is(input[type="checkbox"], input[type="radio"]):not(:checked):not(:disabled) {
        border-color: var(--rrp-navy-soft);
    }

    .rrp-app .btn.danger:hover:not(:disabled) {
        border-color: color-mix(in srgb, var(--rrp-danger) 45%, var(--rrp-paper));
        background: color-mix(in srgb, var(--rrp-danger) 14%, var(--rrp-paper));
    }

    .rrp-app .rrp-flow-bar__prev:hover:not(:disabled) {
        background: color-mix(in srgb, var(--rrp-navy) 12%, var(--rrp-mustard));
    }

    .rrp-notify > a:hover {
        background: var(--rrp-canvas);
    }

    .rrp-notify.is-unread > a:hover {
        background: color-mix(in srgb, var(--rrp-green) 12%, var(--rrp-paper));
    }

    .rrp-menu :is(button, a):hover {
        background: var(--rrp-canvas);
    }

    .rrp-gsearch__result:hover,
    .rrp-gsearch__all:hover {
        background: var(--rrp-canvas);
    }
}

/* ── Desktop ≥ 761px: navy rail shell, two-column overview, full journey ───── */
@media (min-width: 761px) {
    .rrp-app {
        display: grid;
        grid-template-columns: 224px minmax(0, 1fr);
        flex-direction: initial;
    }

    .rrp-sidebar {
        position: relative;
        z-index: var(--rrp-z-rail);
        display: flex;
        min-width: 0;
        flex-direction: column;
        padding: 24px 15px 16px;
        padding-top: max(24px, env(safe-area-inset-top));
        padding-left: max(15px, env(safe-area-inset-left));
        background: var(--rrp-navy);
        color: #fff;
    }

    .rrp-sidebar > .rrp-product {
        margin: 2px 8px 30px;
    }

    .rrp-topbar {
        min-height: 64px;
        padding: 9px clamp(18px, 3vw, 34px);
        border-bottom: 1px solid var(--rrp-line-strong);
        background: color-mix(in srgb, var(--rrp-paper) 96%, transparent);
    }

    .rrp-topbar__brand {
        display: none;
    }

    .rrp-user > summary {
        padding-right: 9px;
        color: var(--rrp-ink);
    }

    .rrp-user > summary:hover {
        background: var(--rrp-canvas);
    }

    .rrp-user__avatar {
        border: 0;
        background: var(--rrp-navy);
        color: #fff;
    }

    .rrp-user__name {
        display: block;
        color: var(--rrp-ink);
    }

    .rrp-user__name small {
        color: var(--rrp-muted);
        opacity: 1;
    }

    .rrp-user > summary > svg {
        display: block;
        color: var(--rrp-muted);
    }

    .rrp-nav--dock {
        display: none;
    }

    .rrp-gsearch {
        flex: 0 1 400px;
        /* Desktop puts the finder where the empty top-left used to be. */
        order: -1;
    }

    .rrp-gsearch__toggle {
        display: none;
    }

    .rrp-gsearch__box {
        display: flex;
    }

    .rrp-gsearch__box kbd {
        display: block;
    }

    .rrp-page {
        padding: clamp(22px, 3.2vw, 40px);
    }

    .rrp-pagehead {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 24px;
        margin-bottom: 20px;
    }

    .rrp-pagehead h1 {
        font-size: clamp(25px, 3.1vw, 36px);
    }

    .rrp-avail {
        width: auto;
        min-width: 264px;
    }

    .rrp-overview-grid {
        display: grid;
        grid-template-columns: minmax(0, 1.4fr) minmax(300px, 1fr);
        gap: clamp(18px, 2.5vw, 30px);
        align-items: start;
        margin-bottom: 16px;
    }

    .rrp-side-col {
        display: block;
        min-width: 0;
    }

    .rrp-resume {
        margin-bottom: 16px;
        padding: 14px 16px;
    }

    .rrp-action {
        min-height: 64px;
        grid-template-columns: 52px minmax(0, 1fr) 20px;
        gap: 12px;
        padding: 12px 16px;
    }

    .rrp-action strong {
        font-size: 26px;
    }

    /* Dashboard tiles: the calm counts become a full-width row of cards. */
    .rrp-actions--tiles {
        display: grid;
        overflow: visible;
        grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
        gap: 14px;
        border: 0;
        border-radius: 0;
        margin-bottom: clamp(18px, 2.5vw, 26px);
        background: transparent;
    }

    .rrp-actions--tiles .rrp-action {
        min-height: 116px;
        grid-template-columns: minmax(0, 1fr) 20px;
        grid-template-rows: auto minmax(0, 1fr);
        align-items: start;
        padding: 15px 17px 14px;
        border: 1px solid var(--rrp-line-strong);
        border-radius: var(--rrp-radius-card);
        box-shadow: var(--rrp-shadow-soft);
    }

    .rrp-actions--tiles .rrp-action strong {
        font-size: 34px;
    }

    .rrp-actions--tiles .rrp-action > span {
        grid-row: 2;
        grid-column: 1 / -1;
        align-self: end;
        color: var(--rrp-muted);
        font-size: 11.5px;
        letter-spacing: 0.02em;
        text-transform: uppercase;
    }

    .rrp-actions--tiles .rrp-action > svg {
        grid-row: 1;
        grid-column: 2;
    }

    .rrp-actions--tiles .rrp-action.is-urgent {
        border-color: color-mix(in srgb, var(--rrp-danger) 34%, var(--rrp-line-strong));
    }

    .rrp-pills {
        display: flex;
    }

    .rrp-pills-select {
        display: none;
    }

    .rrp-search {
        margin-bottom: 18px;
    }

    /* Forms stop wasting desktop width: fields sit side by side where they
       fit, and the confirm button takes its own row. */
    .rrp-inline-form {
        max-width: 640px;
        grid-template-columns: repeat(auto-fit, minmax(216px, 1fr));
        gap: 10px 16px;
        align-items: end;
    }

    .rrp-inline-form > .btn {
        grid-column: 1 / -1;
        justify-self: start;
    }

    .rrp-dialog__fields--booking {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        align-items: end;
    }

    .rrp-search input {
        min-height: 54px;
        font-size: 14px;
    }

    .rrp-search > button {
        padding: 9px 18px;
    }

    .rrp-fmenu__toggle {
        padding: 8px 14px;
    }

    .rrp-fmenu__toggle > span {
        display: inline;
    }

    /* Desktop: the sheet becomes a right-anchored popover under the toggle. */
    .rrp-fmenu__panel {
        position: absolute;
        top: calc(100% + 8px);
        bottom: auto;
        inset-inline: auto 0;
        width: 344px;
        max-height: none;
        padding: 16px;
        border-radius: 12px;
        box-shadow: 0 16px 40px rgba(11, 30, 51, 0.16);
    }

    .rrp-journey {
        display: grid;
        margin-bottom: 34px;
        grid-auto-columns: minmax(0, 1fr);
        grid-auto-flow: column;
    }

    .rrp-jsum,
    .rrp-jfull {
        display: none !important;
    }

    .rrp-mfa-page {
        padding-top: 0;
    }

    .rrp-toast-region .app-toast-stack {
        top: calc(82px + env(safe-area-inset-top));
        right: max(18px, env(safe-area-inset-right));
        bottom: auto;
        left: auto;
        width: min(390px, calc(100vw - 36px));
        max-width: none;
    }
}

/* ── Component: Portal workforce ───────────────────────────────────────────── */
.rrp-workforce {
    display: grid;
    margin: 0;
}

.rrp-workforce__mode,
.rrp-workforce__centres {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
}

.rrp-workforce__mode .check-row {
    flex: 1 1 260px;
    align-items: flex-start;
}

.rrp-workforce__mode .check-row span {
    display: grid;
    gap: 3px;
}

.rrp-workforce__mode small,
.rrp-workforce__token p {
    color: var(--rrp-muted);
    font-size: 11.5px;
}

.rrp-workforce__form {
    display: grid;
    gap: 12px;
}

.rrp-workforce__section-actions,
.rrp-workforce__users-head,
.rrp-workforce__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
}

/* This one heads a list rather than closing a form, so it needs its space
   below the button rather than above it. */
.rrp-workforce__users-head {
    margin-top: 0;
    margin-bottom: 15px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--rrp-line);
}

.rrp-workforce__users-head > span {
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 650;
}

.rrp-workforce__result,
.rrp-workforce__notice,
.rrp-workforce__access-summary {
    display: grid;
    gap: 6px;
    padding: 12px;
    border-left: 3px solid var(--rrp-green);
    background: var(--rrp-canvas);
}

.rrp-workforce__result p {
    margin: 0;
}

.rrp-workforce__notice {
    margin-bottom: 12px;
    border-left-color: var(--rrp-orange);
}

/* Real table so Name / Role / Status stay in columns. overflow:visible so
   the last-row kebab menu is not clipped by the card. */
.rrp-workforce .rrp-panel {
    overflow: visible;
}

.rrp-user-table-wrap {
    width: 100%;
    overflow: visible;
}

.rrp-user-table {
    width: 100%;
    border-collapse: collapse;
}

.rrp-user-table th,
.rrp-user-table td {
    padding: 10px 8px;
    border-bottom: 1px solid var(--rrp-line);
    text-align: left;
    vertical-align: middle;
    overflow: visible;
}

.rrp-user-table th {
    padding-top: 0;
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 750;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.rrp-user-table tbody tr:last-child td {
    border-bottom: 0;
}

.rrp-user-table__actions {
    width: 44px;
    text-align: right;
    white-space: nowrap;
}

.rrp-userrow__who,
.rrp-userrow__meta {
    display: grid;
    gap: 1px;
    min-width: 0;
}

.rrp-userrow__who strong {
    color: var(--rrp-ink);
    font-size: 13.5px;
    font-weight: 750;
}

.rrp-userrow__meta strong {
    color: var(--rrp-ink);
    font-size: 12px;
    font-weight: 700;
}

.rrp-userrow__who small,
.rrp-userrow__meta small {
    overflow: hidden;
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-userrow__more {
    position: relative;
    display: inline-block;
}

.rrp-userrow__more summary {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    cursor: pointer;
    list-style: none;
}

.rrp-userrow__more summary::-webkit-details-marker {
    display: none;
}

.rrp-userrow__more summary svg {
    width: 17px;
    height: 17px;
}

.rrp-userrow__more .rrp-menu {
    z-index: var(--rrp-z-menu);
}

.rrp-user-table tbody tr:nth-last-child(-n+2) .rrp-menu {
    top: auto;
    bottom: calc(100% + 7px);
}

@media (max-width: 640px) {
    .rrp-user-table,
    .rrp-user-table tbody,
    .rrp-user-table tr,
    .rrp-user-table td {
        display: block;
        width: 100%;
    }

    .rrp-user-table thead {
        display: none;
    }

    .rrp-user-table tbody {
        display: grid;
        gap: 10px;
    }

    .rrp-user-table tr {
        padding: 4px 2px 8px;
        border-bottom: 1px solid var(--rrp-line);
    }

    .rrp-user-table tbody tr:last-child {
        border-bottom: 0;
    }

    .rrp-user-table td {
        display: grid;
        grid-template-columns: minmax(90px, 0.35fr) minmax(0, 1fr);
        gap: 10px;
        padding: 8px 0;
        border-bottom: 0;
    }

    .rrp-user-table td::before {
        content: attr(data-label);
        color: var(--rrp-muted);
        font-size: var(--rrp-text-3xs);
        font-weight: 750;
        letter-spacing: 0.04em;
        text-transform: uppercase;
    }

    .rrp-user-table__actions {
        width: auto;
        display: flex;
        justify-content: flex-end;
        white-space: normal;
    }

    .rrp-user-table__actions::before {
        display: none;
    }

    .rrp-user-table tbody tr:nth-last-child(-n+2) .rrp-menu {
        top: calc(100% + 7px);
        bottom: auto;
    }
}

@media (max-width: 760px) {
    .rrp-workforce__users-head {
        align-items: stretch;
    }

    .rrp-workforce__users-head .btn,
    .rrp-workforce__actions .btn {
        width: 100%;
    }
}

/* ── Component: Managed technician assignment ─────────────────────────────── */
.rrp-assignment-panel.is-unassigned {
    border-color: color-mix(in srgb, var(--rrp-orange) 50%, var(--rrp-line));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--rrp-orange) 10%, transparent);
}

.rrp-assignment-control {
    display: grid;
    grid-template-columns: minmax(180px, 1fr) auto;
    align-items: end;
    gap: 12px;
}

.rrp-assignment-control .field {
    margin: 0;
}

.rrp-reminder-snooze__form {
    display: grid;
    grid-template-columns: minmax(190px, .8fr) minmax(220px, 1.2fr);
    align-items: end;
    gap: 12px;
}

.rrp-reminder-snooze__form .field {
    margin: 0;
}

.rrp-reminder-snooze__actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    grid-column: 1 / -1;
}

@media (max-width: 760px) {
    .rrp-assignment-control,
    .rrp-reminder-snooze__form {
        grid-template-columns: 1fr;
    }

    .rrp-assignment-control .btn,
    .rrp-reminder-snooze__actions .btn {
        width: 100%;
    }

    .rrp-reminder-snooze__actions {
        display: grid;
        grid-column: auto;
    }
}

/* ── Component: Jobs view switch ───────────────────────────────────────────── */
.rrp-app .rrp-viewswitch {
    display: inline-flex;
    gap: 2px;
    margin: 0 0 14px;
    padding: 3px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 999px;
    background: var(--rrp-paper);
}

.rrp-app .rrp-viewswitch button {
    padding: 6px 16px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--rrp-muted);
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
}

.rrp-app .rrp-viewswitch button.is-active {
    background: var(--rrp-navy);
    color: #fff;
}

/* ── Component: Job calendar ───────────────────────────────────────────────── */
.rrp-app .rrp-cal {
    display: block;
    padding: 14px 15px 16px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-app .rrp-cal__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}

.rrp-app .rrp-cal__nav {
    display: flex;
    align-items: center;
    gap: 6px;
}

.rrp-app .rrp-cal__nav h2 {
    min-width: 168px;
    margin: 0;
    text-align: center;
    font-size: 16px;
    font-weight: 800;
}

.rrp-app .rrp-cal__nav .btn {
    padding: 4px 12px;
    font-size: 17px;
    line-height: 1.2;
}

.rrp-app .rrp-cal__weekdays {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 4px;
    margin-bottom: 4px;
}

.rrp-app .rrp-cal__weekdays span {
    text-align: center;
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.rrp-app .rrp-cal__grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 4px;
}

.rrp-app .rrp-cal__grid.is-loading {
    opacity: .55;
}
.rrp-app .rrp-cal__day--skeleton {
    pointer-events: none;
    border-radius: var(--rrp-radius-card, 10px);
    background: linear-gradient(
        100deg,
        var(--rrp-line, #e6e8ec) 30%,
        color-mix(in srgb, var(--rrp-line, #e6e8ec) 55%, var(--rrp-paper, #fff)) 50%,
        var(--rrp-line, #e6e8ec) 70%);
    background-size: 200% 100%;
    animation: rrp-cal-shimmer 1.2s ease-in-out infinite;
}
@keyframes rrp-cal-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
.rrp-app .rrp-cal__loading {
    margin: 12px 0 0;
    text-align: center;
    color: var(--rrp-muted);
    font-size: 13px;
}

.rrp-app .rrp-cal__day {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    min-height: 62px;
    padding: 6px 4px;
    border: 1px solid var(--rrp-line);
    border-radius: 10px;
    background: var(--rrp-paper);
    cursor: pointer;
    transition: border-color .12s ease, background .12s ease;
}

.rrp-app .rrp-cal__day:hover {
    border-color: var(--rrp-line-strong);
}

.rrp-app .rrp-cal__day.is-outside {
    opacity: .4;
}

.rrp-app .rrp-cal__day.is-today {
    border-color: var(--rrp-navy);
}

.rrp-app .rrp-cal__day.is-selected {
    background: color-mix(in srgb, var(--rrp-navy) 8%, var(--rrp-paper));
    border-color: var(--rrp-navy);
}

.rrp-app .rrp-cal__date {
    font-size: 13px;
    font-weight: 700;
}

.rrp-app .rrp-cal__day.is-today .rrp-cal__date {
    color: var(--rrp-ink);
}

.rrp-app .rrp-cal__dots {
    display: flex;
    gap: 3px;
}

.rrp-app .rrp-cal__count {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 700;
}

/* One colour, no key. A dot marks that there is work on the day; the number
   beside it says how much. */
.rrp-app .rrp-cal__dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    flex: none;
    border-radius: 50%;
    background: var(--rrp-navy);
}

/* The day's jobs: a sheet lifted over the grid on a phone, a column beside it
   from 980px. Below that the grid can fill the screen, so a panel appended
   underneath changed something the reader had already scrolled past. */
.rrp-app .rrp-cal__side {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: var(--rrp-z-panel);
    max-height: 74vh;
    padding: 0 14px 14px;
    overflow-y: auto;
    overscroll-behavior: contain;
    border-top: 1px solid var(--rrp-line-strong);
    border-radius: 16px 16px 0 0;
    background: var(--rrp-paper);
    box-shadow: 0 -12px 32px rgb(15 27 45 / .18);
    transform: translateY(102%);
    visibility: hidden;
    transition: transform .26s cubic-bezier(.32, .72, .32, 1);
}

.rrp-app .rrp-cal__side.is-open {
    transform: translateY(0);
    visibility: visible;
}

.rrp-app .rrp-cal__scrim {
    position: fixed;
    inset: 0;
    z-index: var(--rrp-z-dock);
    background: rgb(15 27 45 / .34);
    opacity: 0;
    pointer-events: none;
    transition: opacity .22s ease;
}

.rrp-app .rrp-cal__scrim.is-open {
    opacity: 1;
    pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
    .rrp-app .rrp-cal__side,
    .rrp-app .rrp-cal__scrim {
        transition: none;
    }
}

.rrp-app .rrp-cal__side-empty {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 12.5px;
}

.rrp-app .rrp-cal__day-head {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    padding: 13px 0 10px;
    background: var(--rrp-paper);
}

.rrp-app .rrp-cal__day-titles {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 10px;
    min-width: 0;
}

.rrp-app .rrp-cal__day-head h3 {
    margin: 0;
    font-size: 15px;
    font-weight: 800;
}

.rrp-app .rrp-cal__day-titles span {
    color: var(--rrp-muted);
    font-size: 12.5px;
}

.rrp-app .rrp-cal__day-close {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 9px;
    background: var(--rrp-paper);
    color: var(--rrp-muted);
    cursor: pointer;
}

.rrp-app .rrp-cal__day-close:hover {
    border-color: var(--rrp-navy);
    color: var(--rrp-ink);
}

@media (min-width: 980px) {
    .rrp-app .rrp-cal__body {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 340px;
        gap: 20px;
        align-items: start;
    }

    .rrp-app .rrp-cal__main {
        min-width: 0;
    }

    /* Sticky so a long list of jobs stays beside the day that opened it. */
    .rrp-app .rrp-cal__side {
        position: sticky;
        top: 14px;
        z-index: auto;
        max-height: none;
        padding: 0 0 0 20px;
        overflow: visible;
        border: 0;
        border-left: 1px solid var(--rrp-line);
        border-radius: 0;
        background: transparent;
        box-shadow: none;
        transform: none;
        visibility: visible;
    }

    .rrp-app .rrp-cal__scrim {
        display: none;
    }

    .rrp-app .rrp-cal__day-head {
        padding-top: 0;
        background: transparent;
    }

    /* The column is narrow by design, so a job's actions drop under its
       details rather than squeezing the registration to nothing. */
    .rrp-app .rrp-cal__side .rrp-cal__jobs li {
        flex-wrap: wrap;
    }

    .rrp-app .rrp-cal__side .rrp-cal__job-actions {
        width: 100%;
        justify-content: flex-end;
    }

    .rrp-app .rrp-cal__side .rrp-cal__book-open {
        width: 100%;
    }
}

.rrp-app .rrp-cal__jobs {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0 0 12px;
    padding: 0;
    list-style: none;
}

.rrp-app .rrp-cal__jobs li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 10px;
}

.rrp-app .rrp-cal__job {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.rrp-app .rrp-cal__job strong {
    font-size: 13.5px;
    font-weight: 800;
}

.rrp-app .rrp-cal__job small {
    overflow: hidden;
    color: var(--rrp-muted);
    font-size: 11.5px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-app .rrp-cal__job-actions {
    display: flex;
    flex: none;
    align-items: center;
    gap: 8px;
}

.rrp-app .rrp-cal__book {
    display: grid;
    gap: 10px;
    padding: 13px 14px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 12px;
    background: color-mix(in srgb, var(--rrp-navy) 4%, var(--rrp-paper));
}

.rrp-app .rrp-cal__book .field {
    margin: 0;
}

.rrp-app .rrp-cal__book-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

@media (max-width: 640px) {
    .rrp-app .rrp-cal {
        padding: 12px 10px 14px;
    }

    .rrp-app .rrp-cal__day {
        min-height: 52px;
        padding: 5px 2px;
    }

    .rrp-app .rrp-cal__nav h2 {
        min-width: 0;
        font-size: 15px;
    }

    .rrp-app .rrp-cal__jobs li {
        flex-wrap: wrap;
    }

    .rrp-app .rrp-cal__job-actions {
        width: 100%;
        justify-content: flex-end;
    }

    .rrp-app .rrp-cal__book-actions .btn {
        flex: 1 1 0;
    }
}

/* ── Component: Job reference tabs ─────────────────────────────────────────── */
.rrp-app .rrp-jobtabs-panel {
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-app .rrp-jobtabs {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding: 10px;
    background: var(--rrp-paper);
    border-bottom: 1px solid var(--rrp-line);
    scrollbar-width: none;
}

.rrp-app .rrp-jobtabs::-webkit-scrollbar {
    display: none;
}

/* Pills on a track, not faint underlined text — the tabs were disappearing
   into the panel, so an unselected tab now has its own chip and the selected
   one is a solid navy pill. */
.rrp-app .rrp-jobtabs__item {
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: 7px;
    padding: 8px 13px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 999px;
    background: var(--rrp-paper);
    color: var(--rrp-muted);
    font-size: 13px;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
    transition: color .12s ease, background .12s ease, border-color .12s ease;
}

.rrp-app .rrp-jobtabs__item:hover {
    color: var(--rrp-ink);
    border-color: var(--rrp-navy-soft);
}

.rrp-app .rrp-jobtabs__item.is-active {
    background: var(--rrp-navy);
    border-color: var(--rrp-navy);
    color: #fff;
    box-shadow: var(--rrp-shadow-soft);
}

.rrp-app .rrp-jobtabs__icon {
    display: inline-flex;
    opacity: .8;
}

.rrp-app .rrp-jobtabs__item.is-active .rrp-jobtabs__icon {
    opacity: 1;
}

/* The Chat launcher tab carries the same green unread-count badge as the job
   bar's chat control, so the reference strip and the bar always agree. */
.rrp-app .rrp-jobtabs__item--chat {
    position: relative;
}

.rrp-app .rrp-jobtabs__chat-count {
    display: inline-grid;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    place-items: center;
    border-radius: 999px;
    background: var(--rrp-green);
    color: #fff;
    font-size: var(--rrp-text-3xs);
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    line-height: 1;
}

.rrp-app .rrp-jobtabs__body {
    padding: 14px 15px 15px;
}

@media (max-width: 780px) {
    /* On a phone the strip becomes an app-style bar: equal columns, icon with a
       tiny label under each, active section as a solid navy block. Every name is
       always visible and the equal columns mean the row can never overflow the
       screen, whatever the device width. It stays inside the white card so the
       tabs read as part of one boxed panel with the content beneath them. */
    .rrp-app .rrp-jobtabs {
        display: grid;
        grid-auto-flow: column;
        grid-auto-columns: 1fr;
        gap: 4px;
        padding: 8px;
        overflow: visible;
    }

    .rrp-app .rrp-jobtabs__item {
        position: relative;
        flex-direction: column;
        justify-content: center;
        gap: 4px;
        min-width: 0;
        padding: 7px 3px 6px;
        border: 0;
        border-radius: 10px;
        background: transparent;
        font-size: var(--rrp-text-3xs);
    }

    .rrp-app .rrp-jobtabs__item.is-active {
        background: var(--rrp-navy);
        color: #fff;
        box-shadow: none;
    }

    /* Ellipsis is a safety net for system-level text scaling: the longest label
       fits a six-column row down to 320px at normal size, but inflated text on a
       narrow screen clips gracefully instead of breaking the grid. */
    .rrp-app .rrp-jobtabs__text {
        display: block;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* In the stacked app-bar layout the count would push the label down, so it
       floats to the tab's top-right corner instead. */
    .rrp-app .rrp-jobtabs__chat-count {
        position: absolute;
        top: 2px;
        right: 8px;
    }

    .rrp-app .rrp-jobtabs__body {
        padding: 13px 14px 14px;
    }
}

/* ── Component: Job invoices sheet ─────────────────────────────────────────── */
.rrp-job-invoices__facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 10px 14px;
    margin-bottom: 12px;
}

.rrp-job-invoices__facts > span {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.rrp-job-invoices__facts small {
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 650;
}

.rrp-job-invoices__facts strong {
    color: var(--rrp-ink);
    font-size: 14px;
    font-weight: 800;
}

.rrp-job-invoices__facts em {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-style: normal;
}

.rrp-job-invoices__files {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.rrp-job-invoices__files li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 11px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 10px;
}

.rrp-job-invoices__file {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.rrp-job-invoices__file strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    font-weight: 700;
}

.rrp-job-invoices__file small {
    color: var(--rrp-muted);
    font-size: 11px;
}

/* ── Component: Repair evidence workflow ───────────────────────────────────── */
.rrp-workflow {
    display: grid;
    gap: 18px;
    min-width: 0;
}

.rrp-workflow__section :where(h2, h3) {
    margin: 2px 0 4px;
    color: var(--rrp-ink);
    font-family: var(--rrp-font-heading);
    font-size: 16px;
}

.rrp-workflow__status {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    min-height: 28px;
    padding: 4px 9px;
    border: 1px solid var(--rrp-line);
    border-radius: 999px;
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 750;
}

.rrp-workflow__status.is-complete {
    border-color: color-mix(in srgb, var(--rrp-green) 45%, var(--rrp-line));
    background: color-mix(in srgb, var(--rrp-green) 10%, var(--rrp-paper));
    color: var(--rrp-green-deep);
}

.rrp-workflow__status.is-caution,
.rrp-workflow .is-caution {
    color: var(--rrp-amber);
}

.rrp-workflow__status.is-error {
    border-color: color-mix(in srgb, var(--rrp-danger) 40%, var(--rrp-line));
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger);
}

.rrp-travel-directions {
    display: inline-flex;
    align-items: center;
    gap: 7px;
}

/* Two ways to say yes and a quiet way out. On a phone they stack so the
   thumb is not choosing between three targets on one line. */
.modal-foot .rrp-travel-confirm__cancel {
    margin-right: auto;
}

@media (max-width: 560px) {
    .rrp-app .modal-foot {
        flex-wrap: wrap;
        justify-content: center;
    }

    .rrp-app .modal-foot .rrp-travel-confirm {
        flex: 1 1 100%;
        justify-content: center;
    }

    .modal-foot .rrp-travel-confirm__cancel {
        order: 1;
        margin: 4px auto 0;
    }
}

.rrp-travel-directions__icon {
    font-size: 14px;
    line-height: 1;
    transform: translateY(1px);
}

.rrp-workflow__section {
    display: grid;
    gap: 14px;
    padding: 18px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-card);
}

.rrp-file-button {
    position: relative;
    overflow: hidden;
    cursor: pointer;
}

.rrp-file-button input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.rrp-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid rgba(12, 36, 72, 0.2);
    border-top-color: var(--rrp-green);
    border-radius: 50%;
    animation: rrp-spin 700ms linear infinite;
}

/* The photos taken for the job, laid out as a plain grid — only what exists,
   no dashed placeholders demanding more. Tap a tile to see it full size. */
.rrp-photos-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: 8px;
}

.rrp-photos-grid__tile {
    position: relative;
    overflow: hidden;
    aspect-ratio: 1;
    padding: 0;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
    cursor: pointer;
}

.rrp-photos-grid__tile img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.rrp-photos-grid__tile:hover img {
    opacity: 0.9;
}

.rrp-photos-grid__pending {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: 6px;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 700;
    text-align: center;
    overflow-wrap: anywhere;
}

/* Taking photos lives in the body of the stage, not the flow bar — the bar
   below only ever continues. A full-width tile in the invoice drop box's
   family, so it reads as the screen's own affordance rather than a lone
   button floating mid-screen. */
.rrp-app .rrp-photos__capture {
    display: grid;
    gap: 3px;
    justify-items: center;
    width: 100%;
    margin-top: 12px;
    padding: 20px 24px;
    border: 1.5px dashed var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    cursor: pointer;
    text-align: center;
}

/* The border change is the hover affordance; the focus ring itself comes from the
   shared rule. This used to say `outline: none`, which left keyboard users with
   only a 1.5px border-colour shift to find the capture control by. */
.rrp-app .rrp-photos__capture:hover:not(:disabled),
.rrp-app .rrp-photos__capture:focus-visible {
    border-color: var(--rrp-navy);
}

.rrp-app .rrp-photos__capture:disabled {
    cursor: default;
    opacity: 0.55;
}

.rrp-app .rrp-photos__capture svg {
    width: 24px;
    height: 24px;
    margin-bottom: 3px;
}

.rrp-app .rrp-photos__capture strong {
    font-size: 14px;
    font-weight: 800;
}

.rrp-app .rrp-photos__capture small {
    color: var(--rrp-muted);
    font-size: 12.5px;
    font-weight: 600;
}

.rrp-app .rrp-photos__status {
    margin: 10px 0 0;
    padding: 8px 12px;
    border-radius: 10px;
    font-size: 13px;
    line-height: 1.4;
    border: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
}
/* Tokenised so both states follow the theme. These previously carried six
   literal hexes, which meant the evidence banners stayed light-on-light. */
.rrp-app .rrp-photos__status.is-ok {
    border-color: color-mix(in srgb, var(--rrp-green-dark) 40%, var(--rrp-line));
    background: color-mix(in srgb, var(--rrp-green) 12%, var(--rrp-paper));
    color: var(--rrp-green-dark);
}

.rrp-app .rrp-photos__status.is-warn {
    border-color: var(--rrp-amber-line);
    background: color-mix(in srgb, var(--rrp-mustard) 14%, var(--rrp-paper));
    color: var(--rrp-amber);
}

/* -- Photo stages (the capture checklist as photo tiles on the job page) --
   The FNOL hub gallery brought onto the job: a wrapping grid of square
   tiles, 2–3+ per row depending on width, scrolling with the page so a
   30-photo job stays usable. Before a photo is in, the tile is just its
   title and a placeholder icon; afterwards it is the picture itself with a
   status badge. The whole tile is a button — tapping it opens the camera on
   that stage. */
.rrp-app .rrp-capstages {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
    gap: 10px;
}

.rrp-app .rrp-capstage {
    display: grid;
    gap: 5px;
    padding: 0;
    border: none;
    background: none;
    color: var(--rrp-ink);
    cursor: pointer;
    text-align: left;
}

.rrp-app .rrp-capstage:disabled {
    cursor: default;
    opacity: 0.6;
}

.rrp-app .rrp-capstage__thumb {
    position: relative;
    display: grid;
    place-items: center;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border: 1.5px dashed var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
}

/* A photo is in: the picture replaces the dashed "still to take" framing. */
.rrp-app .rrp-capstage.is-done .rrp-capstage__thumb,
.rrp-app .rrp-capstage.is-queued .rrp-capstage__thumb {
    border-style: solid;
    border-color: var(--rrp-line);
}

.rrp-app button.rrp-capstage:hover:not(:disabled) .rrp-capstage__thumb,
.rrp-app button.rrp-capstage:focus-visible .rrp-capstage__thumb {
    border-color: var(--rrp-navy);
}

.rrp-app .rrp-capstage__thumb img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.rrp-app .rrp-capstage.is-done .rrp-capstage__icon {
    color: var(--rrp-green-dark);
}

.rrp-app .rrp-capstage.is-queued .rrp-capstage__icon {
    color: var(--rrp-amber);
}

/* The status word, pinned over the tile's bottom edge. Ink scrim behind so
   it reads over any photograph. */
.rrp-app .rrp-capstage__badge {
    position: absolute;
    bottom: 5px;
    left: 5px;
    padding: 2px 7px;
    border-radius: 999px;
    background: rgba(15, 26, 42, 0.72);
    color: #ffffff;
    font-size: 11px;
    font-weight: 700;
    line-height: 1.3;
}

.rrp-app .rrp-capstage__badge.is-done {
    background: var(--rrp-green-dark);
}

.rrp-app .rrp-capstage__badge.is-queued {
    background: var(--rrp-amber);
}

.rrp-app .rrp-capstage__label {
    overflow: hidden;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

/* Offline stand-in for an additional photo whose picture lives on the
   server: present but not interactive. */
.rrp-app .rrp-capstage--placeholder {
    cursor: default;
}

/* The Continue button while queued photos are still sending. */
.rrp-app .rrp-flow-bar__busy {
    display: inline-block;
    width: 13px;
    height: 13px;
    margin-right: 7px;
    border: 2px solid color-mix(in srgb, currentColor 35%, transparent);
    border-top-color: currentColor;
    border-radius: 50%;
    vertical-align: -2px;
    animation: rrp-flowbar-spin 0.7s linear infinite;
}

@keyframes rrp-flowbar-spin {
    to { transform: rotate(360deg); }
}

/* The required photos still to take, named plainly. */
/* One main action per stage, with the alternative route beside it as a link. */
.rrp-photo-viewer {
    display: grid;
    gap: 12px;
}

.rrp-photo-viewer img {
    display: block;
    width: 100%;
    max-height: min(65vh, 720px);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
    object-fit: contain;
}

.rrp-photo-viewer > div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
}

.rrp-photo-viewer__pending {
    display: grid;
    width: 100%;
    aspect-ratio: 4 / 3;
    max-height: min(65vh, 720px);
    border: 1px dashed var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: 12.5px;
    font-weight: 700;
    place-items: center;
}

.rrp-photo-viewer small,
.rrp-photo-viewer__count {
    color: var(--rrp-muted);
    font-size: 11.5px;
}

.rrp-photo-viewer__count {
    align-self: center;
    margin-inline: auto;
}

.rrp-workflow__decision {
    display: grid;
    gap: 5px;
    padding: 13px 14px;
    border: 1px solid var(--rrp-line-strong);
    border-left: 4px solid var(--rrp-navy);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
}

.rrp-workflow__decision strong {
    color: var(--rrp-ink);
    font-size: 13.5px;
}

.rrp-workflow__decision p {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 12.5px;
    line-height: 1.5;
}

.rrp-workflow__decision.is-caution {
    border-left-color: var(--rrp-amber);
}

.rrp-workflow__decision.is-error {
    border-left-color: var(--rrp-danger);
}

/* A decision that ends in a button — e.g. "set up self-billing" from the
   invoice method that isn't ready yet. */
.rrp-workflow__decision--action .btn {
    justify-self: start;
    margin-top: 4px;
    text-decoration: none;
}

/* Lines the repairer removed, kept reachable so they can be restored. */
.rrp-invoice-removed {
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
}

.rrp-invoice-removed > summary {
    padding: 10px 12px;
    color: var(--rrp-muted);
    cursor: pointer;
    font-size: 11.5px;
    font-weight: 750;
}

.rrp-invoice-removed__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 12px;
    border-top: 1px solid var(--rrp-line);
    background: color-mix(in srgb, var(--rrp-canvas) 75%, transparent);
}

.rrp-invoice-removed__item > span {
    display: grid;
    gap: 2px;
}

.rrp-invoice-removed__item small {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
}

/* ── Add-line dialog: kind radios and a searchable rate schedule ────────────── */
.rrp-kind-radios {
    display: flex;
    gap: 22px;
    margin: 0 0 14px;
    padding: 0;
    border: 0;
}

.rrp-kind-radios legend {
    margin-bottom: 6px;
    padding: 0;
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
}

/* The send-back check-in's question sits below the "RRN asked" recap;
   without its own gap the two read as one run-on block. */
.rrp-sendback__ask {
    margin-top: 18px;
}

.rrp-kind-radios__opt {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--rrp-ink);
    cursor: pointer;
    font-size: 13.5px;
    font-weight: 700;
}

.rrp-kind-radios__opt input {
    width: 17px;
    height: 17px;
    margin: 0;
    accent-color: var(--rrp-navy);
    cursor: pointer;
}

.rrp-option-list {
    display: grid;
    max-height: 240px;
    margin-top: 8px;
    overflow-y: auto;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
}

.rrp-option-list__none {
    margin: 0;
    padding: 12px 14px;
    color: var(--rrp-muted);
    font-size: 12.5px;
}

.rrp-option-list__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 12px;
    border: 0;
    border-top: 1px solid var(--rrp-line);
    background: transparent;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.rrp-option-list__item:first-child {
    border-top: 0;
}

.rrp-option-list__item:hover:not(:disabled) {
    background: var(--rrp-canvas);
}

.rrp-option-list__item.is-selected {
    background: color-mix(in srgb, var(--rrp-navy) 7%, var(--rrp-paper));
    box-shadow: inset 3px 0 var(--rrp-navy);
}

.rrp-option-list__copy {
    display: grid;
    gap: 1px;
    min-width: 0;
}

.rrp-option-list__copy > span {
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 700;
}

.rrp-option-list__copy small {
    color: var(--rrp-muted);
    font-size: 11px;
}

.rrp-option-list__item strong {
    flex: 0 0 auto;
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}

/* ── Invoice method: a compact segmented control in the screen head ────────── */
.rrp-invoice-method {
    display: inline-flex;
    flex: 0 0 auto;
    gap: 2px;
    padding: 3px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 999px;
    background: var(--rrp-canvas);
}

.rrp-invoice-method__opt {
    padding: 6px 13px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--rrp-muted);
    font: inherit;
    font-size: 12px;
    font-weight: 750;
    white-space: nowrap;
    cursor: pointer;
}

/* The chosen method is unmistakable: solid navy, white text. The old white-
   on-canvas pill read as barely different from the unselected side. */
.rrp-invoice-method__opt.is-active {
    background: var(--rrp-navy);
    color: #fff;
    box-shadow: var(--rrp-shadow-soft);
}

.rrp-invoice-method__opt:disabled {
    cursor: default;
}

/* ── Invoice detail (left) + document preview (right) on desktop ──────────── */
.rrp-invoice-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
}

.rrp-invoice-layout__details {
    display: grid;
    gap: 12px;
    align-content: start;
    min-width: 0;
}

.rrp-invoice-layout__preview {
    position: relative;
    display: flex;
    min-width: 0;
    min-height: 320px;
    align-items: stretch;
    justify-content: center;
    overflow: hidden;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-canvas);
}

/* Self-bill mode is nothing but the draft itself, full width. */
.rrp-invoice-layout.is-single {
    grid-template-columns: minmax(0, 1fr);
}

.rrp-invoice-layout.is-single .rrp-invoice-layout__preview {
    min-height: 460px;
}

/* Before anything is uploaded the whole screen is this one box — the ledger,
   number field and preview only appear once there is something to show. */
.rrp-upload-drop {
    display: grid;
    gap: 4px;
    justify-items: center;
    align-content: center;
    min-height: 240px;
    padding: 32px 24px;
    border: 1.5px dashed var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    text-align: center;
    font-size: 14px;
    font-weight: 800;
}

.rrp-upload-drop:hover,
.rrp-upload-drop:focus-within {
    border-color: var(--rrp-navy);
    background: var(--rrp-canvas);
}

.rrp-upload-drop small {
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 650;
}

.rrp-upload-drop__icon {
    display: grid;
    width: 34px;
    height: 34px;
    place-items: center;
    margin-bottom: 6px;
    border-radius: 999px;
    background: var(--rrp-navy);
    color: #fff;
    font-size: 18px;
    line-height: 1;
}

/* The input covers the whole box so a dropped file lands anywhere on it. */
.rrp-upload-drop input[type="file"] {
    position: absolute;
    inset: 0;
    z-index: 2;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.rrp-upload-drop > strong,
.rrp-upload-drop > small,
.rrp-upload-drop > span {
    pointer-events: none;
}

/* ── Component: RepairerEvidenceWorkflow — added/changed part photo ──
   The take-or-upload photo field inside the Add/Edit line popups. It mirrors
   the Photos-stage capability in a compact, in-modal control so evidencing a
   part is never a popup within a popup. */
.rrp-line-photo {
    display: grid;
    gap: 7px;
    margin-block: 2px 4px;
}

.rrp-line-photo__label {
    font-size: 13px;
    font-weight: 800;
    color: var(--rrp-ink);
}

.rrp-line-photo__pick {
    display: grid;
    gap: 2px;
    justify-items: center;
    align-content: center;
    min-height: 108px;
    padding: 14px 18px;
    border: 1.5px dashed var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    text-align: center;
    font-size: 14px;
    font-weight: 800;
    min-block-size: var(--tap-min);
}

.rrp-line-photo__pick:hover,
.rrp-line-photo__pick:focus-within {
    border-color: var(--rrp-navy);
    background: var(--rrp-canvas);
}

.rrp-line-photo__pick small {
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 650;
}

.rrp-line-photo__pick > strong,
.rrp-line-photo__pick > small,
.rrp-line-photo__pick > span {
    pointer-events: none;
}

.rrp-line-photo__icon {
    display: grid;
    width: 30px;
    height: 30px;
    place-items: center;
    margin-bottom: 4px;
    border-radius: 999px;
    background: var(--rrp-navy);
    color: #fff;
    font-size: 17px;
    line-height: 1;
}

.rrp-line-photo__preview {
    display: grid;
    gap: 7px;
    justify-items: start;
}

.rrp-line-photo__preview img {
    width: 100%;
    max-height: 220px;
    object-fit: contain;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
}

.rrp-line-photo__done {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    font-size: 13px;
    font-weight: 800;
    color: var(--rrp-green-deep);
}

.rrp-line-photo__replace {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    align-self: start;
    min-block-size: var(--tap-min);
    padding: 8px 14px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 800;
    cursor: pointer;
}

.rrp-line-photo__replace:hover,
.rrp-line-photo__replace:focus-within {
    border-color: var(--rrp-navy);
    background: var(--rrp-canvas);
}

/* While the AI reads the upload, this panel is the whole screen: the ledger
   and reconciliation only appear once there are read figures to show. */
.rrp-ai-reading {
    display: grid;
    gap: 6px;
    justify-items: center;
    align-content: center;
    min-height: 240px;
    padding: 32px 24px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    text-align: center;
}

.rrp-ai-reading strong {
    color: var(--rrp-ink);
    font-size: 14px;
    font-weight: 800;
    overflow-wrap: anywhere;
}

.rrp-ai-reading p {
    max-width: 360px;
    margin: 0;
    color: var(--rrp-muted);
    font-size: 12.5px;
    line-height: 1.5;
}

.rrp-ai-reading__spark {
    width: 30px;
    height: 30px;
    margin-bottom: 6px;
    color: var(--rrp-ink);
    animation: rrp-spark-think 1.6s ease-in-out infinite;
}

@keyframes rrp-spark-think {
    0%, 100% {
        transform: scale(1) rotate(0deg);
        opacity: 0.55;
    }
    50% {
        transform: scale(1.18) rotate(12deg);
        opacity: 1;
    }
}

/* The scroller between the pane and the document: zooming widens the
   document past the pane and this layer pans it. Flex so an unzoomed frame
   still stretches to the pane's full height, exactly as before. */
.rrp-preview-scroll {
    display: flex;
    flex: 1;
    min-width: 0;
    align-items: stretch;
    justify-content: center;
    overflow: auto;
}

/* Once zoomed the document is wider than the pane; centring a too-wide flex
   child clips its left edge, so zooming pins it to the start instead. */
.rrp-invoice-layout__preview.is-zooming .rrp-preview-scroll {
    justify-content: flex-start;
}

/* The embedded viewer's own toolbar is hidden, so these are the only zoom
   controls the preview has. They float over the pane, clear of the scroll. */
.rrp-preview-zoom {
    position: absolute;
    z-index: 3;
    top: 10px;
    right: 10px;
    display: inline-flex;
    overflow: hidden;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 8px;
    background: var(--rrp-paper);
    box-shadow: 0 4px 14px rgba(15, 34, 58, 0.14);
}

.rrp-preview-zoom button {
    width: 32px;
    height: 30px;
    border: 0;
    background: transparent;
    color: var(--rrp-ink);
    cursor: pointer;
    font-size: 16px;
    font-weight: 800;
    line-height: 1;
}

.rrp-preview-zoom button + button {
    border-left: 1px solid var(--rrp-line);
}

.rrp-preview-zoom button:hover:not(:disabled) {
    background: var(--rrp-canvas);
}

.rrp-preview-zoom button:disabled {
    cursor: default;
    opacity: 0.35;
}

.rrp-preview-zoom button.rrp-preview-zoom__level {
    width: auto;
    min-width: 52px;
    padding: 0 8px;
    font-size: 11.5px;
    letter-spacing: 0.02em;
}

.rrp-invoice-preview__frame {
    width: 100%;
    min-height: 320px;
    border: 0;
    background: #fff;
}

.rrp-invoice-preview__img {
    width: 100%;
    max-height: 620px;
    object-fit: contain;
    background: #fff;
}

.rrp-invoice-preview__empty {
    display: grid;
    gap: 10px;
    align-content: center;
    justify-items: center;
    padding: 24px;
    color: var(--rrp-muted);
    text-align: center;
    font-size: 13px;
    font-weight: 650;
}

.rrp-invoice-preview__glyph {
    font-size: 34px;
    line-height: 1;
    opacity: 0.7;
}

@media (min-width: 860px) {
    .rrp-invoice-layout {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
        align-items: start;
    }

    .rrp-invoice-layout__preview {
        position: sticky;
        top: 12px;
        min-height: 460px;
    }

    .rrp-invoice-preview__frame {
        min-height: 460px;
    }
}

.rrp-invoice-checking {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 700;
}

.rrp-invoice-modal__summary {
    display: flex;
    align-items: start;
    justify-content: space-between;
    gap: 16px;
    padding: 11px 12px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-canvas);
}

.rrp-invoice-modal__summary > span {
    display: grid;
    flex: 0 0 auto;
    justify-items: end;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
}

.rrp-invoice-modal__summary b {
    color: var(--rrp-ink);
    font-size: 14px;
}

/* ── Reconciliation ledger: one table, accounting-style ─────────────────────
   A row per supplier invoice, a slim add-row instead of a drop zone, and a
   totals footer that reconciles what was read against the parts lines. One
   verdict line carries the match state for the whole set. */
.rrp-ledger {
    overflow: hidden;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-ledger__head {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 14px;
    border-bottom: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

/* The "Read" column label sits over the amounts, clear of the remove button. */
.rrp-ledger__head span:last-child {
    padding-right: 46px;
}

.rrp-ledger__empty {
    margin: 0;
    padding: 14px;
    color: var(--rrp-muted);
    font-size: 12.5px;
    line-height: 1.5;
}

.rrp-ledger__row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-top: 1px solid var(--rrp-line);
}

.rrp-ledger__head + .rrp-ledger__row {
    border-top: 0;
}

.rrp-ledger__row.is-previewing {
    background: var(--rrp-canvas);
    box-shadow: inset 3px 0 var(--rrp-navy);
}

/* The file cell is the preview button — tapping a row shows that document. */
.rrp-ledger__file {
    display: grid;
    flex: 1 1 auto;
    gap: 2px;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.rrp-ledger__file strong {
    overflow: hidden;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 750;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-ledger__file:hover:not(:disabled) strong {
    text-decoration: underline;
}

.rrp-ledger__file small {
    color: var(--rrp-muted);
    font-size: 11.5px;
    line-height: 1.4;
}

.rrp-ledger__file small.is-warn {
    color: var(--rrp-danger);
    font-weight: 650;
}

.rrp-ledger__amount {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 7px;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.rrp-ledger__remove {
    display: grid;
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--rrp-muted);
    font: inherit;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
}

.rrp-ledger__remove:hover:not(:disabled) {
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger);
}

/* Works as both a file-drop label and a plain button (regenerate). */
.rrp-ledger__add {
    position: relative;
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 11px 14px;
    border: 0;
    border-top: 1px dashed var(--rrp-line-strong);
    background: transparent;
    color: var(--rrp-ink);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    font-weight: 800;
    text-align: left;
}

.rrp-ledger__add:hover:not(:disabled),
.rrp-ledger__add:focus-within {
    background: var(--rrp-canvas);
}

.rrp-ledger__add:disabled {
    cursor: default;
    opacity: 0.55;
}

/* The input covers the whole row so dropping a file onto it works; the copy
   is decoration and must never swallow the click or the drop. */
.rrp-ledger__add input[type="file"] {
    position: absolute;
    inset: 0;
    z-index: 2;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.rrp-ledger__add > span,
.rrp-ledger__add > small {
    pointer-events: none;
}

.rrp-ledger__add-icon {
    display: grid;
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    place-items: center;
    border-radius: 999px;
    background: var(--rrp-navy);
    color: #fff;
    font-size: 13px;
    line-height: 1;
}

.rrp-ledger__add small {
    margin-left: auto;
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 650;
    text-align: right;
}

/* Reconciliation figures read like the foot of an invoice: right-aligned,
   the difference under its own rule, no tinted band. The right padding
   lines the figures up under the rows' amount column. */
.rrp-ledger__totals {
    display: grid;
    gap: 3px;
    justify-content: end;
    padding: 10px 46px 10px 14px;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-paper);
}

.rrp-ledger__totalrow {
    display: grid;
    grid-template-columns: auto minmax(90px, auto);
    gap: 28px;
    align-items: baseline;
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 650;
}

.rrp-ledger__totalrow span {
    text-align: right;
}

.rrp-ledger__totalrow strong {
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 750;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.rrp-ledger__totalrow.is-difference {
    margin-top: 4px;
    padding-top: 7px;
    border-top: 2px solid var(--rrp-navy);
}

.rrp-ledger__totalrow.is-difference span {
    color: var(--rrp-ink);
    font-weight: 800;
}

/* The check's one-line verdict for the whole reconciliation. */
/* The AI's read of an uploaded invoice: one full-width line that leads the
   screen, above the number field and preview. Same kinds as the ledger
   verdict, just louder. */
.rrp-ai-verdict {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0 0 14px;
    padding: 12px 14px;
    border-radius: var(--rrp-radius-card);
    font-size: 14px;
    font-weight: 700;
    line-height: 1.45;
}

.rrp-ai-verdict.is-ok {
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
}

.rrp-ai-verdict.is-warn {
    background: color-mix(in srgb, var(--rrp-amber) 14%, var(--rrp-paper));
    color: var(--rrp-ink);
}

.rrp-ai-verdict.is-pending {
    border: 1px solid var(--rrp-line);
    background: var(--rrp-paper);
    color: var(--rrp-muted);
}

.rrp-ai-verdict__spark {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    margin-top: 1px;
}

.rrp-ai-verdict.is-pending .rrp-ai-verdict__spark {
    animation: rrp-spark-pulse 1.2s ease-in-out infinite;
}

.rrp-ledger__verdict {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 0 14px 12px;
    padding: 9px 11px;
    border-radius: var(--rrp-radius-control);
    font-size: 12.5px;
    font-weight: 650;
    line-height: 1.45;
}

.rrp-ledger__verdict.is-ok {
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
}

.rrp-ledger__verdict.is-warn {
    background: color-mix(in srgb, var(--rrp-amber) 14%, var(--rrp-paper));
    color: var(--rrp-ink);
}

.rrp-ledger__verdict.is-pending {
    border: 1px solid var(--rrp-line);
    background: var(--rrp-paper);
    color: var(--rrp-muted);
}

.rrp-ledger__spark {
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
    margin-top: 1px;
}

.rrp-ledger__verdict.is-pending .rrp-ledger__spark {
    animation: rrp-spark-pulse 1.2s ease-in-out infinite;
}

@keyframes rrp-spark-pulse {
    0%, 100% { opacity: 0.35; }
    50% { opacity: 1; }
}

@media (max-width: 760px) {
    /* The one main action takes the width; the link and the photo button sit
       under it rather than competing for the same line. */
    .rrp-workflow__cta {
        display: grid;
        justify-items: center;
        gap: 12px;
    }

    .rrp-workflow__cta > .btn.primary {
        width: 100%;
    }

    .rrp-invoice-values {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 760px) {
    .rrp-workflow__status {
        justify-self: start;
    }

    /* The main action takes the width; a link beside it stays a link. */
    .rrp-workflow__actions > .btn:not(.link) {
        width: 100%;
    }

    .rrp-workflow__actions {
        justify-content: center;
    }
}

/* ── Mobile ≤ 760px ───────────────────────────────────────────────────────── */
@media (max-width: 760px) {
    /* Menus drop from their own button on phones too. Sending them to the
       bottom of the screen separated the choices from the dots that opened
       them, so it was never obvious what they belonged to. */
    .rrp-menu {
        max-width: calc(100vw - 24px);
    }

    /* The Rapid-apps table stacks: header hides, each row becomes a
       two-column block (plate + text) with when/value inline beneath.
       These two used to be display:none, which is the one thing the layout
       could not afford — "when is this due" and "what is it worth" are exactly
       what someone scanning their day is looking for, and without them every
       row looks equally urgent and has to be opened to triage. They now move
       to a second line under the title instead of being dropped. */
    .rrp-app .rrp-job-table .rrn-lhead {
        display: none;
    }

    .rrp-app .rrp-job-table .rrn-row {
        grid-template-columns: minmax(72px, auto) minmax(0, 1fr) 18px;
        gap: 3px 9px;
        padding-inline: 10px;
        /* Slightly tighter than the shared 15px so the extra customer line does
           not make the mobile board feel heavier than before. */
        padding-block: 11px;
    }

    /* Every cell is placed explicitly. Auto-placement cannot express "date and
       money in the same cell at opposite ends", and leaving any one of the five
       to flow would push the rest out of position. */
    .rrp-app .rrp-job-table .rrn-row > .rrp-plate-wrap {
        grid-area: 1 / 1 / span 2 / 2;
        align-self: center;
    }

    .rrp-app .rrp-job-table .rrn-row > .rrp-job-cell--chevron {
        grid-area: 1 / 3 / span 2 / 4;
        align-self: center;
    }

    .rrp-app .rrp-job-table .rrn-row
        > .rrp-job-cell:not(.rrp-job-cell--when, .rrp-job-cell--value, .rrp-job-cell--chevron) {
        grid-area: 1 / 2 / 2 / 3;
    }

    /* Date and money share the second cell at opposite ends, so the eye can run
       down either edge of the list without the two competing for one space. */
    .rrp-app .rrp-job-table .rrn-row > .rrp-job-cell--when {
        display: flex;
        grid-area: 2 / 2 / 3 / 3;
        gap: 4px;
        align-items: baseline;
        justify-self: start;
    }

    /* Inline on this line rather than the desktop label-over-value stack. */
    .rrp-app .rrp-job-table .rrp-job-cell--when b {
        display: inline;
        margin-top: 0;
    }

    .rrp-app .rrp-job-table .rrn-row > .rrp-job-cell--value {
        grid-area: 2 / 2 / 3 / 3;
        justify-self: end;
    }

    /* Selecting jobs is an admin task, but not a desktop-only one — a manager
       handing out the morning's work is as likely to be standing in the unit with
       a phone. So the tick column shifts everything one place right rather than
       disappearing below the breakpoint. */
    .rrp-app .rrp-job-table--select .rrn-row {
        grid-template-columns: 26px minmax(64px, auto) minmax(0, 1fr) 18px;
    }

    .rrp-app .rrp-job-table--select .rrn-row > .rrp-job-select {
        grid-area: 1 / 1 / span 2 / 2;
    }

    .rrp-app .rrp-job-table--select .rrn-row > .rrp-plate-wrap {
        grid-area: 1 / 2 / span 2 / 3;
    }

    .rrp-app .rrp-job-table--select .rrn-row
        > .rrp-job-cell:not(.rrp-job-cell--when, .rrp-job-cell--value, .rrp-job-cell--chevron) {
        grid-area: 1 / 3 / 2 / 4;
    }

    .rrp-app .rrp-job-table--select .rrn-row > .rrp-job-cell--when,
    .rrp-app .rrp-job-table--select .rrn-row > .rrp-job-cell--value {
        grid-area: 2 / 3 / 3 / 4;
    }

    .rrp-app .rrp-job-table--select .rrn-row > .rrp-job-cell--chevron {
        grid-area: 1 / 4 / span 2 / 5;
    }
}

@media (max-width: 359px) {
    .rrp-page {
        padding-right: 10px;
        padding-left: 10px;
    }

    .rrp-pagination__button span {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }
}

/* ── In-app job updates ───────────────────────────────────────────────────── */
.rrp-notify__head-actions {
    display: flex;
    justify-content: flex-start;
    gap: 9px;
}

/* Only two filters, so the pill row earns its space on phones too. */
.rrp-pills.rrp-notify__filters {
    display: flex;
}

.rrp-notify-list {
    display: grid;
    margin: 0;
    padding: 0;
    list-style: none;
}

.rrp-notify + .rrp-notify {
    border-top: 1px solid var(--rrp-line);
}

.rrp-notify > a {
    display: grid;
    min-width: 0;
    grid-template-columns: 34px minmax(0, 1fr) 16px;
    align-items: start;
    gap: 12px;
    /* The 4px accent on unread rows is drawn as an inset border so read and
       unread rows keep the same text alignment. */
    padding: 13px 15px 13px 11px;
    border-left: 4px solid transparent;
    color: var(--rrp-ink);
    text-decoration: none;
}

.rrp-notify.is-unread > a {
    border-left-color: var(--rrp-green);
    background: var(--rrp-green-wash);
}

.rrp-notify.is-read > a {
    background: var(--rrp-paper);
}

/* Read rows stay fully legible but lose the emphasis, so a glance down the
   list shows what still needs attention. */
.rrp-notify.is-read .rrp-notify__top strong {
    font-weight: 700;
}

.rrp-notify.is-read .rrp-notify__icon {
    opacity: 0.6;
}

.rrp-notify__icon {
    display: grid;
    width: 34px;
    height: 34px;
    place-items: center;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 50%;
    background: var(--rrp-paper);
    color: var(--rrp-muted);
}

.rrp-notify__icon svg {
    width: 17px;
    height: 17px;
    stroke-width: 1.9;
}

/* Derived from tokens rather than fixed tints, so the three notification kinds
   stay distinguishable on either theme instead of staying pale on dark. */
.rrp-notify__icon--job {
    border-color: var(--rrp-green-line);
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
}

.rrp-notify__icon--invoice {
    border-color: color-mix(in srgb, var(--rrp-navy) 22%, var(--rrp-paper));
    background: color-mix(in srgb, var(--rrp-navy) 7%, var(--rrp-paper));
    color: var(--rrp-ink);
}

.rrp-notify__icon--booking {
    border-color: var(--rrp-amber-line);
    background: color-mix(in srgb, var(--rrp-mustard) 12%, var(--rrp-paper));
    color: var(--rrp-amber);
}

.rrp-notify__body {
    display: grid;
    min-width: 0;
    gap: 3px;
}

.rrp-notify__top {
    display: flex;
    min-width: 0;
    align-items: center;
    gap: 8px;
}

.rrp-notify__top strong {
    min-width: 0;
    font-size: 13px;
    font-weight: 800;
    letter-spacing: -0.01em;
}

.rrp-notify__new {
    flex: 0 0 auto;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--rrp-green);
    color: #fff;
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.rrp-notify__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 650;
}

.rrp-notify__ref {
    padding: 1px 6px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 5px;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font-variant-numeric: tabular-nums;
}

.rrp-notify__text {
    color: var(--rrp-ink, var(--rrp-navy));
    font-size: 12.5px;
    font-weight: 550;
    line-height: 1.45;
    overflow-wrap: anywhere;
}

.rrp-notify__chevron {
    width: 16px;
    height: 16px;
    margin-top: 9px;
    color: var(--rrp-muted);
    stroke-width: 2.2;
}

.rrp-notify__empty {
    padding: 10px 15px 16px;
}

.rrp-notify__retention {
    margin: 0;
    padding: 11px 15px;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: 11px;
}

.rrp-notify__prefs {
    display: grid;
    margin: 0;
    gap: 2px;
}

.rrp-notify__prefs .check-row {
    align-items: flex-start;
    padding: 9px 0;
}

.rrp-notify__prefs .check-row span {
    display: grid;
    gap: 2px;
}

.rrp-notify__prefs .check-row input[type="checkbox"] {
    margin-top: 1px;
}

.rrp-notify-preference-grid {
    display: grid;
    gap: 0;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-control);
    overflow: hidden;
}

.rrp-notify-preference-grid__head,
.rrp-notify-preference-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 72px 72px;
    align-items: center;
    gap: 8px;
}

.rrp-notify-preference-grid__head {
    padding: 9px 12px;
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.rrp-notify-preference-grid__head span:not(:first-child),
.rrp-notify-preference-row > label {
    text-align: center;
}

.rrp-notify-preference-row {
    min-height: 64px;
    padding: 10px 12px;
    border-top: 1px solid var(--rrp-line);
}

.rrp-notify-preference-row__copy {
    display: grid;
    gap: 3px;
}

.rrp-notify-preference-row__copy small {
    color: var(--rrp-muted);
    font-size: 11.5px;
}

@media (max-width: 560px) {
    .rrp-notify-preference-grid__head,
    .rrp-notify-preference-row {
        grid-template-columns: minmax(0, 1fr) 58px 58px;
    }
}

.rrp-notify__prefs-actions {
    display: flex;
    justify-content: flex-start;
    margin-top: 13px;
    padding-top: 13px;
    border-top: 1px solid var(--rrp-line);
}

/* ── Component: NotificationSettings — "On this device" push panel ─────────── */
.rrp-push-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
}

.rrp-push-row__copy {
    display: grid;
    gap: 3px;
    min-width: 0;
    flex: 1 1 240px;
}

.rrp-push-row__copy small {
    color: var(--rrp-muted);
    font-size: 11.5px;
}

/* ── Component: NotificationBell — topbar unread indicator ─────────────────── */
.rrp-bell {
    position: relative;
    display: grid;
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    order: 2;
    place-items: center;
    border-radius: 50%;
    color: #fff;
}

.rrp-bell svg {
    width: 21px;
    height: 21px;
    stroke-width: 1.9;
}

.rrp-bell__badge {
    position: absolute;
    top: 5px;
    right: 4px;
    display: grid;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    place-items: center;
    border: 2px solid var(--rrp-navy);
    border-radius: 999px;
    background: var(--rrp-green);
    color: #fff;
    font-size: var(--rrp-text-3xs);
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    line-height: 1;
}

@media (min-width: 761px) {
    .rrp-bell {
        color: var(--rrp-ink);
    }

    .rrp-bell:hover {
        background: var(--rrp-canvas);
    }

    .rrp-bell__badge {
        /* Matches the desktop topbar fill so the badge reads as a cut-out. */
        border-color: color-mix(in srgb, var(--rrp-paper) 96%, transparent);
    }
}

/* ── Reduced motion ─────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .rrp-app *,
    .rrp-app *::before,
    .rrp-app *::after,
    .rrp-auth *,
    .rrp-auth *::before,
    .rrp-auth *::after,
    .rrp-system-shell *,
    .rrp-system-shell *::before,
    .rrp-system-shell *::after,
    .rrp-bootstrap *,
    .rrp-bootstrap *::before,
    .rrp-bootstrap *::after {
        scroll-behavior: auto !important;
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }

    .rrp-skeleton__line::after {
        display: none;
    }
}

/* ── Component: Earnings chart — stacked invoiced value, approved vs with RRN ─ */
.rrp-earnings {
    min-width: 0;
    padding: 16px 18px;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-soft);
}

.rrp-earnings__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}

.rrp-earnings__head h3 {
    margin: 0;
    font-family: var(--rrp-font-heading);
    font-size: 15px;
    font-weight: 800;
    color: var(--rrp-ink);
}

.rrp-earnings__range {
    padding: 6px 10px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font: inherit;
    font-size: 12.5px;
}

.rrp-earnings__plot {
    position: relative;
}

/* Value reference lines. They sit over the bars (pointer-events off, so the
   per-bucket tooltips still fire) because putting them behind would hide the
   labels wherever a tall bar passes. Dashed and low-contrast keeps them a
   guide rather than a feature. */
.rrp-earnings__grid {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
}

.rrp-earnings__gridline {
    position: absolute;
    right: 0;
    left: 0;
    border-top: 1px dashed var(--rrp-line-strong);
}

.rrp-earnings__gridline i {
    position: absolute;
    top: 2px;
    right: 0;
    padding: 0 4px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--rrp-paper) 82%, transparent);
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-style: normal;
    font-weight: 650;
}

.rrp-earnings__chart {
    display: flex;
    align-items: stretch;
    gap: 6px;
    height: 168px;
}

.rrp-earnings__col {
    display: flex;
    flex: 1;
    min-width: 0;
    flex-direction: column;
    align-items: center;
}

.rrp-earnings__bar {
    display: flex;
    flex: 1;
    width: 100%;
    max-width: 40px;
    flex-direction: column;
    justify-content: flex-end;
    overflow: hidden;
    border-radius: 6px 6px 0 0;
    background: var(--rrp-canvas);
}

.rrp-earnings__seg {
    display: block;
    width: 100%;
}

.rrp-earnings__seg--approved {
    background: var(--rrp-green);
}

.rrp-earnings__seg--pending {
    background: var(--rrp-mustard);
}

/* Bucket labels live in their own row under the plot (same flex maths as the
   columns, so they line up) rather than inside each column, keeping the
   gridlines to the bar area only. */
.rrp-earnings__labels {
    display: flex;
    gap: 6px;
    margin-top: 6px;
}

.rrp-earnings__labels small {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 600;
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Twelve to fourteen tick labels cannot fit a phone — squeezed into their
   ~20px cells they clipped to meaningless fragments. Keep the first, middle
   and last at natural width and spread them across the row: per-bar alignment
   goes, but the date range becomes readable, which is what the labels are
   for. Year view keeps all five — they fit. */
@media (max-width: 640px) {
    :is(.rrp-earnings__labels--day, .rrp-earnings__labels--week, .rrp-earnings__labels--month) {
        justify-content: space-between;
    }

    :is(.rrp-earnings__labels--day, .rrp-earnings__labels--week, .rrp-earnings__labels--month) small {
        display: none;
    }

    :is(.rrp-earnings__labels--day, .rrp-earnings__labels--week, .rrp-earnings__labels--month) small:first-child,
    :is(.rrp-earnings__labels--day, .rrp-earnings__labels--week, .rrp-earnings__labels--month) small:last-child,
    .rrp-earnings__labels--day small:nth-child(7),
    :is(.rrp-earnings__labels--week, .rrp-earnings__labels--month) small:nth-child(6) {
        display: block;
        flex: 0 0 auto;
        overflow: visible;
        white-space: nowrap;
    }
}

.rrp-earnings__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-top: 12px;
    color: var(--rrp-muted);
    font-size: 12.5px;
    font-weight: 600;
}

.rrp-earnings__legend span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.rrp-earnings__legend-total {
    margin-left: auto;
    color: var(--rrp-ink);
    font-weight: 750;
}

.rrp-earnings__swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 3px;
}

.rrp-earnings__swatch--approved {
    background: var(--rrp-green);
}

.rrp-earnings__swatch--pending {
    background: var(--rrp-mustard);
}

.rrp-earnings__empty {
    margin: 0;
    padding: 22px 0;
    color: var(--rrp-muted);
    font-size: 13px;
}

/* ── Component: Rates table — the repairer's own price schedule ─────────────── */
.rrp-rates-table {
    width: 100%;
    margin-top: 10px;
    border-collapse: collapse;
    font-size: 13px;
}

.rrp-rates-table th {
    padding: 8px 10px;
    border-bottom: 1px solid var(--rrp-line-strong);
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    letter-spacing: 0.02em;
    text-align: left;
    text-transform: uppercase;
}

.rrp-rates-table td {
    padding: 9px 10px;
    border-bottom: 1px solid var(--rrp-line);
    color: var(--rrp-ink);
    font-weight: 600;
}

.rrp-rates-table td small {
    color: var(--rrp-muted);
    font-weight: 600;
}

.rrp-rates-table .is-money {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ── Component: Invoices table — the exportable invoices screen list ────────── */
.rrp-invoices-tablehead {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 24px 0 12px;
}

.rrp-invoices-tablehead h3 {
    margin: 0;
    font-family: var(--rrp-font-heading);
    font-size: 15px;
    font-weight: 800;
    color: var(--rrp-ink);
}

.rrp-invoices-table {
    width: 100%;
    overflow: hidden;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    box-shadow: var(--rrp-shadow-soft);
    border-collapse: separate;
    border-spacing: 0;
    font-size: 13px;
}

.rrp-invoices-table th {
    padding: 10px 12px;
    border-bottom: 1px solid var(--rrp-line-strong);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-align: left;
    text-transform: uppercase;
}

.rrp-invoices-table td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--rrp-line);
    color: var(--rrp-ink);
    vertical-align: middle;
}

.rrp-invoices-table tr:last-child td {
    border-bottom: 0;
}

.rrp-invoices-table td.is-money {
    font-family: var(--rrp-font-heading);
    font-weight: 800;
    white-space: nowrap;
}

.rrp-invoices-table__actions {
    text-align: right;
    white-space: nowrap;
}

.rrp-invoices-table__download {
    padding: 4px 6px;
    border: 0;
    border-radius: var(--rrp-radius-control);
    background: transparent;
    color: var(--rrp-green-dark);
    font: inherit;
    font-size: 12.5px;
    font-weight: 800;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.rrp-invoices-table__download:hover:not(:disabled) {
    background: var(--rrp-green-wash);
}

.rrp-invoices-table__download:disabled {
    color: var(--rrp-muted);
    cursor: default;
    text-decoration: none;
}

.rrp-invoices-table__nodoc {
    color: var(--rrp-muted);
}

.rrp-invoices-table .rrp-invoices-table__status {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: 11px;
    font-weight: 800;
}

.rrp-invoices-table .rrp-invoices-table__status.is-approved {
    background: var(--rrp-green-wash);
    color: var(--rrp-green-dark);
}

/* Warm grey on cream measured 3.41:1. Amber-ink clears 4.5:1 on the same tint,
   and the hairline gives the pill an edge that does not rely on its fill. */
.rrp-invoices-table .rrp-invoices-table__status.is-pending {
    border: 1px solid var(--rrp-amber-line);
    background: var(--rrp-amber-soft);
    color: var(--rrp-amber);
}

.rrp-invoices-table .rrp-invoices-table__status.is-rejected {
    background: var(--rrp-danger-soft);
    color: var(--rrp-danger-deep);
}

/* On phones the eight-column table can never fit, so each row becomes a card:
   invoice number and status on top, job and date beneath, then the three
   figures side by side with their own small labels. */
@media (max-width: 780px) {
    .rrp-invoices-tablehead {
        flex-wrap: wrap;
    }

    .rrp-invoices-table {
        display: block;
        border: 0;
        border-radius: 0;
        background: transparent;
        box-shadow: none;
    }

    .rrp-invoices-table thead {
        display: none;
    }

    .rrp-invoices-table tbody {
        display: grid;
        gap: 10px;
    }

    .rrp-invoices-table tr {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        row-gap: 8px;
        column-gap: 12px;
        align-items: center;
        padding: 14px 16px;
        border: 1px solid var(--rrp-line);
        border-radius: var(--rrp-radius-card);
        background: var(--rrp-paper);
        box-shadow: var(--rrp-shadow-soft);
    }

    .rrp-invoices-table td {
        padding: 0;
        border-bottom: 0;
    }

    .rrp-invoices-table td.is-number {
        grid-row: 1;
        grid-column: 1 / 3;
        font-family: var(--rrp-font-heading);
        font-weight: 800;
        color: var(--rrp-ink);
    }

    .rrp-invoices-table td.is-status {
        grid-row: 1;
        grid-column: 3;
        justify-self: end;
    }

    .rrp-invoices-table td.is-job {
        grid-row: 2;
        grid-column: 1 / 3;
    }

    .rrp-invoices-table td.is-sent {
        grid-row: 2;
        grid-column: 3;
        color: var(--rrp-muted);
        font-size: 12px;
        text-align: right;
    }

    .rrp-invoices-table td.is-money {
        grid-row: 3;
        padding-top: 8px;
        border-top: 1px solid var(--rrp-line);
    }

    .rrp-invoices-table td.is-money::before {
        content: attr(data-label);
        display: block;
        color: var(--rrp-muted);
        font-family: var(--rrp-font-body);
        font-size: var(--rrp-text-3xs);
        font-weight: 800;
        letter-spacing: 0.04em;
        text-transform: uppercase;
    }

    .rrp-invoices-table td.is-money.is-total {
        text-align: right;
    }

    .rrp-invoices-table .rrp-invoices-table__actions {
        grid-row: 4;
        grid-column: 1 / -1;
        text-align: right;
    }

    .rrp-invoices-table .rrp-invoices-table__actions .rrp-invoices-table__nodoc {
        display: none;
    }

    .rrp-invoices-table__download {
        padding: 0;
    }
}

/* ── The repair flow: one rail, one screen, one action ─────────────────────
   The workflow reads like an app checkout: a slim step rail up top (done
   steps tappable), a single focused screen, and an action bar pinned to the
   bottom of the card with the running total and the one thing to press. */

.rrp-flow-screen__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
}

.rrp-flow-screen__head :where(h2, h3) {
    margin: 0 0 4px;
    color: var(--rrp-ink);
    font-family: var(--rrp-font-heading);
    font-size: 17px;
}

.rrp-flow-screen__head p {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 13px;
    line-height: 1.45;
}

/* ── Costs as a ledger: tap a line to change it ───────────────────────────── */
.rrp-basket {
    display: grid;
    overflow: hidden;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

/* Column headers are table chrome — a tinted strip of small caps — while the
   section labels below are headings: navy, sentence case, on the paper.
   Two different jobs, two different looks, so they never blend. */
.rrp-basket__head {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 14px;
    border-bottom: 1px solid var(--rrp-line);
    background: var(--rrp-canvas);
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

/* The "Amount" label sits over the figures, clear of the chevron column. */
.rrp-basket__head span:last-child {
    padding-right: 28px;
}

.rrp-basket__group {
    padding: 13px 14px 3px;
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
}

.rrp-basket__group + .rrp-basket__group,
.rrp-basket__row + .rrp-basket__group {
    border-top: 1px solid var(--rrp-line);
}

.rrp-basket__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto 16px;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 44px;
    padding: 8px 14px;
    border: 0;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-paper);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.rrp-basket__row:first-child,
.rrp-basket__head + .rrp-basket__row,
.rrp-basket__group + .rrp-basket__row {
    border-top: 0;
}

.rrp-basket__row:hover:not(:disabled) {
    background: var(--rrp-canvas);
}

.rrp-basket__row:disabled {
    cursor: default;
}

.rrp-basket__body {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.rrp-basket__body strong {
    overflow: hidden;
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 700;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-basket__tag {
    flex: 0 0 auto;
    padding: 1px 7px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 999px;
    background: var(--rrp-paper);
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 750;
    white-space: nowrap;
}

.rrp-basket__tag.is-changed {
    border-color: color-mix(in srgb, var(--rrp-amber) 55%, var(--rrp-line-strong));
    color: var(--rrp-faded, var(--rrp-amber));
}

.rrp-basket__amount {
    color: var(--rrp-ink);
    font-size: 13.5px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.rrp-basket__chev {
    width: 16px;
    height: 16px;
    color: var(--rrp-line-strong);
}

.rrp-basket__row:hover:not(:disabled) .rrp-basket__chev {
    color: var(--rrp-muted);
}

/* Adding a line is a quiet row, not a banner. */
.rrp-basket__add {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 40px;
    padding: 9px 14px;
    border: 0;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-paper);
    color: var(--rrp-green-dark, var(--rrp-navy));
    font: inherit;
    font-size: 12.5px;
    font-weight: 750;
    cursor: pointer;
}

.rrp-basket__add:hover:not(:disabled) {
    background: var(--rrp-canvas);
}

.rrp-basket__add span {
    font-size: 14px;
    line-height: 1;
}

/* All the arithmetic in one right-aligned block at the foot, the way an
   invoice reads: subtotals, then the total under its own rule. The right
   padding lines the figures up under the rows' amount column. */
.rrp-basket__totals {
    display: grid;
    gap: 3px;
    justify-content: end;
    padding: 10px 42px 12px 14px;
    border-top: 1px solid var(--rrp-line);
    background: var(--rrp-paper);
}

.rrp-basket__totalrow {
    display: grid;
    grid-template-columns: auto minmax(90px, auto);
    gap: 28px;
    align-items: baseline;
}

.rrp-basket__totalrow span {
    color: var(--rrp-muted);
    font-size: 12px;
    font-weight: 650;
    text-align: right;
}

.rrp-basket__totalrow em {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-style: normal;
    font-weight: 650;
}

.rrp-basket__totalrow strong {
    color: var(--rrp-ink);
    font-size: 13px;
    font-weight: 750;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.rrp-basket__totalrow.is-total {
    margin-top: 4px;
    padding-top: 7px;
    border-top: 2px solid var(--rrp-navy);
}

.rrp-basket__totalrow.is-total span {
    color: var(--rrp-ink);
    font-weight: 800;
}

.rrp-basket__totalrow.is-total strong {
    font-size: 15px;
}

/* ── The action bar pinned to the bottom of the window ─────────────────────
   Fixed, not sticky: it belongs to the stage, not the card, so it stays put
   however far the page scrolls. On phones it rests on the dock; on desktop it
   starts after the navy rail. The page gets bottom clearance (further down)
   so the last content can always scroll above it. */
.rrp-flow-bar {
    position: fixed;
    z-index: var(--rrp-z-overlay);
    right: 0;
    bottom: calc(var(--rrp-dock-height) + env(safe-area-inset-bottom, 0px));
    left: 0;
    border-top: 1px solid var(--rrp-line-strong);
    background: var(--rrp-paper);
    box-shadow: 0 -10px 26px rgba(12, 36, 72, 0.1);
}

.rrp-flow-bar__inner {
    display: flex;
    width: min(100%, 1240px);
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    margin-inline: auto;
    padding: 11px 14px;
}

/* Previous step rides in the bar rather than up by the header, so moving
   forward and back happen from the same hand position on every stage. It is a
   full button the size and weight of the primary action, filled with the
   caution/warning tone (mustard is this system's --warning fill) over navy
   ink — high-contrast in both themes and never mistaken for a disabled,
   progress-blocking control. */
.rrp-app .rrp-flow-bar__prev {
    flex: 0 0 auto;
    min-width: 0;
    border-color: color-mix(in srgb, var(--rrp-navy) 22%, var(--rrp-mustard));
    background: var(--rrp-mustard);
    color: var(--rrp-navy);
}

.rrp-flow-bar__prev svg {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
}

/* Clearance for the pinned bar. On phones the bar wraps when a blocked
   reason sits above the CTA (hint + full-width button), so a single-row
   allowance left Job details stranded underneath and the page felt like it
   had no true bottom. The viewport scroll-padding keeps scrollIntoView and
   end-of-page scrolling honest about the overlay. */
.rrp-page:has(.rrp-flow-bar) {
    padding-bottom: var(--rrp-flow-bar-clearance, 160px);
}

.rrp-viewport:has(.rrp-flow-bar) {
    scroll-padding-bottom: var(--rrp-flow-bar-clearance, 160px);
}

/* ── Business page: floating save bar and back-to-job note ─────────────────
   The save bar borrows the flow bar's geometry (fixed above the dock on
   phones, on the window edge past the rail on desktop) but only exists while
   something is unsaved — on a long phone form the inline button lived below
   the fold, so saving meant scrolling to find it. */
.rrp-returnbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
    padding: 10px 10px 10px 14px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
    color: var(--rrp-muted);
    font-size: 12.5px;
    font-weight: 600;
}

.rrp-returnbar .btn {
    flex: 0 0 auto;
}

.rrp-savebar {
    position: fixed;
    z-index: var(--rrp-z-overlay);
    right: 0;
    bottom: calc(var(--rrp-dock-height) + env(safe-area-inset-bottom, 0px));
    left: 0;
    border-top: 1px solid var(--rrp-line-strong);
    background: var(--rrp-paper);
    box-shadow: 0 -10px 26px rgba(12, 36, 72, 0.1);
}

.rrp-savebar__inner {
    display: flex;
    width: min(100%, 1240px);
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    margin-inline: auto;
    padding: 11px 14px;
}

.rrp-savebar__note {
    color: var(--rrp-muted);
    font-size: 12.5px;
    font-weight: 700;
}

.rrp-savebar__actions {
    display: flex;
    flex: 0 0 auto;
    gap: 10px;
}

/* Clearance so the end of the form can always scroll above the bar. */
.rrp-page:has(.rrp-savebar) {
    padding-bottom: 120px;
}

.rrp-viewport:has(.rrp-savebar) {
    scroll-padding-bottom: 120px;
}

/* Desktop has no dock: the bar sits on the window edge, spanning the
   workspace only — the navy rail keeps its full height beside it. */
@media (min-width: 761px) {
    .rrp-flow-bar {
        bottom: 0;
        left: 224px;
    }

    .rrp-savebar {
        bottom: 0;
        left: 224px;
    }

    .rrp-page:has(.rrp-savebar) {
        padding-bottom: 96px;
    }

    .rrp-viewport:has(.rrp-savebar) {
        scroll-padding-bottom: 96px;
    }

    .rrp-flow-bar__inner {
        padding: 12px clamp(22px, 3.2vw, 40px);
    }

    .rrp-page:has(.rrp-flow-bar),
    .rrp-viewport:has(.rrp-flow-bar) {
        --rrp-flow-bar-clearance: 96px;
    }

    .rrp-page:has(.rrp-flow-bar) {
        padding-bottom: var(--rrp-flow-bar-clearance);
    }
}

.rrp-flow-bar__total {
    display: grid;
    gap: 1px;
    flex: 0 0 auto;
}

.rrp-flow-bar__total small {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 700;
}

.rrp-flow-bar__total strong {
    color: var(--rrp-ink);
    font-family: var(--rrp-font-heading);
    font-size: 19px;
    line-height: 1.1;
}

.rrp-flow-bar__action {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    min-width: 0;
}

.rrp-flow-bar__hint {
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-weight: 650;
    text-align: right;
}

.rrp-flow-bar__cta {
    flex: 0 0 auto;
    min-width: 170px;
}

/* A stage that can step back shows two equal actions — the warning-toned
   Previous step beside the primary action — split half and half with the
   inner gap between them. The primary side fills its half and stacks its
   disabled-reason hint above the button; the money total and any secondary
   links are dropped on these stages so the bar is just the two buttons. */
.rrp-flow-bar--split .rrp-flow-bar__prev,
.rrp-flow-bar--split .rrp-flow-bar__action {
    flex: 1 1 0;
    min-width: 0;
}

.rrp-flow-bar--split .rrp-flow-bar__action {
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: 4px;
}

.rrp-flow-bar--split .rrp-flow-bar__cta {
    width: 100%;
    min-width: 0;
}

.rrp-flow-bar--split .rrp-flow-bar__hint {
    text-align: center;
}

/* ── Final review: what RRN receives, row by row ──────────────────────────── */
.rrp-review {
    display: grid;
    overflow: hidden;
    border: 1px solid var(--rrp-line);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-paper);
}

.rrp-review__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    min-height: 62px;
    padding: 12px 14px;
    border-top: 1px solid var(--rrp-line);
}

.rrp-review__row:first-child {
    border-top: 0;
}

.rrp-review__copy {
    display: grid;
    gap: 2px;
    min-width: 0;
}

.rrp-review__copy small {
    color: var(--rrp-muted);
    font-size: var(--rrp-text-3xs);
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.rrp-review__copy strong {
    overflow: hidden;
    color: var(--rrp-ink);
    font-size: 13.5px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-review__copy em {
    color: var(--rrp-muted);
    font-size: 11.5px;
    font-style: normal;
}

.rrp-review__copy em.is-caution {
    color: var(--rrp-amber);
    font-weight: 700;
}

.rrp-review__actions {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 4px;
}

/* ── Outstanding issues — everything still standing between this invoice and
      RRN, in one list. Shown on the review screen and again inside the send
      dialog, which is the only confirmation on the way out. Deliberately not a
      run of `.rrp-workflow__decision` blocks: three of those stacked read as
      three separate alarms, where a list reads as a checklist. ───────────────*/
.rrp-issues-panel {
    display: grid;
    gap: 8px;
    margin-top: 14px;
    padding: 13px 14px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: var(--rrp-radius-card);
    background: var(--rrp-canvas);
}

.rrp-issues-panel h4 {
    margin: 0;
    color: var(--rrp-ink);
    font-size: 13.5px;
}

.rrp-issues-panel__note {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 12.5px;
    line-height: 1.5;
}

.rrp-issues {
    display: grid;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.rrp-issues__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--rrp-line);
    border-left: 4px solid var(--rrp-amber);
    border-radius: var(--rrp-radius-control);
    background: var(--rrp-paper);
}

.rrp-issues__item.is-error {
    border-left-color: var(--rrp-danger);
}

.rrp-issues__copy {
    display: grid;
    gap: 2px;
    min-width: 0;
}

.rrp-issues__copy strong {
    color: var(--rrp-ink);
    font-size: 13px;
}

.rrp-issues__copy small {
    color: var(--rrp-muted);
    font-size: 12px;
    line-height: 1.45;
}

/* The fix link keeps its own row on phones: side by side it squeezes the
   sentence that explains the problem down to two words a line. */
@media (max-width: 420px) {
    .rrp-issues__item {
        flex-direction: column;
        align-items: stretch;
        gap: 6px;
    }

    .rrp-issues__item .btn.link {
        justify-self: start;
        margin-inline-end: auto;
    }
}

/* ── Sent: the job is out of the repairer's hands ─────────────────────────── */
.rrp-sent {
    justify-items: center;
    padding: 30px 20px;
    text-align: center;
}

.rrp-sent__badge {
    display: grid;
    width: 46px;
    height: 46px;
    place-items: center;
    border-radius: 999px;
    background: var(--rrp-green);
    color: #fff;
    font-size: 21px;
    font-weight: 900;
}

.rrp-sent h3 {
    margin: 0;
    color: var(--rrp-ink);
    font-family: var(--rrp-font-heading);
    font-size: 17px;
}

.rrp-sent p {
    margin: 0;
    color: var(--rrp-muted);
    font-size: 12.5px;
}

/* The take-away shelf: the sent invoice and its import files, quietly under
   the confirmation rather than competing with it. */
.rrp-sent__downloads {
    display: grid;
    gap: 6px;
    justify-items: center;
    width: 100%;
    max-width: 460px;
    margin-top: 10px;
    padding-top: 16px;
    border-top: 1px solid var(--rrp-line);
}

.rrp-sent__downloads h4 {
    margin: 0;
    color: var(--rrp-ink);
    font-size: 12.5px;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.rrp-sent__downloads-note {
    margin-top: 8px;
}

.rrp-sent__downloads-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
}

/* One chip per accounts package, led by its mark so the right button is
   recognisable at a glance. */
.rrp-export {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px 7px 8px;
    border: 1px solid var(--rrp-line-strong);
    border-radius: 999px;
    background: var(--rrp-paper);
    color: var(--rrp-ink);
    font: inherit;
    font-size: 12.5px;
    font-weight: 750;
    cursor: pointer;
}

.rrp-export:hover:not(:disabled) {
    border-color: var(--rrp-navy);
    background: var(--rrp-canvas);
}

.rrp-export:disabled {
    cursor: default;
    opacity: 0.55;
}

.rrp-export__logo {
    display: grid;
    width: 22px;
    height: 22px;
    place-items: center;
    border-radius: 999px;
    color: #fff;
    font-size: 11px;
    font-weight: 900;
    line-height: 1;
    text-transform: lowercase;
}

.rrp-export__logo.is-xero {
    background: #13b5ea;
    text-transform: uppercase;
}

.rrp-export__logo.is-qb {
    background: #2ca01c;
}

.rrp-export__logo.is-sage {
    background: #008849;
}

.rrp-export__logo.is-csv {
    background: var(--rrp-navy-soft);
    font-size: 13px;
}

/* Help sits apart from the record-keeping, under its own quiet rule. */
.rrp-sent__help {
    width: 100%;
    max-width: 460px;
    margin-top: 10px;
    padding-top: 16px;
    border-top: 1px solid var(--rrp-line);
    display: grid;
    justify-items: center;
}

/* Icon and label on one line: without a size the inline SVG takes its
   default intrinsic box and shoves "Get help" onto its own row. */
.rrp-sent__help .btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
}

.rrp-sent__help .btn svg {
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    stroke-width: 2;
}

@media (max-width: 760px) {
    .rrp-flow-screen__head {
        display: grid;
        gap: 6px;
    }

    /* The head grid stretches the method pill to the full column, which left
       two small options adrift in a long empty track. Split the width between
       them instead, like a proper segmented control. */
    .rrp-invoice-method {
        display: flex;
        width: 100%;
    }

    .rrp-invoice-method__opt {
        flex: 1 1 0;
        text-align: center;
    }

    /* One row, the height of the button: chevron, a compact money figure when
       the stage carries one, then the action. The stage wording that used to
       take a second row is gone on phones — the screen itself already says
       where you are, so the bar only has to act. */
    .rrp-flow-bar__inner {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 8px 12px;
    }

    /* Stage wording ("Set off to the repair", photo progress, the booking
       date) repeats what the screen or the button already says — on phones it
       goes entirely. Compound selector so the generic total rule below cannot
       win the tie and bring it back. */
    .rrp-flow-bar__total.rrp-flow-bar__total--stage {
        display: none;
    }

    /* Money stays — it's the one figure worth a glance at send time — but as
       a single compact line beside the action, not a tall block. */
    .rrp-flow-bar__total {
        display: flex;
        min-width: 0;
        flex: 0 1 auto;
        align-items: baseline;
        gap: 4px;
        white-space: nowrap;
    }

    .rrp-flow-bar__total strong {
        font-size: 14px;
    }

    .rrp-flow-bar__action {
        display: flex;
        min-width: 0;
        flex: 1 1 auto;
        flex-wrap: wrap;
        align-items: center;
        justify-content: flex-end;
        gap: 6px 12px;
    }

    /* The reason a disabled button is disabled has to be readable on a phone —
       there is no hover to reveal it. It sits above the button, full width. */
    .rrp-flow-bar__hint {
        flex: 1 1 100%;
        text-align: left;
    }

    .rrp-flow-bar__cta {
        min-width: 0;
        flex: 1 1 auto;
    }

    .rrp-review__row {
        flex-wrap: wrap;
    }

    .rrp-review__actions {
        margin-left: auto;
    }
}

/* -- Embedded camera overlay --------------------------------------------------
   Hosts the Rapid Capture camera over the job page. The camera's own view is
   position:fixed and covers everything; this backdrop covers the moments
   around it (session loading, an error) so the job page never shows through
   half-dressed. It renders inside cap-shell (the capture palette), so the
   colours are the capture app's literals, not rrp tokens. */
.rrp-capture-overlay {
    position: fixed;
    /* Modal tier: the camera is a full takeover, so it must cover the topbar
       (50) and the bottom tab dock (60) — at the overlay tier (45) both sat on
       top of it and hid the shutter and Done buttons. */
    z-index: var(--rrp-z-modal);
    inset: 0;
    overflow: auto;
    padding: 24px 16px;
    background: #0a1b34;
    color: #ffffff;
}
