/*
 * /assets/core/components.css — unified component patterns.
 *
 * The canonical home for shared trunk components. The original blocks
 * (buttons, fields, tags, cards, tables, dialogs, terminal, segmented,
 * metric) still live in assets/style.css; new patterns and uplifts go
 * here.
 *
 * If you add a new component pattern, add it here and document a variant
 * in /assets/gallery/index.html so the gallery cannot drift.
 */

/* ---- App tab shell ----------------------------------------------------- */

/*
 * Every tab uses .app-tab as its outer wrapper. When a tab has sub-sections
 * (Print modes, Admin sub-tabs, Quote-list filters, Quote-builder sections)
 * add .app-tab--rail and include an <nav class="app-tab__rail"> child.
 * Tabs without a rail (Home, Expenses) get a single full-width column by
 * default — never put a rail-less tab in the two-column grid or its main
 * body collapses into the 220px rail track.
 *
 * Inside, every tab opens with .app-tab__head (eyebrow + title + actions),
 * then .app-tab__main holds the body (cards / forms / tables).
 *
 * The shell replaces the previous mix of bare <section class="card"> tabs
 * (search/checkin/checkout/count/print) and the bespoke .admin-tab grid.
 */

.app-tab {
    display: grid;
    /* minmax(0, …) everywhere: a plain auto/1fr track takes the min-content
       width of wide children (tables), stretching the page sideways. */
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s5);
    min-width: 0;
    /* Subtle entrance — applied each time switchTab clears + re-mounts. */
    animation: app-tab-in var(--dur) var(--ease-out);
}
/* Two-column variant for tabs with a side rail. The :has() fallback keeps
   older templates working even if they lack the modifier class. */
.app-tab--rail,
.app-tab:has(> .app-tab__rail) { grid-template-columns: 220px minmax(0, 1fr); }
.app-tab--single { grid-template-columns: minmax(0, 1fr); }

@keyframes app-tab-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .app-tab { animation: none; }
}

@media (max-width: 720px) {
    .app-tab,
    .app-tab--rail,
    .app-tab:has(> .app-tab__rail) { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
}

.app-tab__main {
    min-width: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s4);
}

/* ---- Tab head (eyebrow + title + actions) ------------------------------ */

.app-tab__head {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    gap: var(--s4);
    padding-bottom: var(--s3);
    border-bottom: 1px solid var(--line);
    /* The display heading wants room to breathe vs surrounding cards. */
    margin-bottom: var(--s1);
}
.app-tab__lead { display: grid; gap: 2px; min-width: 0; }
.app-tab__eyebrow {
    font-family: var(--f-mono);
    font-size: var(--t-xs);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--fg-3);
    /* Red dot prefix so the eyebrow has a tiny visual accent without a tag. */
    display: inline-flex;
    align-items: center;
    gap: var(--s2);
}
.app-tab__eyebrow::before {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    background: var(--red);
    border-radius: 50%;
}
.app-tab__title {
    margin: 0;
    font-family: var(--f-display);
    font-size: var(--t-2xl);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--fg);
    line-height: 1.1;
}
.app-tab__caption {
    margin: 4px 0 0;
    color: var(--fg-3);
    font-size: var(--t-md);
    max-width: 60ch;
}
.app-tab__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s2);
    justify-self: end;
    align-self: end;
}
@media (max-width: 720px) {
    .app-tab__head { grid-template-columns: 1fr; }
    .app-tab__actions { justify-self: stretch; }
}

/* ---- Rail (sub-section nav) -------------------------------------------- */

/*
 * The rail is a refined version of the existing .chrome-tabs--rail. New
 * elements (.app-tab__rail, .app-tab__rail-btn) so the older admin rail in
 * style.css can coexist during migration; once admin is on the new shell
 * the older rules can be retired.
 */
.app-tab__rail {
    display: flex;
    flex-direction: column;
    gap: 2px;
    border-right: 1px solid var(--line);
    padding-right: var(--s3);
    min-width: 0;
    align-self: start;
    position: sticky;
    top: calc(56px + var(--s5));   /* under the chrome top bar */
}
.app-tab__rail-btn {
    display: grid;
    grid-template-columns: 28px 1fr;
    gap: var(--s3);
    align-items: baseline;
    padding: 12px 14px;
    border: 0;
    border-right: 2px solid transparent;
    margin-right: -1px;            /* overlay rail edge so active red replaces grey */
    background: transparent;
    color: var(--fg-3);
    text-align: left;
    cursor: pointer;
    text-transform: none;
    transition: background var(--dur-fast) var(--ease-out),
                color      var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out);
}
.app-tab__rail-num {
    font-family: var(--f-mono);
    font-size: var(--t-xs);
    letter-spacing: 0.06em;
    color: var(--fg-4);
    font-variant-numeric: tabular-nums;
    text-align: right;
}
.app-tab__rail-label {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-family: var(--f-body);
    font-size: var(--t-md);
    font-weight: 500;
    letter-spacing: 0;
    line-height: 1.2;
}
.app-tab__rail-meta {
    font-family: var(--f-mono);
    font-size: var(--t-xs);
    font-weight: 400;
    color: var(--fg-4);
    letter-spacing: 0.02em;
    text-transform: none;
}
.app-tab__rail-btn:hover {
    color: var(--fg);
    background: var(--bg-1);
}
.app-tab__rail-btn:hover .app-tab__rail-num { color: var(--red); }
.app-tab__rail-btn.active {
    color: var(--fg);
    border-right-color: var(--red);
    background: linear-gradient(
        to right,
        transparent 0%,
        var(--red-wash) 100%
    );
}
.app-tab__rail-btn.active .app-tab__rail-num {
    color: var(--red);
    font-weight: 600;
}

@media (max-width: 720px) {
    .app-tab__rail {
        flex-direction: row;
        border-right: 0;
        border-bottom: 1px solid var(--line);
        padding-right: 0;
        padding-bottom: var(--s2);
        margin-bottom: var(--s2);
        overflow-x: auto;
        position: static;
    }
    .app-tab__rail-btn {
        border-right: 0;
        border-bottom: 2px solid transparent;
        margin-right: 0;
        padding: 10px 12px;
        white-space: nowrap;
    }
    .app-tab__rail-btn.active {
        border-right: 0;
        border-bottom-color: var(--red);
        background: var(--red-wash);
    }
}

/* ---- Search-style input ------------------------------------------------ */

/*
 * Polished input variant for search / scan / filter boxes anywhere in the
 * app. Has a magnifier icon, larger height (40px), red focus ring matching
 * the rest of the design vocabulary. Used by:
 *   - the top-bar scan input
 *   - omni-search input on the Search tab
 *   - quote list search
 * Replaces the prior inline-styled inputs scattered through tpl.html files.
 *
 * The icon is an inline SVG data URI rendered in --fg-3. If you want to
 * change the colour later, swap the %238B8680 substring (URL-encoded #888).
 */
.input-search {
    height: 40px;
    padding: 0 14px 0 40px;
    font-family: var(--f-mono);
    font-size: var(--t-md);
    letter-spacing: 0.02em;
    color: var(--fg);
    background-color: var(--bg-3);
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%238B8680' stroke-width='1.5' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='5'/%3E%3Cpath d='m11 11 3 3'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 14px center;
    background-size: 16px 16px;
    border: 1px solid var(--line-hi);
    border-radius: var(--r);
    outline: none;
    transition: border-color var(--dur-fast) var(--ease-out),
                box-shadow   var(--dur-fast) var(--ease-out);
}
.input-search::placeholder { color: var(--fg-4); }
.input-search:focus {
    border-color: var(--red);
    box-shadow: 0 0 0 2px var(--red-wash);
}
/* Wider variant for the header search boxes (quote list, omni-search,
   workbench scan). Replaces the old inline min-width styles, which could
   not shrink and overflowed phone viewports. */
.input-search--wide { min-width: 320px; }
@media (max-width: 720px) {
    .input-search--wide { min-width: 0; width: 100%; }
    /* Header actions stack full-width so buttons make comfortable
       touch targets and search inputs get the whole row. */
    .app-tab__actions { flex-direction: column; align-items: stretch; }
    .app-tab__actions .btn { justify-content: center; }
    /* Filter strips: let each field flex to a sensible column width
       instead of jamming at content size. */
    .filter-strip .field { flex: 1 1 160px; min-width: 0; }
}

/* ---- Filter strip ------------------------------------------------------ */

/*
 * Refined sibling of the existing .filter-bar — same flex flow but with a
 * subtle inset background and rounded edges so it reads as a deliberate
 * console strip rather than a stack of bare inputs.
 */
.filter-strip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s3);
    align-items: end;
    padding: var(--s3) var(--s4);
    background: var(--bg-1);
    border: 1px solid var(--line);
    border-radius: var(--r);
}
.filter-strip .field { margin-bottom: 0; }
.filter-strip__spacer { flex: 1; }

/* ---- Table hover ------------------------------------------------------- */

/*
 * Augments the existing .table styles with a delicate red accent on hover —
 * subtler than the prior bg-2 fill and consistent with the rail/eyebrow.
 * Only applies to clickable rows so non-interactive tables stay calm.
 */
.table--rows-clickable tbody tr {
    transition: background var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
    box-shadow: inset 2px 0 0 transparent;
}
/* Real anchor inside a clickable row — gives the browser its native
   ctrl/middle-click and right-click → "Open in new tab" behaviours while
   looking identical to the plain cell content it wraps. */
.table--rows-clickable .row-link {
    color: inherit;
    text-decoration: none;
}
.table--rows-clickable tbody tr:hover td {
    background: var(--red-wash);
    color: var(--fg);
}
.table--rows-clickable tbody tr:hover {
    box-shadow: inset 2px 0 0 var(--red);
}

/*
 * Horizontal-overflow guard for data tables. Wide tables (audit log, PO
 * lines, item lists) scroll sideways inside this wrapper instead of blowing
 * the page width out on small screens. renderTable() in components.js
 * returns its <table> pre-wrapped; string-template call sites wrap manually.
 */
.table-flow {
    min-width: 0;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Scrollable table inside a card without breaking the rounded edge. */
.table-scroll {
    max-height: 70vh;
    overflow: auto;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--bg);
}
.table-scroll .table thead th {
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 1;
    border-bottom: 1px solid var(--line-hi);
}

/* ---- Omni-search result rows ------------------------------------------ */

/*
 * Result rows used by /assets/tabs/search/. Each row is a click target
 * that dispatches based on the data-type attribute. Layout: lead (label
 * + sublabel) on the left, trailing meta (tags / IDs) on the right.
 */
.omni-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--s3);
    align-items: center;
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
    box-shadow: inset 2px 0 0 transparent;
}
.omni-row:last-child { border-bottom: 0; }
.omni-row:hover {
    background: var(--red-wash);
    box-shadow: inset 2px 0 0 var(--red);
}
.omni-row__lead { min-width: 0; }
.omni-row__label {
    color: var(--fg);
    font-weight: 500;
}
.omni-row__sub {
    margin-top: 2px;
    font-size: var(--t-xs);
    color: var(--fg-3);
    font-family: var(--f-mono);
}
.omni-row__trail {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* ---- Inline view-toggle (active state for line buttons) ---------------- */

/*
 * For small inline toggles like the contacts panel's "List / Org chart"
 * pair. Uses the same red wash as the rail's active state so the whole UI
 * speaks one visual language.
 */
.btn.btn--line.active {
    color: var(--fg);
    background: var(--red-wash);
    border-color: var(--red);
}

/* ---- Anchor scroll (rail-jumps inside .app-tab__main) ------------------ */

/*
 * When a rail button scrolls to a card inside the same tab, we need
 * scroll-margin so the destination doesn't tuck under the sticky top bar
 * (56px) plus the tab nav. 80px gives a little breathing room above the
 * card eyebrow.
 */
.app-tab .card[id] { scroll-margin-top: 80px; }

/* ---- Card refinements -------------------------------------------------- */

/*
 * Section card — lighter than the default .card, used inside .app-tab__main
 * to separate sub-sections without the heavier framed look. Headed by an
 * eyebrow and (optionally) a small title; no card frame.
 */
.section {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s3);
    padding: var(--s4) 0;
    border-top: 1px solid var(--line);
}
.section:first-child { border-top: 0; padding-top: var(--s2); }
.section__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
    flex-wrap: wrap;
}
.section__title {
    margin: 0;
    font-family: var(--f-display);
    font-size: var(--t-lg);
    font-weight: 500;
    color: var(--fg);
}

/* ---- Empty state -------------------------------------------------------- */

/*
 * Replaces the ad-hoc <div class="terminal terminal--empty"> /
 * <li class="terminal--empty"> / bare-text patterns scattered across tabs.
 * Use renderEmpty(message) from /assets/core/components.js.
 */
.empty-state {
    display: block;
    padding: var(--s5) var(--s4);
    font-family: var(--f-mono);
    font-size: var(--t-sm);
    text-align: center;
    color: var(--fg-3);
    font-style: italic;
    background: var(--bg);
    border: 1px dashed var(--line);
    border-radius: var(--r);
}
.empty-state--compact {
    padding: var(--s3);
    font-size: var(--t-xs);
}

/* ---- Error state -------------------------------------------------------- */

/*
 * Replaces ad-hoc tag--red error rows, raw text errors, and modal
 * .textContent injections. Use renderError(message, { retry }) from
 * /assets/core/components.js.
 */
.error-state {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    font-family: var(--f-mono);
    font-size: var(--t-sm);
    color: var(--fg);
    background: var(--red-wash);
    border-left: 2px solid var(--red);
    border-radius: var(--r);
}
.error-state__msg {
    flex: 1;
    min-width: 0;
}

/* ---- Empty state -------------------------------------------------------- */

/*
 * Replaces the ad-hoc <div class="terminal terminal--empty"> /
 * <li class="terminal--empty"> / bare-text patterns scattered across tabs.
 * Use renderEmpty(message) from /assets/core/components.js.
 */
.empty-state {
    display: block;
    padding: var(--s5) var(--s4);
    font-family: var(--f-mono);
    font-size: var(--t-sm);
    text-align: center;
    color: var(--fg-3);
    font-style: italic;
    background: var(--bg);
    border: 1px dashed var(--line);
    border-radius: var(--r);
}
.empty-state--compact {
    padding: var(--s3);
    font-size: var(--t-xs);
}

/* ---- Error state -------------------------------------------------------- */

/*
 * Replaces ad-hoc tag--red error rows, raw text errors, and modal
 * .textContent injections. Use renderError(message, { retry }) from
 * /assets/core/components.js.
 */
.error-state {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    font-family: var(--f-mono);
    font-size: var(--t-sm);
    color: var(--fg);
    background: var(--red-wash);
    border-left: 2px solid var(--red);
    border-radius: var(--r);
}
.error-state__msg {
    flex: 1;
    min-width: 0;
}
