/* wwwroot/css/site.css */
html {
    font-size: 14px;
    height: 100%;
}

@media (min-width: 768px) {
    html {
        font-size: 16px;
    }
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f8f9fa;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

main {
    flex: 1;
    padding: 20px;
}

/* Navigation */
.navbar-brand {
    font-weight: 600;
    font-size: 1.3rem;
}

.navbar-nav .nav-link {
    font-weight: 500;
    padding: 0.75rem 1rem;
}

    .navbar-nav .nav-link:hover {
        background-color: rgba(255, 255, 255, 0.1);
        border-radius: 0.375rem;
    }

/* Cards */
.card {
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
    border: 1px solid rgba(0, 0, 0, 0.125);
    border-radius: 0.5rem;
    margin-bottom: 1.5rem;
}

.card-header {
    background-color: #f8f9fa;
    border-bottom: 1px solid rgba(0, 0, 0, 0.125);
    font-weight: 600;
    padding: 1rem 1.25rem;
}

.card-body {
    padding: 1.25rem;
}

/* Buttons */
.btn {
    font-weight: 500;
    border-radius: 0.375rem;
    padding: 0.5rem 1rem;
    transition: all 0.2s ease-in-out;
}

    .btn:hover {
        transform: translateY(-1px);
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    }

.btn-primary {
    background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
    border: none;
}

    .btn-primary:hover {
        background: linear-gradient(135deg, #0056b3 0%, #004085 100%);
    }

.btn-success {
    background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%);
    border: none;
}

.btn-warning {
    background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%);
    border: none;
    color: #212529;
}

.btn-danger {
    background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
    border: none;
}

.btn-info {
    background: linear-gradient(135deg, #17a2b8 0%, #138496 100%);
    border: none;
}

/* Forms */
.form-control {
    border-radius: 0.375rem;
    border: 1px solid #ced4da;
    padding: 0.5rem 0.75rem;
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

    .form-control:focus {
        border-color: #86b7fe;
        box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
    }

.form-select {
    border-radius: 0.375rem;
    border: 1px solid #ced4da;
}

.form-label {
    font-weight: 500;
    margin-bottom: 0.5rem;
    color: #495057;
}

/* Tables */
.table {
    margin-bottom: 0;
}

    .table th {
        border-top: none;
        font-weight: 600;
        background-color: #f8f9fa;
        border-bottom: 2px solid #dee2e6;
        padding: 0.75rem;
    }

    .table td {
        padding: 0.75rem;
        vertical-align: middle;
    }

.table-hover tbody tr:hover {
    background-color: rgba(0, 0, 0, 0.025);
}

.table-responsive {
    border-radius: 0.5rem;
    overflow: hidden;
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}

/* Badges */
.badge {
    font-size: 0.75em;
    font-weight: 500;
    padding: 0.35em 0.65em;
}

/* Alerts */
.alert {
    border-radius: 0.5rem;
    border: none;
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}

.alert-success {
    background-color: #d1edff;
    color: #0c5460;
    border-left: 4px solid #28a745;
}

.alert-danger {
    background-color: #f8d7da;
    color: #721c24;
    border-left: 4px solid #dc3545;
}

.alert-warning {
    background-color: #fff3cd;
    color: #856404;
    border-left: 4px solid #ffc107;
}

.alert-info {
    background-color: #cce7ff;
    color: #0c5460;
    border-left: 4px solid #17a2b8;
}

/* Dashboard specific styles */
.dashboard-card {
    transition: transform 0.2s ease-in-out;
}

    .dashboard-card:hover {
        transform: translateY(-2px);
    }

.dashboard-stat {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1;
}

/* Loading animations */
.spinner-border {
    width: 1rem;
    height: 1rem;
}

.loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 9999;
}

/* Pagination */
.pagination .page-link {
    border-radius: 0.375rem;
    margin: 0 0.125rem;
    border: 1px solid #dee2e6;
    color: #495057;
}

.pagination .page-item.active .page-link {
    background-color: #007bff;
    border-color: #007bff;
}

/* Login page styles */
.login-body {
    margin: 0;
    padding: 0;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    min-height: 100vh;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

/* Utility classes */
.text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.shadow-sm {
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;
}

.shadow {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
}

.shadow-lg {
    box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;
}

/* Responsive adjustments */
@media (max-width: 768px) {
    main {
        padding: 10px;
    }

    .card-body {
        padding: 1rem;
    }

    .table-responsive {
        font-size: 0.875rem;
    }

    .btn-group-sm .btn {
        padding: 0.125rem 0.25rem;
        font-size: 0.75rem;
    }
}

/* Print styles */
@media print {
    .navbar,
    .footer,
    .btn,
    .pagination,
    .card-header {
        display: none !important;
    }

    .card {
        border: 1px solid #000;
        box-shadow: none;
    }

    body {
        background-color: white;
    }
}

/* Custom scrollbar */
::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 4px;
}

::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 4px;
}

    ::-webkit-scrollbar-thumb:hover {
        background: #a8a8a8;
    }

/* Animation classes */
.fade-in {
    animation: fadeIn 0.5s ease-in;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.slide-in-right {
    animation: slideInRight 0.3s ease-out;
}

@keyframes slideInRight {
    from {
        transform: translateX(100px);
        opacity: 0;
    }

    to {
        transform: translateX(0);
        opacity: 1;
    }
}

/* Focus styles for accessibility */
.btn:focus,
.form-control:focus,
.form-select:focus {
    outline: none;
    box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}

/* Error page styles */
.error-container {
    max-width: 600px;
    margin: 0 auto;
}

// wwwroot/js/site.js
// Global site JavaScript

// Initialize tooltips
document.addEventListener('DOMContentLoaded', function() {
    // Initialize Bootstrap tooltips
    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
    var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
        return new bootstrap.Tooltip(tooltipTriggerEl);
    });

    // Initialize Bootstrap popovers
    var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
    var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
        return new bootstrap.Popover(popoverTriggerEl);
    });

    // Auto-hide alerts after 5 seconds
    setTimeout(function() {
        var alerts = document.querySelectorAll('.alert-dismissible');
        alerts.forEach(function(alert) {
            var bsAlert = new bootstrap.Alert(alert);
            bsAlert.close();
        });
    }, 5000);
});

// Global functions
window.CostingApp = {
    // Show loading overlay showLoading: function()

{
    var overlay = document.createElement('div');
    overlay .className = 'loading-overlay';
    overlay .id = 'loadingOverlay';
    overlay .innerHTML = '<div class="spinner-border text-light" role="status"><span class="visually-hidden">Loading...</span></div>';
    document .body.appendChild(overlay);
}

,
// Hide loading overlay
hideLoading: function() {
    var overlay = document.getElementById('loadingOverlay');
    if (overlay)

{
    overlay .remove();
}

}

,
// Show toast notification
showToast: function(message, type = 'info', duration = 3000) {
    var toastContainer = document.getElementById('toast-container');
    if (!toastContainer)

{
    toastContainer = document.createElement('div');
    toastContainer .id = 'toast-container';
    toastContainer .className = 'toast-container position-fixed top-0 end-0 p-3';
    toastContainer .style.zIndex = '9999';
    document .body.appendChild(toastContainer);
}

var toastId = 'toast-' + Date.now();
var bgClass = type === 'success' ? 'bg-success' :
type === 'error' ? 'bg-danger' :
type === 'warning' ? 'bg-warning' : 'bg-info';

var toastHtml = `
<div id="${toastId}" class="toast align-items-center text-white ${bgClass} border-0" role="alert" aria-live="assertive" aria-atomic="true" >
<div class="d-flex" >
<div class="toast-body" >
$ {
    message
}

</div >
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close" > </button >
</div >
</div >
`;

toastContainer.insertAdjacentHTML('beforeend', toastHtml);
var toastElement = document.getElementById(toastId);
var toast = new bootstrap.Toast(toastElement, { delay: duration });
toast.show();

// Remove toast element after it's hidden
toastElement.addEventListener('hidden.bs.toast', function() {
            toastElement.remove();
        });
}

,
// Confirm dialog
confirm: function(message, callback) {
    if (confirm(message))

{
    callback();
}

}

,
// Format currency
formatCurrency: function(amount, currency = '$') {
    return currency + parseFloat(amount).toLocaleString('en-US', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        });
}

,
// Format percentage
formatPercentage: function(value, decimals = 2) {
    return parseFloat(value).toFixed(decimals) + '%';
}

,
// Validate email
isValidEmail: function(email) {
    var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
}

,
// Debounce function
debounce: function(func, wait) {
    let timeout;
    return function executedFunction(...args)

{
    const later = () =>

{
    clearTimeout(timeout);
    func(...args);
}

;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
}
;
}

,
// Get CSRF token
getAntiForgeryToken: function() {
    var token = document.querySelector('input[name="__RequestVerificationToken"]');
    return token ? token.value : '';
}

,
// AJAX helper
ajax: function(options) {
    var defaults =

{
    method: 'GET', headers:

{
    'Content-Type': 'application/json', 'RequestVerificationToken': this.getAntiForgeryToken()
}

}

;

var config = Object.assign({}, defaults, options);

if (config.showLoading !== false) {
    this .showLoading();
}

return fetch(config.url, {
            method: config.method,
            headers: config.headers,
            body: config.data ? JSON.stringify(config.data) : undefined
        })
.then(response => {
            if (config.showLoading !== false) {
                this.hideLoading();
            }
            
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.json();
        })
.catch(error => {
            if (config.showLoading !== false) {
                this.hideLoading();
            }
            
            if (config.onError) {
                config.onError(error);
            } else {
                this.showToast('An error occurred: ' + error.message, 'error');
            }
            throw error;
        });
}
}

;

// Global event handlers
document.addEventListener('click', function(e) {
    // Handle delete confirmations
    if (e.target.closest('[data-confirm]')) {
        e.preventDefault();
        var element = e.target.closest('[data-confirm]');
        var message = element.dataset.confirm || 'Are you sure?';
        
        if (confirm(message)) {
            if (element.tagName === 'A') {
                window.location.href = element.href;
            } else if (element.tagName === 'FORM') {
                element.submit();
            }
        }
    }
});

// Global form validation
document.addEventListener('submit', function(e) {
    var form = e.target;
    if (form.classList.contains('needs-validation')) {
        if (!form.checkValidity()) {
            e.preventDefault();
            e.stopPropagation();
        }
        form.classList.add('was-validated');
    }
});

// Handle AJAX form submissions
document.addEventListener('submit', function(e) {
    if (e.target.classList.contains('ajax-form')) {
        e.preventDefault();
        
        var form = e.target;
        var formData = new FormData(form);
        var data = {};
        
        formData.forEach(function(value, key) {
            data[key] = value;
        });

        CostingApp.ajax({
            url: form.action,
            method: form.method || 'POST',
            data: data
        })
        .then(function(response) {
            if (response.success) {
                CostingApp.showToast(response.message || 'Operation completed successfully', 'success');
                if (response.redirectUrl) {
                    window.location.href = response.redirectUrl;
                }
            } else {
                CostingApp.showToast(response.message || 'Operation failed', 'error');
            }
        });
    }
});

// Handle session timeout
var sessionTimeout = 30 * 60 * 1000; // 30 minutes
var warningTime = 5 * 60 * 1000; // 5 minutes before timeout

setTimeout(function() {
    CostingApp.showToast('Your session will expire in 5 minutes. Please save your work.', 'warning', 10000);
}, sessionTimeout - warningTime);

setTimeout(function() {
    if (confirm('Your session has expired. Click OK to login again.')) {
        window.location.href = '/login';
    }
}, sessionTimeout);

// wwwroot/js/quote-calculator.js
// Quote calculation specific JavaScript

window.QuoteCalculator = {
    // Initialize calculator init: function()

{
    this .bindEvents();
    this .calculateAll();
}

,
// Bind events
bindEvents: function() {
    var self = this;
    // Bind print cost changes document.addEventListener('input', function(e) {
            if (e.target.classList.contains('murdoch-cost') || 
                e.target.classList.contains('author-offset-cost')) {
                self.calculatePrintCostTotals();
            }
        });
    // Bind sales calculation changes document.addEventListener('input', function(e) {
            if (e.target.classList.contains('sales-quantity') ||
                e.target.classList.contains('returns') ||
                e.target.classList.contains('adv-gratis') ||
                e.target.classList.contains('unit-price') ||
                e.target.classList.contains('discount-percent') ||
                e.target.classList.contains('royalty-percent') ||
                e.target.classList.contains('other-income')) {
                self.calculateAll();
            }
        });
    // Bind royalty advance changes document.addEventListener('input', function(e) {
            if (e.target.id === 'royaltyAdvance' || e.target.id === 'targetGP') {
                self.calculateAll();
            }
        });
}

,
// Calculate print cost totals
calculatePrintCostTotals: function() {
    var totalMurdoch = 0;
    var totalAuthorOffset = 0;
    document .querySelectorAll('.murdoch-cost').forEach(function(input) {
            var murdochCost = parseFloat(input.value) || 0;
            var row = input.closest('tr');
            var authorOffsetInput = row.querySelector('.author-offset-cost');
            var authorOffsetCost = parseFloat(authorOffsetInput.value) || 0;
            var total = murdochCost + authorOffsetCost;
            
            var totalSpan = row.querySelector('.print-cost-total');
            if (totalSpan) {
                totalSpan.textContent = total.toFixed(2);
            }
            
            totalMurdoch += murdochCost;
            totalAuthorOffset += authorOffsetCost;
        });
    this .updateElement('totalMurdochCosts', totalMurdoch.toFixed(2));
    this .updateElement('totalAuthorOffsetCosts', totalAuthorOffset.toFixed(2));
    this .updateElement('totalPrintCosts', (totalMurdoch + totalAuthorOffset).toFixed(2));
}

,
// Calculate all values
calculateAll: function() {
    this .calculateBasicTotals();
    this .calculateBusinessUnitValues();
    this .calculateSummary();
    this .validateGPTargets();
}

,
// Calculate basic totals
calculateBasicTotals: function() {
    var totalSalesQty = this.sumInputs('.sales-quantity');
    var totalReturns = this.sumInputs('.returns');
    var totalAdvGratis = this.sumInputs('.adv-gratis');
    var totalNetQuantity = totalSalesQty - totalReturns - totalAdvGratis;
    var totalPrintCosts = parseFloat(this.getElementText('totalPrintCosts')) || 0;
    var unitCost = totalSalesQty > 0 ? (totalPrintCosts / totalSalesQty) : 0;
    this .updateElement('totalSalesQty', totalSalesQty);
    this .updateElement('totalReturns', totalReturns);
    this .updateElement('totalAdvGratis', totalAdvGratis);
    this .updateElement('totalNetQuantity', totalNetQuantity);
    this .updateElement('totalSalesQuantity', totalSalesQty);
    this .updateElement('unitCost', unitCost.toFixed(2));
    this .updateElement('unitCostDisplay', unitCost.toFixed(2));
}

,
// Calculate business unit values
calculateBusinessUnitValues: function() {
    var businessUnits = ['ANZ', 'Author Sales', 'UK'];
    var totalPrintCosts = parseFloat(this.getElementText('totalPrintCosts')) || 0;
    var totalSalesQty = this.sumInputs('.sales-quantity');
    var unitCost = totalSalesQty > 0 ? (totalPrintCosts / totalSalesQty) : 0;
    var totalNetReceipts = 0;
    var totalRoyalty = 0;
    var totalOtherIncome = 0;
    var totalCostOfSales = 0;
    businessUnits .forEach(function(unit, index) {
            var salesQty = this.getInputValue(`Quote.SalesCalculations[${index}].SalesQuantity`);
            var returns = this.getInputValue(`Quote.SalesCalculations[${index}].Returns`);
            var advGratis = this.getInputValue(`Quote.SalesCalculations[${index}].AdvGratis`);
            var unitPrice = this.getInputValue(`Quote.SalesCalculations[${index}].UnitPrice`);
            var discountPercent = this.getInputValue(`Quote.SalesCalculations[${index}].DiscountPercent`);
            var royaltyPercent = this.getInputValue(`Quote.SalesCalculations[${index}].RoyaltyPercent`);
            var otherIncome = this.getInputValue(`Quote.SalesCalculations[${index}].OtherIncome`);

            var netQty = salesQty - returns - advGratis;
            var rrpIncome = netQty * unitPrice;
            var netReceipts = rrpIncome * (1 - discountPercent / 100);
            var unitNetRevenue = netQty > 0 ? (netReceipts / netQty) : 0;
            var totalIncomeNoRoyalty = netReceipts + otherIncome;
            var costOfSales = totalSalesQty > 0 ? (totalPrintCosts * (salesQty / totalSalesQty)) : 0;
            var royaltyNetReceiptsBasis = netReceipts * (royaltyPercent / 100);

            // Update display elements
            this.updateElementByUnit('net-quantity', unit, netQty);
            this.updateElementByUnit('rrp-income', unit, rrpIncome.toFixed(2));
            this.updateElementByUnit('net-receipts', unit, netReceipts.toFixed(2));
            this.updateElementByUnit('unit-net-revenue', unit, unitNetRevenue.toFixed(2));
            this.updateElementByUnit('total-income-no-royalty', unit, totalIncomeNoRoyalty.toFixed(2));
            this.updateElementByUnit('unit-cost-display', unit, unitCost.toFixed(2));
            this.updateElementByUnit('cost-of-sales', unit, costOfSales.toFixed(2));
            this.updateElementByUnit('royalty-net-receipts', unit, royaltyNetReceiptsBasis.toFixed(2));

            totalNetReceipts += netReceipts;
            totalRoyalty += royaltyNetReceiptsBasis;
            totalOtherIncome += otherIncome;
            totalCostOfSales += costOfSales;
        }, this);
    // Calculate royalty advance offset var royaltyAdvance = this.getInputValue('royaltyAdvance');
    var authorOffsets = parseFloat(this.getElementText('totalAuthorOffsetCosts')) || 0;
    var totalAdvanceAndOffset = royaltyAdvance + authorOffsets;
    var totalRoyaltyAdvanceOffset = Math.max(0, totalAdvanceAndOffset - totalRoyalty);
    var royaltyAdvanceOffsetProvisioning = totalRoyaltyAdvanceOffset / 2;
    // Update provisioning for each business unit and calculate final values businessUnits.forEach(function(unit, index) {
            var costOfSales = parseFloat(this.getElementTextByUnit('cost-of-sales', unit)) || 0;
            var royaltyNetReceiptsBasis = parseFloat(this.getElementTextByUnit('royalty-net-receipts', unit)) || 0;
            var netReceipts = parseFloat(this.getElementTextByUnit('net-receipts', unit)) || 0;
            var otherIncome = this.getInputValue(`Quote.SalesCalculations[${index}].OtherIncome`);

            var totalCost = costOfSales + royaltyNetReceiptsBasis + royaltyAdvanceOffsetProvisioning;
            var grossProfit = netReceipts - totalCost + otherIncome;
            var gpPercent = netReceipts > 0 ? ((grossProfit / netReceipts) * 100) : 0;

            this.updateElementByUnit('royalty-advance-provisioning', unit, royaltyAdvanceOffsetProvisioning.toFixed(2));
            this.updateElementByUnit('total-cost', unit, totalCost.toFixed(2));
            this.updateElementByUnit('gross-profit', unit, grossProfit.toFixed(2));
            this.updateElementByUnit('gp-percent', unit, gpPercent.toFixed(2));
        }, this);
    // Update totals this.updateElement('totalNetReceipts', totalNetReceipts.toFixed(2));
    this .updateElement('totalRoyaltyNetReceipts', totalRoyalty.toFixed(2));
    this .updateElement('totalOtherIncome', totalOtherIncome.toFixed(
