/*
 * Export Connect admin skin — aligns the Sylius admin UI with the public
 * shop's editorial charter (templates/shop/base.html.twig). Same palette,
 * same typography family, same shadow/radius vocabulary so the admin
 * cockpit and the marketing site feel like one product.
 *
 * Loaded via importmap('app') in templates/admin/base.html.twig.
 *
 * Strategy: variables first, then a thin layer of overrides on Sylius's
 * Tabler-based defaults. Sylius components keep working, just on a
 * different visual language.
 */

@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@500;600&family=Inter:wght@300;400;500;600&display=swap');

:root {
    /* Mirrored from templates/shop/base.html.twig so any future palette
       change in the shop ripples here too. */
    --ec-black: #1a1a1a;
    --ec-dark: #2d2d2d;
    --ec-text: #4a4a4a;
    --ec-muted: #888888;
    --ec-border: #e5e5e5;
    --ec-light: #f8f8f8;
    --ec-white: #ffffff;
    --ec-accent: #8b2635;
    --ec-accent-dark: #6d1e2a;
    --ec-gold: #b8956e;

    --ec-font-serif: 'Playfair Display', Georgia, serif;
    --ec-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

    /* Split out of --ec-black and --ec-white when the admin learned a dark
       theme: `ink` and `paper` are the page's text and its surface and they
       swap with the theme, while `black` and `white` keep meaning the fixed
       chrome — the sidebar is dark in both themes, and text on it is white in
       both. Collapsing the four into two is what paints white text on a white
       card the first time somebody switches. */
    --ec-ink: #1a1a1a;
    --ec-paper: #ffffff;

    --ec-shadow-subtle: 0 2px 8px rgba(0, 0, 0, 0.04);
    --ec-shadow-soft: 0 4px 20px rgba(0, 0, 0, 0.06);
    --ec-shadow-medium: 0 8px 30px rgba(0, 0, 0, 0.08);
    --ec-radius: 14px;
}

/* Page background — neutral light gray rather than the stock skyblue
   AssetMapper demo body color. */
body,
.page-wrapper,
.page-body,
.page {
    background-color: var(--ec-light) !important;
    font-family: var(--ec-font-sans);
}

/* Headings adopt the editorial serif used on the shop so the typographic
   identity carries into the admin. Sylius widget labels stay on the sans
   stack via the body inheritance. */
h1, h2, h3, .page-title, .card-title {
    font-family: var(--ec-font-serif);
    font-weight: 500;
    color: var(--ec-ink);
    letter-spacing: -0.01em;
}

h4, h5, h6 {
    font-family: var(--ec-font-sans);
}

/* Generic card refresh: rounder corners, layered shadow instead of the
   flat 1px border. Sylius grids and forms use .card heavily — only the
   chrome changes. */
.card {
    border: 0 !important;
    border-radius: var(--ec-radius) !important;
    box-shadow: var(--ec-shadow-subtle);
}

.card-header {
    border-bottom: 1px solid var(--ec-border);
    background: transparent;
}

/* Page header (h1 + subtitle blocks): tighter, more typographic. */
.page-header .page-title {
    font-weight: 500;
}

.page-header .page-subtitle,
.page-header .text-secondary {
    color: var(--ec-muted) !important;
}

/* Hero band utility — single source of truth for the editorial dark
   strip at the top of dashboards (Statistics, Dashboard). Same palette
   as the shop's CTA section so it reads as one product. */
.stats-card {
    background: var(--ec-paper);
    border-radius: var(--ec-radius);
}

.stats-card-dark {
    background: var(--ec-black);
    border-radius: var(--ec-radius);
    color: var(--ec-white);
    box-shadow: var(--ec-shadow-medium);
}

.stats-card-dark a:not(.btn) {
    color: var(--ec-white);
    text-decoration: underline;
    text-decoration-color: rgba(255, 255, 255, 0.4);
}

.stats-eyebrow {
    text-transform: uppercase;
    font-size: 0.72rem;
    letter-spacing: 0.12em;
    font-weight: 600;
    font-family: var(--ec-font-sans);
    color: var(--ec-muted);
}

.stats-card-dark .stats-eyebrow {
    color: rgba(255, 255, 255, 0.55);
}

.stats-title {
    font-family: var(--ec-font-serif);
    font-size: 1.25rem;
    font-weight: 500;
    color: var(--ec-ink);
    margin: 0.4rem 0 1rem;
    letter-spacing: -0.01em;
}

.stats-card-dark .stats-title {
    color: var(--ec-white);
}

.stats-metric {
    font-family: var(--ec-font-serif);
    font-size: 2.25rem;
    font-weight: 500;
    line-height: 1.1;
}

/* Buttons used inside the hero bands echo the shop's pill primary on
   black background. */
.btn-light.rounded-pill {
    /* Sits on the dark hero bands, which stay dark in both themes: fixed
       white chip, fixed dark letters. */
    background: var(--ec-white);
    color: var(--ec-black);
    border-color: var(--ec-white);
    font-weight: 500;
    font-family: var(--ec-font-sans);
}

/* Accent color on links and selected nav items — wine. */
.btn-primary {
    background: var(--ec-black);
    border-color: var(--ec-black);
}

.btn-primary:hover,
.btn-primary:focus {
    background: var(--ec-dark);
    border-color: var(--ec-dark);
}

.btn-outline-primary {
    color: var(--ec-ink);
    border-color: var(--ec-border);
}

.btn-outline-primary:hover {
    background: var(--ec-black);
    border-color: var(--ec-black);
    color: var(--ec-white);
}

/* ------------------------------------------------------------------------
   Sidebar (navbar-vertical) — pulled in line with the wine/editorial
   charter. Sylius declares `data-bs-theme="dark"` so Bootstrap already
   handles dark text on the navbar; we just swap the chrome colors.
   ------------------------------------------------------------------------ */

.navbar.navbar-vertical {
    background-color: var(--ec-black) !important;
    border-right: 0 !important;
    box-shadow: var(--ec-shadow-soft);
}

.navbar.navbar-vertical .navbar-brand,
.navbar.navbar-vertical .navbar-brand a {
    font-family: var(--ec-font-serif);
    font-weight: 500;
    color: var(--ec-white) !important;
    letter-spacing: -0.01em;
}

/* Replace the stock Sylius logo image with a compact wordmark when the
   sidebar is in our admin. Keeps the existing image hidden so we don't
   touch the host template. */
.navbar.navbar-vertical .navbar-brand-image {
    display: none;
}

.navbar.navbar-vertical .navbar-brand::after {
    content: 'EC';
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    /* A fixed white chip on a sidebar that is dark in both themes, so its
       letters take the fixed dark colour — the theme ink turns cream and
       writes white on white. */
    background: var(--ec-white);
    color: var(--ec-black);
    border-radius: 8px;
    font-family: var(--ec-font-serif);
    font-size: 0.875rem;
    font-weight: 600;
}

/* Nav links: soft white at rest, full white on hover, wine accent for
   the active route. Padding and radius give the items a "chip" feel. */
.navbar.navbar-vertical .nav-link {
    color: rgba(255, 255, 255, 0.65);
    border-radius: 8px;
    margin: 2px 8px;
    padding: 0.55rem 0.75rem;
    font-family: var(--ec-font-sans);
    font-size: 0.9rem;
    font-weight: 400;
    transition: background 0.15s ease, color 0.15s ease;
}

.navbar.navbar-vertical .nav-link:hover,
.navbar.navbar-vertical .nav-link:focus {
    color: var(--ec-white);
    background: rgba(255, 255, 255, 0.06);
}

/* Where you are standing, said with the two things the sidebar already has:
   a lighter ground and full-strength white. No coloured rail — an accent
   stripe on a dark navy chrome reads as an alert, and being on a page is not
   an alert. The surrounding entries sit at 66 % white, so full white is
   already the loudest thing in the column. */
.navbar.navbar-vertical .nav-link.active,
.navbar.navbar-vertical .nav-item.active > .nav-link {
    color: var(--ec-white);
    background: rgba(255, 255, 255, .09);
    font-weight: 600;
}

/* Tabler marks the active entry with a 3px ::after in its own primary — the
   teal this charter replaced everywhere else and forgot here. Removed rather
   than recoloured: the lighter ground and the full white already say it, and a
   stripe on top of them says it twice. */
.navbar.navbar-vertical .nav-item.active::after,
.navbar.navbar-vertical .nav-link.active::after {
    display: none;
}

.navbar.navbar-vertical .nav-link-icon {
    opacity: 0.7;
}

.navbar.navbar-vertical .nav-link.active .nav-link-icon,
.navbar.navbar-vertical .nav-link:hover .nav-link-icon {
    opacity: 1;
}

/* Search input and version pill embedded in the sidebar. */
.navbar.navbar-vertical .form-control {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.1);
    color: var(--ec-white);
}

.navbar.navbar-vertical .form-control::placeholder {
    color: rgba(255, 255, 255, 0.4);
}

/* Top "Hello sylius" user navbar — light surface, sit cleanly above the
   black sidebar without picking up the dark theme glow. */
.navbar.navbar-light,
.page > .navbar:not(.navbar-vertical) {
    background: var(--ec-paper) !important;
    border-bottom: 1px solid var(--ec-border);
}

/* Accent badges (wine) for highlights without overriding all Bootstrap
   bg-* utilities Sylius relies on. */
.bg-accent,
.badge.bg-accent {
    background-color: var(--ec-accent) !important;
    color: var(--ec-white);
}

.text-accent {
    color: var(--ec-accent) !important;
}

/* ------------------------------------------------------------------------
   CRUD grid polish — applies to every Sylius admin index page (Countries,
   Tariff Rules, API Clients…). We don't touch the markup, just soften
   the chrome to match the wine charter.
   ------------------------------------------------------------------------ */

/* Page-header h1 in CRUD grids: bigger Playfair, no link underline. */
.page-header .page-title {
    font-family: var(--ec-font-serif);
    font-size: 1.6rem;
    font-weight: 500;
}

/* Filters card chevron + label */
.card-header .form-label,
.card-header .accordion-button {
    font-family: var(--ec-font-sans);
}

/* Grid tables: editorial headers + neutral row dividers. */
.card-table thead th,
.table thead th {
    font-family: var(--ec-font-sans);
    text-transform: uppercase;
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    font-weight: 600;
    color: var(--ec-muted);
    border-bottom: 1px solid var(--ec-border);
    background: transparent;
}

.card-table tbody td,
.table tbody td {
    border-top: 1px solid rgba(0, 0, 0, 0.05);
    color: var(--ec-text);
}

/* Status "Yes/No" pills replace Tabler's flat green/red. */
.badge.bg-success,
.bg-success.text-white {
    background-color: rgba(0, 0, 0, 0.05) !important;
    color: var(--ec-ink) !important;
    font-weight: 500;
}

.badge.bg-danger,
.bg-danger.text-white {
    background-color: var(--ec-accent) !important;
    color: #fff !important;
}

/* Row action buttons (eye / edit / delete) become slim outlined squares. */
.card-table .btn,
.btn-group-sm > .btn {
    border-radius: 8px !important;
}

/* Pagination — minimal, no boxy borders. */
.pagination .page-item .page-link {
    color: var(--ec-muted);
    border: 0;
    background: transparent;
    border-radius: 8px;
    margin: 0 2px;
}

.pagination .page-item.active .page-link,
.pagination .page-item .page-link:hover {
    background: var(--ec-black);
    color: #fff;
}

/* "Show 10" dropdown */
.dataTables_length .form-select,
select.form-select-sm {
    border-color: var(--ec-border);
    border-radius: 8px;
}

/* Breadcrumb: smaller and quieter. */
.breadcrumb {
    font-family: var(--ec-font-sans);
    font-size: 0.8rem;
    color: var(--ec-muted);
}

.breadcrumb a {
    color: var(--ec-muted);
}

.breadcrumb-item.active {
    color: var(--ec-text);
}

/* "Create" call-to-action at top right of grids. */
.page-header .btn-primary,
.page-header .btn-secondary {
    border-radius: 100px;
    padding: 0.45rem 1.2rem;
    background: var(--ec-black);
    border-color: var(--ec-black);
    color: #fff;
    font-family: var(--ec-font-sans);
    font-weight: 500;
}

.page-header .btn-primary:hover {
    background: var(--ec-dark);
}

/* ==========================================================================
   Home
   ========================================================================== */

:root {
    /* Demand moving up or down. Blue against brick rather than the green and
       red the status pills use: a growing market is not a passed check, and
       the green/red pair fails deuteranopia. Validated as a diverging pair. */
    --ec-up: #2667a8;
    --ec-down: #a83f2c;

    --ec-sane: #3f6f52;
    --ec-sane-soft: #e8f0eb;
    --ec-gold-soft: #f6efe4;
    --ec-line: #efece7;

    --ec-f-douane: #8b2635;
    --ec-f-accise: #b8956e;
    --ec-f-major: #3f6f52;
    --ec-f-tva: #6f6a64;
    --ec-f-frais: #d6cfc5;
}

.ec-home-hero {
    background: var(--ec-paper);
    border: 1px solid var(--ec-border);
    border-radius: 10px;
    padding: 17px;
}

.ec-home-line {
    font-family: var(--ec-font-serif);
    font-size: 1.28rem;
    line-height: 1.28;
    color: var(--ec-ink);
    margin: 0;
    max-width: 32ch;
}

.ec-home-ledger {
    font-size: .76rem;
    color: var(--ec-muted);
    line-height: 1.45;
    margin-top: 9px;
}

.ec-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .69rem;
    font-weight: 600;
    padding: 2px 9px;
    border-radius: 999px;
    white-space: nowrap;
}

.ec-pill-ok { background: var(--ec-sane-soft); color: var(--ec-sane); }
.ec-pill-wa { background: var(--ec-gold-soft); color: var(--ec-gold); }
.ec-pill-cr { background: #f3e7e8; color: var(--ec-accent); }

.ec-sectitle {
    font-family: var(--ec-font-serif);
    font-size: 1rem;
    color: var(--ec-ink);
    font-weight: 600;
    margin: 0;
}

/* Cost breakdown — the country page's charge card. --------------------- */

.ec-dtot {
    font-size: 1.46rem;
    color: var(--ec-ink);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    margin-top: 3px;
}

.ec-stack {
    display: flex;
    height: 11px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--ec-light);
    margin: 11px 0 10px;
}

.ec-brk { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; }
.ec-brk li { display: flex; align-items: baseline; gap: 8px; font-size: .78rem; }
.ec-brk i { width: 9px; height: 9px; border-radius: 2px; flex: 0 0 9px; }
.ec-brk .v { margin-left: auto; color: var(--ec-ink); font-variant-numeric: tabular-nums; }

.ec-across {
    margin-top: 12px;
    padding-top: 11px;
    border-top: 1px solid var(--ec-line);
    display: grid;
    gap: 4px;
}

.ec-across .r { display: flex; align-items: baseline; gap: 8px; font-size: .76rem; }
.ec-across .r .v { margin-left: auto; color: var(--ec-ink); font-variant-numeric: tabular-nums; }
.ec-across .r.cur, .ec-across .r.cur .v { color: var(--ec-accent); font-weight: 600; }

/* Queue ------------------------------------------------------------------ */

.ec-queue { list-style: none; margin: 0; padding: 0; }

.ec-queue li {
    display: flex;
    gap: 10px;
    align-items: baseline;
    padding: 8px 0;
    border-top: 1px solid var(--ec-line);
}

.ec-queue li:first-child { border-top: 0; }

.ec-sev { width: 3px; align-self: stretch; border-radius: 2px; flex: 0 0 3px; }
.ec-sev-cr { background: var(--ec-accent); }
.ec-sev-wa { background: var(--ec-gold); }
.ec-sev-ok { background: var(--ec-sane); }

/* Generic CRUD form ----------------------------------------------------- */

/* The yes/no settings of a record, gathered under the fields as switches. */
.ec-form-switches {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 28px;
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid var(--ec-line);
}
.ec-form-switches > .mb-3 { margin-bottom: 0 !important; }

/* Chip picks — the countries of a document, by fiscal zone -------------- */

.ec-zone-picks { display: grid; gap: 14px; }
.ec-zone-pick { border: 1px solid var(--ec-line); border-radius: 10px; padding: 10px 14px 14px; margin: 0; }
.ec-zone-pick-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    /* Floated, as Bootstrap's reboot does, so the legend sits inside the
       frame rather than notched into its top border. */
    float: left;
    width: 100%;
    margin: 0 0 8px;
    padding: 0;
    font-size: .82rem;
}
.ec-zone-pick-name { font-weight: 600; color: var(--ec-ink); }
.ec-zone-pick > .ec-chips { clear: both; }
.ec-zone-pick-count { font-size: .72rem; color: var(--ec-muted); font-variant-numeric: tabular-nums; }
.ec-zone-pick-toggle {
    margin-left: auto;
    background: none;
    border: 0;
    padding: 0;
    font-size: .74rem;
    font-weight: 600;
    color: var(--ec-accent);
    cursor: pointer;
}
.ec-zone-pick-toggle:focus-visible { outline: 2px solid var(--ec-accent); outline-offset: 2px; border-radius: 3px; }

/* A chip is ticked when it reads as filled: the ink ground, the name in the
   paper colour. Unticked, it stays the ordinary outlined chip. */
.ec-chip-pick { cursor: pointer; user-select: none; }
.ec-chip-pick:has(input:checked) {
    background: var(--ec-ink);
    border-color: var(--ec-ink);
    color: var(--ec-paper);
}
.ec-chip-pick:has(input:checked) .ec-chip-code { color: color-mix(in srgb, var(--ec-paper) 70%, transparent); }
.ec-chip-pick:has(input:focus-visible) { outline: 2px solid var(--ec-ink); outline-offset: 2px; }

/* Tariff rule form ------------------------------------------------------ */

/* The rule's page opens on the rate in large serif figures; the form types it
   in the same place at the same size, with the unit the calculation type
   gives it. Everything else stays at the admin's ordinary scale. */
.ec-rf-section + .ec-rf-section { margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--ec-line); }
.ec-rf-lead { font-size: .8rem; color: var(--ec-muted); margin: 4px 0 14px; }

.ec-rf-rate {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-top: 18px;
    padding: 6px 0 8px;
    border-bottom: 2px solid var(--ec-border);
    transition: border-color .15s ease;
}
.ec-rf-rate:focus-within { border-bottom-color: var(--ec-ink); }
.ec-rf-rate.is-invalid { border-bottom-color: var(--ec-accent); }
/* Scoped under its row: Tabler's .form-control would otherwise draw its own
   box and underline inside the one the row already draws. */
.ec-rf-rate .ec-rf-rate-input {
    /* As wide as the figure, so the unit sits right after it as on the
       rule's page; browsers without field-sizing keep a fixed width. */
    field-sizing: content;
    width: auto;
    flex: 0 1 auto;
    min-width: 2ch;
    max-width: 100%;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    padding: 0;
    font-family: var(--ec-font-serif);
    font-size: 2.4rem;
    line-height: 1.05;
    font-weight: 600;
    color: var(--ec-ink);
    font-variant-numeric: tabular-nums;
}
.ec-rf-rate .ec-rf-rate-input:focus { outline: none; box-shadow: none; }
.ec-rf-rate .ec-rf-rate-input::placeholder { color: var(--ec-border); }
.ec-rf-rate-unit { font-size: 1rem; font-weight: 500; color: var(--ec-muted); white-space: nowrap; }

.ec-rf-range { display: grid; grid-template-columns: 170px 1fr; align-items: center; gap: 6px 16px; padding: 8px 0; }
.ec-rf-range-label { font-size: .82rem; font-weight: 500; color: var(--ec-ink); }
.ec-rf-range-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ec-rf-range > .invalid-feedback, .ec-rf-range > .form-error { grid-column: 2; }

.ec-rf-aside { position: sticky; top: 16px; }
.ec-rf-note { border-top: 1px solid var(--ec-line); background: var(--ec-light); font-size: .8rem; color: var(--ec-text); }

@media (max-width: 576px) {
    .ec-rf-range { grid-template-columns: 1fr; }
    .ec-rf-range > .invalid-feedback, .ec-rf-range > .form-error { grid-column: 1; }
    .ec-rf-rate .ec-rf-rate-input { font-size: 1.9rem; }
}

/* Unfolding rows ---------------------------------------------------------- */

/* A table line that opens into a detail row beneath it: the duty overview
   and the MBE comparison. The chevron turns when the line is open. */
.ec-overview-row { cursor: pointer; }
.ec-overview-row:hover > td { background: var(--ec-light); }
.ec-overview-toggle {
    display: inline-flex;
    align-items: baseline;
    background: none;
    border: 0;
    padding: 0;
    color: inherit;
    font: inherit;
    text-align: left;
}
.ec-overview-toggle:focus-visible { outline: 2px solid var(--ec-ink); outline-offset: 2px; border-radius: 3px; }
.ec-overview-chevron {
    display: inline-block;
    width: .45rem;
    height: .45rem;
    margin-right: .55rem;
    border-right: 1.5px solid var(--ec-muted);
    border-bottom: 1.5px solid var(--ec-muted);
    transform: rotate(-45deg);
    transition: transform .15s ease;
}
.ec-overview-toggle[aria-expanded="true"] .ec-overview-chevron { transform: rotate(45deg); }
.ec-overview-detail > td { white-space: normal; background: var(--ec-paper); padding: 0 !important; }

/* MBE comparison ---------------------------------------------------------- */

.ec-pill-mute { background: var(--ec-light); color: var(--ec-muted); }
.ec-mc td, .ec-mc th { white-space: nowrap; }
.ec-mc-counts { display: flex; flex-wrap: wrap; gap: 14px 40px; }
.ec-mc-counts .k { font-size: .68rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ec-muted); font-weight: 600; margin-bottom: 6px; }
.ec-mc-count-pills { display: flex; flex-wrap: wrap; gap: 6px; }

.ec-mc-detail {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px 28px;
    padding: 16px 22px 16px 34px;
    border-left: 3px solid var(--ec-accent);
}
.ec-mc-col-title { font-family: var(--ec-font-serif); font-weight: 600; color: var(--ec-ink); margin-bottom: 6px; }
.ec-mc-lines { display: grid; grid-template-columns: 1fr auto; gap: 3px 14px; margin: 0; font-size: .8rem; }
.ec-mc-lines dt { font-weight: 400; color: var(--ec-text); white-space: normal; }
.ec-mc-lines dd { margin: 0; text-align: right; color: var(--ec-ink); }
.ec-mc-empty { font-size: .8rem; color: var(--ec-muted); margin: 0; }
.ec-mc-note { font-size: .72rem; color: var(--ec-muted); margin: 8px 0 0; white-space: normal; }
.ec-mc-basis { display: block; font-family: var(--tblr-font-monospace, monospace); font-size: .7rem; color: var(--ec-muted); }

@media (max-width: 768px) {
    .ec-mc-detail { grid-template-columns: 1fr; padding: 14px 12px; }
}

/* Destination detail ---------------------------------------------------- */

/* A line of the duty overview, unfolded. Laid out as a bill: the family on
   the left, what was charged and on what in the middle, the amount on the
   right, the delivered price last. */
/* Narrower than the overview table, which scrolls sideways under its nine
   columns: held at the left edge, the detail stays in view and its amounts
   sit beside their labels instead of past the scroll. */
.ec-dd {
    position: sticky;
    left: 0;
    max-width: min(880px, 100vw - 2rem);
    padding: 18px 22px 14px 30px;
    border-left: 3px solid var(--ec-accent);
}
.ec-dd-loading, .ec-dd-failure { color: var(--ec-muted); font-size: .8rem; }

.ec-dd-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 6px 18px; }
.ec-dd-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ec-dd-code { font-size: .78rem; color: var(--ec-accent); font-weight: 600; }
.ec-dd-name { font-family: var(--ec-font-serif); font-size: 1.15rem; font-weight: 600; color: var(--ec-ink); }
.ec-dd-zone { font-size: .66rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ec-muted); font-weight: 600; }
.ec-dd-headline { font-size: .95rem; font-weight: 600; color: var(--ec-ink); }
.ec-dd-headline-sub { font-size: .74rem; font-weight: 400; color: var(--ec-muted); }

.ec-dd-intro { display: flex; justify-content: space-between; align-items: baseline; gap: 18px; margin: 6px 0 10px; }
.ec-dd-note { font-size: .8rem; color: var(--ec-text); max-width: 70ch; margin: 0; white-space: pre-line; }
.ec-dd-link { font-size: .74rem; font-weight: 600; color: var(--ec-accent); white-space: nowrap; margin-left: auto; }

.ec-dd-table { width: 100%; border-collapse: collapse; }
.ec-dd-table td { padding: 9px 0; border-top: 1px solid var(--ec-line); vertical-align: top; }
.ec-dd-badge-cell { width: 140px; }
.ec-dd-badge {
    display: inline-block;
    font-size: .68rem;
    font-weight: 600;
    padding: 2px 7px;
    border-radius: 4px;
    color: var(--ec-ink);
    background: color-mix(in srgb, var(--ec-dd-family) 22%, transparent);
    box-shadow: inset 3px 0 0 var(--ec-dd-family);
}
.ec-dd-label { font-size: .82rem; color: var(--ec-ink); }
.ec-dd-rule { color: inherit; text-decoration: underline; text-decoration-color: var(--ec-border); text-underline-offset: 3px; }
.ec-dd-rule:hover, .ec-dd-rule:focus-visible { color: var(--ec-accent); text-decoration-color: currentColor; }
.ec-dd-sub { font-size: .72rem; color: var(--ec-muted); margin-top: 2px; }
.ec-dd-amount { text-align: right; white-space: nowrap; font-size: .8rem; color: var(--ec-ink); padding-left: 18px !important; }
.ec-dd-missing { color: var(--ec-accent); font-weight: 600; }
.ec-dd-total td { border-top: 1px solid var(--ec-border); }
.ec-dd-total-label { font-size: .7rem; color: var(--ec-muted); font-weight: 600; padding-left: 7px; }

@media (max-width: 576px) {
    .ec-dd { padding: 14px 12px; }
    .ec-dd-badge-cell { width: 92px; }
}

/* Movers ----------------------------------------------------------------- */

.ec-mv-total { font-family: var(--ec-font-sans); font-size: .8rem; font-weight: 600; margin-left: .4rem; }
.ec-mv-up { color: var(--ec-up); }
.ec-mv-down { color: var(--ec-down); }

.ec-mv-legend { display: flex; gap: 14px; align-items: center; }
.ec-mv-legend span { display: inline-flex; align-items: center; gap: 6px; }
.ec-mv-swatch { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.ec-mv-swatch-up { background: var(--ec-up); }
.ec-mv-swatch-down { background: var(--ec-down); }

.ec-mv { list-style: none; margin: 0; padding: 0; }

.ec-mv-row {
    display: grid;
    grid-template-columns: minmax(110px, 180px) 1fr 1fr 48px 72px;
    align-items: center;
    gap: 0;
    padding: 5px 6px;
    border-radius: 6px;
    color: inherit;
    text-decoration: none;
}

.ec-mv-row:hover, .ec-mv-row:focus-visible { background: var(--ec-light); color: inherit; }
.ec-mv-row:focus-visible { outline: 2px solid var(--ec-ink); outline-offset: 1px; }

.ec-mv-name {
    font-size: .8rem;
    font-weight: 600;
    color: var(--ec-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding-right: 10px;
}

/* Each arm fills half the plot; the axis is the border between them, so a
   zero sits exactly in the middle whatever the labels around it. */
.ec-mv-half { display: flex; height: 14px; }
.ec-mv-half-down { justify-content: flex-end; border-right: 1px solid var(--ec-muted); }
.ec-mv-half-up { justify-content: flex-start; }

.ec-mv-bar { display: block; height: 100%; }
.ec-mv-bar-down { background: var(--ec-down); border-radius: 4px 0 0 4px; margin-right: 1px; }
.ec-mv-bar-up { background: var(--ec-up); border-radius: 0 4px 4px 0; margin-left: 1px; }

.ec-mv-delta { font-size: .78rem; font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.ec-mv-counts { font-size: .72rem; color: var(--ec-muted); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

@media (max-width: 576px) {
    .ec-mv-row { grid-template-columns: 90px 1fr 1fr 40px; }
    .ec-mv-counts { display: none; }
}

.ec-amt { font-size: .77rem; color: var(--ec-ink); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Inventory strip -------------------------------------------------------- */

.ec-strip {
    display: flex;
    flex-wrap: wrap;
    border: 1px solid var(--ec-border);
    border-radius: 9px;
    overflow: hidden;
    background: var(--ec-paper);
}

.ec-strip > div { flex: 1 1 92px; padding: 9px 13px; border-right: 1px solid var(--ec-border); }
.ec-strip > div:last-child { border-right: 0; }

.ec-strip .v {
    font-family: var(--ec-font-serif);
    font-size: 1.1rem;
    color: var(--ec-ink);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.ec-strip .k { font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ec-muted); font-weight: 600; }

/* ==========================================================================
   Dark theme
   ==========================================================================
   Tabler ships its own [data-bs-theme=dark] rules, so every Sylius component
   follows the attribute on <html> by itself; what it cannot know is our
   palette. Only the tokens are redefined here — a colour declared directly
   inside this block would be one the light theme never sees, which is how a
   theme ends up half-applied.

   The ramps are not the light ones inverted. A tint has to keep meaning the
   same charge in both themes and stay legible on its own ground, so the
   parchment end darkens to a warm near-black and the accent end lightens,
   rather than the two swapping places. */

[data-bs-theme="dark"] {
    --ec-ink: #f2efe9;
    --ec-paper: #171513;
    --ec-text: #c3bdb4;
    --ec-muted: #8b857c;
    --ec-border: #332f2b;
    --ec-line: #28241f;
    --ec-light: #201d1a;

    --ec-accent: #d4808c;
    --ec-accent-dark: #b9636f;
    --ec-gold: #cfad84;

    --ec-up: #4f8ed0;
    --ec-down: #d26a50;

    --ec-sane: #7fb094;
    --ec-sane-soft: #1e2a23;
    --ec-gold-soft: #332a1f;

    --ec-f-douane: #d4808c;
    --ec-f-accise: #cfad84;
    --ec-f-major: #7fb094;
    --ec-f-tva: #9a938a;
    --ec-f-frais: #403a34;

    /* Tabler's own dark palette is a cool blue-grey; ours is warm. Handing it
       our tokens is what makes every component we never wrote a rule for —
       cards, dropdowns, modals, table stripes — land on the same ground as the
       ones we did, instead of two dark themes sharing a page. */
    --tblr-body-bg: var(--ec-light);
    --tblr-body-color: var(--ec-text);
    --tblr-bg-surface: var(--ec-paper);
    --tblr-bg-surface-secondary: var(--ec-light);
    --tblr-bg-surface-tertiary: var(--ec-light);
    --tblr-border-color: var(--ec-border);
    --tblr-border-color-translucent: var(--ec-border);
    --tblr-secondary: var(--ec-muted);
    --tblr-secondary-color: var(--ec-muted);
    --tblr-link-color: var(--ec-accent);
    --tblr-link-hover-color: var(--ec-accent-dark);


    /* A shadow is a light effect: on a dark ground it reads as grime unless
       it goes darker and tighter than the one on paper. */
    --ec-shadow-subtle: 0 2px 8px rgba(0, 0, 0, 0.35);
    --ec-shadow-soft: 0 4px 20px rgba(0, 0, 0, 0.45);
    --ec-shadow-medium: 0 8px 30px rgba(0, 0, 0, 0.5);
}

/* The two tints that sit at the pale end of a ramp carry dark text in the
   light theme and have to carry light text once that end is itself dark. */
[data-bs-theme="dark"] .ec-t1,
[data-bs-theme="dark"] .ec-t2 { color: var(--ec-ink); }

[data-bs-theme="dark"] .ec-en1,
[data-bs-theme="dark"] .ec-ep1 { color: var(--ec-ink); }

/* Tabler's `.text-green` and friends read their colour off a `-rgb` triplet,
   and its dark theme re-declares those on <body> at the light-theme values —
   #006110 green, which `.bg-green-lt` then lays on a dark green ground. Every
   coloured badge in the grids came out green on green. Declared on <body> as
   well as on the root, because a value set on <body> is the one the badges
   inherit. */
/* Two of them need the universal selector to reach: Sylius ships a `*` rule
   that stamps its own green and blue on EVERY element, so nothing inherits
   them and a declaration on <body> never arrives. Matching `*` is the only
   thing that overrides `*`. */
[data-bs-theme="dark"] * {
    /* Sage rather than mint: the admin's dark ground is a warm near-black and
       a saturated green reads as a foreign element pasted onto it. This is
       --ec-sane, the same green the home uses to say "sound". */
    --tblr-green-rgb: 143, 184, 155;
    --tblr-blue-rgb: 122, 164, 204;
    --tblr-code-color: var(--ec-ink);
}

[data-bs-theme="dark"],
[data-bs-theme="dark"] body {
    --tblr-green-rgb: 116, 198, 157;
    --tblr-red-rgb: 229, 128, 139;
    --tblr-yellow-rgb: 232, 180, 85;
    --tblr-orange-rgb: 240, 140, 75;
    --tblr-teal-rgb: 95, 194, 164;
    --tblr-blue-rgb: 107, 166, 232;
    --tblr-purple-rgb: 195, 138, 216;
    --tblr-cyan-rgb: 106, 188, 209;
    --tblr-pink-rgb: 226, 140, 176;
}

/* Inline code — a document code, an HS code, a command name — is a chip, and
   it was reading its colour off Tabler's `--tblr-code-color`: a near-black that
   the dark theme never moved, so the Documents grid showed #36393b letters on a
   #3d444b ground. Taken off that variable entirely and drawn from our own
   tokens, in both themes, with the same wash-and-hairline as the pale badges so
   the two read as one vocabulary.

   `:not(pre) > code` leaves fenced blocks alone: they carry their own ground
   and would end up with two. */
:not(pre) > code {
    font-size: .85em;
    color: var(--ec-ink);
    background: color-mix(in srgb, var(--ec-ink) 7%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ec-ink) 14%, transparent);
    padding: 1px 6px;
    border-radius: 4px;
}

/* Tabler's pale badges are a filled slab, which on a light page is a tint and
   on a dark one is a block of colour heavy enough to outweigh the text it is
   supposed to carry — the `authority` badge on the rules grid runs the width of
   its column. In dark they become a wash drawn from the text colour itself,
   with a hairline of the same, so the word stays the loudest thing in the
   badge. `currentColor` is what makes one rule cover all nine colours. */
[data-bs-theme="dark"] .badge[class*="-lt"] {
    background-color: color-mix(in srgb, currentColor 13%, transparent) !important;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 24%, transparent);
}

/* Sylius paints a few blocks by class rather than by token — the filter
   accordion above every grid is `bg-white`, and the tax-section bands on a
   country's page are `bg-light`. A literal colour is the one thing a theme
   switch cannot reach through a variable, so both are named here. `bg-light`
   lands one step ABOVE the card it sits on, which is the relationship it has
   on paper too: a band that separates, not a hole. */
[data-bs-theme="dark"] .bg-white {
    background-color: var(--ec-paper) !important;
}

[data-bs-theme="dark"] .bg-light {
    background-color: var(--ec-light) !important;
}

/* Sylius ships a bright teal primary that belongs to no part of this charter.
   The buttons were already pulled to the ink; the badge was not, and it is the
   same family — a `%` chip beside a rate, in the same teal. In dark both take
   the light ink, because a near-black chip on a near-black ground is a chip
   nobody can see. */
.badge.bg-primary {
    background-color: var(--ec-black) !important;
    color: var(--ec-white) !important;
}

[data-bs-theme="dark"] .badge.bg-primary {
    background-color: var(--ec-ink) !important;
    color: var(--ec-paper) !important;
}

/* The other solid marker: `/env` on a country's rules, "Current" on a rate's
   history, the customer-provided flag on a document. Sylius paints them a
   bright blue that belongs to no part of this charter, and it had to stay
   distinguishable from the `%` chip above — so it takes the gold, the second
   accent, rather than the ink. Gold is light enough to carry dark letters in
   both themes, which is why the colour is fixed and only the shade moves.
   `text-white` in the markup is a Bootstrap utility with !important, so the
   override needs one too. */
.badge.bg-info {
    background-color: var(--ec-gold) !important;
    color: var(--ec-black) !important;
}

[data-bs-theme="dark"] .btn-primary {
    background: var(--ec-ink);
    border-color: var(--ec-ink);
    color: var(--ec-paper);
}

[data-bs-theme="dark"] .btn-primary:hover,
[data-bs-theme="dark"] .btn-primary:focus {
    background: var(--ec-text);
    border-color: var(--ec-text);
    color: var(--ec-paper);
}

/* A five-percent black wash is invisible on a dark ground: the "yes" pill
   takes a light wash of the same weight instead. */
[data-bs-theme="dark"] .badge.bg-success,
[data-bs-theme="dark"] .bg-success.text-white {
    background-color: rgba(255, 255, 255, 0.07) !important;
}

/* Chips — a compact list of things that are mostly just a name and a code.
   The subdivisions of a country were eight full-width rows to say "eight
   states, all of them served"; as chips the same card reads in one glance and
   the fact that actually matters — a state that refuses direct shipment — is
   the only one that breaks the rhythm. */

.ec-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.ec-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
    padding: 4px 11px 5px;
    border: 1px solid var(--ec-border);
    border-radius: 999px;
    background: var(--ec-paper);
    text-decoration: none;
    color: var(--ec-text);
    font-size: .82rem;
    line-height: 1.3;
}

/* Tabler gives every link an underline and its own colour on hover, which on
   a pill lands as a stripe across the name and a colour that belongs to no
   part of this page. The chip lifts instead: its own ground, one step up. */
.ec-chip:hover,
.ec-chip:focus-visible {
    text-decoration: none;
    border-color: var(--ec-ink);
    color: var(--ec-ink);
    background: color-mix(in srgb, var(--ec-ink) 5%, var(--ec-paper));
}

.ec-chip:focus-visible {
    outline: 2px solid var(--ec-ink);
    outline-offset: 2px;
}

.ec-chip:hover .ec-chip-code,
.ec-chip:focus-visible .ec-chip-code {
    color: var(--ec-ink);
}

.ec-chip-code {
    font-size: .68rem;
    letter-spacing: .04em;
    color: var(--ec-muted);
    font-variant-numeric: tabular-nums;
}

.ec-chip-name { color: inherit; }

/* Struck through, not greyed out: a subdivision we cannot ship to is a fact
   about the order, not a disabled control. */
.ec-chip-off .ec-chip-name {
    text-decoration: line-through;
    text-decoration-color: var(--ec-accent);
    text-decoration-thickness: 1px;
}

.ec-chip-off {
    border-style: dashed;
    color: var(--ec-muted);
}

/* Tariff rules — one line per rule, on a destination's page.
   The rate leads and carries its own unit, so the row needs no badge to say
   how it is calculated; what narrows the rule and the note that argues for it
   follow in their own columns. Badges are kept for the two facts that can
   surprise a reader: who stands behind the figure, and a rule switched off
   while still sitting in the list.

   One line per rule, with the columns aligned across the whole card rather
   than per section: five rules that each wrapped to two lines made a card
   taller than the destination's entire cascade above it, and the reader's eye
   had nothing to run down. */

.ec-rules {
    display: flex;
    flex-direction: column;
}

.ec-rule-section {
    display: flex;
    align-items: baseline;
    gap: 9px;
    flex-wrap: wrap;
    padding: 13px 20px 4px;
    border-top: 1px solid var(--ec-border);
}

.ec-rules > .ec-rule-section:first-child { border-top: 0; }

.ec-rule-tax {
    font-size: .66rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--ec-ink);
}

.ec-rule-local {
    font-size: .76rem;
    font-style: italic;
    color: var(--ec-muted);
}

.ec-rule {
    display: grid;
    grid-template-columns: 7.5rem 14rem minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 0 16px;
    padding: 7px 20px;
    text-decoration: none;
    color: inherit;
    border-left: 2px solid transparent;
    border-top: 1px solid var(--ec-line);
}

/* The first rule of a section sits directly under its label, which already
   carries a rule of its own. */
.ec-rule-section + .ec-rule { border-top: 0; }

@media (max-width: 900px) {
    .ec-rule {
        grid-template-columns: 7.5rem minmax(0, 1fr);
        gap: 2px 16px;
    }

    .ec-rule-note { grid-column: 2; }
    .ec-rule-meta { grid-column: 2; justify-self: start; }
}

.ec-rule:hover,
.ec-rule:focus-visible {
    text-decoration: none;
    color: inherit;
    background: color-mix(in srgb, var(--ec-ink) 3.5%, transparent);
    border-left-color: var(--ec-accent);
}

/* The note is the one thing worth un-dimming when the eye is on the row. */
.ec-rule:hover .ec-rule-note,
.ec-rule:focus-visible .ec-rule-note {
    color: var(--ec-text);
}

.ec-rule:focus-visible { outline: 2px solid var(--ec-ink); outline-offset: -2px; }

.ec-rule-rate {
    font-family: var(--ec-font-serif);
    font-size: 1.05rem;
    line-height: 1.3;
    font-weight: 600;
    color: var(--ec-ink);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ec-rule-rate .u {
    font-family: var(--ec-font-sans);
    font-size: .7rem;
    font-weight: 500;
    color: var(--ec-muted);
    letter-spacing: .02em;
}

/* What narrows the rule is the line that tells two 29 % apart, so it reads at
   full strength; the note beside it is reference material and reads as such.
   Both are one line and both truncate: the column is for recognising a rule,
   not for reading it — that is what the rule's own page is for. */
.ec-rule-qual,
.ec-rule-note {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ec-rule-qual {
    font-size: .81rem;
    color: var(--ec-ink);
}

.ec-rule-note {
    font-size: .76rem;
    color: var(--ec-muted);
}

.ec-rule-meta {
    display: flex;
    align-items: baseline;
    gap: 7px;
    justify-self: end;
    white-space: nowrap;
}

/* A withdrawn rule bills nobody, and it has to read that way without
   disappearing: the figure dims, the pill says so. */
.ec-rule-off .ec-rule-rate { color: var(--ec-muted); }
.ec-rule-off .ec-rule-rate .u { opacity: .7; }

/* A rate's own page — the figure, then the document under it. */

.ec-rule-hero {
    font-family: var(--ec-font-serif);
    font-size: 2.4rem;
    line-height: 1.05;
    font-weight: 600;
    color: var(--ec-ink);
    font-variant-numeric: tabular-nums;
}

.ec-rule-hero .u {
    font-family: var(--ec-font-sans);
    font-size: 1rem;
    font-weight: 500;
    color: var(--ec-muted);
    letter-spacing: .02em;
}

/* The cited document. Bordered rather than filled: it is a quotation from
   somewhere else, and a card inside a card reads as a second subject. */
.ec-doc {
    border: 1px solid var(--ec-border);
    border-radius: 10px;
    padding: 13px 15px;
}

.ec-quote {
    margin: 9px 0 0;
    padding-left: 12px;
    border-left: 2px solid var(--ec-gold);
    font-style: italic;
    font-size: .86rem;
    color: var(--ec-text);
}

.ec-doc-note {
    margin-top: 14px;
    padding-top: 13px;
    border-top: 1px solid var(--ec-line);
    font-size: .84rem;
    color: var(--ec-text);
    white-space: pre-wrap;
    max-width: 82ch;
}

/* What an independent document claims about the same charge. */
.ec-claim {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 7px 0;
    border-top: 1px solid var(--ec-line);
    text-decoration: none;
    color: var(--ec-text);
    font-size: .84rem;
}

.ec-claim:hover,
.ec-claim:focus-visible { text-decoration: none; color: var(--ec-ink); }

.ec-claim-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ec-claim-rate {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    color: var(--ec-ink);
    white-space: nowrap;
}

/* Small label/value pairs, for the handful of facts a card states flatly.
   A definition list with a three-column gutter wastes half the card when the
   values are a date and a code. */
.ec-facts {
    display: grid;
    gap: 5px;
    font-size: .82rem;
}

.ec-facts > div {
    display: flex;
    align-items: baseline;
    gap: 12px;
}

.ec-facts .k { color: var(--ec-muted); }
.ec-facts .v { margin-left: auto; color: var(--ec-ink); text-align: right; }

/* A source URL on one line, whatever its length: these are query-string
   monsters, and printed raw one of them was the loudest thing on a page about
   a tariff schedule. */
.ec-doc-link {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .78rem;
    color: var(--ec-muted);
    text-decoration: none;
    min-width: 0;
}

.ec-doc-link > :last-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ec-doc-link:hover,
.ec-doc-link:focus-visible { color: var(--ec-accent); text-decoration: none; }

/* The generic show page — every resource that has no page of its own.
   It printed one row per column of the table, dashes included: a rate's page
   opened on nine of them. A null value is marked in the markup and the pair is
   hidden here, label and all. Browsers without :has() fall back to the dash,
   which is what they showed before. */

.ec-details dd:has(> .ec-empty),
.ec-details dt:has(+ dd > .ec-empty) {
    display: none;
}

.ec-details dt {
    font-size: .72rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--ec-muted) !important;
    padding-top: .35rem;
}

.ec-details dd {
    color: var(--ec-text);
    margin-bottom: .75rem;
}

.ec-details dd strong { color: var(--ec-ink); }

/* Admin grids — a little tighter.
   Sylius pads its rows for a table of five columns; ours carry a document
   title, its authority, its host and a truncated note, so the padding lands on
   top of content that already has its own line height. */

.datatable > tbody > tr > td {
    padding-top: .55rem;
    padding-bottom: .55rem;
    vertical-align: top;
}

.datatable > tbody > tr > td small,
.datatable > tbody > tr > td .small {
    line-height: 1.4;
}

/* The header row reads as a header rather than as the first row of data. */
.datatable > thead > tr > th {
    font-size: .68rem;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ec-muted);
    font-weight: 600;
}

/* One flexible column per grid, and no sideways scroll.

   A table sizes itself to its content, so a cell holding a document title, its
   authority and a note wanted 744px and pushed the last two columns off the
   screen — the registry scrolled sideways to reach the column that says
   whether the link is dead. The cell that carries the prose is marked in the
   template and given `max-width: 0; width: 100%`: the browser then hands it
   whatever the other columns did not take, and its own content truncates
   inside it rather than widening the table.

   `max-width: 0` is not a typo. It is what makes a table cell shrinkable at
   all; the width declaration is what makes it greedy afterwards. */

.datatable td:has(> .ec-flex-cell) {
    max-width: 0;
    width: 100%;
}

.datatable td:has(> .ec-flex-cell) .text-truncate {
    max-width: 100% !important;
}

/* A row the eye can follow across a wide table. */
.datatable > tbody > tr:hover > td {
    background: color-mix(in srgb, var(--ec-ink) 3%, transparent);
}

/* The sourcing digest — two findings, each led by its figure.
   A hairline between the halves rather than two undifferentiated columns:
   they are two separate readings of the registry, not one list in two parts. */

.ec-digest {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 32px;
}

@media (max-width: 860px) {
    .ec-digest { grid-template-columns: 1fr; gap: 24px; }
    .ec-digest-half + .ec-digest-half { border-left: 0; padding-left: 0; border-top: 1px solid var(--ec-border); padding-top: 24px; }
}

.ec-digest-half + .ec-digest-half {
    border-left: 1px solid var(--ec-border);
    padding-left: 32px;
}

.ec-digest-figure {
    font-family: var(--ec-font-serif);
    font-size: 2.2rem;
    line-height: 1;
    font-weight: 600;
    color: var(--ec-ink);
    font-variant-numeric: tabular-nums;
}

.ec-digest-figure .of {
    font-family: var(--ec-font-sans);
    font-size: .9rem;
    font-weight: 500;
    color: var(--ec-muted);
    margin-left: 5px;
}

.ec-digest-label {
    margin: 6px 0 0;
    font-size: .92rem;
    color: var(--ec-ink);
    max-width: 34ch;
}

.ec-digest-why {
    margin: 7px 0 0;
    font-size: .78rem;
    color: var(--ec-muted);
    line-height: 1.5;
    max-width: 52ch;
}

.ec-chips-tight { gap: 4px; margin-top: 12px; }

/* A destination code with no name beside it: the chip is the code. */
.ec-chip-code-only {
    padding: 2px 8px 3px;
    font-size: .7rem;
    letter-spacing: .03em;
    color: var(--ec-muted);
    cursor: default;
}

.ec-digest-more {
    align-self: center;
    font-size: .72rem;
    color: var(--ec-muted);
}

/* A decision: what is billing, what it is billing on, and the two ways out.
   A table row could not hold it — the question runs to three sentences and the
   verdict is a form — so each one is a block with its own severity rail. */

.ec-decision {
    padding: 15px 20px;
    border-top: 1px solid var(--ec-line);
    border-left: 2px solid var(--ec-border);
}

.ec-rules > .ec-decision:first-child { border-top: 0; }

.ec-decision-loud { border-left-color: var(--ec-accent); }

.ec-decision-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    font-size: .88rem;
}

.ec-decision-dest {
    font-family: var(--ec-font-serif);
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--ec-ink);
}

.ec-decision-rate,
.ec-decision-stake {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ec-decision-rate { color: var(--ec-ink); }

/* Pushed to the far end: it is the figure the queue is ordered by, so it wants
   its own column even in a block that has none. */
.ec-decision-stake {
    margin-left: auto;
    color: var(--ec-accent);
    font-weight: 600;
}

.ec-decision-question {
    margin: 6px 0 0;
    font-size: .84rem;
    color: var(--ec-text);
    max-width: 92ch;
    line-height: 1.5;
}

.ec-decision-note {
    margin: 4px 0 0;
    font-size: .76rem;
    color: var(--ec-muted);
    max-width: 92ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ec-decision-actions {
    display: flex;
    gap: 8px;
    margin-top: 11px;
}

/* A date input on the dark cockpit band.
   The box was already translucent and its text white, but the browser paints
   the native parts — the dd/mm/yyyy placeholder and the calendar button —
   from `color-scheme`, so both came out black-on-white and the field read as a
   white slab. `color-scheme: dark` is the only thing that reaches them. */
.ec-date-on-dark {
    max-width: 160px;
    color-scheme: dark;
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .25);
    color: #fff;
}

.ec-date-on-dark:focus {
    background: rgba(255, 255, 255, .16);
    border-color: rgba(255, 255, 255, .5);
    color: #fff;
    box-shadow: none;
}

/* The API reference, beside the keys that open it.
   A three-column table for nine rows of two short strings was more chrome than
   content; each endpoint is one line, the verb fixed-width so the paths align
   down the column. */

.ec-endpoints {
    display: flex;
    flex-direction: column;
}

.ec-endpoint {
    display: grid;
    grid-template-columns: 3.4rem minmax(0, 20rem) minmax(0, 1fr);
    align-items: baseline;
    gap: 4px 14px;
    padding: 7px 0;
    border-top: 1px solid var(--ec-line);
}

.ec-endpoints > .ec-endpoint:first-child { border-top: 0; }

@media (max-width: 720px) {
    .ec-endpoint { grid-template-columns: 3.4rem minmax(0, 1fr); }
    .ec-endpoint-desc { grid-column: 2; }
}

.ec-verb {
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-align: center;
    padding: 2px 0 3px;
    border-radius: 4px;
}

/* A read is the common case and stays quiet; a write is the one that changes
   something on the other side and takes the accent. */
.ec-verb-get {
    color: var(--ec-muted);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ec-muted) 35%, transparent);
}

.ec-verb-post {
    color: var(--ec-accent);
    background: color-mix(in srgb, var(--ec-accent) 10%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ec-accent) 30%, transparent);
}

/* The chip is the path, not the column: stretched to the track it read as an
   empty input box. */
.ec-endpoint > code {
    justify-self: start;
    max-width: 100%;
}

.ec-endpoint-desc {
    font-size: .8rem;
    color: var(--ec-text);
    min-width: 0;
}

/* The alcohol band of a classification, drawn on a fixed 0–60 % scale.
   Two degrees printed on two rows of a definition list are two numbers; the
   bar is the thing that actually happens to a bottle, because the calculator
   refuses a line whose declared degree falls outside it. Fixed scale on
   purpose: the three classifications are meant to be compared, and a bar
   rescaled to its own maximum would make them all look alike. */

.ec-band {
    position: relative;
    height: 12px;
    border-radius: 3px;
    background: var(--ec-light);
    box-shadow: inset 0 0 0 1px var(--ec-border);
    overflow: hidden;
}

.ec-band-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    background: linear-gradient(90deg, var(--ec-gold), var(--ec-accent));
    border-radius: 3px;
}

.ec-band-scale {
    display: flex;
    justify-content: space-between;
    margin-top: 4px;
    font-size: .68rem;
    color: var(--ec-muted);
    font-variant-numeric: tabular-nums;
}

.ec-band-legend {
    margin: 9px 0 0;
    font-size: .82rem;
    color: var(--ec-text);
    max-width: 48ch;
}

/* The record's id and timestamps, beside the actions rather than under the
   whole page: small, grey, and never competing with the figure the page opens
   on. */
.ec-meta-line {
    font-size: .72rem;
    color: var(--ec-muted);
    text-align: right;
    width: 100%;
    font-variant-numeric: tabular-nums;
}

/* The fiscal calendar: a date, who it belongs to, and why it says what it
   says. The reason is the point of the screen — a calendar nobody can read is
   a calendar nobody can argue with — so it gets the width. */

.ec-calendar-row {
    display: grid;
    grid-template-columns: 4.5rem 14rem minmax(0, 1fr);
    align-items: baseline;
    gap: 6px 18px;
    padding: 10px 0;
    border-top: 1px solid var(--ec-line);
}

.ec-rules > .ec-calendar-row:first-child { border-top: 0; }

@media (max-width: 860px) {
    .ec-calendar-row { grid-template-columns: 4.5rem minmax(0, 1fr); }
    .ec-calendar-why { grid-column: 2; }
}

.ec-calendar-date {
    font-family: var(--ec-font-serif);
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--ec-ink);
    font-variant-numeric: tabular-nums;
}

.ec-calendar-why {
    font-size: .82rem;
    color: var(--ec-text);
    line-height: 1.5;
}

/* Not a destination: what every destination nobody has looked at inherits. */
.ec-calendar-fallback { border-top: 1px solid var(--ec-border); }
.ec-calendar-fallback .ec-calendar-date { color: var(--ec-gold); }

/* The key to a coloured column. Five families is more than a reader holds, and
   a rail with no legend beside it is decoration. */
.ec-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 3px 14px;
    font-size: .72rem;
    color: var(--ec-muted);
}

.ec-legend span {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.ec-legend i {
    width: 3px;
    height: 12px;
    border-radius: 1px;
    display: inline-block;
}

/* The sidebar's four sections, foldable.

   Eighteen entries is a scroll on a laptop, and most of the time a reader is
   working inside one of the four. The section holding the current page opens
   itself; the rest stay folded until asked, and the choice is remembered. */

.navbar.navbar-vertical .ec-nav-section-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: .35rem .75rem;
    background: none;
    border: 0;
    font: inherit;
    font-size: .68rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    font-weight: 600;
    color: rgba(255, 255, 255, .45);
    cursor: pointer;
    text-align: left;
}

.navbar.navbar-vertical .ec-nav-section-toggle:hover { color: rgba(255, 255, 255, .8); }
.navbar.navbar-vertical .ec-nav-section-toggle:focus-visible { outline: 2px solid var(--ec-accent); outline-offset: -2px; }

.ec-nav-section { margin-top: .5rem; }

.ec-nav-chevron {
    margin-left: auto;
    width: 7px;
    height: 7px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform .15s ease;
}

@media (prefers-reduced-motion: reduce) {
    .ec-nav-chevron { transition: none; }
}

.ec-nav-section-toggle[aria-expanded="false"] .ec-nav-chevron {
    transform: rotate(-45deg) translate(-2px, 2px);
}

.ec-nav-entry.ec-nav-folded { display: none; }

/* Where a tax sits in the cascade. Twenty-one types and a bare integer between
   them: a priority only reads against its neighbours, so the page shows the
   rung above and the rung below rather than the number alone. */

.ec-family-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-right: 9px;
    vertical-align: baseline;
}

.ec-ladder {
    display: grid;
    gap: 2px;
}

.ec-ladder-step {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 6px 12px;
    border-radius: 6px;
    font-size: .84rem;
    color: var(--ec-muted);
}

.ec-ladder-rank {
    flex: 0 0 2.5rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.ec-ladder-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ec-ladder-pos { margin-left: auto; font-size: .72rem; white-space: nowrap; }

/* The rung the reader is standing on. */
.ec-ladder-here {
    background: color-mix(in srgb, var(--ec-ink) 6%, transparent);
    color: var(--ec-ink);
    font-weight: 600;
}

.ec-ladder-here .ec-ladder-rank {
    font-family: var(--ec-font-serif);
    font-size: 1.05rem;
}

/* The tax overview: a severity rail per row, and a filter panel that folds.

   With the list narrowed to outliers every row carried a tint, and a tint
   every row carries says nothing. The rail is the vocabulary the decisions
   queue and the destination sheet already use. */

.ec-row-critical > td:first-child { box-shadow: inset 3px 0 0 var(--ec-accent); }
.ec-row-warning > td:first-child { box-shadow: inset 3px 0 0 var(--ec-gold); }

/* Seven controls before the thirty-six rates the page exists for. Folded
   unless something is narrowed — a filter nobody can see is a list quoted as
   complete, so `data-open` keeps it visible whenever it bites. */
.ec-overview-filters:not([data-open]) .card-body,
.ec-overview-filters:not([data-open]) .card-footer {
    display: none;
}

.ec-overview-filters .card-header { cursor: pointer; }

.ec-overview-filters.ec-open .card-body,
.ec-overview-filters.ec-open .card-footer {
    display: block;
}

/* A tax type wherever it is named: its family's colour on a quiet chip. The
   overview used to paint every tax purple, the province blue and the client
   azure — three hues that meant nothing and competed with the severity the
   row was trying to state. */
.ec-tax-chip {
    display: inline-block;
    padding: 2px 9px 3px;
    border-radius: 999px;
    font-size: .75rem;
    line-height: 1.35;
    color: var(--ec-ink);
    background: color-mix(in srgb, var(--ec-charge-tint) 14%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ec-charge-tint) 32%, transparent);
}
