/*
 * Forge — modern chrome (AXO-00401)
 *
 * The app chrome restyled in the Polaris design language, in Axon navy and cyan. Scoped so it
 * can never reach a customer-facing document:
 *
 *   - Every rule is prefixed `html.fm`, which is set only when the ?fm flag wants it AND this
 *     file actually loaded. Remove the <link> and the legacy look returns cleanly.
 *   - Rules written against generic Tailwind classes also carry
 *       :not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *)
 *     so they cannot match inside a quote, invoice or contract.
 *   - Loaded media="screen", so print keeps the legacy rules untouched.
 *   - Never declares --axon-* or --quote-* (the documents read those); new tokens are --fm-*.
 *
 * tests/doc-freeze.spec.js proves the documents are unchanged with this file on and off.
 */

/* ── 1. Tokens ──────────────────────────────────────────────────────────────────────────────
 * Derived from the variables applyBrandColorTokens() already writes on :root, so a brand
 * colour changed in Settings flows straight into the chrome with no JS change. Semantic names,
 * so dark mode is a matter of redefining these under html.dark later. */
:root {
    --fm-primary: var(--axon-blue);
    --fm-primary-rgb: var(--axon-blue-rgb);
    --fm-primary-hover: color-mix(in srgb, var(--axon-blue) 86%, #000);
    --fm-primary-soft: color-mix(in srgb, var(--axon-blue) 8%, #fff);
    --fm-primary-soft-border: color-mix(in srgb, var(--axon-blue) 22%, #fff);
    --fm-navy: var(--axon-dark-blue);
    --fm-accent: var(--quote-light-blue, #51BBE1);
    --fm-accent-soft: color-mix(in srgb, var(--fm-accent) 20%, transparent);

    --fm-bg: #f8fafc;
    --fm-bg-2: #eef2f9;
    --fm-surface: rgb(255 255 255 / 0.82);
    --fm-surface-solid: #fff;
    --fm-surface-muted: #f8fafc;
    --fm-surface-hover: rgba(var(--axon-blue-rgb), 0.04);
    --fm-border: rgb(226 232 240 / 0.7);
    --fm-border-strong: #e2e8f0;
    --fm-text: #0f172a;
    --fm-text-2: #334155;
    --fm-text-muted: #64748b;
    --fm-text-subtle: #94a3b8;

    --fm-sidebar-bg: color-mix(in srgb, var(--axon-dark-blue) 92%, #000);
    --fm-sidebar-text: #94a3b8;
    --fm-sidebar-text-hover: #e2e8f0;
    --fm-sidebar-hover: rgb(255 255 255 / 0.06);

    --fm-r-card: 1.5rem;
    --fm-r-tile: 1rem;
    --fm-r-control: 0.75rem;
    --fm-r-btn: 0.625rem;
    --fm-shadow-card: 0 8px 30px rgb(15 23 42 / 0.05);
    --fm-shadow-lift: 0 14px 36px -14px rgba(var(--axon-blue-rgb), 0.3);
    --fm-shadow-header: 0 4px 30px -10px rgba(var(--axon-blue-rgb), 0.18);
    --fm-shadow-btn: 0 4px 14px -4px rgba(var(--axon-blue-rgb), 0.5);
    --fm-ring: 0 0 0 3px rgba(var(--axon-blue-rgb), 0.18);
    --fm-dur: 200ms;
    --fm-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
    --fm-fs-eyebrow: 11px;
    --fm-track-eyebrow: 0.08em;
}
/* html.dark { --fm-bg: #0b1226; --fm-surface: rgb(17 32 69 / 0.7); ... }  — later. */


/* ── 2. Shell ─────────────────────────────────────────────────────────────────────────────── */

html.fm .forge-app-shell {
    background: linear-gradient(135deg, var(--fm-bg) 0%, var(--fm-bg-2) 100%);
}

/* The header already carries Polaris classes (bg-white/75, backdrop-blur-xl, a hairline
   border); guard B stopped the legacy override masking them. Only the glow is re-tinted. */
html.fm header.forge-app-header {
    box-shadow: var(--fm-shadow-header);
}

/* Sidebar — background and depth ONLY. Its position, left, transform and width drive the mobile
   drawer (css ~1959 and toggleMobileNav) and are never touched here. */
html.fm #forge-sidebar {
    background: var(--fm-sidebar-bg);
    border-right-color: rgb(255 255 255 / 0.06);
    box-shadow: 4px 0 24px rgb(0 0 0 / 0.18);
}
html.fm #forge-sidebar .forge-sidebar-footer {
    background: transparent;
}
html.fm #forge-sidebar .forge-sidebar-brand-icon {
    background: linear-gradient(135deg, var(--fm-accent), var(--fm-primary));
    box-shadow: 0 8px 20px -6px color-mix(in srgb, var(--fm-accent) 55%, transparent);
}
html.fm #forge-sidebar .forge-sidebar-brand p {
    color: var(--fm-accent);
}

/* Nav items: sentence case, medium weight, a 4px left rail that lights up cyan when active.
   Font size stays at the global 13px the .text-xs bump already gives. */
html.fm #forge-sidebar .sidebar-link {
    width: 100%;
    padding: 0.625rem 0.75rem;
    border-radius: 0 0.75rem 0.75rem 0;
    border: 0;
    border-left: 4px solid transparent;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    line-height: 1.25;
    color: var(--fm-sidebar-text);
    background: transparent;
    box-shadow: none;
    transition: background-color var(--fm-dur) var(--fm-ease), color var(--fm-dur) var(--fm-ease),
                box-shadow var(--fm-dur) var(--fm-ease);
}
/* Lucide icons in place of the legacy set (the pair lives in the markup; see ax_quote.css). */
html.fm #forge-sidebar .fm-ico-legacy {
    display: none;
}
html.fm #forge-sidebar .fm-ico-new {
    display: inline-block;
}
html.fm #forge-sidebar .sidebar-link svg {
    width: 18px;
    height: 18px;
    opacity: 0.7;
    transition: transform var(--fm-dur) var(--fm-ease), opacity var(--fm-dur) var(--fm-ease);
}
html.fm #forge-sidebar .sidebar-link:hover {
    background: var(--fm-sidebar-hover);
    color: var(--fm-sidebar-text-hover);
}
html.fm #forge-sidebar .sidebar-link:hover svg {
    opacity: 1;
    transform: scale(1.1);
}
html.fm #forge-sidebar .sidebar-link.active,
html.fm #forge-sidebar .sidebar-link.active:hover {
    background: linear-gradient(90deg, var(--fm-accent-soft), transparent);
    color: var(--fm-accent);
    font-weight: 700;
    border-left-color: var(--fm-accent);
    box-shadow: inset 4px 0 20px -5px color-mix(in srgb, var(--fm-accent) 40%, transparent);
}
html.fm #forge-sidebar .sidebar-link.active svg {
    opacity: 1;
}
html.fm #forge-sidebar .sidebar-link:focus-visible {
    outline: 2px solid var(--fm-accent);
    outline-offset: -2px;
}

/* Operations: a quiet group heading, its children indented like Polaris sub-items. */
html.fm #forge-sidebar #nav-ops-toggle {
    margin-top: 0.75rem;
    padding: 0.5rem 0.75rem;
    border-top: 1px solid rgb(255 255 255 / 0.06);
    border-radius: 0;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: #64748b;
}
html.fm #forge-sidebar #nav-ops-toggle:hover {
    background: transparent;
    color: var(--fm-sidebar-text-hover);
}
html.fm #forge-sidebar #nav-ops-items {
    border-left: 0;
    margin-left: 0;
    padding-left: 0.75rem;
}
html.fm #forge-sidebar #nav-ops-items .sidebar-link {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
}


/* ── 3. Surfaces ──────────────────────────────────────────────────────────────────────────── */

/* Page-level cards: the large-radius white panels. Only div/section, so buttons and inputs that
   happen to be bg-white are not turned into cards. Never add backdrop-filter, transform or
   filter to a container — any of them traps position:fixed modals inside it. */
html.fm #app-shell main :is(div, section).bg-white:is(.rounded-2xl, .rounded-3xl):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    background: var(--fm-surface);
    border-radius: var(--fm-r-card);
    box-shadow: var(--fm-shadow-card);
}
/* Neutral cards get the Polaris hairline. A card with a COLOURED border (an error or warning
   panel) keeps its colour — that border is a signal, not decoration. */
html.fm #app-shell main :is(div, section).bg-white:is(.rounded-2xl, .rounded-3xl):not(:is([class*="border-emerald"],[class*="border-green"],[class*="border-red"],[class*="border-rose"],[class*="border-amber"],[class*="border-yellow"],[class*="border-orange"],[class*="border-indigo"],[class*="border-purple"],[class*="border-violet"],[class*="border-blue"],[class*="border-sky"],[class*="border-cyan"],[class*="border-teal"],[class*="border-pink"],[class*="border-fuchsia"])):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    border-color: var(--fm-border);
}

/* Dashboard KPI tiles, as Polaris KPI tiles: uniform hairline, a lift on hover. Their coloured
   eyebrow label already carries the category, so the 4px coloured top rail goes.
   !important is needed on the border colour only: the global blue remap in ax_quote.css forces
   `border-blue-200` to full-strength navy at !important, turning a border meant to be pale into
   a heavy ring. The legacy glass rule used to hide that by painting every card border white. */
html.fm #view-dashboard .bg-white.rounded-2xl.border-t-4 {
    border-width: 1px;
    border-color: var(--fm-border) !important;
    transition: transform 0.3s var(--fm-ease), box-shadow 0.3s var(--fm-ease);
}
html.fm #view-dashboard .bg-white.rounded-2xl.border-t-4:hover {
    transform: translateY(-4px);
    box-shadow: var(--fm-shadow-lift);
}
html.fm #view-dashboard .bg-white.rounded-2xl.border-t-4 .text-3xl {
    font-weight: 700;
    letter-spacing: -0.025em;
    font-variant-numeric: tabular-nums;
}

/* The list shell had backdrop-filter: blur(14px) over a flat background — invisible, and it
   made the shell a containing block that trapped the product-image modal rendered inside it. */
html.fm #app-shell .premium-list-shell {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-radius: var(--fm-r-card);
    border-color: var(--fm-border);
    box-shadow: var(--fm-shadow-card);
}

/* Nested tiles. The DOC exclusion matters here: the quote's own "Payment Terms" block is a
   bg-slate-50 tile, and a test depends on it. */
html.fm #app-shell :is(div, section).rounded-xl.border.bg-slate-50:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    border-color: #eef2f7;
    border-radius: var(--fm-r-tile);
    transition: border-color var(--fm-dur) var(--fm-ease);
}

/* Entry motion, as Polaris: a short fade up. Chrome only — no document node carries .fade-in. */
html.fm #app-shell .fade-in {
    animation: fm-fade-in 0.3s var(--fm-ease);
}
@keyframes fm-fade-in {
    from { opacity: 0; transform: translateY(5px); }
    to   { opacity: 1; transform: none; }
}


/* ── 4. Typography ────────────────────────────────────────────────────────────────────────────
 * Forge had `font-black uppercase tracking-widest` on 505 elements. Split by size, they are two
 * different things:
 *   - 430 are tiny (8–11px): genuine eyebrows, a label above a value ("BOOKED", "START DATE").
 *     Polaris keeps those uppercase too, so they stay — just less tightly shouted.
 *   - 75 are text-xs / text-sm: headings, subtitles and empty states ("ACTIVE PIPELINE
 *     BREAKDOWN", "ALL CAUGHT UP"). That is the shouting, and it goes to sentence case.
 * Weight: Inter is loaded only up to 700, so font-black already renders at 700 — lowering it
 * would thin text rather than tame it. Table headers and form labels keep Polaris' uppercase. */

/* Larger uppercase text → sentence case. */
html.fm #app-shell :is(h1, h2, h3, h4, h5, h6, p, div, span, a).uppercase:is(.text-xs, .text-sm, .text-base, .text-lg):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    text-transform: none;
    letter-spacing: -0.005em;
}
html.fm #app-shell :is(h1, h2, h3, h4, h5, h6).uppercase:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    text-transform: none;
    letter-spacing: -0.01em;
    font-weight: 700;
    /* No colour here: a heading's colour is often a signal ("Needs Attention" is red), and
       calming its case must not quietly strip that meaning. */
}

/* Buttons and links never shout, whatever their size. */
html.fm #app-shell :is(button, a).uppercase:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    text-transform: none;
    letter-spacing: 0.005em;
    font-weight: 600;
}

/* Tiny eyebrows stay uppercase, a touch less tightly tracked. */
html.fm #app-shell :is(p, span, div, label).uppercase:is(.text-\[8px\], .text-\[9px\], .text-\[10px\], .text-\[11px\]):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    letter-spacing: var(--fm-track-eyebrow);
}


/* ── 5. Controls ──────────────────────────────────────────────────────────────────────────────
 * Guard B took the legacy global input rule off the chrome, so inputs are styled here. Padding
 * and height are deliberately left alone: the quote's line-item tables are dense, and a taller
 * input would break their rhythm. */

html.fm #app-shell :is(input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"], [type="hidden"]), select, textarea):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    background-color: var(--fm-surface-solid);
    border: 1px solid var(--fm-border-strong);
    border-radius: var(--fm-r-control);
    color: #1e293b;
    transition: border-color var(--fm-dur) var(--fm-ease), box-shadow var(--fm-dur) var(--fm-ease);
}
/* The document exclusion must sit before the pseudo-element. doc-freeze does not capture
   ::placeholder, so this one has to be right by construction rather than by test. */
html.fm #app-shell :is(input, select, textarea):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *)::placeholder {
    color: var(--fm-text-subtle);
}
html.fm #app-shell :is(input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"], [type="hidden"]), select, textarea):focus:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    outline: none;
    border-color: var(--fm-primary);
    box-shadow: var(--fm-ring);
}
html.fm #app-shell :is(input, select, textarea):disabled:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    background-color: var(--fm-surface-muted);
    color: var(--fm-text-muted);
}
html.fm #app-shell :is(input[type="checkbox"], input[type="radio"]):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    accent-color: var(--fm-primary);
}

/* Field labels: off text-gray-400, which measures about 2.5:1 on white and fails contrast. */
html.fm #app-shell label.uppercase:is(.text-gray-400, .text-slate-400):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    color: var(--fm-text-muted);
}

/* Buttons. The global blue remap already turns bg-blue-600 into brand navy; this adds the
   Polaris shape and a navy glow. Sizes are unchanged in Phase 1. */
html.fm #app-shell button.bg-blue-600:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    border-radius: var(--fm-r-btn);
    box-shadow: var(--fm-shadow-btn);
    transition: background-color var(--fm-dur) var(--fm-ease), box-shadow var(--fm-dur) var(--fm-ease),
                transform var(--fm-dur) var(--fm-ease);
}
html.fm #app-shell button.bg-blue-600:hover:not(:disabled):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    background-color: var(--fm-primary-hover) !important;
}
html.fm #app-shell button.bg-slate-800:not(:disabled):not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    background-color: var(--fm-navy);
    border-radius: var(--fm-r-btn);
}
html.fm #app-shell button:focus-visible:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *) {
    outline: 2px solid var(--fm-primary);
    outline-offset: 2px;
}


/* ── 6. Tables & badges ───────────────────────────────────────────────────────────────────────
 * Forge's own list components. Polaris keeps table headers uppercase; they just stop being
 * weight 900 at 0.12em. Badges become Polaris' rounded-lg tinted chips rather than pills. */

html.fm #app-shell .premium-table th {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.1em;
    padding-top: 16px;
    padding-bottom: 16px;
    background: rgb(248 250 252 / 0.8);
    border-bottom-color: var(--fm-border);
    color: var(--fm-text-muted);
}
html.fm #app-shell .premium-table td {
    border-bottom-color: var(--fm-border);
}
html.fm #app-shell .premium-table tbody tr:hover {
    background: var(--fm-surface-hover);
}
html.fm #app-shell .premium-badge {
    border-radius: 0.5rem;
    font-weight: 700;
    letter-spacing: 0.08em;
}


/* ── 7. Dialogs ───────────────────────────────────────────────────────────────────────────────
 * The confirm dialog sits outside #app-shell, so it is scoped by its own id. Its OK button was
 * a stray teal (#0d9488) that matched nothing else in the brand; it now uses the primary.
 * Cancel becomes a quiet outline; the danger variant stays red. */

html.fm #app-confirm-modal .rounded-2xl {
    border-radius: 1.25rem;
    border-color: var(--fm-border);
}
html.fm #app-confirm-modal #app-confirm-heading {
    font-size: 16px !important;
    font-weight: 700;
    text-transform: none;
    letter-spacing: -0.01em;
    color: var(--fm-text);
}
html.fm #app-confirm-modal .app-confirm-btn {
    border-radius: var(--fm-r-control);
    letter-spacing: 0;
}
html.fm #app-confirm-modal .app-confirm-btn-ok:not(.app-confirm-btn-ok--danger) {
    background: var(--fm-primary);
    border-color: var(--fm-primary);
    box-shadow: var(--fm-shadow-btn);
}
html.fm #app-confirm-modal .app-confirm-btn-ok:not(.app-confirm-btn-ok--danger):hover {
    background: var(--fm-primary-hover);
}
html.fm #app-confirm-modal .app-confirm-btn-cancel {
    background: var(--fm-surface-solid);
    border-color: var(--fm-border-strong);
    color: var(--fm-text-2);
}
html.fm #app-confirm-modal .app-confirm-btn-cancel:hover {
    background: var(--fm-surface-muted);
    border-color: #cbd5e1;
}


/* ── 8. Editor chrome ─────────────────────────────────────────────────────────────────────────
 * The quote builder's tab row becomes a segmented control; the record detail tabs become
 * Polaris underline tabs in the brand colour instead of a hard-coded #2563eb. The document
 * preview column beside them is never touched. */

html.fm #app-shell .quote-workspace-tabs {
    gap: 2px;
    padding: 4px;
    background: rgb(241 245 249 / 0.85);
    border-radius: var(--fm-r-control);
}
html.fm #app-shell .quote-workspace-tab {
    border: 0;
    background: transparent;
    color: var(--fm-text-muted);
    padding: 8px 14px;
    border-radius: 0.5rem;
    font-size: 13px !important;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
    box-shadow: none;
}
html.fm #app-shell .quote-workspace-tab:hover {
    background: rgb(255 255 255 / 0.6);
    color: var(--fm-text);
}
html.fm #app-shell .quote-workspace-tab.active {
    background: var(--fm-surface-solid);
    color: var(--fm-primary);
    box-shadow: 0 1px 3px rgb(15 23 42 / 0.08), 0 1px 2px rgb(15 23 42 / 0.04);
}

html.fm #app-shell .record-shell {
    border-color: var(--fm-border);
    box-shadow: var(--fm-shadow-card);
}
html.fm #app-shell .record-tab {
    font-size: 13px !important;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
}
html.fm #app-shell .record-tab.active {
    color: var(--fm-primary);
    border-bottom-color: var(--fm-primary);
}


/* ── Reduced motion ─────────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    /* The document lives inside #app-shell, so a bare `*` here would reach it. */
    html.fm #app-shell *:not(:is(#proposal-render,#contract-preview-body,#customer-contract-preview,.cust-preview) *),
    html.fm #app-confirm-modal * {
        transition: none !important;
        animation: none !important;
    }
}
