/* ── Fonts ── */
.font-mono, .mono { font-family: 'Geist Mono', ui-monospace, monospace; }
.font-sans { font-family: 'Geist', -apple-system, system-ui, sans-serif; }
body {
    font-family: 'Geist', -apple-system, system-ui, sans-serif;
    /* Base ink. Without this, every element with no explicit text class
       inherits the UA default — black — which is invisible on the dark
       theme. In light mode this is the same near-black the palette already
       uses, so nothing shifts visually. */
    color: rgb(var(--text-primary));
}

/* ── Tabular numerals ──
   Any number rendered in data tables, counts, money, dates, or monospace
   utility surfaces must use tabular figures so columns of digits line up.
   Geist is proportional by default; this opts numeric runs into
   the tabular variant where it matters. */
.font-mono, .mono,
.tabular,
table td, table th {
    font-variant-numeric: tabular-nums;
}

/* ── Display typography ──
   Negative tracking on display sizes makes headlines feel intentional and
   crisp. Thresholds are size-proportional: the larger the text, the more
   we pull letters in. Body text (≤text-base) is left at the font's
   natural tracking — tightening it there hurts readability. */
.text-3xl, .text-4xl, .text-5xl { letter-spacing: -0.022em; }
.text-2xl { letter-spacing: -0.018em; }
.text-xl  { letter-spacing: -0.012em; }

/* Headings pick up the same treatment even without utility classes so
   semantic HTML benefits too. */
h1 { letter-spacing: -0.022em; }
h2 { letter-spacing: -0.015em; }

/* ── Data-table utilities ──
   Opt-in helpers for the numeric-heavy tables on bookings, lots,
   containers, billing. */

/* Right-align + tabular figures. Drop on <td>/<th> for any numeric
   column (counts, weights, CBM, money). */
.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Sticky table header. Parent must have overflow-y scroll (or be inside
   a scrolling container) for this to engage. */
.table-sticky thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: rgb(var(--surface-subtle));
    box-shadow: 0 1px 0 rgb(var(--border-default));
}

/* Row-hover refinement: a smooth transition (no instant flash) and a
   slightly tighter color so dense tables don't feel washed out. */
.table-hover tbody tr {
    transition: background-color 0.1s ease;
}
.table-hover tbody tr:hover {
    background: rgb(var(--surface-hover));
}

/* ── HTMX / Alpine visibility helpers ── */
[x-cloak] { display: none !important; }
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: inline-block; }
.htmx-request.htmx-indicator { display: inline-block; }
.htmx-request #chat-send { display: none; }

/* Inbox upload progress strip — slim 2px bar pinned to the bottom of the
   drop zone. Visible only while the multipart upload is in flight; once
   the request returns and HTMX strips the .htmx-request class, the strip
   disappears and per-file parsing state is shown in the row stack below.
   The translate-X cycle gives a left→right sweep without depending on a
   determinate progress percentage. Pair with `htmx-indicator absolute`. */
.htmx-request #inbox-upload-strip { display: block; }
@keyframes inbox-strip {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(400%); }
}

/* ── Accessibility: skip to main content ──
   First focusable element on every page. Off-screen until focused, then
   pinned top-left so a keyboard user can jump past the sidebar (search +
   nav + account) straight to the page content. Targets #main-content. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
}
.skip-link:focus {
    left: 0.75rem;
    top: 0.75rem;
    padding: 0.5rem 0.875rem;
    background: rgb(var(--surface-card));
    color: rgb(var(--text-primary));
    border: 1px solid rgb(var(--border-default));
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    font-size: var(--fs-sm);
    font-weight: 500;
}
/* The skip target is programmatically focusable (tabindex="-1") but not an
   interactive control; the content jump is the confirmation, so suppress the
   page-wide focus outline that would otherwise frame the whole main region. */
#main-content:focus, #main-content:focus-visible {
    outline: none;
}

/* ── Accessibility: focus-visible ── */
*:focus-visible {
    outline: 2px solid rgb(var(--text-link));
    outline-offset: 2px;
}
/* Suppress outline on elements that have their own focus style */
input:focus-visible, textarea:focus-visible, select:focus-visible {
    outline: none;
}

/* When a keyboard user tabs to an anchor inside a table row, highlight the
   whole row so the focus context matches the mouse :hover affordance.
   Pairs with the row-link anchor pattern on the lots/bookings/buyers index
   tables — see TestTemplateRowsKeyboardAccessible. */
tbody tr:focus-within {
    background: rgb(var(--surface-hover));
}

/* ── Accessibility: reduced motion ── */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
