﻿/*
 * =============================================================================
 * FIRMPORTAL DESIGN SYSTEM
 * =============================================================================
 *
 * Aesthetic: Quiet luxury + structured productivity
 * References: Uber, Brex (aesthetic) / Airtable, Canopy (productivity)
 *
 * BRAND: "Ink & Lime" (Palette 008)
 *   Ink:      #0c0c0e (near-black — text, headings, dark rail surface)
 *   Accent:   #84cc16 lime (on light) / #a3e635 (on dark); INK text on lime
 *   Link:     #65a30d
 *
 * NEUTRALS (warm stone palette)
 *   50: #FAFAFA  100: #F5F5F4  200: #E7E5E4  300: #D6D3D1
 *   400: #A8A29E  500: #78716C  600: #57534E  700: #44403C
 *   800: #292524  900: #1C1917
 *
 * FONTS (Google Fonts)
 *   Body/UI:  Plus Jakarta Sans
 *   Display:  Reem Kufi (all headings)
 *   Italic:   Lora (emphasis only)
 *   Wordmark: stacked SVG asset (/img/wordmark-stacked-on-*.svg)
 *   Body size: 15px (0.9375rem)
 *
 * SPACING
 *   Base unit: 8px
 *   Bootstrap mapping: p-1=4px, p-2=8px, p-3=16px, p-4=24px, p-5=48px
 *
 * RADIUS
 *   sm: 6px, md: 8px, lg: 12px
 *
 * LAYOUT
 *   Sidebar width: 260px (desktop), offcanvas (mobile <992px)
 *   Max content width: 1200px
 *
 * FILE STRUCTURE
 *   1. Design tokens (--ip-* custom properties)
 *   2. Bootstrap variable overrides (:root)
 *   3. Base element resets
 *   4. Typography scale
 *   5. Component overrides (buttons, forms, alerts, tables, cards, badges)
 *   6. App layout (sidebar, main content, mobile header, offcanvas)
 *   7. Auth layout (split panel, branding, form area)
 *   8. Custom utilities
 * =============================================================================
 */


/* =============================================================================
   1. DESIGN TOKENS
   ============================================================================= */

:root {
    /* Accent — Ink & Lime (Palette 008) */
    --ip-accent: #84cc16;            /* lime — primary fill, progress, active, focus (light surfaces) */
    --ip-accent-rgb: 132, 204, 22;
    --ip-accent-hover: #6aa312;      /* lime-deep (lime 80% + black) */
    --ip-accent-light: #a3e635;      /* lime on dark surfaces */
    --ip-accent-on-dark: #a3e635;    /* alias for dark-surface lime accents */
    --ip-accent-subtle: #ebf5d0;     /* lime tint (lime 12% + white) */
    --ip-accent-subtle-hover: #e0eebb;
    --ip-on-accent: #0c0c0e;         /* INK text on lime fills — never white */
    --ip-ink: #0c0c0e;               /* near-black brand ink */
    --ip-link: #65a30d;              /* readable lime link on white */

    /* Status palette — cohesive with Ink & Lime.
       positive = done/confirmed (lime); active = in-progress (faint lime tint);
       action = needs-you (amber, kept); neutral = inactive/info; danger = errors only. */
    --ip-positive-bg: #ebf5d0;       /* lime tint */
    --ip-positive-text: #3f5910;     /* deep lime */
    --ip-positive: #84cc16;          /* lime — dots, check circles */
    --ip-active-bg: #f4f9e6;         /* faint lime tint */
    --ip-active-text: #4d7c0f;       /* olive-lime */
    --ip-action-bg: #F6C453;         /* gold pill — action-required badges (matches sidebar count) */
    --ip-action-text: #3D2A06;
    --ip-info-bg: #E3EDF7;           /* muted blue — informational pills that must read as neither needs-you nor done */
    --ip-info-text: #27496D;

    /* Warm stone neutrals */
    --ip-neutral-50: #FAFAFA;
    --ip-neutral-100: #F5F5F4;
    --ip-neutral-200: #E7E5E4;
    --ip-neutral-300: #D6D3D1;
    --ip-neutral-400: #A8A29E;
    --ip-neutral-500: #78716C;
    --ip-neutral-600: #57534E;
    --ip-neutral-700: #44403C;
    --ip-neutral-800: #292524;
    --ip-neutral-900: #1C1917;

    /* Fonts */
    --ip-font-family: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif; /* body / UI */
    --ip-font-display: 'Reem Kufi', 'Plus Jakarta Sans', system-ui, sans-serif;  /* headings / display */
    --ip-font-serif: 'Lora', Georgia, serif;                                     /* marketing-only emphasis; unused in the app */

    /* Spacing */
    --ip-spacing-unit: 8px;

    /* Radius */
    --ip-radius-sm: 6px;
    --ip-radius-md: 8px;
    --ip-radius-lg: 12px;

    /* Layout */
    --ip-sidebar-width: 260px;

    /* Transitions */
    --ip-transition-fast: 150ms ease;
    --ip-transition-normal: 200ms ease;
}


/* =============================================================================
   2. BOOTSTRAP VARIABLE OVERRIDES
   ============================================================================= */

:root,
[data-bs-theme="light"] {
    /* Font */
    --bs-font-sans-serif: var(--ip-font-family);
    --bs-body-font-family: var(--ip-font-family);
    --bs-body-font-size: 0.9375rem;
    --bs-body-font-weight: 400;
    --bs-body-line-height: 1.6;

    /* Primary = accent */
    --bs-primary: var(--ip-accent);
    --bs-primary-rgb: var(--ip-accent-rgb);
    --bs-primary-text-emphasis: #3f5910;
    --bs-primary-bg-subtle: var(--ip-accent-subtle);
    --bs-primary-border-subtle: #d4e8a8;

    /* Body colors */
    --bs-body-color: var(--ip-neutral-800);
    --bs-body-color-rgb: 41, 37, 36;
    --bs-body-bg: #FFFFFF;
    --bs-body-bg-rgb: 255, 255, 255;

    /* Secondary/tertiary */
    --bs-secondary-color: var(--ip-neutral-500);
    --bs-secondary-bg: var(--ip-neutral-100);
    --bs-tertiary-bg: var(--ip-neutral-50);
    --bs-tertiary-color: var(--ip-neutral-400);

    /* Headings */
    --bs-heading-color: var(--ip-neutral-900);

    /* Links — readable lime on white */
    --bs-link-color: var(--ip-link);
    --bs-link-color-rgb: 101, 163, 13;
    --bs-link-decoration: none;
    --bs-link-hover-color: var(--ip-accent-hover);
    --bs-link-hover-color-rgb: 106, 163, 18;

    /* Borders */
    --bs-border-color: var(--ip-neutral-200);
    --bs-border-color-translucent: rgba(41, 37, 36, 0.08);
    --bs-border-radius: var(--ip-radius-md);
    --bs-border-radius-sm: var(--ip-radius-sm);
    --bs-border-radius-lg: var(--ip-radius-lg);

    /* Shadows — minimal */
    --bs-box-shadow: none;
    --bs-box-shadow-sm: none;
    --bs-box-shadow-lg: 0 4px 24px rgba(0, 0, 0, 0.06);

    /* Focus ring */
    --bs-focus-ring-color: rgba(132, 204, 22, 0.35);
    --bs-focus-ring-width: 0.2rem;

    /* Semantic colors — muted, sophisticated */
    --bs-success: #4d7c0f;
    --bs-success-rgb: 77, 124, 15;
    --bs-danger: #C53030;
    --bs-danger-rgb: 197, 48, 48;
    --bs-warning: #B7791F;
    --bs-warning-rgb: 183, 121, 31;
    --bs-info: #57534E;
    --bs-info-rgb: 87, 83, 78;
}


/* =============================================================================
   3. BASE ELEMENT RESETS
   ============================================================================= */

html {
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    position: relative;
    min-height: 100%;
}

body {
    margin: 0;
    letter-spacing: -0.011em;
}


/* =============================================================================
   4. TYPOGRAPHY SCALE
   ============================================================================= */

/* All headings use the Reem Kufi display face (Ink & Lime brand) */
h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 { font-family: var(--ip-font-display); }

h1, .h1 { font-size: 1.875rem; font-weight: 700; letter-spacing: -0.025em; line-height: 1.2; }
h2, .h2 { font-size: 1.5rem;   font-weight: 700; letter-spacing: -0.02em;  line-height: 1.25; }
h3, .h3 { font-size: 1.25rem;  font-weight: 600; letter-spacing: -0.015em; line-height: 1.3; }
h4, .h4 { font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.01em; line-height: 1.35; }
h5, .h5 { font-size: 0.9375rem; font-weight: 600; line-height: 1.4; }
h6, .h6 {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-500);
    line-height: 1.4;
}

/* A parenthetical inside a section eyebrow — "(optional)" and the like. It annotates the
   label, so it is never louder than it: same size and case, lighter weight, dimmer. An
   inline 0.875rem here made the aside bigger than the heading it belonged to. */
.h6-aside {
    font-weight: 400;
    color: var(--ip-neutral-400);
}

/* Italic emphasis is plain italic in the body face. The Lora-in-lime treatment
   (--ip-font-serif + --ip-accent) is a MARKETING convention and is not used in the apps. */
em {
    font-style: italic;
}


/* =============================================================================
   5. COMPONENT OVERRIDES
   ============================================================================= */

/* ----- Buttons ----- */

.btn {
    font-weight: 500;
    letter-spacing: -0.005em;
    transition: all var(--ip-transition-fast);
}

.btn:active {
    transform: scale(0.98);
}

.btn-primary {
    --bs-btn-color: var(--ip-on-accent);
    --bs-btn-bg: var(--ip-accent);
    --bs-btn-border-color: var(--ip-accent);
    --bs-btn-hover-color: var(--ip-on-accent);
    --bs-btn-hover-bg: var(--ip-accent-hover);
    --bs-btn-hover-border-color: var(--ip-accent-hover);
    --bs-btn-focus-shadow-rgb: var(--ip-accent-rgb);
    --bs-btn-active-color: var(--ip-on-accent);
    --bs-btn-active-bg: var(--ip-accent-hover);
    --bs-btn-active-border-color: var(--ip-accent-hover);
    --bs-btn-disabled-color: var(--ip-on-accent);
    --bs-btn-disabled-bg: var(--ip-accent);
    --bs-btn-disabled-border-color: var(--ip-accent);
    --bs-btn-disabled-opacity: 0.5;
}

.btn-outline-primary {
    --bs-btn-color: var(--ip-accent-hover);
    --bs-btn-border-color: var(--ip-accent);
    --bs-btn-hover-color: var(--ip-on-accent);
    --bs-btn-hover-bg: var(--ip-accent);
    --bs-btn-hover-border-color: var(--ip-accent);
    --bs-btn-active-color: var(--ip-on-accent);
    --bs-btn-active-bg: var(--ip-accent-hover);
    --bs-btn-active-border-color: var(--ip-accent-hover);
    --bs-btn-focus-shadow-rgb: var(--ip-accent-rgb);
}

/* Action button — the primary CTA INSIDE an amber action card/panel (e.g. Confirm
   Elections). Gold to match the count/status pills, so the action zone reads as one
   cohesive amber module. Lime stays reserved for non-action primary buttons. */
.btn-action {
    --bs-btn-color: var(--ip-action-text);
    --bs-btn-bg: var(--ip-action-bg);
    --bs-btn-border-color: var(--ip-action-bg);
    --bs-btn-hover-color: var(--ip-action-text);
    --bs-btn-hover-bg: color-mix(in srgb, var(--ip-action-bg) 88%, black);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--ip-action-bg) 88%, black);
    --bs-btn-active-color: var(--ip-action-text);
    --bs-btn-active-bg: color-mix(in srgb, var(--ip-action-bg) 82%, black);
    --bs-btn-active-border-color: color-mix(in srgb, var(--ip-action-bg) 82%, black);
    --bs-btn-disabled-color: var(--ip-action-text);
    --bs-btn-disabled-bg: var(--ip-action-bg);
    --bs-btn-disabled-border-color: var(--ip-action-bg);
    --bs-btn-disabled-opacity: 0.5;
}

.btn-secondary {
    --bs-btn-color: var(--ip-neutral-700);
    --bs-btn-bg: var(--ip-neutral-100);
    --bs-btn-border-color: var(--ip-neutral-200);
    --bs-btn-hover-color: var(--ip-neutral-800);
    --bs-btn-hover-bg: var(--ip-neutral-200);
    --bs-btn-hover-border-color: var(--ip-neutral-300);
    --bs-btn-active-color: var(--ip-neutral-900);
    --bs-btn-active-bg: var(--ip-neutral-200);
}

.btn-lg {
    padding: 12px 24px;
    font-size: 0.9375rem;
    border-radius: var(--ip-radius-md);
}

/* ----- Form Controls ----- */

.form-control {
    padding: 10px 14px;
    font-size: 0.9375rem;
    border-color: var(--ip-neutral-300);
    border-radius: var(--ip-radius-md);
    transition: border-color var(--ip-transition-fast), box-shadow var(--ip-transition-fast);
}

.form-control:hover {
    border-color: var(--ip-neutral-400);
}

.form-control:focus {
    border-color: var(--ip-accent);
    box-shadow: 0 0 0 3px rgba(132, 204, 22, 0.1);
}

.form-control::placeholder {
    color: var(--ip-neutral-400);
}

.form-label {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--ip-neutral-700);
    margin-bottom: 6px;
}

/* Floating labels */
.form-floating > .form-control {
    padding: 1.25rem 0.875rem 0.625rem;
    height: auto;
    min-height: 3.25rem;
}

.form-floating > label {
    padding: 1rem 0.875rem;
    color: var(--ip-neutral-500);
    font-weight: 400;
}

.form-floating > .form-control:focus ~ label,
.form-floating > .form-control:not(:placeholder-shown) ~ label {
    color: var(--ip-link);
    font-weight: 500;
}

.form-floating > .form-control-plaintext::placeholder,
.form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder,
.form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* Checkboxes */
.form-check-input:checked {
    background-color: var(--ip-accent);
    border-color: var(--ip-accent);
}

.form-check-input:focus {
    border-color: var(--ip-accent);
    box-shadow: 0 0 0 3px rgba(132, 204, 22, 0.1);
}

.form-check-label {
    font-size: 0.875rem;
    color: var(--ip-neutral-600);
}

/* Radios INSIDE the amber elections card use the gold action color (gold fill +
   dark ink dot) so the whole action zone is one cohesive amber module — matching
   the .btn-action CTA. Lime stays the default check color everywhere else. */
.elections-action-card .form-check-input:checked {
    background-color: var(--ip-action-bg);
    border-color: color-mix(in srgb, var(--ip-action-bg) 75%, black);
}

.elections-action-card .form-check-input:checked[type="radio"] {
    --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%233D2A06'/%3e%3c/svg%3e");
}

.elections-action-card .form-check-input:focus {
    border-color: color-mix(in srgb, var(--ip-action-bg) 75%, black);
    box-shadow: 0 0 0 3px rgba(246, 196, 83, 0.35);
}

/* Validation states */
.form-control.is-invalid,
.was-validated .form-control:invalid {
    border-color: var(--bs-danger);
}

.form-control.is-invalid:focus,
.was-validated .form-control:invalid:focus {
    box-shadow: 0 0 0 3px rgba(197, 48, 48, 0.1);
}

.text-danger {
    color: var(--bs-danger) !important;
    font-size: 0.8125rem;
}

/* Focus ring — unified */
.btn:focus-visible,
.form-control:focus-visible,
.form-check-input:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(132, 204, 22, 0.15);
}

/* ----- Input Groups ----- */

.input-group .btn {
    border-color: var(--ip-neutral-300);
    color: var(--ip-neutral-500);
    transition: all var(--ip-transition-fast);
}

.input-group .btn:hover {
    color: var(--ip-neutral-700);
    background-color: var(--ip-neutral-50);
}

/* ----- Alerts ----- */

.alert {
    border: none;
    border-radius: var(--ip-radius-md);
    font-size: 0.875rem;
    font-weight: 500;
    border-left: 3px solid;
}

.alert-danger {
    background-color: #FDF2F2;
    color: #9B2C2C;
    border-left-color: var(--bs-danger);
}

.alert-success {
    background-color: var(--ip-positive-bg);
    color: var(--ip-positive-text);
    border-left-color: var(--bs-success);
}

.alert-warning {
    background-color: #FFFFF0;
    color: #975A16;
    border-left-color: var(--bs-warning);
}

.alert-info {
    background-color: var(--ip-neutral-100);
    color: var(--ip-neutral-700);
    border-left-color: var(--ip-neutral-400);
}

/* Positive badge (Bootstrap's success contextual) — lime tint, not solid green.
   Keeps the "ink on lime / lime = positive" story instead of white-on-green. */
.text-bg-success {
    background-color: var(--ip-positive-bg) !important;
    color: var(--ip-positive-text) !important;
}

/* ----- Tables ----- */

.table {
    --bs-table-bg: transparent;
    --bs-table-striped-bg: var(--ip-neutral-50);
    font-size: 0.875rem;
}

.table > thead > tr > th {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-500);
    border-bottom-width: 1px;
    border-bottom-color: var(--ip-neutral-200);
    padding: 10px 16px;
}

.table > tbody > tr > td {
    padding: 12px 16px;
    border-bottom-color: var(--ip-neutral-100);
    vertical-align: middle;
}

.table > tbody > tr {
    transition: background-color var(--ip-transition-fast);
}

.table > tbody > tr:hover {
    background-color: var(--ip-neutral-50);
}

/* QRE matrix: categories down the left, taxing authorities across the top.
   Lives inside a bg-neutral-50 card, so the default row-hover would be
   invisible — suppress it. Row headers (the category names) opt out of the
   uppercase column-header treatment and get a quieter medium weight. The
   table sizes to its content (not full-width) so the columns pack to the
   left; .table-responsive supplies horizontal scroll when there are enough
   taxing authorities to overflow. The Total row gets a 2px rule above to
   separate the rolled-up per-authority totals from the line items, and
   inter-row hairlines are suppressed so the matrix reads as a clean grid. */
.qre-matrix {
    width: auto;
}

.qre-matrix > tbody > tr:hover {
    background-color: transparent;
}

.qre-matrix > tbody > tr > th[scope="row"] {
    font-size: 0.875rem;
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
    color: var(--ip-neutral-800);
    padding: 2px 16px;
    white-space: nowrap;
}

.qre-matrix > tbody > tr > td,
.qre-matrix > tbody > tr > th {
    border-bottom: none;
    white-space: nowrap;
}

.qre-matrix > tbody > tr > td {
    font-variant-numeric: tabular-nums;
    padding: 2px 16px;
}

/* Total row sits beneath the 2px separator; give it a bit of extra top
   padding so the rule has breathing room from the Computer Rental row above
   and from the Total figure below. */
.qre-matrix > tbody > tr.qre-matrix-total > th,
.qre-matrix > tbody > tr.qre-matrix-total > td {
    border-top: 2px solid var(--ip-neutral-200);
    border-bottom: none;
    font-weight: 600;
    color: var(--ip-neutral-900);
    padding-top: 8px;
    padding-bottom: 2px;
}

/* ----- Cards ----- */

.card {
    --bs-card-border-color: var(--ip-neutral-200);
    --bs-card-border-width: 1px;
    --bs-card-border-radius: var(--ip-radius-lg);
    --bs-card-cap-bg: transparent;
    --bs-card-bg: #fff;
    box-shadow: none;
}

.card-header {
    border-bottom-color: var(--ip-neutral-100);
    padding: 20px 24px 16px;
}

.card-body {
    padding: 20px 24px;
}

/* ----- Badges ----- */

.badge {
    font-weight: 500;
    font-size: 0.6875rem;
    letter-spacing: 0.02em;
    padding: 4px 8px;
}

/* ----- Nav Pills ----- */

.nav-pills .nav-link {
    color: var(--ip-neutral-600);
    font-weight: 500;
    font-size: 0.875rem;
    border-radius: var(--ip-radius-sm);
    transition: all var(--ip-transition-fast);
}

.nav-pills .nav-link:hover {
    color: var(--ip-neutral-800);
    background-color: var(--ip-neutral-100);
}

.nav-pills .nav-link.active,
.nav-pills .show > .nav-link {
    color: #fff;
    background-color: var(--ip-accent);
}

/* ----- Nav Tabs Underline (detail pages) ----- */

.nav-tabs-underline {
    border-bottom: 2px solid var(--ip-neutral-200);
    gap: 0;
}

.nav-tabs-underline .nav-link {
    color: var(--ip-neutral-500);
    font-weight: 500;
    font-size: 0.875rem;
    padding: 10px 20px;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    border-radius: 0;
    transition: all var(--ip-transition-fast);
}

.nav-tabs-underline .nav-link:hover {
    color: var(--ip-neutral-800);
    background: none;
    border-bottom-color: var(--ip-neutral-300);
}

.nav-tabs-underline .nav-link.active {
    color: var(--ip-accent);
    background: none;
    border-bottom-color: var(--ip-accent);
    font-weight: 600;
}

/* Attention-grabbing tab treatment: applied when the user has an open action
   on this tab (e.g., elections awaiting confirmation). Stays within the
   AwaitingElection warm-yellow palette used elsewhere in the app so the
   treatment reads as part of the system, not a bolt-on. */
.nav-tabs-underline .nav-link.requires-action {
    background: #FFF9DB;
    color: #975A16;
    font-weight: 600;
    border-top-left-radius: 6px;
    border-top-right-radius: 6px;
    padding-left: 16px;
    padding-right: 18px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.nav-tabs-underline .nav-link.requires-action:hover {
    color: #6B3E0E;
    background: #FFF4BC;
    border-bottom-color: transparent;
}

.nav-tabs-underline .nav-link.requires-action.active {
    color: #975A16;
    background: #FFF9DB;
    border-bottom-color: #D97706;
}

/* Broadcasting amber dot. Uses an animated box-shadow ring rather than a
   pseudo-element so we don't fight the parent's stacking. Pulse rests when
   the tab is active (user has arrived — no need to keep pulling them in) and
   degrades to a soft static halo for reduced-motion users. */
.elections-tab-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #D97706;
    flex-shrink: 0;
    box-shadow: 0 0 0 0 rgba(217, 119, 6, 0.55);
    animation: elections-tab-pulse 2.4s ease-out infinite;
}

@keyframes elections-tab-pulse {
    0%   { box-shadow: 0 0 0 0    rgba(217, 119, 6, 0.55); }
    80%  { box-shadow: 0 0 0 12px rgba(217, 119, 6, 0);    }
    100% { box-shadow: 0 0 0 12px rgba(217, 119, 6, 0);    }
}

.nav-tabs-underline .nav-link.requires-action.active .elections-tab-dot {
    animation: none;
    box-shadow: 0 0 0 4px rgba(217, 119, 6, 0.18);
}

@media (prefers-reduced-motion: reduce) {
    .elections-tab-dot {
        animation: none;
        box-shadow: 0 0 0 4px rgba(217, 119, 6, 0.18);
    }
}

/* ----- Status Dots ----- */

.status-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
}

.status-dot-provided {
    background-color: var(--ip-positive);
}

.status-dot-pending {
    background-color: var(--ip-neutral-300);
}

/* ----- Dropdowns ----- */

.dropdown-menu {
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-md);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
    padding: 4px;
    font-size: 0.875rem;
}

.dropdown-item {
    border-radius: var(--ip-radius-sm);
    padding: 7px 12px;
    color: var(--ip-neutral-700);
    transition: background-color var(--ip-transition-fast);
}

.dropdown-item:hover,
.dropdown-item:focus {
    background-color: var(--ip-neutral-100);
    color: var(--ip-neutral-900);
}

.dropdown-divider {
    border-color: var(--ip-neutral-100);
    margin: 4px 0;
}

.dropdown-toggle::after {
    vertical-align: 0.15em;
}

/* ----- Form Select ----- */

.form-select {
    font-size: 0.9375rem;
    border-color: var(--ip-neutral-300);
    border-radius: var(--ip-radius-md);
    padding: 10px 14px;
    transition: border-color var(--ip-transition-fast), box-shadow var(--ip-transition-fast);
}

.form-select:hover {
    border-color: var(--ip-neutral-400);
}

.form-select:focus {
    border-color: var(--ip-accent);
    box-shadow: 0 0 0 3px rgba(132, 204, 22, 0.1);
}

/* ----- Searchable Combobox ----- */

.ip-combobox {
    position: relative;
    display: inline-block;
}

.ip-combobox-input {
    width: 100%;
    font-size: 0.9375rem;
    line-height: 1.5;
    color: var(--ip-neutral-900);
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23A8A29E' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 14px 12px;
    border: 1px solid var(--ip-neutral-300);
    border-radius: var(--ip-radius-md);
    padding: 10px 36px 10px 14px;
    transition: border-color var(--ip-transition-fast), box-shadow var(--ip-transition-fast);
}

.ip-combobox-input::placeholder {
    color: var(--ip-neutral-500);
}

.ip-combobox-input:hover {
    border-color: var(--ip-neutral-400);
}

.ip-combobox-input:focus {
    outline: none;
    border-color: var(--ip-accent);
    box-shadow: 0 0 0 3px rgba(132, 204, 22, 0.1);
}

/* When a value is selected, hide the chevron — the clear button takes its slot */
.ip-combobox:has([data-combobox-value]:not([value=""])) .ip-combobox-input {
    background-image: none;
}

.ip-combobox-clear {
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--ip-neutral-400);
    border-radius: var(--ip-radius-sm);
    cursor: pointer;
    transition: color var(--ip-transition-fast), background-color var(--ip-transition-fast);
}

.ip-combobox-clear:hover {
    color: var(--ip-neutral-700);
    background-color: var(--ip-neutral-50);
}

.ip-combobox-clear[hidden] {
    display: none;
}

.ip-combobox-panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 20;
    max-height: 280px;
    overflow-y: auto;
    margin: 0;
    padding: 4px;
    list-style: none;
    background-color: #fff;
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-md);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
}

.ip-combobox-panel[hidden] {
    display: none;
}

.ip-combobox-panel li {
    padding: 8px 12px;
    font-size: 0.9375rem;
    color: var(--ip-neutral-700);
    border-radius: var(--ip-radius-sm);
    cursor: pointer;
    transition: background-color var(--ip-transition-fast);
}

.ip-combobox-panel li.is-active,
.ip-combobox-panel li:hover {
    background-color: var(--ip-neutral-50);
    color: var(--ip-neutral-900);
}

.ip-combobox-panel li[hidden] {
    display: none;
}

.ip-combobox-no-match {
    color: var(--ip-neutral-400) !important;
    font-style: italic;
    cursor: default !important;
    background-color: transparent !important;
}

/* ----- Form Switch ----- */

.form-switch .form-check-input {
    width: 2.5em;
    height: 1.25em;
    cursor: pointer;
}

.form-switch .form-check-input:checked {
    background-color: var(--ip-accent);
    border-color: var(--ip-accent);
}

/* Bootstrap bakes a blue thumb into the switch's background-image on focus.
   Keep the off-state focused thumb neutral (matching the resting thumb) so it
   never flashes brand-foreign blue. Checked+focused still gets Bootstrap's white
   thumb, and our lime focus ring (from .form-check-input:focus) is unaffected. */
.form-switch .form-check-input:not(:checked):focus {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280,0,0,0.25%29'/%3e%3c/svg%3e");
}

/* ----- Breadcrumbs ----- */

.breadcrumb {
    --bs-breadcrumb-divider-color: var(--ip-neutral-400);
    --bs-breadcrumb-item-active-color: var(--ip-neutral-600);
    margin-bottom: 0;
}

.breadcrumb-item a {
    color: var(--ip-neutral-500);
    text-decoration: none;
    transition: color var(--ip-transition-fast);
}

.breadcrumb-item a:hover {
    color: var(--ip-accent);
}

/* ----- Progress Bars ----- */

.progress {
    border-radius: 2px;
    overflow: hidden;
}

.progress-bar {
    transition: width 0.4s ease;
}

/* ----- Modals ----- */

.modal-backdrop.show {
    opacity: 0.3;
}

.modal-content {
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-lg);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
}

/* ----- Accordion ----- */

.accordion {
    --bs-accordion-border-color: var(--ip-neutral-200);
    --bs-accordion-border-radius: var(--ip-radius-md);
    --bs-accordion-btn-padding-x: 20px;
    --bs-accordion-btn-padding-y: 16px;
    --bs-accordion-body-padding-x: 20px;
    --bs-accordion-body-padding-y: 16px;
    --bs-accordion-active-bg: var(--ip-neutral-50);
    --bs-accordion-active-color: var(--ip-neutral-900);
    --bs-accordion-btn-focus-box-shadow: 0 0 0 3px rgba(132, 204, 22, 0.1);
}

.accordion-button {
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--ip-neutral-800);
}

/* ----- Promo Banner ----- */

.comarketing-promo-inner {
    display: flex;
    border-radius: var(--ip-radius-lg);
    background: linear-gradient(135deg, var(--ip-accent-subtle) 0%, #fff 100%);
    border: 1px solid var(--ip-accent-subtle-hover);
    overflow: hidden;
}

.comarketing-promo-accent {
    width: 4px;
    flex-shrink: 0;
    background-color: var(--ip-accent);
}

.comarketing-promo-content {
    padding: 20px 24px;
}

.comarketing-promo-headline {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--ip-neutral-900);
    margin-bottom: 6px;
}

.comarketing-promo-body {
    font-size: 0.8125rem;
    color: var(--ip-neutral-600);
    line-height: 1.6;
    margin-bottom: 16px;
}


.accordion-button:not(.collapsed) {
    color: var(--ip-neutral-900);
    font-weight: 600;
}

.accordion-button::after {
    width: 14px;
    height: 14px;
    background-size: 14px;
}

.accordion-body {
    font-size: 0.875rem;
    color: var(--ip-neutral-600);
    line-height: 1.7;
    border-top: 1px solid var(--ip-neutral-100);
}

.faq-short-answer {
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--ip-neutral-800);
    margin-bottom: 16px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--ip-neutral-100);
}


/* =============================================================================
   6. APP LAYOUT (sidebar + main content)
   ============================================================================= */

/* ----- Wrapper ----- */

.app-wrapper {
    display: flex;
    min-height: 100vh;
}

/* ----- Sidebar ----- */

.app-sidebar {
    width: var(--ip-sidebar-width);
    flex-shrink: 0;
    flex-direction: column;
    background:
        linear-gradient(134deg, rgba(12, 12, 14, 0) 70%, rgba(0, 0, 0, 0.55) 94%),
        radial-gradient(circle at 16px 180px, rgba(0, 0, 0, 0) 10px, rgba(0, 0, 0, 0.30) 760px),
        radial-gradient(circle at 50% 0%, #161617 0%, #0c0c0e 70%);
    border-right: none;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 1030;
    overflow-y: auto;
}

.app-sidebar-header {
    padding: 50px 20px 16px 30px;
}

/* Logo — stacked SVG wordmark; light/dark variant chosen per surface in markup */
.app-logo {
    display: inline-flex;
    text-decoration: none;
}

.app-logo img {
    display: block;
    width: auto;
    height: 30px;
}

.auth-brand-panel .app-logo img { height: 76px; }

.app-sidebar-nav {
    flex: 1;
    padding: 0 20px;
    overflow-y: auto;
}

.app-sidebar-footer {
    padding: 16px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

/* ----- Sidebar Nav Items ----- */

.sidebar-nav-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.sidebar-nav-divider {
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    margin: 12px 12px;
}

.sidebar-nav-group-label {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(255, 255, 255, 0.4);
    padding: 24px 12px 6px;
}

.sidebar-nav-item {
    margin-bottom: 2px;
}

.sidebar-nav-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border-radius: var(--ip-radius-sm);
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    transition: background-color var(--ip-transition-fast), color var(--ip-transition-fast);
}

.sidebar-nav-link:hover {
    background-color: rgba(255, 255, 255, 0.1);
    color: #fff;
}

.sidebar-nav-link.active {
    background-color: rgba(255, 255, 255, 0.15);
    color: #fff;
    font-weight: 600;
}

.sidebar-nav-link.active svg {
    color: var(--ip-accent-on-dark);
}

/* ----- Sidebar User Menu ----- */

.sidebar-user-menu {
    display: flex;
    align-items: center;
    gap: 10px;
}

.sidebar-user-link {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    min-width: 0;
    text-decoration: none;
    border-radius: var(--ip-radius-sm);
    transition: opacity var(--ip-transition-fast);
}

.sidebar-user-link:hover {
    opacity: 0.8;
}

.sidebar-user-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.2);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 600;
    flex-shrink: 0;
}

.sidebar-user-info {
    flex: 1;
    min-width: 0;
}

.sidebar-user-name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-user-org {
    font-size: 0.6875rem;
    color: rgba(255, 255, 255, 0.5);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-logout-form {
    flex-shrink: 0;
}

.sidebar-logout-btn {
    background: none;
    border: none;
    padding: 6px;
    border-radius: var(--ip-radius-sm);
    color: rgba(255, 255, 255, 0.4);
    cursor: pointer;
    transition: color var(--ip-transition-fast), background-color var(--ip-transition-fast);
    display: flex;
    align-items: center;
    justify-content: center;
}

.sidebar-logout-btn:hover {
    color: #fff;
    background-color: rgba(255, 255, 255, 0.1);
}

/* ----- Main Content Area ----- */

.app-main {
    flex: 1;
    margin-left: var(--ip-sidebar-width);
    min-height: 100vh;
}

.app-content {
    padding: 40px 48px;
    max-width: 1200px;
}

/* ----- Mobile Header ----- */

.app-mobile-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--ip-neutral-200);
    background: #fff;
    position: sticky;
    top: 0;
    z-index: 1020;
}

.app-menu-toggle {
    background: none;
    border: none;
    padding: 6px;
    color: var(--ip-neutral-700);
    cursor: pointer;
    border-radius: var(--ip-radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color var(--ip-transition-fast);
}

.app-menu-toggle:hover {
    background-color: var(--ip-neutral-100);
}

/* ----- Offcanvas Sidebar ----- */

.app-sidebar-offcanvas {
    width: var(--ip-sidebar-width) !important;
    background:
        linear-gradient(134deg, rgba(12, 12, 14, 0) 70%, rgba(0, 0, 0, 0.55) 94%),
        radial-gradient(circle at 16px 180px, rgba(0, 0, 0, 0) 10px, rgba(0, 0, 0, 0.30) 760px),
        radial-gradient(circle at 50% 0%, #161617 0%, #0c0c0e 70%);
}

.app-sidebar-offcanvas .btn-close {
    filter: invert(1);
}

.app-sidebar-offcanvas .offcanvas-header {
    padding: 20px 20px 12px;
    border-bottom: none;
}

.app-sidebar-offcanvas .offcanvas-body {
    display: flex;
    flex-direction: column;
}

.app-sidebar-offcanvas .offcanvas-body .sidebar-nav-list {
    flex: 1;
}

/* ----- Responsive ----- */

@media (max-width: 991.98px) {
    .app-main {
        margin-left: 0;
    }

    .app-content {
        padding: 24px 16px;
    }
}


/* =============================================================================
   7. AUTH LAYOUT (split panel)
   ============================================================================= */

.auth-body {
    background-color: #fff;
}

.auth-wrapper {
    display: flex;
    min-height: 100vh;
}

/* Left branding panel */
.auth-brand-panel {
    width: 45%;
    max-width: 600px;
    background: linear-gradient(29deg, rgba(87, 199, 133, 1) 0%, rgba(237, 221, 83, 1) 100%);
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    padding: 48px 56px;
    position: relative;
    overflow: hidden;
}

.auth-brand-content {
    position: relative;
    z-index: 1;
}


.auth-brand-tagline {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, 0.6);
    margin: 0;
}

/* Right form panel */
.auth-form-panel {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 48px 24px;
}

.auth-form-container {
    width: 100%;
    max-width: 420px;
}

/* Auth typography */
.auth-title {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--ip-neutral-900);
    margin-bottom: 4px;
}

.auth-subtitle {
    font-size: 0.9375rem;
    color: var(--ip-neutral-500);
    margin-bottom: 32px;
}

.auth-link-small {
    font-size: 0.8125rem;
    color: var(--ip-link);
    text-decoration: none;
    font-weight: 500;
    transition: color var(--ip-transition-fast);
}

.auth-link-small:hover {
    text-decoration: underline;
    color: var(--ip-accent-hover);
}

/* Positive confirmation mark — lime disc + ink tick with a soft lime-tint halo.
   Reuses the brand's "confirmed / done" vocabulary for reassuring auth states
   (e.g. an already-accepted invitation) so they read as success, not error. */
.auth-confirm-mark {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background-color: var(--ip-positive);
    color: var(--ip-on-accent);
    box-shadow: 0 0 0 8px var(--ip-positive-bg);
    margin: 0 0 28px;
}

.auth-confirm-mark svg {
    display: block;
}

/* Auth mobile */
@media (max-width: 767.98px) {
    .auth-form-panel {
        padding: 32px 20px;
    }

    .auth-form-container {
        max-width: 100%;
    }
}


/* =============================================================================
   7b. ONBOARDING LAYOUT (focused, no navigation)
   ============================================================================= */

.onboarding-body {
    background-color: #fff;
}

.onboarding-header {
    border-bottom: none;
    background:
        linear-gradient(134deg, rgba(12, 12, 14, 0) 70%, rgba(0, 0, 0, 0.55) 94%),
        radial-gradient(circle at 16px 180px, rgba(0, 0, 0, 0) 10px, rgba(0, 0, 0, 0.30) 760px),
        radial-gradient(circle at 50% 0%, #161617 0%, #0c0c0e 70%);
    position: sticky;
    top: 0;
    z-index: 1020;
}

.onboarding-header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    max-width: 720px;
    margin: 0 auto;
    padding: 16px 24px;
}

.onboarding-brand {
    display: flex;
    align-items: center;
}

.onboarding-firm-name {
    display: flex;
    align-items: center;
    gap: 8px;
}

.onboarding-content {
    max-width: 720px;
    margin: 0 auto;
    padding: 48px 24px 80px;
}

@media (max-width: 575.98px) {
    .onboarding-content {
        padding: 32px 16px 64px;
    }

    .onboarding-header-inner {
        padding: 14px 16px;
    }
}


/* =============================================================================
   8. CUSTOM UTILITIES
   ============================================================================= */

/* Neutral text */
.text-neutral-400 { color: var(--ip-neutral-400) !important; }
.text-neutral-500 { color: var(--ip-neutral-500) !important; }
.text-neutral-600 { color: var(--ip-neutral-600) !important; }
.text-neutral-700 { color: var(--ip-neutral-700) !important; }
.text-neutral-900 { color: var(--ip-neutral-900) !important; }

/* Neutral backgrounds */
.bg-neutral-50  { background-color: var(--ip-neutral-50) !important; }
.bg-neutral-100 { background-color: var(--ip-neutral-100) !important; }
.bg-accent-subtle { background-color: var(--ip-accent-subtle) !important; }

/* Section spacing */
.section-gap { margin-bottom: 48px; }

/* Divider */
.divider {
    border: none;
    border-top: 1px solid var(--ip-neutral-200);
    margin: 24px 0;
}

/* Truncation */
.truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Hide number input spinners */
.no-spinners::-webkit-outer-spin-button,
.no-spinners::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.no-spinners {
    -moz-appearance: textfield;
}

/* ===== Stepper (multi-step flows) ===== */

.stepper {
    display: flex;
    align-items: center;
    gap: 0;
    margin-bottom: 48px;
}

.stepper-step {
    display: flex;
    align-items: center;
    gap: 10px;
}

.stepper-indicator {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 600;
    flex-shrink: 0;
    transition: all var(--ip-transition-normal);
}

.stepper-step.is-complete .stepper-indicator {
    background-color: var(--ip-accent);
    color: var(--ip-on-accent);
}

.stepper-step.is-active .stepper-indicator {
    background-color: var(--ip-accent);
    color: var(--ip-on-accent);
    box-shadow: 0 0 0 4px var(--ip-accent-subtle);
}

.stepper-step.is-upcoming .stepper-indicator {
    background-color: var(--ip-neutral-200);
    color: var(--ip-neutral-500);
}

.stepper-label {
    font-size: 0.8125rem;
    font-weight: 500;
    transition: color var(--ip-transition-normal);
}

.stepper-step.is-complete .stepper-label {
    color: var(--ip-neutral-700);
}

.stepper-step.is-active .stepper-label {
    color: var(--ip-neutral-900);
}

.stepper-step.is-upcoming .stepper-label {
    color: var(--ip-neutral-400);
}

.stepper-line {
    flex: 1;
    height: 1px;
    margin: 0 16px;
    transition: background-color var(--ip-transition-normal);
}

.stepper-line.is-complete {
    background-color: var(--ip-accent);
}

.stepper-line.is-incomplete {
    background-color: var(--ip-neutral-200);
}

/* Stepper responsive */
@media (max-width: 575.98px) {
    .stepper-label {
        display: none;
    }

    .stepper-line {
        margin: 0 8px;
    }
}

/* ===== Focused Flow Container ===== */

.flow-container {
    max-width: 640px;
}

.flow-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 32px;
    margin-top: 40px;
    border-top: 1px solid var(--ip-neutral-200);
}

/* ===== Selection Cards (radio-style choices) ===== */

.selection-card {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 20px;
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-lg);
    cursor: pointer;
    transition: border-color var(--ip-transition-fast), background-color var(--ip-transition-fast);
}

.selection-card:hover {
    border-color: var(--ip-neutral-300);
    background-color: var(--ip-neutral-50);
}

.selection-card.is-selected {
    border-color: var(--ip-accent);
    background-color: var(--ip-accent-subtle);
}

.selection-card .form-check-input {
    margin-top: 2px;
    flex-shrink: 0;
}

.selection-card-content {
    flex: 1;
}

.selection-card-title {
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--ip-neutral-800);
    margin-bottom: 2px;
}

.selection-card-description {
    font-size: 0.8125rem;
    color: var(--ip-neutral-500);
    line-height: 1.5;
}

.selection-card-badge {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ip-accent);
    background-color: var(--ip-accent-subtle);
    padding: 2px 8px;
    border-radius: 4px;
    margin-left: auto;
    flex-shrink: 0;
    align-self: center;
}

/* ===== Client List (searchable selection list) ===== */

.client-list-item {
    padding: 12px 16px;
    cursor: pointer;
    transition: background-color 150ms ease;
    border-bottom: 1px solid var(--ip-neutral-100);
}

.client-list-item:last-of-type {
    border-bottom: none;
}

.client-list-item:hover {
    background-color: var(--ip-neutral-50);
}

.client-list-item:active {
    background-color: var(--ip-neutral-100);
}

/* ===== NAICS Picker (New Opportunity) ===== */
/* Type-ahead over the official NAICS reference list. Flat panel — border, no shadow. */

.naics-results {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 20;
    max-height: 280px;
    overflow-y: auto;
    background-color: #fff;
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-lg);
}

.naics-option {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 10px 14px;
    background: none;
    border: none;
    border-bottom: 1px solid var(--ip-neutral-100);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--ip-transition-fast);
}

.naics-option:last-of-type {
    border-bottom: none;
}

.naics-option:hover,
.naics-option:focus-visible {
    background-color: var(--ip-neutral-50);
}

.naics-option-description {
    font-size: 0.875rem;
    color: var(--ip-neutral-900);
}

.naics-option-code {
    flex-shrink: 0;
    font-size: 0.75rem;
    color: var(--ip-neutral-400);
}

.naics-empty {
    padding: 16px 14px;
    font-size: 0.875rem;
    color: var(--ip-neutral-400);
    text-align: center;
}

/* ===== Estimate Readiness Panel (New Opportunity) ===== */
/* Tells the firm what each field unlocks. Describes evidence quality only —
   never a dollar figure, which we cannot know before the estimator runs. */

.readiness-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding-bottom: 16px;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--ip-neutral-200);
}

.readiness-item:last-of-type {
    padding-bottom: 0;
    margin-bottom: 0;
    border-bottom: none;
}

.readiness-icon {
    position: relative;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin-top: 3px;
    border: 1.5px solid var(--ip-neutral-300);
    border-radius: 50%;
}

.readiness-item.is-met .readiness-icon {
    background-color: var(--ip-positive);
    border-color: var(--ip-positive);
}

/* Ink tick on the lime circle, matching the confirmed-value indicator. */
.readiness-item.is-met .readiness-icon::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 4.5px;
    width: 3.5px;
    height: 7px;
    border-right: 1.5px solid var(--ip-ink);
    border-bottom: 1.5px solid var(--ip-ink);
    transform: rotate(45deg);
}

.readiness-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--ip-neutral-900);
    margin-bottom: 2px;
}

.readiness-item.is-met .readiness-title {
    color: var(--ip-positive-text);
}

.readiness-detail {
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--ip-neutral-500);
}

/* ===== Action Step (CTA + skip pattern) ===== */

.action-step-actions {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    margin-top: 40px;
}

.btn-skip {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--ip-neutral-500);
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: var(--ip-radius-sm);
    transition: color var(--ip-transition-fast);
    text-decoration: none;
}

.btn-skip:hover {
    color: var(--ip-accent);
}

/* ===== Confirmation Modal (Are you sure?) ===== */

.confirm-modal-overlay {
    position: fixed;
    inset: 0;
    background-color: rgba(0, 0, 0, 0.3);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 1050;
    padding: 24px;
}

.confirm-modal-overlay.is-visible {
    display: flex;
}

.confirm-modal {
    background: #fff;
    border-radius: var(--ip-radius-lg);
    border: 1px solid var(--ip-neutral-200);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
    max-width: 440px;
    width: 100%;
    padding: 28px;
}

.confirm-modal-title {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--ip-neutral-900);
    margin-bottom: 8px;
}

.confirm-modal-message {
    font-size: 0.875rem;
    color: var(--ip-neutral-500);
    line-height: 1.6;
    margin-bottom: 24px;
}

.confirm-modal-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}

/* ===== Revenue Unavailable (Custom-fee firms) ===== */

.revenue-na {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
    color: var(--ip-neutral-500);
}

.revenue-na-info {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    color: var(--ip-neutral-400);
    display: inline-flex;
    align-items: center;
    transition: color var(--ip-transition-fast);
}

.revenue-na-info:hover {
    color: var(--ip-link);
}

/* ===== Billing Rate Table ===== */

.billing-rate-table {
    width: 100%;
    font-size: 0.875rem;
}

.billing-rate-table th {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-500);
    padding: 10px 16px;
    border-bottom: 1px solid var(--ip-neutral-200);
    text-align: left;
}

.billing-rate-table th:last-child {
    text-align: right;
}

.billing-rate-table td {
    padding: 10px 16px;
    border-bottom: 1px solid var(--ip-neutral-100);
    vertical-align: middle;
    color: var(--ip-neutral-800);
}

.billing-rate-table td:last-child {
    text-align: right;
}

.billing-rate-table .rate-input-wrapper {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    justify-content: flex-end;
}

.billing-rate-table .rate-input {
    width: 76px;
    padding: 6px 10px;
    font-size: 0.875rem;
    font-weight: 500;
    text-align: right;
    border: 1px solid var(--ip-neutral-300);
    border-radius: var(--ip-radius-sm);
    color: var(--ip-neutral-800);
    transition: border-color var(--ip-transition-fast), box-shadow var(--ip-transition-fast);
}

.billing-rate-table .rate-input:hover {
    border-color: var(--ip-neutral-400);
}

.billing-rate-table .rate-input:focus {
    outline: none;
    border-color: var(--ip-accent);
    box-shadow: 0 0 0 3px rgba(132, 204, 22, 0.1);
}

.billing-rate-table .rate-suffix {
    font-size: 0.875rem;
    color: var(--ip-neutral-500);
    font-weight: 500;
}

/* ===== Import Modal Steps ===== */

.import-step {
    display: none;
}

.import-step.is-active {
    display: block;
}

.import-column-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat(8, auto);
    grid-auto-flow: column;
    gap: 6px 24px;
}

.import-column-item {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8125rem;
    padding: 4px 0;
}

.import-column-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    flex-shrink: 0;
}

.import-column-dot.is-required {
    background-color: var(--ip-accent);
}

.import-column-dot.is-optional {
    background-color: var(--ip-neutral-300);
}

.import-column-name {
    color: var(--ip-neutral-700);
}

.import-column-name.is-optional {
    color: var(--ip-neutral-400);
}

.import-upload-zone {
    border: 2px dashed var(--ip-neutral-300);
    border-radius: var(--ip-radius-lg);
    padding: 40px 24px;
    text-align: center;
    cursor: pointer;
    transition: border-color var(--ip-transition-fast), background-color var(--ip-transition-fast);
}

.import-upload-zone:hover,
.import-upload-zone.is-dragover {
    border-color: var(--ip-accent);
    background-color: var(--ip-accent-subtle);
}

.import-upload-zone.has-file {
    border-style: solid;
    border-color: var(--ip-accent);
    background-color: var(--ip-accent-subtle);
}

.import-mapping-table {
    width: 100%;
    font-size: 0.875rem;
}

.import-mapping-table th {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-500);
    padding: 10px 12px;
    border-bottom: 1px solid var(--ip-neutral-200);
}

.import-mapping-table td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--ip-neutral-100);
    vertical-align: middle;
}

.import-mapping-table .field-name {
    font-weight: 500;
    color: var(--ip-neutral-800);
}

.import-mapping-table .field-optional {
    font-size: 0.6875rem;
    color: var(--ip-neutral-400);
    font-weight: 400;
    margin-left: 4px;
}

.import-mapping-table .form-select {
    font-size: 0.8125rem;
    padding: 6px 10px;
    min-width: 200px;
}

.import-mapping-table tr.is-matched td {
    background-color: var(--ip-neutral-50);
}

.import-mapping-table .match-indicator {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.6875rem;
    font-weight: 500;
    margin-left: 8px;
}

.import-mapping-table .match-indicator.is-exact {
    color: var(--bs-success);
}

.import-mapping-table .match-indicator.is-fuzzy {
    color: var(--bs-warning);
}

.import-mapping-table tr.is-unmatched-required td:first-child {
    color: var(--bs-danger);
}

.import-alerts {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 16px;
}

.import-blocking-error {
    text-align: center;
    padding: 32px 24px;
}

.import-loading {
    display: none;
    text-align: center;
    padding: 48px 24px;
}

.import-loading.is-visible {
    display: block;
}

.import-loading-spinner {
    width: 32px;
    height: 32px;
    border: 2.5px solid var(--ip-neutral-200);
    border-top-color: var(--ip-accent);
    border-radius: 50%;
    animation: import-spin 0.7s linear infinite;
    margin: 0 auto 16px;
}

@keyframes import-spin {
    to { transform: rotate(360deg); }
}

/* Inline spinner for the template-download button (reuses import-spin). */
.template-btn-spinner {
    animation: import-spin 0.7s linear infinite;
    vertical-align: -2px;
}

/* Disabled state while the template is being prepared. */
#btnDownloadTemplate.is-busy {
    pointer-events: none;
    opacity: 0.75;
}

.import-loading-text {
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--ip-neutral-700);
    margin-bottom: 4px;
}

.import-loading-subtext {
    font-size: 0.8125rem;
    color: var(--ip-neutral-400);
}

/* ===== Elections — Action Required card + form ===== */
/* "Your Action Required" heading rendered as the gold action pill — same treatment
   as the study's status badge, so the panel heading and the status badge agree. */
.action-required-flag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px 4px 10px;
    margin-bottom: 14px;
    border-radius: 999px;
    background: var(--ip-action-bg);
    color: var(--ip-action-text);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

.action-required-flag svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.elections-action-card {
    background: #FFFFF0;
    border-radius: 24px;
    padding: 36px;
    max-width: 460px;
}

/* ===== Filings — Action Required panel =====
   Same warm-yellow palette as the Elections action card so the two
   action-required moments read as part of the same system. The panel sits at
   the natural width of its content (rather than .elections-action-card's
   460px cap) because the filings list is grouped, multi-line, and benefits
   from horizontal room when there are many taxing authorities / entities.

   Each group renders as: a bold header ("{Authority} for {Entity}") followed
   by a 2-column grid of "{Year} return" labels and their action button. The
   grid is built with justify-content: start so labels and buttons pack
   together on the left rather than stretching to the panel edges. */
.filings-action-panel {
    background: #FFFFF0;
    border-radius: 24px;
    padding: 36px;
    width: fit-content;
    max-width: 100%;
}

.filings-deliverables-link,
.elections-credit-determination-link,
.stalled-cancel-link,
.stalled-client-inputs-link {
    color: #975A16;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.filings-deliverables-link:hover,
.filings-deliverables-link:focus,
.elections-credit-determination-link:hover,
.elections-credit-determination-link:focus,
.stalled-cancel-link:hover,
.stalled-cancel-link:focus,
.stalled-client-inputs-link:hover,
.stalled-client-inputs-link:focus {
    color: #6B3E0E;
}

/* ===== Stalled — Action Required panel =====
   Same warm-yellow palette as the Elections action card and the Filings
   action panel so all three action-required surfaces read as part of the
   same system. Sized at fit-content so the panel hugs its copy rather than
   stretching to fill the page; the max-width cap prevents the long
   paragraph from running edge-to-edge on wide viewports. */
.stalled-action-panel {
    background: #FFFFF0;
    border-radius: 24px;
    padding: 36px;
    width: fit-content;
    max-width: 640px;
}

.filings-groups {
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.filings-group-header {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--ip-neutral-900);
    margin-bottom: 8px;
}

.filings-rows {
    display: grid;
    grid-template-columns: auto auto auto;
    column-gap: 12px;
    row-gap: 6px;
    justify-content: start;
    align-items: center;
}

.filings-row-year {
    font-size: 0.875rem;
    color: var(--ip-neutral-700);
    white-space: nowrap;
}

.filings-row-action {
    margin: 0;
}

/* Inline download icon for the deliverable associated with a filing
   requirement. Echoes the inline row-action pattern from §14 of the design
   guide (14px stroke icon, no label), but tinted with the warm-amber accent
   used elsewhere in the filings panel so it reads as part of this surface
   rather than the standard neutral row-action treatment. */
.filings-deliverable-download {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #975A16;
    transition: color var(--ip-transition-fast);
    flex-shrink: 0;
}

.filings-deliverable-download:hover,
.filings-deliverable-download:focus {
    color: #6B3E0E;
    outline: none;
}

/* Filed chip: small lime pill that doubles as an un-toggle button. Echoes
   the project's positive-tinted badge palette (lime tint bg / deep-lime text)
   with an inset 1px border to read as interactive — hover/focus deepens both
   the background and the border so it's clear the chip is clickable. */
.filings-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    font-size: 0.8125rem;
    font-weight: 500;
    border-radius: 999px;
    border: 1px solid transparent;
    background: transparent;
    cursor: pointer;
    transition: background-color var(--ip-transition-fast),
                border-color var(--ip-transition-fast),
                color var(--ip-transition-fast);
}

.filings-chip-filed {
    background-color: var(--ip-positive-bg);
    color: var(--ip-positive-text);
    border-color: #cfe89a;
}

.filings-chip-filed:hover,
.filings-chip-filed:focus {
    background-color: var(--ip-accent-subtle-hover);
    border-color: #b6d97a;
    color: var(--ip-positive-text);
    outline: none;
}

.filings-chip-filed svg {
    flex-shrink: 0;
}

.elections-radio,
.elections-checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    padding: 4px 0;
    font-size: 0.875rem;
}

.elections-radio .form-check-input,
.elections-checkbox .form-check-input {
    margin: 0;
    flex-shrink: 0;
}

.elections-tooltip-trigger {
    background: transparent;
    border: none;
    padding: 0;
    cursor: pointer;
    color: var(--ip-neutral-400);
    display: inline-flex;
    align-items: center;
    transition: color var(--ip-transition-fast);
}

.elections-tooltip-trigger:hover,
.elections-tooltip-trigger:focus {
    color: var(--ip-neutral-600);
    outline: none;
}

.elections-tooltip {
    z-index: 1080;
    max-width: 360px;
    background: #fff;
    color: var(--ip-neutral-700);
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-md);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    padding: 16px 18px;
    font-size: 0.8125rem;
    line-height: 1.5;
    overflow-y: auto;
}

.elections-tooltip-title {
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--ip-neutral-900);
    margin-bottom: 10px;
}

.elections-tooltip-section + .elections-tooltip-section {
    margin-top: 12px;
}

.elections-tooltip-subhead {
    font-weight: 600;
    color: var(--ip-neutral-900);
    margin-bottom: 4px;
}

.elections-tooltip p {
    margin: 0 0 8px 0;
}

.elections-tooltip p:last-child {
    margin-bottom: 0;
}

.elections-tooltip ul {
    margin: 0;
    padding-left: 18px;
}

.elections-tooltip ul li + li {
    margin-top: 4px;
}

/* ===== Dashboard "Action Required" cards =====
   Surfaces the studies the firm must act on at the top of the dashboard. Reuses the
   warm-amber action-required palette of the in-study cards (#FFFFF0 / #E6D78A / #975A16
   / #D97706) so the dashboard, the study detail, and the nav badge all read as one
   system. Each card is a link to the study detail, where the matching action UI lives. */
.action-required-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

/* On the dashboard the "Action Required" flag sits inline with the count pill —
   drop the flag's own bottom margin so the two pills align. */
.action-required-header .action-required-flag {
    margin-bottom: 0;
}

.action-required-title {
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: #8A5212;
    margin: 0;
}

.action-required-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 7px;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--ip-action-text);
    background: var(--ip-action-bg);
    border-radius: 999px;
    /* Pulses gold, matching the sidebar count and the action-status badges */
    box-shadow: 0 0 0 0 rgba(246, 196, 83, 0.55);
    animation: status-badge-pulse 2.6s ease-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .action-required-count {
        animation: none;
        box-shadow: 0 0 0 3px rgba(246, 196, 83, 0.22);
    }
}

/* Broadcasting amber dot — same technique as .elections-tab-dot (animated box-shadow
   ring), tuned a touch larger for the dashboard headline. */
.action-required-pulse {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #D97706;
    flex-shrink: 0;
    box-shadow: 0 0 0 0 rgba(217, 119, 6, 0.5);
    animation: action-required-pulse 2.4s ease-out infinite;
}

@keyframes action-required-pulse {
    0%   { box-shadow: 0 0 0 0    rgba(217, 119, 6, 0.5); }
    80%  { box-shadow: 0 0 0 12px rgba(217, 119, 6, 0);   }
    100% { box-shadow: 0 0 0 12px rgba(217, 119, 6, 0);   }
}

.action-required-sub {
    font-size: 0.875rem;
    color: var(--ip-neutral-500);
    margin: 0 0 16px;
}

.action-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 16px;
}

.action-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 18px 20px;
    background: #FFFFF0;
    border-radius: var(--ip-radius-lg);
    text-decoration: none;
    transition: background-color var(--ip-transition-fast),
                box-shadow var(--ip-transition-fast),
                transform var(--ip-transition-fast);
}

.action-card:hover,
.action-card:focus-visible {
    background: #FFFDE7;
    box-shadow: 0 6px 20px rgba(180, 83, 9, 0.12);
    transform: translateY(-2px);
    outline: none;
}

.action-card-flag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #975A16;
}

.action-card-client {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ip-neutral-900);
    line-height: 1.3;
}

.action-card-desc {
    font-size: 0.8125rem;
    color: var(--ip-neutral-600);
    line-height: 1.5;
}

.action-card-cta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
    font-size: 0.875rem;
    font-weight: 600;
    color: #B45309;
    transition: gap var(--ip-transition-fast);
}

.action-card:hover .action-card-cta,
.action-card:focus-visible .action-card-cta {
    gap: 10px;
}

@media (prefers-reduced-motion: reduce) {
    .action-required-pulse {
        animation: none;
        box-shadow: 0 0 0 4px rgba(217, 119, 6, 0.18);
    }

    .action-card:hover,
    .action-card:focus-visible {
        transform: none;
    }
}

/* ===== Sidebar nav badge (pending firm actions) =====
   Amber count pill on a nav item against the dark sidebar. Pulses to draw the eye,
   resting to a soft static halo when the item is active/hovered or for reduced-motion
   users. Mirrors the dashboard action-required accent so the two surfaces agree. */
.sidebar-nav-badge {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
    color: #3D2A06;
    background: #F6C453;
    border-radius: 999px;
    box-shadow: 0 0 0 0 rgba(246, 196, 83, 0.6);
    animation: sidebar-nav-badge-pulse 2.6s ease-out infinite;
}

@keyframes sidebar-nav-badge-pulse {
    0%   { box-shadow: 0 0 0 0   rgba(246, 196, 83, 0.55); }
    70%  { box-shadow: 0 0 0 8px rgba(246, 196, 83, 0);    }
    100% { box-shadow: 0 0 0 8px rgba(246, 196, 83, 0);    }
}

.sidebar-nav-link.active .sidebar-nav-badge,
.sidebar-nav-link:hover .sidebar-nav-badge {
    animation: none;
    box-shadow: 0 0 0 3px rgba(246, 196, 83, 0.22);
}

@media (prefers-reduced-motion: reduce) {
    .sidebar-nav-badge {
        animation: none;
        box-shadow: 0 0 0 3px rgba(246, 196, 83, 0.22);
    }
}

/* ===== Action-required status badge (Studies list) =====
   When a study has an open firm action (Election / Filing / Stalled), its status badge
   gains a pulsing dot so the list page carries the same attention signal as the dashboard
   cards and the study detail. The dot uses currentColor (the badge's own status color), so
   the ripple is amber for Election/Filing and red for Stalled without recoloring the badge —
   completing the dashboard → list → detail attention path. */
/* Action-required status badge — a solid GOLD pill matching the sidebar "Studies"
   count badge (#F6C453). The whole pill pulses (like the nav badge) rather than
   carrying a separate inner dot, so the nav badge, the dashboard count pill, and the
   status badges all read as one gold "attention" signal. */
.study-status-action {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    box-shadow: 0 0 0 0 rgba(246, 196, 83, 0.55);
    animation: status-badge-pulse 2.6s ease-out infinite;
}

/* The inner dot is redundant now the whole pill pulses — hide it (markup keeps it). */
.study-status-action .study-status-action-dot {
    display: none;
}

/* Explicit rgba (not color-mix) so the ring actually interpolates — color-mix does
   not animate reliably inside a keyframed box-shadow. */
@keyframes status-badge-pulse {
    0%   { box-shadow: 0 0 0 0   rgba(246, 196, 83, 0.55); }
    70%  { box-shadow: 0 0 0 8px rgba(246, 196, 83, 0);    }
    100% { box-shadow: 0 0 0 8px rgba(246, 196, 83, 0);    }
}

@media (prefers-reduced-motion: reduce) {
    .study-status-action {
        animation: none;
        box-shadow: 0 0 0 3px rgba(246, 196, 83, 0.22);
    }
}

/* ============================================================
   Qualification indicator — three squares that illuminate with the
   qualification tier (Moderate → Significant → High). Strength reads
   from the COUNT of lit squares; every lit square is the same olive
   green. Crisp and flat: solid fills, no borders/gradients/shadows.
   ============================================================ */
.qual-indicator {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    line-height: 1;
}

.qual-indicator-squares {
    display: inline-flex;
    gap: 3px;
}

.qual-square {
    width: 11px;
    height: 11px;
    border-radius: 3px;
    background-color: var(--ip-neutral-200);
}

.qual-square.is-lit {
    background-color: var(--bs-success);
}

.qual-indicator-label {
    font-size: 0.75rem;
    color: var(--ip-neutral-500);
}

/* ============================================================
   Estimate detail panel — the row that opens under a client to
   say what their estimate rests on and what would sharpen it.
   An inset stone surface, flat: no shadow, no gradient. The one
   piece of colour is the lime rule marking the ask that moves
   the estimate most.
   ============================================================ */
.insight-client {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.insight-client-name {
    min-width: 0;
}

.insight-client-title {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* The row's own marker for a client whose estimate is still standing on a benchmark. It wears
   the same gold the panel's "Considerable"/"Substantial" readings wear, so the row and the
   panel it opens are visibly the same statement. No pulse: that belongs to action-required. */
.insight-chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border: none;
    border-radius: 999px;
    background-color: color-mix(in srgb, var(--ip-action-bg) 32%, white);
    color: var(--ip-action-text);
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.insight-chip:hover {
    background-color: var(--ip-action-bg);
}

.insight-toggle,
.insight-toggle-spacer {
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
    margin-top: 1px;
}

.insight-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: var(--ip-radius-sm);
    background: transparent;
    color: var(--ip-neutral-400);
    cursor: pointer;
    transition: transform 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}

.insight-toggle:hover {
    background-color: var(--ip-neutral-100);
    color: var(--ip-neutral-700);
}

.insight-toggle[aria-expanded="true"] {
    transform: rotate(90deg);
    color: var(--ip-neutral-700);
}

.insight-row > .insight-cell {
    padding: 0 12px 16px 12px;
    border-top: none;
}

.insight-panel {
    background-color: var(--ip-neutral-50);
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-md);
    padding: 20px 24px;
}

/* The panel opens with two read-only fields: what the firm can change, and what the number
   rests on. Qualification likelihood stays on the row the panel hangs off; repeating it here
   would label what is already on screen. */
.insight-lede {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 16px 48px;
}

.insight-field-headroom {
    flex: 0 0 auto;
    min-width: 150px;
}

.insight-field-basis {
    flex: 1 1 340px;
    max-width: 70ch;
}

.insight-field-label {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-400);
    margin-bottom: 4px;
}

.insight-field-value {
    font-size: 0.9375rem;
    color: var(--ip-neutral-900);
    line-height: 1.55;
}

.insight-field-basis .insight-field-value {
    font-size: 0.875rem;
    color: var(--ip-neutral-700);
}

/* Room to improve, weighted by how much there is. Gold is the portal's needs-you colour, so
   the client with the most to gain wears it outright and the next step down wears a tint of
   it; the step below that is an informational blue, because stone on a stone panel does not
   read at all, and the quietest step keeps the stone. Nothing left to ask for is lime with a check —
   a finished state in the portal's done colour, not an absence. No pulse anywhere here; that
   is reserved for the action-required system. */
.insight-headroom {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.35;
}

.insight-headroom-0 {
    background-color: var(--ip-positive-bg);
    color: var(--ip-positive-text);
}

.insight-headroom-4 {
    background-color: var(--ip-action-bg);
    color: var(--ip-action-text);
}

.insight-headroom-3 {
    background-color: color-mix(in srgb, var(--ip-action-bg) 32%, white);
    color: var(--ip-action-text);
}

.insight-headroom-2 {
    background-color: var(--ip-info-bg);
    color: var(--ip-info-text);
}

.insight-headroom-1 {
    background-color: var(--ip-neutral-50);
    color: var(--ip-neutral-500);
    box-shadow: inset 0 0 0 1px var(--ip-neutral-200);
}

/* The ask list earns a real prompt rather than an eyebrow: it is the one thing in the panel
   the firm is meant to act on, and the rule above it now separates the readings from the
   asking. */
.insight-prompt {
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--ip-neutral-900);
    margin: 20px 0 10px 0;
    padding-top: 20px;
    border-top: 1px solid var(--ip-neutral-200);
}

.insight-ask {
    display: flex;
    align-items: center;
    /* Not space-between: on a wide panel that threw the field to the far edge, half a
       screen from the question it answers. A bounded text column instead keeps the two
       together AND keeps the controls aligned down the list, which is what space-between
       was really buying. */
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 8px 24px;
    padding: 12px 0 12px 12px;
    border-left: 2px solid var(--ip-neutral-200);
    border-bottom: 1px solid var(--ip-neutral-200);
}

.insight-ask.is-strongest {
    border-left-color: var(--ip-accent);
}

.insight-ask-text {
    flex: 0 1 520px;
    min-width: 0;
}

.insight-ask-prompt {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--ip-neutral-900);
}

.insight-ask-tag {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 7px;
    border-radius: 999px;
    background-color: var(--ip-accent-subtle);
    color: var(--ip-neutral-800);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    vertical-align: 1px;
}

.insight-ask-why {
    font-size: 0.75rem;
    color: var(--ip-neutral-500);
    margin-top: 2px;
}

.insight-ask-form {
    display: flex;
    /* stretch, not center: the Save button then takes its height from the field beside it
       rather than from its own padding, which is what left the two mismatched. */
    align-items: stretch;
    gap: 8px;
    flex: 0 0 auto;
}

/* One width for every kind of answer — figure, percentage, state — so the Save buttons line
   up in a column however many asks are showing. Wide enough for a figure in the billions
   ("$1,000,000,000"), which is an ordinary gross receipts number, not an outlier. */
.insight-ask-form .insight-value,
.insight-ask-form .insight-state {
    width: 196px;
}

/* The industry picker: same footprint as the other answers, with its results hanging
   below rather than widening the row. */
.insight-industry {
    position: relative;
    width: 196px;
}

.insight-industry .naics-results {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 5;
}

.insight-percent {
    position: relative;
    display: flex;
}

.insight-percent .insight-value {
    width: 196px;
    padding-right: 24px;
}

.insight-percent-sign {
    position: absolute;
    top: 50%;
    right: 9px;
    transform: translateY(-50%);
    font-size: 0.8125rem;
    color: var(--ip-neutral-400);
    pointer-events: none;
}

/* Saving. Reuses the import spinner so a wait looks the same everywhere in the portal.
   Not the disabled attribute: the click has already submitted, and disabling a control
   mid-submit is a good way to lose the post. */
.insight-save {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    white-space: nowrap;
}

.insight-save.is-busy {
    pointer-events: none;
    opacity: 0.75;
}

.insight-save-spinner {
    animation: import-spin 0.7s linear infinite;
}

.insight-note {
    font-size: 0.75rem;
    color: var(--ip-neutral-500);
    line-height: 1.6;
    margin-top: 12px;
}

@media (max-width: 575.98px) {
    .insight-ask-form {
        width: 100%;
    }

    .insight-ask-form .insight-value,
    .insight-ask-form .insight-state {
        flex: 1 1 auto;
        width: auto;
    }
}

/* ============================================================
   KPI cards (/Opportunities). Three figures across the top of the
   list. One of the labels carries the firm's own name, so it can
   run to two lines while its neighbours sit on one — which left the
   row ragged at the bottom and the figures off a shared baseline.

   The card is a flex column of fixed parts: a label that always
   occupies two lines' worth of space, the figure, and a note pushed
   to the floor. The labels clamp at two lines rather than growing a
   third, with the full text on the title attribute.
   ============================================================ */
.kpi-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 24px;
    border-radius: var(--ip-radius-lg);
    background-color: var(--ip-neutral-50);
}

.kpi-card-label {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.8em;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    line-height: 1.4;
    color: var(--ip-neutral-400);
    margin-bottom: 4px;
}

.kpi-card-figure {
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.2;
    color: var(--ip-neutral-900);
}

.kpi-card-note {
    margin-top: auto;
    padding-top: 4px;
    font-size: 0.75rem;
    color: var(--ip-neutral-500);
}

/* ============================================================
   Pipeline progress strip (/Opportunities). Between naming a client
   and seeing their credit there are two real stages — research the
   business, then size the credit — and until now the page said
   nothing while they ran. A firm refreshed to watch industries and
   then estimates appear.

   The showpiece here is deliberately not a spinner: it is the work
   itself. The feed lists what research has just learned, in the
   firm's words, newest first. A spinner says "wait"; this says what
   you are waiting for and proves it is moving.

   One motion only: a tick that travels the UNFILLED part of the
   rail. It never fakes progress — the fill is the honest count, and
   the tick is just the sound of the engine. Frozen for anyone who
   asked for less movement.
   ============================================================ */
.pipeline-strip {
    background-color: var(--ip-neutral-50);
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-lg);
    padding: 20px 24px;
    margin-bottom: 28px;
}

.pipeline-strip-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

.pipeline-strip-eyebrow {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-500);
}

.pipeline-strip.is-done .pipeline-strip-eyebrow {
    color: var(--ip-positive-text);
}

.pipeline-strip-count {
    font-size: 0.8125rem;
    color: var(--ip-neutral-500);
    font-variant-numeric: tabular-nums;
}

/* The rail: filled by what is actually done, with the engine running on the rest of it. */
.pipeline-rail {
    position: relative;
    height: 3px;
    margin-top: 12px;
    border-radius: 2px;
    background-color: var(--ip-neutral-200);
    overflow: hidden;
}

.pipeline-rail-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0;
    background-color: var(--ip-accent);
    border-radius: 2px;
    transition: width 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.pipeline-rail-tick {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 88px;
    border-radius: 2px;
    background: linear-gradient(90deg, transparent, rgba(var(--ip-accent-rgb), 0.55), transparent);
    animation: pipeline-sweep 2.4s linear infinite;
}

@keyframes pipeline-sweep {
    from { transform: translateX(-88px); }
    to { transform: translateX(100vw); }
}

/* Nothing running yet: the rail holds its place and stops pretending. */
.pipeline-strip.is-idle .pipeline-rail-tick,
.pipeline-strip.is-done .pipeline-rail-tick {
    display: none;
}

.pipeline-feed {
    margin-top: 18px;
}

.pipeline-feed-label {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-400);
    margin-bottom: 8px;
}

.pipeline-feed-row {
    display: flex;
    align-items: baseline;
    gap: 16px;
    padding: 5px 0;
    font-size: 0.875rem;
    animation: pipeline-arrive 220ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

@keyframes pipeline-arrive {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: none; }
}

.pipeline-feed-client {
    flex: 0 0 190px;
    font-weight: 500;
    color: var(--ip-neutral-900);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pipeline-feed-found {
    color: var(--ip-neutral-600);
    min-width: 0;
}

.pipeline-feed-empty {
    font-size: 0.8125rem;
    color: var(--ip-neutral-400);
}

@media (max-width: 575.98px) {
    .pipeline-feed-row {
        display: block;
    }

    .pipeline-feed-client {
        flex: none;
        white-space: normal;
    }
}

@media (prefers-reduced-motion: reduce) {
    .pipeline-rail-tick {
        animation: none;
        display: none;
    }

    .pipeline-rail-fill {
        transition: none;
    }

    .pipeline-feed-row {
        animation: none;
    }
}

/* A modal that asks the reader to decide something: a display-face question, body copy
   with room to breathe, and two buttons of equal weight with the encouraged one on the
   right. Established by the intake's "Start with your whole list?" and shared from there,
   so a second question does not arrive in a different voice. */
.modal-ask-title {
    font-family: var(--ip-font-display);
    font-size: 1.375rem;
    font-weight: 600;
    color: var(--ip-ink);
    margin-bottom: 12px;
}

.modal-ask-copy {
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--ip-neutral-600);
    margin-bottom: 12px;
}

.modal-ask-body {
    padding: 30px 30px 24px;
}

/* ============================================================
   Full-screen task pages (client intake, Add Client Opportunity).
   An ink bar carrying one control — the way out — and nothing else.
   No sidebar, no breadcrumb, no second escape: every extra exit is
   an invitation to abandon the one thing the page is for, and the
   page writes nothing until its own finish action, so leaving has
   to ask first.
   ============================================================ */
.fs-body {
    background: #fff;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.fs-bar {
    height: 56px;
    background: var(--ip-ink);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 0 16px;
    flex-shrink: 0;
}

.fs-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: var(--ip-radius-sm);
    background: none;
    color: rgba(255, 255, 255, 0.62);
    cursor: pointer;
    transition: color var(--ip-transition-fast), background-color var(--ip-transition-fast);
}

.fs-close:hover {
    color: #fff;
    background-color: rgba(255, 255, 255, 0.1);
}

.fs-close:focus-visible {
    outline: 2px solid var(--ip-accent);
    outline-offset: 2px;
}

.fs-stage {
    flex: 1;
    display: flex;
    justify-content: center;
    padding: 56px 24px 96px;
}

.fs-panel {
    width: 100%;
    max-width: 720px;
}

.fs-panel.is-wide {
    max-width: 1080px;
}

@media (max-width: 640px) {
    .fs-stage {
        padding: 32px 16px 64px;
    }
}

/* ============================================================
   Step wizard (/Studies/New). Four steps, one open at a time, each
   collapsing to a line of what was chosen. The rail on the left
   carries the count and the distance: solid lime behind you, dotted
   stone ahead. The point is that a firm holds one decision in their
   head at a time while still seeing that there are only four.

   Flat throughout: the marker states are a fill change, not a glow,
   and the walked track is a colour change, not an animation.
   ============================================================ */
.wizard {
    display: flex;
    align-items: flex-start;
    gap: 28px;
}

.wizard-rail {
    flex: 0 0 112px;
    position: sticky;
    top: 24px;
    margin: 0;
    padding: 4px 0 0 0;
    list-style: none;
}

.wizard-rail-step {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 38px;
}

.wizard-rail-step:last-child {
    padding-bottom: 0;
}

/* The track between markers. Dotted while unwalked, solid lime once passed. */
.wizard-rail-step:not(:last-child)::before {
    content: '';
    position: absolute;
    left: 19px;
    top: 44px;
    bottom: 6px;
    width: 2px;
    background-image: linear-gradient(var(--ip-neutral-300) 55%, transparent 0);
    background-size: 2px 7px;
    background-repeat: repeat-y;
}

.wizard-rail-step.is-walked::before {
    background-image: none;
    background-color: var(--ip-accent);
}

.wizard-rail-marker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: var(--ip-neutral-100);
    color: var(--ip-neutral-400);
    font-size: 0.9375rem;
    font-weight: 700;
    line-height: 1;
    transition: background-color var(--ip-transition-fast), color var(--ip-transition-fast);
}

.wizard-rail-step.is-active .wizard-rail-marker {
    background-color: var(--ip-accent);
    color: var(--ip-on-accent);
    font-size: 1.125rem;
}

.wizard-rail-step.is-complete .wizard-rail-marker {
    background-color: var(--ip-positive-bg);
    color: var(--ip-positive-text);
}

.wizard-rail-label {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-400);
}

.wizard-rail-step.is-active .wizard-rail-label {
    color: var(--ip-neutral-900);
}

.wizard-rail-step.is-complete .wizard-rail-label {
    color: var(--ip-neutral-600);
}

.wizard-steps {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.wizard-step {
    background-color: #fff;
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-lg);
}

.wizard-step.is-active {
    border-color: var(--ip-neutral-300);
}

.wizard-step-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    padding: 16px 20px;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
}

.wizard-step.is-active .wizard-step-head,
.wizard-step.is-upcoming .wizard-step-head {
    cursor: default;
}

.wizard-step-head:focus-visible {
    outline: 2px solid var(--ip-accent);
    outline-offset: -2px;
    border-radius: var(--ip-radius-lg);
}

.wizard-step-heading {
    min-width: 0;
}

.wizard-step-title {
    display: block;
    font-family: var(--ip-font-display);
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--ip-neutral-900);
    line-height: 1.3;
}

.wizard-step.is-upcoming .wizard-step-title {
    color: var(--ip-neutral-400);
}

/* The open step's body explains itself; a hint under the title only repeats it. Kept in
   the markup for the collapsed states to have something to replace. */
.wizard-step-hint {
    display: none;
}

/* Collapsed, a step is one line: a soft label naming what was decided, then the decision.
   The label is deliberately quieter than the answer — the answer is what a firm scans for. */
.wizard-step-label {
    display: none;
    font-family: var(--ip-font-family);
    font-size: 0.9375rem;
    font-weight: 400;
    color: var(--ip-neutral-500);
    margin-right: 6px;
}

.wizard-step.is-complete .wizard-step-label {
    display: inline;
}

.wizard-step.is-complete .wizard-step-title {
    display: none;
}

/* What was chosen, once the step is behind them. */
.wizard-step-summary {
    display: none;
    font-size: 0.9375rem;
    color: var(--ip-neutral-800);
}

.wizard-step.is-complete .wizard-step-summary {
    display: inline;
}

.wizard-step-change {
    display: none;
    flex: 0 0 auto;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ip-link);
}

.wizard-step.is-complete .wizard-step-change {
    display: inline;
}

.wizard-step-body {
    padding: 0 20px 20px 20px;
}

.wizard-step:not(.is-active) .wizard-step-body {
    display: none;
}

.wizard-step-actions {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-top: 20px;
}

/* Stacked, the rail turns into a strip above the cards: same four markers, same walked
   track, read left to right. */
@media (max-width: 991.98px) {
    .wizard {
        display: block;
    }

    .wizard-rail {
        position: static;
        display: flex;
        padding: 0;
        margin-bottom: 24px;
    }

    .wizard-rail-step {
        flex: 1 1 0;
        flex-direction: column;
        gap: 6px;
        padding-bottom: 0;
        text-align: center;
    }

    .wizard-rail-step:not(:last-child)::before {
        top: 19px;
        bottom: auto;
        left: calc(50% + 26px);
        right: calc(-50% + 26px);
        width: auto;
        height: 2px;
        background-image: linear-gradient(90deg, var(--ip-neutral-300) 55%, transparent 0);
        background-size: 7px 2px;
        background-repeat: repeat-x;
    }
}

/* ============================================================
   The estimate card on /Studies/New — what this client's study is
   worth, shown before the firm is asked for a contact or a send
   method. It leads the page because it is the only thing here the
   firm cannot work out for themselves, and because the decision it
   offers (sharpen this, or send it as it stands) has to come before
   the paperwork rather than after it.

   An inset stone surface, like the estimate panel on /Opportunities,
   and it reuses that panel's ask rows (.insight-ask and friends) so
   a firm meets the same questions in the same shape in both places.
   ============================================================ */
/* The card itself is just a container inside the step; the inset panel holds the figures
   and the decision below it belongs to the step, not to the panel. */
.estimate-card {
    display: block;
}

.estimate-card-readings {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px 24px;
    background-color: var(--ip-neutral-50);
    border: 1px solid var(--ip-neutral-200);
    border-radius: var(--ip-radius-md);
    padding: 20px 24px;
}

/* Credit, then how much better it could get — the figure and its caveat together. */
.estimate-card-main {
    flex: 1 1 170px;
    min-width: 0;
}

.estimate-card-headroom {
    margin-top: 18px;
}

.estimate-card-qualification {
    flex: 0 0 auto;
    white-space: nowrap;
}

.estimate-card-label {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-400);
    margin-bottom: 6px;
}

/* The figure carries the page. Same weight as the KPI numbers on the Opportunities
   dashboard, so a firm reads them as the same kind of thing. */
.estimate-card-amount {
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.15;
    color: var(--ip-neutral-900);
}

.estimate-card-amount.is-absent {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--ip-neutral-400);
}

.estimate-card-years {
    font-size: 0.75rem;
    color: var(--ip-neutral-500);
    margin-top: 4px;
}

.estimate-card-reading {
    padding-top: 2px;
}

.estimate-card-basis {
    font-size: 0.875rem;
    color: var(--ip-neutral-700);
    line-height: 1.6;
    margin: 18px 0 0 0;
    padding-top: 16px;
    border-top: 1px solid var(--ip-neutral-200);
}

.estimate-card-basis-label {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ip-neutral-400);
    margin-right: 8px;
}

/* The decision. Deliberately two plain buttons rather than a question with a default:
   sending as it stands is a legitimate answer, not a failure to comply. */
/* Out on the step's own surface: the panel above is what we know, this is what the firm
   does about it. */
.estimate-card-fork {
    margin-top: 24px;
}

.estimate-card-ask {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--ip-neutral-900);
    max-width: 64ch;
    margin-bottom: 18px;
}

.estimate-card-fork-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.estimate-card-asks {
    margin-top: 20px;
    padding-top: 4px;
    border-top: 1px solid var(--ip-neutral-200);
}

/* The caveat is read before the button that ends the step, not after it. */
.estimate-card-done {
    margin-top: 16px;
}

.estimate-card-done-note {
    font-size: 0.75rem;
    color: var(--ip-neutral-500);
    line-height: 1.55;
    max-width: 72ch;
    margin-bottom: 10px;
}

.estimate-card-empty {
    font-size: 0.875rem;
    color: var(--ip-neutral-500);
}

.estimate-step-loading {
    font-size: 0.8125rem;
    color: var(--ip-neutral-400);
    padding: 8px 0;
}

/* ===== Agreement (Master Services Agreement) =====
   The rendered agreement as the firm's signer reads it. Markup comes from
   AgreementDocumentRenderer (SharedLibraries); OpsPortal carries an equivalent rule set for
   its preview. Same faces as the rest of the portal (and as the PDF, which embeds them). */
.agreement-document { font-family: var(--ip-font-family); font-size: 0.9375rem; line-height: 1.65; color: var(--ip-neutral-800); background: #fff; border: 1px solid var(--ip-neutral-200); border-radius: var(--ip-radius-md); padding: 32px 40px; }
.agreement-document-title { font-family: var(--ip-font-display); text-align: center; font-weight: 600; font-size: 1.375rem; margin-bottom: 2px; }
.agreement-document-version { text-align: center; color: var(--ip-neutral-500); font-size: 0.8125rem; margin-bottom: 24px; }
.agreement-body h1 { font-size: 1.25rem; font-weight: 600; margin: 20px 0 8px; }
.agreement-body h2 { font-size: 1.0625rem; font-weight: 600; margin: 16px 0 6px; }
.agreement-body h3 { font-size: 0.9375rem; font-weight: 600; margin: 12px 0 4px; }
.agreement-body p { margin: 0 0 10px; }
.agreement-body ol, .agreement-body ul { padding-left: 1.6em; margin: 0 0 10px; }
.agreement-body li { margin-bottom: 4px; }
.agreement-body hr { border: 0; border-top: 1px solid var(--ip-neutral-300); margin: 16px 0; }
.agreement-token { background: var(--ip-accent-subtle); border-radius: 3px; padding: 0 3px; }
.agreement-token[data-blank="true"] { background: var(--ip-neutral-100); color: var(--ip-neutral-400); letter-spacing: 0.05em; }
/* The cost share is Incentive Partner's term, not something the firm supplied — no highlight. */
.agreement-token-CostSharePercent { background: none; padding: 0; }
.agreement-signatures { display: flex; gap: 40px; margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--ip-neutral-200); }
.agreement-signature { flex: 1; min-width: 0; }
.agreement-signature-party { font-weight: 700; margin-bottom: 18px; }
.agreement-signature-line { margin-bottom: 4px; font-size: 0.875rem; }
.agreement-signature-label { color: var(--ip-neutral-500); }
.agreement-signature-script { font-family: 'Allura', 'Brush Script MT', cursive; font-size: 1.75rem; line-height: 1; border-bottom: 1px solid var(--ip-neutral-800); display: inline-block; min-width: 200px; padding: 0 6px 2px; }

/* The reading pane scrolls on its own so the signature form stays in reach. */
.agreement-scroll { max-height: 60vh; overflow-y: auto; }

/* The signing block: sits below the document; the typed name previews in the script face. */
.agreement-sign-panel { background: var(--ip-neutral-50); border-radius: var(--ip-radius-md); padding: 24px; margin-top: 24px; }
.agreement-sign-preview { font-family: 'Allura', 'Brush Script MT', cursive; font-size: 2rem; line-height: 1.1; min-height: 2.4rem; color: var(--ip-ink); border-bottom: 1px solid var(--ip-neutral-400); padding: 4px 8px 2px; }
.agreement-sign-preview:empty::before { content: 'Your signature'; color: var(--ip-neutral-300); font-family: var(--ip-font-family); font-size: 0.875rem; }

/* The "a signer must complete this" wall. */
.agreement-wall-signer { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--ip-neutral-100); }
.agreement-wall-signer:last-child { border-bottom: 0; }

@media (max-width: 575.98px) {
    .agreement-document { padding: 20px 16px; }
    .agreement-signatures { flex-direction: column; gap: 24px; }
    .agreement-scroll { max-height: none; }
}


/* =============================================================================
   PRE-IMPORT SURFACES
   A firm that has not given us a client list has nothing to be shown. Two
   patterns fill that gap without pretending to data we do not have.
   ============================================================================= */

/* ── The billboard ───────────────────────────────────────────────────────────
   The dashboard before any client exists. One argument, one artifact, one way
   on: the firm's own name on a study cover, which is the thing they are being
   offered. Replaces the whole dashboard rather than sitting inside a section,
   because with no clients there are no sections to sit in. */
.billboard { display: flex; align-items: center; gap: 80px; flex-wrap: wrap; max-width: 1060px; padding: 24px 0 8px; }
.billboard-copy { flex: 1 1 400px; min-width: 0; }
.billboard-title { font-size: clamp(1.875rem, 3vw, 2.75rem); font-weight: 700; letter-spacing: -0.03em; line-height: 1.1; margin: 0; max-width: 21ch; }
.billboard-lede { margin: 22px 0 0; max-width: 48ch; font-size: 1.0625rem; line-height: 1.7; color: var(--ip-neutral-600); }
.billboard-actions { margin-top: 38px; }
.billboard-actions .btn { font-size: 1rem; padding: 15px 23px; }

/* The study cover. Flat, so the stack is drawn with two offset outlines rather
   than a shadow: the firm's name at full size, ours small at the foot. */
.study-cover-stack { flex: 0 1 400px; position: relative; padding: 14px 14px 0 0; }
.study-cover-sheet { position: absolute; width: 352px; height: 470px; border-radius: var(--ip-radius-lg); }
.study-cover-sheet-back { top: 0; right: 0; border: 1px solid var(--ip-neutral-200); }
.study-cover-sheet-mid { top: 7px; right: 7px; border: 1px solid var(--ip-neutral-300); background: var(--ip-neutral-50); }
.study-cover { position: relative; width: 352px; height: 470px; box-sizing: border-box; background: #fff; border: 1px solid var(--ip-ink); border-radius: var(--ip-radius-lg); padding: 36px 32px; display: flex; flex-direction: column; }
.study-cover-kind { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ip-neutral-500); }
.study-cover-rule { width: 44px; height: 3px; background: var(--ip-accent); margin: 18px 0 22px; }
.study-cover-firm { font-family: var(--ip-font-display); font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; color: var(--ip-ink); }
.study-cover-firm-sub { margin-top: 10px; font-size: 0.875rem; color: var(--ip-neutral-500); }
.study-cover-for { margin-top: auto; padding-top: 28px; }
.study-cover-for-label { font-size: 0.75rem; color: var(--ip-neutral-500); }
.study-cover-for-name { margin-top: 4px; font-size: 1rem; font-weight: 600; }
.study-cover-for-years { margin-top: 2px; font-size: 0.875rem; color: var(--ip-neutral-500); }
/* The logo stands in for the typeset name when the firm has one. align-self matters: the cover
   is a COLUMN flex container, so the default stretch pulls an image to the card's width and the
   max-height then squashes it off its own ratio. The width and height come from
   FirmBrandMark.GetDisplaySize; object-fit is the belt to that braces. */
.study-cover-logo { display: block; align-self: flex-start; max-width: 288px; max-height: 95px; object-fit: contain; }

@media (max-width: 991.98px) {
    .billboard { gap: 48px; }
    .study-cover-stack { flex-basis: 100%; }
}

/* ── The example opportunity ─────────────────────────────────────────────────
   The Opportunities empty state, before a client list exists: the ask on the
   left, one worked row of the absent table on the right. Faster to read than the
   paragraph describing it, and safe to show because "Acme Corporation" plus the
   Example tag can never be taken for one of the firm's own clients. */
.empty-split { display: flex; align-items: center; gap: 56px; flex-wrap: wrap; padding: 20px 12px; }
.empty-split-copy { flex: 1 1 380px; min-width: 0; }
.empty-split-title { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.015em; line-height: 1.3; margin: 0; }
.empty-split-lede { margin: 12px 0 0; max-width: 54ch; font-size: 0.9375rem; line-height: 1.65; color: var(--ip-neutral-500); }
.empty-split-actions { margin-top: 26px; }

.opp-example { flex: 0 1 330px; background: #fff; border: 1px solid var(--ip-neutral-200); border-radius: var(--ip-radius-lg); overflow: hidden; }
/* The one piece of colour on the card, and the only thing announcing it from across the page. */
.opp-example-bar { height: 4px; background: var(--ip-accent); }
.opp-example-body { padding: 24px 26px 28px; }
.opp-example-tag { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ip-neutral-400); }
.opp-example-name { font-family: var(--ip-font-display); font-size: 1.375rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.25; margin-top: 6px; color: var(--ip-ink); }
.opp-example-rule { height: 1px; background: var(--ip-neutral-200); margin: 20px 0; }
.opp-example-reading + .opp-example-reading { margin-top: 22px; }
.opp-example-label { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ip-neutral-500); }
.opp-example-indicator { margin-top: 10px; }
.opp-example-figure { font-family: var(--ip-font-display); font-size: 2.25rem; font-weight: 700; letter-spacing: -0.025em; line-height: 1.05; margin-top: 6px; color: var(--ip-ink); }

@media (max-width: 767.98px) {
    .empty-split { gap: 32px; padding: 8px 0; }
    .opp-example { flex-basis: 100%; }
}
