/*
 * The only hand-written global stylesheet. Loaded after the vendored Pico build, which supplies
 * the element baseline — typography, form controls, buttons, focus rings, tables and the nav
 * dropdown. This file carries only what Pico has no opinion about, plus the two deliberate
 * density overrides.
 *
 * Load order is not cosmetic. Several rules below tie Pico's specificity exactly and win only
 * because this file comes second; see the density section. LayoutViewTest pins the ordering.
 */

/* Grid density. The one place Pico's defaults are deliberately overridden.
 *
 * These screens are scanned hundreds of rows at a time, and Pico's defaults cost roughly 40% of
 * the rows visible per screen at 1280px. Both declarations restore what the app had before.
 *
 * Pico applies the root size through :where(:host),:where(:root) — zero specificity — but *sets*
 * --pico-font-size on :host,:root at (0,1,0), once at base and again in five media queries. This
 * rule ties that specificity and loads later, so it wins over all six: the ramp is flattened to
 * 14px at every width rather than lowered by one step. */
:root {
    --pico-font-size: 87.5%;
}

/* Identical specificity to Pico's td,th rule, so load order alone decides this one. Overrides
 * padding only — Pico's opaque background-color on the same selector still applies, which is why
 * every stripe and hover rule in this file is scoped to the cell rather than the row. */
td, th {
    padding: 3px;
}

/* Navigation.
 *
 * Pico ships `nav,nav ul{display:flex}` and contains the string `flex-wrap` zero times, so its nav
 * is a nowrap row. This app has ten top-level groups plus the brand; unwrapped, that row overflows
 * and an overflowing flex row widens the document, putting a horizontal scrollbar on every page.
 * Mandatory, not cosmetic. */
header nav,
header nav > ul {
    flex-wrap: wrap;
}

/* Pico's nav is justify-content: space-between, so the brand <ul> sits left and the links <ul>
 * sits right — the arrangement menu.css produced with float. flex-end keeps the links hugging the
 * right edge once the row wraps, rather than left-aligning each wrapped line. */
header nav > ul:last-of-type {
    justify-content: flex-end;
}

/* Pico's open dropdown panel is `position:absolute; min-width:fit-content; white-space:nowrap` —
 * as wide as its longest item on one unbreakable line, anchored to its summary's LEFT edge. With
 * the menu on the right that grows toward the viewport edge and widens the document, which put a
 * horizontal scrollbar on every page as soon as a group was opened.
 *
 * Anchoring to the right edge instead makes a panel grow inward, away from the edge it would
 * otherwise pass. */
header nav > ul:last-of-type details.dropdown > summary + ul {
    left: auto;
    right: 0;
}

/* Below 768px the panel drops into flow at full width with its text allowed to wrap, so an opened
 * group expands the nav like an accordion — it cannot exceed its container by construction, and the
 * anchoring above stops mattering.
 *
 * 768px, not Pico's own 576px breakpoint. Right-anchoring trades a right overflow for a possible
 * left one, and left overflow is *unreachable*: a viewport scrolls right, never left, so a clipped
 * panel is unreadable rather than merely untidy. Measured at exactly 576px, the Billbee and FORTAX
 * panels lost 66px off the left edge, because once the row wraps a summary can sit closer to x=0
 * than its panel is wide. Handing those widths to the accordion removes the case entirely. 768px is
 * also where the old menu.css switched to its mobile menu, so this restores the app's own boundary;
 * the .98 avoids a fractional gap against a min-width rule under display scaling. */
@media (max-width: 767.98px) {
    header nav details.dropdown > summary + ul {
        position: static;
        width: 100%;
        min-width: 0;
        white-space: normal;
    }
}

/* A table too wide for the viewport scrolls inside its own region.
 *
 * A <table> ignores overflow, and Pico v2's figure is `display:block;margin:0;padding:0` — the
 * overflow-x that v1 carried is gone — so this needs a wrapper of ours. It wraps the <table> and
 * nothing else: putting it on .datagrid, which is the whole page body on five views, would drag
 * the heading, alerts, toolbar and paginators sideways along with the table. One per <table>. */
.table-scroll {
    overflow-x: auto;
}

/* #buttons-bar is a flex row, so a wrapper inside it is a flex item and shrinks by default —
 * which squeezed the width:100% stats table on etsy/reviews down to a fraction of the bar. */
#buttons-bar > .table-scroll {
    flex: 1 1 100%;
}

/* Page title row. From common.css:29-38. */
#title-header {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
}

.title-actions {
    margin-left: auto;
}

/* Data grids. From datagrid.css:6-56, with every row-level background re-scoped to the cell.
 *
 * Pico paints every cell opaquely — `td,th{...background-color:var(--pico-background-color)...}` —
 * so a background set on <tr> is painted over and disappears. Transcribing the original row-level
 * stripe and hover rules unchanged would produce a table with no striping and no hover at all,
 * silently. The cell-scoped shape below is what Pico's own striped selector uses.
 *
 * Note the stripe parity is Pico's convention (odd) rather than the original's even. */
.datagrid-table {
    border-collapse: collapse;
    display: table;
    width: 100%;
}

.datagrid-table th {
    background-color: black;
    color: white;
    font-weight: normal;
    text-transform: uppercase;
    white-space: nowrap;
}

.datagrid-table td {
    border: solid 1px #d8d8d8;
}

.datagrid-table tbody tr td {
    transition: background-color 150ms ease-out;
}

/* The row part sits in :where() so it contributes no specificity: these compute to (0,0,1), which
 * beats Pico's td,th on load order while still losing to any cell colour a page stylesheet sets.
 *
 * The WHOLE prefix goes inside :where(), not just the row part — `.datagrid-table tbody` alone
 * is (0,1,2) and would still outrank `.rating-1 td`.
 *
 * That ordering is not incidental. On master the stripe lived on <tr>, a different element from the
 * <td> carrying a signal colour, so the signal always won. Scoping to the cell to survive Pico's
 * opaque background put the two in contest for the first time, and a plain
 * `.datagrid-table tbody tr:nth-child(odd) td` (0,2,3) would beat `.rating-1 td` (0,1,1) in
 * etsy-reviews.css — turning the negative-review highlight into a function of row parity. */
:where(.datagrid-table tbody tr:nth-child(odd)) td {
    background-color: #f5f5f5;
}

:where(.datagrid-table tbody tr:hover) td {
    background-color: #ebebeb;
}

.datagrid-table input[type=checkbox] {
    accent-color: black;
    height: 16px;
    width: 16px;
}

/* Toolbar. From datagrid.css:59-102, with the bespoke button colours dropped so Pico's buttons
 * show through. */
#buttons-bar {
    background-color: #060606;
    color: white;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    padding: 8px;
}

#buttons-bar label {
    padding: 8px;
}

#buttons-bar .label {
    font-weight: bold;
}

/* Form controls render at their natural width, everywhere.
 *
 * Pico ships `button[type=submit],input:not([type=checkbox],[type=radio]),select,textarea{width:100%}`.
 * That hits selects and text inputs as well as submit buttons, and this app's toolbars are inline
 * filter forms mixing all three on one row — left alone, every toolbar stacks into a broken pile.
 *
 * This is an opt-out, not an allow-list. An earlier version scoped the override to #buttons-bar,
 * table cells and three named filter forms, and shipped full-width fields on every screen that used
 * an inline form those three did not cover. The app has far more of them than can be enumerated, so
 * natural width is the default and the two places that genuinely want Pico's stacked treatment —
 * fieldset.form.create.edit below, and the auth card in auth.css — opt back in. */
button[type=submit],
select,
textarea,
input:not([type=checkbox], [type=radio]) {
    width: auto;
}

/* Natural width must still not exceed the container. The config screens size their fields with the
 * `size` attribute — `<input size="100">` is ~878px — which overflowed the document by 517px at
 * 375px once the viewport meta made narrow rendering real.
 *
 * The min-width reset on fieldset is the load-bearing half. A fieldset carries a UA default of
 * `min-width: min-content`, so a wide `size` attribute inside it grows the fieldset past its
 * `width: 100%` — and then max-width:100% on the input resolves against that widened parent and
 * caps nothing. Pico does not reset it. */
fieldset {
    min-width: 0;
}

input:not([type=checkbox], [type=radio]),
select,
textarea {
    max-width: 100%;
}

/* One shared vertical size for every inline control, so a row lines up.
 *
 * Two reasons this matters. Density: Pico's control padding and bottom margin are sized for a
 * stacked form, and a submit button per grid row took billbee/order-validations from 27px rows to
 * 87px — about 40% of the rows on screen. Alignment: every control type here is styled by Pico
 * through a *different* selector, so covering only <button> left a Filter button shorter than the
 * <select> beside it, and Calculate shorter than Reset on etsy/reviews, which is an <a role="button">.
 *
 * Hence the full list, `[role=button]` included. The :is() wrapper carries the specificity of its
 * widest argument — (0,1,1), from `input:not([type=checkbox],[type=radio])` — which is what clears
 * Pico's own attribute selectors. Vertical padding only: Pico
 * reserves a select's right padding for its chevron. */
#buttons-bar :is(button, [role="button"], input:not([type="checkbox"], [type="radio"]), select, textarea),
td :is(button, [role="button"], input:not([type="checkbox"], [type="radio"]), select, textarea),
.filter-form :is(button, [role="button"], input:not([type="checkbox"], [type="radio"]), select, textarea) {
    /* height: auto is required, not tidiness. Pico pins an explicit
     * `input:not([type=checkbox],[type=radio],[type=range]){height:calc(...)}` computed from its own
     * spacing variables, so padding alone leaves a text input taller than the select and button
     * beside it. Pico does the same thing for its nav controls. */
    height: auto;
    padding-top: 3px;
    padding-bottom: 3px;
    margin-bottom: 0;
    vertical-align: middle;
}

/* Buttons also lose Pico's wide horizontal padding — they sit inline beside the field they act on.
 * Not applied to select: Pico reserves its right padding for the chevron, and a shorthand here
 * would drop the arrow on top of the text. */
#buttons-bar :is(button, [role="button"]),
td :is(button, [role="button"]),
.filter-form :is(button, [role="button"]) {
    padding-left: 8px;
    padding-right: 8px;
}

/* Pico reserves `spacing-horizontal + 1.5rem` on a select's right edge for its chevron — 35px here.
 * Across the six date selects on etsy/reviews that is ~120px of padding alone, enough to wrap them
 * onto a second row inside their fixed 500px cell. Trimmed to what the arrow actually needs. */
#buttons-bar select,
td select,
.filter-form select {
    padding-left: 6px;
    padding-right: 22px;
    background-position: center right 6px;
}

/* The stacked filter form (vat-oss-api-report) lays its fields out as <div>s and ends with a bare
 * submit. Zeroing control margins for the inline toolbars glued that button to the field above it,
 * so it gets its gap back — matched on `div + button`, which the two inline filter forms never hit. */
.filter-form div + button[type="submit"] {
    margin-top: 8px;
}

/* The stacked create/edit forms are the exception, and deliberately keep Pico's full-width
 * controls — a stacked form is what that styling is for. */
fieldset.form.create.edit input:not([type=checkbox], [type=radio]),
fieldset.form.create.edit select,
fieldset.form.create.edit textarea,
fieldset.form.create.edit button[type=submit] {
    width: 100%;
}

/* Pico turns a <small> immediately after a form control into a block-level hint spanning the full
 * width. This app writes those notes inline, usually inside parentheses —
 * `<input ...> (<small>Comma separated list</small>)` on the config screens — and blocking it strands
 * the brackets on the line above. Restored to inline so the note reads as written. */
:where(input, select, textarea, fieldset) + small {
    display: inline;
    width: auto;
    margin-top: 0;
    margin-bottom: 0;
}

/* The wrapping form is Pico's `form { margin-bottom: var(--pico-spacing) }` reaching into a cell. */
td form {
    margin-bottom: 0;
}

/* Alerts. Lifted verbatim from datagrid.css:124-143 — Pico has no alert component and these are
 * used across 24 views. Design originally from Bootstrap. */
.alert {
    position: relative;
    padding: 0.75rem 1.25rem;
    margin-bottom: 1rem;
    border: 1px solid #0000;
    border-radius: 0.25rem;
}

.alert-success {
    color: #155724;
    background-color: #d4edda;
    border-color: #c3e6cb;
}

.alert-danger {
    color: #721c24;
    background-color: #f8d7da;
    border-color: #f5c6cb;
}

/* From common.css:41-59. Used by billbee/declaration-package-report only. */
.vertical-data-table {
    border-collapse: collapse;
    border: 2px solid black;
    margin-bottom: 20px;
}

.vertical-data-table caption {
    font-size: 1.5em;
    font-weight: bold;
    white-space: nowrap;
    caption-side: top;
    text-align: left;
    padding-bottom: 10px;
}

.vertical-data-table td {
    border: 1px solid #ccc;
    padding: 8px;
}

/* Pico ships `[type=checkbox]~label,[type=radio]~label{display:inline-block}` — a *general* sibling
   selector, so it catches every label after a checkbox in the same parent, not only the checkbox's
   own. On a form whose labels sit above their inputs, that silently turns any field added below a
   checkbox into a row with the label beside the input, indented out of the column the others share.
   It cost the config screen exactly that when the products-rebuild field was added below the Order
   Validation checkbox.

   Narrow it to the adjacent sibling, which is the pattern Pico is actually for — `<input
   type=checkbox><label>` rendered inline, as shopify-hh/product-translation-fix does with its
   DE | ES | FR radios. Anything further down the fieldset goes back to block.

   Scoped to `fieldset` so the inline checkbox/label pairs outside one — billbee/refunds' Select All —
   are untouched. Fixing this here rather than by ordering fields is deliberate: ordering a form by
   widget type to satisfy a stylesheet constrains where every future field can go. */
fieldset [type="checkbox"] ~ label,
fieldset [type="radio"] ~ label {
    display: block;
}

fieldset [type="checkbox"] + label,
fieldset [type="radio"] + label {
    display: inline-block;
    margin-bottom: 0;
    cursor: pointer;
}
