/* ==========================================================================
   SETU Shared Components
   Cards, buttons, pills, forms, messages, tables.
   All colours reference tokens.css custom properties.

   Type-scale discipline:
   - Normal page UI (forms, buttons, pipeline cards) stays at --s-font-size-base.
   - Data-dense list/table views use .data-table (sm/xs tokens, tight rows).
   ========================================================================== */

/* ---- Utility ---- */
.muted {
    color: var(--s-color-text-secondary);
}

/* ---- Cards ---- */
.card {
    background-color: var(--s-color-surface);
    border: 1px solid var(--s-color-border);
    border-radius: var(--s-radius-lg);
    box-shadow: var(--s-shadow-sm);
    padding: var(--s-space-4) var(--s-space-5);
    margin-bottom: var(--s-space-4);
    transition: background-color var(--s-transition-normal),
                border-color var(--s-transition-normal);
}

/* ---- Modal (Alpine, x-show + x-cloak) ----
   Generic shell in templates/common/components/modal.html. Backdrop dims
   the page and closes on click; the panel is centered and the backdrop
   scrolls if the panel is taller than the viewport. */
.modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: var(--s-space-5);
    overflow-y: auto;
    background: rgba(0, 0, 0, 0.45);
}
.modal-panel {
    background: var(--s-color-surface);
    border: 1px solid var(--s-color-border);
    border-radius: var(--s-radius-lg);
    box-shadow: var(--s-shadow-md);
    width: 100%;
    max-width: 34rem;
    margin: auto;
}
.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-space-3);
    padding: var(--s-space-4) var(--s-space-5);
    border-bottom: 1px solid var(--s-color-border);
}
.modal-header h2 {
    margin: 0;
    font-size: var(--s-font-size-lg);
}
.modal-body {
    padding: var(--s-space-4) var(--s-space-5);
}

/* ---- Buttons ---- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-space-1);
    padding: 0.4rem 0.85rem;
    border: 1px solid var(--s-color-accent);
    border-radius: var(--s-radius-md);
    background: var(--s-color-accent);
    color: #fff;
    font-family: var(--s-font-family);
    font-size: var(--s-font-size-md);
    font-weight: var(--s-font-weight-medium);
    line-height: var(--s-line-height-control);
    cursor: pointer;
    text-decoration: none;
    transition: all var(--s-transition-fast);
}
.btn:hover {
    background: var(--s-color-accent-hover);
    border-color: var(--s-color-accent-hover);
    color: #fff;
}
.btn.secondary {
    background: var(--s-color-surface);
    color: var(--s-color-accent-text);
    border-color: var(--s-color-border-strong);
}
.btn.secondary:hover {
    background: var(--s-color-surface-hover);
    border-color: var(--s-color-accent);
    color: var(--s-color-accent-text);
}
.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ---- Icon buttons: compact, icon-only actions (BOM line grid's remove/add/
   flag-PR controls) — a Material Icons ligature standing in for a .btn.
   secondary, with the action name conveyed via the title attribute (native
   tooltip) instead of visible text. */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 1px solid var(--s-color-border-strong);
    border-radius: var(--s-radius-md);
    background: var(--s-color-surface);
    color: var(--s-color-accent-text);
    cursor: pointer;
    transition: all var(--s-transition-fast);
}
.btn-icon:hover {
    background: var(--s-color-surface-hover);
    border-color: var(--s-color-accent);
}
.btn-icon:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.btn-icon .material-icons-outlined {
    font-size: 18px;
}

/* ---- HTMX loading indicator (hx-indicator) ---- */
/* Hidden by default; htmx toggles .htmx-request on the indicator element
   itself for the duration of the request. Used by anything that can take a
   noticeable amount of time (e.g. an AI call) so a slow response doesn't
   look like a dead button. */
.htmx-indicator {
    display: none;
}
.htmx-request.htmx-indicator,
.htmx-request .htmx-indicator {
    display: inline;
}

/* ---- Detail-page badge row (above the first card) ---- */
.detail-badges {
    display: flex;
    align-items: center;
    gap: var(--s-space-2);
    margin-bottom: var(--s-space-4);
    flex-wrap: wrap;
}

/* ---- Pills / status badges ---- */
.pill {
    display: inline-block;
    padding: 0.1rem 0.6rem;
    border-radius: 999px;
    font-size: var(--s-font-size-sm);
    font-weight: var(--s-font-weight-medium);
    background: var(--s-color-bg-alt);
    color: var(--s-color-text-secondary);
    border: 1px solid transparent;
}
.pill.ok {
    background: var(--s-color-success-bg);
    color: var(--s-color-success-text);
}
.pill.warn {
    background: var(--s-color-warning-bg);
    color: var(--s-color-warning-text);
}
a.pill:hover {
    border-color: var(--s-color-border-strong);
    color: var(--s-color-text);
}
a.pill.ok:hover {
    color: var(--s-color-success-text);
}

/* ---- Tables: normal scale (default) ---- */
table {
    width: 100%;
    border-collapse: collapse;
    background: transparent;
}
th, td {
    text-align: left;
    padding: var(--s-space-2) var(--s-space-3);
    border-bottom: 1px solid var(--s-color-border);
    font-size: var(--s-font-size-md);
}
th {
    color: var(--s-color-text-secondary);
    font-weight: var(--s-font-weight-semibold);
    font-size: var(--s-font-size-sm);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;
}
tbody tr:hover {
    background-color: var(--s-color-surface-hover);
}
tbody tr:last-child td {
    border-bottom: none;
}

/* ---- Tables: dense data view (.data-table) ----
   For genuinely data-heavy screens: item list, stock bins, enquiry list,
   customer list, BOM lines. Small text, tight rows, tabular numerals —
   AlignBooks/Tally information density without the cluttered chrome. */
.data-table {
    font-variant-numeric: tabular-nums;
}
.data-table th {
    font-size: var(--s-font-size-xs);
    padding: var(--s-space-1) var(--s-space-2);
    letter-spacing: 0.04em;
}
.data-table td {
    font-size: var(--s-font-size-sm);
    padding: 0.3rem var(--s-space-2);
    line-height: 1.45;
}
.data-table .pill {
    font-size: var(--s-font-size-xs);
    padding: 0.05rem 0.5rem;
}
.data-table .btn {
    font-size: var(--s-font-size-xs);
    padding: 0.1rem 0.4rem;
}
.data-table .btn-icon {
    width: 1.6rem;
    height: 1.6rem;
}
.data-table .btn-icon .material-icons-outlined {
    font-size: 16px;
}

/* Wrap wide tables so they scroll inside the card, not the page */
.table-scroll {
    overflow-x: auto;
}

/* ---- Forms ---- */
form.stacked label {
    display: block;
    margin-top: var(--s-space-3);
    margin-bottom: var(--s-space-1);
    font-size: var(--s-font-size-sm);
    font-weight: var(--s-font-weight-medium);
    color: var(--s-color-text-secondary);
}
form.stacked input,
form.stacked select,
form.stacked textarea {
    width: 100%;
    padding: 0.45rem 0.65rem;
    border: 1px solid var(--s-color-border);
    border-radius: var(--s-radius-md);
    font: inherit;
    font-size: var(--s-font-size-md);
    background-color: var(--s-color-input-bg);
    color: var(--s-color-input-text);
    transition: border-color var(--s-transition-fast),
                box-shadow var(--s-transition-fast);
}
form.stacked input::placeholder,
form.stacked textarea::placeholder {
    color: var(--s-color-input-placeholder);
}
form.stacked input:focus,
form.stacked select:focus,
form.stacked textarea:focus {
    outline: none;
    border-color: var(--s-color-accent);
    box-shadow: 0 0 0 3px var(--s-color-accent-light);
}
/* Radios/checkboxes are inline controls, not full-width fields — without
   this the generic `form.stacked input` width:100% stretches the control's
   box and shoves its label text onto the next line. */
form.stacked input[type="radio"],
form.stacked input[type="checkbox"] {
    width: auto;
    margin: 0 var(--s-space-1) 0 0;
    padding: 0;
    accent-color: var(--s-color-accent);
    vertical-align: middle;
}
/* Spreadsheet row inputs (the PR create page's inline entry row) keep
   their borderless-until-interaction grid look even when their form gains
   the .stacked class — form.stacked input would otherwise force a solid
   field box on them. Reproduces .bom-grid-input's states at higher
   specificity so hover/focus behave exactly the same. */
form.stacked input.bom-grid-input {
    padding: 0.35rem 0.5rem;
    border: 1px solid transparent;
    background: transparent;
    font-size: var(--s-font-size-sm);
}
form.stacked input.bom-grid-input:hover {
    border-color: var(--s-color-border);
    background: var(--s-color-surface);
}
form.stacked input.bom-grid-input:focus {
    outline: none;
    border-color: var(--s-color-accent);
    background: var(--s-color-surface);
    box-shadow: 0 0 0 3px var(--s-color-accent-light);
}

/* Bare inputs outside .stacked (e.g. valuation qty peek) */
input[type="number"]:not(form.stacked input) {
    padding: 0.4rem 0.65rem;
    border: 1px solid var(--s-color-border);
    border-radius: var(--s-radius-md);
    font: inherit;
    font-size: var(--s-font-size-md);
    background-color: var(--s-color-input-bg);
    color: var(--s-color-input-text);
}

/* Dark mode: invert the native calendar picker icon (WebKit/Blink) */
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator {
    filter: invert(1) brightness(2) contrast(1);
}

/* ---- Filter bars (list pages, org approval oversight) ----
   `.filters` is the plain-GET form used to filter a list (item list,
   organization pending requests). Its controls get the same field look as
   .stacked forms — padding, border, radius, focus ring — but arranged as a
   compact wrapping flex row with labels left of their field, so the bar
   reads as one control cluster instead of a row of bare browser widgets. */
.filters {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-space-2) var(--s-space-3);
}
.filters label {
    font-size: var(--s-font-size-sm);
    font-weight: var(--s-font-weight-medium);
    color: var(--s-color-text-secondary);
}
.filters input,
.filters select {
    padding: 0.45rem 0.65rem;
    border: 1px solid var(--s-color-border);
    border-radius: var(--s-radius-md);
    font: inherit;
    font-size: var(--s-font-size-md);
    background-color: var(--s-color-input-bg);
    color: var(--s-color-input-text);
    transition: border-color var(--s-transition-fast),
                box-shadow var(--s-transition-fast);
}
.filters input::placeholder {
    color: var(--s-color-input-placeholder);
}
.filters input:focus,
.filters select:focus {
    outline: none;
    border-color: var(--s-color-accent);
    box-shadow: 0 0 0 3px var(--s-color-accent-light);
}
.filters input[type="search"] {
    min-width: 14rem;
}

/* ---- List page header: title + meta on the left, actions on the right ----
   Used by data-dense list screens (item list, and any future list page that
   wants the same title/count/actions row instead of a bare <h1>). */
.list-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-space-4);
    flex-wrap: wrap;
    margin-bottom: var(--s-space-5);
}
.list-header h1 {
    margin: 0 0 0.2rem;
}
.list-header .list-header-actions {
    display: flex;
    align-items: center;
    gap: var(--s-space-2);
}

/* ---- Table footer: pagination row under a .card table ---- */
.table-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--s-space-3) var(--s-space-4);
    border-top: 1px solid var(--s-color-border);
    background: var(--s-color-bg-alt);
    font-size: var(--s-font-size-sm);
    color: var(--s-color-text-secondary);
}
.table-footer .table-footer-pages {
    display: flex;
    gap: var(--s-space-2);
}

/* ---- Detail page header: breadcrumb + title + meta ----
   Used above a pipeline/hub partial (enquiry detail, BOM page). */
.detail-header {
    margin-bottom: var(--s-space-5);
}
.detail-header .breadcrumb {
    display: block;
    margin: 0 0 0.3rem;
    font-size: var(--s-font-size-sm);
}
.detail-header h1 {
    margin: 0 0 0.2rem;
}
.detail-header .detail-meta {
    margin: 0;
}

/* ---- Process pipeline: step cards ----
   Each step of a hub/pipeline screen (Enquiry pipeline today) renders as its
   own .card. These modifiers give that card the complete/current/pending
   states the Process Pipeline redesign calls for, without changing which
   Django conditional renders which card. */
.step-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-space-3);
    flex-wrap: wrap;
    margin-bottom: var(--s-space-2);
}
.step-header-left {
    display: flex;
    align-items: center;
    gap: var(--s-space-2);
}
.step-header-left h2 {
    margin: 0;
}
.step-badge {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--s-radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: var(--s-font-size-xs);
    font-weight: var(--s-font-weight-bold);
}
.step-badge.complete {
    background: var(--s-color-success);
    color: #fff;
}
.step-badge.current {
    background: var(--s-color-accent);
    color: #fff;
}
.step-badge.pending {
    background: var(--s-color-surface);
    border: 1px solid var(--s-color-border-strong);
    color: var(--s-color-text-tertiary);
}
.step-body {
    padding-left: calc(1.5rem + var(--s-space-2));
}
.step-body > *:last-child {
    margin-bottom: 0;
}
.card.step-current {
    border-color: var(--s-color-accent);
    box-shadow: 0 0 0 3px var(--s-color-accent-light);
}
.card.step-pending {
    background: var(--s-color-bg-alt);
    opacity: 0.65;
}
.card.step-pending .step-header-left h2 {
    color: var(--s-color-text-secondary);
}

/* ---- BOM Line Grid: spreadsheet-style row entry ----
   Borderless until hovered/focused, so a dense grid of rows doesn't read as
   a wall of boxes — border and background appear only on interaction. */
.bom-grid-input {
    width: 100%;
    padding: 0.35rem 0.5rem;
    border: 1px solid transparent;
    border-radius: var(--s-radius-sm);
    font: inherit;
    font-size: var(--s-font-size-sm);
    background: transparent;
    color: var(--s-color-input-text);
}
.bom-grid-input:hover {
    border-color: var(--s-color-border);
    background: var(--s-color-surface);
}
.bom-grid-input:focus {
    outline: none;
    border-color: var(--s-color-accent);
    background: var(--s-color-surface);
    box-shadow: 0 0 0 3px var(--s-color-accent-light);
}
.bom-grid-row-new {
    background: var(--s-color-surface-hover);
}

/* ---- Two-column cost estimate grid (BOM page) ---- */
.cost-estimate-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-space-4);
}

/* ---- AI judgment panel (BOM substitute suggestions) ---- */
.ai-judgment-panel {
    margin-top: var(--s-space-2);
    border-top: 1px solid var(--s-color-border);
    padding-top: var(--s-space-2);
}
.ai-candidate-row {
    display: flex;
    align-items: center;
    gap: var(--s-space-2);
    margin-bottom: var(--s-space-1);
    font-size: var(--s-font-size-sm);
}

/* ---- Tab strip (dashboard, and any future tabbed page) ----
   Both panels render server-side in the same response; Alpine only toggles
   x-show on the panel wrapper. .active reflects Alpine's :class binding. */
.tab-strip {
    display: flex;
    gap: var(--s-space-5);
    border-bottom: 1px solid var(--s-color-border);
    margin-bottom: var(--s-space-5);
}
.tab-strip button {
    appearance: none;
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    padding: var(--s-space-3) var(--s-space-1);
    font: inherit;
    font-size: var(--s-font-size-base);
    font-weight: var(--s-font-weight-medium);
    color: var(--s-color-text-secondary);
    cursor: pointer;
    transition: color var(--s-transition-fast), border-color var(--s-transition-fast);
}
.tab-strip button:hover {
    color: var(--s-color-text);
}
.tab-strip button.active {
    color: var(--s-color-accent-text);
    border-bottom-color: var(--s-color-accent);
}

/* ---- Django messages ---- */
ul.messages {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--s-space-4);
}
ul.messages li {
    padding: var(--s-space-2) var(--s-space-3);
    border-radius: var(--s-radius-md);
    margin-bottom: var(--s-space-2);
    background: var(--s-color-info-bg);
    color: var(--s-color-info-text);
    border: 1px solid var(--s-color-border);
    font-size: var(--s-font-size-md);
}
ul.messages li.success {
    background: var(--s-color-success-bg);
    color: var(--s-color-success-text);
}
ul.messages li.warning {
    background: var(--s-color-warning-bg);
    color: var(--s-color-warning-text);
}
ul.messages li.error {
    background: var(--s-color-danger-bg);
    color: var(--s-color-danger-text);
}

/* ---- Upload Spinner ---- */
.upload-wrapper {
    position: relative;
}

.upload-spinner {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--s-space-3);
    padding: var(--s-space-4);
    text-align: center;
}

.spinner {
    width: 32px;
    height: 32px;
    border: 3px solid var(--s-color-border);
    border-top-color: var(--s-color-accent);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

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