/* ========================================================================== */
/* ArchEx Shared UI Components                                                */
/*                                                                            */
/* GOLD STANDARD: These classes are extracted from the approved login page.   */
/* New pages must compose these components rather than creating parallel       */
/* card, field, button, link, heading, action-row or footer styling.           */
/* ========================================================================== */

/* Page canvas -------------------------------------------------------------- */
.ax-page {
    position: relative;
    min-height: 100dvh;
    /* clip, not hidden (21 September 2026): hidden makes this a scroll container, and every
       position:sticky child inside it stops sticking. clip contains the contours layer without
       that side effect — which matters now that every page carries this class, including the
       ones with sticky field navigation. */
    overflow: clip;
    background:
        radial-gradient(circle at 18% 12%, rgba(217, 162, 107, .20), transparent 34%),
        radial-gradient(circle at 82% 84%, rgba(242, 108, 33, .08), transparent 28%),
        var(--color-background);
    color: var(--color-charcoal);
    font-family: var(--font-body);
    isolation: isolate;
}

.ax-page-contours {
    position: absolute;
    inset: -12%;
    z-index: -1;
    opacity: .28;
    pointer-events: none;
    transform: rotate(-5deg) scale(1.08);
    background-image:
        repeating-radial-gradient(
            ellipse at 18% 34%,
            transparent 0,
            transparent 38px,
            rgba(59, 59, 59, .10) 39px,
            transparent 41px,
            transparent 64px),
        repeating-radial-gradient(
            ellipse at 78% 68%,
            transparent 0,
            transparent 44px,
            rgba(217, 162, 107, .18) 45px,
            transparent 47px,
            transparent 72px);
}

.ax-centered-shell {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-5);
    padding: var(--space-5);
}

/* Surface/card ------------------------------------------------------------- */
.ax-authcard {
    width: min(100%, 480px);
    padding: var(--space-5);
    border: 1px solid rgba(31, 31, 31, .06);
    border-radius: var(--radius-component);
    background: rgba(255, 255, 255, .96);
    box-shadow: var(--shadow-dialog);
    backdrop-filter: blur(8px);
}

/* Branded heading ---------------------------------------------------------- */
.ax-brand-heading {
    display: grid;
    gap: 12px;
    margin-bottom: var(--space-5);
    text-align: center;
}

.ax-brand-logo {
    display: block;
    width: 100%;
    height: auto;
    max-height: 250px;
    margin: 0 auto;
    object-fit: contain;
}

.ax-heading-group {
    display: grid;
    gap: var(--space-2);
}

.ax-title {
    margin: 0;
    color: var(--color-charcoal);
    font-family: var(--font-heading);
    font-size: clamp(1.75rem, 4vw, 2.25rem);
    font-weight: 700;
    line-height: 1.2;
}

.ax-subtitle {
    margin: 0;
    color: var(--color-gunmetal);
    font-size: 1rem;
    line-height: 1.5;
}

/* Forms -------------------------------------------------------------------- */
.ax-form {
    display: grid;
    gap: var(--space-4);
}

.ax-authfield {
    display: grid;
    gap: var(--space-2);
}

.ax-authfield + .ax-authfield {
    margin-top: 16px;
}

.ax-authlabel,
.ax-authfield > label {
    color: var(--color-charcoal);
    font-family: var(--font-body);
    font-size: .95rem;
    font-weight: 700;
}

.ax-authinput {
    box-sizing: border-box;
    width: 100%;
    height: 46px;
    padding: 0 var(--space-3);
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-component);
    background: var(--color-surface);
    color: var(--color-charcoal);
    font-family: var(--font-body);
    font-size: 1rem;
    transition: border-color var(--motion-duration) var(--motion-easing),
                box-shadow var(--motion-duration) var(--motion-easing);
}

.ax-authinput::placeholder {
    color: #6f6f6f;
}

.ax-authinput:hover {
    border-color: var(--color-sandstone);
}

.ax-authinput:focus {
    border-color: var(--color-primary);
    outline: none;
    box-shadow: 0 0 0 3px rgba(242, 108, 33, .18);
}

.ax-authinput.invalid {
    border-color: var(--color-danger);
    outline: none;
}

.ax-form-options {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: 8px;
    margin-bottom: 18px;
}

.ax-checkbox-option {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-gunmetal);
    cursor: pointer;
    font-size: .95rem;
}

.ax-checkbox {
    width: 20px;
    height: 20px;
    margin: 0;
    border: 1px solid var(--color-divider);
    border-radius: 4px;
    appearance: none;
    background: var(--color-surface);
    cursor: pointer;
}

.ax-checkbox:checked {
    border-color: var(--color-primary);
    background-color: var(--color-primary);
    background-image:
        linear-gradient(45deg, transparent 45%, #fff 45%, #fff 55%, transparent 55%),
        linear-gradient(-45deg, transparent 38%, #fff 38%, #fff 48%, transparent 48%);
    background-position: 6px 9px, 3px 9px;
    background-size: 8px 8px;
    background-repeat: no-repeat;
}

.ax-checkbox:focus-visible {
    outline: 3px solid rgba(242, 108, 33, .24);
    outline-offset: 2px;
}

/* Links and buttons -------------------------------------------------------- */
.ax-link,
.ax-link:link,
.ax-link:visited {
    color: var(--color-primary-dark);
    font-weight: 700;
    text-decoration: none;
    transition: color var(--motion-duration) var(--motion-easing);
}

.ax-link:hover,
.ax-link:focus-visible,
.ax-link:active {
    color: var(--color-charcoal);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ax-button-primary {
    width: 100%;
    height: 52px;
    min-height: 52px;
    margin-top: var(--space-1);
    border: 0;
    border-radius: var(--radius-component);
    background: var(--color-primary);
    color: #FFFFFF;
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(242, 108, 33, .22);
    transition: background var(--motion-duration) var(--motion-easing),
                box-shadow var(--motion-duration) var(--motion-easing),
                transform var(--motion-duration) var(--motion-easing);
}

.ax-button-primary:hover {
    background: var(--color-primary-dark);
    box-shadow: 0 4px 12px rgba(216, 90, 20, .28);
}

.ax-button-primary:active {
    transform: translateY(1px);
}

.ax-button-primary:focus-visible {
    outline: 3px solid rgba(242, 108, 33, .30);
    outline-offset: 3px;
}

.ax-secondary-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2) var(--space-3);
    padding-top: 12px;
    font-size: .875rem;
    text-align: center;
}

.ax-secondary-actions .ax-link,
.ax-secondary-actions .ax-link-button {
    color: var(--color-primary-dark);
    font-family: var(--font-body);
    font-size: .875rem;
    font-weight: 700;
}

.ax-link-button {
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}

/* Validation and notices -------------------------------------------------- */
.ax-validation {
    margin: 0;
    color: var(--color-danger);
    font-size: .875rem;
    line-height: 1.4;
}

.ax-validation-summary {
    padding: var(--space-3);
    border-left: 4px solid var(--color-danger);
    border-radius: var(--radius-component);
    background: rgba(198, 40, 40, .06);
}

.ax-authcard .alert {
    margin: 0 0 var(--space-4);
    padding: var(--space-3);
    border: 1px solid rgba(198, 40, 40, .30);
    border-radius: var(--radius-component);
    background: rgba(198, 40, 40, .06);
    color: var(--color-danger);
    font-family: var(--font-body);
    font-size: .9rem;
}

/* Application footer ------------------------------------------------------ */
.ax-page-footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2);
    max-width: 640px;
    margin-top: 32px;
    color: var(--color-gunmetal);
    font-size: .78rem;
    line-height: 1.5;
    text-align: center;
}

@media (max-width: 768px) {
    .ax-centered-shell {
        justify-content: flex-start;
        padding: var(--space-4);
        padding-top: var(--space-7);
    }

    .ax-authcard {
        padding: var(--space-4);
    }

    .ax-brand-heading {
        gap: var(--space-4);
        margin-bottom: var(--space-4);
    }

    .ax-brand-logo {
        max-height: 128px;
    }
}

@media (max-width: 480px) {
    .ax-centered-shell {
        padding: var(--space-3);
        padding-top: var(--space-5);
    }

    .ax-authcard {
        padding: var(--space-4) var(--space-3);
    }

    .ax-form-options {
        align-items: flex-start;
        flex-direction: column;
    }

    .ax-page-footer {
        display: grid;
        gap: var(--space-1);
    }

    .ax-page-footer span[aria-hidden="true"] {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ax-button-primary,
    .ax-authinput,
    .ax-link {
        transition: none;
    }
}

/* ArchEx 5.0A operating-system foundation -------------------------------- */
.ax-os-page {
    width: min(1480px, 100%);
    margin: 0 auto;
    padding: clamp(20px, 3vw, 38px);
    color: var(--color-charcoal);
    font-family: var(--font-body);
}

.ax-os-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}
.ax-os-heading { min-width: 0; }
.ax-os-title-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); min-width: 0; }
.ax-os-heading h1 {
    margin: 0;
    font-family: var(--font-heading);
    /* The top of the type scale, like every other page title. This asked for
       clamp(2rem, 4vw, 3.6rem) - 57.6px at a 1440px desktop - which is the same habit that
       had page titles ranging from 18px to 86px across the application. The shared header is
       the last place that should be setting its own size: whatever it does, every page that
       adopts it inherits. */
    font-size: var(--archex-text-2xl);
    line-height: 1.12;
    letter-spacing: -.02em;
}
.ax-os-eyebrow {
    margin: 0 0 8px;
    color: var(--color-primary-dark);
    font-size: .7rem;
    font-weight: 800;
    letter-spacing: .16em;
    text-transform: uppercase;
}
.ax-os-subtitle { margin: 8px 0 0; color: var(--color-gunmetal); }
.ax-os-header-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }

.ax-os-focus {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1px;
    margin-bottom: var(--space-4);
    overflow: hidden;
    border: 1px solid var(--color-divider);
    border-radius: 8px;
    background: var(--color-divider);
    box-shadow: var(--shadow-card);
}
.ax-os-focus article {
    min-height: 110px;
    padding: 18px 20px;
    background: var(--color-surface);
}
.ax-os-focus article.attention { background: #fff8f3; }
.ax-os-focus article.next-action { background: var(--color-panel); }
.ax-os-focus span { display:block; color:var(--color-primary-dark); font-size:.68rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; }
.ax-os-focus strong { display:block; margin-top:8px; font-family:var(--font-heading); font-size:1.05rem; }
.ax-os-focus small { display:block; margin-top:6px; color:var(--color-gunmetal); line-height:1.4; }
.ax-os-focus .next-action div { margin-top:12px; }

.ax-os-context-bar {
    position: sticky;
    top: 0;
    z-index: 8;
    display: flex;
    gap: 6px;
    margin: 0 0 var(--space-4);
    padding: 8px;
    overflow-x: auto;
    border: 1px solid var(--color-divider);
    border-radius: 8px;
    background: rgba(255,255,255,.96);
    box-shadow: var(--shadow-card);
    backdrop-filter: blur(10px);
}
.ax-os-context-bar button,
.ax-os-context-bar a {
    min-height: 38px;
    padding: 0 13px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--color-charcoal);
    font: 700 .82rem var(--font-body);
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
}
.ax-os-context-bar button:hover,
.ax-os-context-bar a:hover,
.ax-os-context-bar .active { background: var(--color-panel); color: var(--color-primary-dark); }

.ax-os-progressive {
    margin-top: var(--space-3);
    border: 1px solid var(--color-divider);
    border-radius: 8px;
    background: var(--color-surface);
    box-shadow: var(--shadow-card);
}
.ax-os-progressive > summary {
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:16px;
    padding:16px 18px;
    list-style:none;
    cursor:pointer;
}
.ax-os-progressive > summary::-webkit-details-marker { display:none; }
.ax-os-progressive > summary span { display:grid; gap:2px; }
.ax-os-progressive > summary small { color:var(--color-primary-dark); font-size:.65rem; font-weight:800; letter-spacing:.12em; }
.ax-os-progressive > summary strong { font-family:var(--font-heading); }
.ax-os-progressive > summary em { color:var(--color-gunmetal); font-size:.82rem; font-style:normal; font-weight:400; }
.ax-os-progressive[open] > summary b { transform:rotate(45deg); }
.ax-os-progressive-body { padding:0 18px 18px; }

@media (max-width: 850px) {
    /* stretch, not flex-start: flex-start sizes each child to its own content, so a long subtitle
       made the heading 946px wide inside a 360px phone and Permissions, Audit and Governance
       could be dragged 833px sideways. The header looked right in every screenshot, because what
       overflowed was off the side of it. */
    .ax-os-header { align-items:stretch; flex-direction:column; }
    .ax-os-header > * { max-width:100%; min-width:0; }
    .ax-os-header-actions { justify-content:flex-start; }
    .ax-os-focus { grid-template-columns:1fr; }
    .ax-os-focus article { min-height:0; }
    .ax-os-page { padding:16px; }
}

/* Shared operating-system workspace controls ------------------------------ */
.ax-os-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    margin: 0 0 18px;
    padding: 12px 14px;
    border: 1px solid rgba(31,31,31,.08);
    border-radius: var(--radius-component);
    background: rgba(255,255,255,.94);
    box-shadow: var(--shadow-card);
}

.ax-os-toolbar-controls {
    display: flex;
    align-items: center;
    flex: 1;
    flex-wrap: wrap;
    gap: 10px;
    min-width: 0;
}

.ax-os-toolbar input[type="search"],
.ax-os-toolbar input[type="text"],
.ax-os-toolbar select {
    min-height: 40px;
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-component);
    background: var(--color-surface);
    color: var(--color-charcoal);
    font: inherit;
}

.ax-os-toolbar input[type="search"],
.ax-os-toolbar input[type="text"] {
    flex: 1 1 280px;
    min-width: min(280px, 100%);
    padding: 0 12px;
}

.ax-os-toolbar select { padding: 0 34px 0 12px; }
.ax-os-toolbar-result {
    flex: 0 0 auto;
    color: var(--color-gunmetal);
    font-size: .78rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Shared classes deliberately normalise major workspaces without changing
   their business-specific content or interaction logic. */
.ax-os-page > .ax-os-header:first-of-type { margin-bottom: 14px; }
.ax-os-page > .ax-os-focus { margin-bottom: 16px; }
.ax-os-page .primary-button,
.ax-os-page .primary-action,
.ax-os-page .hero-action:not(.secondary) { border-radius: var(--radius-component); }
.ax-os-page .secondary-button,
.ax-os-page .secondary-action,
.ax-os-page .hero-action.secondary { border-radius: var(--radius-component); }

@media (max-width: 720px) {
    .ax-os-toolbar { align-items: stretch; flex-direction: column; }
    .ax-os-toolbar-controls { width: 100%; }
    .ax-os-toolbar-result { white-space: normal; }
}

/* Clean page layouts for unified design ===================================== */

.ax-page {
    position: relative;
    min-height: 100dvh;
    padding: var(--space-4);
    background: var(--color-background);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: 0;
}

.page-header h1 {
    margin: 0;
    font-size: clamp(1.75rem, 4vw, 2.25rem);
    font-weight: 700;
}

.page-header .eyebrow {
    margin: 0 0 var(--space-2);
    font-size: 0.65rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    color: var(--color-primary);
}

.action-button {
    padding: var(--space-3) var(--space-4);
    border: none;
    border-radius: var(--radius-component);
    background: var(--color-primary);
    color: white;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    white-space: nowrap;
    transition: all 150ms ease-in-out;
}

.action-button:hover {
    background: var(--color-primary-dark);
    transform: translateY(-1px);
}

.action-button:active {
    transform: translateY(0);
}

.search-bar {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
}

.search-bar input {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-component);
    font-size: 0.95rem;
}

.search-bar small {
    color: var(--color-gunmetal);
    font-size: 0.8rem;
}

.projects-grid,
.projects-list {
    display: grid;
    gap: var(--space-3);
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.projects-list {
    grid-template-columns: 1fr;
}

.project-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    transition: all 150ms ease-in-out;
}

.project-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 35px rgba(0, 0, 0, 0.12);
}

.project-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--space-3);
}

.project-header h3 {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 600;
}

.project-reference {
    margin: 0;
    color: var(--color-gunmetal);
    font-size: 0.85rem;
    font-weight: 600;
}

.project-meta {
    display: grid;
    gap: var(--space-2);
    margin: 0;
    font-size: 0.9rem;
}

.project-meta div {
    display: flex;
    gap: var(--space-2);
}

.project-meta dt {
    font-weight: 600;
    min-width: 60px;
    color: var(--color-gunmetal);
}

.project-meta dd {
    margin: 0;
    flex: 1;
}

.created-date {
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-divider);
    font-size: 0.8rem;
    color: var(--color-muted);
}

.status-badge {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
    background: var(--color-panel);
    color: var(--color-charcoal);
}

.status-badge.active {
    background: var(--color-success);
    color: white;
}

.status-badge.warning {
    background: var(--color-warning);
    color: white;
}

.status-badge.danger {
    background: var(--color-danger);
    color: white;
}

/* ================================================================================================
   EMPTY STATE  (21 September 2026)
   ------------------------------------------------------------------------------------------------
   WHY THIS GREW. A shared .empty-state already existed here, but it only centred text and added
   padding — no border, no background, nothing that reads as a placed object. So twenty pages each
   added their own chrome in their own scoped sheet, and because scoped CSS cannot be shared they
   added it twenty times: seven corner radii (10 to 18px), padding from 1rem to 4rem, dashed and
   solid borders, four background treatments. The under-specified shared rule CAUSED the drift; the
   pages were each finishing a job it had left half done.

   Nine of the twenty had independently arrived at the same design — dashed divider border, rounded,
   centred, muted, generous padding — so that is what this now is. It is their design, promoted, not
   a new one imposed.

   TWO CONTROLS SHARED ONE NAME. Seventeen pages use .empty-state for a titled block with a heading
   and a line of guidance. Three use it for a bare sentence inside a panel: "No spatial packages
   have been uploaded for this project." Giving that a 48px dashed card would be wrong, so .compact
   keeps it a muted line. ActionCentre had already invented that modifier locally; it is promoted
   rather than replaced.
   ============================================================================================== */

.empty-state {
    display: grid;
    gap: 6px;
    padding: 48px 24px;
    border: 1px dashed var(--color-divider);
    border-radius: 16px;
    background: rgba(255, 255, 255, .6);
    color: var(--color-gunmetal);
    text-align: center;
}

.empty-state h1,
.empty-state h2,
.empty-state h3 {
    margin: 0;
    color: var(--color-charcoal);
}

.empty-state h2 { font-size: 1.5rem; }

.empty-state strong {
    color: var(--color-charcoal);
    font-size: 1.05rem;
}

.empty-state p,
.empty-state span {
    margin: 0;
    color: var(--color-gunmetal);
}

/* A line of prose reads badly across a wide card. */
.empty-state p,
.empty-state span { max-width: 62ch; justify-self: center; }

/* One sentence inside a panel, not a placed object. */
.empty-state.compact {
    padding: 14px 0;
    border: 0;
    border-radius: 0;
    background: none;
}

/* The page already put it in a card; two borders around one message is one too many. */
.empty-state.ax-card {
    border-style: solid;
    background: none;
}

.project-item {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4) !important;
    cursor: pointer;
    transition: all 150ms ease-in-out;
}

.project-item:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 35px rgba(0, 0, 0, 0.12);
}

.project-main h3 {
    margin: 0 0 var(--space-2);
    font-size: 1.1rem;
}

.project-details-row {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
    font-size: 0.9rem;
}

.detail {
    color: var(--color-gunmetal);
}

.readiness-issues {
    display: flex;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.issue-badge {
    display: inline-block;
    padding: 4px 8px;
    border-radius: 8px;
    background: rgba(198, 40, 40, 0.1);
    color: var(--color-danger);
    font-size: 0.8rem;
    font-weight: 600;
}

.finance-summary {
    padding: var(--space-4) !important;
}

.summary-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--space-3);
}

.summary-stats article {
    text-align: center;
}

.summary-stats strong {
    display: block;
    font-size: 1.8rem;
    color: var(--color-primary);
}

.summary-stats p {
    margin: var(--space-1) 0 0;
    font-size: 0.8rem;
    color: var(--color-gunmetal);
}

.summary-stats.alert strong {
    color: var(--color-danger);
}

/* ==========================================================================
   UNIFY LAYER — loaded last, wins over every page's scoped .razor.css.
   Purpose: one brand look on all pages (orange primary, warm neutrals,
   small quiet headings) regardless of what each page's own CSS says.
   ========================================================================== */

:root { accent-color: var(--color-primary); }

/* Old operating headers: keep them (they hold each page's title + actions)
   but force them compact and quiet instead of hiding them. */
.ax-page .ax-os-focus { display: none !important; }

.ax-page .ax-os-header {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    padding: 0 !important;
    margin: 0 0 var(--space-3) !important;
}

.ax-page .ax-os-header p:not(.eyebrow),
.ax-page .ax-os-header .ax-subtitle {
    margin: 2px 0 0 !important;
    color: var(--color-gunmetal) !important;
    font-size: 0.83rem !important;
    max-width: 640px;
}

/* Form controls — no browser blue, no page-specific colours */
.ax-page select,
.ax-page input[type="search"],
.ax-page input[type="text"],
.ax-page input[type="date"],
.ax-page input[type="email"],
.ax-page input[type="number"],
.ax-page textarea {
    padding: 10px 14px !important;
    border: 1px solid var(--color-divider) !important;
    border-radius: var(--radius-component) !important;
    background: var(--color-surface) !important;
    color: var(--color-charcoal) !important;
    font-size: 0.92rem !important;
    font-family: var(--font-body) !important;
}

/* Kill the native Windows dropdown look entirely — this is where the
   "blue" came from. Custom charcoal chevron, brand focus ring. */
.ax-page select {
    cursor: pointer;
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%233B3B3B' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 12px center !important;
    padding-right: 34px !important;
}

.ax-page select option {
    background: var(--color-surface);
    color: var(--color-charcoal);
}

.ax-page select:focus,
.ax-page input:focus,
.ax-page textarea:focus {
    outline: none !important;
    border-color: var(--color-primary) !important;
    box-shadow: 0 0 0 3px rgba(242, 108, 33, 0.12) !important;
}

/* TYPE ON A DARK SURFACE KEEPS ITS OWN COLOUR (23 September 2026).
   The heading rules below are written for the cream canvas and carry !important, so any heading on
   a dark panel rendered charcoal on charcoal - invisible. Adam Deane, of the landing band: "can see
   some text as its dark and the background is dark." A surface that sets its own dark background
   marks itself .ax-on-dark, and the ink rules step aside for everything inside it. */
.ax-page .ax-on-dark h1,
.ax-page .ax-on-dark h2,
.ax-page .ax-on-dark h3,
.ax-page .ax-on-dark h4 {
    color: inherit !important;
}

/* Headings — small, present, out of the way. Focus goes to the work. */
.ax-page h1 {
    font-family: var(--font-heading) !important;
    font-size: 1.45rem !important;
    font-weight: 700 !important;
    color: var(--color-charcoal) !important;
    letter-spacing: 0 !important;
}

.ax-page h2 {
    font-family: var(--font-heading) !important;
    font-size: 1.05rem !important;
    font-weight: 700 !important;
    color: var(--color-charcoal) !important;
}

.ax-page h3 {
    font-family: var(--font-heading) !important;
    font-size: 0.95rem !important;
    font-weight: 600 !important;
}

.ax-page .eyebrow {
    color: var(--color-primary) !important;
    font-size: 0.66rem !important;
    font-weight: 800 !important;
    letter-spacing: 0.14em !important;
}

/* Primary actions — always brand orange, never page-local greens/blues */
.ax-page .primary-action,
.ax-page .primary-button,
.ax-page .hero-action:not(.secondary),
.ax-page .action-button {
    background: var(--color-primary) !important;
    color: #fff !important;
    border: none !important;
    border-radius: var(--radius-component) !important;
    font-weight: 650 !important;
    cursor: pointer;
    transition: background var(--motion-duration) var(--motion-easing),
                transform var(--motion-duration) var(--motion-easing);
}

.ax-page .primary-action:hover,
.ax-page .primary-button:hover,
.ax-page .hero-action:not(.secondary):hover,
.ax-page .action-button:hover {
    background: var(--color-primary-dark) !important;
    transform: translateY(-1px);
}

/* Secondary / quiet buttons — warm neutral, thin border.

   WHERE A BUTTON SITS DOES NOT OUTRANK WHAT IT IS (21 September 2026). Two of these selectors
   name a CONTEXT — any button inside a row-actions group or a section heading — and both this
   rule and the primary one are !important, so for a .primary-button inside a section heading the
   context won on source order. Resources drew "New assignment" in brand orange and "Allocate
   resource", the same class in a heading, in white. The three classes that mean "this is the
   main action here" are now excluded from the context selectors, so the class decides. */
.ax-page .secondary-button,
.ax-page .row-actions button:not(.primary-button):not(.primary-action):not(.action-button),
.ax-page .section-heading button:not(.primary-button):not(.primary-action):not(.action-button),
.ax-page .hero-action.secondary,
.ax-page button.quiet {
    background: var(--color-surface) !important;
    color: var(--color-charcoal) !important;
    border: 1px solid var(--color-divider) !important;
    border-radius: var(--radius-component) !important;
    cursor: pointer;
    transition: border-color var(--motion-duration) var(--motion-easing),
                color var(--motion-duration) var(--motion-easing);
}

.ax-page .secondary-button:hover,
.ax-page .row-actions button:not(.primary-button):not(.primary-action):not(.action-button):hover,
.ax-page .section-heading button:not(.primary-button):not(.primary-action):not(.action-button):hover,
.ax-page .hero-action.secondary:hover,
.ax-page button.quiet:hover {
    border-color: var(--color-primary) !important;
    color: var(--color-primary-dark) !important;
}

/* Accent text that pages painted green/teal/blue → brand copper */
.ax-page .workflow-card span,
.ax-page .project-identity small,
.ax-page .record-number,
.ax-page .connector-type,
.ax-page .project-type {
    color: var(--color-primary-dark) !important;
}

/* Status pills — tokenised, quiet */
.ax-page .readiness-list span,
.ax-page .status,
.ax-page .status-pill,
.ax-page .mapping-pill {
    border-radius: 999px !important;
    font-size: 0.7rem !important;
    font-weight: 700 !important;
    background: var(--color-panel) !important;
    color: var(--color-gunmetal) !important;
}

.ax-page .readiness-list .ready,
.ax-page .status.complete,
.ax-page .status-pill.active {
    background: rgba(46, 125, 50, 0.12) !important;
    color: var(--color-success) !important;
}

.ax-page .readiness-list .attention,
.ax-page .status.review,
.ax-page .status-pill.warning {
    background: rgba(249, 168, 37, 0.16) !important;
    color: #8a5a00 !important;
}

/* Readable width — long full-screen rows are hard to scan */
.ax-page {
    max-width: 1440px;
    margin-inline: auto;
    width: 100%;

    /* MEASURED, 24 Aug 2026: without this the page scrolled sideways at every
       width. .ax-page carries `width: 100%` AND `padding: var(--space-4)`, and
       there is no global box-sizing reset — only .ax-authinput sets it. As
       content-box the border-box width became 100% + 48px, `margin-inline: auto`
       resolved to a NEGATIVE right margin, and the document overflowed by 40px
       (scrollWidth 1305 vs clientWidth 1265). Every page using .ax-page was
       affected, which is why it never looked like one page's bug. */
    box-sizing: border-box;
}

/* Tab / filter rows: never overlap — wrap instead */
.ax-page .job-filters,
.ax-page .view-switch,
.ax-page [role="group"] {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 6px !important;
}

/* THE HAMMER — every button on every page (front page excluded) gets the
   brand look, regardless of what its page own stylesheet says.
   Primary/action classes stay orange via the rules above.

   .axcal-day is excluded because a calendar day is a button only so that it can be reached from
   the keyboard, not because it is a control. The hammer gave all thirty-five of them a border and
   an 8px radius, which turned the month into a tray of rounded boxes; the exception is stated here,
   where the rule is, rather than fought with a louder !important in the component. */
/* A CHOSEN CONTROL IS EXCLUDED, not argued with. The "selected tab / active filter = orange"
   rule below scores three classes; this hammer scores seven, and both carry !important - so the
   hammer has been winning since it was written and NO button inside .ax-page has been able to show
   that it is the chosen one. The Library filter chips rendered white-on-white: the selected filter
   was invisible and so was its count. Excluding the three chosen-state classes here is the fix;
   raising the other rule to eight classes would only move the argument.

   .ax-list-button is excluded for the reason .axcal-day is (21 September 2026). An email in the
   mailbox list and a folder in its folder tree are buttons only so they can be reached from the
   keyboard; they are ROWS, and a list of rows each boxed with a border and a radius stops reading
   as a list. The hammer boxed every email and all 169 Outlook folders, and the owner looked at the
   result and said the inbox was "nothing like an email place". The row is styled by the list it
   belongs to, and the exception is stated here, where the rule is. */
.ax-page:not(.activity-page) button:not(.action-button):not(.primary-button):not(.primary-action):not(.hero-action):not(.close-button):not(.axcal-day):not(.ax-list-button):not(.active):not(.selected):not(.is-on) {
    background: var(--color-surface) !important;
    color: var(--color-charcoal) !important;
    border: 1px solid var(--color-divider) !important;
    border-radius: var(--radius-component) !important;
    font-family: var(--font-body) !important;
    transition: border-color var(--motion-duration) var(--motion-easing),
                color var(--motion-duration) var(--motion-easing),
                background var(--motion-duration) var(--motion-easing);
}

.ax-page:not(.activity-page) button:not(.action-button):not(.primary-button):not(.primary-action):not(.hero-action):not(.axcal-day):not(.ax-list-button):not(.active):not(.selected):not(.is-on):hover:not(:disabled) {
    border-color: var(--color-primary) !important;
    color: var(--color-primary-dark) !important;
}

/* Selected tab / active filter = orange, everywhere.

   .is-on IS IN THIS LIST because the hammer above forces every button to the surface colour with
   !important, so a page that writes its own selected state loses it silently. The Library filter
   chips set `background: var(--color-primary-dark)` for .is-on and rendered WHITE, with a white
   count on a white chip - the selected filter was invisible and so was its number. Four pages use
   .is-on this way. A page inventing a fifth name for "chosen" will lose it the same way, which is
   an argument for these three and not a fourth. */
.ax-page:not(.activity-page) button.active,
.ax-page:not(.activity-page) button.selected,
.ax-page:not(.activity-page) button.is-on,
.ax-page:not(.activity-page) .summary-card.selected {
    background: var(--color-primary) !important;
    color: #fff !important;
    border-color: var(--color-primary) !important;
}

/* Catch-all for stray coloured chips: anything named pill/badge/tag/chip */
.ax-page:not(.activity-page) :is([class*="pill"], [class*="badge"], [class*="-tag"], [class*="chip"]) {
    background: var(--color-panel) !important;
    color: var(--color-gunmetal) !important;
    border-radius: 999px !important;
}

/* Accent text painted green/teal by page stylesheets → brand copper */
.ax-page:not(.activity-page) .project-identity small,
.ax-page:not(.activity-page) .record-number,
.ax-page:not(.activity-page) .workflow-card span,
.ax-page:not(.activity-page) .register-heading strong,
.ax-page:not(.activity-page) .map-register strong {
    color: var(--color-primary-dark) !important;
}

.ax-page .summary-card,
.ax-page .summary-grid article {
    background: var(--color-surface) !important;
    border: 1px solid var(--color-divider) !important;
    color: var(--color-charcoal) !important;
    padding: var(--space-3) !important;
    border-radius: var(--radius-component) !important;
}

.ax-page .summary-card strong,
.ax-page .summary-grid article strong {
    color: var(--color-primary) !important;
    font-size: 1.5rem;
}

.ax-page button:not(.action-button):not(.primary-button):not(.axcal-day) {
    background: var(--color-surface);
    border: 1px solid var(--color-divider);
    color: var(--color-charcoal);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-component);
    cursor: pointer;
    font-size: 0.9rem;
    transition: all 150ms ease-in-out;
}

.ax-page button:not(.action-button):not(.primary-button):not(.axcal-day):hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.ax-page .hero-action {
    background: var(--color-surface) !important;
    border: 1px solid var(--color-divider) !important;
    color: var(--color-charcoal) !important;
    padding: var(--space-2) var(--space-3) !important;
}

.ax-page .hero-action:not(.secondary):hover {
    background: var(--color-primary) !important;
    color: white !important;
}

.ax-page .status-pill {
    background: var(--color-panel) !important;
    color: var(--color-charcoal) !important;
}

.ax-page .workflow-card {
    background: var(--color-surface) !important;
    border: 1px solid var(--color-divider) !important;
    color: var(--color-charcoal) !important;
    padding: var(--space-4) !important;
    border-radius: var(--radius-component) !important;
    text-align: left !important;
}

.ax-page .workflow-card:hover:not(:disabled) {
    border-color: var(--color-primary) !important;
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}

.ax-page .workflow-card span {
    color: var(--color-primary) !important;
    font-size: 1.2rem !important;
    font-weight: 700 !important;
}

.ax-page .eyebrow {
    color: var(--color-primary) !important;
}

@media (max-width: 850px) {
    .ax-page { padding: var(--space-3); gap: var(--space-3); }
    .page-header { flex-direction: column; }
    .projects-grid { grid-template-columns: 1fr; }
}

/* ---- WR-61 slice 2: intake review, sponsor and parties ------------------- */
.sponsor-status { padding: 4px 12px; border-radius: 999px; font-size: .78rem;
  font-weight: 600; letter-spacing: .01em; white-space: nowrap; }
.sponsor-status.verified { background: #e6f4e4; color: #2f6b30; }
.sponsor-status.blocked { background: #fbe6e2; color: #a03626; }
.sponsor-status.attention { background: #fdf1d8; color: #8a6316; }
.sponsor-status.pending { background: #eee9e2; color: #6a6157; }

.review-warning { border: 1px solid #e0b64f; background: #fdf7e6; border-radius: 10px;
  padding: 14px 16px; margin: 14px 0; }
.review-warning strong { display: block; margin-bottom: 4px; }
.review-warning ul { margin: 6px 0 0; padding-left: 20px; }

/* Evidence must never be cut off by a narrow pane - it scrolls instead. */
.verification-scroll { overflow-x: auto; margin-top: 12px; }
.verification-table { width: 100%; min-width: 720px; border-collapse: collapse;
  font-size: .84rem; }
.verification-table th { text-align: left; padding: 8px 10px; border-bottom: 2px solid #e2d9cd;
  color: #6a6157; font-weight: 600; }
.verification-table td { padding: 8px 10px; border-bottom: 1px solid #f0eae1;
  vertical-align: top; }
.verification-table tr.party-empty td { color: #a49a8d; }

.outcome-buttons { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.outcome-buttons button { width: 100%; }
.danger-button { background: #a03626; color: #fff; border: 1px solid #8c2f21;
  border-radius: 8px; padding: 10px 16px; font-weight: 600; cursor: pointer; }
.danger-button:disabled { opacity: .5; cursor: not-allowed; }

/* A blocked action must LOOK blocked. An enabled-looking button that silently
   does nothing teaches people the interface is broken rather than that the
   decision is gated. */
.outcome-buttons button:disabled { opacity: .45; cursor: not-allowed; filter: grayscale(1); }

/* On a phone the sponsor status must wrap rather than run off the edge — a
   half-visible "Legal sponsor verified — natural per…" is worse than two lines. */
@media (max-width: 640px) {
  .sponsor-status { white-space: normal; display: inline-block; margin-top: 6px; }
}

/* A missing verification basis is the thing a reviewer must not skim past. */
.basis-missing { color: #a03626; }
.basis-notes { font-weight: 400; font-size: .86rem; line-height: 1.45; }

/* ---- WR-62 slice 3: activity-area review -------------------------------- */
.review-map { height: 460px; border: 1px solid #e2d9cd; border-radius: 10px;
  background: #f6f2ec; margin: 12px 0; }
.map-layer-toggles { display: flex; gap: 16px; font-size: .84rem; color: #6a6157; }
.map-layer-toggles label { display: flex; align-items: center; gap: 6px; }

.map-legend { display: flex; flex-wrap: wrap; gap: 18px; font-size: .84rem;
  color: #4a4238; margin: 8px 0 16px; }
.map-legend span { display: flex; align-items: center; gap: 7px; }
.map-legend .swatch { width: 16px; height: 12px; border-radius: 2px; display: inline-block; }
.swatch.property { background: #ffffff; border: 1px dashed #4a4a4a; }
.swatch.activity { background: rgba(217,43,43,.35); border: 1px solid #c01c1c; }
.swatch.added    { background: rgba(240,165,0,.45); border: 1px solid #b37700; }
.swatch.removed  { background: rgba(122,47,176,.40); border: 1px solid #7a2fb0; }
.swatch.excluded { background: rgba(150,150,150,.18); border: 1px dashed #8a8a8a; }

.area-summary .off-property { color: #b37700; }
.area-summary .hash, td.hash { font-family: Consolas, monospace; font-size: .78rem; }

/* The 13 pre-generation questions. */
.works-grid { display: grid; gap: 2px; margin: 14px 0; }
.works-row { display: grid; grid-template-columns: minmax(200px, 1fr) auto;
  align-items: center; gap: 12px; padding: 7px 10px; border-radius: 6px; }
.works-row:nth-child(odd) { background: #faf7f2; }
.works-label { font-size: .9rem; }
.works-answers { display: flex; gap: 6px; }
.works-option { display: flex; align-items: center; gap: 5px; padding: 4px 10px;
  border: 1px solid #ded4c6; border-radius: 999px; font-size: .82rem; cursor: pointer;
  background: #fff; white-space: nowrap; }
.works-option.chosen { border-color: var(--color-primary-dark); background: var(--color-primary-light); font-weight: 600; }
.works-notes { display: block; margin-top: 14px; }
.works-notes textarea { display: block; width: 100%; margin-top: 6px; }

/* One frontage, one decision. */
.frontage { border: 1px solid #e2d9cd; border-left-width: 5px; border-radius: 10px;
  padding: 14px 16px; margin: 12px 0; }
.frontage.included  { border-left-color: #b37700; background: #fffaf0; }
.frontage.excluded  { border-left-color: #b0b0b0; background: #fafafa; }
.frontage.unsure    { border-left-color: #e0b64f; background: #fdfaf0; }
.frontage.undecided { border-left-color: #ded4c6; }
.frontage-head { display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; }
.frontage-head h3 { margin: 0 0 2px; font-size: 1rem; }
.frontage-reason { font-size: .88rem; line-height: 1.5; color: #4a4238; margin: 8px 0; }
.frontage-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.frontage .source { font-size: .74rem; color: #8a8178; margin-top: 8px; }

.decision-pill { padding: 3px 11px; border-radius: 999px; font-size: .76rem;
  font-weight: 600; white-space: nowrap; }
.decision-pill.included  { background: #fdf1e0; color: #8a5a00; }
.decision-pill.excluded  { background: #efefef; color: #666; }
.decision-pill.unsure    { background: #fdf6e0; color: #8a6316; }
.decision-pill.undecided { background: #f4efe8; color: #6a6157; }

.review-warning.difference { border-color: #9ec7e8; background: #f2f8fd; }
.upload-label { display: block; font-size: .84rem; color: #4a4238; margin-top: 6px; }
.upload-label input { display: block; margin-top: 5px; }

.check-pass { color: #2f6b30; font-weight: 600; }
.check-fail { color: #a03626; font-weight: 600; }
tr.superseded { opacity: .58; }
tr.superseded td:first-child::after { content: " (superseded)"; font-weight: 400;
  font-size: .74rem; color: #8a8178; }

/* The difference map draws added area green and removed purple. The legend has to
   agree with the map: an amber swatch next to a green polygon is worse than no
   legend at all. */
.swatch.diff-added   { background: rgba(31,138,59,.45); border: 1px solid #1f8a3b; }
.swatch.diff-removed { background: rgba(122,47,176,.40); border: 1px solid #7a2fb0; }

/* The breadcrumb above a workspace header. Used by several pages and never
   actually styled — it has been rendering as bare inline text with no spacing. */
.breadcrumb-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: .82rem; color: #8a8178; margin-bottom: 6px; }
.breadcrumb-row .back-link { color: var(--color-primary-dark); text-decoration: none; }
.breadcrumb-row .back-link:hover { text-decoration: underline; }
.breadcrumb-row strong { color: #4a4238; font-weight: 600; }

/* WR-63 slice 4 — the preliminary screening gate, shown on the enquiry workspace
   immediately above the commercial document. It lives here rather than in a scoped
   sheet because EnquiryWorkspace.razor has none. Amber until the screen has been
   confirmed, green once a fee proposal is permitted: the state a person needs to
   read is "may I quote yet", not "is there a screen". */
.screen-gate { padding: 12px 14px; border-radius: 9px; margin: 4px 0 0;
  border-left: 5px solid #c8862a; background: #fffaf1; font-size: .88rem;
  line-height: 1.55; color: #4a4238; }
.screen-gate.is-open { border-left-color: #2f7d44; background: #f5fbf6; }
.screen-gate strong { display: block; margin-bottom: 4px; color: #3a332c; }

/* WR-64 slice 5 — the promotion conditions, shown all together.
   Every condition is listed, met and unmet alike, because the shape of what is
   outstanding is as useful as the list of it: someone who can see nine ticks and
   one cross knows they are nearly there. Unmet rows carry their reason inline
   rather than in a tooltip nobody opens. */
.promotion-conditions { list-style: none; padding: 0; margin: 12px 0 0; }
.promotion-conditions li { display: grid;
  grid-template-columns: 20px minmax(220px, auto) 1fr; gap: 4px 10px;
  align-items: baseline; padding: 7px 10px; border-radius: 7px; font-size: .87rem; }
.promotion-conditions li.met { color: #4a4238; }
.promotion-conditions li.unmet { background: #fff6f4; }
.promotion-conditions .mark { font-weight: 700; }
.promotion-conditions li.met .mark { color: #2f7d44; }
.promotion-conditions li.unmet .mark { color: #a52a1e; }
.promotion-conditions li.unmet .name { font-weight: 600; }
.promotion-conditions .why { grid-column: 3; color: #7a2318; font-size: .82rem;
  line-height: 1.5; }

/* The way back, on the shared page header. Eighteen pages had grown their own .back-link with
   their own arrow, spacing and colour; this is that need met once. */
.ax-os-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 10px;
    color: var(--color-gunmetal);
    font-size: var(--archex-text-sm, 13.5px);
    font-weight: 700;
    text-decoration: none;
}

.ax-os-back:hover { color: var(--color-primary-dark); }

.ax-os-back:focus-visible {
    outline: 3px solid var(--color-primary);
    outline-offset: 3px;
    border-radius: 4px;
}

/* ================================================================================================
   THE SHARED PAGE HEADER WINS, WHEREVER IT IS (20 September 2026)
   ------------------------------------------------------------------------------------------------
   AxOperatingHeader was rendering two different ways depending on the page's root class, which is
   the opposite of what a shared header is for:

       inside .ax-page     title 23.2px, eyebrow grey,   margin 16px
       everywhere else     title 36px,   eyebrow orange, margin 24px

   Two causes, both above in this file:

     1. `.ax-page h1 { font-size: 1.45rem !important }` catches the header's own title along with
        every other h1 on the page.

     2. `.ax-page .ax-os-header p:not(.eyebrow)` was written to spare the eyebrow and does not,
        because the shared header renders class="ax-os-eyebrow" — which is not "eyebrow", so the
        selector matches it and greys out the very thing it was meant to skip.

   Rather than unpick two !important rules that dozens of pages still lean on, this restores the
   header's own styling inside them. It is placed last so it wins on order, and it is scoped to the
   header so nothing else on those pages moves.
   ============================================================================================== */

.ax-page .ax-os-heading h1,
.ax-workspace .ax-os-heading h1 {
    font-size: var(--archex-text-2xl) !important;
    line-height: 1.12 !important;
    letter-spacing: -.02em !important;
}

/* The `p` in these two selectors is NOT redundant, and removing it silently reverts the eyebrow to
   grey. The rule being overridden is `.ax-page .ax-os-header p:not(.eyebrow)`, which scores three
   classes PLUS an element; a three-class selector loses to it however late it appears and however
   many !importants it carries. Measured, not guessed: the first attempt here omitted the `p` and
   the eyebrow stayed grey while the browser reported this rule as matching. */
.ax-page .ax-os-header p.ax-os-eyebrow,
.ax-workspace .ax-os-header p.ax-os-eyebrow {
    margin: 0 0 8px !important;
    color: var(--color-primary-dark) !important;
    font-size: .7rem !important;
    font-weight: 800 !important;
    letter-spacing: .16em !important;
    text-transform: uppercase !important;
}

.ax-page .ax-os-header p.ax-os-subtitle,
.ax-workspace .ax-os-header p.ax-os-subtitle {
    margin: 8px 0 0 !important;
    color: var(--color-gunmetal) !important;
    font-size: var(--archex-text-base) !important;
    max-width: 78ch;
}

.ax-page .ax-os-header,
.ax-workspace .ax-os-header {
    align-items: flex-end !important;
    margin: 0 0 var(--space-4) !important;
}

/* The way back sits above the eyebrow and must not be caught by the p:not(.eyebrow) rule either. */
.ax-page .ax-os-back,
.ax-workspace .ax-os-back {
    font-size: var(--archex-text-sm) !important;
    color: var(--color-gunmetal) !important;
}

/* The breadcrumb trail on the shared page header. Four pages had each grown their own
   .breadcrumb-row with its own separator and spacing; this is that need met once. */
.ax-os-crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 0 0 10px;
    color: var(--archex-faint, var(--color-gunmetal));
    font-size: var(--archex-text-sm, 13.5px);
    font-weight: 600;
}

.ax-os-crumbs a {
    color: var(--color-gunmetal);
    text-decoration: none;
    font-weight: 700;
}

.ax-os-crumbs a:hover { color: var(--color-primary-dark); text-decoration: underline; text-underline-offset: 3px; }

.ax-os-crumbs a:focus-visible {
    outline: 3px solid var(--color-primary);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Same specificity trap as the eyebrow above: inside .ax-page these would otherwise be caught by
   `.ax-page .ax-os-header p:not(.eyebrow)` and by the blanket link colours. */
.ax-page .ax-os-header .ax-os-crumbs,
.ax-workspace .ax-os-header .ax-os-crumbs {
    margin: 0 0 10px !important;
    font-size: var(--archex-text-sm) !important;
}

/* ================================================================================================
   THE STACKED HEADER STAYS INSIDE THE SCREEN (20 September 2026)
   ------------------------------------------------------------------------------------------------
   Below 850px the shared header stacks. Stacking on its own is not enough: two rules further up
   this file set `align-items: center !important` and then `align-items: flex-end !important` on
   `.ax-page .ax-os-header`, and in a column that sizes each child to its own content. A long
   subtitle therefore made the heading 946px wide inside a 360px phone, and Permissions, Audit and
   Governance could be dragged 833px sideways while every screenshot of it looked correct — what
   overflowed was off the side of the picture.

   This block has to carry !important to reach past those two, and it has to come last. It is the
   only place in this stylesheet where the phone layout is stated. */
@media (max-width: 850px) {
    .ax-os-header,
    .ax-page .ax-os-header,
    .ax-workspace .ax-os-header {
        flex-direction: column !important;
        align-items: stretch !important;
    }

    .ax-os-header > *,
    .ax-page .ax-os-header > *,
    .ax-workspace .ax-os-header > * {
        max-width: 100% !important;
        min-width: 0 !important;
    }

    .ax-os-header-actions { justify-content: flex-start !important; }
}

/* ================================================================================================
   A BUTTON IS THE SIZE OF A BUTTON (20 September 2026)
   ------------------------------------------------------------------------------------------------
   The rules above give .primary-button, .action-button and .secondary-button the brand colour, the
   border and the radius — and say nothing about their SIZE. A page that used the class without also
   styling it therefore got an orange control with the browser's own `padding: 1px 6px`: "New
   enquiry" on the enquiry register rendered 18px tall. Coloured correctly, and too small to press.

   Stated here, beside the rules that made the class mean something, rather than in each page.

   A FLOOR WAS NOT ENOUGH (21 September 2026). This began as a minimum, and said so: "anything that
   sets its own padding still wins". Measured across ten routes, the same two classes rendered at
   ten different heights — 36, 38, 39, 40, 42, 43, 44, 45, 47 and 50px — because twenty scoped
   sheets set their own padding or min-height, and the ones below the floor were on pages that
   never carried .ax-page at all, so none of this reached them.

   So it is now a ruler, and no longer gated on .ax-page. Two consequences worth understanding:

   The height is var(--archex-control-h), the same token .ax-btn uses. The application had two
   button systems — .ax-btn/.ax-btn-primary and .primary-button/.secondary-button, roughly half the
   pages each — and this at least makes them the same size.

   The declarations are !important because a scoped sheet's `.primary-button[b-xyz]` and a plain
   `.primary-button` here have equal specificity, and scoped CSS is served after this file. Without
   it the twenty local paddings win, which is exactly the state being corrected.
   ============================================================================================== */
.primary-action,
.primary-button,
.hero-action,
.action-button,
.secondary-button,
button.quiet {
    min-height: var(--archex-control-h) !important;
    padding: 0 12px !important;
    font-size: var(--archex-text-base);
}

/* A DELIBERATE SMALLER ONE. .secondary-button.compact is written on eight buttons and was 34px in
   ProjectWorkspace's own sheet. An explicit modifier is a decision, not drift, so it is honoured
   here rather than flattened — the same treatment .empty-state.compact gets. Under a thumb it
   still goes to 44px with everything else. */
.secondary-button.compact {
    min-height: 32px !important;
    padding: 0 12px !important;
    font-size: var(--archex-text-sm);
}

/* TOUCH. On a tablet or a phone the finger, not the cursor, is the instrument: 38px is comfortable
   with a mouse and small under a thumb. pointer:coarse is exactly the question being asked, so the
   dense desktop layout is left alone. The classes are named rather than every button, because a
   blanket rule would stretch the inline links inside prose to 44px as well. */
@media (pointer: coarse) {
    /* Ungated and !important for the same reason the rule above is: half the pages never carried
       .ax-page, and the desktop height above is now !important, which this has to outrank. */
    .primary-action,
    .primary-button,
    .hero-action,
    .action-button,
    .secondary-button,
    button.quiet,
    .text-button,
    .status-pill {
        min-height: 44px !important;
    }
    /* .ax-btn's touch size lives beside .ax-btn itself, in the foundation: a class is declared in
       one stylesheet, and there is a check that says so. */

    /* The map zoom controls are OpenLayers own, and 20px square. A map is the thing most likely to
       be used on a tablet in the field, so they are the last controls that should stay mouse-sized. */
    .ol-zoom .ol-zoom-in,
    .ol-zoom .ol-zoom-out {
        width: 40px;
        height: 40px;
        font-size: 1.3rem;
    }

    /* An icon-only control is square, so it needs the width as well as the height. */
    .ax-page .ax-icon-btn,
    .ax-page .staff-menu-button,
    .ax-page .period-arrow,
    .ax-page .close-button {
        min-width: 44px;
        min-height: 44px;
    }
}

/* ================================================================================================
   EVERYTHING WRITTEN ON A CHOSEN CONTROL TAKES ITS COLOUR (20 September 2026)
   ------------------------------------------------------------------------------------------------
   The selected rule colours the control. Its CHILDREN kept whatever the page had given them, so the
   selected summary card on Reports became an orange fill with an orange number on it and the
   selected entry on the map register had an orange CHMP number on orange — both invisible.

   THIS BLOCK IS LAST IN THE FILE ON PURPOSE. Several accent rules above also carry !important at
   the same specificity — "accent text that pages painted green → brand copper" is one — and among
   equal !important declarations the last one wins. Written earlier in the file it lost, and the
   map register's CHMP number stayed orange-on-orange.

   A chip with its own fill inside a chosen control is given the translucent treatment instead of
   inheriting, because inheriting made the schedule's tab icon white on its own white square.
   ============================================================================================== */
.ax-page:not(.activity-page) button.active *,
.ax-page:not(.activity-page) button.selected *,
.ax-page:not(.activity-page) button.is-on *,
.ax-page:not(.activity-page) .summary-card.selected * {
    color: inherit !important;
}

.ax-page:not(.activity-page) button.active .tab-icon,
.ax-page:not(.activity-page) button.selected .tab-icon,
.ax-page:not(.activity-page) button.is-on .tab-icon {
    background: rgba(255, 255, 255, .18) !important;
    border-color: rgba(255, 255, 255, .38) !important;
    color: #fff !important;
}

/* ================================================================================================
   FILTER CHIPS — .ax-chips / .ax-chip / .ax-chip-count          (20 September 2026)
   ------------------------------------------------------------------------------------------------
   ONE CONTROL, WRITTEN ONCE. Seven pages had drawn their own row of "show me only these" chips:
   Tasks (.filter), Library (.lib-filter), People (.filter-chip), OrganisationWorkspace
   (.project-filter-row button), Reports (.filter-button), Field records (.filter-row button) and
   the project diary (.ax-diary-filters button). Tasks and Library were byte-for-byte identical
   apart from the class name.

   They diverged because each lived in that page's SCOPED stylesheet, where no other component can
   reach it — so the only way to reuse the design was to paste it. Heights had drifted from 31px to
   48px for the same control, and three of them sat under the 40px touch target the rest of the
   application keeps. Selected state had three different treatments.

   WHY EVERY DECLARATION IS !important. Two rules above this one already govern any button inside
   .ax-page: the hammer forces unchosen buttons to the surface colour, and the stray-chip catch-all
   matches [class*="chip"] — which .ax-chip is. Without !important the catch-all wins and an
   unselected chip renders in panel grey; worse, `button.is-on *` forces a selected chip's count to
   `color: inherit` while the catch-all holds its background at panel, which is white on light grey.
   That is the same collision that made the Library chips invisible before, so it is spelled out
   here rather than rediscovered.

   Both .is-on and .active select a chip. Supporting the two names means a page migrating to this
   pattern changes only its container and base class, never the Razor conditional that writes the
   state — and those conditionals are where the attribute quote trap bites.
   ============================================================================================== */

.ax-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: var(--space-3, 16px);
}

.ax-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 0 14px;
    border: 1px solid var(--color-divider) !important;
    border-radius: 999px;
    background: var(--color-surface) !important;
    color: var(--color-gunmetal) !important;
    font: inherit;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
}

.ax-chip:hover:not(:disabled) { border-color: var(--color-primary) !important; }

.ax-chip.is-on,
.ax-chip.active {
    background: var(--color-primary) !important;
    border-color: var(--color-primary) !important;
    color: #fff !important;
}

.ax-chip .ax-chip-count {
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--color-panel) !important;
    color: var(--color-gunmetal) !important;
    font-size: var(--archex-text-xs, 12px);
    font-variant-numeric: tabular-nums;
}

/* Prefixed with .ax-page so this beats `button.is-on *`, which would otherwise force the count to
   inherit white while the catch-all held its background grey.

   The badge DARKENS rather than lightens. Both pages this replaced used a 26% white wash, which
   puts white digits on pale orange: measured on the Tasks chips at 2.35:1, under the 2.4 this
   application holds itself to. An 18% black wash over the same chip measures 4.26:1, and reads as
   inset rather than floating. */
.ax-page .ax-chip.is-on .ax-chip-count,
.ax-page .ax-chip.active .ax-chip-count,
.ax-chip.is-on .ax-chip-count,
.ax-chip.active .ax-chip-count {
    background: rgba(0, 0, 0, .18) !important;
    color: #fff !important;
}

/* ================================================================================================
   ONE PAGE GUTTER  (21 September 2026)
   ------------------------------------------------------------------------------------------------
   Measured across twelve routes, the page root's padding was 24, 26, 28, 30, 32, 40 and 51.2px —
   seven values. Moving between pages, the content stepped in and out from the rail each time. It
   is the kind of difference nobody names and everybody feels.

   Stated once, by the workspace, about whatever it holds. Naming the two shared root classes left
   Knowledge out -- its root carries neither -- and adding it by name would have been the eighth
   number in a different disguise. !important because each of
   those values is written in that page's own scoped sheet, which is served after this file and has
   equal specificity.

   Pages that must reach the edge — a map, a full-bleed canvas — opt out with .ax-full-bleed rather
   than by writing their own number again.
   ============================================================================================== */
.ax-app-workspace > *:not(.ax-full-bleed) {
    padding: var(--archex-page-gutter) !important;
}

/* ================================================================================================
   BETWEEN PAGES  (21 September 2026)
   ------------------------------------------------------------------------------------------------
   There was no page-loading indication anywhere in the application. You clicked, nothing changed,
   and the only way to know ArchEx had heard you was that the page eventually arrived. On a slow
   query that reads as a broken button, and people click again.

   A compass rose rather than a generic spinner: this is a mapping application. The needle turns,
   the card does not, which is how a compass actually behaves.
   ============================================================================================== */
.ax-navigating {
    position: absolute;
    inset-inline: 0;
    top: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--archex-gap-3);
    padding: var(--archex-gap-4);
    background: color-mix(in srgb, var(--color-background) 86%, transparent);
    backdrop-filter: blur(2px);
    color: var(--color-gunmetal);
    font-weight: 700;
}

.ax-navigating-mark { width: 32px; height: 32px; flex: 0 0 32px; overflow: visible; }

/* Shared ink for every mark: filled shapes in brand orange, quiet shapes in gunmetal, and
   anything that is a line stays a line. */
.ax-navigating-mark .ax-mark-strong { fill: var(--color-primary); stroke: none; }
.ax-navigating-mark .ax-mark-quiet  { fill: var(--color-gunmetal); stroke: none; }
.ax-navigating-mark .ax-mark-ring,
.ax-navigating-mark .ax-mark-line   { fill: none; stroke: var(--color-gunmetal); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.ax-navigating-mark rect.ax-mark-strong,
.ax-navigating-mark rect.ax-mark-quiet { stroke: none; }

/* Three movements, shared out across the kit so no two consecutive marks feel identical. */
.ax-mark-spin { transform-origin: 24px 24px; animation: ax-compass 1.1s cubic-bezier(.6, 0, .4, 1) infinite; }
.ax-mark-rock { transform-origin: 24px 34px; animation: ax-rock 1.25s ease-in-out infinite; }
.ax-mark-bob  { transform-origin: 24px 24px; animation: ax-bob 1.1s ease-in-out infinite; }

@keyframes ax-rock {
    0%, 100% { transform: rotate(-11deg); }
    50%      { transform: rotate(11deg); }
}

@keyframes ax-bob {
    0%, 100% { transform: translateY(-2.5px); }
    50%      { transform: translateY(2.5px); }
}

@keyframes ax-compass {
    0%   { transform: rotate(0deg); }
    55%  { transform: rotate(340deg); }
    75%  { transform: rotate(330deg); }
    100% { transform: rotate(360deg); }
}

/* A compass that spins for a reader who has asked for less motion is just a distraction. */
@media (prefers-reduced-motion: reduce) {
    .ax-mark-spin,
    .ax-mark-rock,
    .ax-mark-bob { animation: none; }
}

/* ------------------------------------------------------------------------------------------- */
/* WHAT THE APPLICATION SAYS BACK (21 September 2026)                                           */
/* ------------------------------------------------------------------------------------------- */
/* One appearance for an outcome, replacing ".save-message", which was defined three times and
   looked different in each: white with a red border in LibraryReview, blue on a hard-coded 7px
   radius in the intake sheet, and panel-with-green-text in OrganisationWorkspace — where it had
   no error variant at all, so a refusal there rendered in the colour of success.

   The refusal deliberately matches .ax-error, which the same application already used for the
   same idea. Two shapes for "this did not happen" was one too many. */
.ax-outcome {
    display: flex;
    flex-direction: column;
    gap: var(--archex-gap-2);
    margin: var(--archex-gap-4) 0;
    padding: var(--archex-gap-4) var(--archex-gap-5);
    border: 1px solid var(--color-divider);
    border-left-width: 3px;
    border-radius: var(--archex-radius-small);
    font-size: var(--archex-text-base);
}

.ax-outcome:focus { outline: none; }
.ax-outcome:focus-visible { outline: 2px solid var(--archex-ochre); outline-offset: 2px; }

.ax-outcome-title {
    font-family: var(--archex-font-heading);
    font-size: var(--archex-text-md);
    font-weight: 700;
}

.ax-outcome-body { margin: 0; }
.ax-outcome-actions { display: flex; gap: var(--archex-gap-3); flex-wrap: wrap; }

.ax-outcome-refusal {
    background: rgba(198, 40, 40, .05);
    border-color: rgba(198, 40, 40, .26);
    color: #7F1D1D;
}

.ax-outcome-done {
    background: rgba(46, 125, 50, .06);
    border-color: rgba(46, 125, 50, .28);
    color: #1B5E20;
}

/* Amber, not the brand ochre: .ax-notice already uses the ochre tint for standing information,
   and a caution has to be tellable from a note at a glance. #6B4A00 on this tint is 6.8:1. */
.ax-outcome-caution {
    background: rgba(180, 120, 0, .07);
    border-color: rgba(180, 120, 0, .30);
    color: #6B4A00;
}

.ax-outcome-note {
    background: var(--color-panel);
    border-color: var(--color-divider);
    color: var(--color-gunmetal);
}

/* ------------------------------------------------------------------------------------------- */
/* WHERE THINGS ARE KEPT (21 September 2026)                                                    */
/* ------------------------------------------------------------------------------------------- */
/* Three stores, two of them calling their contents "documents", and no page saying the other
   two existed — so a library of 19 sitting beside a register of 748 read as 729 lost files.
   This band is the sentence that was missing. It is navigation, not a filter: each count is the
   place that holds it, so it is built from links and reads as links. */
.ax-holdings {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--archex-gap-3);
    margin: var(--archex-gap-4) 0;
}

.ax-holdings .ax-holding {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--archex-gap-3) var(--archex-gap-4);
    border: 1px solid var(--color-divider);
    border-radius: var(--archex-radius-small);
    background: #fff;
    color: inherit;
    text-decoration: none;
}

.ax-holdings a.ax-holding:hover,
.ax-holdings a.ax-holding:focus-visible { border-color: var(--archex-ochre); }

/* The shelf you are standing on is stated, not offered. */
.ax-holdings .ax-holding.is-here { background: var(--color-panel); }

.ax-holdings .ax-holding strong {
    font-family: var(--archex-font-heading);
    font-size: var(--archex-text-xl);
    line-height: 1.1;
}

.ax-holdings .ax-holding > span {
    font-size: var(--archex-text-sm);
    font-weight: 700;
    color: var(--color-gunmetal);
}

.ax-holdings .ax-holding small {
    color: var(--color-gunmetal);
    font-size: var(--archex-text-sm);
    line-height: 1.4;
}

@media (max-width: 820px) {
    .ax-holdings { grid-template-columns: 1fr; }
}

/* Inside a card, beside the control that caused it: the same tones, less room. An upload refused
   under its own file picker does not need a page-sized box to be noticed. */
.ax-outcome.ax-outcome-compact {
    margin: var(--archex-gap-2) 0;
    padding: var(--archex-gap-2) var(--archex-gap-3);
    gap: 2px;
    font-size: var(--archex-text-sm);
}

/* ------------------------------------------------------------------------------------------- */
/* PRINTING (21 September 2026)                                                                  */
/* ------------------------------------------------------------------------------------------- */
/* The application had no print rules, so printing any page printed the brand bar, the top bar and
   the whole navigation rail beside a squeezed page. The SWMS is meant to be printed or saved as a
   PDF for the job file, and it is not the only page that will be. On paper, only the page. */
/* The shell's own print rules live with the shell, in archex-foundation.css. Only two things are here:
   classes this sheet owns, and the page gutter — which this sheet sets with !important, so its print
   override has to be here too. */
@media print {
    .ax-navigating,
    .no-print {
        display: none !important;
    }

    .ax-app-workspace > *:not(.ax-full-bleed) {
        padding: 0 !important;
        margin: 0 !important;
    }
}

/* ================================================================================================
   THE CARD THAT SAYS WHAT TO DO (24 September 2026)

   SHARED, NOT PASTED. It began life inside EnquiryWorkspace.razor.css, and the moment the
   screening page needed the same card the choice was to copy it or to move it here. Seven pages in
   this application each drew their own filter chip that way, and no two of them ended up the same
   — which is exactly the complaint this card exists to answer. Adam Deane: "nothing is the same".

   Any page can now open with one thing to do, and every one of them will look identical.
   ================================================================================================ */
/* ---- THE CARD THAT SAYS WHAT TO DO -------------------------------------------------------------

   BIGGER THAN EVERYTHING ELSE ON PURPOSE. It is the answer to "what do I do with this", which is
   the question somebody opens an enquiry to ask, and the page's whole failure was that the answer
   was the same size as nine things that were not the answer. */

.next-card {
    padding: 22px 24px;
    border-left: 4px solid var(--archex-ochre, #F26C21);
}

.next-eyebrow {
    margin: 0;
    color: var(--archex-ochre-strong, #C9541A);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.next-title {
    margin: 6px 0 0;
    font-family: var(--archex-font-heading, inherit);
    font-size: 1.45rem;
    line-height: 1.2;

    /* SET, NOT INHERITED. A global h1-h6 colour rule is why headings on tinted surfaces elsewhere
       in the application rendered near-black on near-black; this one names its own colour so a
       later change to the waiting or done tint cannot swallow it. */
    color: var(--archex-text, #2B2B2B);
}

.next-why {
    max-width: 62ch;
    margin: 10px 0 0;
    color: var(--archex-muted, #3B3B3B);
    line-height: 1.55;
}

.next-do {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 18px;
}

/* The two values side by side while the reason is being given. Somebody answering "why did this
   change" needs to see what it changed from without scrolling to find it. */
.next-change {
    margin: 14px 0 0;
    padding: 12px 14px;
    border-radius: 6px;
    background: var(--archex-panel, #F2EDE6);
    line-height: 1.6;
}

/* A secure link is read aloud down a phone as often as it is clicked, so it wraps rather than
   scrolling sideways and it is never truncated. */
.next-link {
    margin: 14px 0 0;
}

.next-link code {
    display: block;
    padding: 10px 12px;
    border: 1px solid var(--archex-border, #E3DCD1);
    border-radius: 6px;
    background: var(--archex-panel, #F2EDE6);
    font-size: 0.85rem;
    overflow-wrap: anywhere;
}

/* The four tones. Waiting is deliberately the quiet one: a card that shouts when the honest answer
   is "nothing, they have not come back to you" trains everybody to stop reading the loud ones. */
.next-card.is-doing { border-left-color: var(--archex-ochre, #F26C21); }

.next-card.is-attention {
    border-left-color: #C9541A;
    background: #FFF8F3;
}

.next-card.is-waiting {
    border-left-color: var(--archex-border, #E3DCD1);
}

.next-card.is-waiting .next-eyebrow {
    color: var(--archex-muted, #3B3B3B);
}

.next-card.is-done {
    border-left-color: var(--archex-success, #2E7D32);
}

.next-card.is-done .next-eyebrow {
    color: var(--archex-success, #2E7D32);
}


@media (max-width: 700px) {
    .next-card { padding: 18px 16px; }
    .next-title { font-size: 1.25rem; }

    /* Full-width buttons under a thumb. A next-step card usually has one button and it is the
       thing the page exists for, so it gets the width rather than sitting in a corner. */
    .next-do > * { flex: 1 1 auto; }
}
